From d0e4d510cf21cd56115750b0ec6a810537284267 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Sun, 28 Feb 2021 16:01:01 +0000 Subject: [PATCH] AP_HAL_ChibiOS: order PWM timers by DMA UP stream id to prevent deadlocks in dshot --- .../hwdef/scripts/chibios_hwdef.py | 15 +++++++++------ .../hwdef/scripts/dma_resolver.py | 19 ++++++++++++++++++- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py index df9878031c..1979f2d76b 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py +++ b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py @@ -1362,14 +1362,15 @@ def parse_timer(str): error("Bad timer definition %s" % str) -def write_PWM_config(f): +def write_PWM_config(f, ordered_timers): '''write PWM config defines''' rc_in = None rc_in_int = None alarm = None bidir = None pwm_out = [] - pwm_timers = [] + # start with the ordered list from the dma resolver + pwm_timers = ordered_timers has_bidir = False for l in bylabel.keys(): p = bylabel[l] @@ -1388,6 +1389,7 @@ def write_PWM_config(f): if p.type not in pwm_timers: pwm_timers.append(p.type) + f.write('#define HAL_PWM_COUNT %u\n' % len(pwm_out)) if not pwm_out and not alarm: print("No PWM output defined") @@ -1471,7 +1473,7 @@ def write_PWM_config(f): f.write('// PWM timer config\n') if bidir is not None: f.write('#define HAL_WITH_BIDIR_DSHOT\n') - for t in sorted(pwm_timers): + for t in pwm_timers: n = int(t[3:]) f.write('#define STM32_PWM_USE_TIM%u TRUE\n' % n) f.write('#define STM32_TIM%u_SUPPRESS_ISR\n' % n) @@ -1479,7 +1481,8 @@ def write_PWM_config(f): f.write('// PWM output config\n') groups = [] have_complementary = False - for t in sorted(pwm_timers): + + for t in pwm_timers: group = len(groups) + 1 n = int(t[3:]) chan_list = [255, 255, 255, 255] @@ -1761,13 +1764,13 @@ def write_hwdef_header(outfilename): write_peripheral_enable(f) - dma_unassigned = dma_resolver.write_dma_header(f, periph_list, mcu_type, + dma_unassigned, ordered_timers = dma_resolver.write_dma_header(f, periph_list, mcu_type, dma_exclude=get_dma_exclude(periph_list), dma_priority=get_config('DMA_PRIORITY', default='TIM* SPI*', spaces=True), dma_noshare=get_config('DMA_NOSHARE', default='', spaces=True)) if not args.bootloader: - write_PWM_config(f) + write_PWM_config(f, ordered_timers) write_I2C_config(f) write_UART_config(f) else: diff --git a/libraries/AP_HAL_ChibiOS/hwdef/scripts/dma_resolver.py b/libraries/AP_HAL_ChibiOS/hwdef/scripts/dma_resolver.py index 16cff44c39..f8629c5a4d 100755 --- a/libraries/AP_HAL_ChibiOS/hwdef/scripts/dma_resolver.py +++ b/libraries/AP_HAL_ChibiOS/hwdef/scripts/dma_resolver.py @@ -346,6 +346,23 @@ def write_dma_header(f, peripheral_list, mcu_type, dma_exclude=[], "\n// Note: The following peripherals can't be resolved for DMA: %s\n\n" % unassigned) + ordered_up_channels = [] + + # produce a list of timers ordered by the DMA streamid of the UP channel + # this is so that the dshot code can take out the UP DMA locks in the same order as I2C and SPI + for key in curr_dict.keys(): + if "_UP" in key: + ordered_up_channels.append(key) + + def order_by_streamid(key): + stream = curr_dict[key] + return (stream[0] * 8 + stream[1]) * 20 + int(key[3:-3]) + + ordered_up_channels = sorted(ordered_up_channels, key=order_by_streamid) + ordered_timers = [] + for key in ordered_up_channels: + ordered_timers.append(key[0:-3]) + for key in sorted(curr_dict.keys()): stream = curr_dict[key] shared = '' @@ -435,7 +452,7 @@ def write_dma_header(f, peripheral_list, mcu_type, dma_exclude=[], continue f.write('#define STM32_SPI_%s_DMA_STREAMS STM32_SPI_%s_TX_%s_STREAM, STM32_SPI_%s_RX_%s_STREAM\n' % ( key, key, dma_name(key), key, dma_name(key))) - return unassigned + return unassigned, ordered_timers if __name__ == '__main__':