mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-20 23:05:19 +03:00
Merge pull request #4843 from jflyper/bfdev-f4-dmar
F4 Dshot-DMAR first cut
This commit is contained in:
commit
809a7d6b41
7 changed files with 192 additions and 19 deletions
|
@ -109,9 +109,14 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
TIM_TypeDef *timer;
|
||||
uint16_t timerDmaSources;
|
||||
#ifdef USE_DSHOT_DMAR
|
||||
#if defined(USE_DSHOT_DMAR)
|
||||
#if !defined(USE_HAL_DRIVER)
|
||||
DMA_Stream_TypeDef *dmaBurstRef;
|
||||
uint16_t dmaBurstLength;
|
||||
#endif
|
||||
uint32_t dmaBurstBuffer[DSHOT_DMA_BUFFER_SIZE * 4];
|
||||
#else
|
||||
uint16_t timerDmaSources;
|
||||
#endif
|
||||
} motorDmaTimer_t;
|
||||
|
||||
|
@ -119,7 +124,9 @@ typedef struct {
|
|||
ioTag_t ioTag;
|
||||
const timerHardware_t *timerHardware;
|
||||
uint16_t value;
|
||||
#if !defined(USE_DSHOT_DMAR)
|
||||
uint16_t timerDmaSource;
|
||||
#endif
|
||||
motorDmaTimer_t *timer;
|
||||
volatile bool requestTelemetry;
|
||||
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7)
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#ifdef USE_DSHOT
|
||||
|
||||
#include "build/debug.h"
|
||||
|
||||
#include "drivers/io.h"
|
||||
#include "timer.h"
|
||||
#if defined(STM32F4)
|
||||
|
@ -58,17 +60,34 @@ void pwmWriteDshotInt(uint8_t index, uint16_t value)
|
|||
{
|
||||
motorDmaOutput_t *const motor = &dmaMotors[index];
|
||||
|
||||
#ifdef USE_DSHOT_DMAR
|
||||
if (!motor->timerHardware || !motor->timerHardware->dmaTimUPRef) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!motor->timerHardware || !motor->timerHardware->dmaRef) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t packet = prepareDshotPacket(motor, value);
|
||||
|
||||
// XXX Replace this with striding loader in the next refactor
|
||||
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;
|
||||
DMA_SetCurrDataCounter(motor->timerHardware->dmaRef, bufferSize);
|
||||
DMA_Cmd(motor->timerHardware->dmaRef, ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pwmCompleteDshotMotorUpdate(uint8_t motorCount)
|
||||
|
@ -76,9 +95,16 @@ void pwmCompleteDshotMotorUpdate(uint8_t motorCount)
|
|||
UNUSED(motorCount);
|
||||
|
||||
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_DMACmd(dmaMotorTimers[i].timer, dmaMotorTimers[i].timerDmaSources, ENABLE);
|
||||
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)) {
|
||||
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);
|
||||
TIM_DMACmd(motor->timerHardware->tim, motor->timerDmaSource, DISABLE);
|
||||
#endif
|
||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
|
||||
|
@ -138,9 +185,6 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
|||
|
||||
timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
#if defined(STM32F3)
|
||||
DMA_Channel_TypeDef *dmaRef = timerHardware->dmaRef;
|
||||
#elif defined(STM32F4)
|
||||
DMA_Stream_TypeDef *dmaRef = timerHardware->dmaRef;
|
||||
#else
|
||||
#error "No MCU specified in DSHOT"
|
||||
#endif
|
||||
motor->timer = &dmaMotorTimers[timerIndex];
|
||||
|
||||
if (dmaRef == NULL) {
|
||||
#ifdef USE_DSHOT_DMAR
|
||||
motor->timer->dmaBurstRef = dmaRef;
|
||||
|
||||
if (!configureTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex));
|
||||
dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
|
||||
#else
|
||||
motor->timerDmaSource = timerDmaSource(timerHardware->channel);
|
||||
motor->timer->timerDmaSources &= ~motor->timerDmaSource;
|
||||
#endif
|
||||
|
||||
DMA_Cmd(dmaRef, DISABLE);
|
||||
DMA_DeInit(dmaRef);
|
||||
|
||||
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)
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)motor->dmaBuffer;
|
||||
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_Mode = DMA_Mode_Normal;
|
||||
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_ITConfig(dmaRef, DMA_IT_TC, ENABLE);
|
||||
|
|
|
@ -193,11 +193,85 @@ TIM_TypeDef * const usedTimers[USED_TIMER_COUNT] = {
|
|||
#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)
|
||||
{
|
||||
return channel >> 2;
|
||||
}
|
||||
|
||||
uint8_t timerLookupChannelIndex(const uint16_t channel)
|
||||
{
|
||||
return lookupChannelIndex(channel);
|
||||
}
|
||||
|
||||
rccPeriphTag_t timerRCC(TIM_TypeDef *tim)
|
||||
{
|
||||
for (int i = 0; i < HARDWARE_TIMER_DEFINITION_COUNT; i++) {
|
||||
|
|
|
@ -104,7 +104,7 @@ typedef struct timerHardware_s {
|
|||
DMA_Channel_TypeDef *dmaRef;
|
||||
#endif
|
||||
uint8_t dmaIrqHandler;
|
||||
#if defined(STM32F7)
|
||||
#if defined(STM32F4) || defined(STM32F7)
|
||||
// TIMUP
|
||||
DMA_Stream_TypeDef *dmaTimUPRef;
|
||||
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);
|
||||
|
||||
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_CHANNEL(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
|
||||
|
||||
// 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)
|
||||
#define DEF_TIM(tim, chan, pin, flags, out, dmaopt) { \
|
||||
tim, \
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#ifdef STM32F4
|
||||
#define USE_DSHOT
|
||||
#define USE_DSHOT_DMAR
|
||||
#define USE_ESC_SENSOR
|
||||
#define I2C3_OVERCLOCK true
|
||||
#define USE_TELEMETRY_IBUS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue