From 7f9c9de134dcd1fe5244fdbfbea0783469190dfb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 28 Sep 2024 10:12:52 +1000 Subject: [PATCH] dshot: check for bad pulses and handle wrap correctly this ensures we handle timer wrap correctly, fixing bad dshot frames with ArduPilot, and also checks for much too narrow or wide pulses by making variables static this also saves flash and ram. Using REF_F031 as the benchmark we get: current REF_F031: Memory region Used Size Region Size %age Used SRAM: 0 GB 192 B 0.00% RAM: 3760 B 3904 B 96.31% FLASH_VECTAB: 192 B 192 B 100.00% FLASH_VERSION: 16 B 16 B 100.00% FLASH: 23260 B 27408 B 84.87% FILE_NAME: 32 B 32 B 100.00% EEPROM: 0 GB 1 KB 0.00% with this PR: Memory region Used Size Region Size %age Used SRAM: 0 GB 192 B 0.00% RAM: 3704 B 3904 B 94.88% FLASH_VECTAB: 192 B 192 B 100.00% FLASH_VERSION: 16 B 16 B 100.00% FLASH: 23244 B 27408 B 84.81% FILE_NAME: 32 B 32 B 100.00% EEPROM: 0 GB 1 KB 0.00% so we save 54 bytes of ram and 16 bytes of flash, while fixing the wrap issue and adding pulse width checks --- Src/dshot.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/Src/dshot.c b/Src/dshot.c index 218b5ba5..bc0e6e14 100644 --- a/Src/dshot.c +++ b/Src/dshot.c @@ -12,45 +12,47 @@ #include "sounds.h" #include "targets.h" -int dpulse[16] = { 0 }; +static uint8_t dpulse[16]; -const char gcr_encode_table[16] = { +static const uint8_t gcr_encode_table[16] = { 0b11001, 0b11011, 0b10010, 0b10011, 0b11101, 0b10101, 0b10110, 0b10111, 0b11010, 0b01001, 0b01010, 0b01011, 0b11110, 0b01101, 0b01110, 0b01111 }; -char EDT_ARM_ENABLE = 0; -char EDT_ARMED = 0; -int shift_amount = 0; -uint32_t gcrnumber; +char EDT_ARM_ENABLE; +char EDT_ARMED; +static int shift_amount; +static uint32_t gcrnumber; extern int zero_crosses; extern char send_telemetry; extern uint8_t max_duty_cycle_change; -int dshot_full_number; +static uint32_t dshot_full_number; extern char play_tone_flag; -uint8_t command_count = 0; -uint8_t last_command = 0; -uint8_t high_pin_count = 0; -uint32_t gcr[37] = { 0 }; -uint16_t dshot_frametime; -uint16_t dshot_goodcounts; -uint16_t dshot_badcounts; -char dshot_extended_telemetry = 0; -uint16_t send_extended_dshot = 0; -uint16_t processtime = 0; -uint16_t halfpulsetime = 0; +static uint8_t command_count; +static uint8_t last_command; +static uint8_t high_pin_count; +uint32_t gcr[37]; +static uint16_t dshot_frametime; +static uint16_t dshot_goodcounts; +static uint16_t dshot_badcounts; +char dshot_extended_telemetry; +uint16_t send_extended_dshot; +static uint16_t halfpulsetime; void computeDshotDMA() { dshot_frametime = dma_buffer[31] - dma_buffer[0]; halfpulsetime = dshot_frametime >> 5; if ((dshot_frametime > dshot_frametime_low) && (dshot_frametime < dshot_frametime_high)) { - signaltimeout = 0; + signaltimeout = 0; for (int i = 0; i < 16; i++) { - // note that dma_buffer[] is uint32_t, we cast the difference to uint16_t to handle - // timer wrap correctly - const uint16_t pdiff = dma_buffer[(i << 1) + 1] - dma_buffer[(i << 1)]; - dpulse[i] = (pdiff > halfpulsetime); + const uint16_t pwidth = dma_buffer[(i << 1) + 1] - dma_buffer[(i << 1)]; + if (pwidth < (halfpulsetime>>1) || pwidth > (halfpulsetime<<1)) { + // pulse width way off, bad frame + dshot_badcounts++; + return; + } + dpulse[i] = (pwidth > halfpulsetime); } uint8_t calcCRC = ((dpulse[0] ^ dpulse[4] ^ dpulse[8]) << 3 | (dpulse[1] ^ dpulse[5] ^ dpulse[9]) << 2 | (dpulse[2] ^ dpulse[6] ^ dpulse[10]) << 1 | (dpulse[3] ^ dpulse[7] ^ dpulse[11])); uint8_t checkCRC = (dpulse[12] << 3 | dpulse[13] << 2 | dpulse[14] << 1 | dpulse[15]);