Advertisement
Guest User

Untitled

a guest
Apr 11th, 2019
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.27 KB | None | 0 0
  1. fuck the stupid forum, seriously.
  2.  
  3. Greetings.
  4. 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)
  5.  
  6. I've updated a design that uses CANBUS with the dsPIC33CK256MP502 and i'm having problems because the ID is not correct.
  7. Upon investigation, the ID is not correct because the memory buffer for the ID IS NOT CORRECT!
  8. In fact, if i write directly to the fifo area the correct ID, the correct ID is transferred.
  9.  
  10. To make things more portable between architectures my CAN library uses several layers and types... Unfortunately that's necessary to mantain sanity.
  11. 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
  12.  
  13. [code]
  14. typedef volatile struct {
  15. uint32_t id; //Message ID
  16. uint8_t format; //STD or EXT
  17. uint8_t type; //RTR or DATA
  18. uint8_t unused; //Unused byte so the structure size is a power of two -> 16 bytes
  19. uint8_t data_lenght; //Number of Data Bytes
  20. uint8_t data[8]; //Up to 8 Data Bytes
  21. } can_t;[/code]
  22.  
  23. 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
  24.  
  25. [code]typedef union {
  26. volatile struct {
  27. struct {
  28. uint16_t SID_l :11;
  29. uint16_t EID_l :5;
  30. } T0;
  31. struct {
  32. uint16_t EID_h :13;
  33. uint16_t SID_h :1;
  34. uint16_t :2;
  35. } T1;
  36. struct {
  37. uint16_t DLC :4;
  38. uint16_t IDE :1;
  39. uint16_t RTR :1;
  40. uint16_t BRS :1;
  41. uint16_t FDF :1;
  42. uint16_t ESI :1;
  43. uint16_t SEQ_l :7;
  44. } T2;
  45. struct {
  46. uint16_t SEQ_h;
  47. } T3;
  48. struct {
  49. uint16_t data0 :8;
  50. uint16_t data1 :8;
  51. } T4;
  52. struct {
  53. uint16_t data2 :8;
  54. uint16_t data3 :8;
  55. } T5;
  56. struct {
  57. uint16_t data4 :8;
  58. uint16_t data5 :8;
  59. } T6;
  60. struct {
  61. uint16_t data6 :8;
  62. uint16_t data7 :8;
  63. } T7;
  64. };
  65. uint16_t word[8];
  66. } canFDtxFifoEntry_t;[/code]
  67.  
  68. *** It would be a struct, now it is temporarly an union so i can se the actual memory content
  69.  
  70.  
  71.  
  72. 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
  73.  
  74. [code]if (can_frame->format == CAN_FORMAT_EXT) {
  75. txMsg.T2.IDE = 1;
  76. txMsg.T0.SID_l = can_frame->id & 0x7FF;
  77. txMsg.T0.EID_l = can_frame->id >> 11;
  78. txMsg.T1.EID_h = can_frame->id >> 16;
  79. txMsg.T1.SID_h = 0;
  80. }
  81. else {
  82. txMsg.T2.IDE = 0;
  83. txMsg.T0.SID_l = can_frame->id;
  84. txMsg.T0.EID_l = 0;
  85. txMsg.T1.EID_h = 0;
  86. txMsg.T1.SID_h = 0;
  87. }[/code]
  88.  
  89.  
  90.  
  91. 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.
  92.  
  93.  
  94.  
  95. 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
  96.  
  97. [code]
  98. 230: txMsg.T0.SID_l = can_frame->id;
  99. 001976 BE0211 MOV.D [W1], W4 ;Move ID (32bit) to WREG4-5. Correct
  100. 001978 207FF2 MOV #0x7FF, W2 ;Move the bitfield mask to W2. Correct
  101. 00197A 610184 AND W2, W4, W3 ;Apply the mask. Correct
  102. 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.
  103. 00197E 0A03A0 BFINS #0x0, #0xb, W3, W4 ;Apply the data to the bitfield. Correct
  104. 001980 000004 NOP
  105. 001982 9FF784 MOV.B W4, [W15-16] ;Write back the new value... but only the low byte. Why??? It's a 11 bit field.
  106. [/code]
  107.  
  108.  
  109.  
  110. 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
  111.  
  112.  
  113.  
  114. 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