From 5f2cb5436cf545c2d5efba7994f458b98644ef6f Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sun, 19 Jul 2020 23:59:44 -0400 Subject: [PATCH] linux: Disable hardware pwm when it is set to zero Only write "1" to the "enable" file when a non-zero pwm width is requested. Write "0" to the "enable" file when a zero pwm width is requested. This fixes a problem on the replicape servo lines that prevented them from being fully disabled. Signed-off-by: Kevin O'Connor --- src/linux/gpio.h | 2 +- src/linux/hard_pwm.c | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/linux/gpio.h b/src/linux/gpio.h index e6ef86bd..e2a39be0 100644 --- a/src/linux/gpio.h +++ b/src/linux/gpio.h @@ -37,7 +37,7 @@ void spi_transfer(struct spi_config config, uint8_t receive_data , uint8_t len, uint8_t *data); struct gpio_pwm { - int fd; + int duty_fd, enable_fd; uint32_t period; }; struct gpio_pwm gpio_pwm_setup(uint32_t pin, uint32_t cycle_time, uint16_t val); diff --git a/src/linux/hard_pwm.c b/src/linux/hard_pwm.c index cfe8b436..842776c6 100644 --- a/src/linux/hard_pwm.c +++ b/src/linux/hard_pwm.c @@ -77,20 +77,18 @@ struct gpio_pwm gpio_pwm_setup(uint32_t pin, uint32_t cycle_time, uint16_t val) report_errno("pwm duty_cycle", fd); goto fail; } - - g.fd = fd; - gpio_pwm_write(g, val); + g.duty_fd = fd; // enable PWM snprintf(filename, sizeof(filename), pwm_path, chip_id, pwm_id, "enable"); fd = open(filename, O_WRONLY|O_CLOEXEC); if (fd == -1) { - close(g.fd); report_errno("pwm enable", fd); + close(g.duty_fd); goto fail; } - write(fd, "1", 2); - close(fd); + g.enable_fd = fd; + gpio_pwm_write(g, val); return g; @@ -103,12 +101,13 @@ fail: void gpio_pwm_write(struct gpio_pwm g, uint16_t val) { + if (!val) { + write(g.enable_fd, "0", 2); + return; + } char scratch[16]; uint32_t duty_cycle = g.period * (uint64_t)val / MAX_PWM; - snprintf(scratch, sizeof(scratch), "%u", duty_cycle); - if (g.fd != -1) { - write(g.fd, scratch, strlen(scratch)); - } else { - report_errno("pwm set duty_cycle", g.fd); - } + int len = snprintf(scratch, sizeof(scratch), "%u", duty_cycle); + write(g.duty_fd, scratch, len + 1); + write(g.enable_fd, "1", 2); }