Calculating 802.15.4 CRC

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm having a devil of a time calculating the 802.15.4 CRC value. I have, for instance, the string

[9     1   128     1     0     0     0     4    23   215]

where the first value is the length of data values, not counting the length value itself, and the final two values are the FCS (Frame Check Sequence, which is the CRC).

My CRC algorithm (CRC-CCITT 16-bit checksum) works with the example input strings I have found on the internet. Great. That's the hard part down. Now I just need to feed it the right string. Only...

No matter the combination I cannot reproduce the correct FCS values. According to the 802.15.4 specifications, the FCS field is "calculated over the MHR and MAC payload parts of the frame". Which is already a confusing statement. (Over? Does that mean the two together, as if they were one long sequence, or does that perhaps mean something else?)

Again, according to the docs (Fig. 5.5.3.2 in IEEE Std 802.15.4-2005), the frame length (first value) is not part of the MHR and MAC payload, nor are the FCS (last two values). So that should, in theory, mean that the correct string is

[1   128     1     0     0     0     4]

only that doesn't give the right CRC. Nor does it if I reverse the order of the bits in the in each individual byte (that is to say, switch the endianness). Nor does it for any LINEAR combination of the above set.

So I've been bashing my head for over an hour, and I cannot find any source that gives me a worked example of an entire packet. Can someone out there help?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wonder why you need to calculate it? The chip generates/checks it. Perhaps you are doing some test equipment to validate the chips' calculation?

If MAC ACKs are enabled (and normally they are), then if the CRC is correct, the receiving device sends an ACK to the transmitting device (excluding broadcast frames).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to calculate it because I'm sending the data from the RF module to Matlab across an Arduino and then USB, so I get spurious data a little too often. I'd like to be able to use the built-in checksum rather than having to implement another one in the data stream (I'm on an extremely tight bandwidth budget, so I'd like to avoid adding to the overhead).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is how atmel did it in the contiki radio driver

void
hal_frame_read(hal_rx_frame_t *rx_frame)
{
    uint8_t *rx_data=0;

    AVR_ENTER_CRITICAL_REGION();

    HAL_SS_LOW();

    /*Send frame read command.*/
    SPDR = HAL_TRX_CMD_FR;
    while ((SPSR & (1 << SPIF)) == 0) {;}
    uint8_t frame_length = SPDR;

    /*Read frame length.*/
    SPDR = frame_length;
    while ((SPSR & (1 << SPIF)) == 0) {;}
    frame_length = SPDR;

    /*Check for correct frame length.*/
    if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){
        uint16_t crc = 0;
        rx_data = (rx_frame->data);
        rx_frame->length = frame_length;

        /*Upload frame buffer to data pointer. Calculate CRC.*/
        SPDR = frame_length;
        while ((SPSR & (1 << SPIF)) == 0) {;}

        do{
            uint8_t tempData = SPDR;
            SPDR = 0;       /*  dummy write */
            *rx_data++ = tempData;
            crc = _crc_ccitt_update(crc, tempData);

            while ((SPSR & (1 << SPIF)) == 0) {;}

        } while (--frame_length > 0);

        /*Read LQI value for this frame.*/
        rx_frame->lqi = SPDR;       
        HAL_SS_HIGH();

        /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/
        rx_frame->crc = (crc == HAL_CALCULATED_CRC_OK);
    } else {
        HAL_SS_HIGH();
        rx_frame->length = 0;
        rx_frame->lqi    = 0;
        rx_frame->crc    = false;
    }

    AVR_LEAVE_CRITICAL_REGION();
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The UDP checksum is a word checksum. I guess the guy that wrote it was on a 16 bit cpu?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kubark42 wrote:
I want to calculate it because I'm sending the data from the RF module to Matlab across an Arduino and then USB, so I get spurious data a little too often. I'd like to be able to use the built-in checksum rather than having to implement another one in the data stream (I'm on an extremely tight bandwidth budget, so I'd like to avoid adding to the overhead).

The 802.15.4 frame check (CRC) is not normally available to you - you get only the payload data after checking.

so if you are merely taking 802.15.4 payload data, which is error free IF you have MAC ACKs turned on in the MAC settings... you should get no spurious data. If you ignore data from invalid source MAC addresses, and ignore broadcast data.

Sounds like you may have a flow control issue or some such going to the PC with Matlab, likely via RS232. That really has nothing to do with 802.15.4 but is a buffering issue on the PC.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stevech wrote:
The 802.15.4 frame check (CRC) is not normally available to you - you get only the payload data after checking.

The Microchip MRF24J40 includes the FCS as part of the received message.

Quote:

so if you are merely taking 802.15.4 payload data, which is error free IF you have MAC ACKs turned on in the MAC settings... you should get no spurious data. If you ignore data from invalid source MAC addresses, and ignore broadcast data.

Sounds like you may have a flow control issue or some such going to the PC with Matlab, likely via RS232. That really has nothing to do with 802.15.4 but is a buffering issue on the PC.

Yup, that's absolutely correct. It's also something that I cannot fix, so I have to live with it. My idea is to use the already existing CRC checksum so that I don't have to use up bandwidth creating a new packet protocol.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dak664 wrote:
Here is how atmel did it in the contiki radio driver...

Unfortunately, that doesn't really give me something I can sink my teeth into. I can see what bytes it's using to calculate the FCS, but I can't see what those bytes correspond to. Are they the MHR? The Payload? Other things I don't have access to?

It's all quite frustrating. I would love a worked example. It could be that my chip isn't reporting all the information necessary, if in theory the FCS is already "used up"-- that is to say that the hardware has verified that it's a good transmission and thus is *not* transmitting to the RX_FIFO register all the bytes necessary for making the FCS.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To calculate a CRC8 on the received data and forward the data + CRC8 on a different comms link is not very compute intensive. CRC8 via table lookup is fast and since an 802.15.4 payload is at most about 100 bytes or less, CRC8 is probably good enough for reliable error detection. Heck, even a 16 bit half-sum would do and that's quite fast.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stevech wrote:
To calculate a CRC8 on the received data and forward the data + CRC8 on a different comms link is not very compute intensive. CRC8 via table lookup is fast and since an 802.15.4 payload is at most about 100 bytes or less, CRC8 is probably good enough for reliable error detection. Heck, even a 16 bit half-sum would do and that's quite fast.

That's all true, but it's added bytes and computation time (I would also need to add an additional byte as a message header so I can be sure that I have started the message in the appropriate spot) for something that has already been done for me. It seems better to use what is already existing then to reinvent the wheel.

No one knows anything about 802.15.4?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The 802.15.4 checksum is a bit of a devil, mostly due to a very poorly worded spec. The computation is done over the header starting at the frame control field (the frame length is NOT included) and the payload section. The fun part is CCITT algorithm... which they actually don't implement properly. 802.15.4 feeds the shift register in the opposite direction, so you need to reverse the bits of every byte you feed in to your routine. Don't forget to initialize your CRC to all 0s (the normal algorithm starts with all 1s, at least the one I've been using for the last 9 years). When you're done and having gotten past the 16 padding zeroes at the end of the compution, you need to again reverse the bits in the final crc value, because the shift register shifts them out in the wrong direction.

While you're at it, you should double check your frame control field, since you probably assumed that 802.15.4 follows convention and has the MSB on the leftmost side of a word. This is not the case, LSB is on the left, so you need to reverse that field.

I'm not sure about the other fields (addressing mostly), but they are probably reversed too. That hasn't been a problem for me since my devices only talk to themselves. If you want to be compatible with other 802.15.4 devices, I would recommend getting a packet sniffer and protocol analyzer to help you verify your frames are constructed properly. I've used the Microchip ZENA, it's cheap and works great.

I do the FCS, retries, and acks in software, mainly because when I originally tried to enable hardware FCS and acks I had the frame control field reversed so the chip wouldn't send the frames properly. After I'd figured that out, I already had the working software implementation, so I've left that for now. That being said, most chips will do all of that heavy lifting for you, so it would be worth it to try and get that to work. I plan to once I have time.

Also, technically the turnaround time for acks is very short, and quite difficult to meet in software. It will probably still work though.

I hope that helps!

-JeremyB

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note that at least with the ATARF231, the receive buffer can be overwritten with new data while it is being read out. This can combine two packets each of which satisfied the hardware CRC. Ouch!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fix the flow control problem. Either with software messaging protocol or hardware RTS/CTS