mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-19 15:13:33 +08:00
imxrt:io_timers Support 1 channel per group (timer)
This commit is contained in:
@@ -45,7 +45,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
/* configuration limits */
|
/* 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_TIMER_IO_CHANNELS 16
|
||||||
|
|
||||||
#define MAX_LED_TIMERS 2
|
#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 {
|
typedef struct io_timers_t {
|
||||||
uint32_t base; /* Base address of the timer */
|
uint32_t base; /* Base address of the timer */
|
||||||
|
uint32_t submodle; /* Which Submodule */
|
||||||
uint32_t clock_register; /* SIM_SCGCn */
|
uint32_t clock_register; /* SIM_SCGCn */
|
||||||
uint32_t clock_bit; /* SIM_SCGCn bit pos */
|
uint32_t clock_bit; /* SIM_SCGCn bit pos */
|
||||||
uint32_t vectorno; /* IRQ number */
|
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)
|
PWM::FlexPWMConfig pwm_config, IOMUX::Pad pad)
|
||||||
{
|
{
|
||||||
timer_io_channels_t ret{};
|
timer_io_channels_t ret{};
|
||||||
|
|
||||||
PWM::FlexPWM pwm{};
|
PWM::FlexPWM pwm{};
|
||||||
|
|
||||||
// FlexPWM Muxing Options
|
// 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);
|
const uint32_t timer_base = getFlexPWMBaseRegister(pwm);
|
||||||
|
|
||||||
for (int i = 0; i < MAX_IO_TIMERS; ++i) {
|
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;
|
ret.timer_index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -602,11 +601,11 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
|
|||||||
return ret;
|
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{};
|
io_timers_t ret{};
|
||||||
|
|
||||||
ret.base = getFlexPWMBaseRegister(pwm);
|
ret.base = getFlexPWMBaseRegister(pwm);
|
||||||
|
ret.submodle = sub;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -431,46 +431,69 @@ static inline void io_timer_set_PWM_mode(unsigned channel)
|
|||||||
|
|
||||||
void io_timer_trigger(unsigned channel_mask)
|
void io_timer_trigger(unsigned channel_mask)
|
||||||
{
|
{
|
||||||
|
// Any Channels in oneshot?
|
||||||
|
|
||||||
int oneshots = io_timer_get_mode_channels(IOTimerChanMode_OneShot) & channel_mask;
|
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 */
|
// Yes do triggering
|
||||||
int mask;
|
if (oneshots) {
|
||||||
|
struct {
|
||||||
|
uint32_t base;
|
||||||
|
uint16_t triggers;
|
||||||
|
} action_cache[MAX_IO_TIMERS] = {0};
|
||||||
|
|
||||||
for (int timer = 0; timer < MAX_IO_TIMERS; timer++) {
|
int actions = 0;
|
||||||
action_cache[actions].base = io_timers[timer].base;
|
|
||||||
|
|
||||||
if (action_cache[actions].base) {
|
// Get the Timer modules addresses
|
||||||
uint32_t first_channel_index = io_timers_channel_mapping.element[timer].first_channel_index;
|
for (int timer = 0; timer < MAX_IO_TIMERS && io_timers[timer].base != 0; timer++) {
|
||||||
uint32_t last_channel_index = first_channel_index + io_timers_channel_mapping.element[timer].channel_count;
|
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);
|
mask = get_channel_mask(channel);
|
||||||
|
|
||||||
if (oneshots & mask) {
|
if (oneshots & mask) {
|
||||||
action_cache[actions].triggers |= timer_io_channels[channel].sub_module_bits;
|
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)
|
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 {
|
if (masks) {
|
||||||
uint32_t sm_ens;
|
struct {
|
||||||
uint32_t base;
|
uint32_t sm_ens;
|
||||||
uint32_t io_index;
|
uint32_t base;
|
||||||
uint32_t gpios[MAX_TIMER_IO_CHANNELS];
|
uint32_t io_index;
|
||||||
} action_cache[MAX_IO_TIMERS];
|
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++) {
|
for (int timer = 0; timer < MAX_IO_TIMERS && io_timers[timer].base != 0; timer++) {
|
||||||
if (masks & (1 << chan_index)) {
|
if (action_cache[actions].base == 0) {
|
||||||
masks &= ~(1 << chan_index);
|
action_cache[actions].base = io_timers[timer].base;
|
||||||
|
|
||||||
if (io_timer_validate_channel_index(chan_index) == 0) {
|
} else if (action_cache[actions].base != io_timers[timer].base) {
|
||||||
uint32_t timer_index = channels_timer(chan_index);
|
actions++;
|
||||||
action_cache[timer_index].base = io_timers[timer_index].base;
|
action_cache[actions].base = io_timers[timer].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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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++) {
|
for (unsigned int index = 0; index < action_cache[actions].io_index; index++) {
|
||||||
if (action_cache[actions].gpios[index]) {
|
if (action_cache[actions].gpios[index]) {
|
||||||
px4_arch_configgpio(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user