Search code examples
cuartcrc

How is tmc2209 stepper driver IC calculating CRC?


I have tmc2209 stepper driver. I am planning to use UART for communication. The communication protocol looks pretty simple, but I can't figure out how to calculate this damn CRC. The polynomial is CRC-8 0x07. For the message 0x05 0x00 0x00 the correct CRC is 0x48 and for message 0x05 0x00 0x06 is correct CRC 0x6F. I know this because I have brute forced all possible combinations for these messages and with correct CRC tmc2209 responses. When I calculate CRC manually for these messages it doesn't match. They have some CRC example calculation in datasheet but this code looks broken for me. Here is the datasheet: https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2209_Datasheet_V103.pdf UART starts at page 15 and CRC calculation is on page 17.


Solution

  • CRC located in last byte of message, add return datagram[datagramLength - 1]; on last method, you will get that crc value. Look at this:

    #include <stdio.h>
    #include <stdint.h>
    
    uint8_t swuart_calcCRC (uint8_t * datagram, uint8_t datagramLength) {
      int i, j;
      uint8_t *crc = datagram + (datagramLength - 1);   // CRC located in last byte of message
      uint8_t currentByte;
      *crc = 0;
      for (i = 0; i < (datagramLength - 1); i++) {      // Execute for all bytes of a message
          currentByte = datagram[i];                    // Retrieve a byte to be sent from Array
          for (j = 0; j < 8; j++) {
              if ((*crc >> 7) ^ (currentByte & 0x01)) { // update CRC based result of XOR operation
                  *crc = (*crc << 1) ^ 0x07;
              }
              else {
                  *crc = (*crc << 1);
              }
              currentByte = currentByte >> 1;
          }         // for CRC bit
      }             // for message byte
      return datagram[datagramLength - 1];
    }
    
    
    int main () {
      uint8_t datagram1[] = { 0x05, 0x00, 0x00, 0x00 };
      uint8_t datagram2[] = { 0x05, 0x00, 0x06, 0x00 };
      uint8_t length = 4;
    
      uint8_t crc1 = swuart_calcCRC (datagram1, length);
      printf ("crc1: %02X\n", crc1);
    
      uint8_t crc2 = swuart_calcCRC (datagram2, length);
      printf ("crc2: %02X\n", crc2);
    
      return 0;
    }
    

    Result:

    crc1: 48
    crc2: 6F