AP_HAL_ChibiOS: reset DMA after exiting soft serial

only configure DMA on groups that are actually being used for soft serial
This commit is contained in:
Andy Piper 2025-01-08 16:28:05 +00:00 committed by Randy Mackay
parent e21e61286a
commit 7c92663ce5
2 changed files with 20 additions and 7 deletions

View File

@ -1783,6 +1783,7 @@ void RCOutput::send_pulses_DMAR(pwm_group &group, uint32_t buffer_length)
#ifdef HAL_GPIO_LINE_GPIO54
TOGGLE_PIN_DEBUG(54);
#endif
#if STM32_DMA_SUPPORTS_DMAMUX
dmaSetRequestSource(group.dma, group.dma_up_channel);
#endif
@ -1909,6 +1910,11 @@ void RCOutput::dma_cancel(pwm_group& group)
While serial output is active normal output to the channel group is
suspended.
chanmask could refer to more than one group so it is assumed that
this function is always called before outputting to the group
implied by chan, but that DMA channels are setup only once
until serial_end() has been called
*/
#if HAL_SERIAL_ESC_COMM_ENABLED
bool RCOutput::serial_setup_output(uint8_t chan, uint32_t baudrate, uint32_t chanmask)
@ -1918,7 +1924,7 @@ bool RCOutput::serial_setup_output(uint8_t chan, uint32_t baudrate, uint32_t cha
chanmask >>= chan_offset;
pwm_group *new_serial_group = nullptr;
// find the channel group
// find the channel group for the next output
for (auto &group : pwm_group_list) {
if (group.current_mode == MODE_PWM_BRUSHED) {
// can't do serial output with brushed motors
@ -1935,6 +1941,7 @@ bool RCOutput::serial_setup_output(uint8_t chan, uint32_t baudrate, uint32_t cha
}
}
// couldn't find a group, shutdown everything
if (!new_serial_group) {
if (in_soft_serial()) {
// shutdown old group
@ -1946,22 +1953,23 @@ bool RCOutput::serial_setup_output(uint8_t chan, uint32_t baudrate, uint32_t cha
// stop further dshot output before we reconfigure the DMA
serial_group = new_serial_group;
// setup the groups for serial output. We ask for a bit width of 1, which gets modified by the
// setup the unconfigured groups for serial output. We ask for a bit width of 1, which gets modified by the
// we setup all groups so they all are setup with the right polarity, and to make switching between
// channels in blheli pass-thru fast
for (auto &group : pwm_group_list) {
if (group.ch_mask & chanmask) {
if ((group.ch_mask & chanmask) && !(group.ch_mask & serial_chanmask)) {
if (!setup_group_DMA(group, baudrate, 10, false, DSHOT_BUFFER_LENGTH, 10, false)) {
serial_end();
return false;
}
}
}
// run the thread doing serial IO at highest priority. This is needed to ensure we don't
// lose bytes when we switch between output and input
serial_thread = chThdGetSelfX();
serial_priority = chThdGetSelfX()->realprio;
// mask of channels currently configured
serial_chanmask |= chanmask;
chThdSetPriority(HIGHPRIO);
// remember the bit period for serial_read_byte()
@ -1997,7 +2005,6 @@ void RCOutput::fill_DMA_buffer_byte(dmar_uint_t *buffer, uint8_t stride, uint8_t
}
}
/*
send one serial byte, blocking call, should be called with the DMA lock held
*/
@ -2224,11 +2231,15 @@ void RCOutput::serial_end(void)
irq.waiter = nullptr;
for (uint8_t i = 0; i < NUM_GROUPS; i++ ) {
pwm_group &group = pwm_group_list[i];
// re-configure groups that were previous configured
if (group.ch_mask & serial_chanmask) {
dma_cancel(group); // this ensures the DMA is in a sane state
set_group_mode(group);
set_freq_group(group);
}
}
}
serial_group = nullptr;
serial_chanmask = 0;
}
#endif // HAL_SERIAL_ESC_COMM_ENABLED

View File

@ -507,6 +507,8 @@ private:
struct pwm_group *serial_group;
thread_t *serial_thread;
tprio_t serial_priority;
// mask of channels configured for serial output
uint32_t serial_chanmask;
#endif // HAL_SERIAL_ESC_COMM_ENABLED
static bool soft_serial_waiting() {