drivers: pwm: pwm_mcux: make thread safe with mutex.
Fixes a bug where more than one thread trying to access different PWM devices can cause erroneous behavior. Co-authored-by: James Goppert <james.goppert@gmail.com> Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
This commit is contained in:
parent
c9649bdef8
commit
daaf06db94
1 changed files with 35 additions and 19 deletions
|
@ -12,6 +12,7 @@
|
|||
#include <soc.h>
|
||||
#include <fsl_pwm.h>
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
|
@ -35,9 +36,10 @@ struct pwm_mcux_config {
|
|||
struct pwm_mcux_data {
|
||||
uint32_t period_cycles[CHANNEL_COUNT];
|
||||
pwm_signal_param_t channel[CHANNEL_COUNT];
|
||||
struct k_mutex lock;
|
||||
};
|
||||
|
||||
static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel,
|
||||
static int mcux_pwm_set_cycles_internal(const struct device *dev, uint32_t channel,
|
||||
uint32_t period_cycles, uint32_t pulse_cycles,
|
||||
pwm_flags_t flags)
|
||||
{
|
||||
|
@ -45,24 +47,6 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel,
|
|||
struct pwm_mcux_data *data = dev->data;
|
||||
pwm_level_select_t level;
|
||||
|
||||
if (channel >= CHANNEL_COUNT) {
|
||||
LOG_ERR("Invalid channel");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (period_cycles == 0) {
|
||||
LOG_ERR("Channel can not be set to inactive level");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (period_cycles > UINT16_MAX) {
|
||||
/* 16-bit resolution */
|
||||
LOG_ERR("Too long period (%u), adjust pwm prescaler!",
|
||||
period_cycles);
|
||||
/* TODO: dynamically adjust prescaler */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (flags & PWM_POLARITY_INVERTED) {
|
||||
level = kPWM_LowTrue;
|
||||
} else {
|
||||
|
@ -158,6 +142,36 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel,
|
||||
uint32_t period_cycles, uint32_t pulse_cycles,
|
||||
pwm_flags_t flags)
|
||||
{
|
||||
struct pwm_mcux_data *data = dev->data;
|
||||
int result;
|
||||
|
||||
if (channel >= CHANNEL_COUNT) {
|
||||
LOG_ERR("Invalid channel");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (period_cycles == 0) {
|
||||
LOG_ERR("Channel can not be set to inactive level");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (period_cycles > UINT16_MAX) {
|
||||
/* 16-bit resolution */
|
||||
LOG_ERR("Too long period (%u), adjust pwm prescaler!",
|
||||
period_cycles);
|
||||
/* TODO: dynamically adjust prescaler */
|
||||
return -EINVAL;
|
||||
}
|
||||
k_mutex_lock(&data->lock, K_FOREVER);
|
||||
result = mcux_pwm_set_cycles_internal(dev, channel, period_cycles, pulse_cycles, flags);
|
||||
k_mutex_unlock(&data->lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int mcux_pwm_get_cycles_per_sec(const struct device *dev,
|
||||
uint32_t channel, uint64_t *cycles)
|
||||
{
|
||||
|
@ -181,6 +195,8 @@ static int pwm_mcux_init(const struct device *dev)
|
|||
status_t status;
|
||||
int i, err;
|
||||
|
||||
k_mutex_init(&data->lock);
|
||||
|
||||
if (!device_is_ready(config->clock_dev)) {
|
||||
LOG_ERR("clock control device not ready");
|
||||
return -ENODEV;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue