mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-16 12:55:19 +03:00
[G4] BB-DSHOT support (TIM1/TIM8 limited version)
This commit is contained in:
parent
de35df8e07
commit
35bad24c55
3 changed files with 65 additions and 8 deletions
|
@ -79,6 +79,9 @@ dshotBitbangStatus_e bbStatus;
|
||||||
#elif defined(STM32H7)
|
#elif defined(STM32H7)
|
||||||
#define BB_OUTPUT_BUFFER_ATTRIBUTE DMA_RAM
|
#define BB_OUTPUT_BUFFER_ATTRIBUTE DMA_RAM
|
||||||
#define BB_INPUT_BUFFER_ATTRIBUTE DMA_RAM
|
#define BB_INPUT_BUFFER_ATTRIBUTE DMA_RAM
|
||||||
|
#elif defined(STM32G4)
|
||||||
|
#define BB_OUTPUT_BUFFER_ATTRIBUTE DMA_RAM_W
|
||||||
|
#define BB_INPUT_BUFFER_ATTRIBUTE DMA_RAM_R
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BB_OUTPUT_BUFFER_ATTRIBUTE uint32_t bbOutputBuffer[MOTOR_DSHOT_BUFFER_SIZE * MAX_SUPPORTED_MOTOR_PORTS];
|
BB_OUTPUT_BUFFER_ATTRIBUTE uint32_t bbOutputBuffer[MOTOR_DSHOT_BUFFER_SIZE * MAX_SUPPORTED_MOTOR_PORTS];
|
||||||
|
@ -101,6 +104,25 @@ const timerHardware_t bbTimerHardware[] = {
|
||||||
DEF_TIM(TIM1, CH2, NONE, TIM_USE_NONE, 0, 1),
|
DEF_TIM(TIM1, CH2, NONE, TIM_USE_NONE, 0, 1),
|
||||||
DEF_TIM(TIM1, CH3, NONE, TIM_USE_NONE, 0, 1),
|
DEF_TIM(TIM1, CH3, NONE, TIM_USE_NONE, 0, 1),
|
||||||
DEF_TIM(TIM1, CH4, NONE, TIM_USE_NONE, 0, 0),
|
DEF_TIM(TIM1, CH4, NONE, TIM_USE_NONE, 0, 0),
|
||||||
|
#elif defined(STM32G4)
|
||||||
|
// XXX TODO: STM32G4 can use any timer for pacing
|
||||||
|
|
||||||
|
// DMA request numbers are duplicated for TIM1 and TIM8:
|
||||||
|
// - Any pacer can serve a GPIO port.
|
||||||
|
// - For quads (or less), 4 pacers can cover the worst case scenario of
|
||||||
|
// 4 motors scattered across 4 different GPIO ports.
|
||||||
|
// - For hexas (and larger), more channels may become necessary,
|
||||||
|
// in which case the DMA request numbers should be modified.
|
||||||
|
DEF_TIM(TIM8, CH1, NONE, TIM_USE_NONE, 0, 0, 0),
|
||||||
|
DEF_TIM(TIM8, CH2, NONE, TIM_USE_NONE, 0, 1, 0),
|
||||||
|
DEF_TIM(TIM8, CH3, NONE, TIM_USE_NONE, 0, 2, 0),
|
||||||
|
DEF_TIM(TIM8, CH4, NONE, TIM_USE_NONE, 0, 3, 0),
|
||||||
|
DEF_TIM(TIM1, CH1, NONE, TIM_USE_NONE, 0, 0, 0),
|
||||||
|
DEF_TIM(TIM1, CH2, NONE, TIM_USE_NONE, 0, 1, 0),
|
||||||
|
DEF_TIM(TIM1, CH3, NONE, TIM_USE_NONE, 0, 2, 0),
|
||||||
|
DEF_TIM(TIM1, CH4, NONE, TIM_USE_NONE, 0, 3, 0),
|
||||||
|
#else
|
||||||
|
#error MCU dependent code required
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -649,6 +671,8 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t
|
||||||
useDshotTelemetry = motorConfig->useDshotTelemetry;
|
useDshotTelemetry = motorConfig->useDshotTelemetry;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
memset(bbOutputBuffer, 0, sizeof(bbOutputBuffer));
|
||||||
|
|
||||||
for (int motorIndex = 0; motorIndex < MAX_SUPPORTED_MOTORS && motorIndex < motorCount; motorIndex++) {
|
for (int motorIndex = 0; motorIndex < MAX_SUPPORTED_MOTORS && motorIndex < motorCount; motorIndex++) {
|
||||||
const unsigned reorderedMotorIndex = motorConfig->motorOutputReordering[motorIndex];
|
const unsigned reorderedMotorIndex = motorConfig->motorOutputReordering[motorIndex];
|
||||||
const timerHardware_t *timerHardware = timerGetByTag(motorConfig->ioTags[reorderedMotorIndex]);
|
const timerHardware_t *timerHardware = timerGetByTag(motorConfig->ioTags[reorderedMotorIndex]);
|
||||||
|
@ -679,7 +703,7 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t
|
||||||
bbMotors[motorIndex].output = output;
|
bbMotors[motorIndex].output = output;
|
||||||
#if defined(STM32F4) || defined(STM32F3)
|
#if defined(STM32F4) || defined(STM32F3)
|
||||||
bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, bbPuPdMode);
|
bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, bbPuPdMode);
|
||||||
#elif defined(STM32F7)
|
#elif defined(STM32F7) || defined(STM32G4)
|
||||||
bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_VERY_HIGH, bbPuPdMode);
|
bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_VERY_HIGH, bbPuPdMode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,11 @@ typedef struct dmaRegCache_s {
|
||||||
uint32_t NDTR;
|
uint32_t NDTR;
|
||||||
uint32_t PAR;
|
uint32_t PAR;
|
||||||
uint32_t M0AR;
|
uint32_t M0AR;
|
||||||
|
#elif defined(STM32G4)
|
||||||
|
uint32_t CCR;
|
||||||
|
uint32_t CNDTR;
|
||||||
|
uint32_t CPAR;
|
||||||
|
uint32_t CMAR;
|
||||||
#else
|
#else
|
||||||
#error No MCU dependent code here
|
#error No MCU dependent code here
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -73,7 +73,7 @@ void bbGpioSetup(bbMotor_t *bbMotor)
|
||||||
IOWrite(bbMotor->io, 0);
|
IOWrite(bbMotor->io, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(STM32F7)
|
#if defined(STM32F7) || defined(STM32G4)
|
||||||
IOConfigGPIO(bbMotor->io, IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_HIGH, bbPuPdMode));
|
IOConfigGPIO(bbMotor->io, IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_HIGH, bbPuPdMode));
|
||||||
#else
|
#else
|
||||||
#error MCU dependent code required
|
#error MCU dependent code required
|
||||||
|
@ -127,20 +127,38 @@ void bbTimerChannelInit(bbPort_t *bbPort)
|
||||||
#ifdef USE_DMA_REGISTER_CACHE
|
#ifdef USE_DMA_REGISTER_CACHE
|
||||||
void bbLoadDMARegs(dmaResource_t *dmaResource, dmaRegCache_t *dmaRegCache)
|
void bbLoadDMARegs(dmaResource_t *dmaResource, dmaRegCache_t *dmaRegCache)
|
||||||
{
|
{
|
||||||
|
#if defined(STM32F7)
|
||||||
((DMA_ARCH_TYPE *)dmaResource)->CR = dmaRegCache->CR;
|
((DMA_ARCH_TYPE *)dmaResource)->CR = dmaRegCache->CR;
|
||||||
((DMA_ARCH_TYPE *)dmaResource)->FCR = dmaRegCache->FCR;
|
((DMA_ARCH_TYPE *)dmaResource)->FCR = dmaRegCache->FCR;
|
||||||
((DMA_ARCH_TYPE *)dmaResource)->NDTR = dmaRegCache->NDTR;
|
((DMA_ARCH_TYPE *)dmaResource)->NDTR = dmaRegCache->NDTR;
|
||||||
((DMA_ARCH_TYPE *)dmaResource)->PAR = dmaRegCache->PAR;
|
((DMA_ARCH_TYPE *)dmaResource)->PAR = dmaRegCache->PAR;
|
||||||
((DMA_ARCH_TYPE *)dmaResource)->M0AR = dmaRegCache->M0AR;
|
((DMA_ARCH_TYPE *)dmaResource)->M0AR = dmaRegCache->M0AR;
|
||||||
|
#elif defined(STM32G4)
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CCR = dmaRegCache->CCR;
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CNDTR = dmaRegCache->CNDTR;
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CPAR = dmaRegCache->CPAR;
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CMAR = dmaRegCache->CMAR;
|
||||||
|
#else
|
||||||
|
#error MCU dependent code required
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bbSaveDMARegs(dmaResource_t *dmaResource, dmaRegCache_t *dmaRegCache)
|
static void bbSaveDMARegs(dmaResource_t *dmaResource, dmaRegCache_t *dmaRegCache)
|
||||||
{
|
{
|
||||||
|
#if defined(STM32F7)
|
||||||
dmaRegCache->CR = ((DMA_ARCH_TYPE *)dmaResource)->CR;
|
dmaRegCache->CR = ((DMA_ARCH_TYPE *)dmaResource)->CR;
|
||||||
dmaRegCache->FCR = ((DMA_ARCH_TYPE *)dmaResource)->FCR;
|
dmaRegCache->FCR = ((DMA_ARCH_TYPE *)dmaResource)->FCR;
|
||||||
dmaRegCache->NDTR = ((DMA_ARCH_TYPE *)dmaResource)->NDTR;
|
dmaRegCache->NDTR = ((DMA_ARCH_TYPE *)dmaResource)->NDTR;
|
||||||
dmaRegCache->PAR = ((DMA_ARCH_TYPE *)dmaResource)->PAR;
|
dmaRegCache->PAR = ((DMA_ARCH_TYPE *)dmaResource)->PAR;
|
||||||
dmaRegCache->M0AR = ((DMA_ARCH_TYPE *)dmaResource)->M0AR;
|
dmaRegCache->M0AR = ((DMA_ARCH_TYPE *)dmaResource)->M0AR;
|
||||||
|
#elif defined(STM32G4)
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CCR = dmaRegCache->CCR;
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CNDTR = dmaRegCache->CNDTR;
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CPAR = dmaRegCache->CPAR;
|
||||||
|
((DMA_ARCH_TYPE *)dmaResource)->CMAR = dmaRegCache->CMAR;
|
||||||
|
#else
|
||||||
|
#error MCU dependent code required
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -224,15 +242,15 @@ void bbDMAPreconfigure(bbPort_t *bbPort, uint8_t direction)
|
||||||
LL_DMA_StructInit(dmainit);
|
LL_DMA_StructInit(dmainit);
|
||||||
|
|
||||||
dmainit->Mode = LL_DMA_MODE_NORMAL;
|
dmainit->Mode = LL_DMA_MODE_NORMAL;
|
||||||
|
#if defined(STM32G4)
|
||||||
|
dmainit->PeriphRequest = bbPort->dmaChannel;
|
||||||
|
#else
|
||||||
dmainit->Channel = bbPort->dmaChannel;
|
dmainit->Channel = bbPort->dmaChannel;
|
||||||
|
dmainit->FIFOMode = LL_DMA_FIFOMODE_ENABLE ;
|
||||||
|
#endif
|
||||||
|
|
||||||
dmainit->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
dmainit->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||||
dmainit->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
dmainit->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||||
dmainit->FIFOMode = LL_DMA_FIFOMODE_ENABLE ;
|
|
||||||
#if 0
|
|
||||||
dmainit->DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
|
|
||||||
dmainit->DMA_MemoryBurst = DMA_MemoryBurst_Single ;
|
|
||||||
dmainit->DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (direction == DSHOT_BITBANG_DIRECTION_OUTPUT) {
|
if (direction == DSHOT_BITBANG_DIRECTION_OUTPUT) {
|
||||||
dmainit->Priority = LL_DMA_PRIORITY_VERYHIGH;
|
dmainit->Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||||
|
@ -255,7 +273,13 @@ void bbDMAPreconfigure(bbPort_t *bbPort, uint8_t direction)
|
||||||
dmainit->PeriphOrM2MSrcAddress = (uint32_t)&bbPort->gpio->IDR;
|
dmainit->PeriphOrM2MSrcAddress = (uint32_t)&bbPort->gpio->IDR;
|
||||||
dmainit->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
|
dmainit->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
|
||||||
dmainit->MemoryOrM2MDstAddress = (uint32_t)bbPort->portInputBuffer;
|
dmainit->MemoryOrM2MDstAddress = (uint32_t)bbPort->portInputBuffer;
|
||||||
|
|
||||||
|
#ifdef STM32G4
|
||||||
|
// XXX G4 seems to require 16-bit transfer
|
||||||
|
dmainit->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
|
||||||
|
#else
|
||||||
dmainit->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
dmainit->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_DMA_REGISTER_CACHE
|
#ifdef USE_DMA_REGISTER_CACHE
|
||||||
xLL_EX_DMA_Init(bbPort->dmaResource, dmainit);
|
xLL_EX_DMA_Init(bbPort->dmaResource, dmainit);
|
||||||
|
@ -293,7 +317,11 @@ void bbDMA_ITConfig(bbPort_t *bbPort)
|
||||||
|
|
||||||
xLL_EX_DMA_EnableIT_TC(bbPort->dmaResource);
|
xLL_EX_DMA_EnableIT_TC(bbPort->dmaResource);
|
||||||
|
|
||||||
|
#if defined(STM32G4)
|
||||||
|
SET_BIT(((DMA_Channel_TypeDef *)(bbPort->dmaResource))->CCR, DMA_CCR_TCIE|DMA_CCR_TEIE);
|
||||||
|
#else
|
||||||
SET_BIT(((DMA_Stream_TypeDef *)(bbPort->dmaResource))->CR, DMA_SxCR_TCIE|DMA_SxCR_TEIE);
|
SET_BIT(((DMA_Stream_TypeDef *)(bbPort->dmaResource))->CR, DMA_SxCR_TCIE|DMA_SxCR_TEIE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void bbDMA_Cmd(bbPort_t *bbPort, FunctionalState NewState)
|
void bbDMA_Cmd(bbPort_t *bbPort, FunctionalState NewState)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue