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
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

View File

@ -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
}

View File

@ -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 */
#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
# ifdef CONFIG_PWM_PULSECOUNT
uint32_t count; /* The number of pulse to generate. 0 means to
* generate an indefinite number of pulses */
# endif
#endif
};