Kaynağa Gözat

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
Andrew Tridgell 2 yıl önce
ebeveyn
işleme
a9869b4955

+ 7 - 4
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)

+ 1 - 1
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);

+ 19 - 1
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);