mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-28 18:53:57 -04:00
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:
parent
e21e61286a
commit
7c92663ce5
@ -1783,6 +1783,7 @@ void RCOutput::send_pulses_DMAR(pwm_group &group, uint32_t buffer_length)
|
|||||||
#ifdef HAL_GPIO_LINE_GPIO54
|
#ifdef HAL_GPIO_LINE_GPIO54
|
||||||
TOGGLE_PIN_DEBUG(54);
|
TOGGLE_PIN_DEBUG(54);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
dmaSetRequestSource(group.dma, group.dma_up_channel);
|
dmaSetRequestSource(group.dma, group.dma_up_channel);
|
||||||
#endif
|
#endif
|
||||||
@ -1909,6 +1910,11 @@ void RCOutput::dma_cancel(pwm_group& group)
|
|||||||
|
|
||||||
While serial output is active normal output to the channel group is
|
While serial output is active normal output to the channel group is
|
||||||
suspended.
|
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
|
#if HAL_SERIAL_ESC_COMM_ENABLED
|
||||||
bool RCOutput::serial_setup_output(uint8_t chan, uint32_t baudrate, uint32_t chanmask)
|
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;
|
chanmask >>= chan_offset;
|
||||||
pwm_group *new_serial_group = nullptr;
|
pwm_group *new_serial_group = nullptr;
|
||||||
|
|
||||||
// find the channel group
|
// find the channel group for the next output
|
||||||
for (auto &group : pwm_group_list) {
|
for (auto &group : pwm_group_list) {
|
||||||
if (group.current_mode == MODE_PWM_BRUSHED) {
|
if (group.current_mode == MODE_PWM_BRUSHED) {
|
||||||
// can't do serial output with brushed motors
|
// 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 (!new_serial_group) {
|
||||||
if (in_soft_serial()) {
|
if (in_soft_serial()) {
|
||||||
// shutdown old group
|
// 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
|
// stop further dshot output before we reconfigure the DMA
|
||||||
serial_group = new_serial_group;
|
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
|
// we setup all groups so they all are setup with the right polarity, and to make switching between
|
||||||
// channels in blheli pass-thru fast
|
// channels in blheli pass-thru fast
|
||||||
for (auto &group : pwm_group_list) {
|
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)) {
|
if (!setup_group_DMA(group, baudrate, 10, false, DSHOT_BUFFER_LENGTH, 10, false)) {
|
||||||
serial_end();
|
serial_end();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the thread doing serial IO at highest priority. This is needed to ensure we don't
|
// 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
|
// lose bytes when we switch between output and input
|
||||||
serial_thread = chThdGetSelfX();
|
serial_thread = chThdGetSelfX();
|
||||||
serial_priority = chThdGetSelfX()->realprio;
|
serial_priority = chThdGetSelfX()->realprio;
|
||||||
|
// mask of channels currently configured
|
||||||
|
serial_chanmask |= chanmask;
|
||||||
chThdSetPriority(HIGHPRIO);
|
chThdSetPriority(HIGHPRIO);
|
||||||
|
|
||||||
// remember the bit period for serial_read_byte()
|
// 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
|
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;
|
irq.waiter = nullptr;
|
||||||
for (uint8_t i = 0; i < NUM_GROUPS; i++ ) {
|
for (uint8_t i = 0; i < NUM_GROUPS; i++ ) {
|
||||||
pwm_group &group = pwm_group_list[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_group_mode(group);
|
||||||
set_freq_group(group);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serial_group = nullptr;
|
serial_group = nullptr;
|
||||||
|
serial_chanmask = 0;
|
||||||
}
|
}
|
||||||
#endif // HAL_SERIAL_ESC_COMM_ENABLED
|
#endif // HAL_SERIAL_ESC_COMM_ENABLED
|
||||||
|
|
||||||
|
@ -507,6 +507,8 @@ private:
|
|||||||
struct pwm_group *serial_group;
|
struct pwm_group *serial_group;
|
||||||
thread_t *serial_thread;
|
thread_t *serial_thread;
|
||||||
tprio_t serial_priority;
|
tprio_t serial_priority;
|
||||||
|
// mask of channels configured for serial output
|
||||||
|
uint32_t serial_chanmask;
|
||||||
#endif // HAL_SERIAL_ESC_COMM_ENABLED
|
#endif // HAL_SERIAL_ESC_COMM_ENABLED
|
||||||
|
|
||||||
static bool soft_serial_waiting() {
|
static bool soft_serial_waiting() {
|
||||||
|
Loading…
Reference in New Issue
Block a user