67 #define DMASHOT_MESSAGE_WIDTH 16
68 #define DMASHOT_MESSAGE_PAUSE 1
69 #define DMASHOT_STM32_BUFFER (DMASHOT_MESSAGE_PAUSE + DMASHOT_MESSAGE_WIDTH + DMASHOT_MESSAGE_PAUSE)
73 #define DSHOT_DUTY_CYCLE_0 36
74 #define DSHOT_DUTY_CYCLE_1 74
76 #define TIMC_TO_INDEX(c) ((c)>>2)
85 return (s_timer->
dma->
timer == TIM2 || s_timer->
dma->
timer == TIM5 ?
false :
true);
93 return (channels >> 2) + 1;
112 memset(servo_timers, 0,
sizeof(servo_timers) * MAX_TIMERS);
115 if (servo_timers[
i]) {
157 bool telem_bit =
false;
160 if ((throttle > 0) && (throttle < 48)) {
174 ((throttle >> 4 ) & 0xf) ^
175 ((throttle >> 8 ) & 0xf) ^
176 ((throttle >> 12) & 0xf);
180 int addr =
i * channels + shift;
193 if (!dmashot_cfg || !servo_timers)
216 if (servo_timers[
i] && servo_timers[
i]->
dma->
timer == timer) {
217 s_timer = servo_timers[
i];
226 if (!servo_timers[
i]) {
231 memset(s_timer, 0,
sizeof(*s_timer));
234 servo_timers[
i] = s_timer;
245 s_timer->
dma = dma_config;
253 if (!dmashot_cfg || !servo_timers)
281 if (!dmashot_cfg || !servo_timers)
303 for (
int j = 0;
j < 4;
j++) {
312 GPIO_InitTypeDef gpio_cfg = servo_channel->
pin.
init;
313 gpio_cfg.GPIO_Speed = GPIO_High_Speed;
314 GPIO_Init(servo_channel->
pin.
gpio, &gpio_cfg);
325 TIM_TimeBaseInitTypeDef timerdef;
327 TIM_Cmd(timer, DISABLE);
329 TIM_TimeBaseStructInit(&timerdef);
331 timerdef.TIM_Prescaler = 0;
332 timerdef.TIM_Period = sysclock / dshot_freq;
333 timerdef.TIM_ClockDivision = TIM_CKD_DIV1;
334 timerdef.TIM_RepetitionCounter = 0;
335 timerdef.TIM_CounterMode = TIM_CounterMode_Up;
337 TIM_TimeBaseInit(timer, &timerdef);
340 for(
int i = s_timer->
low_channel; i <= s_timer->high_channel;
i+=4)
345 TIM_OC1Init(timer, ocinit);
346 TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
349 TIM_OC2Init(timer, ocinit);
350 TIM_OC2PreloadConfig(timer, TIM_OCPreload_Enable);
353 TIM_OC3Init(timer, ocinit);
354 TIM_OC3PreloadConfig(timer, TIM_OCPreload_Enable);
357 TIM_OC4Init(timer, ocinit);
358 TIM_OC4PreloadConfig(timer, TIM_OCPreload_Enable);
364 TIM_SelectOnePulseMode(timer, TIM_OPMode_Repetitive);
402 while (DMA_GetCmdStatus(s_timer->
dma->
stream) == ENABLE) ;
407 DMA_StructInit(&dma);
410 dma.DMA_Memory0BaseAddr = s_timer->
buffer.
ptr;
416 dma.DMA_PeripheralBaseAddr = (uint32_t)(&s_timer->
dma->
timer->DMAR);
420 dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
421 dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
423 dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
424 dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
427 dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
428 dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
430 dma.DMA_DIR = DMA_DIR_MemoryToPeripheral;
431 dma.DMA_Mode = DMA_Mode_Normal;
435 dma.DMA_Priority = DMA_Priority_VeryHigh;
436 dma.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
437 dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
439 dma.DMA_FIFOMode = DMA_FIFOMode_Enable;
440 dma.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
445 DMA_ITConfig(s_timer->
dma->
stream, DMA_IT_TC, DISABLE);
458 memset((
void*)ptr, 0, size);
461 uint32_t shift = 16 - (ptr % 16);
462 if(shift != 16) ptr += shift;
505 while (DMA_GetCmdStatus(s_timer->
dma->
stream) == ENABLE) ;
515 TIM_DMACmd(s_timer->
dma->
timer, TIM_DMA_Update, DISABLE);
518 TIM_Cmd(s_timer->
dma->
timer, DISABLE);
519 TIM_SetCounter(s_timer->
dma->
timer, 0);
536 TIM_Cmd(s_timer->
dma->
timer, ENABLE);
541 TIM_DMAConfig(s_timer->
dma->
timer, TIM_DMABase_CCR1 + offset, transfers << 8);
543 TIM_DMACmd(s_timer->
dma->
timer, TIM_DMA_Update, ENABLE);
544 TIM_Cmd(s_timer->
dma->
timer, ENABLE);
554 if (!dmashot_cfg || !servo_timers)
559 if (s_timer && s_timer->
sysclock)
return true;
567 return dmashot_cfg != NULL;
#define DMASHOT_STM32_BUFFER
static void PIOS_DMAShot_DMASetup(struct servo_timer *s_timer)
const struct pios_dmashot_timer_cfg * timer_cfg
Main PiOS header to include all the compiled in PiOS options.
void PIOS_DMAShot_Prepare()
Makes sure the DMAShot driver has allocated all internal structs.
struct usb_configuration_desc config
void PIOS_DMAShot_InitializeTimers(TIM_OCInitTypeDef *ocinit)
Initializes and configures the registered timers for DMAShot operation.
static uint32_t PIOS_DMAShot_AllocateBuffer(uint16_t size)
void PIOS_DMAShot_Validate()
Validates any timer and servo registrations.
TIM_TypeDef * master_timer
void * PIOS_malloc(size_t size)
bool PIOS_DMAShot_RegisterTimer(TIM_TypeDef *timer, uint32_t clockrate, uint32_t dshot_freq)
Tells the DMAShot driver about a timer that needs to be set up.
bool PIOS_DMAShot_RegisterServo(const struct pios_tim_channel *servo_channel)
Tells the DMAShot driver about a servo that needs to be set up.
void * PIOS_malloc_no_dma(size_t size)
static struct servo_timer * PIOS_DMAShot_GetServoTimer(const struct pios_tim_channel *servo_channel)
DMA_Stream_TypeDef * stream
bool PIOS_DMAShot_IsConfigured()
Checks whether DMAShot has been configured.
Configuration struct holding all timer configurations.
Configuration struct to assign a DMA channel and stream to a timer, and optionally specify a master t...
void PIOS_DMAShot_InitializeGPIOs()
Initializes the GPIO on the registered servos for DMAShot operation.
const struct pios_dmashot_timer_cfg * dma
static int PIOS_DMAShot_GetNumChannels(struct servo_timer *timer)
static void PIOS_DMAShot_TimerSetup(struct servo_timer *s_timer, uint32_t sysclock, uint32_t dshot_freq, TIM_OCInitTypeDef *ocinit, bool master)
void PIOS_DMAShot_InitializeDMAs()
Initializes and configures the known DMA channels for DMAShot operation.
#define DMASHOT_MESSAGE_PAUSE
#define DSHOT_DUTY_CYCLE_0
#define DSHOT_DUTY_CYCLE_1
#define DMASHOT_MESSAGE_WIDTH
void PIOS_DMAShot_WriteValue(const struct pios_tim_channel *servo_channel, uint16_t throttle)
Sets the throttle value of a specific servo.
struct servo_timer ** servo_timers
bool PIOS_DMAShot_IsReady()
Checks whether DMAShot is ready for use (i.e. at least one DMA configured timer). ...
const struct pios_dmashot_cfg * dmashot_cfg
static bool PIOS_DMAShot_HalfWord(struct servo_timer *s_timer)
const struct pios_tim_channel * servo_channels[4]
void PIOS_DMAShot_Init(const struct pios_dmashot_cfg *config)
Initializes the DMAShot driver by loading the configuration.
#define PIOS_Assert(test)
void PIOS_DMAShot_TriggerUpdate()
Triggers the configured DMA channels to fire and send throttle values to the timer DMAR and optional ...