GCC Code Coverage Report


Directory: src/drv/
File: src/drv/can/src/can_driver.c
Date: 2024-01-25 15:03:18
Exec Total Coverage
Lines: 0 186 0.0%
Branches: 0 94 0.0%

Line Branch Exec Source
1 /********************************************************************************************************//**
2 * @file can_driver.c
3 *
4 * @brief File containing the APIs for configuring the CAN peripheral.
5 *
6 * Public Functions:
7 * - uint8_t CAN_Init(CAN_Handle_t* pCAN_Handle)
8 * - void CAN_DeInit(CAN_RegDef_t* pCANx)
9 * - void CAN_PerClkCtrl(CAN_RegDef_t* pCANx, uint8_t en_or_di)
10 * - uint8_t CAN_AddTxMsg(CAN_RegDef_t* pCANx, CAN_TxHeader_t* pTxHeader, uint8_t* msg, uint32_t mailbox)
11 * - uint8_t CAN_TxMsgPending(CAN_RegDef_t* pCANx, uint32_t mailbox)
12 * - uint8_t CAN_SetFilter(CAN_Filter_t* filter)
13 * - uint8_t CAN_GetRxMsg(CAN_RegDef_t* pCANx, CAN_RxMessage_t* pRxMessage, uint8_t FIFO_number)
14 * - uint8_t CAN_InterruptsEnable(CAN_RegDef_t* pCANx, uint32_t irq_flags)
15 * - uint8_t CAN_InterruptsDisable(CAN_RegDef_t* pCANx, uint32_t irq_flags)
16 * - void CAN_Tx_IRQHandling(CAN_RegDef_t* pCANx)
17 * - void CAN_Rx0_IRQHandling(CAN_RegDef_t* pCANx)
18 * - void CAN_Rx1_IRQHandling(CAN_RegDef_t* pCANx)
19 * - void CAN_SCE_IRQHandling(CAN_RegDef_t* pCANx)
20 * - void CAN_ApplicationEventCallback(CAN_RegDef_t* pCANx, can_app_event_t app_event)
21 *
22 * @note
23 * For further information about functions refer to the corresponding header file.
24 **/
25
26 #include "can_driver.h"
27 #include "stm32f446xx.h"
28 #include <stdint.h>
29 #include <stddef.h>
30
31 /***********************************************************************************************************/
32 /* Static Function Prototypes */
33 /***********************************************************************************************************/
34
35 /***********************************************************************************************************/
36 /* Public API Definitions */
37 /***********************************************************************************************************/
38
39 uint8_t CAN_Init(CAN_Handle_t* pCAN_Handle){
40
41 uint32_t temp = 0;
42
43 /* Initial check of parameters */
44 if((pCAN_Handle->CAN_Config.CAN_SyncJumpWidth < 1) || (pCAN_Handle->CAN_Config.CAN_SyncJumpWidth > 4)){
45 return 1;
46 }
47 if((pCAN_Handle->CAN_Config.CAN_Prescalar < 1) || (pCAN_Handle->CAN_Config.CAN_Prescalar > 0x400)){
48 return 1;
49 }
50 if((pCAN_Handle->CAN_Config.CAN_TimeSeg1 < 1) || (pCAN_Handle->CAN_Config.CAN_TimeSeg1 > 0x10)){
51 return 1;
52 }
53 if((pCAN_Handle->CAN_Config.CAN_TimeSeg2 < 1) || (pCAN_Handle->CAN_Config.CAN_TimeSeg2 > 8)){
54 return 1;
55 }
56
57 /* Enable the peripheral clock */
58 CAN_PerClkCtrl(pCAN_Handle->pCANx, ENABLE);
59
60 /* Enter in initialization mode */
61 pCAN_Handle->pCANx->MCR |= (1 << CAN_MCR_INRQ);
62 while(!(pCAN_Handle->pCANx->MSR & (1 << CAN_MSR_INAK)));
63
64 /* Set master control register */
65 temp |= ((pCAN_Handle->CAN_Config.CAN_TimeTriggerMode << CAN_MCR_TTCM) |
66 (pCAN_Handle->CAN_Config.CAN_AutoBusOff << CAN_MCR_ABOM) |
67 (pCAN_Handle->CAN_Config.CAN_AutoWakeup << CAN_MCR_AWUM) |
68 (pCAN_Handle->CAN_Config.CAN_AutoRetransmission << CAN_MCR_NART) |
69 (pCAN_Handle->CAN_Config.CAN_ReceiveFifoLocked << CAN_MCR_RFLM) |
70 (pCAN_Handle->CAN_Config.CAN_TxFifoPriority << CAN_MCR_TXFP));
71 /* Clean register before write taking into account the INRQ bit */
72 pCAN_Handle->pCANx->MCR &= ~(0xFFFFFFFE);
73 pCAN_Handle->pCANx->MCR |= temp;
74
75 /* Set bit timing register */
76 temp = 0;
77 temp |= ((pCAN_Handle->CAN_Config.CAN_Mode << CAN_BTR_LBKM) |
78 ((pCAN_Handle->CAN_Config.CAN_SyncJumpWidth - 1) << CAN_BTR_SJW) |
79 ((pCAN_Handle->CAN_Config.CAN_Prescalar - 1) << CAN_BTR_BRP) |
80 ((pCAN_Handle->CAN_Config.CAN_TimeSeg1 - 1) << CAN_BTR_TS1) |
81 ((pCAN_Handle->CAN_Config.CAN_TimeSeg2 - 1) << CAN_BTR_TS2));
82 pCAN_Handle->pCANx->BTR &= ~(0xFFFFFFFF);
83 pCAN_Handle->pCANx->BTR = temp;
84
85 /* Exit from initialization mode */
86 pCAN_Handle->pCANx->MCR &= ~(1 << CAN_MCR_INRQ);
87 while(pCAN_Handle->pCANx->MSR & (1 << CAN_MSR_INAK));
88
89 return 0;
90 }
91
92 void CAN_DeInit(CAN_RegDef_t* pCANx){
93
94 if(pCANx == CAN1){
95 CAN1_REG_RESET();
96 }
97 else if(pCANx == CAN2){
98 CAN2_REG_RESET();
99 }
100 else{
101 /* do nothing */
102 }
103 }
104
105 void CAN_PerClkCtrl(CAN_RegDef_t* pCANx, uint8_t en_or_di){
106
107 if(en_or_di == ENABLE){
108 if(pCANx == CAN1){
109 CAN1_PCLK_EN();
110 }
111 else if(pCANx == CAN2){
112 CAN2_PCLK_EN();
113 }
114 else{
115 /* do nothing */
116 }
117 }
118 else{
119 if(pCANx == CAN1){
120 CAN1_PCLK_DI();
121 }
122 else if(pCANx == CAN2){
123 CAN2_PCLK_DI();
124 }
125 else{
126 /* do nothing */
127 }
128 }
129 }
130
131 uint8_t CAN_AddTxMsg(CAN_RegDef_t* pCANx, CAN_TxHeader_t* pTxHeader, uint8_t* msg, uint32_t mailbox){
132
133 uint32_t temp = 0;
134 uint32_t* pTIxR = NULL;
135
136 /* Check if the mailbox is free */
137 if(!(pCANx->TSR & (mailbox << CAN_TSR_TME0))){
138 return 2;
139 }
140
141 /* Set the selected mailbox address to manage it */
142 switch(mailbox){
143 case CAN_MAILBOX_0:
144 pTIxR = (uint32_t*)&(pCANx->TI0R);
145 break;
146 case CAN_MAILBOX_1:
147 pTIxR = (uint32_t*)&(pCANx->TI1R);
148 break;
149 case CAN_MAILBOX_2:
150 pTIxR = (uint32_t*)&(pCANx->TI2R);
151 break;
152 default:
153 return 1;
154 break;
155 }
156
157 /* Set CAN Tx mailbox identifier register */
158 *pTIxR &= ~(0xFFFFFFFF);
159
160 if(pTxHeader->IDE == CAN_STDI){
161 temp |= (pTxHeader->StId << CAN_TIxR_STID);
162 }
163 else{
164 temp |= (pTxHeader->ExId << CAN_TIxR_EXID);
165 }
166 temp |= ((pTxHeader->IDE << CAN_TIxR_IDE) |
167 (pTxHeader->RTR << CAN_TIxR_RTR));
168 *pTIxR = temp;
169
170 /* Set DLC value (TDTxR register has offset 4 bytes from TIxR register) */
171 *(pTIxR + 1) &= ~(0x0000000F);
172 *(pTIxR + 1) |= (pTxHeader->DLC << CAN_TDTxR_DLC);
173
174 /* Set CAN mailbox data register */
175 /* Clear TDLxR register (offset 8 bytes from TIxR register) */
176 *(pTIxR + 2) &= ~(0xFFFFFFFF);
177 /* Clear TDHxR register (offset 12 bytes from TIxR register) */
178 *(pTIxR + 3) &= ~(0xFFFFFFFF);
179 /* Set TDLxR register */
180 temp = 0;
181 temp |= ((msg[0] << 0) |
182 (msg[1] << 8) |
183 (msg[2] << 16) |
184 (msg[3] << 24));
185 *(pTIxR + 2) = temp;
186 /* Set TDHxR register */
187 temp = 0;
188 temp |= ((msg[4] << 0) |
189 (msg[5] << 8) |
190 (msg[6] << 16) |
191 (msg[7] << 24));
192 *(pTIxR + 3) = temp;
193
194 /* Request transmission */
195 *(pTIxR) |= (1 << CAN_TIxR_TXRQ);
196
197 return 0;
198 }
199
200 uint8_t CAN_TxMsgPending(CAN_RegDef_t* pCANx, uint32_t mailbox){
201
202 uint8_t ret = 0;
203
204 if(pCANx->TSR & (mailbox << CAN_TSR_TME0)){
205 return 1;
206 }
207
208 return ret;
209 }
210
211 uint8_t CAN_SetFilter(CAN_Filter_t* filter){
212
213 uint32_t temp = 0;
214
215 /* Check the filter number is valid */
216 if(filter->FilterNumber > 27){
217 return 1;
218 }
219
220 /* Enter in filter initialization mode */
221 CAN1->FMR |= (1 << CAN_FMR_FINIT);
222
223 /* Set filter mode */
224 CAN1->FM1R &= ~(1 << filter->FilterNumber);
225 CAN1->FM1R |= (filter->Mode << filter->FilterNumber);
226
227 /* Set filter scale */
228 CAN1->FS1R &= ~(1 << filter->FilterNumber);
229 CAN1->FS1R |= (filter->Scale << filter->FilterNumber);
230
231 /* Set filter FIFO assignment */
232 CAN1->FFA1R &= ~(1 << filter->FilterNumber);
233 CAN1->FFA1R |= (filter->FIFO << filter->FilterNumber);
234
235 /* Set filter banks */
236 /* Clear identifier filter register */
237 CAN1->FiRx[2*(filter->FilterNumber)] &= ~(0xFFFFFFFF);
238 /* Set identifier filter register */
239 temp |= ((filter->IdentifierHR << 16) |
240 (filter->IdentifierLR));
241 CAN1->FiRx[2*(filter->FilterNumber)] = temp;
242 /* Clear mask filter register */
243 CAN1->FiRx[2*(filter->FilterNumber) + 1] &= ~(0xFFFFFFFF);
244 /* Set mask filter register */
245 temp = 0;
246 temp |= ((filter->MaskHR << 16) |
247 (filter->MaskLR));
248 CAN1->FiRx[2*(filter->FilterNumber) + 1] = temp;
249
250 /* Active filters mode */
251 CAN1->FMR &= ~(1 << CAN_FMR_FINIT);
252
253 /* Activate filter */
254 CAN1->FA1R |= (1 << filter->FilterNumber);
255
256 return 0;
257 }
258
259 uint8_t CAN_GetRxMsg(CAN_RegDef_t* pCANx, CAN_RxMessage_t* pRxMessage, uint8_t FIFO_number){
260
261 uint32_t* pFIFO = NULL;
262
263 /* Check if selected FIFO has a message pending */
264 if(FIFO_number == 0){
265 if(!(pCANx->RF0R & (0x3 << CAN_RFxR_FMP))){
266 return 2;
267 }
268 pFIFO = (uint32_t*)&(pCANx->RI0R);
269 }
270 else if(FIFO_number == 1){
271 if(!(pCANx->RF1R & (0x3 << CAN_RFxR_FMP))){
272 return 2;
273 }
274 pFIFO = (uint32_t*)&(pCANx->RI1R);
275 }
276 else{
277 /* If FIFO number is not correct return error */
278 return 1;
279 }
280
281 pRxMessage->IDE = (*pFIFO << CAN_RIxR_IDE);
282 pRxMessage->RTR = (*pFIFO << CAN_RIxR_RTR);
283 if(pRxMessage->IDE == 0){
284 pRxMessage->StId = (*pFIFO << CAN_RIxR_STID);
285 }
286 else{
287 pRxMessage->ExId = (*pFIFO << CAN_RIxR_EXID);
288 }
289 pRxMessage->DLC = (*(pFIFO + 1) << CAN_RDTxR_DLC);
290 pRxMessage->DataLR = *(pFIFO + 2);
291 pRxMessage->DataHR = *(pFIFO + 3);
292
293 /* Release the output mailbox */
294 if(FIFO_number == 0){
295 pCANx->RF0R |= (1 << CAN_RFxR_RFOM);
296 }
297 else{
298 pCANx->RF1R |= (1 << CAN_RFxR_RFOM);
299 }
300
301 return 0;
302 }
303
304 uint8_t CAN_InterruptsEnable(CAN_RegDef_t* pCANx, uint32_t irq_flags){
305
306 if(irq_flags & 0xFFFC7080){
307 return 1;
308 }
309
310 pCANx->IER |= irq_flags;
311
312 return 0;
313 }
314
315 uint8_t CAN_InterruptsDisable(CAN_RegDef_t* pCANx, uint32_t irq_flags){
316
317 if(irq_flags & 0xFFFC7080){
318 return 1;
319 }
320
321 pCANx->IER &= ~irq_flags;
322
323 return 0;
324 }
325
326 void CAN_Tx_IRQHandling(CAN_RegDef_t* pCANx){
327
328 if(pCANx->TSR & (1 << CAN_TSR_RQCP0)){
329 CAN_ApplicationEventCallback(pCANx, CAN_TX_REQ_CMPT_M0);
330 }
331 else if(pCANx->TSR & (1 << CAN_TSR_RQCP1)){
332 CAN_ApplicationEventCallback(pCANx, CAN_TX_REQ_CMPT_M1);
333 }
334 else if(pCANx->TSR & (1 << CAN_TSR_RQCP2)){
335 CAN_ApplicationEventCallback(pCANx, CAN_TX_REQ_CMPT_M2);
336 }
337 else{
338 /* do nothing */
339 }
340
341 }
342
343 void CAN_Rx0_IRQHandling(CAN_RegDef_t* pCANx){
344
345 if(pCANx->RF0R & (0x3 << CAN_RFxR_FMP)){
346 CAN_ApplicationEventCallback(pCANx, CAN_FIFO0_MSG_PEND);
347 }
348 else if(pCANx->RF0R & (1 << CAN_RFxR_FULL)){
349 CAN_ApplicationEventCallback(pCANx, CAN_FIFO0_FULL);
350 }
351 else if(pCANx->RF0R & (1<< CAN_RFxR_FOVR)){
352 CAN_ApplicationEventCallback(pCANx, CAN_FIFO0_OVERRUN);
353 }
354 else{
355 /* do nothing */
356 }
357 }
358
359 void CAN_Rx1_IRQHandling(CAN_RegDef_t* pCANx){
360
361 if(pCANx->RF1R & (0x3 << CAN_RFxR_FMP)){
362 CAN_ApplicationEventCallback(pCANx, CAN_FIFO1_MSG_PEND);
363 }
364 else if(pCANx->RF1R & (1 << CAN_RFxR_FULL)){
365 CAN_ApplicationEventCallback(pCANx, CAN_FIFO1_FULL);
366 }
367 else if(pCANx->RF1R & (1<< CAN_RFxR_FOVR)){
368 CAN_ApplicationEventCallback(pCANx, CAN_FIFO1_OVERRUN);
369 }
370 else{
371 /* do nothing */
372 }
373 }
374
375 void CAN_SCE_IRQHandling(CAN_RegDef_t* pCANx){
376
377 /* Check if the irq is caused by an error */
378 if(pCANx->MSR & (1 << CAN_MSR_ERRI)){
379 if(pCANx->ESR & (1<< CAN_ESR_EWGF)){
380 CAN_ApplicationEventCallback(pCANx, CAN_ERROR_WARNING);
381 }
382 else if(pCANx->ESR & (1 << CAN_ESR_EPVF)){
383 CAN_ApplicationEventCallback(pCANx, CAN_ERROR_PASSIVE);
384 }
385 else if(pCANx->ESR & (1 << CAN_ESR_BOFF)){
386 CAN_ApplicationEventCallback(pCANx, CAN_ERROR_BUSOFF);
387 }
388 else if(pCANx->ESR & (0x7 << CAN_ESR_LEC)){
389 CAN_ApplicationEventCallback(pCANx, CAN_ERROR_CODE);
390 }
391 else{
392 /* do nothing */
393 }
394 }
395 if(pCANx->MSR & (1 << CAN_MSR_SLAKI)){
396 CAN_ApplicationEventCallback(pCANx, CAN_SLEEP_ACK);
397 }
398 else if(pCANx->MSR & (1 << CAN_MSR_WKUI)){
399 CAN_ApplicationEventCallback(pCANx, CAN_WAKEUP_IRQ);
400 }
401 else{
402 /* do nothing */
403 }
404 }
405
406 /***********************************************************************************************************/
407 /* Weak Functions */
408 /* This is a weak implementation. The application may override this function */
409 /***********************************************************************************************************/
410
411 __attribute__((weak)) void CAN_ApplicationEventCallback(CAN_RegDef_t* pCANx, can_app_event_t app_event){
412
413 /* This is a weak implementation. The application may override this function */
414 (void)pCANx;
415 (void)app_event;
416 }
417
418 /***********************************************************************************************************/
419 /* Static Function Definitions */
420 /***********************************************************************************************************/
421