Zephyr API Documentation 4.3.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
pwm.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Intel Corporation.
3 * Copyright (c) 2020-2021 Vestas Wind Systems A/S
4 * Copyright (c) 2025 Basalte bv
5 * Copyright (c) 2025 Siemens SA
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
15
16#ifndef ZEPHYR_INCLUDE_DRIVERS_PWM_H_
17#define ZEPHYR_INCLUDE_DRIVERS_PWM_H_
18
32
33#include <errno.h>
34#include <stdint.h>
35
36#include <zephyr/device.h>
37#include <zephyr/devicetree.h>
38#include <zephyr/sys_clock.h>
40#include <zephyr/sys/slist.h>
41#include <zephyr/toolchain.h>
42
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
54
56/* Bit 0 is used for PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED */
57#define PWM_CAPTURE_TYPE_SHIFT 1U
58#define PWM_CAPTURE_TYPE_MASK (3U << PWM_CAPTURE_TYPE_SHIFT)
59#define PWM_CAPTURE_MODE_SHIFT 3U
60#define PWM_CAPTURE_MODE_MASK (1U << PWM_CAPTURE_MODE_SHIFT)
62
64#define PWM_CAPTURE_TYPE_PERIOD (1U << PWM_CAPTURE_TYPE_SHIFT)
65
67#define PWM_CAPTURE_TYPE_PULSE (2U << PWM_CAPTURE_TYPE_SHIFT)
68
70#define PWM_CAPTURE_TYPE_BOTH (PWM_CAPTURE_TYPE_PERIOD | \
71 PWM_CAPTURE_TYPE_PULSE)
72
74#define PWM_CAPTURE_MODE_SINGLE (0U << PWM_CAPTURE_MODE_SHIFT)
75
77#define PWM_CAPTURE_MODE_CONTINUOUS (1U << PWM_CAPTURE_MODE_SHIFT)
78
80
86
87#define PWM_EVENT_TYPE_SHIFT 0U
88
90#define PWM_EVENT_TYPE_PERIOD (1U << PWM_EVENT_TYPE_SHIFT)
91
98#define PWM_EVENT_TYPE_FAULT (2U << PWM_EVENT_TYPE_SHIFT)
99
101
110
112
118
120
146
191#define PWM_DT_SPEC_GET_BY_NAME(node_id, name) \
192 { \
193 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_NAME(node_id, name)), \
194 .channel = DT_PWMS_CHANNEL_BY_NAME(node_id, name), \
195 .period = DT_PWMS_PERIOD_BY_NAME(node_id, name), \
196 .flags = DT_PWMS_FLAGS_BY_NAME(node_id, name), \
197 }
198
211#define PWM_DT_SPEC_INST_GET_BY_NAME(inst, name) \
212 PWM_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
213
232#define PWM_DT_SPEC_GET_BY_NAME_OR(node_id, name, default_value) \
233 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
234 (PWM_DT_SPEC_GET_BY_NAME(node_id, name)), \
235 (default_value))
236
251#define PWM_DT_SPEC_INST_GET_BY_NAME_OR(inst, name, default_value) \
252 PWM_DT_SPEC_GET_BY_NAME_OR(DT_DRV_INST(inst), name, default_value)
253
296#define PWM_DT_SPEC_GET_BY_IDX(node_id, idx) \
297 { \
298 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_IDX(node_id, idx)), \
299 .channel = DT_PWMS_CHANNEL_BY_IDX(node_id, idx), \
300 .period = DT_PWMS_PERIOD_BY_IDX(node_id, idx), \
301 .flags = DT_PWMS_FLAGS_BY_IDX(node_id, idx), \
302 }
303
315#define PWM_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
316 PWM_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
317
335#define PWM_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \
336 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
337 (PWM_DT_SPEC_GET_BY_IDX(node_id, idx)), \
338 (default_value))
339
353#define PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \
354 PWM_DT_SPEC_GET_BY_IDX_OR(DT_DRV_INST(inst), idx, default_value)
355
366#define PWM_DT_SPEC_GET(node_id) PWM_DT_SPEC_GET_BY_IDX(node_id, 0)
367
378#define PWM_DT_SPEC_INST_GET(inst) PWM_DT_SPEC_GET(DT_DRV_INST(inst))
379
392#define PWM_DT_SPEC_GET_OR(node_id, default_value) \
393 PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)
394
407#define PWM_DT_SPEC_INST_GET_OR(inst, default_value) \
408 PWM_DT_SPEC_GET_OR(DT_DRV_INST(inst), default_value)
409
429typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
430 uint32_t channel,
431 uint32_t period_cycles,
432 uint32_t pulse_cycles,
433 int status, void *user_data);
434
435struct pwm_event_callback;
436
451typedef void (*pwm_event_callback_handler_t)(const struct device *dev,
452 struct pwm_event_callback *callback, uint32_t channel,
453 pwm_events_t events);
454
480
486typedef int (*pwm_set_cycles_t)(const struct device *dev, uint32_t channel,
487 uint32_t period_cycles, uint32_t pulse_cycles,
489
494typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
495 uint32_t channel, uint64_t *cycles);
496
497#ifdef CONFIG_PWM_CAPTURE
502typedef int (*pwm_configure_capture_t)(const struct device *dev,
503 uint32_t channel, pwm_flags_t flags,
505 void *user_data);
506
511typedef int (*pwm_enable_capture_t)(const struct device *dev, uint32_t channel);
512
517typedef int (*pwm_disable_capture_t)(const struct device *dev,
518 uint32_t channel);
519#endif /* CONFIG_PWM_CAPTURE */
520
521#ifdef CONFIG_PWM_EVENT
522
527typedef int (*pwm_manage_event_callback_t)(const struct device *dev,
528 struct pwm_event_callback *callback, bool set);
529#endif /* CONFIG_PWM_EVENT */
530
531#ifdef CONFIG_PWM_WITH_DMA
536typedef int (*pwm_enable_dma_t)(const struct device *dev, uint32_t channel);
537
542typedef int (*pwm_disable_dma_t)(const struct device *dev, uint32_t channel);
543#endif /* CONFIG_PWM_WITH_DMA */
544
546__subsystem struct pwm_driver_api {
547 pwm_set_cycles_t set_cycles;
548 pwm_get_cycles_per_sec_t get_cycles_per_sec;
549#ifdef CONFIG_PWM_CAPTURE
550 pwm_configure_capture_t configure_capture;
551 pwm_enable_capture_t enable_capture;
552 pwm_disable_capture_t disable_capture;
553#endif /* CONFIG_PWM_CAPTURE */
554#ifdef CONFIG_PWM_EVENT
555 pwm_manage_event_callback_t manage_event_callback;
556#endif /* CONFIG_PWM_EVENT */
557#ifdef CONFIG_PWM_WITH_DMA
558 pwm_enable_dma_t enable_dma;
559 pwm_disable_dma_t disable_dma;
560#endif /* CONFIG_PWM_WITH_DMA */
561};
563
594__syscall int pwm_set_cycles(const struct device *dev, uint32_t channel,
595 uint32_t period, uint32_t pulse,
597
598static inline int z_impl_pwm_set_cycles(const struct device *dev,
599 uint32_t channel, uint32_t period,
601{
602 const struct pwm_driver_api *api =
603 (const struct pwm_driver_api *)dev->api;
604
605 if (pulse > period) {
606 return -EINVAL;
607 }
608
609 return api->set_cycles(dev, channel, period, pulse, flags);
610}
611
623__syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
624 uint64_t *cycles);
625
626static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
627 uint32_t channel,
628 uint64_t *cycles)
629{
630 const struct pwm_driver_api *api =
631 (const struct pwm_driver_api *)dev->api;
632
633 return api->get_cycles_per_sec(dev, channel, cycles);
634}
635
652static inline int pwm_set(const struct device *dev, uint32_t channel,
653 uint32_t period, uint32_t pulse, pwm_flags_t flags)
654{
655 int err;
656 uint64_t pulse_cycles;
657 uint64_t period_cycles;
658 uint64_t cycles_per_sec;
659
660 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
661 if (err < 0) {
662 return err;
663 }
664
665 period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
666 if (period_cycles > UINT32_MAX) {
667 return -ENOTSUP;
668 }
669
670 pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
671 if (pulse_cycles > UINT32_MAX) {
672 return -ENOTSUP;
673 }
674
675 return pwm_set_cycles(dev, channel, (uint32_t)period_cycles,
676 (uint32_t)pulse_cycles, flags);
677}
678
698static inline int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period,
699 uint32_t pulse)
700{
701 return pwm_set(spec->dev, spec->channel, period, pulse, spec->flags);
702}
703
719static inline int pwm_set_pulse_dt(const struct pwm_dt_spec *spec,
720 uint32_t pulse)
721{
722 return pwm_set(spec->dev, spec->channel, spec->period, pulse,
723 spec->flags);
724}
725
738static inline int pwm_cycles_to_usec(const struct device *dev, uint32_t channel,
739 uint32_t cycles, uint64_t *usec)
740{
741 int err;
742 uint64_t temp;
743 uint64_t cycles_per_sec;
744
745 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
746 if (err < 0) {
747 return err;
748 }
749
750 if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
751 return -ERANGE;
752 }
753
754 *usec = temp / cycles_per_sec;
755
756 return 0;
757}
758
771static inline int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel,
772 uint32_t cycles, uint64_t *nsec)
773{
774 int err;
775 uint64_t temp;
776 uint64_t cycles_per_sec;
777
778 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
779 if (err < 0) {
780 return err;
781 }
782
783 if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
784 return -ERANGE;
785 }
786
787 *nsec = temp / cycles_per_sec;
788
789 return 0;
790}
791
792#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
821static inline int pwm_configure_capture(const struct device *dev,
822 uint32_t channel, pwm_flags_t flags,
824 void *user_data)
825{
826 const struct pwm_driver_api *api =
827 (const struct pwm_driver_api *)dev->api;
828
829 if (api->configure_capture == NULL) {
830 return -ENOSYS;
831 }
832
833 return api->configure_capture(dev, channel, flags, cb,
834 user_data);
835}
836#endif /* CONFIG_PWM_CAPTURE */
837
856__syscall int pwm_enable_capture(const struct device *dev, uint32_t channel);
857
858#ifdef CONFIG_PWM_CAPTURE
859static inline int z_impl_pwm_enable_capture(const struct device *dev,
860 uint32_t channel)
861{
862 const struct pwm_driver_api *api =
863 (const struct pwm_driver_api *)dev->api;
864
865 if (api->enable_capture == NULL) {
866 return -ENOSYS;
867 }
868
869 return api->enable_capture(dev, channel);
870}
871#endif /* CONFIG_PWM_CAPTURE */
872
887__syscall int pwm_disable_capture(const struct device *dev, uint32_t channel);
888
889#ifdef CONFIG_PWM_CAPTURE
890static inline int z_impl_pwm_disable_capture(const struct device *dev,
891 uint32_t channel)
892{
893 const struct pwm_driver_api *api =
894 (const struct pwm_driver_api *)dev->api;
895
896 if (api->disable_capture == NULL) {
897 return -ENOSYS;
898 }
899
900 return api->disable_capture(dev, channel);
901}
902#endif /* CONFIG_PWM_CAPTURE */
903
904#if defined(CONFIG_PWM_WITH_DMA) || defined(__DOXYGEN__)
916__syscall int pwm_enable_dma(const struct device *dev, uint32_t channel);
917
918static inline int z_impl_pwm_enable_dma(const struct device *dev, uint32_t channel)
919{
920 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
921
922 if (api->enable_dma == NULL) {
923 return -ENOSYS;
924 }
925
926 return api->enable_dma(dev, channel);
927}
928
940__syscall int pwm_disable_dma(const struct device *dev, uint32_t channel);
941
942static inline int z_impl_pwm_disable_dma(const struct device *dev, uint32_t channel)
943{
944 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
945
946 if (api->disable_dma == NULL) {
947 return -ENOSYS;
948 }
949
950 return api->disable_dma(dev, channel);
951}
952#endif /* CONFIG_PWM_WITH_DMA */
953
981__syscall int pwm_capture_cycles(const struct device *dev, uint32_t channel,
982 pwm_flags_t flags, uint32_t *period,
983 uint32_t *pulse, k_timeout_t timeout);
984
1013static inline int pwm_capture_usec(const struct device *dev, uint32_t channel,
1014 pwm_flags_t flags, uint64_t *period,
1015 uint64_t *pulse, k_timeout_t timeout)
1016{
1017 int err;
1018 uint32_t pulse_cycles;
1019 uint32_t period_cycles;
1020
1021 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
1022 &pulse_cycles, timeout);
1023 if (err < 0) {
1024 return err;
1025 }
1026
1027 err = pwm_cycles_to_usec(dev, channel, period_cycles, period);
1028 if (err < 0) {
1029 return err;
1030 }
1031
1032 err = pwm_cycles_to_usec(dev, channel, pulse_cycles, pulse);
1033 if (err < 0) {
1034 return err;
1035 }
1036
1037 return 0;
1038}
1039
1068static inline int pwm_capture_nsec(const struct device *dev, uint32_t channel,
1069 pwm_flags_t flags, uint64_t *period,
1070 uint64_t *pulse, k_timeout_t timeout)
1071{
1072 int err;
1073 uint32_t pulse_cycles;
1074 uint32_t period_cycles;
1075
1076 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
1077 &pulse_cycles, timeout);
1078 if (err < 0) {
1079 return err;
1080 }
1081
1082 err = pwm_cycles_to_nsec(dev, channel, period_cycles, period);
1083 if (err < 0) {
1084 return err;
1085 }
1086
1087 err = pwm_cycles_to_nsec(dev, channel, pulse_cycles, pulse);
1088 if (err < 0) {
1089 return err;
1090 }
1091
1092 return 0;
1093}
1094
1095#if defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__)
1104static inline void pwm_init_event_callback(struct pwm_event_callback *callback,
1105 pwm_event_callback_handler_t handler, uint32_t channel,
1106 pwm_events_t event_mask)
1107{
1108 __ASSERT_NO_MSG(callback != NULL);
1109 __ASSERT_NO_MSG(handler != NULL);
1110
1111 callback->handler = handler;
1112 callback->channel = channel;
1113 callback->event_mask = event_mask;
1114}
1115
1128static inline int pwm_add_event_callback(const struct device *dev,
1129 struct pwm_event_callback *callback)
1130{
1131 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
1132
1133 if (api->manage_event_callback == NULL) {
1134 return -ENOSYS;
1135 }
1136
1137 return api->manage_event_callback(dev, callback, true);
1138}
1139
1150static inline int pwm_remove_event_callback(const struct device *dev,
1151 struct pwm_event_callback *callback)
1152{
1153 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
1154
1155 if (api->manage_event_callback == NULL) {
1156 return -ENOSYS;
1157 }
1158
1159 return api->manage_event_callback(dev, callback, false);
1160}
1161#endif /* defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__) */
1162
1171static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
1172{
1173 return device_is_ready(spec->dev);
1174}
1175
1176#ifdef __cplusplus
1177}
1178#endif
1179
1183
1184#include <zephyr/syscalls/pwm.h>
1185
1186#endif /* ZEPHYR_INCLUDE_DRIVERS_PWM_H_ */
Devicetree main header.
System error numbers.
#define NSEC_PER_SEC
number of nanoseconds per second
Definition clock.h:113
#define USEC_PER_SEC
number of microseconds per second
Definition clock.h:110
bool device_is_ready(const struct device *dev)
Verify that a device is ready for use.
static bool u64_mul_overflow(uint64_t a, uint64_t b, uint64_t *result)
Multiply two unsigned 64-bit integers.
int pwm_capture_cycles(const struct device *dev, uint32_t channel, pwm_flags_t flags, uint32_t *period, uint32_t *pulse, k_timeout_t timeout)
Capture a single PWM period/pulse width in clock cycles for a single PWM input.
static int pwm_add_event_callback(const struct device *dev, struct pwm_event_callback *callback)
Add an application event callback.
Definition pwm.h:1128
int pwm_disable_capture(const struct device *dev, uint32_t channel)
Disable PWM period/pulse width capture for a single PWM input.
static int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period, uint32_t pulse)
Set the period and pulse width in nanoseconds from a struct pwm_dt_spec (with custom period).
Definition pwm.h:698
void(* pwm_capture_callback_handler_t)(const struct device *dev, uint32_t channel, uint32_t period_cycles, uint32_t pulse_cycles, int status, void *user_data)
PWM capture callback handler function signature.
Definition pwm.h:429
int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, uint64_t *cycles)
Get the clock rate (cycles per second) for a single PWM output.
static int pwm_capture_usec(const struct device *dev, uint32_t channel, pwm_flags_t flags, uint64_t *period, uint64_t *pulse, k_timeout_t timeout)
Capture a single PWM period/pulse width in microseconds for a single PWM input.
Definition pwm.h:1013
uint16_t pwm_events_t
Provides a type to hold PWM events.
Definition pwm.h:119
static int pwm_capture_nsec(const struct device *dev, uint32_t channel, pwm_flags_t flags, uint64_t *period, uint64_t *pulse, k_timeout_t timeout)
Capture a single PWM period/pulse width in nanoseconds for a single PWM input.
Definition pwm.h:1068
static int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel, uint32_t cycles, uint64_t *nsec)
Convert from PWM cycles to nanoseconds.
Definition pwm.h:771
static bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
Validate that the PWM device is ready.
Definition pwm.h:1171
static int pwm_remove_event_callback(const struct device *dev, struct pwm_event_callback *callback)
Remove an application event callback.
Definition pwm.h:1150
static int pwm_set_pulse_dt(const struct pwm_dt_spec *spec, uint32_t pulse)
Set the period and pulse width in nanoseconds from a struct pwm_dt_spec.
Definition pwm.h:719
static int pwm_configure_capture(const struct device *dev, uint32_t channel, pwm_flags_t flags, pwm_capture_callback_handler_t cb, void *user_data)
Configure PWM period/pulse width capture for a single PWM input.
Definition pwm.h:821
int pwm_disable_dma(const struct device *dev, uint32_t channel)
Disable DMA requests triggered by PWM cycles for a single PWM channel.
int pwm_enable_capture(const struct device *dev, uint32_t channel)
Enable PWM period/pulse width capture for a single PWM input.
static int pwm_set(const struct device *dev, uint32_t channel, uint32_t period, uint32_t pulse, pwm_flags_t flags)
Set the period and pulse width in nanoseconds for a single PWM output.
Definition pwm.h:652
uint16_t pwm_flags_t
Provides a type to hold PWM configuration flags.
Definition pwm.h:111
static int pwm_cycles_to_usec(const struct device *dev, uint32_t channel, uint32_t cycles, uint64_t *usec)
Convert from PWM cycles to microseconds.
Definition pwm.h:738
int pwm_enable_dma(const struct device *dev, uint32_t channel)
Enable DMA requests triggered by PWM cycles for a single PWM channel.
void(* pwm_event_callback_handler_t)(const struct device *dev, struct pwm_event_callback *callback, uint32_t channel, pwm_events_t events)
PWM event callback handler function signature.
Definition pwm.h:451
static void pwm_init_event_callback(struct pwm_event_callback *callback, pwm_event_callback_handler_t handler, uint32_t channel, pwm_events_t event_mask)
Helper to initialize a struct pwm_event_callback properly.
Definition pwm.h:1104
int pwm_set_cycles(const struct device *dev, uint32_t channel, uint32_t period, uint32_t pulse, pwm_flags_t flags)
Set the period and pulse width for a single PWM output.
struct _snode sys_snode_t
Single-linked list node structure.
Definition slist.h:39
#define EINVAL
Invalid argument.
Definition errno.h:60
#define ENOSYS
Function not implemented.
Definition errno.h:82
#define ENOTSUP
Unsupported value.
Definition errno.h:114
#define ERANGE
Result too large.
Definition errno.h:72
#define NULL
Definition iar_missing_defs.h:20
flags
Definition parser.h:97
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT64_TYPE__ uint64_t
Definition stdint.h:91
__UINT16_TYPE__ uint16_t
Definition stdint.h:89
#define UINT32_MAX
Definition stdint.h:29
Runtime device structure (in ROM) per driver instance.
Definition device.h:513
const void * api
Address of the API structure exposed by the device instance.
Definition device.h:519
Kernel timeout type.
Definition clock.h:65
Container for PWM information specified in devicetree.
Definition pwm.h:136
pwm_flags_t flags
Flags.
Definition pwm.h:144
uint32_t channel
Channel number.
Definition pwm.h:140
uint32_t period
Period in nanoseconds.
Definition pwm.h:142
const struct device * dev
PWM device instance.
Definition pwm.h:138
PWM event callback structure.
Definition pwm.h:466
uint32_t channel
Channel the callback is interested in.
Definition pwm.h:475
pwm_events_t event_mask
A mask of events the callback is interested in.
Definition pwm.h:478
pwm_event_callback_handler_t handler
Actual callback function being called when relevant.
Definition pwm.h:472
Macros to abstract toolchain specific capabilities.