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 <jaro.vanlandschoot@basalte.be>
This commit is contained in:
Jaro Van Landschoot
2025-09-24 09:25:55 +02:00
committed by Anas Nashif
parent 1becebc8f9
commit 9be9684b53
6 changed files with 142 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(pwm_event)
target_sources(app PRIVATE src/main.c)

View File

@@ -0,0 +1,38 @@
.. zephyr:code-sample:: event
:name: PWM Event
:relevant-api: pwm_interface
Events on a PWM signal.
Overview
********
This sample provides an example application using the :ref:`PWM API <pwm_api>` event
API to get events on a PWM signal. The sample demonstrates how events can be used to
precisely time x periods of a PWM signal. A usecase for this would be the transmitting
part of an IR remote, where precise pulse timing is needed.
Requirements
************
This sample requires the support of the :ref:`PWM API <pwm_api>` event API.
Building and Running
********************
.. zephyr-app-commands::
:zephyr-app: samples/drivers/pwm/event
:host-os: unix
:board: sam4s_xplained
:goals: run
:compact:
Sample Output
=============
When capturing the signal using an oscilloscope or logic analyzer, it should look like
the following repeating sequence (after a startup transient)
.. code-block::
┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
─┘ └─┘ └─┘ └─┘ └─┘ └───────────────────┘ └─┘ └─┘ └─┘ └─┘ └─────

View File

@@ -0,0 +1,13 @@
/*
* Copyright (c) 2025 Basalte bv
*
* SPDX-License-Identifier: Apache-2.0
*/
&pinctrl {
pwm0_default: pwm0_default {
group1 {
pinmux = <PA11B_PWM_PWMH0>;
};
};
};

View File

@@ -0,0 +1,2 @@
CONFIG_PWM=y
CONFIG_PWM_EVENT=y

View File

@@ -0,0 +1,12 @@
sample:
name: PWM event
description: precisely time 5 PWM periods using the PWM event API
common:
tags:
- drivers
- pwm
depends_on: pwm
tests:
sample.drivers.pwm.event:
platform_allow:
- sam4s_xplained

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2025 Basalte bv
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/pwm.h>
#include <zephyr/dt-bindings/pwm/pwm.h>
#include <zephyr/kernel.h>
#define N_PERIODS 5
#define PWM_CHANNEL 0
#define PWM_PERIOD_NS (1 * NSEC_PER_MSEC)
#define PWM_FLAGS PWM_POLARITY_NORMAL
static struct pwm_event_callback callback;
static bool pwm_idle;
static uint8_t counter;
static void pwm_callback_handler(const struct device *dev, struct pwm_event_callback *cb,
uint32_t channel, pwm_events_t events)
{
ARG_UNUSED(channel);
ARG_UNUSED(events);
int ret;
if (++counter == N_PERIODS) {
pwm_idle = !pwm_idle;
counter = 0;
ret = pwm_set(dev, PWM_CHANNEL, PWM_PERIOD_NS, pwm_idle ? 0 : PWM_PERIOD_NS / 2,
PWM_FLAGS);
if (ret < 0) {
printk("failed to set pwm (%d)\n", ret);
(void)pwm_remove_event_callback(dev, cb);
return;
}
}
}
int main(void)
{
const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(pwm_0));
int ret;
if (!device_is_ready(dev)) {
printk("device is not ready\n");
return 0;
}
ret = pwm_set(dev, PWM_CHANNEL, PWM_PERIOD_NS, PWM_PERIOD_NS / 2, PWM_FLAGS);
if (ret < 0) {
printk("failed to set idle (%d)\n", ret);
return ret;
}
pwm_init_event_callback(&callback, pwm_callback_handler, PWM_CHANNEL,
PWM_EVENT_TYPE_PERIOD);
ret = pwm_add_event_callback(dev, &callback);
if (ret < 0) {
printk("failed to add event callback (%d)\n", ret);
return ret;
}
return 0;
}