Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- fuck the stupid forum, seriously.
- Greetings.
- I've stumbled upon what i believe is a serious bug (or a serious case of me not knowing how to declare bitfields in C)
- I've updated a design that uses CANBUS with the dsPIC33CK256MP502 and i'm having problems because the ID is not correct.
- Upon investigation, the ID is not correct because the memory buffer for the ID IS NOT CORRECT!
- In fact, if i write directly to the fifo area the correct ID, the correct ID is transferred.
- To make things more portable between architectures my CAN library uses several layers and types... Unfortunately that's necessary to mantain sanity.
- To the scope of this example i have two different structures that hold a CAN frame, one that i call "can_t" which has the frame in human-readable format, as it will appear on a bus decoder, defined as such
- [code]
- typedef volatile struct {
- uint32_t id; //Message ID
- uint8_t format; //STD or EXT
- uint8_t type; //RTR or DATA
- uint8_t unused; //Unused byte so the structure size is a power of two -> 16 bytes
- uint8_t data_lenght; //Number of Data Bytes
- uint8_t data[8]; //Up to 8 Data Bytes
- } can_t;[/code]
- Then i have the "MCU" layer which will have the function for the controller used by the target MCU that will take a frame and put it in memory and set the appropriate bit fields and vice versa. for the 33CK which uses the new CAN FD Module, i have defined the TX FIFO ENTRY as it is done in the reference manual
- [code]typedef union {
- volatile struct {
- struct {
- uint16_t SID_l :11;
- uint16_t EID_l :5;
- } T0;
- struct {
- uint16_t EID_h :13;
- uint16_t SID_h :1;
- uint16_t :2;
- } T1;
- struct {
- uint16_t DLC :4;
- uint16_t IDE :1;
- uint16_t RTR :1;
- uint16_t BRS :1;
- uint16_t FDF :1;
- uint16_t ESI :1;
- uint16_t SEQ_l :7;
- } T2;
- struct {
- uint16_t SEQ_h;
- } T3;
- struct {
- uint16_t data0 :8;
- uint16_t data1 :8;
- } T4;
- struct {
- uint16_t data2 :8;
- uint16_t data3 :8;
- } T5;
- struct {
- uint16_t data4 :8;
- uint16_t data5 :8;
- } T6;
- struct {
- uint16_t data6 :8;
- uint16_t data7 :8;
- } T7;
- };
- uint16_t word[8];
- } canFDtxFifoEntry_t;[/code]
- *** It would be a struct, now it is temporarly an union so i can se the actual memory content
- so, somewhere in my code i have a call to the function that takes the data from can_t and put it in the buffer... and there i have this block of code
- [code]if (can_frame->format == CAN_FORMAT_EXT) {
- txMsg.T2.IDE = 1;
- txMsg.T0.SID_l = can_frame->id & 0x7FF;
- txMsg.T0.EID_l = can_frame->id >> 11;
- txMsg.T1.EID_h = can_frame->id >> 16;
- txMsg.T1.SID_h = 0;
- }
- else {
- txMsg.T2.IDE = 0;
- txMsg.T0.SID_l = can_frame->id;
- txMsg.T0.EID_l = 0;
- txMsg.T1.EID_h = 0;
- txMsg.T1.SID_h = 0;
- }[/code]
- which, to me, seems correct C. I have tens of projects where i do these things and i never had issues before, also we all do this all the time when manipulating registers.
- I am having a completely wrong ID in extended mode and a truncated ID in standard mode so i checked the disassembly. With -O1, Commented by me
- [code]
- 230: txMsg.T0.SID_l = can_frame->id;
- 001976 BE0211 MOV.D [W1], W4 ;Move ID (32bit) to WREG4-5. Correct
- 001978 207FF2 MOV #0x7FF, W2 ;Move the bitfield mask to W2. Correct
- 00197A 610184 AND W2, W4, W3 ;Apply the mask. Correct
- 00197C 97F20F MOV.B [W15-16], W4 ;Takes the first byte of the structure and put it in WREG4. Why?? it should be the whole register as it's uint16.
- 00197E 0A03A0 BFINS #0x0, #0xb, W3, W4 ;Apply the data to the bitfield. Correct
- 001980 000004 NOP
- 001982 9FF784 MOV.B W4, [W15-16] ;Write back the new value... but only the low byte. Why??? It's a 11 bit field.
- [/code]
- There are these two byte instructions and i don't understand why. They are producing the wrong output because the higher byte is never changed and remains with whatever wrong content it has be
- With -O0 instead no byte mode instructions and no bitfield instructions are used. The resulting Frame ID is correct.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement