Bi-directional dshot support

There is a thread for that!

It doesn’t look like you’ll be able to use the existing motor outputs for bdshot, as they use two different timers and would take up too many DMA assignments. It looks like the only option is using UART6 and M5, M6, but TX6 isn’t broken out on the board so you’d have to solder directly to the MCU. If you’re willing to go that route I can take a stab at the firmware, but it would be much easier to switch to a FC that already has a bdshot target.

Thanks for reviewing!

It’s doesn’t sound like F405-SE is that valuable for the community then since directly soldering to the mcu pin isn’t something most people will want to deal with. I may be able to do it, but not worth the headache for me either =)

I would say F4’s are not that valuable. Too many handicaps now and it will only get worse.

Might work:

Do the BIDIR outputs need their own DMA stream? It looks like this PR requires a bunch of shared DMA streams between DSHOT outputs and SPI, I2C, and UARTs:

// auto-generated DMA mapping from dma_resolver.py

// Note: The following peripherals can't be resolved for DMA: ['UART4_RX', 'USART3_RX', 'UART5_RX']

#define STM32_ADC_ADC1_DMA_STREAM      STM32_DMA_STREAM_ID(2, 4)
#define STM32_ADC_ADC1_DMA_CHAN        0
#define STM32_I2C_I2C1_RX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 5) // shared SPI3_TX,I2C1_RX
#define STM32_I2C_I2C1_RX_DMA_CHAN     1
#define STM32_I2C_I2C1_TX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 6) // shared TIM4_UP,I2C1_TX
#define STM32_I2C_I2C1_TX_DMA_CHAN     1
#define STM32_I2C_I2C2_RX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 3) // shared TIM4_CH2,SPI2_RX,I2C2_RX
#define STM32_I2C_I2C2_RX_DMA_CHAN     7
#define STM32_I2C_I2C2_TX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 7) // shared TIM3_CH3,I2C2_TX,UART5_TX
#define STM32_I2C_I2C2_TX_DMA_CHAN     7
#define STM32_SPI_SPI1_RX_DMA_STREAM   STM32_DMA_STREAM_ID(2, 0)
#define STM32_SPI_SPI1_RX_DMA_CHAN     3
#define STM32_SPI_SPI1_TX_DMA_STREAM   STM32_DMA_STREAM_ID(2, 3)
#define STM32_SPI_SPI1_TX_DMA_CHAN     3
#define STM32_SPI_SPI2_RX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 3) // shared TIM4_CH2,SPI2_RX,I2C2_RX
#define STM32_SPI_SPI2_RX_DMA_CHAN     0
#define STM32_SPI_SPI2_TX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 4) // shared SPI2_TX,UART4_TX,USART3_TX
#define STM32_SPI_SPI2_TX_DMA_CHAN     0
#define STM32_SPI_SPI3_RX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 0)
#define STM32_SPI_SPI3_RX_DMA_CHAN     0
#define STM32_SPI_SPI3_TX_DMA_STREAM   STM32_DMA_STREAM_ID(1, 5) // shared SPI3_TX,I2C1_RX
#define STM32_SPI_SPI3_TX_DMA_CHAN     0
#define STM32_TIM_TIM1_UP_DMA_STREAM   STM32_DMA_STREAM_ID(2, 5)
#define STM32_TIM_TIM1_UP_DMA_CHAN     6
#define STM32_TIM_TIM2_UP_DMA_STREAM   STM32_DMA_STREAM_ID(1, 1)
#define STM32_TIM_TIM2_UP_DMA_CHAN     3
#define STM32_TIM_TIM3_CH3_DMA_STREAM  STM32_DMA_STREAM_ID(1, 7) // shared TIM3_CH3,I2C2_TX,UART5_TX
#define STM32_TIM_TIM3_CH3_DMA_CHAN    5
#define STM32_TIM_TIM3_UP_DMA_STREAM   STM32_DMA_STREAM_ID(1, 2)
#define STM32_TIM_TIM3_UP_DMA_CHAN     5
#define STM32_TIM_TIM4_CH2_DMA_STREAM  STM32_DMA_STREAM_ID(1, 3) // shared TIM4_CH2,SPI2_RX,I2C2_RX
#define STM32_TIM_TIM4_CH2_DMA_CHAN    2
#define STM32_TIM_TIM4_UP_DMA_STREAM   STM32_DMA_STREAM_ID(1, 6) // shared TIM4_UP,I2C1_TX
#define STM32_TIM_TIM4_UP_DMA_CHAN     2
#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) // shared SPI2_TX,UART4_TX,USART3_TX
#define STM32_UART_UART4_TX_DMA_CHAN   4
#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) // shared TIM3_CH3,I2C2_TX,UART5_TX
#define STM32_UART_UART5_TX_DMA_CHAN   4
#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_UART_USART1_RX_DMA_CHAN  4
#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
#define STM32_UART_USART1_TX_DMA_CHAN  4
#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) // shared SPI2_TX,UART4_TX,USART3_TX
#define STM32_UART_USART3_TX_DMA_CHAN  7
#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
#define STM32_UART_USART6_RX_DMA_CHAN  5
#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6)
#define STM32_UART_USART6_TX_DMA_CHAN  5

On that second point… the hardware target page softly warn against using F4 (like they don’t have enough RAM) but some of us may be inclined to cheap out (or in my case I had a specific desire for AIO + separate ESC) and regret it later. It would be nice to have some table listing caveats for the later releases or just asterixis-note which FCs are well used by the dev-team.

It would be better if they did - I’ve not tried recently to see how bad it is if they don’t

@chronowarper are you able to test?

@andyp1per Sorry not yet; I may get time to this weekend. Had some issues with new computer not booting, then was out for the Thanksgiving holidays.

I tried the build but couldn’t get motors to spin with bdshot enabled on the F405-SE. Had some discussion with Andy to confirm think the params are set up right, so there’s something not working. We didn’t think it’s worth spending more time on this board since it’s only an F4.

Hi all,

is there any chance to see the bdshot enable for the MatekF765-Wing (copter and q_plane) or it’s a limitation for this board ?

thanks

I can put together a candidate PR if you are willing to test - no guarantees it will work

Thanks @andyp1per.
That would be great, I can test with a 2 tilt motors qplane if you think that type of test is relevant.

Why are only 2 of the 4 motor outputs in the bdshot-enabled hwdef.dat files annotated with BIDIR?

Example:

PB0  TIM3_CH3 TIM3 PWM(1) GPIO(50)
PB1  TIM3_CH4 TIM3 PWM(2) GPIO(51) BIDIR
PE9  TIM1_CH1 TIM1 PWM(3) GPIO(52) BIDIR
PE11 TIM1_CH2 TIM1 PWM(4) GPIO(53)

Why not this?

PB0  TIM3_CH3 TIM3 PWM(1) GPIO(50) BIDIR
PB1  TIM3_CH4 TIM3 PWM(2) GPIO(51) BIDIR
PE9  TIM1_CH1 TIM1 PWM(3) GPIO(52) BIDIR
PE11 TIM1_CH2 TIM1 PWM(4) GPIO(53) BIDIR

Because the DMA channel is rotated between ch1/2 and ch3/4 on the same timer

Does that mean DMA channels are required for all of the individual timer channels (eg TIM3_CH3, TIM3_CH4, TIM1_CH1, TIM1_CH2) for bdshot to work, or would DMA channels for TIM1_UP and TIM3_UP sufficient?

Also, can inverted timers (eg TIM8_CH2N) be used for bdshot?

You need one DMA channel per timer pair. So TIM3_CH1 will also cover TIM3_CH2. You can use the same DMA channel for _UP and _CHn if the chip allows it, generally it won’t unless you are on H7

You can’t use complementary timers with bdshot

1 Like

So TIM3_CH1 and TIM3_CH2 can share a DMA channel even though they are on different streams?

That is, would bdshot require both DMA1 Stream4 Ch5 and DMA1 Stream5 Ch5, or could Stream5 be left open for USART2_RX use?

No, you use either one or the other. But if you look at the input capture spec you will see that one can cover both.

1 Like