PWM: Add support for multiple output channels per timer

This commit is contained in:
Paul A. Patience 2015-11-01 17:15:12 -05:00
parent 00af71dd78
commit e8c2466c1c
3 changed files with 104 additions and 47 deletions

View File

@ -139,6 +139,10 @@ config ARCH_HAVE_PWM_PULSECOUNT
bool bool
default n default n
config ARCH_HAVE_PWM_MULTICHAN
bool
default n
menuconfig PWM menuconfig PWM
bool "PWM Driver Support" bool "PWM Driver Support"
default n default n
@ -147,6 +151,7 @@ menuconfig PWM
See include/nuttx/pwm.h for further PWM driver information. See include/nuttx/pwm.h for further PWM driver information.
if PWM if PWM
config PWM_PULSECOUNT config PWM_PULSECOUNT
bool "PWM Pulse Count Support" bool "PWM Pulse Count Support"
default n default n
@ -157,6 +162,26 @@ config PWM_PULSECOUNT
hardware will support a fixed pulse count, then this configuration hardware will support a fixed pulse count, then this configuration
should be set to enable the capability. 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 endif # PWM
config ARCH_HAVE_I2CRESET config ARCH_HAVE_I2CRESET

View File

@ -107,11 +107,17 @@ struct pwm_upperhalf_s
* Private Function Prototypes * 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_open(FAR struct file *filep);
static int pwm_close(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_read(FAR struct file *filep, FAR char *buffer,
static ssize_t pwm_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); size_t buflen);
static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags); 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); 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 * 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 * Name: pwm_open
* *
* Description: * Description:
* This function is called whenever the PWM device is opened. * This function is called whenever the PWM device is opened.
* *
************************************************************************************/ ****************************************************************************/
static int pwm_open(FAR struct file *filep) static int pwm_open(FAR struct file *filep)
{ {
@ -205,13 +241,13 @@ errout:
return ret; return ret;
} }
/************************************************************************************ /****************************************************************************
* Name: pwm_close * Name: pwm_close
* *
* Description: * Description:
* This function is called when the PWM device is closed. * This function is called when the PWM device is closed.
* *
************************************************************************************/ ****************************************************************************/
static int pwm_close(FAR struct file *filep) static int pwm_close(FAR struct file *filep)
{ {
@ -262,41 +298,43 @@ errout:
return ret; return ret;
} }
/************************************************************************************ /****************************************************************************
* Name: pwm_read * Name: pwm_read
* *
* Description: * Description:
* A dummy read method. This is provided only to satisfy the VFS layer. * 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 zero -- usually meaning end-of-file */
return 0; return 0;
} }
/************************************************************************************ /****************************************************************************
* Name: pwm_write * Name: pwm_write
* *
* Description: * Description:
* A dummy write method. This is provided only to satisfy the VFS layer. * 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; return 0;
} }
/************************************************************************************ /****************************************************************************
* Name: pwm_start * Name: pwm_start
* *
* Description: * Description:
* Handle the PWMIOC_START ioctl command * Handle the PWMIOC_START ioctl command
* *
************************************************************************************/ ****************************************************************************/
#ifdef CONFIG_PWM_PULSECOUNT #ifdef CONFIG_PWM_PULSECOUNT
static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags) 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 #endif
/************************************************************************************ /****************************************************************************
* Name: pwm_ioctl * Name: pwm_ioctl
* *
* Description: * Description:
* The standard ioctl method. This is where ALL of the PWM work is done. * 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) 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); FAR const struct pwm_info_s *info = (FAR const struct pwm_info_s *)((uintptr_t)arg);
DEBUGASSERT(info != NULL && lower->ops->start != NULL); DEBUGASSERT(info != NULL && lower->ops->start != NULL);
#ifdef CONFIG_PWM_PULSECOUNT pwm_dump("PWMIOC_SETCHARACTERISTICS", info, upper->started);
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
/* Save the pulse train characteristics */ /* 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)); memcpy(info, &upper->info, sizeof(struct pwm_info_s));
#ifdef CONFIG_PWM_PULSECOUNT pwm_dump("PWMIOC_GETCHARACTERISTICS", info, upper->started);
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
} }
break; break;
@ -498,14 +524,7 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case PWMIOC_START: case PWMIOC_START:
{ {
#ifdef CONFIG_PWM_PULSECOUNT pwm_dump("PWMIOC_START", &upper->info, upper->started);
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
DEBUGASSERT(lower->ops->start != NULL); DEBUGASSERT(lower->ops->start != NULL);
/* Start the pulse train */ /* 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 #ifdef CONFIG_PWM_PULSECOUNT
if (upper->waiting) if (upper->waiting)
{ {
upper->waiting = FALSE; upper->waiting = false;
} }
#endif #endif
} }

View File

@ -122,17 +122,30 @@
/**************************************************************************** /****************************************************************************
* Public Types * 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 */ /* This structure describes the characteristics of the pulsed output */
struct pwm_info_s struct pwm_info_s
{ {
uint32_t frequency; /* Frequency of the pulse train */ uint32_t frequency; /* Frequency of the pulse train */
ub16_t duty; /* Duty of the pulse train, "1"-to-"0" duration. #ifdef CONFIG_PWM_MULTICHAN
* Maximum: 65535/65536 (0x0000ffff) struct pwm_chan_s channels[CONFIG_PWM_NCHANNELS];
* Minimum: 1/65536 (0x00000001) */ #else
#ifdef CONFIG_PWM_PULSECOUNT ub16_t duty; /* Duty of the pulse train, "1"-to-"0" duration.
uint32_t count; /* The number of pulse to generate. 0 means to * Maximum: 65535/65536 (0x0000ffff)
* generate an indefinite number of pulses */ * 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 #endif
}; };