imxrt io_timer: remove some fields from io_timers_t and split out channel indexes

IOMUX uses different enumeration from GPIO pin + port, so we cannot use
.gpio_out, and add a .gpio_portpin.
This commit is contained in:
Beat Küng 2020-01-13 13:50:53 +01:00 committed by David Sidrane
parent d74d094940
commit 8cd9afc19a
4 changed files with 107 additions and 23 deletions

View File

@ -86,26 +86,37 @@
__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = {
{
.base = IMXRT_FLEXPWM2_BASE,
.first_channel_index = 0,
.last_channel_index = 3,
},
{
.base = IMXRT_FLEXPWM3_BASE,
.first_channel_index = 4,
.last_channel_index = 5,
},
{
.base = IMXRT_FLEXPWM4_BASE,
.first_channel_index = 6,
.last_channel_index = 7,
},
};
__EXPORT const io_timers_channel_mapping_t io_timers_channel_mapping = {
.element = {
{
.first_channel_index = 0,
.channel_count = 4,
},
{
.first_channel_index = 4,
.channel_count = 2,
},
{
.first_channel_index = 6,
.channel_count = 2,
}
}
};
__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH1 : GPIO_B0_06 GPIO2 Pin 6 FLEXPWM2_PWMA0 */
.gpio_out = PIN_FLEXPWM2_PWMA00,
.gpio_portpin = GPIO_PORT2 | GPIO_PIN6,
.timer_index = 0,
.val_offset = PWMA_VAL,
.sub_module = SM0,
@ -115,6 +126,7 @@ __EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH2 : GPIO_EMC_08 GPIO4 Pin 8 FLEXPWM2_PWMA1 */
.gpio_out = PIN_FLEXPWM2_PWMA01,
.gpio_portpin = GPIO_PORT4 | GPIO_PIN8,
.timer_index = 0,
.val_offset = PWMA_VAL,
.sub_module = SM1,
@ -124,6 +136,7 @@ __EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH3 : GPIO_EMC_10 GPIO4 Pin 10 FLEXPWM2_PWMA2 */
.gpio_out = PIN_FLEXPWM2_PWMA02,
.gpio_portpin = GPIO_PORT4 | GPIO_PIN10,
.timer_index = 0,
.val_offset = PWMA_VAL,
.sub_module = SM2,
@ -133,6 +146,7 @@ __EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH4 : GPIO_AD_B0_09 GPIO1 Pin 9 FLEXPWM2_PWMA3 */
.gpio_out = PIN_FLEXPWM2_PWMA03,
.gpio_portpin = GPIO_PORT1 | GPIO_PIN9,
.timer_index = 0,
.val_offset = PWMA_VAL,
.sub_module = SM3,
@ -142,6 +156,7 @@ __EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH5 : GPIO_EMC_33 GPIO3 Pin 19 FLEXPWM3_PWMA2 */
.gpio_out = PIN_FLEXPWM3_PWMA02,
.gpio_portpin = GPIO_PORT3 | GPIO_PIN19,
.timer_index = 1,
.val_offset = PWMA_VAL,
.sub_module = SM2,
@ -150,6 +165,7 @@ __EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH6 : GPIO_EMC_30 GPIO4 Pin 30 FLEXPWM3_PWMB0 */
.gpio_out = PIN_FLEXPWM3_PWMB00,
.gpio_portpin = GPIO_PORT4 | GPIO_PIN30,
.timer_index = 1,
.val_offset = PWMB_VAL,
.sub_module = SM0,
@ -160,6 +176,7 @@ __EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH7 : GPIO_EMC_04 GPIO4 Pin 4 FLEXPWM4_PWMA2 */
.gpio_out = PIN_FLEXPWM4_PWMA02,
.gpio_portpin = GPIO_PORT4 | GPIO_PIN4,
.timer_index = 2,
.val_offset = PWMA_VAL,
.sub_module = SM2,
@ -169,6 +186,7 @@ __EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
{
/* FMU_CH8 : GPIO_EMC_01 GPIO4 Pin 1 FLEXPWM4_PWMB0 */
.gpio_out = PIN_FLEXPWM4_PWMB00,
.gpio_portpin = GPIO_PORT4 | GPIO_PIN1,
.timer_index = 2,
.val_offset = PWMB_VAL,
.sub_module = SM0,

View File

@ -77,15 +77,23 @@ typedef struct io_timers_t {
uint32_t clock_register; /* SIM_SCGCn */
uint32_t clock_bit; /* SIM_SCGCn bit pos */
uint32_t vectorno; /* IRQ number */
uint32_t first_channel_index; /* 0 based index in timer_io_channels */
uint32_t last_channel_index; /* 0 based index in timer_io_channels */
xcpt_t handler;
} io_timers_t;
typedef struct io_timers_channel_mapping_element_t {
uint32_t first_channel_index;
uint32_t channel_count;
} io_timers_channel_mapping_element_t;
/* mapping for each io_timers to timer_io_channels */
typedef struct io_timers_channel_mapping_t {
io_timers_channel_mapping_element_t element[MAX_IO_TIMERS];
} io_timers_channel_mapping_t;
/* array of channels in logical order */
typedef struct timer_io_channels_t {
uint32_t gpio_out; /* The timer valn_offset GPIO for PWM */
uint32_t gpio_in; /* The timer valn_offset GPIO for Capture */
uint32_t gpio_portpin; /* The GPIO Port + Pin (e.g. GPIO_PORT2 | GPIO_PIN6) */
uint8_t timer_index; /* 0 based index in the io_timers_t table */
uint8_t val_offset; /* IMXRT_FLEXPWM_SM0VAL3_OFFSET or IMXRT_FLEXPWM_SM0VAL5_OFFSET */
uint8_t sub_module; /* 0 based sub module offset */
@ -109,16 +117,13 @@ typedef void (*channel_handler_t)(void *context, const io_timers_t *timer, uint3
/* supplied by board-specific code */
__EXPORT extern const io_timers_t io_timers[MAX_IO_TIMERS];
__EXPORT extern const io_timers_channel_mapping_t io_timers_channel_mapping;
__EXPORT extern const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS];
__EXPORT extern const io_timers_t led_pwm_timers[MAX_LED_TIMERS];
__EXPORT extern const timer_io_channels_t led_pwm_channels[MAX_TIMER_LED_CHANNELS];
__EXPORT extern io_timer_channel_allocation_t allocations[IOTimerChanModeSize];
__EXPORT int io_timer_handler0(int irq, void *context, void *arg);
__EXPORT int io_timer_handler1(int irq, void *context, void *arg);
__EXPORT int io_timer_handler2(int irq, void *context, void *arg);
__EXPORT int io_timer_handler3(int irq, void *context, void *arg);
__EXPORT int io_timer_channel_init(unsigned channel, io_timer_channel_mode_t mode,
channel_handler_t channel_handler, void *context);
@ -139,4 +144,15 @@ __EXPORT int io_timer_get_channel_mode(unsigned channel);
__EXPORT int io_timer_get_mode_channels(io_timer_channel_mode_t mode);
__EXPORT extern void io_timer_trigger(void);
/**
* Returns the pin configuration for a specific channel, to be used as GPIO output.
* 0 is returned if the channel is not valid.
*/
__EXPORT uint32_t io_timer_channel_get_gpio_output(unsigned channel);
/**
* Returns the pin configuration for a specific channel, to be used as PWM input.
* 0 is returned if the channel is not valid.
*/
__EXPORT uint32_t io_timer_channel_get_as_pwm_input(unsigned channel);
__END_DECLS

View File

@ -31,6 +31,10 @@
#
############################################################################
add_compile_options(
-Wno-unused-function
) # TODO: remove once io_timer_handlerX are used
px4_add_library(arch_io_pins
io_timer.c
pwm_servo.c

View File

@ -31,8 +31,8 @@
*
****************************************************************************/
/*
* @file drv_io_timer.c
/**
* @file io_timer.c
*
* Servo driver supporting PWM servos connected to imxrt FLEXPWM blocks.
*/
@ -62,6 +62,15 @@
#include "hardware/imxrt_flexpwm.h"
#include "imxrt_periphclks.h"
static int io_timer_handler0(int irq, void *context, void *arg);
static int io_timer_handler1(int irq, void *context, void *arg);
static int io_timer_handler2(int irq, void *context, void *arg);
static int io_timer_handler3(int irq, void *context, void *arg);
static int io_timer_handler4(int irq, void *context, void *arg);
static int io_timer_handler5(int irq, void *context, void *arg);
static int io_timer_handler6(int irq, void *context, void *arg);
static int io_timer_handler7(int irq, void *context, void *arg);
#if !defined(BOARD_PWM_FREQ)
#define BOARD_PWM_FREQ 1000000
#endif
@ -169,26 +178,39 @@ static int io_timer_handler(uint16_t timer_index)
int io_timer_handler0(int irq, void *context, void *arg)
{
return io_timer_handler(0);
}
int io_timer_handler1(int irq, void *context, void *arg)
{
return io_timer_handler(1);
}
int io_timer_handler2(int irq, void *context, void *arg)
{
return io_timer_handler(2);
}
int io_timer_handler3(int irq, void *context, void *arg)
{
return io_timer_handler(3);
}
int io_timer_handler4(int irq, void *context, void *arg)
{
return io_timer_handler(4);
}
int io_timer_handler5(int irq, void *context, void *arg)
{
return io_timer_handler(5);
}
int io_timer_handler6(int irq, void *context, void *arg)
{
return io_timer_handler(6);
}
int io_timer_handler7(int irq, void *context, void *arg)
{
return io_timer_handler(7);
}
static inline int is_timer_uninitalized(unsigned timer)
@ -247,6 +269,26 @@ int io_timer_validate_channel_index(unsigned channel)
return rv;
}
uint32_t io_timer_channel_get_gpio_output(unsigned channel)
{
if (io_timer_validate_channel_index(channel) != 0) {
return 0;
}
return timer_io_channels[channel].gpio_portpin | (GPIO_OUTPUT | GPIO_OUTPUT_ZERO | IOMUX_CMOS_OUTPUT | IOMUX_PULL_KEEP
| IOMUX_DRIVE_33OHM | IOMUX_SPEED_MEDIUM | IOMUX_SLEW_FAST);
return 0;
}
uint32_t io_timer_channel_get_as_pwm_input(unsigned channel)
{
if (io_timer_validate_channel_index(channel) != 0) {
return 0;
}
return timer_io_channels[channel].gpio_in;
}
int io_timer_get_mode_channels(io_timer_channel_mode_t mode)
{
if (mode < IOTimerChanModeSize) {
@ -409,8 +451,10 @@ void io_timer_trigger(void)
action_cache[actions].base = io_timers[timer].base;
if (action_cache[actions].base) {
for (uint32_t channel = io_timers[timer].first_channel_index;
channel <= io_timers[timer].last_channel_index; channel++) {
uint32_t first_channel_index = io_timers_channel_mapping.element[timer].first_channel_index;
uint32_t last_channel_index = first_channel_index + io_timers_channel_mapping.element[timer].channel_count;
for (uint32_t channel = first_channel_index; channel < last_channel_index; channel++) {
mask = get_channel_mask(channel);
if (oneshots & mask) {
@ -467,8 +511,10 @@ int io_timer_init_timer(unsigned timer)
break;
}
for (uint32_t chan = io_timers[timer].first_channel_index;
chan <= io_timers[timer].last_channel_index; chan++) {
uint32_t first_channel_index = io_timers_channel_mapping.element[timer].first_channel_index;
uint32_t last_channel_index = first_channel_index + io_timers_channel_mapping.element[timer].channel_count;
for (uint32_t chan = first_channel_index; chan < last_channel_index; chan++) {
/* Clear all Faults */
rFSTS0(timer) = FSTS_FFLAG_MASK;