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:
parent
2a18209492
commit
65be79c86a
4 changed files with 43 additions and 31 deletions
|
@ -59,7 +59,6 @@ FAST_RAM_ZERO_INIT int usedMotorPorts;
|
||||||
|
|
||||||
FAST_RAM_ZERO_INIT bbMotor_t bbMotors[MAX_SUPPORTED_MOTORS];
|
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;
|
static FAST_RAM_ZERO_INIT int motorCount;
|
||||||
dshotBitbangStatus_e bbStatus;
|
dshotBitbangStatus_e bbStatus;
|
||||||
|
|
||||||
|
@ -102,6 +101,11 @@ const timerHardware_t bbTimerHardware[] = {
|
||||||
#endif
|
#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
|
// DMA GPIO output buffer formatting
|
||||||
|
|
||||||
static void bbOutputDataInit(uint32_t *buffer, uint16_t portMask, bool inverted)
|
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)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,11 +201,14 @@ static bbPort_t *bbAllocMotorPort(int portIndex)
|
||||||
|
|
||||||
if (!bbPort->timhw) {
|
if (!bbPort->timhw) {
|
||||||
// No more pacer channel available
|
// No more pacer channel available
|
||||||
bbStatus = DSHOT_BITBANG_NO_PACER;
|
bbStatus = DSHOT_BITBANG_STATUS_NO_PACER;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpioToMotorPort[portIndex] = bbPort;
|
bbPort->portIndex = portIndex;
|
||||||
|
bbPort->owner.owner = OWNER_DSHOT_BITBANG;
|
||||||
|
bbPort->owner.resourceIndex = RESOURCE_INDEX(portIndex);
|
||||||
|
|
||||||
++usedMotorPorts;
|
++usedMotorPorts;
|
||||||
|
|
||||||
return bbPort;
|
return bbPort;
|
||||||
|
@ -208,12 +216,10 @@ static bbPort_t *bbAllocMotorPort(int portIndex)
|
||||||
|
|
||||||
const resourceOwner_t *dshotBitbangTimerGetOwner(int8_t timerNumber, uint16_t timerChannel)
|
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++) {
|
for (int index = 0; index < usedMotorPorts; index++) {
|
||||||
const timerHardware_t *timer = bbPorts[index].timhw;
|
const timerHardware_t *timer = bbPorts[index].timhw;
|
||||||
if (timerGetTIMNumber(timer->tim) == timerNumber && timer->channel == timerChannel) {
|
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
|
#endif
|
||||||
|
|
||||||
dmaIdentifier_e dmaIdentifier = dmaGetIdentifier(bbPort->dmaResource);
|
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);
|
bbPort->dmaSource = timerDmaSource(timhw->channel);
|
||||||
|
|
||||||
bbPacer_t *bbPacer = bbFindMotorPacer(timhw->tim);
|
bbPacer_t *bbPacer = bbFindMotorPacer(timhw->tim);
|
||||||
|
@ -304,12 +310,9 @@ void bbDMAIrqHandler(dmaChannelDescriptor_t *descriptor)
|
||||||
|
|
||||||
static void bbFindPacerTimer(void)
|
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 (int bbPortIndex = 0; bbPortIndex < MAX_SUPPORTED_MOTOR_PORTS; bbPortIndex++) {
|
||||||
for (unsigned timerIndex = 0; timerIndex < ARRAYLEN(bbTimerHardware); timerIndex++) {
|
for (unsigned timerIndex = 0; timerIndex < ARRAYLEN(bbTimerHardware); timerIndex++) {
|
||||||
timer = &bbTimerHardware[timerIndex];
|
const timerHardware_t *timer = &bbTimerHardware[timerIndex];
|
||||||
int timNumber = timerGetTIMNumber(timer->tim);
|
int timNumber = timerGetTIMNumber(timer->tim);
|
||||||
if ((motorConfig()->dev.useDshotBitbangedTimer == DSHOT_BITBANGED_TIMER_TIM1 && timNumber != 1)
|
if ((motorConfig()->dev.useDshotBitbangedTimer == DSHOT_BITBANGED_TIMER_TIM1 && timNumber != 1)
|
||||||
|| (motorConfig()->dev.useDshotBitbangedTimer == DSHOT_BITBANGED_TIMER_TIM8 && timNumber != 8)) {
|
|| (motorConfig()->dev.useDshotBitbangedTimer == DSHOT_BITBANGED_TIMER_TIM8 && timNumber != 8)) {
|
||||||
|
@ -323,6 +326,14 @@ static void bbFindPacerTimer(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < bbPortIndex; index++) {
|
||||||
|
if (bbPorts[index].timhw == timer) {
|
||||||
|
timerConflict = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (timerConflict) {
|
if (timerConflict) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -335,14 +346,12 @@ static void bbFindPacerTimer(void)
|
||||||
dmaResource_t *dma = timer->dmaRef;
|
dmaResource_t *dma = timer->dmaRef;
|
||||||
#endif
|
#endif
|
||||||
dmaIdentifier_e dmaIdentifier = dmaGetIdentifier(dma);
|
dmaIdentifier_e dmaIdentifier = dmaGetIdentifier(dma);
|
||||||
if (dmaGetOwner(dmaIdentifier)->owner == OWNER_FREE &&
|
if (dmaGetOwner(dmaIdentifier)->owner == OWNER_FREE) {
|
||||||
!usedTimerChannels[timNumber][timer->channel]) {
|
bbPorts[bbPortIndex].timhw = timer;
|
||||||
usedTimerChannels[timNumber][timer->channel] = true;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bbPorts[bbPortIndex].timhw = timer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,11 +386,14 @@ static bool bbMotorConfig(IO_t io, uint8_t motorIndex, motorPwmProtocolTypes_e p
|
||||||
|
|
||||||
bbPort = bbAllocMotorPort(portIndex);
|
bbPort = bbAllocMotorPort(portIndex);
|
||||||
if (!bbPort) {
|
if (!bbPort) {
|
||||||
|
bbDevice.vTable.write = motorWriteNull;
|
||||||
|
bbDevice.vTable.updateStart = motorUpdateStartNull;
|
||||||
|
bbDevice.vTable.updateComplete = motorUpdateCompleteNull;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bbPort->gpio = IO_GPIO(io);
|
bbPort->gpio = IO_GPIO(io);
|
||||||
bbPort->portIndex = portIndex;
|
|
||||||
|
|
||||||
bbPort->portOutputCount = MOTOR_DSHOT_BUFFER_SIZE;
|
bbPort->portOutputCount = MOTOR_DSHOT_BUFFER_SIZE;
|
||||||
bbPort->portOutputBuffer = &bbOutputBuffer[(bbPort - bbPorts) * 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FAST_RAM_ZERO_INIT motorDevice_t bbDevice;
|
|
||||||
static FAST_RAM_ZERO_INIT timeUs_t lastSendUs;
|
|
||||||
|
|
||||||
static bool bbUpdateStart(void)
|
static bool bbUpdateStart(void)
|
||||||
{
|
{
|
||||||
#ifdef USE_DSHOT_TELEMETRY
|
#ifdef USE_DSHOT_TELEMETRY
|
||||||
|
@ -561,7 +570,9 @@ static void bbUpdateComplete(void)
|
||||||
static bool bbEnableMotors(void)
|
static bool bbEnableMotors(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < motorCount; i++) {
|
for (int i = 0; i < motorCount; i++) {
|
||||||
IOConfigGPIO(bbMotors[i].io, bbMotors[i].iocfg);
|
if (bbMotors[i].configured) {
|
||||||
|
IOConfigGPIO(bbMotors[i].io, bbMotors[i].iocfg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -581,15 +592,13 @@ static bool bbIsMotorEnabled(uint8_t index)
|
||||||
return bbMotors[index].enabled;
|
return bbMotors[index].enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const motorDevConfig_t *lastMotorConfig;
|
|
||||||
|
|
||||||
static void bbPostInit()
|
static void bbPostInit()
|
||||||
{
|
{
|
||||||
bbFindPacerTimer();
|
bbFindPacerTimer();
|
||||||
|
|
||||||
for (int motorIndex = 0; motorIndex < MAX_SUPPORTED_MOTORS && motorIndex < motorCount; motorIndex++) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,10 +636,10 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t
|
||||||
dbgPinLo(0);
|
dbgPinLo(0);
|
||||||
dbgPinLo(1);
|
dbgPinLo(1);
|
||||||
|
|
||||||
lastMotorConfig = motorConfig;
|
motorPwmProtocol = motorConfig->motorPwmProtocol;
|
||||||
bbDevice.vTable = bbVTable;
|
bbDevice.vTable = bbVTable;
|
||||||
motorCount = count;
|
motorCount = count;
|
||||||
bbStatus = DSHOT_BITBANG_OK;
|
bbStatus = DSHOT_BITBANG_STATUS_OK;
|
||||||
|
|
||||||
#ifdef USE_DSHOT_TELEMETRY
|
#ifdef USE_DSHOT_TELEMETRY
|
||||||
useDshotTelemetry = motorConfig->useDshotTelemetry;
|
useDshotTelemetry = motorConfig->useDshotTelemetry;
|
||||||
|
@ -652,8 +661,9 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t
|
||||||
if (!IOIsFreeOrPreinit(io)) {
|
if (!IOIsFreeOrPreinit(io)) {
|
||||||
/* not enough motors initialised for the mixer or a break in the motors */
|
/* not enough motors initialised for the mixer or a break in the motors */
|
||||||
bbDevice.vTable.write = motorWriteNull;
|
bbDevice.vTable.write = motorWriteNull;
|
||||||
|
bbDevice.vTable.updateStart = motorUpdateStartNull;
|
||||||
bbDevice.vTable.updateComplete = motorUpdateCompleteNull;
|
bbDevice.vTable.updateComplete = motorUpdateCompleteNull;
|
||||||
bbStatus = DSHOT_BITBANG_MOTOR_PIN_CONFLICT;
|
bbStatus = DSHOT_BITBANG_STATUS_MOTOR_PIN_CONFLICT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,10 @@ typedef enum {
|
||||||
} dshotBitbangMode_e;
|
} dshotBitbangMode_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DSHOT_BITBANG_OK,
|
DSHOT_BITBANG_STATUS_OK,
|
||||||
DSHOT_BITBANG_MOTOR_PIN_CONFLICT,
|
DSHOT_BITBANG_STATUS_MOTOR_PIN_CONFLICT,
|
||||||
DSHOT_BITBANG_NO_PACER
|
DSHOT_BITBANG_STATUS_NO_PACER,
|
||||||
|
DSHOT_BITBANG_STATUS_TOO_MANY_PORTS,
|
||||||
} dshotBitbangStatus_e;
|
} dshotBitbangStatus_e;
|
||||||
|
|
||||||
struct motorDevConfig_s;
|
struct motorDevConfig_s;
|
||||||
|
|
|
@ -156,6 +156,7 @@ typedef struct bbPort_s {
|
||||||
uint32_t outputIrq;
|
uint32_t outputIrq;
|
||||||
uint32_t inputIrq;
|
uint32_t inputIrq;
|
||||||
#endif
|
#endif
|
||||||
|
resourceOwner_t owner;
|
||||||
} bbPort_t;
|
} bbPort_t;
|
||||||
|
|
||||||
// Per motor output
|
// Per motor output
|
||||||
|
|
|
@ -310,7 +310,7 @@ void updateArmingStatus(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_DSHOT_BITBANG
|
#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);
|
setArmingDisabled(ARMING_DISABLED_DSHOT_BITBANG);
|
||||||
} else {
|
} else {
|
||||||
unsetArmingDisabled(ARMING_DISABLED_DSHOT_BITBANG);
|
unsetArmingDisabled(ARMING_DISABLED_DSHOT_BITBANG);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue