drivers: pwm: add support for inverted PWM signals
Add support for requesting an inverted PWM pulse (active-low) when setting up the period and pulse width of a PWM pin. This is useful when driving external, active-low circuitry (e.g. an LED) with a PWM signal. All in-tree PWM drivers is updated to match the new API signature, but no driver support for inverted PWM signals is added yet. All in-tree PWM consumers are updated to pass a flags value of 0 (0 meaning default, which is normal PWM polarity). Fixes #21384. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
def1f0e2d5
commit
db611e6781
24 changed files with 152 additions and 38 deletions
|
@ -135,11 +135,13 @@ static int __set_one_port(struct device *dev, u32_t pwm,
|
||||||
* @param pwm Which PWM pin to set
|
* @param pwm Which PWM pin to set
|
||||||
* @param period_cycles Period in clock cycles of the pwm.
|
* @param period_cycles Period in clock cycles of the pwm.
|
||||||
* @param pulse_cycles PWM width in clock cycles
|
* @param pulse_cycles PWM width in clock cycles
|
||||||
|
* @param flags Flags for pin configuration (polarity).
|
||||||
*
|
*
|
||||||
* @return 0
|
* @return 0
|
||||||
*/
|
*/
|
||||||
static int pwm_dw_pin_set_cycles(struct device *dev,
|
static int pwm_dw_pin_set_cycles(struct device *dev,
|
||||||
u32_t pwm, u32_t period_cycles, u32_t pulse_cycles)
|
u32_t pwm, u32_t period_cycles,
|
||||||
|
u32_t pulse_cycles, pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
const struct pwm_dw_config * const cfg =
|
const struct pwm_dw_config * const cfg =
|
||||||
(struct pwm_dw_config *)dev->config->config_info;
|
(struct pwm_dw_config *)dev->config->config_info;
|
||||||
|
@ -151,6 +153,11 @@ static int pwm_dw_pin_set_cycles(struct device *dev,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
if (period_cycles == 0U || pulse_cycles > period_cycles) {
|
if (period_cycles == 0U || pulse_cycles > period_cycles) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,12 @@
|
||||||
#include <drivers/pwm.h>
|
#include <drivers/pwm.h>
|
||||||
|
|
||||||
static inline int z_vrfy_pwm_pin_set_cycles(struct device *dev, u32_t pwm,
|
static inline int z_vrfy_pwm_pin_set_cycles(struct device *dev, u32_t pwm,
|
||||||
u32_t period, u32_t pulse)
|
u32_t period, u32_t pulse,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, pin_set));
|
Z_OOPS(Z_SYSCALL_DRIVER_PWM(dev, pin_set));
|
||||||
return z_impl_pwm_pin_set_cycles((struct device *)dev, pwm, period,
|
return z_impl_pwm_pin_set_cycles((struct device *)dev, pwm, period,
|
||||||
pulse);
|
pulse, flags);
|
||||||
}
|
}
|
||||||
#include <syscalls/pwm_pin_set_cycles_mrsh.c>
|
#include <syscalls/pwm_pin_set_cycles_mrsh.c>
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,8 @@ static int imx_pwm_get_cycles_per_sec(struct device *dev, u32_t pwm,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx_pwm_pin_set(struct device *dev, u32_t pwm,
|
static int imx_pwm_pin_set(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
PWM_Type *base = DEV_BASE(dev);
|
PWM_Type *base = DEV_BASE(dev);
|
||||||
const struct imx_pwm_config *config = DEV_CFG(dev);
|
const struct imx_pwm_config *config = DEV_CFG(dev);
|
||||||
|
@ -69,6 +70,11 @@ static int imx_pwm_pin_set(struct device *dev, u32_t pwm,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("enabled=%d, pulse_cycles=%d, period_cycles=%d,"
|
LOG_DBG("enabled=%d, pulse_cycles=%d, period_cycles=%d,"
|
||||||
" duty_cycle=%d\n", enabled, pulse_cycles, period_cycles,
|
" duty_cycle=%d\n", enabled, pulse_cycles, period_cycles,
|
||||||
(pulse_cycles * 100U / period_cycles));
|
(pulse_cycles * 100U / period_cycles));
|
||||||
|
|
|
@ -311,7 +311,7 @@ static int pwm_led_esp32_timer_set(int speed_mode, int timer,
|
||||||
/* period_cycles is not used, set frequency on menuconfig instead. */
|
/* period_cycles is not used, set frequency on menuconfig instead. */
|
||||||
static int pwm_led_esp32_pin_set_cycles(struct device *dev,
|
static int pwm_led_esp32_pin_set_cycles(struct device *dev,
|
||||||
u32_t pwm, u32_t period_cycles,
|
u32_t pwm, u32_t period_cycles,
|
||||||
u32_t pulse_cycles)
|
u32_t pulse_cycles, pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
int speed_mode;
|
int speed_mode;
|
||||||
int channel;
|
int channel;
|
||||||
|
@ -322,6 +322,11 @@ static int pwm_led_esp32_pin_set_cycles(struct device *dev,
|
||||||
|
|
||||||
ARG_UNUSED(period_cycles);
|
ARG_UNUSED(period_cycles);
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
channel = pwm_led_esp32_get_gpio_config(pwm, config->ch_cfg);
|
channel = pwm_led_esp32_get_gpio_config(pwm, config->ch_cfg);
|
||||||
if (channel < 0) {
|
if (channel < 0) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -305,7 +305,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pwm_xec_pin_set(struct device *dev, u32_t pwm,
|
static int pwm_xec_pin_set(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
PWM_Type *pwm_regs = PWM_XEC_REG_BASE(dev);
|
PWM_Type *pwm_regs = PWM_XEC_REG_BASE(dev);
|
||||||
u32_t target_freq;
|
u32_t target_freq;
|
||||||
|
@ -319,6 +320,11 @@ static int pwm_xec_pin_set(struct device *dev, u32_t pwm,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
on = pulse_cycles;
|
on = pulse_cycles;
|
||||||
off = period_cycles - pulse_cycles;
|
off = period_cycles - pulse_cycles;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,8 @@ struct pwm_mcux_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mcux_pwm_pin_set(struct device *dev, u32_t pwm,
|
static int mcux_pwm_pin_set(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
const struct pwm_mcux_config *config = dev->config->config_info;
|
const struct pwm_mcux_config *config = dev->config->config_info;
|
||||||
struct pwm_mcux_data *data = dev->driver_data;
|
struct pwm_mcux_data *data = dev->driver_data;
|
||||||
|
@ -41,6 +42,11 @@ static int mcux_pwm_pin_set(struct device *dev, u32_t pwm,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
if ((period_cycles == 0) || (pulse_cycles > period_cycles)) {
|
if ((period_cycles == 0) || (pulse_cycles > period_cycles)) {
|
||||||
LOG_ERR("Invalid combination: period_cycles=%u, "
|
LOG_ERR("Invalid combination: period_cycles=%u, "
|
||||||
"pulse_cycles=%u", period_cycles, pulse_cycles);
|
"pulse_cycles=%u", period_cycles, pulse_cycles);
|
||||||
|
|
|
@ -34,7 +34,8 @@ struct mcux_ftm_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mcux_ftm_pin_set(struct device *dev, u32_t pwm,
|
static int mcux_ftm_pin_set(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
const struct mcux_ftm_config *config = dev->config->config_info;
|
const struct mcux_ftm_config *config = dev->config->config_info;
|
||||||
struct mcux_ftm_data *data = dev->driver_data;
|
struct mcux_ftm_data *data = dev->driver_data;
|
||||||
|
@ -51,6 +52,11 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
duty_cycle = pulse_cycles * 100U / period_cycles;
|
duty_cycle = pulse_cycles * 100U / period_cycles;
|
||||||
data->channel[pwm].dutyCyclePercent = duty_cycle;
|
data->channel[pwm].dutyCyclePercent = duty_cycle;
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,8 @@ static u8_t pwm_channel_map(struct pwm_data *data, u8_t map_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pwm_nrf5_sw_pin_set(struct device *dev, u32_t pwm,
|
static int pwm_nrf5_sw_pin_set(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
struct pwm_config *config;
|
struct pwm_config *config;
|
||||||
NRF_TIMER_Type *timer;
|
NRF_TIMER_Type *timer;
|
||||||
|
@ -101,6 +102,11 @@ static int pwm_nrf5_sw_pin_set(struct device *dev, u32_t pwm,
|
||||||
timer = config->timer;
|
timer = config->timer;
|
||||||
data = dev->driver_data;
|
data = dev->driver_data;
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
/* check if requested period is allowed while other channels are
|
/* check if requested period is allowed while other channels are
|
||||||
* active.
|
* active.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -123,7 +123,8 @@ static bool any_other_channel_is_active(u8_t channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pwm_nrfx_pin_set(struct device *dev, u32_t pwm,
|
static int pwm_nrfx_pin_set(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
/* We assume here that period_cycles will always be 16MHz
|
/* We assume here that period_cycles will always be 16MHz
|
||||||
* peripheral clock. Since pwm_nrfx_get_cycles_per_sec() function might
|
* peripheral clock. Since pwm_nrfx_get_cycles_per_sec() function might
|
||||||
|
@ -134,6 +135,11 @@ static int pwm_nrfx_pin_set(struct device *dev, u32_t pwm,
|
||||||
struct pwm_nrfx_data *data = dev->driver_data;
|
struct pwm_nrfx_data *data = dev->driver_data;
|
||||||
u8_t channel;
|
u8_t channel;
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if PWM pin is one of the predefiend DTS config pins.
|
/* Check if PWM pin is one of the predefiend DTS config pins.
|
||||||
* Return its array index (channel number),
|
* Return its array index (channel number),
|
||||||
* or NRF_PWM_CHANNEL_COUNT if not initialized through DTS.
|
* or NRF_PWM_CHANNEL_COUNT if not initialized through DTS.
|
||||||
|
|
|
@ -61,7 +61,8 @@ static inline int has_i2c_master(struct device *dev)
|
||||||
* value to pulse_count
|
* value to pulse_count
|
||||||
*/
|
*/
|
||||||
static int pwm_pca9685_pin_set_cycles(struct device *dev, u32_t pwm,
|
static int pwm_pca9685_pin_set_cycles(struct device *dev, u32_t pwm,
|
||||||
u32_t period_count, u32_t pulse_count)
|
u32_t period_count, u32_t pulse_count,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
const struct pwm_pca9685_config * const config =
|
const struct pwm_pca9685_config * const config =
|
||||||
dev->config->config_info;
|
dev->config->config_info;
|
||||||
|
@ -76,6 +77,11 @@ static int pwm_pca9685_pin_set_cycles(struct device *dev, u32_t pwm,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
if (pwm > MAX_PWM_OUT) {
|
if (pwm > MAX_PWM_OUT) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ static int sam_pwm_get_cycles_per_sec(struct device *dev, u32_t pwm,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sam_pwm_pin_set(struct device *dev, u32_t ch,
|
static int sam_pwm_pin_set(struct device *dev, u32_t ch,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
Pwm *const pwm = DEV_CFG(dev)->regs;
|
Pwm *const pwm = DEV_CFG(dev)->regs;
|
||||||
|
|
||||||
|
@ -44,6 +45,11 @@ static int sam_pwm_pin_set(struct device *dev, u32_t ch,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
if (period_cycles == 0U || pulse_cycles > period_cycles) {
|
if (period_cycles == 0U || pulse_cycles > period_cycles) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ static int cmd_cycles(const struct shell *shell, size_t argc, char **argv)
|
||||||
period = strtoul(argv[args_indx.period], NULL, 0);
|
period = strtoul(argv[args_indx.period], NULL, 0);
|
||||||
pulse = strtoul(argv[args_indx.pulse], NULL, 0);
|
pulse = strtoul(argv[args_indx.pulse], NULL, 0);
|
||||||
|
|
||||||
err = pwm_pin_set_cycles(dev, pwm, period, pulse);
|
err = pwm_pin_set_cycles(dev, pwm, period, pulse, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
shell_error(shell, "failed to setup PWM (err %d)",
|
shell_error(shell, "failed to setup PWM (err %d)",
|
||||||
err);
|
err);
|
||||||
|
@ -73,7 +73,7 @@ static int cmd_usec(const struct shell *shell, size_t argc, char **argv)
|
||||||
period = strtoul(argv[args_indx.period], NULL, 0);
|
period = strtoul(argv[args_indx.period], NULL, 0);
|
||||||
pulse = strtoul(argv[args_indx.pulse], NULL, 0);
|
pulse = strtoul(argv[args_indx.pulse], NULL, 0);
|
||||||
|
|
||||||
err = pwm_pin_set_usec(dev, pwm, period, pulse);
|
err = pwm_pin_set_usec(dev, pwm, period, pulse, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
shell_error(shell, "failed to setup PWM (err %d)", err);
|
shell_error(shell, "failed to setup PWM (err %d)", err);
|
||||||
return err;
|
return err;
|
||||||
|
@ -100,7 +100,7 @@ static int cmd_nsec(const struct shell *shell, size_t argc, char **argv)
|
||||||
period = strtoul(argv[args_indx.period], NULL, 0);
|
period = strtoul(argv[args_indx.period], NULL, 0);
|
||||||
pulse = strtoul(argv[args_indx.pulse], NULL, 0);
|
pulse = strtoul(argv[args_indx.pulse], NULL, 0);
|
||||||
|
|
||||||
err = pwm_pin_set_nsec(dev, pwm, period, pulse);
|
err = pwm_pin_set_nsec(dev, pwm, period, pulse, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
shell_error(shell, "failed to setup PWM (err %d)", err);
|
shell_error(shell, "failed to setup PWM (err %d)", err);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -96,7 +96,8 @@ static int pwm_sifive_init(struct device *dev)
|
||||||
static int pwm_sifive_pin_set(struct device *dev,
|
static int pwm_sifive_pin_set(struct device *dev,
|
||||||
u32_t pwm,
|
u32_t pwm,
|
||||||
u32_t period_cycles,
|
u32_t period_cycles,
|
||||||
u32_t pulse_cycles)
|
u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
const struct pwm_sifive_cfg *config = NULL;
|
const struct pwm_sifive_cfg *config = NULL;
|
||||||
u32_t count_max = 0U;
|
u32_t count_max = 0U;
|
||||||
|
@ -112,6 +113,11 @@ static int pwm_sifive_pin_set(struct device *dev,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
config = dev->config->config_info;
|
config = dev->config->config_info;
|
||||||
if (config == NULL) {
|
if (config == NULL) {
|
||||||
LOG_ERR("The device configuration is NULL\n");
|
LOG_ERR("The device configuration is NULL\n");
|
||||||
|
|
|
@ -71,7 +71,8 @@ static u32_t __get_tim_clk(u32_t bus_clk,
|
||||||
* return 0, or negative errno code
|
* return 0, or negative errno code
|
||||||
*/
|
*/
|
||||||
static int pwm_stm32_pin_set(struct device *dev, u32_t pwm,
|
static int pwm_stm32_pin_set(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles)
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
struct pwm_stm32_data *data = DEV_DATA(dev);
|
struct pwm_stm32_data *data = DEV_DATA(dev);
|
||||||
TIM_HandleTypeDef *TimerHandle = &data->hpwm;
|
TIM_HandleTypeDef *TimerHandle = &data->hpwm;
|
||||||
|
@ -83,6 +84,11 @@ static int pwm_stm32_pin_set(struct device *dev, u32_t pwm,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
/* PWM polarity not supported (yet?) */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
/* configure channel */
|
/* configure channel */
|
||||||
channel = (pwm - 1)*CHANNEL_LENGTH;
|
channel = (pwm - 1)*CHANNEL_LENGTH;
|
||||||
|
|
||||||
|
|
|
@ -23,18 +23,25 @@
|
||||||
#include <zephyr/types.h>
|
#include <zephyr/types.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <device.h>
|
#include <device.h>
|
||||||
|
#include <dt-bindings/pwm/pwm.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Provides a type to hold PWM configuration flags.
|
||||||
|
*/
|
||||||
|
typedef u8_t pwm_flags_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef pwm_pin_set_t
|
* @typedef pwm_pin_set_t
|
||||||
* @brief Callback API upon setting the pin
|
* @brief Callback API upon setting the pin
|
||||||
* See @a pwm_pin_set_cycles() for argument description
|
* See @a pwm_pin_set_cycles() for argument description
|
||||||
*/
|
*/
|
||||||
typedef int (*pwm_pin_set_t)(struct device *dev, u32_t pwm,
|
typedef int (*pwm_pin_set_t)(struct device *dev, u32_t pwm,
|
||||||
u32_t period_cycles, u32_t pulse_cycles);
|
u32_t period_cycles, u32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef pwm_get_cycles_per_sec_t
|
* @typedef pwm_get_cycles_per_sec_t
|
||||||
|
@ -57,20 +64,22 @@ struct pwm_driver_api {
|
||||||
* @param pwm PWM pin.
|
* @param pwm PWM pin.
|
||||||
* @param period Period (in clock cycle) set to the PWM. HW specific.
|
* @param period Period (in clock cycle) set to the PWM. HW specific.
|
||||||
* @param pulse Pulse width (in clock cycle) set to the PWM. HW specific.
|
* @param pulse Pulse width (in clock cycle) set to the PWM. HW specific.
|
||||||
|
* @param flags Flags for pin configuration (polarity).
|
||||||
*
|
*
|
||||||
* @retval 0 If successful.
|
* @retval 0 If successful.
|
||||||
* @retval Negative errno code if failure.
|
* @retval Negative errno code if failure.
|
||||||
*/
|
*/
|
||||||
__syscall int pwm_pin_set_cycles(struct device *dev, u32_t pwm,
|
__syscall int pwm_pin_set_cycles(struct device *dev, u32_t pwm,
|
||||||
u32_t period, u32_t pulse);
|
u32_t period, u32_t pulse, pwm_flags_t flags);
|
||||||
|
|
||||||
static inline int z_impl_pwm_pin_set_cycles(struct device *dev, u32_t pwm,
|
static inline int z_impl_pwm_pin_set_cycles(struct device *dev, u32_t pwm,
|
||||||
u32_t period, u32_t pulse)
|
u32_t period, u32_t pulse,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
struct pwm_driver_api *api;
|
struct pwm_driver_api *api;
|
||||||
|
|
||||||
api = (struct pwm_driver_api *)dev->driver_api;
|
api = (struct pwm_driver_api *)dev->driver_api;
|
||||||
return api->pin_set(dev, pwm, period, pulse);
|
return api->pin_set(dev, pwm, period, pulse, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,12 +113,14 @@ static inline int z_impl_pwm_get_cycles_per_sec(struct device *dev, u32_t pwm,
|
||||||
* @param pwm PWM pin.
|
* @param pwm PWM pin.
|
||||||
* @param period Period (in microseconds) set to the PWM.
|
* @param period Period (in microseconds) set to the PWM.
|
||||||
* @param pulse Pulse width (in microseconds) set to the PWM.
|
* @param pulse Pulse width (in microseconds) set to the PWM.
|
||||||
|
* @param flags Flags for pin configuration (polarity).
|
||||||
*
|
*
|
||||||
* @retval 0 If successful.
|
* @retval 0 If successful.
|
||||||
* @retval Negative errno code if failure.
|
* @retval Negative errno code if failure.
|
||||||
*/
|
*/
|
||||||
static inline int pwm_pin_set_usec(struct device *dev, u32_t pwm,
|
static inline int pwm_pin_set_usec(struct device *dev, u32_t pwm,
|
||||||
u32_t period, u32_t pulse)
|
u32_t period, u32_t pulse,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
u64_t period_cycles, pulse_cycles, cycles_per_sec;
|
u64_t period_cycles, pulse_cycles, cycles_per_sec;
|
||||||
|
|
||||||
|
@ -128,7 +139,7 @@ static inline int pwm_pin_set_usec(struct device *dev, u32_t pwm,
|
||||||
}
|
}
|
||||||
|
|
||||||
return pwm_pin_set_cycles(dev, pwm, (u32_t)period_cycles,
|
return pwm_pin_set_cycles(dev, pwm, (u32_t)period_cycles,
|
||||||
(u32_t)pulse_cycles);
|
(u32_t)pulse_cycles, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,12 +149,14 @@ static inline int pwm_pin_set_usec(struct device *dev, u32_t pwm,
|
||||||
* @param pwm PWM pin.
|
* @param pwm PWM pin.
|
||||||
* @param period Period (in nanoseconds) set to the PWM.
|
* @param period Period (in nanoseconds) set to the PWM.
|
||||||
* @param pulse Pulse width (in nanoseconds) set to the PWM.
|
* @param pulse Pulse width (in nanoseconds) set to the PWM.
|
||||||
|
* @param flags Flags for pin configuration (polarity).
|
||||||
*
|
*
|
||||||
* @retval 0 If successful.
|
* @retval 0 If successful.
|
||||||
* @retval Negative errno code if failure.
|
* @retval Negative errno code if failure.
|
||||||
*/
|
*/
|
||||||
static inline int pwm_pin_set_nsec(struct device *dev, u32_t pwm,
|
static inline int pwm_pin_set_nsec(struct device *dev, u32_t pwm,
|
||||||
u32_t period, u32_t pulse)
|
u32_t period, u32_t pulse,
|
||||||
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
u64_t period_cycles, pulse_cycles, cycles_per_sec;
|
u64_t period_cycles, pulse_cycles, cycles_per_sec;
|
||||||
|
|
||||||
|
@ -162,7 +175,7 @@ static inline int pwm_pin_set_nsec(struct device *dev, u32_t pwm,
|
||||||
}
|
}
|
||||||
|
|
||||||
return pwm_pin_set_cycles(dev, pwm, (u32_t)period_cycles,
|
return pwm_pin_set_cycles(dev, pwm, (u32_t)period_cycles,
|
||||||
(u32_t)pulse_cycles);
|
(u32_t)pulse_cycles, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
27
include/dt-bindings/pwm/pwm.h
Normal file
27
include/dt-bindings/pwm/pwm.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Vestas Wind Systems A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PWM_PWM_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DT_BINDINGS_PWM_PWM_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name PWM polarity flags
|
||||||
|
* The `PWM_POLARITY_*` flags are used with pwm_pin_set_cycles(),
|
||||||
|
* pwm_pin_set_usec(), or pwm_pin_set_nsec() to specify the polarity
|
||||||
|
* of a PWM pin.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** PWM pin normal polarity (active-high pulse). */
|
||||||
|
#define PWM_POLARITY_NORMAL (0 << 0)
|
||||||
|
|
||||||
|
/** PWM pin inverted polarity (active-low pulse). */
|
||||||
|
#define PWM_POLARITY_INVERTED (1 << 0)
|
||||||
|
|
||||||
|
/** @cond INTERNAL_HIDDEN */
|
||||||
|
#define PWM_POLARITY_MASK 0x1
|
||||||
|
/** @endcond */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PWM_PWM_H_ */
|
|
@ -51,7 +51,7 @@ void main(void)
|
||||||
*/
|
*/
|
||||||
max_period = MAX_PERIOD;
|
max_period = MAX_PERIOD;
|
||||||
while (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL,
|
while (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL,
|
||||||
max_period, max_period / 2U)) {
|
max_period, max_period / 2U, 0)) {
|
||||||
max_period /= 2U;
|
max_period /= 2U;
|
||||||
if (max_period < (4U * MIN_PERIOD)) {
|
if (max_period < (4U * MIN_PERIOD)) {
|
||||||
printk("This sample needs to set a period that is "
|
printk("This sample needs to set a period that is "
|
||||||
|
@ -63,7 +63,7 @@ void main(void)
|
||||||
period = max_period;
|
period = max_period;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL,
|
if (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL,
|
||||||
period, period / 2U)) {
|
period, period / 2U, 0)) {
|
||||||
printk("pwm pin set fails\n");
|
printk("pwm pin set fails\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ void main(void)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL,
|
if (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL,
|
||||||
PERIOD, pulse_width)) {
|
PERIOD, pulse_width, 0)) {
|
||||||
printk("pwm pin set fails\n");
|
printk("pwm pin set fails\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
static int write_pin(struct device *pwm_dev, u32_t pwm_pin,
|
static int write_pin(struct device *pwm_dev, u32_t pwm_pin,
|
||||||
u32_t pulse_width)
|
u32_t pulse_width)
|
||||||
{
|
{
|
||||||
return pwm_pin_set_usec(pwm_dev, pwm_pin, PERIOD, pulse_width);
|
return pwm_pin_set_usec(pwm_dev, pwm_pin, PERIOD, pulse_width, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
|
|
|
@ -45,7 +45,7 @@ void main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (pwm_pin_set_usec(pwm_dev, 0, PERIOD, pulse_width)) {
|
if (pwm_pin_set_usec(pwm_dev, 0, PERIOD, pulse_width, 0)) {
|
||||||
printk("pwm pin set fails\n");
|
printk("pwm pin set fails\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,13 +126,14 @@ void board_play_tune(const char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (period) {
|
if (period) {
|
||||||
pwm_pin_set_usec(pwm, BUZZER_PIN, period, period / 2U);
|
pwm_pin_set_usec(pwm, BUZZER_PIN, period, period / 2U,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
k_sleep(duration);
|
k_sleep(duration);
|
||||||
|
|
||||||
/* Disable the PWM */
|
/* Disable the PWM */
|
||||||
pwm_pin_set_usec(pwm, BUZZER_PIN, 0, 0);
|
pwm_pin_set_usec(pwm, BUZZER_PIN, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ static enum sound_state {
|
||||||
|
|
||||||
static inline void beep(int period)
|
static inline void beep(int period)
|
||||||
{
|
{
|
||||||
pwm_pin_set_usec(pwm, SOUND_PIN, period, period / 2);
|
pwm_pin_set_usec(pwm, SOUND_PIN, period, period / 2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sound_set(enum sound_state state)
|
static void sound_set(enum sound_state state)
|
||||||
|
|
|
@ -34,11 +34,11 @@ static void beep(struct k_work *work)
|
||||||
/* The "period / 2" pulse duration gives 50% duty cycle, which
|
/* The "period / 2" pulse duration gives 50% duty cycle, which
|
||||||
* should result in the maximum sound volume.
|
* should result in the maximum sound volume.
|
||||||
*/
|
*/
|
||||||
pwm_pin_set_usec(pwm, BUZZER_PIN, period, period / 2U);
|
pwm_pin_set_usec(pwm, BUZZER_PIN, period, period / 2U, 0);
|
||||||
k_sleep(BEEP_DURATION);
|
k_sleep(BEEP_DURATION);
|
||||||
|
|
||||||
/* Disable the PWM */
|
/* Disable the PWM */
|
||||||
pwm_pin_set_usec(pwm, BUZZER_PIN, 0, 0);
|
pwm_pin_set_usec(pwm, BUZZER_PIN, 0, 0, 0);
|
||||||
|
|
||||||
/* Ensure there's a clear silent period between two tones */
|
/* Ensure there's a clear silent period between two tones */
|
||||||
k_sleep(K_MSEC(50));
|
k_sleep(K_MSEC(50));
|
||||||
|
|
|
@ -86,19 +86,19 @@ static int test_task(u32_t port, u32_t period, u32_t pulse, u8_t unit)
|
||||||
|
|
||||||
if (unit == UNIT_CYCLES) {
|
if (unit == UNIT_CYCLES) {
|
||||||
/* Verify pwm_pin_set_cycles() */
|
/* Verify pwm_pin_set_cycles() */
|
||||||
if (pwm_pin_set_cycles(pwm_dev, port, period, pulse)) {
|
if (pwm_pin_set_cycles(pwm_dev, port, period, pulse, 0)) {
|
||||||
TC_PRINT("Fail to set the period and pulse width\n");
|
TC_PRINT("Fail to set the period and pulse width\n");
|
||||||
return TC_FAIL;
|
return TC_FAIL;
|
||||||
}
|
}
|
||||||
} else if (unit == UNIT_USECS) {
|
} else if (unit == UNIT_USECS) {
|
||||||
/* Verify pwm_pin_set_usec() */
|
/* Verify pwm_pin_set_usec() */
|
||||||
if (pwm_pin_set_usec(pwm_dev, port, period, pulse)) {
|
if (pwm_pin_set_usec(pwm_dev, port, period, pulse, 0)) {
|
||||||
TC_PRINT("Fail to set the period and pulse width\n");
|
TC_PRINT("Fail to set the period and pulse width\n");
|
||||||
return TC_FAIL;
|
return TC_FAIL;
|
||||||
}
|
}
|
||||||
} else { /* unit == UNIT_NSECS */
|
} else { /* unit == UNIT_NSECS */
|
||||||
/* Verify pwm_pin_set_nsec() */
|
/* Verify pwm_pin_set_nsec() */
|
||||||
if (pwm_pin_set_nsec(pwm_dev, port, period, pulse)) {
|
if (pwm_pin_set_nsec(pwm_dev, port, period, pulse, 0)) {
|
||||||
TC_PRINT("Fail to set the period and pulse width\n");
|
TC_PRINT("Fail to set the period and pulse width\n");
|
||||||
return TC_FAIL;
|
return TC_FAIL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue