Skip to content

Commit b67c65b

Browse files
dakejahlAlexKlimaj
authored andcommitted
dshot: fix bidirectional dshot stream sharing (#24996)
Freeing the DMA stream in the hrt callback causes other peripherals on that DMA controller to lock up (namely GPS). Moving the free back into thread context, right before allocation, solves the problem
1 parent e3fecd9 commit b67c65b

File tree

1 file changed

+22
-14
lines changed
  • platforms/nuttx/src/px4/stm/stm32_common/dshot

1 file changed

+22
-14
lines changed

platforms/nuttx/src/px4/stm/stm32_common/dshot/dshot.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -206,20 +206,24 @@ static void init_timers_dma_up(void)
206206
timer_configs[timer_index].dma_handle = stm32_dmachannel(io_timers[timer_index].dshot.dma_map_up);
207207

208208
if (timer_configs[timer_index].dma_handle == NULL) {
209-
PX4_DEBUG("Failed to allocate Timer %u DMA UP", timer_index);
209+
PX4_WARN("Failed to allocate Timer %u DMA UP", timer_index);
210210
continue;
211211
}
212212

213213
PX4_INFO("Allocated DMA UP Timer Index %u", timer_index);
214214
timer_configs[timer_index].initialized = true;
215215
}
216216

217-
// Free the allocated DMA channels
218-
for (uint8_t timer_index = 0; timer_index < MAX_IO_TIMERS; timer_index++) {
219-
if (timer_configs[timer_index].dma_handle != NULL) {
220-
stm32_dmafree(timer_configs[timer_index].dma_handle);
221-
timer_configs[timer_index].dma_handle = NULL;
222-
PX4_INFO("Freed DMA UP Timer Index %u", timer_index);
217+
// Bidirectional DShot will free/allocate DMA stream on every update event. This is required
218+
// in order to reconfigure the DMA stream between Timer Burst and CaptureCompare.
219+
if (_bidirectional) {
220+
// Free the allocated DMA channels
221+
for (uint8_t timer_index = 0; timer_index < MAX_IO_TIMERS; timer_index++) {
222+
if (timer_configs[timer_index].dma_handle != NULL) {
223+
stm32_dmafree(timer_configs[timer_index].dma_handle);
224+
timer_configs[timer_index].dma_handle = NULL;
225+
PX4_INFO("Freed DMA UP Timer Index %u", timer_index);
226+
}
223227
}
224228
}
225229
}
@@ -341,8 +345,15 @@ void up_dshot_trigger()
341345

342346
io_timer_set_dshot_burst_mode(timer_index, _dshot_frequency, channel_count);
343347

344-
// Allocate DMA
345-
if (timer_configs[timer_index].dma_handle == NULL) {
348+
if (_bidirectional) {
349+
// Deallocate DMA from previous transaction
350+
if (timer_configs[timer_index].dma_handle != NULL) {
351+
stm32_dmastop(timer_configs[timer_index].dma_handle);
352+
stm32_dmafree(timer_configs[timer_index].dma_handle);
353+
timer_configs[timer_index].dma_handle = NULL;
354+
}
355+
356+
// Allocate DMA
346357
timer_configs[timer_index].dma_handle = stm32_dmachannel(io_timers[timer_index].dshot.dma_map_up);
347358

348359
if (timer_configs[timer_index].dma_handle == NULL) {
@@ -502,11 +513,8 @@ static void capture_complete_callback(void *arg)
502513
// Disable capture DMA
503514
io_timer_capture_dma_req(timer_index, capture_channel, false);
504515

505-
if (timer_configs[timer_index].dma_handle != NULL) {
506-
stm32_dmastop(timer_configs[timer_index].dma_handle);
507-
stm32_dmafree(timer_configs[timer_index].dma_handle);
508-
timer_configs[timer_index].dma_handle = NULL;
509-
}
516+
// Stop DMA (should already be finished)
517+
stm32_dmastop(timer_configs[timer_index].dma_handle);
510518

511519
// Re-initialize all output channels on this timer
512520
for (uint8_t output_channel = 0; output_channel < MAX_TIMER_IO_CHANNELS; output_channel++) {

0 commit comments

Comments
 (0)