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 *
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
100
109
111
117
119
145
190#define PWM_DT_SPEC_GET_BY_NAME(node_id, name) \
191 { \
192 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_NAME(node_id, name)), \
193 .channel = DT_PWMS_CHANNEL_BY_NAME(node_id, name), \
194 .period = DT_PWMS_PERIOD_BY_NAME(node_id, name), \
195 .flags = DT_PWMS_FLAGS_BY_NAME(node_id, name), \
196 }
197
210#define PWM_DT_SPEC_INST_GET_BY_NAME(inst, name) \
211 PWM_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
212
231#define PWM_DT_SPEC_GET_BY_NAME_OR(node_id, name, default_value) \
232 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
233 (PWM_DT_SPEC_GET_BY_NAME(node_id, name)), \
234 (default_value))
235
250#define PWM_DT_SPEC_INST_GET_BY_NAME_OR(inst, name, default_value) \
251 PWM_DT_SPEC_GET_BY_NAME_OR(DT_DRV_INST(inst), name, default_value)
252
295#define PWM_DT_SPEC_GET_BY_IDX(node_id, idx) \
296 { \
297 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_IDX(node_id, idx)), \
298 .channel = DT_PWMS_CHANNEL_BY_IDX(node_id, idx), \
299 .period = DT_PWMS_PERIOD_BY_IDX(node_id, idx), \
300 .flags = DT_PWMS_FLAGS_BY_IDX(node_id, idx), \
301 }
302
314#define PWM_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
315 PWM_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
316
334#define PWM_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \
335 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
336 (PWM_DT_SPEC_GET_BY_IDX(node_id, idx)), \
337 (default_value))
338
352#define PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \
353 PWM_DT_SPEC_GET_BY_IDX_OR(DT_DRV_INST(inst), idx, default_value)
354
365#define PWM_DT_SPEC_GET(node_id) PWM_DT_SPEC_GET_BY_IDX(node_id, 0)
366
377#define PWM_DT_SPEC_INST_GET(inst) PWM_DT_SPEC_GET(DT_DRV_INST(inst))
378
391#define PWM_DT_SPEC_GET_OR(node_id, default_value) \
392 PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)
393
406#define PWM_DT_SPEC_INST_GET_OR(inst, default_value) \
407 PWM_DT_SPEC_GET_OR(DT_DRV_INST(inst), default_value)
408
428typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
429 uint32_t channel,
430 uint32_t period_cycles,
431 uint32_t pulse_cycles,
432 int status, void *user_data);
433
434struct pwm_event_callback;
435
450typedef void (*pwm_event_callback_handler_t)(const struct device *dev,
451 struct pwm_event_callback *callback, uint32_t channel,
452 pwm_events_t events);
453
479
485typedef int (*pwm_set_cycles_t)(const struct device *dev, uint32_t channel,
486 uint32_t period_cycles, uint32_t pulse_cycles,
488
493typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
494 uint32_t channel, uint64_t *cycles);
495
496#ifdef CONFIG_PWM_CAPTURE
501typedef int (*pwm_configure_capture_t)(const struct device *dev,
502 uint32_t channel, pwm_flags_t flags,
504 void *user_data);
505
510typedef int (*pwm_enable_capture_t)(const struct device *dev, uint32_t channel);
511
516typedef int (*pwm_disable_capture_t)(const struct device *dev,
517 uint32_t channel);
518#endif /* CONFIG_PWM_CAPTURE */
519
520#ifdef CONFIG_PWM_EVENT
521
526typedef int (*pwm_manage_event_callback_t)(const struct device *dev,
527 struct pwm_event_callback *callback, bool set);
528#endif /* CONFIG_PWM_EVENT */
529
531__subsystem struct pwm_driver_api {
532 pwm_set_cycles_t set_cycles;
533 pwm_get_cycles_per_sec_t get_cycles_per_sec;
534#ifdef CONFIG_PWM_CAPTURE
535 pwm_configure_capture_t configure_capture;
536 pwm_enable_capture_t enable_capture;
537 pwm_disable_capture_t disable_capture;
538#endif /* CONFIG_PWM_CAPTURE */
539#ifdef CONFIG_PWM_EVENT
540 pwm_manage_event_callback_t manage_event_callback;
541#endif /* CONFIG_PWM_EVENT */
542};
544
575__syscall int pwm_set_cycles(const struct device *dev, uint32_t channel,
576 uint32_t period, uint32_t pulse,
578
579static inline int z_impl_pwm_set_cycles(const struct device *dev,
580 uint32_t channel, uint32_t period,
582{
583 const struct pwm_driver_api *api =
584 (const struct pwm_driver_api *)dev->api;
585
586 if (pulse > period) {
587 return -EINVAL;
588 }
589
590 return api->set_cycles(dev, channel, period, pulse, flags);
591}
592
604__syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
605 uint64_t *cycles);
606
607static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
608 uint32_t channel,
609 uint64_t *cycles)
610{
611 const struct pwm_driver_api *api =
612 (const struct pwm_driver_api *)dev->api;
613
614 return api->get_cycles_per_sec(dev, channel, cycles);
615}
616
633static inline int pwm_set(const struct device *dev, uint32_t channel,
634 uint32_t period, uint32_t pulse, pwm_flags_t flags)
635{
636 int err;
637 uint64_t pulse_cycles;
638 uint64_t period_cycles;
639 uint64_t cycles_per_sec;
640
641 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
642 if (err < 0) {
643 return err;
644 }
645
646 period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
647 if (period_cycles > UINT32_MAX) {
648 return -ENOTSUP;
649 }
650
651 pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
652 if (pulse_cycles > UINT32_MAX) {
653 return -ENOTSUP;
654 }
655
656 return pwm_set_cycles(dev, channel, (uint32_t)period_cycles,
657 (uint32_t)pulse_cycles, flags);
658}
659
679static inline int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period,
680 uint32_t pulse)
681{
682 return pwm_set(spec->dev, spec->channel, period, pulse, spec->flags);
683}
684
700static inline int pwm_set_pulse_dt(const struct pwm_dt_spec *spec,
701 uint32_t pulse)
702{
703 return pwm_set(spec->dev, spec->channel, spec->period, pulse,
704 spec->flags);
705}
706
719static inline int pwm_cycles_to_usec(const struct device *dev, uint32_t channel,
720 uint32_t cycles, uint64_t *usec)
721{
722 int err;
723 uint64_t temp;
724 uint64_t cycles_per_sec;
725
726 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
727 if (err < 0) {
728 return err;
729 }
730
731 if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
732 return -ERANGE;
733 }
734
735 *usec = temp / cycles_per_sec;
736
737 return 0;
738}
739
752static inline int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel,
753 uint32_t cycles, uint64_t *nsec)
754{
755 int err;
756 uint64_t temp;
757 uint64_t cycles_per_sec;
758
759 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
760 if (err < 0) {
761 return err;
762 }
763
764 if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
765 return -ERANGE;
766 }
767
768 *nsec = temp / cycles_per_sec;
769
770 return 0;
771}
772
773#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
802static inline int pwm_configure_capture(const struct device *dev,
803 uint32_t channel, pwm_flags_t flags,
805 void *user_data)
806{
807 const struct pwm_driver_api *api =
808 (const struct pwm_driver_api *)dev->api;
809
810 if (api->configure_capture == NULL) {
811 return -ENOSYS;
812 }
813
814 return api->configure_capture(dev, channel, flags, cb,
815 user_data);
816}
817#endif /* CONFIG_PWM_CAPTURE */
818
837__syscall int pwm_enable_capture(const struct device *dev, uint32_t channel);
838
839#ifdef CONFIG_PWM_CAPTURE
840static inline int z_impl_pwm_enable_capture(const struct device *dev,
841 uint32_t channel)
842{
843 const struct pwm_driver_api *api =
844 (const struct pwm_driver_api *)dev->api;
845
846 if (api->enable_capture == NULL) {
847 return -ENOSYS;
848 }
849
850 return api->enable_capture(dev, channel);
851}
852#endif /* CONFIG_PWM_CAPTURE */
853
868__syscall int pwm_disable_capture(const struct device *dev, uint32_t channel);
869
870#ifdef CONFIG_PWM_CAPTURE
871static inline int z_impl_pwm_disable_capture(const struct device *dev,
872 uint32_t channel)
873{
874 const struct pwm_driver_api *api =
875 (const struct pwm_driver_api *)dev->api;
876
877 if (api->disable_capture == NULL) {
878 return -ENOSYS;
879 }
880
881 return api->disable_capture(dev, channel);
882}
883#endif /* CONFIG_PWM_CAPTURE */
884
912__syscall int pwm_capture_cycles(const struct device *dev, uint32_t channel,
913 pwm_flags_t flags, uint32_t *period,
914 uint32_t *pulse, k_timeout_t timeout);
915
944static inline int pwm_capture_usec(const struct device *dev, uint32_t channel,
945 pwm_flags_t flags, uint64_t *period,
946 uint64_t *pulse, k_timeout_t timeout)
947{
948 int err;
949 uint32_t pulse_cycles;
950 uint32_t period_cycles;
951
952 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
953 &pulse_cycles, timeout);
954 if (err < 0) {
955 return err;
956 }
957
958 err = pwm_cycles_to_usec(dev, channel, period_cycles, period);
959 if (err < 0) {
960 return err;
961 }
962
963 err = pwm_cycles_to_usec(dev, channel, pulse_cycles, pulse);
964 if (err < 0) {
965 return err;
966 }
967
968 return 0;
969}
970
999static inline int pwm_capture_nsec(const struct device *dev, uint32_t channel,
1000 pwm_flags_t flags, uint64_t *period,
1001 uint64_t *pulse, k_timeout_t timeout)
1002{
1003 int err;
1004 uint32_t pulse_cycles;
1005 uint32_t period_cycles;
1006
1007 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
1008 &pulse_cycles, timeout);
1009 if (err < 0) {
1010 return err;
1011 }
1012
1013 err = pwm_cycles_to_nsec(dev, channel, period_cycles, period);
1014 if (err < 0) {
1015 return err;
1016 }
1017
1018 err = pwm_cycles_to_nsec(dev, channel, pulse_cycles, pulse);
1019 if (err < 0) {
1020 return err;
1021 }
1022
1023 return 0;
1024}
1025
1026#if defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__)
1035static inline void pwm_init_event_callback(struct pwm_event_callback *callback,
1036 pwm_event_callback_handler_t handler, uint32_t channel,
1037 pwm_events_t event_mask)
1038{
1039 __ASSERT_NO_MSG(callback != NULL);
1040 __ASSERT_NO_MSG(handler != NULL);
1041
1042 callback->handler = handler;
1043 callback->channel = channel;
1044 callback->event_mask = event_mask;
1045}
1046
1059static inline int pwm_add_event_callback(const struct device *dev,
1060 struct pwm_event_callback *callback)
1061{
1062 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
1063
1064 if (api->manage_event_callback == NULL) {
1065 return -ENOSYS;
1066 }
1067
1068 return api->manage_event_callback(dev, callback, true);
1069}
1070
1081static inline int pwm_remove_event_callback(const struct device *dev,
1082 struct pwm_event_callback *callback)
1083{
1084 const struct pwm_driver_api *api = (const struct pwm_driver_api *)dev->api;
1085
1086 if (api->manage_event_callback == NULL) {
1087 return -ENOSYS;
1088 }
1089
1090 return api->manage_event_callback(dev, callback, false);
1091}
1092#endif /* defined(CONFIG_PWM_EVENT) || defined(__DOXYGEN__) */
1093
1102static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
1103{
1104 return device_is_ready(spec->dev);
1105}
1106
1107#ifdef __cplusplus
1108}
1109#endif
1110
1114
1115#include <zephyr/syscalls/pwm.h>
1116
1117#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:1059
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:679
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:428
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:944
uint16_t pwm_events_t
Provides a type to hold PWM events.
Definition pwm.h:118
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:999
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:752
static bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
Validate that the PWM device is ready.
Definition pwm.h:1102
static int pwm_remove_event_callback(const struct device *dev, struct pwm_event_callback *callback)
Remove an application event callback.
Definition pwm.h:1081
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:700
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:802
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:633
uint16_t pwm_flags_t
Provides a type to hold PWM configuration flags.
Definition pwm.h:110
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:719
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:450
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:1035
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:135
pwm_flags_t flags
Flags.
Definition pwm.h:143
uint32_t channel
Channel number.
Definition pwm.h:139
uint32_t period
Period in nanoseconds.
Definition pwm.h:141
const struct device * dev
PWM device instance.
Definition pwm.h:137
PWM event callback structure.
Definition pwm.h:465
uint32_t channel
Channel the callback is interested in.
Definition pwm.h:474
pwm_events_t event_mask
A mask of events the callback is interested in.
Definition pwm.h:477
pwm_event_callback_handler_t handler
Actual callback function being called when relevant.
Definition pwm.h:471
Macros to abstract toolchain specific capabilities.