I don't have a dsPIC33EP256MU806 to test with, bit I was able to dig up a test platform for a dsPIC33EP512MU810, which I used in a project some years ago.
The reason that I mention this is because, in my experience, different MCUs with CRC modules have different functionality, and direct personal experience with, say, a PIC24FJ1024GB610 does not exactly carry over to, say a dsPIC33EP512MU810 or a PIC16F1619.
To keep things simple, I'll give an example with straight calculations, no interrupts or any other fancy stuff.
Bottom line for the disclaimer: I am telling what works for me with a dsPIC33EP512MU810. Since there is no CRC errata that I know of for any chips in this family, I would be shocked if there is any different functionality for a dsPIC33EP256MU806.
OK, here are some "issues" with the O.P. code
This is for an 8-bit CRC being fed 8 bits at a time. This is the simplest case, and there are no problems with odd numbers of bytes or other things that make other cases somewhat more problematic.
So: This is absolutely wrong:
CRCDATL = 0x10; // As a test CRC a single byte
CRCDATL is a 16-bit register. The compiler generates code that writes 16 bits to CRCDATL: One byte is your data (that's good), and an extra byte that results from promoting your data to a 16-bit integer (that's bad---Very Bad). So every place in your code where you have an assignment to CRCDATL, the code must be changed so that it only writes eight bits
One way to do this is to define a pointer. Maybe like this:
uint8_t *dest = (uint8_t *)&CRCDATL;
This will not change for the duration of the calculation.
Now, instead of the assignment statement to CRCDATL, you would have
*dest = 0x10; // Or whatever
Secondly, I don't know where the guy who wrote the thing in the Family Reference Manual (about the CRCGO bit resetting itself) got the information or what chip that refers to, but I absolutely, positively, guarandamtee that it is not true for this chip (or any other Microchip MPU that I have ever used). GO stays set until you clear it. At least that's my experience. I'll talk about that in a minute.
Thirdly, when you have shifted all of the data bytes through the CRC engine, the last byte is still in the internal CRC shift register, which is not visible to the outside world. (This may or may not be true for other chips, but is definitely true for this chip.)
So, after all of the data have been exhausted, then you write an extra eight bits to shift all of the bits to the CRCWDATL register so that you can retrieve it for your use. I just write eight zero bits.
That is, after all data have been shifted, there is another statement like this
*dest = 0x00; /* Do this to shift the last word out of the CRC shift register */
Bottom line for calculations: After your program has transferred all of the bytes to the CRC register, and the final zero byte, wait until TRMT is 1, then clear the GO bit and read the value of CRCWDATL. Period. Full Stop.
Finally (for now), we gotta talk about the the "LENDIAN" thing. This is a convenience, not found on older chips, that allows you to feed data bytes in the same order that they were calculated and have them shifted into the CRC engine LSB first. Nothing is changed in the way that the CRC is calculated. The final result in the CRC registers is the true, mathematical CRC.
This is important in the following case (the case we are testing: MAXIM CRC stuff, as document in Maxim Application Note AN27)
We have seven data bytes. We calculate the CRC of those bytes with LENDIAN=1, and we want to append a value to the data stream so that the total CRC for the resulting eight bytes is zero.
You have to reverse the bits of the mathematical CRC from the CRC module and put that byte into the array, since those bits will be reversed when they get shifted into the CRC register. Really. You have to reverse the bits (if and only if LENDIAN is 1).
The other end doesn't know or care how you calculated the byte that you appended to the data. It simply calculates the CRC for all eight bytes and expects to get zero. (That is, assuming there is some higher level protocol that tells the other end where the data stream starts and stops.)
I have attached a part of the test program that uses your data. I used your seven data bytes. Just to illustrate partial CRC results, I did a separate calculation using one byte, two bytes, three, bytes, etc. For purposes of illustration, the CRC routine does not reverse the results before returning. I wanted to show what the CRC engine calculates, and then show the reversed value. The only one of those reversed values that I used is the one from the 7-byte sequence.
Finally, I took the result from the 7-byte calculation, appended its bit-reversed value to the seven original data bytes and show the CRC results for those eight.
Here's the output:
Compiled on May 17 2018 at 14:37:24 PDT with XC16 version 1034
The original data: 0x10 0x92 0xC8 0x72 0x03 0x08 0x00
Calculating CRC for number of bytes = 1,2,...,7
Number of Hardware Bit-Reversed
Bytes CRC CRC
1 0xB9 0x9D
2 0x82 0x41
3 0x08 0x10
4 0x9B 0xD9
5 0x94 0x29
6 0xBE 0x7D
7 0xA0 0x05
Appended the (reversed) 7-byte CRC value to the original data.
The entire stream: 0x10 0x92 0xC8 0x72 0x03 0x08 0x00 0x05
Calculating CRC for the entire eight bytes
Hardware CRC Value = 0x00, reversed = 0x00
post edited by davekw7x - 2018/05/18 06:38:20