1
0
Fork 0
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:
Michael Keller 2017-12-26 15:17:52 +13:00 committed by GitHub
commit 809a7d6b41
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 192 additions and 19 deletions

View file

@ -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)

View file

@ -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);

View file

@ -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++) {

View file

@ -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);

View file

@ -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, \

View file

@ -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