| /* |
| * Copyright (c) 2020-2021 Vestas Wind Systems A/S |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/drivers/pwm.h> |
| #include <zephyr/logging/log.h> |
| |
| LOG_MODULE_REGISTER(pwm_capture, CONFIG_PWM_LOG_LEVEL); |
| |
| struct z_pwm_capture_cb_data { |
| uint32_t period; |
| uint32_t pulse; |
| struct k_sem sem; |
| int status; |
| }; |
| |
| static void z_pwm_capture_cycles_callback(const struct device *dev, |
| uint32_t channel, |
| uint32_t period_cycles, |
| uint32_t pulse_cycles, int status, |
| void *user_data) |
| { |
| struct z_pwm_capture_cb_data *data = user_data; |
| |
| data->period = period_cycles; |
| data->pulse = pulse_cycles; |
| data->status = status; |
| |
| k_sem_give(&data->sem); |
| } |
| |
| int z_impl_pwm_capture_cycles(const struct device *dev, uint32_t channel, |
| pwm_flags_t flags, uint32_t *period, |
| uint32_t *pulse, k_timeout_t timeout) |
| { |
| struct z_pwm_capture_cb_data data; |
| int err; |
| |
| if ((flags & PWM_CAPTURE_MODE_MASK) == PWM_CAPTURE_MODE_CONTINUOUS) { |
| LOG_ERR("continuous capture mode only supported via callback"); |
| return -ENOTSUP; |
| } |
| |
| flags |= PWM_CAPTURE_MODE_SINGLE; |
| k_sem_init(&data.sem, 0, 1); |
| |
| err = pwm_configure_capture(dev, channel, flags, |
| z_pwm_capture_cycles_callback, &data); |
| if (err) { |
| LOG_ERR("failed to configure pwm capture"); |
| return err; |
| } |
| |
| err = pwm_enable_capture(dev, channel); |
| if (err) { |
| LOG_ERR("failed to enable pwm capture"); |
| return err; |
| } |
| |
| err = k_sem_take(&data.sem, timeout); |
| if (err == -EAGAIN) { |
| (void)pwm_disable_capture(dev, channel); |
| (void)pwm_configure_capture(dev, channel, flags, NULL, NULL); |
| LOG_WRN("pwm capture timed out"); |
| return err; |
| } |
| |
| if (data.status == 0) { |
| if (period != NULL) { |
| *period = data.period; |
| } |
| |
| if (pulse != NULL) { |
| *pulse = data.pulse; |
| } |
| } |
| |
| return data.status; |
| } |