This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

CRC8 Check in NRF Connect 1.8.0

Hello,

I am working with a sensor that generates a simple crc8 XOR on based on this code from the nrf sdk 17 and sends it to a central:

#include <stdio.h>
#include <string.h>
#include <math.h>

static unsigned int L2_calculate_crc(unsigned char *buffer_ptr, unsigned int count)
   {
   register unsigned int crc_reg;
   register unsigned char bit_count;

   #define CRC_GEN_POLY  (0x11021)   /* CRC-CCITT (X^^16 + X^^12 + X^^5 + 1): */
   #define CRC_WORK_POLY (0x08408)   /* Bit order reversed to match Tx order */

   /*
    * Initialize the working register to all one bits.
    * This is equivalent to initializing to zero and then
    * inverting the first sixteen message bits.
    */

   crc_reg = 0xFFFF;

   /* Loop for each byte in the message */
   do
      {
      crc_reg ^= (unsigned int)*buffer_ptr;
      ++buffer_ptr;
​
      for (bit_count=8; bit_count; --bit_count)
         {
         if (crc_reg & 0x01)
            {

            /*
             * Bit ready to be shifted off the right is a one.
             * A division is possible.  This bit is logically
             * XORed with the implied "testing" bit below
             * bit zero of the working polynomial.
             */

            crc_reg >>= 1;
            crc_reg ^= CRC_WORK_POLY;
            }
         else
            {

            /*
             * Bit ready to be shifted off the right is a zero.
             * No division is possible.  Just shift right one bit.
             */

            crc_reg >>= 1;
            }
         }/*end for each bit*/
      } while (--count);

   /* Return the one's complement of the calculated remainder. */
   return (~crc_reg);
   }

char CalculateSum8 (__uint8_t *Buffer, __uint16_t Length)
{
  __uint8_t     Sum;
  __uint16_t     Count;

  for (Sum = 0, Count = 0; Count < Length; Count++) {
    Sum = (__uint8_t) (Sum + *(Buffer + Count));
  }

  return Sum;
}
char CalculateCheckSum8 ( __uint8_t *Buffer, __uint16_t Length)
{
  __uint8_t     CheckSum;
  CheckSum = CalculateSum8 (Buffer, Length);
  return (__uint8_t) (0x100 - CheckSum);
}




int main()
{   unsigned char crc[2]  ={0xff,0xff};
    printf("Test CRC8 generation\n");

                                /*66    11      01      1650861179				'e'*/
    unsigned char array1[]   ={ 0x42 ,  0x0B ,  0x01 ,  0x62,0x66,0x24,0x7B ,	0x65}; 
                            
    unsigned char crc_value;
    unsigned char *buffer_ptr  = array1;
    unsigned int count = sizeof(array1);
    
    crc_value = CalculateCheckSum8(buffer_ptr,count); // test function
    printf("crc_value: 0X%X\n",crc_value);

    return 0;
   
}

I need to check this CRC8 on the central and noticed that zephyr had a crc8 function: https://docs.zephyrproject.org/apidoc/latest/group__crc.html#ga9a925de71cd0255a22c769dc4b130da5
but that it required a polynomial and initial value.  Can this be configured to be compatible with the crc8 check done from the nrf sdk 17 so that I can check the crc8 code sent from the sensor?

  • Hello,

    Since you already have a simple CRC8 function at hand, I suggest that you just copy it into your NCS application.

    If you really want to use the existing CRC8 function, just look at the implementation to figure out what the initial value and polynomial value is. I have not studied them, but I would guess the initial value is the initial value of crc_reg (0xFFFF) in your old function, and that the polynomial is either CRC_GEN_POLY or CRC_WORK_POLY from your old function.

    Best regards,

    Edvin

  • Okay I was able to port it directly, that's definitely the best option thanks.  The issue I'm running into now is that I'm receiving a byte array that is being cast to decimal when it's saved.

    For example the first byte coming in is 0x58, but the value stored in my data array is 88.  For the crc check to function properly I need to pass it the same number of bytes in their hex form.  So just passing the first member of the data array (88) fails the check. I also can't do something like convert the data to a hex string since it would increase the length.  Is there a 1:1 method to pass my data array as hex and not as decimal?

    In memory the first member of the array should be in its hex form, so is there a way to dereference the memory location to get the hex value?  Or is there a better way?

  • Are you sure that it is actually an issue with decimal to hexadecimal conversion? 0x58 is equal to (dec)88. They are identical in the memory. The only difference is when you print the data, whether you choose to print with %d or %x. 

    If I have a function:

    void my_function(uint8_t input_number)
    {
        printk("hexadecimal 0x%02x", input_number);
        printk("decimal %d", input_number);
    }

    This function would behave exactly the same if I call:

    my_function(0x58);

    and

    my_function(88);

    So I suspect that if you see any issues, they are caused by something else. 

    What do you see, exactly?

    Best regards,

    Edvin

  • You're right, I think there was a difference in the string that was coming in because I checked it with test data, one array initialized with bytes ie: 0x52, 0x48, then the other with decimal ie: 82,72 and the check comes back the same for both.  

    Thanks for the help!

Related