Skip to content

Commit b330a8a

Browse files
committed
dronecan: F7 ISR-driven TX, NVIC masking, TEC/REC/LEC counters, cliDronecan
Phase 2 of the combined DroneCAN driver rework (folds in iNavFlight#11560 content): F7 bxCAN ISR-driven TX refill: - Add NVIC_PRIO_CAN=4 to nvic.h (shared by H7 and F7) - Enable CAN_IT_TX_MAILBOX_EMPTY and CAN1_TX_IRQn at NVIC_PRIO_CAN - Add HAL_CAN_TxMailbox{0,1,2}CompleteCallback ISR pumps in dronecan.c - Wire dronecanMaskTxISR/UnmaskTxISR to NVIC_DisableIRQ/EnableIRQ(CAN1_TX_IRQn) - Add #else branch for SITL/AT32 (was missing, would break SITL build) TEC/REC/LEC error counters: - Extend canardProtocolStatus_t with tec, rec, lec fields - F7: populate from ESR register (bits 23:16, 31:24, 6:4) - H7: populate from ECR register (bits 22:16, 14:8) + PSR.LastErrorCode Typo fix: canardSTM32Recieve -> canardSTM32Receive across all drivers and call sites Other: - Add canardSTM32GetTxQueueFillLevel() to all three drivers (returns 0; no SW queue) - Make canard and memory_pool static in dronecan.c - Add cliDronecan CLI command showing bus health (BusOff, ErrorPassive, TEC, REC, LEC, fill levels)
1 parent 1532585 commit b330a8a

7 files changed

Lines changed: 83 additions & 20 deletions

File tree

src/main/drivers/dronecan/dronecan.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727

2828
/* Private variables ---------------------------------------------------------*/
2929

30-
CanardInstance canard;
31-
uint8_t memory_pool[1024];
30+
static CanardInstance canard;
31+
static uint8_t memory_pool[1024];
3232
static struct uavcan_protocol_NodeStatus node_status;
3333

3434
PG_REGISTER_WITH_RESET_TEMPLATE(dronecanConfig_t, dronecanConfig, PG_DRONECAN_CONFIG, 0);
@@ -45,6 +45,9 @@ static dronecanNodeInfo_t nodeTable[DRONECAN_MAX_NODES];
4545
#if defined(STM32H7)
4646
static inline void dronecanMaskTxISR(void) { NVIC_DisableIRQ(FDCAN1_IT1_IRQn); }
4747
static inline void dronecanUnmaskTxISR(void) { NVIC_EnableIRQ(FDCAN1_IT1_IRQn); }
48+
#elif defined(STM32F7)
49+
static inline void dronecanMaskTxISR(void) { NVIC_DisableIRQ(CAN1_TX_IRQn); }
50+
static inline void dronecanUnmaskTxISR(void) { NVIC_EnableIRQ(CAN1_TX_IRQn); }
4851
#else
4952
static inline void dronecanMaskTxISR(void) {}
5053
static inline void dronecanUnmaskTxISR(void) {}
@@ -385,6 +388,11 @@ void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t Bu
385388
processCanardTxQueue();
386389
}
387390
#endif
391+
#if defined(STM32F7)
392+
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { UNUSED(hcan); processCanardTxQueue(); }
393+
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { UNUSED(hcan); processCanardTxQueue(); }
394+
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { UNUSED(hcan); processCanardTxQueue(); }
395+
#endif
388396

389397

390398
/*
@@ -478,7 +486,7 @@ void dronecanUpdate(timeUs_t currentTimeUs)
478486
for (numMessagesToProcess = canardSTM32GetRxFifoFillLevel(); numMessagesToProcess > 0; numMessagesToProcess--)
479487
{
480488
timestamp = millis() * 1000ULL;
481-
rx_res = canardSTM32Recieve(&rx_frame);
489+
rx_res = canardSTM32Receive(&rx_frame);
482490

483491
if (rx_res < 0) {
484492
LOG_DEBUG(CAN, "Receive error %d", rx_res);

src/main/drivers/dronecan/libcanard/canard_sitl_driver.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ static int16_t sitlCANTransmitStub(const CanardCANFrame* const tx_frame) {
106106
}
107107

108108
static void sitlCANGetStatsStub(canardProtocolStatus_t *pProtocolStat) {
109-
pProtocolStat->BusOff = 0;
110-
pProtocolStat->ErrorPassive = 0;
109+
memset(pProtocolStat, 0, sizeof(*pProtocolStat));
111110
}
112111

113112
#ifdef __linux__
@@ -267,11 +266,7 @@ static int16_t sitlCANTransmitSocketCAN(const CanardCANFrame* const tx_frame) {
267266
* @param pProtocolStat Pointer to status structure to fill
268267
*/
269268
static void sitlCANGetStatsSocketCAN(canardProtocolStatus_t *pProtocolStat) {
270-
// SocketCAN doesn't expose bus-off/error-passive directly
271-
// We could check interface flags via netlink, but for SITL testing
272-
// we assume the virtual CAN is always healthy
273-
pProtocolStat->BusOff = 0;
274-
pProtocolStat->ErrorPassive = 0;
269+
memset(pProtocolStat, 0, sizeof(*pProtocolStat));
275270
}
276271
#endif // __linux__
277272

@@ -280,7 +275,7 @@ static void sitlCANGetStatsSocketCAN(canardProtocolStatus_t *pProtocolStat) {
280275
* @param rx_frame Pointer to frame structure to fill
281276
* @retval 0 if no frame available, 1 if frame received, negative on error
282277
*/
283-
int16_t canardSTM32Recieve(CanardCANFrame *const rx_frame) {
278+
int16_t canardSTM32Receive(CanardCANFrame *const rx_frame) {
284279
if (rx_frame == NULL) {
285280
return -CANARD_ERROR_INVALID_ARGUMENT;
286281
}
@@ -357,6 +352,10 @@ int32_t canardSTM32GetRxFifoFillLevel(void) {
357352
return 0;
358353
}
359354

355+
int32_t canardSTM32GetTxQueueFillLevel(void) {
356+
return 0;
357+
}
358+
360359
/**
361360
* @brief Recover from bus-off condition
362361
*/

src/main/drivers/dronecan/libcanard/canard_stm32_driver.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@
1212
typedef struct {
1313
uint32_t BusOff;
1414
uint32_t ErrorPassive;
15+
uint8_t tec;
16+
uint8_t rec;
17+
uint8_t lec;
1518
} canardProtocolStatus_t;
1619

1720
#ifdef USE_DRONECAN
1821

1922
int16_t canardSTM32CAN1_Init(uint32_t bitrate);
2023

21-
int16_t canardSTM32Recieve(CanardCANFrame *const rx_frame);
24+
int16_t canardSTM32Receive(CanardCANFrame *const rx_frame);
2225
int16_t canardSTM32Transmit(const CanardCANFrame* const tx_frame);
2326
void canardSTM32GetProtocolStatus(canardProtocolStatus_t *pProtocolStat);
27+
int32_t canardSTM32GetTxQueueFillLevel(void);
2428
int32_t canardSTM32GetRxFifoFillLevel(void);
2529
void canardSTM32RecoverFromBusOff(void);
2630
void canardSTM32GetUniqueID(uint8_t id[16]);

src/main/drivers/dronecan/libcanard/canard_stm32f7xx_driver.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "common/log.h"
99
#include "common/time.h"
1010
#include "drivers/io.h"
11+
#include "drivers/nvic.h"
1112
#include "canard.h"
1213
#include "canard_stm32_driver.h"
1314

@@ -93,7 +94,7 @@ uint8_t rxBufferNumMessages(struct RxBuffer_t *rxBuf) {
9394
* stored.
9495
* @retval ret == 1: OK, ret < 0: CANARD_ERROR, ret == 0: Check hfdcan->ErrorCode
9596
*/
96-
int16_t canardSTM32Recieve(CanardCANFrame *const rx_frame) {
97+
int16_t canardSTM32Receive(CanardCANFrame *const rx_frame) {
9798
RxFrame_t canRxFrame;
9899

99100
if (rx_frame == NULL) {
@@ -240,8 +241,14 @@ int16_t canardSTM32CAN1_Init(uint32_t bitrate)
240241

241242
// Enable interrupt only after all initialization succeeds
242243
// (if any previous step failed, we return early without enabling IRQ)
243-
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
244+
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, NVIC_PRIO_CAN, 0);
244245
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
246+
if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_TX_MAILBOX_EMPTY) != HAL_OK) {
247+
LOG_ERROR(CAN, "Failed to activate TX interrupt");
248+
return -CANARD_ERROR_INTERNAL;
249+
}
250+
HAL_NVIC_SetPriority(CAN1_TX_IRQn, NVIC_PRIO_CAN, 0);
251+
HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
245252

246253
return CANARD_OK;
247254
}
@@ -387,9 +394,16 @@ static bool canardSTM32ComputeTimings(const uint32_t target_bitrate, struct Timi
387394
}
388395

389396
void canardSTM32GetProtocolStatus(canardProtocolStatus_t *pProtocolStat){
390-
391-
pProtocolStat->BusOff = __HAL_CAN_GET_FLAG(&hcan1, CAN_FLAG_BOF);
397+
uint32_t esr = hcan1.Instance->ESR;
398+
pProtocolStat->BusOff = __HAL_CAN_GET_FLAG(&hcan1, CAN_FLAG_BOF);
392399
pProtocolStat->ErrorPassive = __HAL_CAN_GET_FLAG(&hcan1, CAN_FLAG_EPV);
400+
pProtocolStat->tec = (uint8_t)((esr >> 16) & 0xFF);
401+
pProtocolStat->rec = (uint8_t)((esr >> 24) & 0xFF);
402+
pProtocolStat->lec = (uint8_t)((esr >> 4) & 0x07);
403+
}
404+
405+
int32_t canardSTM32GetTxQueueFillLevel(void){
406+
return 0;
393407
}
394408

395409
int32_t canardSTM32GetRxFifoFillLevel(void){
@@ -420,6 +434,10 @@ void CAN1_RX0_IRQHandler(void) {
420434
HAL_CAN_IRQHandler(&hcan1);
421435
}
422436

437+
void CAN1_TX_IRQHandler(void) {
438+
HAL_CAN_IRQHandler(&hcan1);
439+
}
440+
423441
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
424442
RxFrame_t frame;
425443
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &frame.header, frame.data) == HAL_OK) {

src/main/drivers/dronecan/libcanard/canard_stm32h7xx_driver.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static FDCAN_HandleTypeDef hfdcan1;
4040
* stored.
4141
* @retval ret == 1: OK, ret < 0: CANARD_ERROR, ret == 0: Check hfdcan->ErrorCode
4242
*/
43-
int16_t canardSTM32Recieve(CanardCANFrame *const rx_frame) {
43+
int16_t canardSTM32Receive(CanardCANFrame *const rx_frame) {
4444
if (rx_frame == NULL) {
4545
return -CANARD_ERROR_INVALID_ARGUMENT;
4646
}
@@ -351,11 +351,18 @@ static bool canardSTM32ComputeTimings(const uint32_t target_bitrate, struct Timi
351351
}
352352

353353
void canardSTM32GetProtocolStatus(canardProtocolStatus_t *pProtocolStat){
354-
FDCAN_ProtocolStatusTypeDef protocolStatus = {};
355-
354+
FDCAN_ProtocolStatusTypeDef protocolStatus = {};
356355
HAL_FDCAN_GetProtocolStatus(&hfdcan1, &protocolStatus);
357-
pProtocolStat->BusOff = protocolStatus.BusOff;
356+
pProtocolStat->BusOff = protocolStatus.BusOff;
358357
pProtocolStat->ErrorPassive = protocolStatus.ErrorPassive;
358+
uint32_t ecr = hfdcan1.Instance->ECR;
359+
pProtocolStat->tec = (uint8_t)((ecr >> 16) & 0x7F);
360+
pProtocolStat->rec = (uint8_t)((ecr >> 8) & 0x7F);
361+
pProtocolStat->lec = (uint8_t)(protocolStatus.LastErrorCode & 0x07);
362+
}
363+
364+
int32_t canardSTM32GetTxQueueFillLevel(void){
365+
return 0;
359366
}
360367

361368
int32_t canardSTM32GetRxFifoFillLevel(void){

src/main/drivers/nvic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define NVIC_PRIO_TIMER 3
1313
#define NVIC_PRIO_TIMER_DMA 3
1414
#define NVIC_PRIO_SDIO 3
15+
#define NVIC_PRIO_CAN 4
1516
#define NVIC_PRIO_USB 5
1617
#define NVIC_PRIO_SERIALUART 5
1718
#define NVIC_PRIO_VCP 7

src/main/fc/cli.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ bool cliMode = false;
125125
#include "sensors/temperature.h"
126126
#ifdef USE_DRONECAN
127127
#include "drivers/dronecan/dronecan.h"
128+
#include "drivers/dronecan/libcanard/canard_stm32_driver.h"
128129
#endif
129130
#ifdef USE_ESC_SENSOR
130131
#include "sensors/esc_sensor.h"
@@ -4694,6 +4695,28 @@ static void printConfig(const char *cmdline, bool doDiff)
46944695
restoreConfigs();
46954696
}
46964697

4698+
#ifdef USE_DRONECAN
4699+
static void cliDronecan(char *cmdline)
4700+
{
4701+
UNUSED(cmdline);
4702+
static const char * const lecNames[] = {
4703+
"None", "Stuff", "Form", "ACK", "BitR", "BitD", "CRC", "SW"
4704+
};
4705+
canardProtocolStatus_t stat;
4706+
canardSTM32GetProtocolStatus(&stat);
4707+
int32_t txFill = canardSTM32GetTxQueueFillLevel();
4708+
int32_t rxFill = canardSTM32GetRxFifoFillLevel();
4709+
cliPrintLine("DroneCAN CAN peripheral status:");
4710+
cliPrintLinef(" BusOff: %s", stat.BusOff ? "YES" : "no");
4711+
cliPrintLinef(" ErrorPassive: %s", stat.ErrorPassive ? "YES" : "no");
4712+
cliPrintLinef(" TEC: %u", (unsigned)stat.tec);
4713+
cliPrintLinef(" REC: %u", (unsigned)stat.rec);
4714+
cliPrintLinef(" LEC: %s (%u)", lecNames[stat.lec & 0x7], (unsigned)stat.lec);
4715+
cliPrintLinef(" TX queue: %ld", (long)txFill);
4716+
cliPrintLinef(" RX buffer: %ld", (long)rxFill);
4717+
}
4718+
#endif
4719+
46974720
static void cliDump(char *cmdline)
46984721
{
46994722
printConfig(cmdline, false);
@@ -4939,6 +4962,9 @@ const clicmd_t cmdTable[] = {
49394962
CLI_COMMAND_DEF("dfu", "DFU mode on reboot", NULL, cliDfu),
49404963
CLI_COMMAND_DEF("diff", "list configuration changes from default",
49414964
"[master|battery_profile|control_profile|mixer_profile|rates|all] {showdefaults}", cliDiff),
4965+
#ifdef USE_DRONECAN
4966+
CLI_COMMAND_DEF("dronecan", "show DroneCAN CAN peripheral debug status", NULL, cliDronecan),
4967+
#endif
49424968
CLI_COMMAND_DEF("dump", "dump configuration",
49434969
"[master|battery_profile|control_profile|mixer_profile|rates|all] {showdefaults}", cliDump),
49444970
#ifdef USE_RX_ELERES

0 commit comments

Comments
 (0)