mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-14 11:59:58 +03:00
F4 Dshot-DMAR initial working version
This commit is contained in:
parent
5594a5c5b9
commit
759e03c47e
8 changed files with 220 additions and 52 deletions
|
@ -109,9 +109,14 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
TIM_TypeDef *timer;
|
TIM_TypeDef *timer;
|
||||||
uint16_t timerDmaSources;
|
#if defined(USE_DSHOT_DMAR)
|
||||||
#ifdef USE_DSHOT_DMAR
|
#if !defined(USE_HAL_DRIVER)
|
||||||
|
DMA_Stream_TypeDef *dmaBurstRef;
|
||||||
|
uint16_t dmaBurstLength;
|
||||||
|
#endif
|
||||||
uint32_t dmaBurstBuffer[DSHOT_DMA_BUFFER_SIZE * 4];
|
uint32_t dmaBurstBuffer[DSHOT_DMA_BUFFER_SIZE * 4];
|
||||||
|
#else
|
||||||
|
uint16_t timerDmaSources;
|
||||||
#endif
|
#endif
|
||||||
} motorDmaTimer_t;
|
} motorDmaTimer_t;
|
||||||
|
|
||||||
|
@ -119,7 +124,9 @@ typedef struct {
|
||||||
ioTag_t ioTag;
|
ioTag_t ioTag;
|
||||||
const timerHardware_t *timerHardware;
|
const timerHardware_t *timerHardware;
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
|
#if !defined(USE_DSHOT_DMAR)
|
||||||
uint16_t timerDmaSource;
|
uint16_t timerDmaSource;
|
||||||
|
#endif
|
||||||
motorDmaTimer_t *timer;
|
motorDmaTimer_t *timer;
|
||||||
volatile bool requestTelemetry;
|
volatile bool requestTelemetry;
|
||||||
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7)
|
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7)
|
||||||
|
@ -127,11 +134,10 @@ typedef struct {
|
||||||
#else
|
#else
|
||||||
uint8_t dmaBuffer[DSHOT_DMA_BUFFER_SIZE];
|
uint8_t dmaBuffer[DSHOT_DMA_BUFFER_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#if defined(STM32F7)
|
#if defined(USE_HAL_DRIVER)
|
||||||
TIM_HandleTypeDef TimHandle;
|
TIM_HandleTypeDef TimHandle;
|
||||||
DMA_HandleTypeDef hdma_tim;
|
DMA_HandleTypeDef hdma_tim;
|
||||||
uint16_t timerDmaIndex;
|
uint16_t timerDmaIndex;
|
||||||
uint8_t timerIndex;
|
|
||||||
#endif
|
#endif
|
||||||
} motorDmaOutput_t;
|
} motorDmaOutput_t;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#ifdef USE_DSHOT
|
#ifdef USE_DSHOT
|
||||||
|
|
||||||
|
#include "build/debug.h"
|
||||||
|
|
||||||
#include "drivers/io.h"
|
#include "drivers/io.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#if defined(STM32F4)
|
#if defined(STM32F4)
|
||||||
|
@ -58,17 +60,34 @@ void pwmWriteDshotInt(uint8_t index, uint16_t value)
|
||||||
{
|
{
|
||||||
motorDmaOutput_t *const motor = &dmaMotors[index];
|
motorDmaOutput_t *const motor = &dmaMotors[index];
|
||||||
|
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
if (!motor->timerHardware || !motor->timerHardware->dmaTimUPRef) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!motor->timerHardware || !motor->timerHardware->dmaRef) {
|
if (!motor->timerHardware || !motor->timerHardware->dmaRef) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t packet = prepareDshotPacket(motor, value);
|
uint16_t packet = prepareDshotPacket(motor, value);
|
||||||
|
|
||||||
|
// XXX Replace this with striding loader in the next refactor
|
||||||
uint8_t bufferSize = loadDmaBuffer(motor, packet);
|
uint8_t bufferSize = loadDmaBuffer(motor, packet);
|
||||||
|
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
// Load channel data into burst buffer
|
||||||
|
uint8_t channelIndex = timerLookupChannelIndex(motor->timerHardware->channel);
|
||||||
|
// XXX This copy will be deleted once the striding loader is available
|
||||||
|
for (int i = 0; i < bufferSize; i++) {
|
||||||
|
motor->timer->dmaBurstBuffer[channelIndex + i * 4] = motor->dmaBuffer[i];
|
||||||
|
}
|
||||||
|
motor->timer->dmaBurstLength = bufferSize * 4;
|
||||||
|
#else
|
||||||
motor->timer->timerDmaSources |= motor->timerDmaSource;
|
motor->timer->timerDmaSources |= motor->timerDmaSource;
|
||||||
DMA_SetCurrDataCounter(motor->timerHardware->dmaRef, bufferSize);
|
DMA_SetCurrDataCounter(motor->timerHardware->dmaRef, bufferSize);
|
||||||
DMA_Cmd(motor->timerHardware->dmaRef, ENABLE);
|
DMA_Cmd(motor->timerHardware->dmaRef, ENABLE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void pwmCompleteDshotMotorUpdate(uint8_t motorCount)
|
void pwmCompleteDshotMotorUpdate(uint8_t motorCount)
|
||||||
|
@ -76,9 +95,16 @@ void pwmCompleteDshotMotorUpdate(uint8_t motorCount)
|
||||||
UNUSED(motorCount);
|
UNUSED(motorCount);
|
||||||
|
|
||||||
for (int i = 0; i < dmaMotorTimerCount; i++) {
|
for (int i = 0; i < dmaMotorTimerCount; i++) {
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
DMA_SetCurrDataCounter(dmaMotorTimers[i].dmaBurstRef, dmaMotorTimers[i].dmaBurstLength);
|
||||||
|
DMA_Cmd(dmaMotorTimers[i].dmaBurstRef, ENABLE);
|
||||||
|
TIM_DMAConfig(dmaMotorTimers[i].timer, TIM_DMABase_CCR1, TIM_DMABurstLength_4Transfers);
|
||||||
|
TIM_DMACmd(dmaMotorTimers[i].timer, TIM_DMA_Update, ENABLE);
|
||||||
|
#else
|
||||||
TIM_SetCounter(dmaMotorTimers[i].timer, 0);
|
TIM_SetCounter(dmaMotorTimers[i].timer, 0);
|
||||||
TIM_DMACmd(dmaMotorTimers[i].timer, dmaMotorTimers[i].timerDmaSources, ENABLE);
|
TIM_DMACmd(dmaMotorTimers[i].timer, dmaMotorTimers[i].timerDmaSources, ENABLE);
|
||||||
dmaMotorTimers[i].timerDmaSources = 0;
|
dmaMotorTimers[i].timerDmaSources = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,14 +112,35 @@ static void motor_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
|
||||||
{
|
{
|
||||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
|
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
|
||||||
motorDmaOutput_t * const motor = &dmaMotors[descriptor->userParam];
|
motorDmaOutput_t * const motor = &dmaMotors[descriptor->userParam];
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
DMA_Cmd(motor->timerHardware->dmaTimUPRef, DISABLE);
|
||||||
|
TIM_DMACmd(motor->timerHardware->tim, TIM_DMA_Update, DISABLE);
|
||||||
|
#else
|
||||||
DMA_Cmd(motor->timerHardware->dmaRef, DISABLE);
|
DMA_Cmd(motor->timerHardware->dmaRef, DISABLE);
|
||||||
TIM_DMACmd(motor->timerHardware->tim, motor->timerDmaSource, DISABLE);
|
TIM_DMACmd(motor->timerHardware->tim, motor->timerDmaSource, DISABLE);
|
||||||
|
#endif
|
||||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
|
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType, uint8_t output)
|
void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType, uint8_t output)
|
||||||
{
|
{
|
||||||
|
#if defined(STM32F3)
|
||||||
|
DMA_Channel_TypeDef *dmaRef = timerHardware->dmaRef;
|
||||||
|
#elif defined(STM32F4)
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
DMA_Stream_TypeDef *dmaRef = timerHardware->dmaTimUPRef;
|
||||||
|
#else
|
||||||
|
DMA_Stream_TypeDef *dmaRef = timerHardware->dmaRef;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error "No MCU specified in DSHOT"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (dmaRef == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||||
DMA_InitTypeDef DMA_InitStructure;
|
DMA_InitTypeDef DMA_InitStructure;
|
||||||
|
|
||||||
|
@ -138,9 +185,6 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
||||||
|
|
||||||
timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);
|
timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);
|
||||||
timerOCPreloadConfig(timer, timerHardware->channel, TIM_OCPreload_Enable);
|
timerOCPreloadConfig(timer, timerHardware->channel, TIM_OCPreload_Enable);
|
||||||
motor->timerDmaSource = timerDmaSource(timerHardware->channel);
|
|
||||||
motor->timer = &dmaMotorTimers[timerIndex];
|
|
||||||
motor->timer->timerDmaSources &= ~motor->timerDmaSource;
|
|
||||||
|
|
||||||
if (output & TIMER_OUTPUT_N_CHANNEL) {
|
if (output & TIMER_OUTPUT_N_CHANNEL) {
|
||||||
TIM_CCxNCmd(timer, timerHardware->channel, TIM_CCxN_Enable);
|
TIM_CCxNCmd(timer, timerHardware->channel, TIM_CCxN_Enable);
|
||||||
|
@ -154,25 +198,47 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
||||||
TIM_Cmd(timer, ENABLE);
|
TIM_Cmd(timer, ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(STM32F3)
|
motor->timer = &dmaMotorTimers[timerIndex];
|
||||||
DMA_Channel_TypeDef *dmaRef = timerHardware->dmaRef;
|
|
||||||
#elif defined(STM32F4)
|
|
||||||
DMA_Stream_TypeDef *dmaRef = timerHardware->dmaRef;
|
|
||||||
#else
|
|
||||||
#error "No MCU specified in DSHOT"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dmaRef == NULL) {
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
motor->timer->dmaBurstRef = dmaRef;
|
||||||
|
|
||||||
|
if (!configureTimer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex));
|
motor->timerDmaSource = timerDmaSource(timerHardware->channel);
|
||||||
dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
|
motor->timer->timerDmaSources &= ~motor->timerDmaSource;
|
||||||
|
#endif
|
||||||
|
|
||||||
DMA_Cmd(dmaRef, DISABLE);
|
DMA_Cmd(dmaRef, DISABLE);
|
||||||
DMA_DeInit(dmaRef);
|
DMA_DeInit(dmaRef);
|
||||||
|
|
||||||
DMA_StructInit(&DMA_InitStructure);
|
DMA_StructInit(&DMA_InitStructure);
|
||||||
|
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
dmaInit(timerHardware->dmaTimUPIrqHandler, OWNER_TIMUP, timerGetTIMNumber(timerHardware->tim));
|
||||||
|
dmaSetHandler(timerHardware->dmaTimUPIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
|
||||||
|
|
||||||
|
DMA_InitStructure.DMA_Channel = timerHardware->dmaTimUPChannel;
|
||||||
|
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)motor->timer->dmaBurstBuffer;
|
||||||
|
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||||
|
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
|
||||||
|
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||||
|
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||||
|
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||||
|
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&timerHardware->tim->DMAR;
|
||||||
|
DMA_InitStructure.DMA_BufferSize = (pwmProtocolType == PWM_TYPE_PROSHOT1000) ? PROSHOT_DMA_BUFFER_SIZE : DSHOT_DMA_BUFFER_SIZE; // XXX
|
||||||
|
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||||
|
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||||
|
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
|
||||||
|
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
|
||||||
|
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||||
|
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||||
|
|
||||||
|
#else // !USE_DSHOT_DMAR
|
||||||
|
dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex));
|
||||||
|
dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
|
||||||
|
|
||||||
#if defined(STM32F3)
|
#if defined(STM32F3)
|
||||||
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)motor->dmaBuffer;
|
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)motor->dmaBuffer;
|
||||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
||||||
|
@ -194,6 +260,9 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
||||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
|
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
|
||||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||||
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||||
|
#endif // USE_DSHOT_DMAR
|
||||||
|
|
||||||
|
// XXX Consolidate common settings in the next refactor
|
||||||
|
|
||||||
DMA_Init(dmaRef, &DMA_InitStructure);
|
DMA_Init(dmaRef, &DMA_InitStructure);
|
||||||
DMA_ITConfig(dmaRef, DMA_IT_TC, ENABLE);
|
DMA_ITConfig(dmaRef, DMA_IT_TC, ENABLE);
|
||||||
|
|
|
@ -71,10 +71,10 @@ void pwmWriteDshotInt(uint8_t index, uint16_t value)
|
||||||
uint8_t channel_index = motor->timerHardware->channel / TIM_CHANNEL_2;
|
uint8_t channel_index = motor->timerHardware->channel / TIM_CHANNEL_2;
|
||||||
// load channel data into burst buffer
|
// load channel data into burst buffer
|
||||||
for(int i = 0; i < bufferSize; i++) {
|
for(int i = 0; i < bufferSize; i++) {
|
||||||
dmaMotorTimers[motor->timerIndex].dmaBurstBuffer[channel_index + i * 4] = motor->dmaBuffer[i];
|
motor->timer->dmaBurstBuffer[channel_index + i * 4] = motor->dmaBuffer[i];
|
||||||
}
|
}
|
||||||
if(HAL_DMA_STATE_READY == motor->TimHandle.hdma[motor->timerDmaIndex]->State) {
|
if(HAL_DMA_STATE_READY == motor->TimHandle.hdma[motor->timerDmaIndex]->State) {
|
||||||
HAL_DMA_Start_IT(motor->TimHandle.hdma[motor->timerDmaIndex], (uint32_t)dmaMotorTimers[motor->timerIndex].dmaBurstBuffer, (uint32_t)&motor->TimHandle.Instance->DMAR, bufferSize * 4);
|
HAL_DMA_Start_IT(motor->TimHandle.hdma[motor->timerDmaIndex], (uint32_t)motor->timer->dmaBurstBuffer, (uint32_t)&motor->TimHandle.Instance->DMAR, bufferSize * 4);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (DMA_SetCurrDataCounter(&motor->TimHandle, motor->timerHardware->channel, motor->dmaBuffer, bufferSize) != HAL_OK) {
|
if (DMA_SetCurrDataCounter(&motor->TimHandle, motor->timerHardware->channel, motor->dmaBuffer, bufferSize) != HAL_OK) {
|
||||||
|
@ -125,14 +125,22 @@ static void motor_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor)
|
||||||
|
|
||||||
void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType, uint8_t output)
|
void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType, uint8_t output)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
if (timerHardware->dmaTimUPRef == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (timerHardware->dmaRef == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
motorDmaOutput_t * const motor = &dmaMotors[motorIndex];
|
motorDmaOutput_t * const motor = &dmaMotors[motorIndex];
|
||||||
motor->timerHardware = timerHardware;
|
motor->timerHardware = timerHardware;
|
||||||
|
|
||||||
TIM_TypeDef *timer = timerHardware->tim;
|
TIM_TypeDef *timer = timerHardware->tim;
|
||||||
const IO_t motorIO = IOGetByTag(timerHardware->tag);
|
const IO_t motorIO = IOGetByTag(timerHardware->tag);
|
||||||
|
|
||||||
const uint8_t timerIndex = getTimerIndex(timer);
|
|
||||||
|
|
||||||
IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN), timerHardware->alternateFunction);
|
IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN), timerHardware->alternateFunction);
|
||||||
|
|
||||||
__DMA1_CLK_ENABLE();
|
__DMA1_CLK_ENABLE();
|
||||||
|
@ -146,15 +154,15 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
||||||
motor->TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
motor->TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||||
motor->TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
motor->TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||||
motor->TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
motor->TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||||
|
|
||||||
if (HAL_TIM_PWM_Init(&motor->TimHandle) != HAL_OK) {
|
if (HAL_TIM_PWM_Init(&motor->TimHandle) != HAL_OK) {
|
||||||
/* Initialization Error */
|
/* Initialization Error */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DSHOT_DMAR
|
motor->timer = &dmaMotorTimers[getTimerIndex(timer)];
|
||||||
motor->timerDmaIndex = TIM_DMA_ID_UPDATE;
|
|
||||||
/* Set the parameters to be configured */
|
/* Set the common dma handle parameters to be configured */
|
||||||
motor->hdma_tim.Init.Channel = timerHardware->dmaTimUPChannel;
|
|
||||||
motor->hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
motor->hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||||
motor->hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
|
motor->hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||||
motor->hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
|
motor->hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
|
||||||
|
@ -162,17 +170,19 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
||||||
motor->hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
motor->hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
||||||
motor->hdma_tim.Init.Mode = DMA_NORMAL;
|
motor->hdma_tim.Init.Mode = DMA_NORMAL;
|
||||||
motor->hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
|
motor->hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
|
||||||
motor->hdma_tim.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
|
||||||
motor->hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
motor->hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
||||||
motor->hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
|
motor->hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
|
||||||
motor->hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
motor->hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
||||||
|
|
||||||
|
#ifdef USE_DSHOT_DMAR
|
||||||
|
motor->timerDmaIndex = TIM_DMA_ID_UPDATE;
|
||||||
|
/* Set the DMAR specific dma handle parameters to be configured */
|
||||||
|
motor->hdma_tim.Init.Channel = timerHardware->dmaTimUPChannel;
|
||||||
|
motor->hdma_tim.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
||||||
|
|
||||||
/* Set hdma_tim instance */
|
/* Set hdma_tim instance */
|
||||||
if (timerHardware->dmaTimUPRef == NULL) {
|
|
||||||
/* Initialization Error */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motor->hdma_tim.Instance = timerHardware->dmaTimUPRef;
|
motor->hdma_tim.Instance = timerHardware->dmaTimUPRef;
|
||||||
|
|
||||||
/* Link hdma_tim to hdma[x] (channelx) */
|
/* Link hdma_tim to hdma[x] (channelx) */
|
||||||
__HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim);
|
__HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim);
|
||||||
|
|
||||||
|
@ -180,29 +190,15 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
||||||
dmaSetHandler(timerHardware->dmaTimUPIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
|
dmaSetHandler(timerHardware->dmaTimUPIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
|
||||||
#else
|
#else
|
||||||
motor->timerDmaIndex = timerDmaIndex(timerHardware->channel);
|
motor->timerDmaIndex = timerDmaIndex(timerHardware->channel);
|
||||||
motor->timer = &dmaMotorTimers[timerIndex];
|
motor->timer->timerDmaSources |= timerDmaSource(timerHardware->channel);
|
||||||
dmaMotorTimers[timerIndex].timerDmaSources |= timerDmaSource(timerHardware->channel);
|
|
||||||
|
|
||||||
/* Set the parameters to be configured */
|
/* Set the non-DMAR specific dma handle parameters to be configured */
|
||||||
motor->hdma_tim.Init.Channel = timerHardware->dmaChannel;
|
motor->hdma_tim.Init.Channel = timerHardware->dmaChannel;
|
||||||
motor->hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
|
||||||
motor->hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
|
|
||||||
motor->hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
|
|
||||||
motor->hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
|
||||||
motor->hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
|
||||||
motor->hdma_tim.Init.Mode = DMA_NORMAL;
|
|
||||||
motor->hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
|
|
||||||
motor->hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
motor->hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||||
motor->hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
|
||||||
motor->hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
|
|
||||||
motor->hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
|
||||||
|
|
||||||
/* Set hdma_tim instance */
|
/* Set hdma_tim instance */
|
||||||
if (timerHardware->dmaRef == NULL) {
|
|
||||||
/* Initialization Error */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motor->hdma_tim.Instance = timerHardware->dmaRef;
|
motor->hdma_tim.Instance = timerHardware->dmaRef;
|
||||||
|
|
||||||
/* Link hdma_tim to hdma[x] (channelx) */
|
/* Link hdma_tim to hdma[x] (channelx) */
|
||||||
__HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim);
|
__HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim);
|
||||||
|
|
||||||
|
@ -262,7 +258,7 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
motor->timerIndex = timerIndex;
|
|
||||||
LL_TIM_CC_EnableChannel(motor->timerHardware->tim, channels);
|
LL_TIM_CC_EnableChannel(motor->timerHardware->tim, channels);
|
||||||
#else
|
#else
|
||||||
if (output & TIMER_OUTPUT_N_CHANNEL) {
|
if (output & TIMER_OUTPUT_N_CHANNEL) {
|
||||||
|
|
|
@ -193,11 +193,85 @@ TIM_TypeDef * const usedTimers[USED_TIMER_COUNT] = {
|
||||||
#undef _DEF
|
#undef _DEF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Map timer index to timer number (Straight copy of usedTimers array)
|
||||||
|
const int8_t timerNumbers[USED_TIMER_COUNT] = {
|
||||||
|
#define _DEF(i) i
|
||||||
|
|
||||||
|
#if USED_TIMERS & TIM_N(1)
|
||||||
|
_DEF(1),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(2)
|
||||||
|
_DEF(2),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(3)
|
||||||
|
_DEF(3),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(4)
|
||||||
|
_DEF(4),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(5)
|
||||||
|
_DEF(5),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(6)
|
||||||
|
_DEF(6),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(7)
|
||||||
|
_DEF(7),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(8)
|
||||||
|
_DEF(8),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(9)
|
||||||
|
_DEF(9),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(10)
|
||||||
|
_DEF(10),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(11)
|
||||||
|
_DEF(11),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(12)
|
||||||
|
_DEF(12),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(13)
|
||||||
|
_DEF(13),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(14)
|
||||||
|
_DEF(14),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(15)
|
||||||
|
_DEF(15),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(16)
|
||||||
|
_DEF(16),
|
||||||
|
#endif
|
||||||
|
#if USED_TIMERS & TIM_N(17)
|
||||||
|
_DEF(17),
|
||||||
|
#endif
|
||||||
|
#undef _DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
int8_t timerGetTIMNumber(const TIM_TypeDef *tim)
|
||||||
|
{
|
||||||
|
uint8_t index = lookupTimerIndex(tim);
|
||||||
|
|
||||||
|
if (index < USED_TIMER_COUNT) {
|
||||||
|
return timerNumbers[index];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint8_t lookupChannelIndex(const uint16_t channel)
|
static inline uint8_t lookupChannelIndex(const uint16_t channel)
|
||||||
{
|
{
|
||||||
return channel >> 2;
|
return channel >> 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t timerLookupChannelIndex(const uint16_t channel)
|
||||||
|
{
|
||||||
|
return lookupChannelIndex(channel);
|
||||||
|
}
|
||||||
|
|
||||||
rccPeriphTag_t timerRCC(TIM_TypeDef *tim)
|
rccPeriphTag_t timerRCC(TIM_TypeDef *tim)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < HARDWARE_TIMER_DEFINITION_COUNT; i++) {
|
for (int i = 0; i < HARDWARE_TIMER_DEFINITION_COUNT; i++) {
|
||||||
|
|
|
@ -104,7 +104,7 @@ typedef struct timerHardware_s {
|
||||||
DMA_Channel_TypeDef *dmaRef;
|
DMA_Channel_TypeDef *dmaRef;
|
||||||
#endif
|
#endif
|
||||||
uint8_t dmaIrqHandler;
|
uint8_t dmaIrqHandler;
|
||||||
#if defined(STM32F7)
|
#if defined(STM32F4) || defined(STM32F7)
|
||||||
// TIMUP
|
// TIMUP
|
||||||
DMA_Stream_TypeDef *dmaTimUPRef;
|
DMA_Stream_TypeDef *dmaTimUPRef;
|
||||||
uint32_t dmaTimUPChannel;
|
uint32_t dmaTimUPChannel;
|
||||||
|
@ -212,3 +212,4 @@ uint16_t timerGetPrescalerByDesiredMhz(TIM_TypeDef *tim, uint16_t mhz);
|
||||||
uint16_t timerGetPeriodByPrescaler(TIM_TypeDef *tim, uint16_t prescaler, uint32_t hz);
|
uint16_t timerGetPeriodByPrescaler(TIM_TypeDef *tim, uint16_t prescaler, uint32_t hz);
|
||||||
|
|
||||||
int8_t timerGetTIMNumber(const TIM_TypeDef *tim);
|
int8_t timerGetTIMNumber(const TIM_TypeDef *tim);
|
||||||
|
uint8_t timerLookupChannelIndex(const uint16_t channel);
|
||||||
|
|
|
@ -374,6 +374,11 @@
|
||||||
DEF_TIM_DMA_STREAM(dmaopt, TCH_## tim ## _ ## chan), \
|
DEF_TIM_DMA_STREAM(dmaopt, TCH_## tim ## _ ## chan), \
|
||||||
DEF_TIM_DMA_CHANNEL(dmaopt, TCH_## tim ## _ ## chan), \
|
DEF_TIM_DMA_CHANNEL(dmaopt, TCH_## tim ## _ ## chan), \
|
||||||
DEF_TIM_DMA_HANDLER(dmaopt, TCH_## tim ## _ ## chan) \
|
DEF_TIM_DMA_HANDLER(dmaopt, TCH_## tim ## _ ## chan) \
|
||||||
|
), \
|
||||||
|
DEF_TIM_DMA_COND( \
|
||||||
|
DEF_TIM_DMA_STREAM(0, TCH_## tim ## _UP), \
|
||||||
|
DEF_TIM_DMA_CHANNEL(0, TCH_## tim ## _UP), \
|
||||||
|
DEF_TIM_DMA_HANDLER(0, TCH_## tim ## _UP) \
|
||||||
) \
|
) \
|
||||||
} \
|
} \
|
||||||
/**/
|
/**/
|
||||||
|
@ -447,6 +452,22 @@
|
||||||
|
|
||||||
#define DEF_TIM_DMA__BTCH_TIM14_CH1 NONE
|
#define DEF_TIM_DMA__BTCH_TIM14_CH1 NONE
|
||||||
|
|
||||||
|
// TIM_UP table
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM1_UP D(2, 5, 6)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM2_UP D(1, 7, 3)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM3_UP D(1, 2, 5)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM4_UP D(1, 6, 2)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM5_UP D(1, 0, 6)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM6_UP D(1, 1, 7)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM7_UP D(1, 4, 1)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM8_UP D(2, 1, 7)
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM9_UP NONE
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM10_UP NONE
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM11_UP NONE
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM12_UP NONE
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM13_UP NONE
|
||||||
|
#define DEF_TIM_DMA__BTCH_TIM14_UP NONE
|
||||||
|
|
||||||
#elif defined(STM32F7)
|
#elif defined(STM32F7)
|
||||||
#define DEF_TIM(tim, chan, pin, flags, out, dmaopt) { \
|
#define DEF_TIM(tim, chan, pin, flags, out, dmaopt) { \
|
||||||
tim, \
|
tim, \
|
||||||
|
|
|
@ -9,4 +9,4 @@ TARGET_SRC = \
|
||||||
drivers/barometer/barometer_ms5611.c \
|
drivers/barometer/barometer_ms5611.c \
|
||||||
drivers/compass/compass_hmc5883l.c \
|
drivers/compass/compass_hmc5883l.c \
|
||||||
drivers/max7456.c
|
drivers/max7456.c
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
|
|
||||||
#ifdef STM32F4
|
#ifdef STM32F4
|
||||||
#define USE_DSHOT
|
#define USE_DSHOT
|
||||||
|
#define USE_DSHOT_DMAR
|
||||||
#define USE_ESC_SENSOR
|
#define USE_ESC_SENSOR
|
||||||
#define I2C3_OVERCLOCK true
|
#define I2C3_OVERCLOCK true
|
||||||
#define USE_TELEMETRY_IBUS
|
#define USE_TELEMETRY_IBUS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue