I've been messing around with the BMS master hardware instead of welding stuff together. I'm trying to send a CAN message and, rather than write my own library from the datasheet, I tried to use Microchip application note AN878. It was easy to adjust so it would compile with SDCC but I seem to have found a bug in the compiler.
Because the PIC is a Harvard Architecture CPU, pointers to code and pointers to data are handled differently, which SDCC implements by adding some extra bits to the pointer. Unfortunately it's possible to loose those bits while casting the address of an SFR to a pointer and assigning that to a pointer array element by index.
With the the bits cleared, the write-to-pointer-target helper will do nothing, leaving the pointer on the stack. When it returns, the rest of the code freaks out because it expects the pointer to have been popped off the stack.
The solution (apart from fixing the compiler bug) is to leave out the cast. It seems that assigning an SFR to a pointer array element doesn't actually need a cast.
| BAD | pb[1] = (unsigned char *) &TXB0CON; |
|---|
| GOOD | pb[1] = &TXB0CON; |
|---|