From 74b5aa2f468cc433c03da48fb15c18d6d608c377 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 15 Oct 2023 07:54:01 +1100 Subject: [PATCH] DroneCAN: use TWAI acceptance filters this allows the ESP32 to cope with high rate traffic for DroneCAN ESCs without choking. We use the priority field as a discriminator as the TWAI acceptance filters are don't allow complex enough filters to work on all the message IDs we need. We rely on the messages we want being low priority --- RemoteIDModule/CANDriver.cpp | 11 +++++++---- RemoteIDModule/CANDriver.h | 2 +- RemoteIDModule/DroneCAN.cpp | 20 +++++++++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/RemoteIDModule/CANDriver.cpp b/RemoteIDModule/CANDriver.cpp index c742700..46cd647 100644 --- a/RemoteIDModule/CANDriver.cpp +++ b/RemoteIDModule/CANDriver.cpp @@ -33,8 +33,14 @@ CANDriver::CANDriver() {} -void CANDriver::init(uint32_t bitrate) +static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS(); +static twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); + +void CANDriver::init(uint32_t bitrate, uint32_t acceptance_code, uint32_t acceptance_mask) { + f_config.acceptance_code = acceptance_code; + f_config.acceptance_mask = acceptance_mask; + f_config.single_filter = true; init_bus(bitrate); } @@ -45,9 +51,6 @@ static const twai_general_config_t g_config = {.mode = TWAI .intr_flags = ESP_INTR_FLAG_LEVEL2 }; -static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS(); -static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); - void CANDriver::init_once(bool enable_irq) { if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) diff --git a/RemoteIDModule/CANDriver.h b/RemoteIDModule/CANDriver.h index 39e79d0..467ac57 100644 --- a/RemoteIDModule/CANDriver.h +++ b/RemoteIDModule/CANDriver.h @@ -4,7 +4,7 @@ struct CANFrame; class CANDriver { public: CANDriver(); - void init(uint32_t bitrate); + void init(uint32_t bitrate, uint32_t acceptance_code, uint32_t acceptance_mask); bool send(const CANFrame &frame); bool receive(CANFrame &out_frame); diff --git a/RemoteIDModule/DroneCAN.cpp b/RemoteIDModule/DroneCAN.cpp index 8e5ca3f..55cd066 100644 --- a/RemoteIDModule/DroneCAN.cpp +++ b/RemoteIDModule/DroneCAN.cpp @@ -52,7 +52,25 @@ void DroneCAN::init(void) gpio_reset_pin(GPIO_NUM_20); #endif - can_driver.init(1000000); + /* + the ESP32 has a very inefficient CAN (TWAI) stack. If we let it + receive all message types then when the bus is busy it will + spend all its time in processRx(). To cope we need to use + acceptance filters so we don't see most traffic. Unfortunately + the ESP32 has a very rudimentary acceptance filter system which + cannot be setup to block the high rate messages (such as ESC + commands) while still allowing all of the RemoteID messages we + need. The best we can do is use the message priority. The high + rate messages all have a low valued priority number (which means + a high priority). So by setting a single bit acceptance code in + the top bit of the 3 bit priority field we only see messages + that have a priority number of 16 or higher (which means + CANARD_TRANSFER_PRIORITY_MEDIUM or lower priority) + */ + const uint32_t acceptance_code = 0x10000000U<<3; + const uint32_t acceptance_mask = 0x0FFFFFFFU<<3; + + can_driver.init(1000000, acceptance_code, acceptance_mask); canardInit(&canard, (uint8_t *)canard_memory_pool, sizeof(canard_memory_pool), onTransferReceived_trampoline, shouldAcceptTransfer_trampoline, NULL);