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
13#ifndef ZEPHYR_INCLUDE_DRIVERS_PWM_H_
14#define ZEPHYR_INCLUDE_DRIVERS_PWM_H_
15
30#include <errno.h>
31#include <stdint.h>
32
33#include <zephyr/device.h>
34#include <zephyr/devicetree.h>
35#include <zephyr/sys_clock.h>
37#include <zephyr/toolchain.h>
38
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
52/* Bit 0 is used for PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED */
53#define PWM_CAPTURE_TYPE_SHIFT 1U
54#define PWM_CAPTURE_TYPE_MASK (3U << PWM_CAPTURE_TYPE_SHIFT)
55#define PWM_CAPTURE_MODE_SHIFT 3U
56#define PWM_CAPTURE_MODE_MASK (1U << PWM_CAPTURE_MODE_SHIFT)
60#define PWM_CAPTURE_TYPE_PERIOD (1U << PWM_CAPTURE_TYPE_SHIFT)
61
63#define PWM_CAPTURE_TYPE_PULSE (2U << PWM_CAPTURE_TYPE_SHIFT)
64
66#define PWM_CAPTURE_TYPE_BOTH (PWM_CAPTURE_TYPE_PERIOD | \
67 PWM_CAPTURE_TYPE_PULSE)
68
70#define PWM_CAPTURE_MODE_SINGLE (0U << PWM_CAPTURE_MODE_SHIFT)
71
73#define PWM_CAPTURE_MODE_CONTINUOUS (1U << PWM_CAPTURE_MODE_SHIFT)
74
87
113
158#define PWM_DT_SPEC_GET_BY_NAME(node_id, name) \
159 { \
160 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_NAME(node_id, name)), \
161 .channel = DT_PWMS_CHANNEL_BY_NAME(node_id, name), \
162 .period = DT_PWMS_PERIOD_BY_NAME(node_id, name), \
163 .flags = DT_PWMS_FLAGS_BY_NAME(node_id, name), \
164 }
165
178#define PWM_DT_SPEC_INST_GET_BY_NAME(inst, name) \
179 PWM_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
180
199#define PWM_DT_SPEC_GET_BY_NAME_OR(node_id, name, default_value) \
200 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
201 (PWM_DT_SPEC_GET_BY_NAME(node_id, name)), \
202 (default_value))
203
218#define PWM_DT_SPEC_INST_GET_BY_NAME_OR(inst, name, default_value) \
219 PWM_DT_SPEC_GET_BY_NAME_OR(DT_DRV_INST(inst), name, default_value)
220
263#define PWM_DT_SPEC_GET_BY_IDX(node_id, idx) \
264 { \
265 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_IDX(node_id, idx)), \
266 .channel = DT_PWMS_CHANNEL_BY_IDX(node_id, idx), \
267 .period = DT_PWMS_PERIOD_BY_IDX(node_id, idx), \
268 .flags = DT_PWMS_FLAGS_BY_IDX(node_id, idx), \
269 }
270
282#define PWM_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
283 PWM_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
284
302#define PWM_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \
303 COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms), \
304 (PWM_DT_SPEC_GET_BY_IDX(node_id, idx)), \
305 (default_value))
306
320#define PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \
321 PWM_DT_SPEC_GET_BY_IDX_OR(DT_DRV_INST(inst), idx, default_value)
322
333#define PWM_DT_SPEC_GET(node_id) PWM_DT_SPEC_GET_BY_IDX(node_id, 0)
334
345#define PWM_DT_SPEC_INST_GET(inst) PWM_DT_SPEC_GET(DT_DRV_INST(inst))
346
359#define PWM_DT_SPEC_GET_OR(node_id, default_value) \
360 PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)
361
374#define PWM_DT_SPEC_INST_GET_OR(inst, default_value) \
375 PWM_DT_SPEC_GET_OR(DT_DRV_INST(inst), default_value)
376
396typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
397 uint32_t channel,
398 uint32_t period_cycles,
399 uint32_t pulse_cycles,
400 int status, void *user_data);
401
407typedef int (*pwm_set_cycles_t)(const struct device *dev, uint32_t channel,
408 uint32_t period_cycles, uint32_t pulse_cycles,
410
415typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
416 uint32_t channel, uint64_t *cycles);
417
418#ifdef CONFIG_PWM_CAPTURE
423typedef int (*pwm_configure_capture_t)(const struct device *dev,
424 uint32_t channel, pwm_flags_t flags,
426 void *user_data);
427
432typedef int (*pwm_enable_capture_t)(const struct device *dev, uint32_t channel);
433
438typedef int (*pwm_disable_capture_t)(const struct device *dev,
439 uint32_t channel);
440#endif /* CONFIG_PWM_CAPTURE */
441
443__subsystem struct pwm_driver_api {
444 pwm_set_cycles_t set_cycles;
445 pwm_get_cycles_per_sec_t get_cycles_per_sec;
446#ifdef CONFIG_PWM_CAPTURE
447 pwm_configure_capture_t configure_capture;
448 pwm_enable_capture_t enable_capture;
449 pwm_disable_capture_t disable_capture;
450#endif /* CONFIG_PWM_CAPTURE */
451};
484__syscall int pwm_set_cycles(const struct device *dev, uint32_t channel,
485 uint32_t period, uint32_t pulse,
487
488static inline int z_impl_pwm_set_cycles(const struct device *dev,
489 uint32_t channel, uint32_t period,
491{
492 const struct pwm_driver_api *api =
493 (const struct pwm_driver_api *)dev->api;
494
495 if (pulse > period) {
496 return -EINVAL;
497 }
498
499 return api->set_cycles(dev, channel, period, pulse, flags);
500}
501
513__syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
514 uint64_t *cycles);
515
516static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
517 uint32_t channel,
518 uint64_t *cycles)
519{
520 const struct pwm_driver_api *api =
521 (const struct pwm_driver_api *)dev->api;
522
523 return api->get_cycles_per_sec(dev, channel, cycles);
524}
525
542static inline int pwm_set(const struct device *dev, uint32_t channel,
543 uint32_t period, uint32_t pulse, pwm_flags_t flags)
544{
545 int err;
546 uint64_t pulse_cycles;
547 uint64_t period_cycles;
548 uint64_t cycles_per_sec;
549
550 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
551 if (err < 0) {
552 return err;
553 }
554
555 period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
556 if (period_cycles > UINT32_MAX) {
557 return -ENOTSUP;
558 }
559
560 pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
561 if (pulse_cycles > UINT32_MAX) {
562 return -ENOTSUP;
563 }
564
565 return pwm_set_cycles(dev, channel, (uint32_t)period_cycles,
566 (uint32_t)pulse_cycles, flags);
567}
568
588static inline int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period,
589 uint32_t pulse)
590{
591 return pwm_set(spec->dev, spec->channel, period, pulse, spec->flags);
592}
593
609static inline int pwm_set_pulse_dt(const struct pwm_dt_spec *spec,
610 uint32_t pulse)
611{
612 return pwm_set(spec->dev, spec->channel, spec->period, pulse,
613 spec->flags);
614}
615
628static inline int pwm_cycles_to_usec(const struct device *dev, uint32_t channel,
629 uint32_t cycles, uint64_t *usec)
630{
631 int err;
632 uint64_t temp;
633 uint64_t cycles_per_sec;
634
635 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
636 if (err < 0) {
637 return err;
638 }
639
640 if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
641 return -ERANGE;
642 }
643
644 *usec = temp / cycles_per_sec;
645
646 return 0;
647}
648
661static inline int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel,
662 uint32_t cycles, uint64_t *nsec)
663{
664 int err;
665 uint64_t temp;
666 uint64_t cycles_per_sec;
667
668 err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
669 if (err < 0) {
670 return err;
671 }
672
673 if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
674 return -ERANGE;
675 }
676
677 *nsec = temp / cycles_per_sec;
678
679 return 0;
680}
681
682#if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
711static inline int pwm_configure_capture(const struct device *dev,
712 uint32_t channel, pwm_flags_t flags,
714 void *user_data)
715{
716 const struct pwm_driver_api *api =
717 (const struct pwm_driver_api *)dev->api;
718
719 if (api->configure_capture == NULL) {
720 return -ENOSYS;
721 }
722
723 return api->configure_capture(dev, channel, flags, cb,
724 user_data);
725}
726#endif /* CONFIG_PWM_CAPTURE */
727
746__syscall int pwm_enable_capture(const struct device *dev, uint32_t channel);
747
748#ifdef CONFIG_PWM_CAPTURE
749static inline int z_impl_pwm_enable_capture(const struct device *dev,
750 uint32_t channel)
751{
752 const struct pwm_driver_api *api =
753 (const struct pwm_driver_api *)dev->api;
754
755 if (api->enable_capture == NULL) {
756 return -ENOSYS;
757 }
758
759 return api->enable_capture(dev, channel);
760}
761#endif /* CONFIG_PWM_CAPTURE */
762
777__syscall int pwm_disable_capture(const struct device *dev, uint32_t channel);
778
779#ifdef CONFIG_PWM_CAPTURE
780static inline int z_impl_pwm_disable_capture(const struct device *dev,
781 uint32_t channel)
782{
783 const struct pwm_driver_api *api =
784 (const struct pwm_driver_api *)dev->api;
785
786 if (api->disable_capture == NULL) {
787 return -ENOSYS;
788 }
789
790 return api->disable_capture(dev, channel);
791}
792#endif /* CONFIG_PWM_CAPTURE */
793
821__syscall int pwm_capture_cycles(const struct device *dev, uint32_t channel,
822 pwm_flags_t flags, uint32_t *period,
823 uint32_t *pulse, k_timeout_t timeout);
824
853static inline int pwm_capture_usec(const struct device *dev, uint32_t channel,
854 pwm_flags_t flags, uint64_t *period,
855 uint64_t *pulse, k_timeout_t timeout)
856{
857 int err;
858 uint32_t pulse_cycles;
859 uint32_t period_cycles;
860
861 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
862 &pulse_cycles, timeout);
863 if (err < 0) {
864 return err;
865 }
866
867 err = pwm_cycles_to_usec(dev, channel, period_cycles, period);
868 if (err < 0) {
869 return err;
870 }
871
872 err = pwm_cycles_to_usec(dev, channel, pulse_cycles, pulse);
873 if (err < 0) {
874 return err;
875 }
876
877 return 0;
878}
879
908static inline int pwm_capture_nsec(const struct device *dev, uint32_t channel,
909 pwm_flags_t flags, uint64_t *period,
910 uint64_t *pulse, k_timeout_t timeout)
911{
912 int err;
913 uint32_t pulse_cycles;
914 uint32_t period_cycles;
915
916 err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
917 &pulse_cycles, timeout);
918 if (err < 0) {
919 return err;
920 }
921
922 err = pwm_cycles_to_nsec(dev, channel, period_cycles, period);
923 if (err < 0) {
924 return err;
925 }
926
927 err = pwm_cycles_to_nsec(dev, channel, pulse_cycles, pulse);
928 if (err < 0) {
929 return err;
930 }
931
932 return 0;
933}
934
943static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
944{
945 return device_is_ready(spec->dev);
946}
947
948#ifdef __cplusplus
949}
950#endif
951
956#include <zephyr/syscalls/pwm.h>
957
958#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:588
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:396
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:853
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:908
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:661
static bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
Validate that the PWM device is ready.
Definition pwm.h:943
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:609
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:711
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:542
uint16_t pwm_flags_t
Provides a type to hold PWM configuration flags.
Definition pwm.h:86
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:628
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:103
pwm_flags_t flags
Flags.
Definition pwm.h:111
uint32_t channel
Channel number.
Definition pwm.h:107
uint32_t period
Period in nanoseconds.
Definition pwm.h:109
const struct device * dev
PWM device instance.
Definition pwm.h:105
Macros to abstract toolchain specific capabilities.