FlexCAN.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. //==============================================================================
  2. // Purpose: allgemeines CAN Interface für FlexCAN von MPC5646
  3. //
  4. // Created on: 20.04.2012 by IPE
  5. //
  6. // History
  7. // 20.04.2012 neu, T.Maurer
  8. // 29.07.2013 CAN_Init() modified V.Reiling
  9. // 26.02.2016 CAN_Init() modified V.Reiling: Sample Point at 87.5%
  10. //==============================================================================
  11. #include "BMS_Master.h"
  12. //CAN - MESSAGEBOX-STATUS-CODES
  13. #define CAN_MBCODE_RXINACTIVE 0
  14. #define CAN_MBCODE_RXEMPTY 4
  15. #define CAN_MBCODE_RXFULL 2
  16. #define CAN_MBCODE_RXOVERRUN 6 // MB war voll und wurde nicht von CPU ausgelesen
  17. #define CAN_MBCODE_RXBUSY 1 // (XXX1)
  18. #define CAN_MBCODE_TXINACTIVE 8 //Grundzustand
  19. #define CAN_MBCODE_TXABORT 9 //ABORT muss mit MCR.AEN freigegeben werden
  20. #define CAN_MBCODE_TXSEND 12 //RTR=0 -> sende Data, wenn beendet: Rückkehr zu INACTIVE;
  21. //RTR=1 -> sende RemoteFrame, Wenn fertig: neuer Zustand = CAN_MBCODE_RXEMPTY
  22. #define CAN_MBCODE_TXREMOTEWAIT 10 //warte auf Remote request und sende Data zurück (-> CAN_MBCODE_TXREMOTESEND)
  23. #define CAN_MBCODE_TXREMOTESEND 16 //sende Data nach Remote request, wenn beendet: Rückkehr zu CAN_MBCODE_TXREMOTEWAIT;
  24. //Abort Enable des Boards verwenden?
  25. #define CAN_AEN 0
  26. //Funktionen
  27. int8_t CAN_Init(CAN_CONFIG *config)
  28. {
  29. volatile struct FLEXCAN_tag *p_CAN = config->CAN_Modul;
  30. uint8_t i;
  31. // Fehler-Check: CAN-Modul-Adresse vorhanden?
  32. if ((p_CAN != &CAN_0) &&
  33. (p_CAN != &CAN_1) &&
  34. (p_CAN != &CAN_2) &&
  35. (p_CAN != &CAN_3) &&
  36. (p_CAN != &CAN_4) &&
  37. (p_CAN != &CAN_5) )
  38. return CAN_ERROR;
  39. // MCR-Register, die meisten Bits koennen nur im FreezeMode beschrieben werden
  40. p_CAN->MCR.B.MDIS = 0; // Module Disable (init=1)
  41. while (p_CAN->MCR.B.LPMACK) {}
  42. p_CAN->MCR.B.FRZ = 1; // FreezeMode enable (initVal=1)
  43. p_CAN->MCR.B.HALT = 1; // FreezeMode ON (wenn FRZ=1);(initVal=1) Clear after module-init
  44. while (!p_CAN->MCR.B.FRZACK) {} // warte auf FreezeMode
  45. p_CAN->MCR.B.BCC = 1; // 1 = Enable Indididual RxMasking
  46. if (config->RxMaskType == RxMask_Global)
  47. {
  48. p_CAN->MCR.B.BCC = 0; // 0 = Enable Global RxMasking
  49. p_CAN->RXGMASK.R = config->GlobalRxMask; // Global Acceptance Mask (InitVal = 0xFFFF_FFFF)
  50. }
  51. p_CAN->MCR.B.AEN = CAN_AEN; // Abort Enable
  52. p_CAN->MCR.B.SUPV = 0; // Freeze mode only:
  53. switch( config->BaudConfig )
  54. {
  55. case CANBaud_1000kHz_OSC_40MHz : // @ 40m Buslength
  56. p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
  57. p_CAN->CR.B.PRESDIV = 1; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
  58. p_CAN->CR.B.PROPSEG = 7; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
  59. p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
  60. p_CAN->CR.B.PSEG2 = 2; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
  61. p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
  62. break;
  63. case CANBaud_500kHz_OSC_40MHz : // @ 100m Buslength
  64. p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
  65. p_CAN->CR.B.PRESDIV = 4; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
  66. p_CAN->CR.B.PROPSEG = 4; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
  67. p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
  68. p_CAN->CR.B.PSEG2 = 1; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
  69. p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
  70. break;
  71. case CANBaud_250kHz_OSC_40MHz : // @ 200m Buslength
  72. p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
  73. p_CAN->CR.B.PRESDIV = 9; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
  74. p_CAN->CR.B.PROPSEG = 4; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
  75. p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
  76. p_CAN->CR.B.PSEG2 = 1; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
  77. p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
  78. break;
  79. case CANBaud_125kHz_OSC_40MHz : // @ 420m Buslength
  80. p_CAN->CR.B.CLKSRC = 0; // CPI-ClockSource: 0=oscillator clock (40MHz); 1=bus clock (PLL/2=60MHz)
  81. p_CAN->CR.B.PRESDIV = 19; // f_SerialClock = f_CPI_clock / (PRESDIV + 1)
  82. p_CAN->CR.B.PROPSEG = 4; // Propagation Segment Time = (PROPSEG + 1) * Time-Quanta.
  83. p_CAN->CR.B.PSEG1 = 7; // Phase Buffer Segment 1 = (PSEG1 + 1) x Time-Quanta.
  84. p_CAN->CR.B.PSEG2 = 1; // Phase Buffer Segment 2 = (PSEG1 + 1) x Time-Quanta.
  85. p_CAN->CR.B.RJW = 0; // Resync Jump Width = RJW + 1.
  86. break;
  87. default :
  88. return CAN_ERROR;
  89. }
  90. p_CAN->CR.B.SMP = 1; // Sampling Mode: 0=1 Sample, 1=3 Samples
  91. switch( config->Port )
  92. {
  93. case CAN0_PortB0_1 : // Config Ports: PB0 = CAN0_Tx, PB1 = CAN0_Rx
  94. SIU.PCR[16].B.OBE = 1; // Output Buffer Enable = Output
  95. SIU.PCR[16].B.PA = 1; // Pad Output Assignment = CAN0TX
  96. SIU.PCR[16].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
  97. SIU.PCR[16].B.SRC = 1; // Slew Rate Control = Fast
  98. SIU.PCR[17].B.IBE = 1; // Input Buffer Enable = Input
  99. break;
  100. case CAN1_PortC10_11 : // Config Ports: PC10 = CAN1_Tx, PC11 = CAN1_Rx
  101. SIU.PCR[42].B.OBE = 1; // Output Buffer Enable = Output
  102. SIU.PCR[42].B.PA = 1; // Pad Output Assignment = CAN1TX
  103. SIU.PCR[42].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
  104. SIU.PCR[42].B.SRC = 1; // Slew Rate Control = Fast
  105. SIU.PCR[43].B.IBE = 1; // Input Buffer Enable = Input
  106. SIU.PSMI[0].R = 0x01; // Peripheral input pin selection: CAN1RX -> PCR[43]
  107. break;
  108. case CAN2_PortE8_9 : // Config Ports: PE8 = CAN2_Tx, PE9 = CAN2_Rx
  109. SIU.PCR[72].B.OBE = 1; // Output Buffer Enable = Output
  110. SIU.PCR[72].B.PA = 1; // Pad Output Assignment = CAN2TX
  111. SIU.PCR[72].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
  112. SIU.PCR[72].B.SRC = 1; // Slew Rate Control = Fast
  113. SIU.PCR[73].B.IBE = 1; // Input Buffer Enable = Input
  114. SIU.PSMI[1].R = 0x00; // Peripheral input pin selection: CAN2RX -> PCR[73]
  115. break;
  116. case CAN3_PortF8_9 : // Config Ports: PF8 = CAN3_Tx, PF9 = CAN3_Rx
  117. SIU.PCR[88].B.OBE = 1; // Output Buffer Enable = Output
  118. SIU.PCR[88].B.PA = 1; // Pad Output Assignment = CAN3TX
  119. SIU.PCR[88].B.ODE = (config->TxPortType==Tx_OpenDrain)? 1:0; // Open Drain Output Enable
  120. SIU.PCR[88].B.SRC = 1; // Slew Rate Control = Fast
  121. SIU.PCR[89].B.IBE = 1; // Input Buffer Enable = Input
  122. SIU.PSMI[2].R = 0x02; // Peripheral input pin selection: CAN3RX -> PCR[89]
  123. break;
  124. default :
  125. return CAN_ERROR;
  126. }
  127. p_CAN->MCR.B.MAXMB = 55; // Max 64 Massage Buffer
  128. for (i=0; i<64; i++)
  129. p_CAN->BUF[i].CS.B.CODE = CAN_MBCODE_RXINACTIVE; // Inactivate all message buffers
  130. p_CAN->MCR.B.HALT = 0; // FreezeModeON-Bit; Clear after module-init (init=1)
  131. p_CAN->MCR.B.FRZ = 0; // FreezeMode
  132. return CAN_OK;
  133. }
  134. int8_t CAN_Init_Mailbox(CAN_MAILBOX *mbox)
  135. {
  136. volatile struct FLEXCAN_BUF_t *p_BUF; //pointer auf einen Message Buffer
  137. volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
  138. if (mbox->MBNumber >= 64) return CAN_ERROR;
  139. p_BUF = p_CAN->BUF + mbox->MBNumber;
  140. if (p_CAN->MCR.B.LPMACK) return CAN_ERROR; //CAN in DisableMode
  141. p_CAN->MCR.B.FRZ = 1; // FreezeMode enable (initVal=1)
  142. p_CAN->MCR.B.HALT = 1; // FreezeMode ON (wenn FRZ=1);(initVal=1) Clear after module-init
  143. while (!p_CAN->MCR.B.FRZACK) {} //warte auf FreezeMode
  144. if (mbox->RemoteEn >= 2) return CAN_ERROR;
  145. p_BUF->CS.B.RTR = mbox->RemoteEn; /* Data frame, not remote Tx request frame */
  146. if (mbox->Direction == MB_Tx) {
  147. //TX-Box
  148. if (mbox->DataBytes >= 9) return CAN_ERROR;
  149. p_BUF->CS.B.LENGTH = mbox->DataBytes; /* # bytes to transmit*/
  150. p_BUF->CS.B.CODE = CAN_MBCODE_TXINACTIVE;
  151. }
  152. else if (mbox->Direction == MB_Rx) {
  153. //RX-Box
  154. p_BUF->CS.B.CODE = CAN_MBCODE_RXEMPTY;
  155. //Individuelle Acceptance Mask
  156. if (mbox->p_CAN_Config->RxMaskType == RxMask_Individual)
  157. p_CAN->RXIMR[mbox->MBNumber].R = mbox->AcceptMask;
  158. //MB-Interrupt-Enable
  159. }
  160. else return CAN_ERROR;
  161. if( mbox->IDE == SHORT_ID)
  162. {
  163. p_BUF->CS.B.IDE = 0; // Use standard ID length
  164. p_BUF->ID.B.STD_ID = mbox->ID;
  165. }
  166. else
  167. {
  168. p_BUF->CS.B.IDE = 1; // Use extended ID length
  169. p_BUF->ID.B.EXT_ID = (mbox->ID & 0x3FFFF);
  170. p_BUF->ID.B.STD_ID = (mbox->ID >> 18);
  171. }
  172. if (mbox->Interrupt) {
  173. if (mbox->MBNumber <= 31)
  174. SETBIT(p_CAN->IMRL.R, mbox->MBNumber); // Interrupt Mask 1
  175. else
  176. SETBIT(p_CAN->IMRH.R, mbox->MBNumber - 32); // Interrupt Mask 2
  177. }
  178. p_CAN->MCR.B.HALT = 0; // FreezeMode ON (wenn FRZ=1);(initVal=1) Clear after module-init
  179. p_CAN->MCR.B.FRZ = 0; //FreezeMode;
  180. //init Ende
  181. return CAN_OK;
  182. }
  183. int8_t CAN_Write(CAN_MAILBOX *mbox, uint8_t *data)
  184. {
  185. uint8_t i;
  186. volatile struct FLEXCAN_BUF_t *p_BUF;
  187. volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
  188. if (p_CAN->MCR.B.NOTRDY) return CAN_ERROR;
  189. p_BUF = p_CAN->BUF + mbox->MBNumber;
  190. if (mbox->MBNumber >= 64) return CAN_ERROR;
  191. p_BUF->CS.B.CODE = CAN_MBCODE_TXINACTIVE;
  192. //I-Flag löschen, um die MB zu entsperren
  193. /* if (mbox->MBNumber < 32)
  194. p_CAN->IFRL.R = 1 << mbox->MBNumber;
  195. else
  196. p_CAN->IFRH.R = 1 << (mbox->MBNumber-32);
  197. */ p_BUF = p_CAN->BUF + mbox->MBNumber; //pointer auf einen Message Buffer
  198. if( mbox->IDE == SHORT_ID)
  199. p_BUF->ID.B.STD_ID = mbox->ID;
  200. else
  201. p_BUF->ID.B.EXT_ID = mbox->ID;
  202. for (i=0; i<mbox->DataBytes; i++) {
  203. p_BUF->DATA.B[i] = *(data+i); /* Data to be transmitted */
  204. }
  205. // CAN_0.BUF[0].CS.B.SRR = 1; /* Tx frame (not req'd for standard frame)*/
  206. p_BUF->CS.B.CODE = CAN_MBCODE_TXSEND; /* Activate msg. buf. to transmit data frame */
  207. return CAN_OK;
  208. }
  209. int8_t CAN_Write_dataset(CAN_MAILBOX *mbox, uint8_t* data,uint32_t timestamp)
  210. {
  211. uint8_t i;
  212. int8_t CAN_status=CAN_OK;
  213. uint8_t dataSetSize= mbox->DataBytes;
  214. volatile struct FLEXCAN_BUF_t *p_BUF;
  215. volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
  216. p_BUF = p_CAN->BUF + mbox->MBNumber;
  217. while(p_BUF->CS.B.CODE !=CAN_MBCODE_TXINACTIVE) {
  218. //wait
  219. if(Global_1msCounter >= timestamp + CAN1_TX_TIMEOUT) {
  220. return CAN_ERROR;
  221. }
  222. }
  223. CAN_status=CAN_Write(mbox,data);
  224. timestamp=Global_1msCounter;
  225. if(CAN_status != CAN_OK) {
  226. return CAN_ERROR;
  227. }
  228. return CAN_OK;
  229. }
  230. int8_t CAN_Read(CAN_MAILBOX *mbox, uint8_t *data)
  231. {
  232. uint8_t i;
  233. int8_t returnval;
  234. uint32_t dummy;
  235. volatile struct FLEXCAN_BUF_t *p_BUF; //pointer auf einen Message Buffer
  236. volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
  237. returnval = CAN_OK;
  238. if (mbox->MBNumber >= 64) return CAN_ERROR;
  239. p_BUF = p_CAN->BUF + mbox->MBNumber;
  240. dummy = p_BUF->CS.B.CODE; //Muss ausgelesen werden zum Lock des Puffers
  241. if (p_BUF->CS.B.LENGTH > CAN_DATA_ARR_LEN) returnval = CAN_ERROR;
  242. if (p_BUF->CS.B.LENGTH != mbox->DataBytes) returnval = CAN_ERROR;
  243. if( mbox->IDE == SHORT_ID)
  244. mbox->ID = p_BUF->ID.B.STD_ID; // copy received ID to MailBox
  245. else
  246. mbox->ID = p_BUF->ID.B.EXT_ID; // copy received ID to MailBox
  247. for (i=0; i < p_BUF->CS.B.LENGTH; i++){
  248. *(data+i) = p_BUF->DATA.B[i];
  249. }
  250. //Timer auslesen und I-Flag löschen, um die MB zu entsperren
  251. dummy = p_CAN->TIMER.R;
  252. // Clear Int-Flag
  253. if (mbox->MBNumber < 32)
  254. p_CAN->IFRL.R = 1 << mbox->MBNumber;
  255. else
  256. p_CAN->IFRH.R = 1 << (mbox->MBNumber-32);
  257. return returnval;
  258. }
  259. // Funktionen
  260. int8_t CAN_Abort(CAN_MAILBOX *mbox)
  261. {
  262. volatile struct FLEXCAN_BUF_t *p_BUF;
  263. volatile struct FLEXCAN_tag *p_CAN = mbox->p_CAN_Config->CAN_Modul;
  264. p_BUF = p_CAN->BUF + mbox->MBNumber; //pointer auf einen Message Buffer
  265. if (mbox->Direction == MB_Rx) return CAN_ERROR;
  266. #if CAN_AEN == 1
  267. p_BUF->CS.B.CODE = CAN_MBCODE_TXABORT;
  268. #else
  269. p_BUF->CS.B.CODE = CAN_MBCODE_TXINACTIVE;
  270. #endif
  271. return CAN_OK;
  272. }
  273. /**
  274. * @function Check CAN Error State Register for Errors
  275. * @param config pointer to CAN Module
  276. * @param can_esr 32 Bi vaiable for error state
  277. * @return TRUE if CAN IS OK, FALSE IF Error occured
  278. *
  279. */
  280. uint8_t CAN_Get_error_Register(CAN_CONFIG *config,uint32_t* can_esr) {
  281. volatile struct FLEXCAN_tag *p_CAN = config->CAN_Modul;
  282. if(p_CAN->ESR.R == 0) {
  283. return TRUE;
  284. }
  285. else {
  286. *can_esr=p_CAN->ESR.R;
  287. return FALSE;
  288. }
  289. }
  290. /**
  291. *@brief Check if CAN Errors occured
  292. */
  293. int8_t CAN_Check_error_Register(CAN_CONFIG *config) {
  294. volatile struct FLEXCAN_tag *p_CAN = config->CAN_Modul;
  295. if(p_CAN->ESR.R == 0) {
  296. return CAN_OK;
  297. }
  298. else {
  299. return CAN_ERROR;
  300. }
  301. }