Zephyr API Documentation  3.5.0
A Scalable Open Source RTOS
3.5.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
13#ifndef ZEPHYR_INCLUDE_DRIVERS_PWM_H_
14#define ZEPHYR_INCLUDE_DRIVERS_PWM_H_
15
23#include <errno.h>
24#include <stdint.h>
25
26#include <zephyr/device.h>
27#include <zephyr/devicetree.h>
28#include <zephyr/sys_clock.h>
30#include <zephyr/toolchain.h>
31
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
45/* Bit 0 is used for PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED */
46#define PWM_CAPTURE_TYPE_SHIFT 1U
47#define PWM_CAPTURE_TYPE_MASK (3U << PWM_CAPTURE_TYPE_SHIFT)
48#define PWM_CAPTURE_MODE_SHIFT 3U
49#define PWM_CAPTURE_MODE_MASK (1U << PWM_CAPTURE_MODE_SHIFT)
53#define PWM_CAPTURE_TYPE_PERIOD (1U << PWM_CAPTURE_TYPE_SHIFT)
54
56#define PWM_CAPTURE_TYPE_PULSE (2U << PWM_CAPTURE_TYPE_SHIFT)
57
59#define PWM_CAPTURE_TYPE_BOTH (PWM_CAPTURE_TYPE_PERIOD | \
60 PWM_CAPTURE_TYPE_PULSE)
61
63#define PWM_CAPTURE_MODE_SINGLE (0U << PWM_CAPTURE_MODE_SHIFT)
64
66#define PWM_CAPTURE_MODE_CONTINUOUS (1U << PWM_CAPTURE_MODE_SHIFT)
67
80
98 const struct device *dev;
105};
106
151#define PWM_DT_SPEC_GET_BY_NAME(node_id, name) \
152 { \
153 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_NAME(node_id, name)), \
154 .channel = DT_PWMS_CHANNEL_BY_NAME(node_id, name), \
155 .period = DT_PWMS_PERIOD_BY_NAME(node_id, name), \
156 .flags = DT_PWMS_FLAGS_BY_NAME(node_id, name), \
157 }
158
171#define PWM_DT_SPEC_INST_GET_BY_NAME(inst, name) \
172 PWM_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
173
192#define PWM_DT_SPEC_GET_BY_NAME_OR(node_id, name, default_value) \
193 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
194 (PWM_DT_SPEC_GET_BY_NAME(node_id, name)), \
195 (default_value))
196
211#define PWM_DT_SPEC_INST_GET_BY_NAME_OR(inst, name, default_value) \
212 PWM_DT_SPEC_GET_BY_NAME_OR(DT_DRV_INST(inst), name, default_value)
213
256#define PWM_DT_SPEC_GET_BY_IDX(node_id, idx) \
257 { \
258 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_IDX(node_id, idx)), \
259 .channel = DT_PWMS_CHANNEL_BY_IDX(node_id, idx), \
260 .period = DT_PWMS_PERIOD_BY_IDX(node_id, idx), \
261 .flags = DT_PWMS_FLAGS_BY_IDX(node_id, idx), \
262 }
263
275#define PWM_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
276 PWM_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
277
295#define PWM_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \
296 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
297 (PWM_DT_SPEC_GET_BY_IDX(node_id, idx)), \
298 (default_value))
299
313#define PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \
314 PWM_DT_SPEC_GET_BY_IDX_OR(DT_DRV_INST(inst), idx, default_value)
315
326#define PWM_DT_SPEC_GET(node_id) PWM_DT_SPEC_GET_BY_IDX(node_id, 0)
327
338#define PWM_DT_SPEC_INST_GET(inst) PWM_DT_SPEC_GET(DT_DRV_INST(inst))
339
352#define PWM_DT_SPEC_GET_OR(node_id, default_value) \
353 PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)
354
367#define PWM_DT_SPEC_INST_GET_OR(inst, default_value) \
368 PWM_DT_SPEC_GET_OR(DT_DRV_INST(inst), default_value)
369
389typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
390 uint32_t channel,
391 uint32_t period_cycles,
392 uint32_t pulse_cycles,
393 int status, void *user_data);
394
400typedef int (*pwm_set_cycles_t)(const struct device *dev, uint32_t channel,
401 uint32_t period_cycles, uint32_t pulse_cycles,
403
408typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
409 uint32_t channel, uint64_t *cycles);
410
411#ifdef CONFIG_PWM_CAPTURE
416typedef int (*pwm_configure_capture_t)(const struct device *dev,
417 uint32_t channel, pwm_flags_t flags,
419 void *user_data);
420
425typedef int (*pwm_enable_capture_t)(const struct device *dev, uint32_t channel);
426
431typedef int (*pwm_disable_capture_t)(const struct device *dev,
432 uint32_t channel);
433#endif /* CONFIG_PWM_CAPTURE */
434
436__subsystem struct pwm_driver_api {
437 pwm_set_cycles_t set_cycles;
438 pwm_get_cycles_per_sec_t get_cycles_per_sec;
439#ifdef CONFIG_PWM_CAPTURE
440 pwm_configure_capture_t configure_capture;
441 pwm_enable_capture_t enable_capture;
442 pwm_disable_capture_t disable_capture;
443#endif /* CONFIG_PWM_CAPTURE */
444};
477__syscall int pwm_set_cycles(const struct device *dev, uint32_t channel,
478 uint32_t period, uint32_t pulse,
480
481static inline int z_impl_pwm_set_cycles(const struct device *dev,
482 uint32_t channel, uint32_t period,
484{
485 const struct pwm_driver_api *api =
486 (const struct pwm_driver_api *)dev->api;
487
488 if (pulse > period) {
489 return -EINVAL;
490 }
491
492 return api->set_cycles(dev, channel, period, pulse, flags);
493}
494
506__syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
507 uint64_t *cycles);
508
509static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
510 uint32_t channel,
511 uint64_t *cycles)
512{
513 const struct pwm_driver_api *api =
514 (const struct pwm_driver_api *)dev->api;
515
516 return api->get_cycles_per_sec(dev, channel, cycles);
517}
518
535static inline int pwm_set(const struct device *dev, uint32_t channel,
536 uint32_t period, uint32_t pulse, pwm_flags_t flags)
537{
538 int err;
539 uint64_t pulse_cycles;
540 uint64_t period_cycles;
541 uint64_t cycles_per_sec;
542
543 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
544 if (err < 0) {
545 return err;
546 }
547
548 period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
549 if (period_cycles > UINT32_MAX) {
550 return -ENOTSUP;
551 }
552
553 pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
554 if (pulse_cycles > UINT32_MAX) {
555 return -ENOTSUP;
556 }
557
558 return pwm_set_cycles(dev, channel, (uint32_t)period_cycles,
559 (uint32_t)pulse_cycles, flags);
560}
561
581static inline int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period,
582 uint32_t pulse)
583{
584 return pwm_set(spec->dev, spec->channel, period, pulse, spec->flags);
585}
586
602static inline int pwm_set_pulse_dt(const struct pwm_dt_spec *spec,
603 uint32_t pulse)
604{
605 return pwm_set(spec->dev, spec->channel, spec->period, pulse,
606 spec->flags);
607}
608
621static inline int pwm_cycles_to_usec(const struct device *dev, uint32_t channel,
622 uint32_t cycles, uint64_t *usec)
623{
624 int err;
625 uint64_t temp;
626 uint64_t cycles_per_sec;
627
628 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
629 if (err < 0) {
630 return err;
631 }
632
633 if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
634 return -ERANGE;
635 }
636
637 *usec = temp / cycles_per_sec;
638
639 return 0;
640}
641
654static inline int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel,
655 uint32_t cycles, uint64_t *nsec)
656{
657 int err;
658 uint64_t temp;
659 uint64_t cycles_per_sec;
660
661 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
662 if (err < 0) {
663 return err;
664 }
665
666 if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
667 return -ERANGE;
668 }
669
670 *nsec = temp / cycles_per_sec;
671
672 return 0;
673}
674
675#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
704static inline int pwm_configure_capture(const struct device *dev,
705 uint32_t channel, pwm_flags_t flags,
707 void *user_data)
708{
709 const struct pwm_driver_api *api =
710 (const struct pwm_driver_api *)dev->api;
711
712 if (api->configure_capture == NULL) {
713 return -ENOSYS;
714 }
715
716 return api->configure_capture(dev, channel, flags, cb,
717 user_data);
718}
719#endif /* CONFIG_PWM_CAPTURE */
720
739__syscall int pwm_enable_capture(const struct device *dev, uint32_t channel);
740
741#ifdef CONFIG_PWM_CAPTURE
742static inline int z_impl_pwm_enable_capture(const struct device *dev,
743 uint32_t channel)
744{
745 const struct pwm_driver_api *api =
746 (const struct pwm_driver_api *)dev->api;
747
748 if (api->enable_capture == NULL) {
749 return -ENOSYS;
750 }
751
752 return api->enable_capture(dev, channel);
753}
754#endif /* CONFIG_PWM_CAPTURE */
755
770__syscall int pwm_disable_capture(const struct device *dev, uint32_t channel);
771
772#ifdef CONFIG_PWM_CAPTURE
773static inline int z_impl_pwm_disable_capture(const struct device *dev,
774 uint32_t channel)
775{
776 const struct pwm_driver_api *api =
777 (const struct pwm_driver_api *)dev->api;
778
779 if (api->disable_capture == NULL) {
780 return -ENOSYS;
781 }
782
783 return api->disable_capture(dev, channel);
784}
785#endif /* CONFIG_PWM_CAPTURE */
786
814__syscall int pwm_capture_cycles(const struct device *dev, uint32_t channel,
815 pwm_flags_t flags, uint32_t *period,
816 uint32_t *pulse, k_timeout_t timeout);
817
846static inline int pwm_capture_usec(const struct device *dev, uint32_t channel,
847 pwm_flags_t flags, uint64_t *period,
848 uint64_t *pulse, k_timeout_t timeout)
849{
850 int err;
851 uint32_t pulse_cycles;
852 uint32_t period_cycles;
853
854 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
855 &pulse_cycles, timeout);
856 if (err < 0) {
857 return err;
858 }
859
860 err = pwm_cycles_to_usec(dev, channel, period_cycles, period);
861 if (err < 0) {
862 return err;
863 }
864
865 err = pwm_cycles_to_usec(dev, channel, pulse_cycles, pulse);
866 if (err < 0) {
867 return err;
868 }
869
870 return 0;
871}
872
901static inline int pwm_capture_nsec(const struct device *dev, uint32_t channel,
902 pwm_flags_t flags, uint64_t *period,
903 uint64_t *pulse, k_timeout_t timeout)
904{
905 int err;
906 uint32_t pulse_cycles;
907 uint32_t period_cycles;
908
909 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
910 &pulse_cycles, timeout);
911 if (err < 0) {
912 return err;
913 }
914
915 err = pwm_cycles_to_nsec(dev, channel, period_cycles, period);
916 if (err < 0) {
917 return err;
918 }
919
920 err = pwm_cycles_to_nsec(dev, channel, pulse_cycles, pulse);
921 if (err < 0) {
922 return err;
923 }
924
925 return 0;
926}
927
936static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
937{
938 return device_is_ready(spec->dev);
939}
940
941#ifdef __cplusplus
942}
943#endif
944
949#include <syscalls/pwm.h>
950
951#endif /* ZEPHYR_INCLUDE_DRIVERS_PWM_H_ */
Devicetree main header.
System error numbers.
#define NSEC_PER_SEC
number of nanoseconds per second
Definition: sys_clock.h:107
#define USEC_PER_SEC
number of microseconds per second
Definition: sys_clock.h:104
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.
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:581
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:389
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:846
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:901
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:654
static bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
Validate that the PWM device is ready.
Definition: pwm.h:936
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:602
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:704
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:535
uint16_t pwm_flags_t
Provides a type to hold PWM configuration flags.
Definition: pwm.h:79
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:621
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.
#define EINVAL
Invalid argument.
Definition: errno.h:61
#define ENOSYS
Function not implemented.
Definition: errno.h:83
#define ENOTSUP
Unsupported value.
Definition: errno.h:115
#define ERANGE
Result too large.
Definition: errno.h:73
Variables needed for system clock.
flags
Definition: parser.h:96
__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:381
const void * api
Address of the API structure exposed by the device instance.
Definition: device.h:387
Kernel timeout type.
Definition: sys_clock.h:65
Container for PWM information specified in devicetree.
Definition: pwm.h:96
pwm_flags_t flags
Flags.
Definition: pwm.h:104
uint32_t channel
Channel number.
Definition: pwm.h:100
uint32_t period
Period in nanoseconds.
Definition: pwm.h:102
const struct device * dev
PWM device instance.
Definition: pwm.h:98
Macros to abstract toolchain specific capabilities.