forked from Archive/PX4-Autopilot
imxrt:io_timers Support 1 channel per group (timer)
This commit is contained in:
parent
7f7137320a
commit
3be8d52c8e
|
@ -45,7 +45,11 @@
|
|||
#pragma once
|
||||
__BEGIN_DECLS
|
||||
/* configuration limits */
|
||||
#define MAX_IO_TIMERS 4
|
||||
#ifdef BOARD_NUM_IO_TIMERS
|
||||
#define MAX_IO_TIMERS BOARD_NUM_IO_TIMERS
|
||||
#else
|
||||
#define MAX_IO_TIMERS 4
|
||||
#endif
|
||||
#define MAX_TIMER_IO_CHANNELS 16
|
||||
|
||||
#define MAX_LED_TIMERS 2
|
||||
|
@ -78,6 +82,7 @@ typedef uint16_t io_timer_channel_allocation_t; /* big enough to hold MAX_TIMER_
|
|||
*/
|
||||
typedef struct io_timers_t {
|
||||
uint32_t base; /* Base address of the timer */
|
||||
uint32_t submodle; /* Which Submodule */
|
||||
uint32_t clock_register; /* SIM_SCGCn */
|
||||
uint32_t clock_bit; /* SIM_SCGCn bit pos */
|
||||
uint32_t vectorno; /* IRQ number */
|
||||
|
|
|
@ -56,7 +56,6 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
|
|||
PWM::FlexPWMConfig pwm_config, IOMUX::Pad pad)
|
||||
{
|
||||
timer_io_channels_t ret{};
|
||||
|
||||
PWM::FlexPWM pwm{};
|
||||
|
||||
// FlexPWM Muxing Options
|
||||
|
@ -591,7 +590,7 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
|
|||
const uint32_t timer_base = getFlexPWMBaseRegister(pwm);
|
||||
|
||||
for (int i = 0; i < MAX_IO_TIMERS; ++i) {
|
||||
if (io_timers_conf[i].base == timer_base) {
|
||||
if (io_timers_conf[i].base == timer_base && io_timers_conf[i].submodle == ret.sub_module) {
|
||||
ret.timer_index = i;
|
||||
break;
|
||||
}
|
||||
|
@ -602,11 +601,11 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline constexpr io_timers_t initIOPWM(PWM::FlexPWM pwm)
|
||||
static inline constexpr io_timers_t initIOPWM(PWM::FlexPWM pwm, PWM::FlexPWMSubmodule sub)
|
||||
{
|
||||
io_timers_t ret{};
|
||||
|
||||
ret.base = getFlexPWMBaseRegister(pwm);
|
||||
|
||||
ret.submodle = sub;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -431,46 +431,69 @@ static inline void io_timer_set_PWM_mode(unsigned channel)
|
|||
|
||||
void io_timer_trigger(unsigned channel_mask)
|
||||
{
|
||||
// Any Channels in oneshot?
|
||||
|
||||
int oneshots = io_timer_get_mode_channels(IOTimerChanMode_OneShot) & channel_mask;
|
||||
struct {
|
||||
uint32_t base;
|
||||
uint16_t triggers;
|
||||
} action_cache[MAX_IO_TIMERS] = {0};
|
||||
int actions = 0;
|
||||
|
||||
/* Pre-calculate the list of channels to Trigger */
|
||||
int mask;
|
||||
// Yes do triggering
|
||||
if (oneshots) {
|
||||
struct {
|
||||
uint32_t base;
|
||||
uint16_t triggers;
|
||||
} action_cache[MAX_IO_TIMERS] = {0};
|
||||
|
||||
for (int timer = 0; timer < MAX_IO_TIMERS; timer++) {
|
||||
action_cache[actions].base = io_timers[timer].base;
|
||||
int actions = 0;
|
||||
|
||||
if (action_cache[actions].base) {
|
||||
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;
|
||||
// Get the Timer modules addresses
|
||||
for (int timer = 0; timer < MAX_IO_TIMERS && io_timers[timer].base != 0; timer++) {
|
||||
if (action_cache[actions].base == 0) {
|
||||
action_cache[actions].base = io_timers[timer].base;
|
||||
|
||||
} else if (action_cache[actions].base != io_timers[timer].base) {
|
||||
actions++;
|
||||
action_cache[actions].base = io_timers[timer].base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Pre-calculate the list of channels to Trigger for each Timer module */
|
||||
|
||||
int mask;
|
||||
uint32_t channel = 0;
|
||||
|
||||
for (actions = 0; actions < MAX_IO_TIMERS; actions++) {
|
||||
if (action_cache[actions].base == 0) {
|
||||
// All have been processed
|
||||
break;
|
||||
}
|
||||
|
||||
// Group the bits from channels on the same timer
|
||||
for (; channel < MAX_TIMER_IO_CHANNELS && timer_io_channels[channel].val_offset; channel++) {
|
||||
|
||||
if (io_timers[timer_io_channels[channel].timer_index].base != action_cache[actions].base) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32_t channel = first_channel_index; channel < last_channel_index; channel++) {
|
||||
mask = get_channel_mask(channel);
|
||||
|
||||
if (oneshots & mask) {
|
||||
action_cache[actions].triggers |= timer_io_channels[channel].sub_module_bits;
|
||||
}
|
||||
}
|
||||
|
||||
actions++;
|
||||
}
|
||||
|
||||
/* Now do them all with the shortest delay in between */
|
||||
|
||||
irqstate_t flags = px4_enter_critical_section();
|
||||
|
||||
for (actions = 0; action_cache[actions].base != 0 && actions < MAX_IO_TIMERS; actions++) {
|
||||
_REG16(action_cache[actions].base, IMXRT_FLEXPWM_MCTRL_OFFSET) |= (action_cache[actions].triggers >> MCTRL_LDOK_SHIFT)
|
||||
<< MCTRL_CLDOK_SHIFT ;
|
||||
_REG16(action_cache[actions].base, IMXRT_FLEXPWM_MCTRL_OFFSET) |= action_cache[actions].triggers;
|
||||
}
|
||||
|
||||
px4_leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/* Now do them all with the shortest delay in between */
|
||||
|
||||
irqstate_t flags = px4_enter_critical_section();
|
||||
|
||||
for (actions = 0; action_cache[actions].base != 0 && actions < MAX_IO_TIMERS; actions++) {
|
||||
_REG16(action_cache[actions].base, IMXRT_FLEXPWM_MCTRL_OFFSET) |= (action_cache[actions].triggers >> MCTRL_LDOK_SHIFT)
|
||||
<< MCTRL_CLDOK_SHIFT ;
|
||||
_REG16(action_cache[actions].base, IMXRT_FLEXPWM_MCTRL_OFFSET) |= action_cache[actions].triggers;
|
||||
}
|
||||
|
||||
px4_leave_critical_section(flags);
|
||||
}
|
||||
|
||||
int io_timer_init_timer(unsigned timer, io_timer_channel_mode_t mode)
|
||||
|
@ -685,44 +708,71 @@ int io_timer_set_enable(bool state, io_timer_channel_mode_t mode, io_timer_chann
|
|||
|
||||
}
|
||||
|
||||
struct {
|
||||
uint32_t sm_ens;
|
||||
uint32_t base;
|
||||
uint32_t io_index;
|
||||
uint32_t gpios[MAX_TIMER_IO_CHANNELS];
|
||||
} action_cache[MAX_IO_TIMERS];
|
||||
if (masks) {
|
||||
struct {
|
||||
uint32_t sm_ens;
|
||||
uint32_t base;
|
||||
uint32_t io_index;
|
||||
uint32_t gpios[MAX_TIMER_IO_CHANNELS];
|
||||
} action_cache[MAX_IO_TIMERS];
|
||||
|
||||
memset(action_cache, 0, sizeof(action_cache));
|
||||
unsigned int actions = 0;
|
||||
memset(action_cache, 0, sizeof(action_cache));
|
||||
|
||||
for (int chan_index = 0; masks != 0 && chan_index < MAX_TIMER_IO_CHANNELS; chan_index++) {
|
||||
if (masks & (1 << chan_index)) {
|
||||
masks &= ~(1 << chan_index);
|
||||
for (int timer = 0; timer < MAX_IO_TIMERS && io_timers[timer].base != 0; timer++) {
|
||||
if (action_cache[actions].base == 0) {
|
||||
action_cache[actions].base = io_timers[timer].base;
|
||||
|
||||
if (io_timer_validate_channel_index(chan_index) == 0) {
|
||||
uint32_t timer_index = channels_timer(chan_index);
|
||||
action_cache[timer_index].base = io_timers[timer_index].base;
|
||||
action_cache[timer_index].sm_ens |= MCTRL_RUN(1 << timer_io_channels[chan_index].sub_module) |
|
||||
timer_io_channels[chan_index].sub_module_bits;
|
||||
action_cache[timer_index].gpios[action_cache[timer_index].io_index++] = timer_io_channels[chan_index].gpio_out;
|
||||
} else if (action_cache[actions].base != io_timers[timer].base) {
|
||||
actions++;
|
||||
action_cache[actions].base = io_timers[timer].base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
irqstate_t flags = px4_enter_critical_section();
|
||||
int chan_index = 0;
|
||||
|
||||
for (actions = 0; actions < MAX_IO_TIMERS; actions++) {
|
||||
if (action_cache[actions].base == 0) {
|
||||
// All have been processed
|
||||
break;
|
||||
}
|
||||
|
||||
for (; masks != 0 && chan_index < MAX_TIMER_IO_CHANNELS && timer_io_channels[chan_index].val_offset; chan_index++) {
|
||||
|
||||
if (masks & (1 << chan_index)) {
|
||||
|
||||
if (io_timers[timer_io_channels[chan_index].timer_index].base != action_cache[actions].base) {
|
||||
break;
|
||||
}
|
||||
|
||||
masks &= ~(1 << chan_index);
|
||||
|
||||
action_cache[actions].sm_ens |= MCTRL_RUN(1 << timer_io_channels[chan_index].sub_module) |
|
||||
timer_io_channels[chan_index].sub_module_bits;
|
||||
action_cache[actions].gpios[action_cache[actions].io_index++] = timer_io_channels[chan_index].gpio_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
irqstate_t flags = px4_enter_critical_section();
|
||||
|
||||
for (actions = 0; actions < arraySize(action_cache); actions++) {
|
||||
if (action_cache[actions].base == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned actions = 0; actions < arraySize(action_cache); actions++) {
|
||||
if (action_cache[actions].base != 0) {
|
||||
for (unsigned int index = 0; index < action_cache[actions].io_index; index++) {
|
||||
if (action_cache[actions].gpios[index]) {
|
||||
px4_arch_configgpio(action_cache[actions].gpios[index]);
|
||||
}
|
||||
|
||||
_REG16(action_cache[actions].base, IMXRT_FLEXPWM_MCTRL_OFFSET) = action_cache[actions].sm_ens;
|
||||
}
|
||||
|
||||
_REG16(action_cache[actions].base, IMXRT_FLEXPWM_MCTRL_OFFSET) = action_cache[actions].sm_ens;
|
||||
}
|
||||
|
||||
px4_leave_critical_section(flags);
|
||||
}
|
||||
|
||||
px4_leave_critical_section(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue