1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-26 01:35:41 +03:00

Fix faulty timer allocation in bitbanged Dshot.

This commit is contained in:
mikeller 2019-09-11 01:26:38 +12:00
parent 2a18209492
commit 65be79c86a
4 changed files with 43 additions and 31 deletions

View file

@ -59,7 +59,6 @@ FAST_RAM_ZERO_INIT int usedMotorPorts;
FAST_RAM_ZERO_INIT bbMotor_t bbMotors[MAX_SUPPORTED_MOTORS];
FAST_RAM_ZERO_INIT bbPort_t *gpioToMotorPort[10]; // GPIO group to bbPort mappin
static FAST_RAM_ZERO_INIT int motorCount;
dshotBitbangStatus_e bbStatus;
@ -102,6 +101,11 @@ const timerHardware_t bbTimerHardware[] = {
#endif
};
static FAST_RAM_ZERO_INIT motorDevice_t bbDevice;
static FAST_RAM_ZERO_INIT timeUs_t lastSendUs;
static motorPwmProtocolTypes_e motorPwmProtocol;
// DMA GPIO output buffer formatting
static void bbOutputDataInit(uint32_t *buffer, uint16_t portMask, bool inverted)
@ -188,7 +192,8 @@ static bbPort_t *bbFindMotorPort(int portIndex)
static bbPort_t *bbAllocMotorPort(int portIndex)
{
if (usedMotorPorts == MAX_SUPPORTED_MOTOR_PORTS) {
if (usedMotorPorts >= MAX_SUPPORTED_MOTOR_PORTS) {
bbStatus = DSHOT_BITBANG_STATUS_TOO_MANY_PORTS;
return NULL;
}
@ -196,11 +201,14 @@ static bbPort_t *bbAllocMotorPort(int portIndex)
if (!bbPort->timhw) {
// No more pacer channel available
bbStatus = DSHOT_BITBANG_NO_PACER;
bbStatus = DSHOT_BITBANG_STATUS_NO_PACER;
return NULL;
}
gpioToMotorPort[portIndex] = bbPort;
bbPort->portIndex = portIndex;
bbPort->owner.owner = OWNER_DSHOT_BITBANG;
bbPort->owner.resourceIndex = RESOURCE_INDEX(portIndex);
++usedMotorPorts;
return bbPort;
@ -208,12 +216,10 @@ static bbPort_t *bbAllocMotorPort(int portIndex)
const resourceOwner_t *dshotBitbangTimerGetOwner(int8_t timerNumber, uint16_t timerChannel)
{
static resourceOwner_t bitbangOwner = { .owner = OWNER_DSHOT_BITBANG, .resourceIndex = 0 };
for (int index = 0; index < usedMotorPorts; index++) {
const timerHardware_t *timer = bbPorts[index].timhw;
if (timerGetTIMNumber(timer->tim) == timerNumber && timer->channel == timerChannel) {
return &bitbangOwner;
return &bbPorts[index].owner;
}
}
@ -250,7 +256,7 @@ static void bbAllocDma(bbPort_t *bbPort)
#endif
dmaIdentifier_e dmaIdentifier = dmaGetIdentifier(bbPort->dmaResource);
dmaInit(dmaIdentifier, OWNER_DSHOT_BITBANG, RESOURCE_INDEX(bbPort - bbPorts));
dmaInit(dmaIdentifier, OWNER_DSHOT_BITBANG, bbPort->owner.resourceIndex);
bbPort->dmaSource = timerDmaSource(timhw->channel);
bbPacer_t *bbPacer = bbFindMotorPacer(timhw->tim);
@ -304,12 +310,9 @@ void bbDMAIrqHandler(dmaChannelDescriptor_t *descriptor)
static void bbFindPacerTimer(void)
{
const timerHardware_t *timer;
bool usedTimerChannels[32][CC_CHANNELS_PER_TIMER] = {0};
for (int bbPortIndex = 0; bbPortIndex < MAX_SUPPORTED_MOTOR_PORTS; bbPortIndex++) {
for (unsigned timerIndex = 0; timerIndex < ARRAYLEN(bbTimerHardware); timerIndex++) {
timer = &bbTimerHardware[timerIndex];
const timerHardware_t *timer = &bbTimerHardware[timerIndex];
int timNumber = timerGetTIMNumber(timer->tim);
if ((motorConfig()->dev.useDshotBitbangedTimer == DSHOT_BITBANGED_TIMER_TIM1 && timNumber != 1)
|| (motorConfig()->dev.useDshotBitbangedTimer == DSHOT_BITBANGED_TIMER_TIM8 && timNumber != 8)) {
@ -323,6 +326,14 @@ static void bbFindPacerTimer(void)
break;
}
}
for (int index = 0; index < bbPortIndex; index++) {
if (bbPorts[index].timhw == timer) {
timerConflict = true;
break;
}
}
if (timerConflict) {
continue;
}
@ -335,14 +346,12 @@ static void bbFindPacerTimer(void)
dmaResource_t *dma = timer->dmaRef;
#endif
dmaIdentifier_e dmaIdentifier = dmaGetIdentifier(dma);
if (dmaGetOwner(dmaIdentifier)->owner == OWNER_FREE &&
!usedTimerChannels[timNumber][timer->channel]) {
usedTimerChannels[timNumber][timer->channel] = true;
if (dmaGetOwner(dmaIdentifier)->owner == OWNER_FREE) {
bbPorts[bbPortIndex].timhw = timer;
break;
}
}
bbPorts[bbPortIndex].timhw = timer;
}
}
@ -377,11 +386,14 @@ static bool bbMotorConfig(IO_t io, uint8_t motorIndex, motorPwmProtocolTypes_e p
bbPort = bbAllocMotorPort(portIndex);
if (!bbPort) {
bbDevice.vTable.write = motorWriteNull;
bbDevice.vTable.updateStart = motorUpdateStartNull;
bbDevice.vTable.updateComplete = motorUpdateCompleteNull;
return false;
}
bbPort->gpio = IO_GPIO(io);
bbPort->portIndex = portIndex;
bbPort->portOutputCount = MOTOR_DSHOT_BUFFER_SIZE;
bbPort->portOutputBuffer = &bbOutputBuffer[(bbPort - bbPorts) * MOTOR_DSHOT_BUFFER_SIZE];
@ -427,9 +439,6 @@ static bool bbMotorConfig(IO_t io, uint8_t motorIndex, motorPwmProtocolTypes_e p
return true;
}
static FAST_RAM_ZERO_INIT motorDevice_t bbDevice;
static FAST_RAM_ZERO_INIT timeUs_t lastSendUs;
static bool bbUpdateStart(void)
{
#ifdef USE_DSHOT_TELEMETRY
@ -561,8 +570,10 @@ static void bbUpdateComplete(void)
static bool bbEnableMotors(void)
{
for (int i = 0; i < motorCount; i++) {
if (bbMotors[i].configured) {
IOConfigGPIO(bbMotors[i].io, bbMotors[i].iocfg);
}
}
return true;
}
@ -581,15 +592,13 @@ static bool bbIsMotorEnabled(uint8_t index)
return bbMotors[index].enabled;
}
static const motorDevConfig_t *lastMotorConfig;
static void bbPostInit()
{
bbFindPacerTimer();
for (int motorIndex = 0; motorIndex < MAX_SUPPORTED_MOTORS && motorIndex < motorCount; motorIndex++) {
if (!bbMotorConfig(bbMotors[motorIndex].io, motorIndex, lastMotorConfig->motorPwmProtocol, bbMotors[motorIndex].output)) {
if (!bbMotorConfig(bbMotors[motorIndex].io, motorIndex, motorPwmProtocol, bbMotors[motorIndex].output)) {
return NULL;
}
@ -627,10 +636,10 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t
dbgPinLo(0);
dbgPinLo(1);
lastMotorConfig = motorConfig;
motorPwmProtocol = motorConfig->motorPwmProtocol;
bbDevice.vTable = bbVTable;
motorCount = count;
bbStatus = DSHOT_BITBANG_OK;
bbStatus = DSHOT_BITBANG_STATUS_OK;
#ifdef USE_DSHOT_TELEMETRY
useDshotTelemetry = motorConfig->useDshotTelemetry;
@ -652,8 +661,9 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t
if (!IOIsFreeOrPreinit(io)) {
/* not enough motors initialised for the mixer or a break in the motors */
bbDevice.vTable.write = motorWriteNull;
bbDevice.vTable.updateStart = motorUpdateStartNull;
bbDevice.vTable.updateComplete = motorUpdateCompleteNull;
bbStatus = DSHOT_BITBANG_MOTOR_PIN_CONFLICT;
bbStatus = DSHOT_BITBANG_STATUS_MOTOR_PIN_CONFLICT;
return NULL;
}

View file

@ -29,9 +29,10 @@ typedef enum {
} dshotBitbangMode_e;
typedef enum {
DSHOT_BITBANG_OK,
DSHOT_BITBANG_MOTOR_PIN_CONFLICT,
DSHOT_BITBANG_NO_PACER
DSHOT_BITBANG_STATUS_OK,
DSHOT_BITBANG_STATUS_MOTOR_PIN_CONFLICT,
DSHOT_BITBANG_STATUS_NO_PACER,
DSHOT_BITBANG_STATUS_TOO_MANY_PORTS,
} dshotBitbangStatus_e;
struct motorDevConfig_s;

View file

@ -156,6 +156,7 @@ typedef struct bbPort_s {
uint32_t outputIrq;
uint32_t inputIrq;
#endif
resourceOwner_t owner;
} bbPort_t;
// Per motor output

View file

@ -310,7 +310,7 @@ void updateArmingStatus(void)
#endif
#ifdef USE_DSHOT_BITBANG
if (isDshotBitbangActive(&motorConfig()->dev) && dshotBitbangGetStatus() != DSHOT_BITBANG_OK) {
if (isDshotBitbangActive(&motorConfig()->dev) && dshotBitbangGetStatus() != DSHOT_BITBANG_STATUS_OK) {
setArmingDisabled(ARMING_DISABLED_DSHOT_BITBANG);
} else {
unsetArmingDisabled(ARMING_DISABLED_DSHOT_BITBANG);