2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
23 #include "common/time.h"
24 #include "drivers/motor.h"
26 #define USE_DMA_REGISTER_CACHE
28 #define DEBUG_COUNT_INTERRUPT
29 #define DEBUG_MONITOR_PACER
31 #define MAX_SUPPORTED_MOTOR_PORTS 4 // Max direct dshot port groups, limited by number of usable timer (TIM1 and TIM8) x number of channels per timer (4), 3 is enough to cover motor pins on GPIOA, GPIOB and GPIOC.
33 #define DSHOT_BITBANG_TELEMETRY_OVER_SAMPLE 3
35 #define DSHOT_BITBANG_DIRECTION_OUTPUT 0
36 #define DSHOT_BITBANG_DIRECTION_INPUT 1
38 #define DSHOT_BITBANG_INVERTED true
39 #define DSHOT_BITBANG_NONINVERTED false
41 // XXX MOTOR_xSHOTyyyy_HZ is not usable as generic frequency for timers.
42 // XXX Trying to fiddle with constants here.
44 // Symbol rate [symbol/sec]
45 #define MOTOR_DSHOT600_SYMBOL_RATE (600 * 1000)
46 #define MOTOR_DSHOT300_SYMBOL_RATE (300 * 1000)
47 #define MOTOR_DSHOT150_SYMBOL_RATE (150 * 1000)
49 #define MOTOR_DSHOT_SYMBOL_TIME_NS(rate) (1000000000 / (rate))
51 #define MOTOR_DSHOT_BIT_PER_SYMBOL 1
53 #define MOTOR_DSHOT_STATE_PER_SYMBOL 3 // Initial high, 0/1, low
55 #define MOTOR_DSHOT_FRAME_BITS 16
57 #define MOTOR_DSHOT_FRAME_TIME_NS(rate) ((MOTOR_DSHOT_FRAME_BITS / MOTOR_DSHOT_BIT_PER_SYMBOL) * MOTOR_DSHOT_SYMBOL_TIME_NS(rate))
59 #define MOTOR_DSHOT_TELEMETRY_WINDOW_US (30000 + MOTOR_DSHOT_FRAME_TIME_NS(rate) * (1.1)) / 1000
61 #define MOTOR_DSHOT_CHANGE_INTERVAL_NS(rate) (MOTOR_DSHOT_SYMBOL_TIME_NS(rate) / MOTOR_DSHOT_STATE_PER_SYMBOL)
63 #define MOTOR_DSHOT_GCR_CHANGE_INTERVAL_NS(rate) (MOTOR_DSHOT_CHANGE_INTERVAL_NS(rate) * 5 / 4)
65 #define MOTOR_DSHOT_BUF_LENGTH ((MOTOR_DSHOT_FRAME_BITS / MOTOR_DSHOT_BIT_PER_SYMBOL) * MOTOR_DSHOT_STATE_PER_SYMBOL)
66 #ifdef USE_DSHOT_CACHE_MGMT
67 // MOTOR_DSHOT_BUF_LENGTH is multiples of uint32_t
68 // Number of bytes required for buffer
69 #define MOTOR_DSHOT_BUF_BYTES (MOTOR_DSHOT_BUF_LENGTH * sizeof(uint32_t))
70 // Number of bytes required to cache align buffer
71 #define MOTOR_DSHOT_BUF_CACHE_ALIGN_BYTES ((MOTOR_DSHOT_BUF_BYTES + 0x20) & ~0x1f)
72 // Size of array to create a cache aligned buffer
73 #define MOTOR_DSHOT_BUF_CACHE_ALIGN_LENGTH (MOTOR_DSHOT_BUF_CACHE_ALIGN_BYTES / sizeof(uint32_t))
75 #define MOTOR_DSHOT_BUF_CACHE_ALIGN_LENGTH MOTOR_DSHOT_BUF_LENGTH
79 #define BB_GPIO_PULLDOWN GPIO_PULLDOWN
80 #define BB_GPIO_PULLUP GPIO_PULLUP
82 #define BB_GPIO_PULLDOWN GPIO_PuPd_DOWN
83 #define BB_GPIO_PULLUP GPIO_PuPd_UP
86 #ifdef USE_DMA_REGISTER_CACHE
87 typedef struct dmaRegCache_s
{
88 #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
94 #elif defined(STM32G4)
100 #error No MCU dependent code here
107 typedef struct bbPacer_s
{
112 // Per GPIO port and timer channel
114 typedef struct bbPort_s
{
117 const timerHardware_t
*timhw
;
118 #ifdef USE_HAL_DRIVER
124 dmaResource_t
*dmaResource
; // DMA resource for this port & timer channel
125 uint32_t dmaChannel
; // DMA channel or peripheral request
129 #ifdef USE_DMA_REGISTER_CACHE
130 // DMA resource register cache
131 dmaRegCache_t dmaRegOutput
;
132 dmaRegCache_t dmaRegInput
;
135 // For direct manipulation of GPIO_MODER register
136 uint32_t gpioModeMask
;
137 uint32_t gpioModeInput
;
138 uint32_t gpioModeOutput
;
141 uint32_t gpioIdleBSRR
;
143 #ifdef USE_HAL_DRIVER
144 LL_TIM_InitTypeDef timeBaseInit
;
146 TIM_TimeBaseInitTypeDef timeBaseInit
;
151 #ifdef USE_HAL_DRIVER
152 LL_DMA_InitTypeDef outputDmaInit
;
154 DMA_InitTypeDef outputDmaInit
;
156 uint32_t *portOutputBuffer
;
157 uint32_t portOutputCount
;
161 #ifdef USE_HAL_DRIVER
162 LL_DMA_InitTypeDef inputDmaInit
;
164 DMA_InitTypeDef inputDmaInit
;
166 uint16_t *portInputBuffer
;
167 uint32_t portInputCount
;
171 #ifdef DEBUG_COUNT_INTERRUPT
175 resourceOwner_t owner
;
180 typedef struct bbMotor_s
{
181 dshotProtocolControl_t protocolControl
;
182 int pinIndex
; // pinIndex of this motor output within a group that bbPort points to
184 IO_t io
; // IO_t for this output
192 #define MAX_MOTOR_PACERS 4
193 extern FAST_DATA_ZERO_INIT bbPacer_t bbPacers
[MAX_MOTOR_PACERS
]; // TIM1 or TIM8
194 extern FAST_DATA_ZERO_INIT
int usedMotorPacers
;
196 extern FAST_DATA_ZERO_INIT bbPort_t bbPorts
[MAX_SUPPORTED_MOTOR_PORTS
];
197 extern FAST_DATA_ZERO_INIT
int usedMotorPorts
;
199 extern FAST_DATA_ZERO_INIT bbMotor_t bbMotors
[MAX_SUPPORTED_MOTORS
];
201 extern uint8_t bbPuPdMode
;
204 // Note that we are not sharing input and output buffers,
205 // as output buffer is only modified for middle bits
207 // DMA output buffer:
208 // DShot requires 3 [word/bit] * 16 [bit] = 48 [word]
209 extern uint32_t bbOutputBuffer
[MOTOR_DSHOT_BUF_CACHE_ALIGN_LENGTH
* MAX_SUPPORTED_MOTOR_PORTS
];
212 // (30us + <frame time> + <slack>) / <input sampling clock period>
213 // <frame time> = <DShot symbol time> * 16
214 // Temporary size for DS600
215 // <frame time> = 26us
216 // <sampling period> = 0.44us
218 // (30 + 26 + 3) / 0.44 = 134
219 // In some cases this was not enough, so we add 6 extra samples
220 #define DSHOT_BB_PORT_IP_BUF_LENGTH 140
221 #ifdef USE_DSHOT_CACHE_MGMT
222 // Each sample is a uint16_t
223 // Number of bytes required for buffer
224 #define DSHOT_BB_PORT_IP_BUF_BYTES (DSHOT_BB_PORT_IP_BUF_LENGTH * sizeof(uint16_t))
225 // Number of bytes required to cache align buffer
226 #define DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_BYTES ((DSHOT_BB_PORT_IP_BUF_BYTES + 0x20) & ~0x1f)
227 // Size of array to create a cache aligned buffer
228 #define DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_LENGTH (DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_BYTES / sizeof(uint16_t))
230 #define DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_LENGTH DSHOT_BB_PORT_IP_BUF_LENGTH
232 extern uint16_t bbInputBuffer
[DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_LENGTH
* MAX_SUPPORTED_MOTOR_PORTS
];
234 void bbGpioSetup(bbMotor_t
*bbMotor
);
235 void bbTimerChannelInit(bbPort_t
*bbPort
);
236 void bbDMAPreconfigure(bbPort_t
*bbPort
, uint8_t direction
);
237 void bbDMAIrqHandler(dmaChannelDescriptor_t
*descriptor
);
238 void bbSwitchToOutput(bbPort_t
* bbPort
);
239 void bbSwitchToInput(bbPort_t
* bbPort
);
241 void bbTIM_TimeBaseInit(bbPort_t
*bbPort
, uint16_t period
);
242 void bbTIM_DMACmd(TIM_TypeDef
* TIMx
, uint16_t TIM_DMASource
, FunctionalState NewState
);
243 void bbDMA_ITConfig(bbPort_t
*bbPort
);
244 void bbDMA_Cmd(bbPort_t
*bbPort
, FunctionalState NewState
);
245 int bbDMA_Count(bbPort_t
*bbPort
);