pwmcmds: Add Kconfig option to allow boards to disable hardware PWM commands

Some boards may not support hardware based PWM.  Update the build so
that those commands do not need to be compiled if they are not
available.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2016-06-08 19:44:34 -04:00
parent c20f993747
commit 4fcf5a31f5
5 changed files with 85 additions and 70 deletions

View File

@ -21,6 +21,9 @@ config HAVE_GPIO_ADC
config HAVE_GPIO_SPI
bool
default n
config HAVE_GPIO_HARD_PWM
bool
default n
config INLINE_STEPPER_HACK
# Enables gcc to inline stepper_event() into the main timer irq handler

View File

@ -3,3 +3,4 @@
src-y += sched.c command.c stepper.c basecmd.c gpiocmds.c endstop.c
src-$(CONFIG_HAVE_GPIO_ADC) += adccmds.c
src-$(CONFIG_HAVE_GPIO_SPI) += spicmds.c
src-$(CONFIG_HAVE_GPIO_HARD_PWM) += pwmcmds.c

View File

@ -7,6 +7,7 @@ config AVR_SELECT
default y
select HAVE_GPIO_ADC
select HAVE_GPIO_SPI
select HAVE_GPIO_HARD_PWM
config BOARD_DIRECTORY
string

View File

@ -4,12 +4,11 @@
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include <stddef.h> // offsetof
#include "basecmd.h" // alloc_oid
#include "board/gpio.h" // struct gpio
#include "board/gpio.h" // struct gpio_out
#include "board/irq.h" // irq_save
#include "command.h" // DECL_COMMAND
#include "sched.h" // DECL_TASK
#include "sched.h" // sched_timer
/****************************************************************
@ -86,73 +85,6 @@ command_set_digital_out(uint32_t *args)
DECL_COMMAND(command_set_digital_out, "set_digital_out pin=%u value=%c");
/****************************************************************
* Hardware PWM pins
****************************************************************/
struct pwm_out_s {
struct timer timer;
struct gpio_pwm pin;
uint32_t max_duration;
uint8_t value, default_value;
};
static uint8_t
pwm_event(struct timer *timer)
{
struct pwm_out_s *p = container_of(timer, struct pwm_out_s, timer);
gpio_pwm_write(p->pin, p->value);
if (p->value == p->default_value || !p->max_duration)
return SF_DONE;
p->timer.waketime += p->max_duration;
p->timer.func = digital_end_event;
return SF_RESCHEDULE;
}
void
command_config_pwm_out(uint32_t *args)
{
struct pwm_out_s *p = alloc_oid(args[0], command_config_pwm_out, sizeof(*p));
p->default_value = args[3];
p->pin = gpio_pwm_setup(args[1], args[2], p->default_value);
p->max_duration = args[4];
}
DECL_COMMAND(command_config_pwm_out,
"config_pwm_out oid=%c pin=%u cycle_ticks=%u default_value=%c"
" max_duration=%u");
void
command_schedule_pwm_out(uint32_t *args)
{
struct pwm_out_s *p = lookup_oid(args[0], command_config_pwm_out);
sched_del_timer(&p->timer);
p->timer.func = pwm_event;
p->timer.waketime = args[1];
p->value = args[2];
sched_timer(&p->timer);
}
DECL_COMMAND(command_schedule_pwm_out,
"schedule_pwm_out oid=%c clock=%u value=%c");
static void
pwm_shutdown(void)
{
uint8_t i;
struct pwm_out_s *p;
foreach_oid(i, p, command_config_pwm_out) {
gpio_pwm_write(p->pin, p->default_value);
}
}
DECL_SHUTDOWN(pwm_shutdown);
void
command_set_pwm_out(uint32_t *args)
{
gpio_pwm_setup(args[0], args[1], args[2]);
}
DECL_COMMAND(command_set_pwm_out, "set_pwm_out pin=%u cycle_ticks=%u value=%c");
/****************************************************************
* Soft PWM output pins
****************************************************************/

78
src/pwmcmds.c Normal file
View File

@ -0,0 +1,78 @@
// Commands for controlling hardware based pulse-width-modulator pins
//
// Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include "basecmd.h" // alloc_oid
#include "board/gpio.h" // struct gpio_pwm
#include "command.h" // DECL_COMMAND
#include "sched.h" // sched_timer
struct pwm_out_s {
struct timer timer;
struct gpio_pwm pin;
uint32_t max_duration;
uint8_t value, default_value;
};
static uint8_t
pwm_end_event(struct timer *timer)
{
shutdown("Missed scheduling of next hard pwm event");
}
static uint8_t
pwm_event(struct timer *timer)
{
struct pwm_out_s *p = container_of(timer, struct pwm_out_s, timer);
gpio_pwm_write(p->pin, p->value);
if (p->value == p->default_value || !p->max_duration)
return SF_DONE;
p->timer.waketime += p->max_duration;
p->timer.func = pwm_end_event;
return SF_RESCHEDULE;
}
void
command_config_pwm_out(uint32_t *args)
{
struct pwm_out_s *p = alloc_oid(args[0], command_config_pwm_out, sizeof(*p));
p->default_value = args[3];
p->pin = gpio_pwm_setup(args[1], args[2], p->default_value);
p->max_duration = args[4];
}
DECL_COMMAND(command_config_pwm_out,
"config_pwm_out oid=%c pin=%u cycle_ticks=%u default_value=%c"
" max_duration=%u");
void
command_schedule_pwm_out(uint32_t *args)
{
struct pwm_out_s *p = lookup_oid(args[0], command_config_pwm_out);
sched_del_timer(&p->timer);
p->timer.func = pwm_event;
p->timer.waketime = args[1];
p->value = args[2];
sched_timer(&p->timer);
}
DECL_COMMAND(command_schedule_pwm_out,
"schedule_pwm_out oid=%c clock=%u value=%c");
static void
pwm_shutdown(void)
{
uint8_t i;
struct pwm_out_s *p;
foreach_oid(i, p, command_config_pwm_out) {
gpio_pwm_write(p->pin, p->default_value);
}
}
DECL_SHUTDOWN(pwm_shutdown);
void
command_set_pwm_out(uint32_t *args)
{
gpio_pwm_setup(args[0], args[1], args[2]);
}
DECL_COMMAND(command_set_pwm_out, "set_pwm_out pin=%u cycle_ticks=%u value=%c");