Skip to content

Commit 9be9684

Browse files
javlandsnashif
authored andcommitted
samples: drivers: pwm: event: Add sample
Add a simple sample demonstrating how the PWM event API can be used to precisely time 5 periods of a PWM signal. Signed-off-by: Jaro Van Landschoot <[email protected]>
1 parent 1becebc commit 9be9684

File tree

6 files changed

+142
-0
lines changed

6 files changed

+142
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(pwm_event)
7+
8+
target_sources(app PRIVATE src/main.c)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
.. zephyr:code-sample:: event
2+
:name: PWM Event
3+
:relevant-api: pwm_interface
4+
5+
Events on a PWM signal.
6+
7+
Overview
8+
********
9+
This sample provides an example application using the :ref:`PWM API <pwm_api>` event
10+
API to get events on a PWM signal. The sample demonstrates how events can be used to
11+
precisely time x periods of a PWM signal. A usecase for this would be the transmitting
12+
part of an IR remote, where precise pulse timing is needed.
13+
14+
Requirements
15+
************
16+
17+
This sample requires the support of the :ref:`PWM API <pwm_api>` event API.
18+
19+
Building and Running
20+
********************
21+
22+
.. zephyr-app-commands::
23+
:zephyr-app: samples/drivers/pwm/event
24+
:host-os: unix
25+
:board: sam4s_xplained
26+
:goals: run
27+
:compact:
28+
29+
Sample Output
30+
=============
31+
32+
When capturing the signal using an oscilloscope or logic analyzer, it should look like
33+
the following repeating sequence (after a startup transient)
34+
35+
.. code-block::
36+
37+
┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
38+
─┘ └─┘ └─┘ └─┘ └─┘ └───────────────────┘ └─┘ └─┘ └─┘ └─┘ └─────
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright (c) 2025 Basalte bv
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&pinctrl {
8+
pwm0_default: pwm0_default {
9+
group1 {
10+
pinmux = <PA11B_PWM_PWMH0>;
11+
};
12+
};
13+
};

samples/drivers/pwm/event/prj.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CONFIG_PWM=y
2+
CONFIG_PWM_EVENT=y
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
sample:
2+
name: PWM event
3+
description: precisely time 5 PWM periods using the PWM event API
4+
common:
5+
tags:
6+
- drivers
7+
- pwm
8+
depends_on: pwm
9+
tests:
10+
sample.drivers.pwm.event:
11+
platform_allow:
12+
- sam4s_xplained
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2025 Basalte bv
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/pwm.h>
8+
#include <zephyr/dt-bindings/pwm/pwm.h>
9+
#include <zephyr/kernel.h>
10+
11+
#define N_PERIODS 5
12+
13+
#define PWM_CHANNEL 0
14+
#define PWM_PERIOD_NS (1 * NSEC_PER_MSEC)
15+
#define PWM_FLAGS PWM_POLARITY_NORMAL
16+
17+
static struct pwm_event_callback callback;
18+
19+
static bool pwm_idle;
20+
static uint8_t counter;
21+
22+
static void pwm_callback_handler(const struct device *dev, struct pwm_event_callback *cb,
23+
uint32_t channel, pwm_events_t events)
24+
{
25+
ARG_UNUSED(channel);
26+
ARG_UNUSED(events);
27+
int ret;
28+
29+
if (++counter == N_PERIODS) {
30+
pwm_idle = !pwm_idle;
31+
counter = 0;
32+
33+
ret = pwm_set(dev, PWM_CHANNEL, PWM_PERIOD_NS, pwm_idle ? 0 : PWM_PERIOD_NS / 2,
34+
PWM_FLAGS);
35+
if (ret < 0) {
36+
printk("failed to set pwm (%d)\n", ret);
37+
(void)pwm_remove_event_callback(dev, cb);
38+
return;
39+
}
40+
}
41+
}
42+
43+
int main(void)
44+
{
45+
const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(pwm_0));
46+
int ret;
47+
48+
if (!device_is_ready(dev)) {
49+
printk("device is not ready\n");
50+
return 0;
51+
}
52+
53+
ret = pwm_set(dev, PWM_CHANNEL, PWM_PERIOD_NS, PWM_PERIOD_NS / 2, PWM_FLAGS);
54+
if (ret < 0) {
55+
printk("failed to set idle (%d)\n", ret);
56+
return ret;
57+
}
58+
59+
pwm_init_event_callback(&callback, pwm_callback_handler, PWM_CHANNEL,
60+
PWM_EVENT_TYPE_PERIOD);
61+
62+
ret = pwm_add_event_callback(dev, &callback);
63+
if (ret < 0) {
64+
printk("failed to add event callback (%d)\n", ret);
65+
return ret;
66+
}
67+
68+
return 0;
69+
}

0 commit comments

Comments
 (0)