From e8c2466c1cecf22035976a2dd577dfc67f9ea373 Mon Sep 17 00:00:00 2001 From: "Paul A. Patience" Date: Sun, 1 Nov 2015 17:15:12 -0500 Subject: [PATCH] PWM: Add support for multiple output channels per timer --- drivers/Kconfig | 25 ++++++++++++ drivers/pwm.c | 99 +++++++++++++++++++++++++++------------------ include/nuttx/pwm.h | 27 +++++++++---- 3 files changed, 104 insertions(+), 47 deletions(-) diff --git a/drivers/Kconfig b/drivers/Kconfig index 263001d9cc..f223e1c795 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -139,6 +139,10 @@ config ARCH_HAVE_PWM_PULSECOUNT bool default n +config ARCH_HAVE_PWM_MULTICHAN + bool + default n + menuconfig PWM bool "PWM Driver Support" default n @@ -147,6 +151,7 @@ menuconfig PWM See include/nuttx/pwm.h for further PWM driver information. if PWM + config PWM_PULSECOUNT bool "PWM Pulse Count Support" default n @@ -157,6 +162,26 @@ config PWM_PULSECOUNT hardware will support a fixed pulse count, then this configuration should be set to enable the capability. +config PWM_MULTICHAN + bool "PWM Multiple Output Channel Support" + default n + depends on ARCH_HAVE_PWM_MULTICHAN + depends on !PWM_PULSECOUNT + ---help--- + Enables support for multiple output channels per timer. + +if PWM_MULTICHAN + +config PWM_NCHANNELS + int "Number of Output Channels Per Timer" + default 1 + range 1 4 + ---help--- + Specifies the number of output channels per timer. Each timer + may support fewer output channels than this value. + +endif # PWM_MULTICHAN + endif # PWM config ARCH_HAVE_I2CRESET diff --git a/drivers/pwm.c b/drivers/pwm.c index 9071ab0543..3903bdf4fa 100644 --- a/drivers/pwm.c +++ b/drivers/pwm.c @@ -107,11 +107,17 @@ struct pwm_upperhalf_s * Private Function Prototypes ****************************************************************************/ +static void pwm_dump(FAR const char *msg, + FAR const struct pwm_info_s *info, + bool started); static int pwm_open(FAR struct file *filep); static int pwm_close(FAR struct file *filep); -static ssize_t pwm_read(FAR struct file *filep, FAR char *buffer, size_t buflen); -static ssize_t pwm_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); -static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags); +static ssize_t pwm_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t pwm_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int pwm_start(FAR struct pwm_upperhalf_s *upper, + unsigned int oflags); static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg); /**************************************************************************** @@ -135,13 +141,43 @@ static const struct file_operations g_pwmops = * Private Functions ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** + * Name: pwm_dump + ****************************************************************************/ + +static void pwm_dump(FAR const char *msg, FAR const struct pwm_info_s *info, + bool started) +{ +#ifdef CONFIG_PWM_MULTICHAN + int i; +#endif + + pwmvdbg("%s: frequency: %d", msg, info->frequency); + +#ifdef CONFIG_PWM_MULTICHAN + for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) + { + pwmvdbg(" channel: %d duty: %08x", + info->channels[i].channel, info->channels[i].duty); + } +#else + pwmvdbg(" duty: %08x", info->duty); +#endif + +#ifdef CONFIG_PWM_PULSECOUNT + pwmvdbg(" count: %d\n", info->count); +#endif + + pwmvdbg(" started: %d\n", started); +} + +/**************************************************************************** * Name: pwm_open * * Description: * This function is called whenever the PWM device is opened. * - ************************************************************************************/ + ****************************************************************************/ static int pwm_open(FAR struct file *filep) { @@ -205,13 +241,13 @@ errout: return ret; } -/************************************************************************************ +/**************************************************************************** * Name: pwm_close * * Description: * This function is called when the PWM device is closed. * - ************************************************************************************/ + ****************************************************************************/ static int pwm_close(FAR struct file *filep) { @@ -262,41 +298,43 @@ errout: return ret; } -/************************************************************************************ +/**************************************************************************** * Name: pwm_read * * Description: * A dummy read method. This is provided only to satisfy the VFS layer. * - ************************************************************************************/ + ****************************************************************************/ -static ssize_t pwm_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +static ssize_t pwm_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) { /* Return zero -- usually meaning end-of-file */ return 0; } -/************************************************************************************ +/**************************************************************************** * Name: pwm_write * * Description: * A dummy write method. This is provided only to satisfy the VFS layer. * - ************************************************************************************/ + ****************************************************************************/ -static ssize_t pwm_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) +static ssize_t pwm_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) { return 0; } -/************************************************************************************ +/**************************************************************************** * Name: pwm_start * * Description: * Handle the PWMIOC_START ioctl command * - ************************************************************************************/ + ****************************************************************************/ #ifdef CONFIG_PWM_PULSECOUNT static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags) @@ -397,13 +435,13 @@ static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags) } #endif -/************************************************************************************ +/**************************************************************************** * Name: pwm_ioctl * * Description: * The standard ioctl method. This is where ALL of the PWM work is done. * - ************************************************************************************/ + ****************************************************************************/ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { @@ -441,13 +479,7 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg) FAR const struct pwm_info_s *info = (FAR const struct pwm_info_s *)((uintptr_t)arg); DEBUGASSERT(info != NULL && lower->ops->start != NULL); -#ifdef CONFIG_PWM_PULSECOUNT - pwmvdbg("PWMIOC_SETCHARACTERISTICS frequency: %d duty: %08x count: %d started: %d\n", - info->frequency, info->duty, info->count, upper->started); -#else - pwmvdbg("PWMIOC_SETCHARACTERISTICS frequency: %d duty: %08x started: %d\n", - info->frequency, info->duty, upper->started); -#endif + pwm_dump("PWMIOC_SETCHARACTERISTICS", info, upper->started); /* Save the pulse train characteristics */ @@ -480,13 +512,7 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg) memcpy(info, &upper->info, sizeof(struct pwm_info_s)); -#ifdef CONFIG_PWM_PULSECOUNT - pwmvdbg("PWMIOC_GETCHARACTERISTICS frequency: %d duty: %08x count: %d\n", - info->frequency, info->duty, info->count); -#else - pwmvdbg("PWMIOC_GETCHARACTERISTICS frequency: %d duty: %08x\n", - info->frequency, info->duty); -#endif + pwm_dump("PWMIOC_GETCHARACTERISTICS", info, upper->started); } break; @@ -498,14 +524,7 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg) case PWMIOC_START: { -#ifdef CONFIG_PWM_PULSECOUNT - pwmvdbg("PWMIOC_START frequency: %d duty: %08x count: %d started: %d\n", - upper->info.frequency, upper->info.duty, upper->info.count, - upper->started); -#else - pwmvdbg("PWMIOC_START frequency: %d duty: %08x started: %d\n", - upper->info.frequency, upper->info.duty, upper->started); -#endif + pwm_dump("PWMIOC_START", &upper->info, upper->started); DEBUGASSERT(lower->ops->start != NULL); /* Start the pulse train */ @@ -531,7 +550,7 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg) #ifdef CONFIG_PWM_PULSECOUNT if (upper->waiting) { - upper->waiting = FALSE; + upper->waiting = false; } #endif } diff --git a/include/nuttx/pwm.h b/include/nuttx/pwm.h index 8abb51e713..f77cbee23a 100644 --- a/include/nuttx/pwm.h +++ b/include/nuttx/pwm.h @@ -122,17 +122,30 @@ /**************************************************************************** * Public Types ****************************************************************************/ + +#ifdef CONFIG_PWM_MULTICHAN +struct pwm_chan_s +{ + ub16_t duty; + uint8_t channel; +}; +#endif + /* This structure describes the characteristics of the pulsed output */ struct pwm_info_s { - uint32_t frequency; /* Frequency of the pulse train */ - ub16_t duty; /* Duty of the pulse train, "1"-to-"0" duration. - * Maximum: 65535/65536 (0x0000ffff) - * Minimum: 1/65536 (0x00000001) */ -#ifdef CONFIG_PWM_PULSECOUNT - uint32_t count; /* The number of pulse to generate. 0 means to - * generate an indefinite number of pulses */ + uint32_t frequency; /* Frequency of the pulse train */ +#ifdef CONFIG_PWM_MULTICHAN + struct pwm_chan_s channels[CONFIG_PWM_NCHANNELS]; +#else + ub16_t duty; /* Duty of the pulse train, "1"-to-"0" duration. + * Maximum: 65535/65536 (0x0000ffff) + * Minimum: 1/65536 (0x00000001) */ +# ifdef CONFIG_PWM_PULSECOUNT + uint32_t count; /* The number of pulse to generate. 0 means to + * generate an indefinite number of pulses */ +# endif #endif };