forked from Archive/PX4-Autopilot
imxrt: flexpwm remove 1:1 mapping requirement
This commit is contained in:
parent
62d611b25b
commit
096dc306be
|
@ -34,24 +34,23 @@ def extract_timer(line):
|
||||||
if search:
|
if search:
|
||||||
return search.group(1), 'generic'
|
return search.group(1), 'generic'
|
||||||
|
|
||||||
# nxp rt1062 format: initIOPWM(PWM::FlexPWM2),
|
# NXP FlexPWM format format: initIOPWM(PWM::FlexPWM2),
|
||||||
search = re.search('PWM::Flex([0-9a-zA-Z_]+)[,\)]', line, re.IGNORECASE)
|
search = re.search('PWM::Flex([0-9a-zA-Z_]+)..PWM::Submodule([0-9])[,\)]', line, re.IGNORECASE)
|
||||||
if search:
|
if search:
|
||||||
return search.group(1), 'imxrt'
|
return (search.group(1) + '_' + search.group(2)), 'imxrt'
|
||||||
|
|
||||||
return None, 'unknown'
|
return None, 'unknown'
|
||||||
|
|
||||||
def extract_timer_from_channel(line, num_channels_already_found):
|
def extract_timer_from_channel(line, timer_names):
|
||||||
# Try format: initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortA, GPIO::Pin0}),
|
# Try format: initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortA, GPIO::Pin0}),
|
||||||
search = re.search('Timer::([0-9a-zA-Z_]+), ', line, re.IGNORECASE)
|
search = re.search('Timer::([0-9a-zA-Z_]+), ', line, re.IGNORECASE)
|
||||||
if search:
|
if search:
|
||||||
return search.group(1)
|
return search.group(1)
|
||||||
|
|
||||||
# nxp rt1062 format: initIOTimerChannel(io_timers, {PWM::PWM2_PWM_A, PWM::Submodule0}, IOMUX::Pad::GPIO_B0_06),
|
# NXP FlexPWM format: initIOTimerChannel(io_timers, {PWM::PWM2_PWM_A, PWM::Submodule0}, IOMUX::Pad::GPIO_B0_06),
|
||||||
search = re.search('PWM::(PWM[0-9]+)[_,\)]', line, re.IGNORECASE)
|
search = re.search('PWM::(PWM[0-9]+).*PWM::Submodule([0-9])', line, re.IGNORECASE)
|
||||||
if search:
|
if search:
|
||||||
# imxrt uses a 1:1 timer group to channel association
|
return str(timer_names.index((search.group(1) + '_' + search.group(2))))
|
||||||
return str(num_channels_already_found)
|
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -69,6 +68,7 @@ def get_timer_groups(timer_config_file, verbose=False):
|
||||||
open_idx, close_idx = find_matching_brackets(('{', '}'), timer_config, verbose)
|
open_idx, close_idx = find_matching_brackets(('{', '}'), timer_config, verbose)
|
||||||
timers_str = timer_config[open_idx:close_idx]
|
timers_str = timer_config[open_idx:close_idx]
|
||||||
timers = []
|
timers = []
|
||||||
|
timer_names = []
|
||||||
for line in timers_str.splitlines():
|
for line in timers_str.splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if len(line) == 0 or line.startswith('//'):
|
if len(line) == 0 or line.startswith('//'):
|
||||||
|
@ -77,14 +77,12 @@ def get_timer_groups(timer_config_file, verbose=False):
|
||||||
|
|
||||||
if timer_type == 'imxrt':
|
if timer_type == 'imxrt':
|
||||||
if verbose: print('imxrt timer found')
|
if verbose: print('imxrt timer found')
|
||||||
max_num_channels = 16 # Just add a fixed number of timers
|
timer_names.append(timer)
|
||||||
timers = [str(i) for i in range(max_num_channels)]
|
timers.append(str(len(timers)))
|
||||||
dshot_support = {str(i): False for i in range(max_num_channels)}
|
dshot_support = {str(i): False for i in range(16)}
|
||||||
for i in range(8): # First 8 channels support dshot
|
for i in range(8): # First 8 channels support dshot
|
||||||
dshot_support[str(i)] = True
|
dshot_support[str(i)] = True
|
||||||
break
|
elif timer:
|
||||||
|
|
||||||
if timer:
|
|
||||||
if verbose: print('found timer def: {:}'.format(timer))
|
if verbose: print('found timer def: {:}'.format(timer))
|
||||||
dshot_support[timer] = 'DMA' in line
|
dshot_support[timer] = 'DMA' in line
|
||||||
timers.append(timer)
|
timers.append(timer)
|
||||||
|
@ -111,7 +109,7 @@ def get_timer_groups(timer_config_file, verbose=False):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if verbose: print('--'+line+'--')
|
if verbose: print('--'+line+'--')
|
||||||
timer = extract_timer_from_channel(line, len(channel_timers))
|
timer = extract_timer_from_channel(line, timer_names)
|
||||||
|
|
||||||
if timer:
|
if timer:
|
||||||
if verbose: print('Found timer: {:} in channel line {:}'.format(timer, line))
|
if verbose: print('Found timer: {:} in channel line {:}'.format(timer, line))
|
||||||
|
|
|
@ -255,6 +255,34 @@ static inline int channels_timer(unsigned channel)
|
||||||
return timer_io_channels[channel].timer_index;
|
return timer_io_channels[channel].timer_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t get_timer_channels(unsigned timer)
|
||||||
|
{
|
||||||
|
uint32_t channels = 0;
|
||||||
|
static uint32_t channels_cache[MAX_IO_TIMERS] = {0};
|
||||||
|
|
||||||
|
if (validate_timer_index(timer) < 0) {
|
||||||
|
return channels;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (channels_cache[timer] == 0) {
|
||||||
|
/* Gather the channel bits that belong to the timer */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cache them */
|
||||||
|
|
||||||
|
channels_cache[timer] = channels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return channels_cache[timer];
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t get_channel_mask(unsigned channel)
|
static uint32_t get_channel_mask(unsigned channel)
|
||||||
{
|
{
|
||||||
return io_timer_validate_channel_index(channel) == 0 ? 1 << channel : 0;
|
return io_timer_validate_channel_index(channel) == 0 ? 1 << channel : 0;
|
||||||
|
@ -391,41 +419,60 @@ static int allocate_channel(unsigned channel, io_timer_channel_mode_t mode)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int timer_set_rate(unsigned channel, unsigned rate)
|
static int timer_set_rate(unsigned timer, unsigned rate)
|
||||||
{
|
{
|
||||||
|
int channels = get_timer_channels(timer);
|
||||||
|
|
||||||
irqstate_t flags = px4_enter_critical_section();
|
irqstate_t flags = px4_enter_critical_section();
|
||||||
rMCTRL(channels_timer(channel)) |= (timer_io_channels[channel].sub_module_bits >> MCTRL_LDOK_SHIFT) << MCTRL_CLDOK_SHIFT
|
for (uint32_t channel = 0; channel < DIRECT_PWM_OUTPUT_CHANNELS; ++channel) {
|
||||||
;
|
if ((1 << channel) & channels) {
|
||||||
rVAL1(channels_timer(channel), timer_io_channels[channel].sub_module) = (BOARD_PWM_FREQ / rate) - 1;
|
rMCTRL(channels_timer(channel)) |= (timer_io_channels[channel].sub_module_bits >> MCTRL_LDOK_SHIFT) << MCTRL_CLDOK_SHIFT
|
||||||
rMCTRL(channels_timer(channel)) |= timer_io_channels[channel].sub_module_bits;
|
;
|
||||||
|
rVAL1(channels_timer(channel), timer_io_channels[channel].sub_module) = (BOARD_PWM_FREQ / rate) - 1;
|
||||||
|
rMCTRL(channels_timer(channel)) |= timer_io_channels[channel].sub_module_bits;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
px4_leave_critical_section(flags);
|
px4_leave_critical_section(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void io_timer_set_oneshot_mode(unsigned channel)
|
static inline void io_timer_set_oneshot_mode(unsigned timer)
|
||||||
{
|
{
|
||||||
|
int channels = get_timer_channels(timer);
|
||||||
|
|
||||||
irqstate_t flags = px4_enter_critical_section();
|
irqstate_t flags = px4_enter_critical_section();
|
||||||
uint16_t rvalue = rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module);
|
for (uint32_t channel = 0; channel < DIRECT_PWM_OUTPUT_CHANNELS; ++channel) {
|
||||||
rvalue &= ~SMCTRL_PRSC_MASK;
|
if ((1 << channel) & channels) {
|
||||||
rvalue |= SMCTRL_PRSC_DIV2 | SMCTRL_LDMOD;
|
uint16_t rvalue = rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module);
|
||||||
rMCTRL(channels_timer(channel)) |= (timer_io_channels[channel].sub_module_bits >> MCTRL_LDOK_SHIFT) << MCTRL_CLDOK_SHIFT
|
rvalue &= ~SMCTRL_PRSC_MASK;
|
||||||
;
|
rvalue |= SMCTRL_PRSC_DIV2 | SMCTRL_LDMOD;
|
||||||
rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module) = rvalue;
|
rMCTRL(channels_timer(channel)) |= (timer_io_channels[channel].sub_module_bits >> MCTRL_LDOK_SHIFT) << MCTRL_CLDOK_SHIFT
|
||||||
rMCTRL(channels_timer(channel)) |= timer_io_channels[channel].sub_module_bits;
|
;
|
||||||
|
rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module) = rvalue;
|
||||||
|
rMCTRL(channels_timer(channel)) |= timer_io_channels[channel].sub_module_bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
px4_leave_critical_section(flags);
|
px4_leave_critical_section(flags);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void io_timer_set_PWM_mode(unsigned channel)
|
static inline void io_timer_set_PWM_mode(unsigned timer)
|
||||||
{
|
{
|
||||||
|
int channels = get_timer_channels(timer);
|
||||||
|
|
||||||
irqstate_t flags = px4_enter_critical_section();
|
irqstate_t flags = px4_enter_critical_section();
|
||||||
uint16_t rvalue = rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module);
|
for (uint32_t channel = 0; channel < DIRECT_PWM_OUTPUT_CHANNELS; ++channel) {
|
||||||
rvalue &= ~(SMCTRL_PRSC_MASK | SMCTRL_LDMOD);
|
if ((1 << channel) & channels) {
|
||||||
rvalue |= SMCTRL_PRSC_DIV16;
|
uint16_t rvalue = rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module);
|
||||||
rMCTRL(channels_timer(channel)) |= (timer_io_channels[channel].sub_module_bits >> MCTRL_LDOK_SHIFT) << MCTRL_CLDOK_SHIFT
|
rvalue &= ~(SMCTRL_PRSC_MASK | SMCTRL_LDMOD);
|
||||||
;
|
rvalue |= SMCTRL_PRSC_DIV16;
|
||||||
rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module) = rvalue;
|
rMCTRL(channels_timer(channel)) |= (timer_io_channels[channel].sub_module_bits >> MCTRL_LDOK_SHIFT) << MCTRL_CLDOK_SHIFT
|
||||||
rMCTRL(channels_timer(channel)) |= timer_io_channels[channel].sub_module_bits;
|
;
|
||||||
|
rCTRL(channels_timer(channel), timer_io_channels[channel].sub_module) = rvalue;
|
||||||
|
rMCTRL(channels_timer(channel)) |= timer_io_channels[channel].sub_module_bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
px4_leave_critical_section(flags);
|
px4_leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,33 +577,35 @@ int io_timer_init_timer(unsigned timer, io_timer_channel_mode_t mode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t first_channel_index = io_timers_channel_mapping.element[timer].first_channel_index;
|
int channels = get_timer_channels(timer);
|
||||||
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++) {
|
for (uint32_t chan = 0; chan < DIRECT_PWM_OUTPUT_CHANNELS; ++chan) {
|
||||||
|
if ((1 << chan) & channels) {
|
||||||
|
|
||||||
/* Clear all Faults */
|
/* Clear all Faults */
|
||||||
rFSTS0(timer) = FSTS_FFLAG_MASK;
|
rFSTS0(timer) = FSTS_FFLAG_MASK;
|
||||||
|
|
||||||
rCTRL2(timer, timer_io_channels[chan].sub_module) = SMCTRL2_CLK_SEL_EXT_CLK | SMCTRL2_DBGEN | SMCTRL2_INDEP;
|
rCTRL2(timer, timer_io_channels[chan].sub_module) = SMCTRL2_CLK_SEL_EXT_CLK | SMCTRL2_DBGEN | SMCTRL2_INDEP;
|
||||||
rCTRL(timer, timer_io_channels[chan].sub_module) = SMCTRL_PRSC_DIV16 | SMCTRL_FULL;
|
rCTRL(timer, timer_io_channels[chan].sub_module) = SMCTRL_PRSC_DIV16 | SMCTRL_FULL;
|
||||||
/* Edge aligned at 0 */
|
/* Edge aligned at 0 */
|
||||||
rINIT(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
rINIT(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
||||||
rVAL0(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
rVAL0(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
||||||
rVAL2(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
rVAL2(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
||||||
rVAL4(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
rVAL4(channels_timer(chan), timer_io_channels[chan].sub_module) = 0;
|
||||||
rFFILT0(timer) &= ~FFILT_FILT_PER_MASK;
|
rFFILT0(timer) &= ~FFILT_FILT_PER_MASK;
|
||||||
rDISMAP0(timer, timer_io_channels[chan].sub_module) = 0xf000;
|
rDISMAP0(timer, timer_io_channels[chan].sub_module) = 0xf000;
|
||||||
rDISMAP1(timer, timer_io_channels[chan].sub_module) = 0xf000;
|
rDISMAP1(timer, timer_io_channels[chan].sub_module) = 0xf000;
|
||||||
rOUTEN(timer) |= timer_io_channels[chan].val_offset == PWMA_VAL ? OUTEN_PWMA_EN(1 << timer_io_channels[chan].sub_module)
|
rOUTEN(timer) |= timer_io_channels[chan].val_offset == PWMA_VAL ? OUTEN_PWMA_EN(1 << timer_io_channels[chan].sub_module)
|
||||||
: OUTEN_PWMB_EN(1 << timer_io_channels[chan].sub_module);
|
: OUTEN_PWMB_EN(1 << timer_io_channels[chan].sub_module);
|
||||||
rDTSRCSEL(timer) = 0;
|
rDTSRCSEL(timer) = 0;
|
||||||
rMCTRL(timer) = MCTRL_LDOK(1 << timer_io_channels[chan].sub_module);
|
rMCTRL(timer) = MCTRL_LDOK(1 << timer_io_channels[chan].sub_module);
|
||||||
rMCTRL(timer) = timer_io_channels[chan].sub_module_bits;
|
rMCTRL(timer) = timer_io_channels[chan].sub_module_bits;
|
||||||
io_timer_set_PWM_mode(chan);
|
}
|
||||||
timer_set_rate(chan, 50);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
io_timer_set_PWM_mode(timer);
|
||||||
|
timer_set_rate(timer, 50);
|
||||||
|
|
||||||
px4_leave_critical_section(flags);
|
px4_leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,8 +867,7 @@ uint16_t io_channel_get_ccr(unsigned channel)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The rt has 1:1 group to channel
|
uint32_t io_timer_get_group(unsigned timer)
|
||||||
uint32_t io_timer_get_group(unsigned group)
|
|
||||||
{
|
{
|
||||||
return get_channel_mask(group);
|
return get_timer_channels(timer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue