Zephyr API Documentation 4.4.0-rc1
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 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
14
15#ifndef ZEPHYR_INCLUDE_DRIVERS_PWM_H_
16#define ZEPHYR_INCLUDE_DRIVERS_PWM_H_
17
31
32#include <errno.h>
33#include <stdint.h>
34
35#include <zephyr/device.h>
36#include <zephyr/devicetree.h>
37#include <zephyr/sys_clock.h>
39#include <zephyr/sys/slist.h>
40#include <zephyr/toolchain.h>
41
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
53
55/* Bit 0 is used for PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED */
56#define PWM_CAPTURE_TYPE_SHIFT 1U
57#define PWM_CAPTURE_TYPE_MASK (3U << PWM_CAPTURE_TYPE_SHIFT)
58#define PWM_CAPTURE_MODE_SHIFT 3U
59#define PWM_CAPTURE_MODE_MASK (1U << PWM_CAPTURE_MODE_SHIFT)
61
63#define PWM_CAPTURE_TYPE_PERIOD (1U << PWM_CAPTURE_TYPE_SHIFT)
64
66#define PWM_CAPTURE_TYPE_PULSE (2U << PWM_CAPTURE_TYPE_SHIFT)
67
69#define PWM_CAPTURE_TYPE_BOTH (PWM_CAPTURE_TYPE_PERIOD | \
70 PWM_CAPTURE_TYPE_PULSE)
71
73#define PWM_CAPTURE_MODE_SINGLE (0U << PWM_CAPTURE_MODE_SHIFT)
74
76#define PWM_CAPTURE_MODE_CONTINUOUS (1U << PWM_CAPTURE_MODE_SHIFT)
77
79
85
86#define PWM_EVENT_TYPE_SHIFT 0U
87
89#define PWM_EVENT_TYPE_PERIOD (1U << PWM_EVENT_TYPE_SHIFT)
90
97#define PWM_EVENT_TYPE_FAULT (2U << PWM_EVENT_TYPE_SHIFT)
98
103#define PWM_EVENT_TYPE_COMPARE_CAPTURE (4U << PWM_EVENT_TYPE_SHIFT)
104
106
115
117
123
125
151
196#define PWM_DT_SPEC_GET_BY_NAME(node_id, name) \
197 { \
198 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_NAME(node_id, name)), \
199 .channel = DT_PWMS_CHANNEL_BY_NAME(node_id, name), \
200 .period = DT_PWMS_PERIOD_BY_NAME(node_id, name), \
201 .flags = DT_PWMS_FLAGS_BY_NAME(node_id, name), \
202 }
203
216#define PWM_DT_SPEC_INST_GET_BY_NAME(inst, name) \
217 PWM_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
218
237#define PWM_DT_SPEC_GET_BY_NAME_OR(node_id, name, default_value) \
238 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
239 (PWM_DT_SPEC_GET_BY_NAME(node_id, name)), \
240 (default_value))
241
256#define PWM_DT_SPEC_INST_GET_BY_NAME_OR(inst, name, default_value) \
257 PWM_DT_SPEC_GET_BY_NAME_OR(DT_DRV_INST(inst), name, default_value)
258
301#define PWM_DT_SPEC_GET_BY_IDX(node_id, idx) \
302 { \
303 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_IDX(node_id, idx)), \
304 .channel = DT_PWMS_CHANNEL_BY_IDX(node_id, idx), \
305 .period = DT_PWMS_PERIOD_BY_IDX(node_id, idx), \
306 .flags = DT_PWMS_FLAGS_BY_IDX(node_id, idx), \
307 }
308
320#define PWM_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
321 PWM_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
322
340#define PWM_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \
341 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
342 (PWM_DT_SPEC_GET_BY_IDX(node_id, idx)), \
343 (default_value))
344
358#define PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \
359 PWM_DT_SPEC_GET_BY_IDX_OR(DT_DRV_INST(inst), idx, default_value)
360
371#define PWM_DT_SPEC_GET(node_id) PWM_DT_SPEC_GET_BY_IDX(node_id, 0)
372
383#define PWM_DT_SPEC_INST_GET(inst) PWM_DT_SPEC_GET(DT_DRV_INST(inst))
384
397#define PWM_DT_SPEC_GET_OR(node_id, default_value) \
398 PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)
399
412#define PWM_DT_SPEC_INST_GET_OR(inst, default_value) \
413 PWM_DT_SPEC_GET_OR(DT_DRV_INST(inst), default_value)
414
434typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
435 uint32_t channel,
436 uint32_t period_cycles,
437 uint32_t pulse_cycles,
438 int status, void *user_data);
439
440struct pwm_event_callback;
441
456typedef void (*pwm_event_callback_handler_t)(const struct device *dev,
457 struct pwm_event_callback *callback, uint32_t channel,
458 pwm_events_t events);
459
485
490
495typedef int (*pwm_set_cycles_t)(const struct device *dev, uint32_t channel,
496 uint32_t period_cycles, uint32_t pulse_cycles,
498
503typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
504 uint32_t channel, uint64_t *cycles);
505
506#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
511typedef int (*pwm_configure_capture_t)(const struct device *dev,
512 uint32_t channel, pwm_flags_t flags,
514 void *user_data);
515
520typedef int (*pwm_enable_capture_t)(const struct device *dev, uint32_t channel);
521
526typedef int (*pwm_disable_capture_t)(const struct device *dev,
527 uint32_t channel);
528#endif /* CONFIG_PWM_CAPTURE */
529
530#if defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__)
535typedef int (*pwm_manage_event_callback_t)(const struct device *dev,
536 struct pwm_event_callback *callback, bool set);
537#endif /* CONFIG_PWM_EVENT */
538
542__subsystem struct pwm_driver_api {
551#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
567#endif /* CONFIG_PWM_CAPTURE */
568#if defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__)
574#endif /* CONFIG_PWM_EVENT */
575};
576
580
611__syscall int pwm_set_cycles(const struct device *dev, uint32_t channel,
612 uint32_t period, uint32_t pulse,
614
615static inline int z_impl_pwm_set_cycles(const struct device *dev,
616 uint32_t channel, uint32_t period,
618{
619 const struct pwm_driver_api *api =
620 (const struct pwm_driver_api *)dev->api;
621
622 if (pulse > period) {
623 return -EINVAL;
624 }
625
626 return api->set_cycles(dev, channel, period, pulse, flags);
627}
628
640__syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
641 uint64_t *cycles);
642
643static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
644 uint32_t channel,
645 uint64_t *cycles)
646{
647 const struct pwm_driver_api *api =
648 (const struct pwm_driver_api *)dev->api;
649
650 return api->get_cycles_per_sec(dev, channel, cycles);
651}
652
669static inline int pwm_set(const struct device *dev, uint32_t channel,
670 uint32_t period, uint32_t pulse, pwm_flags_t flags)
671{
672 int err;
673 uint64_t pulse_cycles;
674 uint64_t period_cycles;
675 uint64_t cycles_per_sec;
676
677 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
678 if (err < 0) {
679 return err;
680 }
681
682 period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
683 if (period_cycles > UINT32_MAX) {
684 return -ENOTSUP;
685 }
686
687 pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
688 if (pulse_cycles > UINT32_MAX) {
689 return -ENOTSUP;
690 }
691
692 return pwm_set_cycles(dev, channel, (uint32_t)period_cycles,
693 (uint32_t)pulse_cycles, flags);
694}
695
715static inline int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period,
716 uint32_t pulse)
717{
718 return pwm_set(spec->dev, spec->channel, period, pulse, spec->flags);
719}
720
736static inline int pwm_set_pulse_dt(const struct pwm_dt_spec *spec,
737 uint32_t pulse)
738{
739 return pwm_set(spec->dev, spec->channel, spec->period, pulse,
740 spec->flags);
741}
742
755static inline int pwm_cycles_to_usec(const struct device *dev, uint32_t channel,
756 uint32_t cycles, uint64_t *usec)
757{
758 int err;
759 uint64_t temp;
760 uint64_t cycles_per_sec;
761
762 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
763 if (err < 0) {
764 return err;
765 }
766
767 if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
768 return -ERANGE;
769 }
770
771 *usec = temp / cycles_per_sec;
772
773 return 0;
774}
775
788static inline int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel,
789 uint32_t cycles, uint64_t *nsec)
790{
791 int err;
792 uint64_t temp;
793 uint64_t cycles_per_sec;
794
795 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
796 if (err < 0) {
797 return err;
798 }
799
800 if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
801 return -ERANGE;
802 }
803
804 *nsec = temp / cycles_per_sec;
805
806 return 0;
807}
808
809#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
837static inline int pwm_configure_capture(const struct device *dev,
838 uint32_t channel, pwm_flags_t flags,
840 void *user_data)
841{
842 const struct pwm_driver_api *api =
843 (const struct pwm_driver_api *)dev->api;
844
845 if (api->configure_capture == NULL) {
846 return -ENOSYS;
847 }
848
849 return api->configure_capture(dev, channel, flags, cb,
850 user_data);
851}
852#endif /* CONFIG_PWM_CAPTURE */
853
872__syscall int pwm_enable_capture(const struct device *dev, uint32_t channel);
873
874#ifdef CONFIG_PWM_CAPTURE
875static inline int z_impl_pwm_enable_capture(const struct device *dev,
876 uint32_t channel)
877{
878 const struct pwm_driver_api *api =
879 (const struct pwm_driver_api *)dev->api;
880
881 if (api->enable_capture == NULL) {
882 return -ENOSYS;
883 }
884
885 return api->enable_capture(dev, channel);
886}
887#endif /* CONFIG_PWM_CAPTURE */
888
902__syscall int pwm_disable_capture(const struct device *dev, uint32_t channel);
903
904#ifdef CONFIG_PWM_CAPTURE
905static inline int z_impl_pwm_disable_capture(const struct device *dev,
906 uint32_t channel)
907{
908 const struct pwm_driver_api *api =
909 (const struct pwm_driver_api *)dev->api;
910
911 if (api->disable_capture == NULL) {
912 return -ENOSYS;
913 }
914
915 return api->disable_capture(dev, channel);
916}
917#endif /* CONFIG_PWM_CAPTURE */
918
945__syscall int pwm_capture_cycles(const struct device *dev, uint32_t channel,
946 pwm_flags_t flags, uint32_t *period,
947 uint32_t *pulse, k_timeout_t timeout);
948
976static inline int pwm_capture_usec(const struct device *dev, uint32_t channel,
977 pwm_flags_t flags, uint64_t *period,
978 uint64_t *pulse, k_timeout_t timeout)
979{
980 int err;
981 uint32_t pulse_cycles;
982 uint32_t period_cycles;
983
984 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
985 &pulse_cycles, timeout);
986 if (err < 0) {
987 return err;
988 }
989
990 err = pwm_cycles_to_usec(dev, channel, period_cycles, period);
991 if (err < 0) {
992 return err;
993 }
994
995 err = pwm_cycles_to_usec(dev, channel, pulse_cycles, pulse);
996 if (err < 0) {
997 return err;
998 }
999
1000 return 0;
1001}
1002
1030static inline int pwm_capture_nsec(const struct device *dev, uint32_t channel,
1031 pwm_flags_t flags, uint64_t *period,
1032 uint64_t *pulse, k_timeout_t timeout)
1033{
1034 int err;
1035 uint32_t pulse_cycles;
1036 uint32_t period_cycles;
1037
1038 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
1039 &pulse_cycles, timeout);
1040 if (err < 0) {
1041 return err;
1042 }
1043
1044 err = pwm_cycles_to_nsec(dev, channel, period_cycles, period);
1045 if (err < 0) {
1046 return err;
1047 }
1048
1049 err = pwm_cycles_to_nsec(dev, channel, pulse_cycles, pulse);
1050 if (err < 0) {
1051 return err;
1052 }
1053
1054 return 0;
1055}
1056
1057#if defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__)
1068static inline void pwm_init_event_callback(struct pwm_event_callback *callback,
1069 pwm_event_callback_handler_t handler, uint32_t channel,
1070 pwm_events_t event_mask)
1071{
1072 __ASSERT_NO_MSG(callback != NULL);
1073 __ASSERT_NO_MSG(handler != NULL);
1074
1075 callback->handler = handler;
1076 callback->channel = channel;
1077 callback->event_mask = event_mask;
1078}
1079
1094static inline int pwm_add_event_callback(const struct device *dev,
1095 struct pwm_event_callback *callback)
1096{
1097 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
1098
1099 if (api->manage_event_callback == NULL) {
1100 return -ENOSYS;
1101 }
1102
1103 return api->manage_event_callback(dev, callback, true);
1104}
1105
1118static inline int pwm_remove_event_callback(const struct device *dev,
1119 struct pwm_event_callback *callback)
1120{
1121 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
1122
1123 if (api->manage_event_callback == NULL) {
1124 return -ENOSYS;
1125 }
1126
1127 return api->manage_event_callback(dev, callback, false);
1128}
1129#endif /* defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__) */
1130
1139static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
1140{
1141 return device_is_ready(spec->dev);
1142}
1143
1144#ifdef __cplusplus
1145}
1146#endif
1147
1151
1152#include <zephyr/syscalls/pwm.h>
1153
1154#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_set_cycles_t)(const struct device *dev, uint32_t channel, uint32_t period_cycles, uint32_t pulse_cycles, pwm_flags_t flags)
Callback API to configure PWM pin period and pulse width.
Definition pwm.h:495
int(* pwm_disable_capture_t)(const struct device *dev, uint32_t channel)
Callback API to disable PWM capture.
Definition pwm.h:526
int(* pwm_get_cycles_per_sec_t)(const struct device *dev, uint32_t channel, uint64_t *cycles)
Callback API to obtain PWM cycles per second (frequency).
Definition pwm.h:503
int(* pwm_manage_event_callback_t)(const struct device *dev, struct pwm_event_callback *callback, bool set)
Callback API to manage event callbacks.
Definition pwm.h:535
int(* pwm_configure_capture_t)(const struct device *dev, uint32_t channel, pwm_flags_t flags, pwm_capture_callback_handler_t cb, void *user_data)
Callback API to configure PWM capture.
Definition pwm.h:511
int(* pwm_enable_capture_t)(const struct device *dev, uint32_t channel)
Callback API to enable PWM capture.
Definition pwm.h:520
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:1094
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:715
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:434
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:976
uint16_t pwm_events_t
Provides a type to hold PWM events.
Definition pwm.h:124
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:1030
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:788
static bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
Validate that the PWM device is ready.
Definition pwm.h:1139
static int pwm_remove_event_callback(const struct device *dev, struct pwm_event_callback *callback)
Remove an application event callback.
Definition pwm.h:1118
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:736
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:837
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:669
uint16_t pwm_flags_t
Provides a type to hold PWM configuration flags.
Definition pwm.h:116
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:755
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:456
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:1068
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
<span class="mlabel">Driver Operations</span> PWM driver operations
Definition pwm.h:542
pwm_get_cycles_per_sec_t get_cycles_per_sec
<span class="op-badge op-req" title="This operation MUST be implemented by the driver....
Definition pwm.h:550
pwm_configure_capture_t configure_capture
<span class="op-badge op-opt" title="This operation MAY optionally be implemented by the driver....
Definition pwm.h:556
pwm_set_cycles_t set_cycles
<span class="op-badge op-req" title="This operation MUST be implemented by the driver....
Definition pwm.h:546
pwm_disable_capture_t disable_capture
<span class="op-badge op-opt" title="This operation MAY optionally be implemented by the driver....
Definition pwm.h:566
pwm_manage_event_callback_t manage_event_callback
<span class="op-badge op-opt" title="This operation MAY optionally be implemented by the driver....
Definition pwm.h:573
pwm_enable_capture_t enable_capture
<span class="op-badge op-opt" title="This operation MAY optionally be implemented by the driver....
Definition pwm.h:561
Container for PWM information specified in devicetree.
Definition pwm.h:141
pwm_flags_t flags
Flags.
Definition pwm.h:149
uint32_t channel
Channel number.
Definition pwm.h:145
uint32_t period
Period in nanoseconds.
Definition pwm.h:147
const struct device * dev
PWM device instance.
Definition pwm.h:143
PWM event callback structure.
Definition pwm.h:471
uint32_t channel
Channel the callback is interested in.
Definition pwm.h:480
pwm_events_t event_mask
A mask of events the callback is interested in.
Definition pwm.h:483
pwm_event_callback_handler_t handler
Actual callback function being called when relevant.
Definition pwm.h:477
Macros to abstract toolchain specific capabilities.