mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-21 04:03:34 +08:00
io timer: remove some fields from io_timers_t and split out channel indexes
- reduces amount of board configuration required - removes the cyclic dependency between io_timers_t and timer_io_channels_t Fixes a bug in the fmuk66-v3 config: the 2. timer has 3 channels associated not 2. Fixes a bug in the modelai config: the 2. timer has 4 channels associated.
This commit is contained in:
@@ -82,11 +82,18 @@ 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 channel GPIO for PWM */
|
||||
@@ -104,16 +111,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);
|
||||
|
||||
@@ -62,6 +62,16 @@
|
||||
#include "hardware/kinetis_sim.h"
|
||||
#include "hardware/kinetis_ftm.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);
|
||||
|
||||
/* The FTM pre-scalers are limited to Divide by 2^n where n={1-7}
|
||||
* Therefore we use Y1 at 16 Mhz to drive FTM_CLKIN0 (PCT12)
|
||||
* and use this at a 16Mhz clock for FTM0, FTM2 and FTM3.
|
||||
@@ -184,7 +194,10 @@ static int io_timer_handler(uint16_t timer_index)
|
||||
|
||||
/* Iterate over the timer_io_channels table */
|
||||
|
||||
for (unsigned chan_index = tmr->first_channel_index; chan_index <= tmr->last_channel_index; chan_index++) {
|
||||
uint32_t first_channel_index = io_timers_channel_mapping.element[timer_index].first_channel_index;
|
||||
uint32_t last_channel_index = first_channel_index + io_timers_channel_mapping.element[timer_index].channel_count;
|
||||
|
||||
for (unsigned chan_index = first_channel_index; chan_index < last_channel_index; chan_index++) {
|
||||
|
||||
uint16_t chan = 1 << chan_index;
|
||||
|
||||
@@ -216,26 +229,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 validate_timer_index(unsigned timer)
|
||||
@@ -269,17 +295,6 @@ static inline int channels_timer(unsigned channel)
|
||||
return timer_io_channels[channel].timer_index;
|
||||
}
|
||||
|
||||
static inline int get_timers_firstchannels(unsigned timer)
|
||||
{
|
||||
int channel = -1;
|
||||
|
||||
if (validate_timer_index(timer) == 0) {
|
||||
channel = timer_io_channels[io_timers[timer].first_channel_index].timer_channel;
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
static uint32_t get_timer_channels(unsigned timer)
|
||||
{
|
||||
uint32_t channels = 0;
|
||||
@@ -290,11 +305,13 @@ static uint32_t get_timer_channels(unsigned timer)
|
||||
|
||||
} else {
|
||||
if (channels_cache[timer] == 0) {
|
||||
const io_timers_t *tmr = &io_timers[timer];
|
||||
|
||||
/* Gather the channel bits that belong to the timer */
|
||||
|
||||
for (unsigned chan_index = tmr->first_channel_index; chan_index <= tmr->last_channel_index; chan_index++) {
|
||||
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 (unsigned chan_index = first_channel_index; chan_index < last_channel_index; chan_index++) {
|
||||
channels |= 1 << chan_index;
|
||||
}
|
||||
|
||||
@@ -577,10 +594,35 @@ int io_timer_init_timer(unsigned timer)
|
||||
* Note that the timer is left disabled with IRQ subs installed
|
||||
* and active but DEIR bits are not set.
|
||||
*/
|
||||
xcpt_t handler;
|
||||
|
||||
irq_attach(io_timers[timer].vectorno, io_timers[timer].handler, NULL);
|
||||
switch (timer) {
|
||||
case 0: handler = io_timer_handler0; break;
|
||||
|
||||
up_enable_irq(io_timers[timer].vectorno);
|
||||
case 1: handler = io_timer_handler1; break;
|
||||
|
||||
case 2: handler = io_timer_handler2; break;
|
||||
|
||||
case 3: handler = io_timer_handler3; break;
|
||||
|
||||
case 4: handler = io_timer_handler4; break;
|
||||
|
||||
case 5: handler = io_timer_handler5; break;
|
||||
|
||||
case 6: handler = io_timer_handler6; break;
|
||||
|
||||
case 7: handler = io_timer_handler7; break;
|
||||
|
||||
default:
|
||||
handler = NULL;
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
irq_attach(io_timers[timer].vectorno, handler, NULL);
|
||||
up_enable_irq(io_timers[timer].vectorno);
|
||||
}
|
||||
|
||||
px4_leave_critical_section(flags);
|
||||
}
|
||||
|
||||
@@ -82,11 +82,18 @@ 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 channel GPIO for PWM */
|
||||
@@ -104,16 +111,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);
|
||||
@@ -133,5 +137,17 @@ __EXPORT int io_timer_free_channel(unsigned channel);
|
||||
__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
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* @file drv_io_timer.c
|
||||
/**
|
||||
* @file io_timer.c
|
||||
*
|
||||
* Servo driver supporting PWM servos connected to Kinetis FTM timer blocks.
|
||||
*/
|
||||
@@ -62,6 +62,16 @@
|
||||
#include "hardware/kinetis_sim.h"
|
||||
#include "hardware/kinetis_ftm.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);
|
||||
|
||||
/* The FTM pre-scalers are limited to Divide by 2^n where n={1-7}
|
||||
* Therefore we use Y1 at 16 Mhz to drive FTM_CLKIN0 (PCT12)
|
||||
* and use this at a 16Mhz clock for FTM0, FTM2 and FTM3.
|
||||
@@ -184,7 +194,10 @@ static int io_timer_handler(uint16_t timer_index)
|
||||
|
||||
/* Iterate over the timer_io_channels table */
|
||||
|
||||
for (unsigned chan_index = tmr->first_channel_index; chan_index <= tmr->last_channel_index; chan_index++) {
|
||||
uint32_t first_channel_index = io_timers_channel_mapping.element[timer_index].first_channel_index;
|
||||
uint32_t last_channel_index = first_channel_index + io_timers_channel_mapping.element[timer_index].channel_count;
|
||||
|
||||
for (unsigned chan_index = first_channel_index; chan_index < last_channel_index; chan_index++) {
|
||||
|
||||
uint16_t chan = 1 << chan_index;
|
||||
|
||||
@@ -216,26 +229,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 validate_timer_index(unsigned timer)
|
||||
@@ -269,17 +295,6 @@ static inline int channels_timer(unsigned channel)
|
||||
return timer_io_channels[channel].timer_index;
|
||||
}
|
||||
|
||||
static inline int get_timers_firstchannels(unsigned timer)
|
||||
{
|
||||
int channel = -1;
|
||||
|
||||
if (validate_timer_index(timer) == 0) {
|
||||
channel = timer_io_channels[io_timers[timer].first_channel_index].timer_channel;
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
static uint32_t get_timer_channels(unsigned timer)
|
||||
{
|
||||
uint32_t channels = 0;
|
||||
@@ -290,11 +305,13 @@ static uint32_t get_timer_channels(unsigned timer)
|
||||
|
||||
} else {
|
||||
if (channels_cache[timer] == 0) {
|
||||
const io_timers_t *tmr = &io_timers[timer];
|
||||
|
||||
/* Gather the channel bits that belong to the timer */
|
||||
|
||||
for (unsigned chan_index = tmr->first_channel_index; chan_index <= tmr->last_channel_index; chan_index++) {
|
||||
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 (unsigned chan_index = first_channel_index; chan_index < last_channel_index; chan_index++) {
|
||||
channels |= 1 << chan_index;
|
||||
}
|
||||
|
||||
@@ -345,6 +362,25 @@ 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_out & ~(_PIN_MODE_MASK | _PIN_OPTIONS_MASK)) | GPIO_HIGHDRIVE;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -577,10 +613,35 @@ int io_timer_init_timer(unsigned timer)
|
||||
* Note that the timer is left disabled with IRQ subs installed
|
||||
* and active but DEIR bits are not set.
|
||||
*/
|
||||
xcpt_t handler;
|
||||
|
||||
irq_attach(io_timers[timer].vectorno, io_timers[timer].handler, NULL);
|
||||
switch (timer) {
|
||||
case 0: handler = io_timer_handler0; break;
|
||||
|
||||
up_enable_irq(io_timers[timer].vectorno);
|
||||
case 1: handler = io_timer_handler1; break;
|
||||
|
||||
case 2: handler = io_timer_handler2; break;
|
||||
|
||||
case 3: handler = io_timer_handler3; break;
|
||||
|
||||
case 4: handler = io_timer_handler4; break;
|
||||
|
||||
case 5: handler = io_timer_handler5; break;
|
||||
|
||||
case 6: handler = io_timer_handler6; break;
|
||||
|
||||
case 7: handler = io_timer_handler7; break;
|
||||
|
||||
default:
|
||||
handler = NULL;
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
irq_attach(io_timers[timer].vectorno, handler, NULL);
|
||||
up_enable_irq(io_timers[timer].vectorno);
|
||||
}
|
||||
|
||||
px4_leave_critical_section(flags);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq)
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
dshot_burst_buffer[timer] = (uint32_t *)&dshot_burst_buffer_array[buffer_offset];
|
||||
#pragma GCC diagnostic pop
|
||||
buffer_offset += DSHOT_BURST_BUFFER_SIZE(io_timers[timer].dshot.channels_number);
|
||||
buffer_offset += DSHOT_BURST_BUFFER_SIZE(io_timers_channel_mapping.element[timer].channel_count);
|
||||
|
||||
if (buffer_offset > sizeof(dshot_burst_buffer_array)) {
|
||||
return -EINVAL; // something is wrong with the board configuration or some other logic
|
||||
@@ -143,8 +143,9 @@ int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq)
|
||||
for (uint8_t timer_index = 0; (timer_index < DSHOT_TIMERS) && (OK == ret_val); timer_index++) {
|
||||
|
||||
if (true == dshot_handler[timer_index].init) {
|
||||
dshot_handler[timer_index].dma_size = io_timers[timer_index].dshot.channels_number * ONE_MOTOR_BUFF_SIZE;
|
||||
io_timer_set_dshot_mode(timer_index, dshot_pwm_freq, io_timers[timer_index].dshot.channels_number);
|
||||
dshot_handler[timer_index].dma_size = io_timers_channel_mapping.element[timer_index].channel_count *
|
||||
ONE_MOTOR_BUFF_SIZE;
|
||||
io_timer_set_dshot_mode(timer_index, dshot_pwm_freq, io_timers_channel_mapping.element[timer_index].channel_count);
|
||||
|
||||
dshot_handler[timer_index].dma_handle = stm32_dmachannel(io_timers[timer_index].dshot.dmamap);
|
||||
|
||||
@@ -165,7 +166,7 @@ void up_dshot_trigger(void)
|
||||
|
||||
if (true == dshot_handler[timer].init) {
|
||||
|
||||
uint8_t motors_number = io_timers[timer].dshot.channels_number;
|
||||
uint8_t motors_number = io_timers_channel_mapping.element[timer].channel_count;
|
||||
dshot_dmar_data_prepare(timer, first_motor, motors_number);
|
||||
|
||||
// Flush cache so DMA sees the data
|
||||
|
||||
@@ -59,6 +59,4 @@
|
||||
typedef struct dshot_conf_t {
|
||||
uint32_t dma_base;
|
||||
uint32_t dmamap;
|
||||
uint32_t start_ccr_register;
|
||||
uint8_t channels_number; ///< number of channels/outputs (<=MAX_NUM_CHANNELS_PER_TIMER)
|
||||
} dshot_conf_t;
|
||||
|
||||
@@ -89,12 +89,19 @@ typedef struct io_timers_t {
|
||||
uint32_t clock_bit;
|
||||
uint32_t clock_freq;
|
||||
uint32_t vectorno;
|
||||
uint32_t first_channel_index;
|
||||
uint32_t last_channel_index;
|
||||
xcpt_t handler;
|
||||
dshot_conf_t dshot;
|
||||
} 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;
|
||||
@@ -105,7 +112,6 @@ typedef struct timer_io_channels_t {
|
||||
uint8_t ccr_offset;
|
||||
} timer_io_channels_t;
|
||||
|
||||
|
||||
typedef void (*channel_handler_t)(void *context, const io_timers_t *timer, uint32_t chan_index,
|
||||
const timer_io_channels_t *chan,
|
||||
hrt_abstime isrs_time, uint16_t isrs_rcnt);
|
||||
@@ -113,17 +119,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_handler4(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);
|
||||
|
||||
@@ -59,6 +59,16 @@
|
||||
#include <stm32_gpio.h>
|
||||
#include <stm32_tim.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(HAVE_GTIM_CCXNP)
|
||||
#define HW_GTIM_CCER_CC1NP GTIM_CCER_CC1NP
|
||||
#else
|
||||
@@ -182,7 +192,10 @@ static int io_timer_handler(uint16_t timer_index)
|
||||
|
||||
/* Iterate over the timer_io_channels table */
|
||||
|
||||
for (unsigned chan_index = tmr->first_channel_index; chan_index <= tmr->last_channel_index; chan_index++) {
|
||||
uint32_t first_channel_index = io_timers_channel_mapping.element[timer_index].first_channel_index;
|
||||
uint32_t last_channel_index = first_channel_index + io_timers_channel_mapping.element[timer_index].channel_count;
|
||||
|
||||
for (unsigned chan_index = first_channel_index; chan_index < last_channel_index; chan_index++) {
|
||||
|
||||
uint16_t masks = timer_io_channels[chan_index].masks;
|
||||
|
||||
@@ -222,32 +235,42 @@ 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 validate_timer_index(unsigned timer)
|
||||
@@ -281,17 +304,6 @@ static inline int channels_timer(unsigned channel)
|
||||
return timer_io_channels[channel].timer_index;
|
||||
}
|
||||
|
||||
static inline int get_timers_firstchannels(unsigned timer)
|
||||
{
|
||||
int channel = -1;
|
||||
|
||||
if (validate_timer_index(timer) == 0) {
|
||||
channel = timer_io_channels[io_timers[timer].first_channel_index].timer_channel;
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
static uint32_t get_timer_channels(unsigned timer)
|
||||
{
|
||||
uint32_t channels = 0;
|
||||
@@ -302,11 +314,12 @@ static uint32_t get_timer_channels(unsigned timer)
|
||||
|
||||
} else {
|
||||
if (channels_cache[timer] == 0) {
|
||||
const io_timers_t *tmr = &io_timers[timer];
|
||||
|
||||
/* Gather the channel bits that belong to the timer */
|
||||
|
||||
for (unsigned chan_index = tmr->first_channel_index; chan_index <= tmr->last_channel_index; chan_index++) {
|
||||
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 (unsigned chan_index = first_channel_index; chan_index < last_channel_index; chan_index++) {
|
||||
channels |= 1 << chan_index;
|
||||
}
|
||||
|
||||
@@ -527,7 +540,31 @@ int io_timer_set_dshot_mode(uint8_t timer, unsigned dshot_pwm_freq, uint8_t dma_
|
||||
rARR(timer) = DSHOT_MOTOR_PWM_BIT_WIDTH;
|
||||
rPSC(timer) = ((int)(io_timers[timer].clock_freq / dshot_pwm_freq) / DSHOT_MOTOR_PWM_BIT_WIDTH) - 1;
|
||||
rEGR(timer) = ATIM_EGR_UG;
|
||||
rDCR(timer) = (io_timers[timer].dshot.start_ccr_register | tim_dma_burst_length);
|
||||
|
||||
// find the lowest channel index for the timer (they are not necesarily in ascending order)
|
||||
unsigned lowest_timer_channel = 4;
|
||||
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 (unsigned chan_index = first_channel_index; chan_index < last_channel_index; chan_index++) {
|
||||
if (timer_io_channels[chan_index].timer_channel < lowest_timer_channel) {
|
||||
lowest_timer_channel = timer_io_channels[chan_index].timer_channel;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t start_ccr_register = 0;
|
||||
|
||||
switch (lowest_timer_channel) {
|
||||
case 1: start_ccr_register = TIM_DMABASE_CCR1; break;
|
||||
|
||||
case 2: start_ccr_register = TIM_DMABASE_CCR2; break;
|
||||
|
||||
case 3: start_ccr_register = TIM_DMABASE_CCR3; break;
|
||||
|
||||
case 4: start_ccr_register = TIM_DMABASE_CCR4; break;
|
||||
}
|
||||
|
||||
rDCR(timer) = start_ccr_register | tim_dma_burst_length;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
@@ -621,10 +658,35 @@ int io_timer_init_timer(unsigned timer)
|
||||
* Note that the timer is left disabled with IRQ subs installed
|
||||
* and active but DEIR bits are not set.
|
||||
*/
|
||||
xcpt_t handler;
|
||||
|
||||
irq_attach(io_timers[timer].vectorno, io_timers[timer].handler, NULL);
|
||||
switch (timer) {
|
||||
case 0: handler = io_timer_handler0; break;
|
||||
|
||||
up_enable_irq(io_timers[timer].vectorno);
|
||||
case 1: handler = io_timer_handler1; break;
|
||||
|
||||
case 2: handler = io_timer_handler2; break;
|
||||
|
||||
case 3: handler = io_timer_handler3; break;
|
||||
|
||||
case 4: handler = io_timer_handler4; break;
|
||||
|
||||
case 5: handler = io_timer_handler5; break;
|
||||
|
||||
case 6: handler = io_timer_handler6; break;
|
||||
|
||||
case 7: handler = io_timer_handler7; break;
|
||||
|
||||
default:
|
||||
handler = NULL;
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
irq_attach(io_timers[timer].vectorno, handler, NULL);
|
||||
up_enable_irq(io_timers[timer].vectorno);
|
||||
}
|
||||
|
||||
px4_leave_critical_section(flags);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user