Zephyr Project API 4.2.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 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
14#ifndef ZEPHYR_INCLUDE_DRIVERS_PWM_H_
15#define ZEPHYR_INCLUDE_DRIVERS_PWM_H_
16
31#include <errno.h>
32#include <stdint.h>
33
34#include <zephyr/device.h>
35#include <zephyr/devicetree.h>
36#include <zephyr/sys_clock.h>
38#include <zephyr/toolchain.h>
39
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
53/* Bit 0 is used for PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED */
54#define PWM_CAPTURE_TYPE_SHIFT 1U
55#define PWM_CAPTURE_TYPE_MASK (3U << PWM_CAPTURE_TYPE_SHIFT)
56#define PWM_CAPTURE_MODE_SHIFT 3U
57#define PWM_CAPTURE_MODE_MASK (1U << PWM_CAPTURE_MODE_SHIFT)
61#define PWM_CAPTURE_TYPE_PERIOD (1U << PWM_CAPTURE_TYPE_SHIFT)
62
64#define PWM_CAPTURE_TYPE_PULSE (2U << PWM_CAPTURE_TYPE_SHIFT)
65
67#define PWM_CAPTURE_TYPE_BOTH (PWM_CAPTURE_TYPE_PERIOD | \
68 PWM_CAPTURE_TYPE_PULSE)
69
71#define PWM_CAPTURE_MODE_SINGLE (0U << PWM_CAPTURE_MODE_SHIFT)
72
74#define PWM_CAPTURE_MODE_CONTINUOUS (1U << PWM_CAPTURE_MODE_SHIFT)
75
88
114
159#define PWM_DT_SPEC_GET_BY_NAME(node_id, name) \
160 { \
161 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_NAME(node_id, name)), \
162 .channel = DT_PWMS_CHANNEL_BY_NAME(node_id, name), \
163 .period = DT_PWMS_PERIOD_BY_NAME(node_id, name), \
164 .flags = DT_PWMS_FLAGS_BY_NAME(node_id, name), \
165 }
166
179#define PWM_DT_SPEC_INST_GET_BY_NAME(inst, name) \
180 PWM_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
181
200#define PWM_DT_SPEC_GET_BY_NAME_OR(node_id, name, default_value) \
201 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
202 (PWM_DT_SPEC_GET_BY_NAME(node_id, name)), \
203 (default_value))
204
219#define PWM_DT_SPEC_INST_GET_BY_NAME_OR(inst, name, default_value) \
220 PWM_DT_SPEC_GET_BY_NAME_OR(DT_DRV_INST(inst), name, default_value)
221
264#define PWM_DT_SPEC_GET_BY_IDX(node_id, idx) \
265 { \
266 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_IDX(node_id, idx)), \
267 .channel = DT_PWMS_CHANNEL_BY_IDX(node_id, idx), \
268 .period = DT_PWMS_PERIOD_BY_IDX(node_id, idx), \
269 .flags = DT_PWMS_FLAGS_BY_IDX(node_id, idx), \
270 }
271
283#define PWM_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
284 PWM_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
285
303#define PWM_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \
304 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
305 (PWM_DT_SPEC_GET_BY_IDX(node_id, idx)), \
306 (default_value))
307
321#define PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \
322 PWM_DT_SPEC_GET_BY_IDX_OR(DT_DRV_INST(inst), idx, default_value)
323
334#define PWM_DT_SPEC_GET(node_id) PWM_DT_SPEC_GET_BY_IDX(node_id, 0)
335
346#define PWM_DT_SPEC_INST_GET(inst) PWM_DT_SPEC_GET(DT_DRV_INST(inst))
347
360#define PWM_DT_SPEC_GET_OR(node_id, default_value) \
361 PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)
362
375#define PWM_DT_SPEC_INST_GET_OR(inst, default_value) \
376 PWM_DT_SPEC_GET_OR(DT_DRV_INST(inst), default_value)
377
397typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
398 uint32_t channel,
399 uint32_t period_cycles,
400 uint32_t pulse_cycles,
401 int status, void *user_data);
402
408typedef int (*pwm_set_cycles_t)(const struct device *dev, uint32_t channel,
409 uint32_t period_cycles, uint32_t pulse_cycles,
411
416typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
417 uint32_t channel, uint64_t *cycles);
418
419#ifdef CONFIG_PWM_CAPTURE
424typedef int (*pwm_configure_capture_t)(const struct device *dev,
425 uint32_t channel, pwm_flags_t flags,
427 void *user_data);
428
433typedef int (*pwm_enable_capture_t)(const struct device *dev, uint32_t channel);
434
439typedef int (*pwm_disable_capture_t)(const struct device *dev,
440 uint32_t channel);
441#endif /* CONFIG_PWM_CAPTURE */
442
444__subsystem struct pwm_driver_api {
445 pwm_set_cycles_t set_cycles;
446 pwm_get_cycles_per_sec_t get_cycles_per_sec;
447#ifdef CONFIG_PWM_CAPTURE
448 pwm_configure_capture_t configure_capture;
449 pwm_enable_capture_t enable_capture;
450 pwm_disable_capture_t disable_capture;
451#endif /* CONFIG_PWM_CAPTURE */
452};
485__syscall int pwm_set_cycles(const struct device *dev, uint32_t channel,
486 uint32_t period, uint32_t pulse,
488
489static inline int z_impl_pwm_set_cycles(const struct device *dev,
490 uint32_t channel, uint32_t period,
492{
493 const struct pwm_driver_api *api =
494 (const struct pwm_driver_api *)dev->api;
495
496 if (pulse > period) {
497 return -EINVAL;
498 }
499
500 return api->set_cycles(dev, channel, period, pulse, flags);
501}
502
514__syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
515 uint64_t *cycles);
516
517static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
518 uint32_t channel,
519 uint64_t *cycles)
520{
521 const struct pwm_driver_api *api =
522 (const struct pwm_driver_api *)dev->api;
523
524 return api->get_cycles_per_sec(dev, channel, cycles);
525}
526
543static inline int pwm_set(const struct device *dev, uint32_t channel,
544 uint32_t period, uint32_t pulse, pwm_flags_t flags)
545{
546 int err;
547 uint64_t pulse_cycles;
548 uint64_t period_cycles;
549 uint64_t cycles_per_sec;
550
551 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
552 if (err < 0) {
553 return err;
554 }
555
556 period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
557 if (period_cycles > UINT32_MAX) {
558 return -ENOTSUP;
559 }
560
561 pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
562 if (pulse_cycles > UINT32_MAX) {
563 return -ENOTSUP;
564 }
565
566 return pwm_set_cycles(dev, channel, (uint32_t)period_cycles,
567 (uint32_t)pulse_cycles, flags);
568}
569
589static inline int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period,
590 uint32_t pulse)
591{
592 return pwm_set(spec->dev, spec->channel, period, pulse, spec->flags);
593}
594
610static inline int pwm_set_pulse_dt(const struct pwm_dt_spec *spec,
611 uint32_t pulse)
612{
613 return pwm_set(spec->dev, spec->channel, spec->period, pulse,
614 spec->flags);
615}
616
629static inline int pwm_cycles_to_usec(const struct device *dev, uint32_t channel,
630 uint32_t cycles, uint64_t *usec)
631{
632 int err;
633 uint64_t temp;
634 uint64_t cycles_per_sec;
635
636 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
637 if (err < 0) {
638 return err;
639 }
640
641 if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
642 return -ERANGE;
643 }
644
645 *usec = temp / cycles_per_sec;
646
647 return 0;
648}
649
662static inline int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel,
663 uint32_t cycles, uint64_t *nsec)
664{
665 int err;
666 uint64_t temp;
667 uint64_t cycles_per_sec;
668
669 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
670 if (err < 0) {
671 return err;
672 }
673
674 if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
675 return -ERANGE;
676 }
677
678 *nsec = temp / cycles_per_sec;
679
680 return 0;
681}
682
683#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
712static inline int pwm_configure_capture(const struct device *dev,
713 uint32_t channel, pwm_flags_t flags,
715 void *user_data)
716{
717 const struct pwm_driver_api *api =
718 (const struct pwm_driver_api *)dev->api;
719
720 if (api->configure_capture == NULL) {
721 return -ENOSYS;
722 }
723
724 return api->configure_capture(dev, channel, flags, cb,
725 user_data);
726}
727#endif /* CONFIG_PWM_CAPTURE */
728
747__syscall int pwm_enable_capture(const struct device *dev, uint32_t channel);
748
749#ifdef CONFIG_PWM_CAPTURE
750static inline int z_impl_pwm_enable_capture(const struct device *dev,
751 uint32_t channel)
752{
753 const struct pwm_driver_api *api =
754 (const struct pwm_driver_api *)dev->api;
755
756 if (api->enable_capture == NULL) {
757 return -ENOSYS;
758 }
759
760 return api->enable_capture(dev, channel);
761}
762#endif /* CONFIG_PWM_CAPTURE */
763
778__syscall int pwm_disable_capture(const struct device *dev, uint32_t channel);
779
780#ifdef CONFIG_PWM_CAPTURE
781static inline int z_impl_pwm_disable_capture(const struct device *dev,
782 uint32_t channel)
783{
784 const struct pwm_driver_api *api =
785 (const struct pwm_driver_api *)dev->api;
786
787 if (api->disable_capture == NULL) {
788 return -ENOSYS;
789 }
790
791 return api->disable_capture(dev, channel);
792}
793#endif /* CONFIG_PWM_CAPTURE */
794
822__syscall int pwm_capture_cycles(const struct device *dev, uint32_t channel,
823 pwm_flags_t flags, uint32_t *period,
824 uint32_t *pulse, k_timeout_t timeout);
825
854static inline int pwm_capture_usec(const struct device *dev, uint32_t channel,
855 pwm_flags_t flags, uint64_t *period,
856 uint64_t *pulse, k_timeout_t timeout)
857{
858 int err;
859 uint32_t pulse_cycles;
860 uint32_t period_cycles;
861
862 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
863 &pulse_cycles, timeout);
864 if (err < 0) {
865 return err;
866 }
867
868 err = pwm_cycles_to_usec(dev, channel, period_cycles, period);
869 if (err < 0) {
870 return err;
871 }
872
873 err = pwm_cycles_to_usec(dev, channel, pulse_cycles, pulse);
874 if (err < 0) {
875 return err;
876 }
877
878 return 0;
879}
880
909static inline int pwm_capture_nsec(const struct device *dev, uint32_t channel,
910 pwm_flags_t flags, uint64_t *period,
911 uint64_t *pulse, k_timeout_t timeout)
912{
913 int err;
914 uint32_t pulse_cycles;
915 uint32_t period_cycles;
916
917 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
918 &pulse_cycles, timeout);
919 if (err < 0) {
920 return err;
921 }
922
923 err = pwm_cycles_to_nsec(dev, channel, period_cycles, period);
924 if (err < 0) {
925 return err;
926 }
927
928 err = pwm_cycles_to_nsec(dev, channel, pulse_cycles, pulse);
929 if (err < 0) {
930 return err;
931 }
932
933 return 0;
934}
935
944static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
945{
946 return device_is_ready(spec->dev);
947}
948
949#ifdef __cplusplus
950}
951#endif
952
957#include <zephyr/syscalls/pwm.h>
958
959#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.
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:589
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:397
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:854
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:909
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:662
static bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
Validate that the PWM device is ready.
Definition pwm.h:944
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:610
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:712
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:543
uint16_t pwm_flags_t
Provides a type to hold PWM configuration flags.
Definition pwm.h:87
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:629
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: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:510
const void * api
Address of the API structure exposed by the device instance.
Definition device.h:516
Kernel timeout type.
Definition clock.h:65
Container for PWM information specified in devicetree.
Definition pwm.h:104
pwm_flags_t flags
Flags.
Definition pwm.h:112
uint32_t channel
Channel number.
Definition pwm.h:108
uint32_t period
Period in nanoseconds.
Definition pwm.h:110
const struct device * dev
PWM device instance.
Definition pwm.h:106
Macros to abstract toolchain specific capabilities.