View previous topic :: View next topic |
Author |
Message |
NePe
Joined: 21 Jun 2011 Posts: 9
|
mmcsd driver mmcsd_crc16 function alway return 1 |
Posted: Tue Apr 24, 2012 10:05 am |
|
|
I want to use the mmcsd driver with crc but, the crc16 function always return 1.
The source of the function:
Code: |
uint16_t mmcsd_crc16(char *data, uint8_t length)
{
uint8_t i, ibit, c;
uint16_t crc;
crc = 0x0000; // Set initial value
for (i = 0; i < length; i++, data++)
{
c = *data;
for (ibit = 0; ibit < 8; ibit++)
{
crc = crc << 1;
if ((c ^ crc) & 0x8000) crc = crc ^ 0x1021; // ^ is XOR
c = c << 1;
}
crc = crc & 0x7FFF;
}
shift_left(&crc, 2, 1); // MMC card stores the result in the top 7 bits so shift them left 1
// Should shift in a 1 not a 0 as one of the cards I have won't work otherwise
return crc;
}
|
The problem is that (c ^ crc) & 0x8000 never return 1 when I tested.
CCS version 4.124
How can I fix the driver? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Tue Apr 24, 2012 10:47 am |
|
|
hmmm...
you've defined 'c' as an 8 bit value, 'crc' as a 16 bit...
..best check the listing to see what the compiler does about that.. |
|
|
NePe
Joined: 21 Jun 2011 Posts: 9
|
|
Posted: Tue Apr 24, 2012 11:30 am |
|
|
The asm version of the c code:
Code: |
if ((c ^ crc) & 0x8000) {
331C: MOVF xCD,W
331E: XORWF xD0,W
3320: MOVWF xD2
3322: MOVF xD1,W
3324: MOVWF xD3
3326: ANDLW 00
3328: MOVWF 00
332A: MOVF xD3,W
332C: ANDLW 80
332E: MOVWF 03
3330: MOVF 00,W
3332: IORWF 03,W
3334: BZ 333E
|
It seams that the (c ^ crc) is a 8 bit value, when its bitwise anded with a 0x8000 the result is always 0.
This function is the original code from the mmcsd.c
I think that the developers never tested it.
It's a bug, i know that, but how can fix it ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Apr 24, 2012 2:40 pm |
|
|
I suspect they did test it, but before latter compilers. The way that things like this are extended or trimmed is an area where various compiler versions have changed. Simply use a cast:
Code: |
if ((((int16)c) ^ crc) & 0x8000) crc = crc ^ 0x1021;
|
This forces 'c' to be extended into an int16 before the operation. Being explicit with casting in CCS, can avoid a lot of compiler problems....
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
|
|