]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cr4/drivers/Can.c
Fixed bug causing CAN driver not to use the right mailbox when transmitting.
[arc.git] / arch / arm / arm_cr4 / drivers / Can.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 #include "Can.h"\r
18 #include "core_cr4.h"\r
19 #if defined(USE_DEM)\r
20 #include "Dem.h"\r
21 #endif\r
22 #include "Det.h"\r
23 #include "CanIf_Cbk.h"\r
24 #include "Os.h"\r
25 #include "irq.h"\r
26 #include "Mcu.h"\r
27 \r
28 #define DCAN1_MAX_MESSAGEBOXES 64\r
29 #define DCAN2_MAX_MESSAGEBOXES 64\r
30 #define DCAN3_MAX_MESSAGEBOXES 32\r
31 \r
32 #define CAN_TIMEOUT_DURATION   0xFFFFFFFF\r
33 #define CAN_INSTANCE           0\r
34 \r
35 #define DCAN_IRQ_MASK           0x00000006\r
36 \r
37 \r
38 #if !defined(USE_DEM)\r
39 // If compiled without the DEM, calls to DEM are simply ignored.\r
40 #define Dem_ReportErrorStatus(...)\r
41 #endif\r
42 \r
43 \r
44 // Array for easy access to DCAN register definitions.\r
45 static Can_RegisterType* CanRegs[]=\r
46 {\r
47         DCAN1_Base,\r
48         DCAN2_Base,\r
49         DCAN3_Base\r
50 };\r
51 \r
52 typedef enum\r
53 {\r
54     CAN_UNINIT,\r
55     CAN_READY\r
56 } Can_StateType;\r
57 \r
58 \r
59 typedef struct\r
60 {\r
61     uint16       MaxBoxes;\r
62     uint32       WakeupSrc;\r
63     Can_PduType *PduPtr;\r
64     uint8       *CancelPtr;\r
65     uint8       *TxPtr;    \r
66 } Controller_PreConfigType;\r
67 \r
68 \r
69 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
70 /* Module is in uninitialized state */\r
71 static Can_StateType            ModuleState = CAN_UNINIT;\r
72 #endif\r
73 \r
74 static CanIf_ControllerModeType ControllerMode[CAN_ARC_CTRL_CONFIG_CNT];\r
75 \r
76 /* Used to switch between IF1 and IF2 of DCAN */\r
77 static uint8 IfRegId = 0;\r
78 \r
79 /* Used to order Data Bytes according to hardware registers in DCAN */\r
80 static const uint8 ElementIndex[] = {3, 2, 1, 0, 7, 6, 5, 4};\r
81 \r
82 /* To save pointer to the configuration set */\r
83 static const Can_ConfigType *CurConfig;\r
84 \r
85 /* To save the PduData of transmission objects */\r
86 static Can_PduType PduInfoArray_1[DCAN1_MAX_MESSAGEBOXES];\r
87 /* To save pending Cancel Requests of transmission objects */\r
88 static uint8 CancelRqstArray_1[DCAN1_MAX_MESSAGEBOXES];\r
89 /* To save pending Transmit Requests of transmission objects */\r
90 static uint8 TxRqstArray_1[DCAN1_MAX_MESSAGEBOXES];\r
91 \r
92 static Can_PduType PduInfoArray_2[DCAN2_MAX_MESSAGEBOXES];\r
93 static uint8 CancelRqstArray_2[DCAN2_MAX_MESSAGEBOXES];\r
94 static uint8 TxRqstArray_2[DCAN2_MAX_MESSAGEBOXES];\r
95 \r
96 static Can_PduType PduInfoArray_3[DCAN3_MAX_MESSAGEBOXES];\r
97 static uint8 CancelRqstArray_3[DCAN3_MAX_MESSAGEBOXES];\r
98 static uint8 TxRqstArray_3[DCAN3_MAX_MESSAGEBOXES];\r
99 \r
100 \r
101 /* Holds the Controller specific configuration */ \r
102 static Controller_PreConfigType ControllerConfig[] =\r
103 {\r
104     { // DCAN1\r
105         .MaxBoxes = DCAN1_MAX_MESSAGEBOXES,\r
106         .WakeupSrc = 0,\r
107         .PduPtr = PduInfoArray_1,\r
108         .CancelPtr = CancelRqstArray_1,\r
109         .TxPtr = TxRqstArray_1\r
110     },\r
111     { // DCAN2\r
112         .MaxBoxes = DCAN2_MAX_MESSAGEBOXES,\r
113         .WakeupSrc = 1,\r
114         .PduPtr = PduInfoArray_2,\r
115         .CancelPtr = CancelRqstArray_2,\r
116         .TxPtr = TxRqstArray_2\r
117     },\r
118     { // DCAN3\r
119                 .MaxBoxes = DCAN3_MAX_MESSAGEBOXES,\r
120                 .WakeupSrc = 1,\r
121                 .PduPtr = PduInfoArray_3,\r
122                 .CancelPtr = CancelRqstArray_3,\r
123                 .TxPtr = TxRqstArray_3\r
124         }\r
125 \r
126 };\r
127 \r
128 /* Shadow Buffer is used for buffering of received data */ \r
129 static uint8 RxShadowBuf[CAN_ARC_CTRL_CONFIG_CNT][8];\r
130 \r
131 /* Driver must know how often Can_DisableControllerInterrupts() has been called */\r
132 static uint32 IntDisableCount[CAN_ARC_CTRL_CONFIG_CNT];\r
133 \r
134 \r
135 static inline const Can_HardwareObjectType * Can_FindTxHoh(Can_Arc_HTHType hth) {\r
136         for (int i = 0; i < CAN_ARC_CTRL_CONFIG_CNT; i++) {\r
137                 const Can_HardwareObjectType * hoh = CanControllerConfigData[i].Can_Arc_Hoh;\r
138                 hoh--;\r
139                 do {\r
140                         hoh++;\r
141                         if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {\r
142                                 return hoh;\r
143                         }\r
144                 } while (!hoh->Can_Arc_EOL);\r
145         }\r
146         return 0;\r
147 }\r
148 \r
149 static inline uint8 Can_FindControllerId(Can_Arc_HTHType hth) {\r
150         for (int i = 0; i < CAN_ARC_CTRL_CONFIG_CNT; i++) {\r
151                 const Can_HardwareObjectType * hoh = CanControllerConfigData[i].Can_Arc_Hoh;\r
152                 hoh--;\r
153                 do {\r
154                         hoh++;\r
155                         if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {\r
156                                 return i;\r
157                         }\r
158                 } while (!hoh->Can_Arc_EOL);\r
159         }\r
160         return 0;\r
161 }\r
162 \r
163 static inline const Can_HardwareObjectType * Can_FindRxHoh(CanControllerIdType Controller, uint8 msgNr) {\r
164         const Can_HardwareObjectType * hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;\r
165         hoh--;\r
166         do {\r
167                 hoh++;\r
168                 if (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE\r
169                                 && (hoh->Can_Arc_MbMask & (1 << (msgNr - 1))) ) {\r
170                         return hoh;\r
171                 }\r
172         } while (!hoh->Can_Arc_EOL);\r
173         return 0;\r
174 }\r
175 \r
176 uint32 usedBoxes[64] = {0};\r
177 \r
178 void Can_InterruptHandler(CanControllerIdType controller)\r
179 {\r
180     uint32  ErrCounter;\r
181     uint32  MsgNr;\r
182     uint32  MsgId;\r
183     uint8   MsgDlc;\r
184     uint8   DataByteIndex;\r
185     uint8  *SduPtr;\r
186 \r
187     Can_DisableControllerInterrupts(controller);\r
188 \r
189     ErrCounter = CAN_TIMEOUT_DURATION;\r
190 \r
191     uint32 ir = CanRegs[controller]->IR;\r
192 \r
193     if(ir == 0x8000)\r
194     {\r
195         uint32 sr = CanRegs[controller]->SR;\r
196         /* WakeUp Pending */\r
197         if(sr & 0x00000200) {\r
198             /* Set Init Bit, so that Controller is in Stop state */\r
199             CanRegs[controller]->CTL |= 0x1;\r
200            // EcuM_CheckWakeUp(ControllerConfig[0].WakeupSrc);\r
201 \r
202         }\r
203         /* Bus Off */\r
204         if(sr & 0x00000080) {\r
205                 Can_SetControllerMode(controller, CAN_T_STOP); // CANIF272\r
206             //CanIf_ControllerBusOff(0); // Not implemented in Arctic Core\r
207 \r
208         }\r
209     }\r
210     else\r
211     {\r
212         MsgNr = ir;\r
213 \r
214 \r
215         if (MsgNr == 0) {\r
216                 usedBoxes[MsgNr]++;\r
217         } else {\r
218                 usedBoxes[MsgNr]++;\r
219         }\r
220         \r
221 \r
222         /* Read Arbitration, Control and Data Bits and clear IntPnd and NewDat*/\r
223         CanRegs[controller]->IFx[IfRegId].COM = 0x003F0000 | MsgNr;\r
224 \r
225         /* Wait until Busy Flag is 0 */\r
226         while(CanRegs[controller]->IFx[IfRegId].COM & 0x8000)\r
227         {\r
228             ErrCounter--;\r
229             if(ErrCounter == 0)\r
230             {\r
231                 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
232                 ErrCounter = CAN_TIMEOUT_DURATION;\r
233                 return;\r
234             }\r
235         }\r
236 \r
237         /* Transmit Object */\r
238         if(CanRegs[controller]->IFx[IfRegId].ARB & 0x20000000)\r
239         {\r
240             /* Reset TxRqst-Array Element */\r
241                 ControllerConfig[controller].TxPtr[MsgNr - 1] = 0;\r
242             /* A Message was successfully transmitted */\r
243             CanIf_TxConfirmation(ControllerConfig[controller].PduPtr[MsgNr - 1].swPduHandle);\r
244         }\r
245         /* Receive Object */\r
246         else\r
247         {\r
248             /* Extended Id */\r
249             if(CanRegs[controller]->IFx[IfRegId].ARB & 0x40000000)\r
250             {\r
251                 /* Bring Id to standardized format (MSB marks extended Id) */\r
252                 MsgId = (CanRegs[controller]->IFx[IfRegId].ARB & 0x1FFFFFFF) | 0x80000000;\r
253             }\r
254             /* Standard Id */\r
255             else\r
256             {\r
257                 /* Bring Id to standardized format (MSB marks extended Id) */\r
258                 MsgId = (CanRegs[controller]->IFx[IfRegId].ARB & 0x1FFC0000) >> 18;\r
259             }\r
260             /* DLC (Max 8) */\r
261             MsgDlc = CanRegs[controller]->IFx[IfRegId].MC & 0x000F;\r
262             if(MsgDlc > 8)\r
263             {\r
264                 MsgDlc = 8;\r
265             }\r
266             /* Let SduPtr point to Shadow Buffer */\r
267             SduPtr = RxShadowBuf[controller];\r
268 \r
269             /* Copy Message Data to Shadow Buffer */\r
270             for(DataByteIndex = 0; DataByteIndex < MsgDlc; DataByteIndex++)\r
271             {\r
272                 SduPtr[DataByteIndex] = CanRegs[controller]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]];\r
273             }\r
274             /* Indicate successful Reception */\r
275             const Can_HardwareObjectType *hoh = Can_FindRxHoh(controller, MsgNr);\r
276             CanIf_RxIndication(hoh->CanObjectId, MsgId, MsgDlc, SduPtr);\r
277 \r
278         }\r
279     }\r
280     Can_EnableControllerInterrupts(controller);\r
281 }\r
282 \r
283 void Can1_InterruptHandler() {\r
284         Can_InterruptHandler(DCAN1);\r
285 }\r
286 \r
287 void Can2_InterruptHandler() {\r
288         Can_InterruptHandler(DCAN2);\r
289 }\r
290 \r
291 void Can3_InterruptHandler() {\r
292         Can_InterruptHandler(DCAN3);\r
293 }\r
294 \r
295 uint32 Can_CalculateBTR(uint8 Controller) {\r
296 \r
297         uint32 clock = McuE_GetPeripheralClock(PERIPHERAL_CLOCK_CAN);\r
298         uint32 tq1 = CanControllerConfigData[Controller].CanControllerPropSeg + CanControllerConfigData[Controller].CanControllerSeg1;\r
299         uint32 tq2 = CanControllerConfigData[Controller].CanControllerSeg2;\r
300         uint32 ntq = tq1 + tq2 + 1 + 1 + 1;\r
301         uint32 brp = clock / (CanControllerConfigData[Controller].CanControllerBaudRate * 1000 * ntq) - 1;\r
302 \r
303         uint32 retVal = (brp | (tq1 << 8) | (tq2 << 12));\r
304         return retVal;\r
305 }\r
306 \r
307 \r
308 void Can_Init(const Can_ConfigType *Config)\r
309 {\r
310     uint32                    Controller;\r
311     uint8                     MsgNr;\r
312     uint32                    ErrCounter;\r
313     uint32                    Eob;\r
314 \r
315 /* DET Error Check */\r
316 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
317     if(ModuleState != CAN_UNINIT)\r
318     {\r
319         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_TRANSITION);\r
320         return;\r
321     }\r
322     if(Config == NULL)\r
323     {\r
324         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_PARAM_POINTER);\r
325         return;\r
326     }\r
327 #endif \r
328      \r
329     // TODO This should be used instead of other variables in the Can_Lcfg file.\r
330     CurConfig        = Config;\r
331 \r
332     for(Controller = 0; Controller < CAN_ARC_CTRL_CONFIG_CNT; Controller++)\r
333     {\r
334         ErrCounter = CAN_TIMEOUT_DURATION;\r
335 \r
336         /* Init, IE, AutomaticRetransmission, ConfChangeEnable, ABO Off,Parity On, SIE and EIE depending on ControllerConfig, loopback */\r
337 #if(CAN_WAKEUP_SUPPORT == STD_ON)\r
338         CanRegs[Controller]->CTL = 0x02001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);\r
339 #else\r
340         CanRegs[Controller]->CTL = 0x00001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);\r
341 #endif        \r
342         /* LEC 7, TxOk, RxOk, PER */\r
343         CanRegs[Controller]->SR  = 0x0000011F;\r
344 \r
345         /* Test Mode only for Development time: Silent Loopback */\r
346         if (CanControllerConfigData[Controller].Can_Arc_Loopback) {\r
347                 CanRegs[Controller]->TR   = 0x00000018;\r
348         }\r
349             \r
350 \r
351         // Basic message object initialization\r
352         for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MaxBoxes; MsgNr++) {\r
353             /* Initialize the Arrays for Transmit and Cancellation handling */\r
354             *(ControllerConfig[Controller].CancelPtr + MsgNr) = 0;\r
355             *(ControllerConfig[Controller].TxPtr     + MsgNr) = 0;\r
356             \r
357             /* Wait until Busy Flag is 0 */\r
358             while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)\r
359             {\r
360                 ErrCounter--;\r
361                 if(ErrCounter == 0)\r
362                 {\r
363                     Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
364                     ErrCounter = CAN_TIMEOUT_DURATION;\r
365                     return;\r
366                 }\r
367             }\r
368 \r
369             // Initialize all message objects for this controller to invalid state.\r
370             /* Valid = 0 */\r
371                         CanRegs[Controller]->IFx[IfRegId].ARB = 0x00000000;\r
372                         /* Start writing Arbitration Bits */\r
373                         CanRegs[Controller]->IFx[IfRegId].COM = 0x00A80000 | (MsgNr + 1);\r
374 \r
375                         /* Use IFx[0] and IFx[1] alternating */\r
376                         IfRegId ^= 1;\r
377 \r
378         }\r
379 \r
380                 /* Configure the HOHs for this controller. */\r
381                 const Can_HardwareObjectType* hoh;\r
382                 hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;\r
383                 hoh--;\r
384                 do {\r
385                         hoh++;\r
386                         uint64 mbMask = hoh->Can_Arc_MbMask;\r
387                         uint32 mbNr = 0;\r
388                         uint32 nProcessedMb = 0;\r
389 \r
390                         // For every message object in this hoh\r
391                         for(; mbMask != 0; mbMask >>= 1) {\r
392                                 mbNr++;\r
393                                 if (!(mbMask & 1)) {\r
394                                         // This message object is not part of this hoh.\r
395                                         continue;\r
396                                 }\r
397                                 nProcessedMb++;\r
398 \r
399                                 // Check if this is the last message box for this hoh.\r
400                                 if((mbMask != 1) &&\r
401                                    (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)) {\r
402                                         /* EndOfBlock Bit will not be set */\r
403                                         Eob = 0x00000000;\r
404                                 }\r
405                                 else\r
406                                 {\r
407                                         /* EndOfBlock Bit will be set */\r
408                                         Eob = 0x00000080;\r
409                                 }\r
410 \r
411                                 /* DLC=8, Use Mask only for receive, Set RxIE/TxIE depending on pre-config settings, Eob */\r
412                                 CanRegs[Controller]->IFx[IfRegId].MC =    0x00000008 // DLC = 8\r
413                                                                                                                 | 0x00001000 // umask = ON\r
414                                                                                                                 | CanControllerConfigData[Controller].CanRxProcessing // Rx interrupt enabled\r
415                                                                                                                 | (CanControllerConfigData[Controller].CanTxProcessing << 1) // Tx confirmation interrupt enabled\r
416                                                                                                                 | (Eob & ~(hoh->CanObjectType >> 22)); // Eob, only for Rx.\r
417 \r
418                                 //CanRegs[Controller]->IFx[IfRegId].MC = 0x00001008 | CanControllerConfigData[Controller].CanRxProcessing | (CanControllerConfigData[Controller].CanTxProcessing) | Eob & ~(hoh->CanObjectType >> 17);\r
419 \r
420                                 if(hoh->CanIdType == CAN_ID_TYPE_STANDARD)      /* Standard Identifiers */\r
421                                 {\r
422                                         /* Only Standard-Ids are accepted, Set Mask */\r
423                                         CanRegs[Controller]->IFx[IfRegId].MASK = 0x80000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF);\r
424                                         /* Message valid, Id, Direction */\r
425                                         CanRegs[Controller]->IFx[IfRegId].ARB  = 0x80000000 | ((hoh->CanIdValue & 0x7FF) << 18) | hoh->CanObjectType;\r
426                                 }\r
427                                 else if(hoh->CanIdType == CAN_ID_TYPE_EXTENDED) /* Extended Identifiers */\r
428                                 {\r
429                                         /* Only Extended-Ids are accepted, Set Mask */\r
430                                         CanRegs[Controller]->IFx[IfRegId].MASK = 0x80000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF);\r
431                                         /* Message valid, Id, Direction */\r
432                                         CanRegs[Controller]->IFx[IfRegId].ARB  = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFFF) | hoh->CanObjectType;\r
433                                 }\r
434                                 else /* Mixed Identifiers */\r
435                                 {\r
436                                         /* Standard- and Mixed-Ids are accepted, Set Mask */\r
437                                         CanRegs[Controller]->IFx[IfRegId].MASK = 0x00000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFF);\r
438                                         /* Message valid, Id, Direction */\r
439                                         CanRegs[Controller]->IFx[IfRegId].ARB  = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFF) | hoh->CanObjectType;\r
440                                 }\r
441                                 /* Start writing Mask, Arb, Control and Id bits */\r
442                                 CanRegs[Controller]->IFx[IfRegId].COM  = 0x00F80000 | mbNr;\r
443 \r
444                                 /* Use IFx[0] and IFx[1] alternating */\r
445                                 IfRegId ^= 1;\r
446 \r
447                         }\r
448                 } while (!hoh->Can_Arc_EOL);\r
449 \r
450 \r
451         /* Set Bit Timing Register */\r
452         CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);\r
453 \r
454         /* Reset CCE Bit */\r
455         CanRegs[Controller]->CTL &= ~0x00000040;\r
456 \r
457 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
458         /* Switch Controller State to CANIF_CS_STOPPED */\r
459         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
460 #endif\r
461 \r
462         // Install interrupt handlers\r
463                 TaskType tid;\r
464                 if (CanControllerConfigData[Controller].CanControllerId == DCAN1) {\r
465                         tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2 ,"DCAN1Level0");\r
466                         Irq_AttachIsr2(tid, NULL, 16);\r
467 \r
468                         tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2, "DCAN1Level1");\r
469                         Irq_AttachIsr2(tid, NULL, 29);\r
470 \r
471                 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN2) {\r
472                         tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2 ,"DCAN2Level0");\r
473                         Irq_AttachIsr2(tid, NULL, 35);\r
474 \r
475                         tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2, "DCAN2Level1");\r
476                         Irq_AttachIsr2(tid, NULL, 42);\r
477 \r
478                 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN3) {\r
479                         tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2 ,"DCAN3Level0");\r
480                         Irq_AttachIsr2(tid, NULL, 45);\r
481 \r
482                         tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2, "DCAN3Level1");\r
483                         Irq_AttachIsr2(tid, NULL, 55);\r
484 \r
485                 }\r
486 \r
487     }\r
488 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
489     /* Switch Module State to CAN_READY */\r
490     ModuleState = CAN_READY;\r
491 #endif\r
492 \r
493 \r
494 \r
495 }\r
496 \r
497 \r
498 \r
499 void Can_InitController(uint8 Controller, const Can_ControllerConfigType* Config)\r
500 {\r
501     uint8   MsgNr;\r
502     uint32  ErrCounter;\r
503 \r
504 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
505     if(Config == NULL)\r
506     {\r
507         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_POINTER);\r
508         return;\r
509     }\r
510     if(ModuleState == CAN_UNINIT)\r
511     {\r
512         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_UNINIT);\r
513         return;\r
514     }\r
515     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
516     {\r
517         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_CONTROLLER);\r
518         return;\r
519     }\r
520     if(ControllerMode[Controller] != CANIF_CS_STOPPED)\r
521     {\r
522         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_TRANSITION);\r
523         return;\r
524     }\r
525 #endif \r
526 \r
527     ErrCounter = CAN_TIMEOUT_DURATION;\r
528     \r
529     //for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MessageBoxCount; MsgNr++)\r
530         const Can_HardwareObjectType* hoh;\r
531         hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;\r
532         uint64 mbMask = hoh->Can_Arc_MbMask;\r
533         uint32 nProcessedMb = 0;\r
534         MsgNr = 0;\r
535 \r
536         // For every message object in this hoh\r
537         for(; mbMask != 0; mbMask >>= 1) {\r
538                 MsgNr++;\r
539                 if (!(mbMask & 1)) {\r
540                         // This message object is not part of this hoh.\r
541                         continue;\r
542                 }\r
543                 nProcessedMb++;\r
544 \r
545         /* Wait until Busy Flag is 0 */\r
546         while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)\r
547         {\r
548             ErrCounter--;\r
549             if(ErrCounter == 0)\r
550             {\r
551                 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
552                 ErrCounter = CAN_TIMEOUT_DURATION;\r
553                 return;\r
554             }\r
555         }\r
556         /* Read actual MaskRegister value of MessageObject */\r
557         CanRegs[Controller]->IFx[IfRegId].COM = 0x004C0000 | (MsgNr);\r
558 \r
559         /* Wait until Busy Flag is 0 */\r
560         while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)\r
561         {\r
562             ErrCounter--;\r
563             if(ErrCounter == 0)\r
564             {\r
565                 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
566                 ErrCounter = CAN_TIMEOUT_DURATION;\r
567                 return;\r
568             }\r
569         }\r
570         CanRegs[Controller]->IFx[IfRegId].MASK &= 0xD0000000;\r
571         /* Set new Mask */\r
572         CanRegs[Controller]->IFx[IfRegId].MASK |= (*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF;\r
573         /* Write new Mask to MaskRegister */\r
574         CanRegs[Controller]->IFx[IfRegId].COM   = 0x00C80000 | (MsgNr);\r
575 \r
576         IfRegId ^= 1;\r
577     }\r
578 \r
579     /* Wait until Busy Flag is 0 */\r
580     while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)\r
581     {\r
582         ErrCounter--;\r
583         if(ErrCounter == 0)\r
584         {\r
585             Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
586             ErrCounter = CAN_TIMEOUT_DURATION;\r
587             return;\r
588         }\r
589     }   \r
590     /* Set CCE Bit to allow access to BitTiming Register (Init already set, in mode "stopped") */\r
591     CanRegs[Controller]->CTL |= 0x00000040;\r
592     /* Set Bit Timing Register */\r
593     CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);\r
594     /* Clear CCE Bit */\r
595     CanRegs[Controller]->CTL &= ~0x00000040;\r
596 \r
597 }\r
598 \r
599 \r
600 Can_ReturnType Can_SetControllerMode(uint8 Controller, Can_StateTransitionType Transition)\r
601 {\r
602     Can_ReturnType Status     = CAN_OK;\r
603     uint32         ErrCounter = CAN_TIMEOUT_DURATION;\r
604     uint32         RegBuf;\r
605     \r
606 #if(CAN_DEV_ERROR_DETECT == STD_ON)    \r
607     if(ModuleState == CAN_UNINIT)\r
608     {\r
609         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_UNINIT);\r
610         return CAN_NOT_OK;\r
611     }\r
612     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
613     {\r
614         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_PARAM_CONTROLLER);\r
615         return CAN_NOT_OK;\r
616     }\r
617     if(((Transition == CAN_T_START ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||\r
618        ((Transition == CAN_T_STOP  ) && (ControllerMode[Controller] != CANIF_CS_STARTED)) ||\r
619        ((Transition == CAN_T_SLEEP ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||\r
620        ((Transition == CAN_T_WAKEUP) && (ControllerMode[Controller] != CANIF_CS_SLEEP  )))\r
621     {\r
622         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);\r
623         return CAN_NOT_OK;\r
624     }\r
625 #endif \r
626 \r
627     switch(Transition)\r
628     {\r
629     case CAN_T_START:\r
630         /* Clear Init Bit */\r
631         CanRegs[Controller]->CTL  &= ~0x00000001;\r
632         /* Clear Status Register */\r
633         CanRegs[Controller]->SR    = 0x0000011F;\r
634 \r
635         ControllerMode[Controller] = CANIF_CS_STARTED;\r
636         Can_EnableControllerInterrupts(Controller);\r
637         break;\r
638 \r
639     case CAN_T_STOP:\r
640         /* Set Init Bit */\r
641         CanRegs[Controller]->CTL  |=  0x00000001;\r
642         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
643         Can_DisableControllerInterrupts(Controller);\r
644         break;\r
645 \r
646     case CAN_T_SLEEP:\r
647         /* Set PDR  Bit */\r
648         CanRegs[Controller]->CTL |=  0x01000000;\r
649         /* Save actual Register status */\r
650         RegBuf = CanRegs[Controller]->CTL;\r
651         /* Disable Status Interrupts and WUBA */\r
652         CanRegs[Controller]->CTL &= ~0x02000004;\r
653         /* Wait until Local Power Down Mode acknowledged */\r
654         while(!(CanRegs[Controller]->SR & 0x00000400))\r
655         {\r
656             /* Check if a WakeUp occurs */\r
657             if(CanRegs[Controller]->SR & 0x00000200)\r
658             {\r
659                 Status = CAN_NOT_OK;\r
660                 break;\r
661             }\r
662             ErrCounter--;\r
663             if(ErrCounter == 0)\r
664             {\r
665                 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
666                 ErrCounter = CAN_TIMEOUT_DURATION;\r
667                 Status     = CAN_NOT_OK;\r
668                 break;\r
669             }\r
670         }\r
671         /* Reset Control Register */\r
672         CanRegs[Controller]->CTL   = RegBuf;\r
673         ControllerMode[Controller] = CANIF_CS_SLEEP;\r
674         break;\r
675 \r
676     case CAN_T_WAKEUP:\r
677         /* Clear PDR Bit */\r
678         CanRegs[Controller]->CTL  &= ~0x01000000;\r
679         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
680         break;\r
681 \r
682     default:\r
683 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
684         /* Invalid Transition */\r
685         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);\r
686         return CAN_NOT_OK;\r
687 #endif\r
688         break;\r
689     }\r
690 \r
691     return Status;\r
692 }\r
693 \r
694 \r
695 void Can_DisableControllerInterrupts(uint8 Controller)\r
696 {\r
697 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
698     if(ModuleState == CAN_UNINIT)\r
699     {\r
700         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_UNINIT);\r
701         return;\r
702     }\r
703     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
704     {\r
705         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_PARAM_CONTROLLER);\r
706         return;\r
707     }\r
708 #endif \r
709     /* Clear IE */\r
710     CanRegs[Controller]->CTL &= ~DCAN_IRQ_MASK;\r
711     /* Increment Disable Counter */\r
712     IntDisableCount[Controller]++;\r
713 }\r
714 \r
715 void Can_EnableControllerInterrupts(uint8 Controller)\r
716 {\r
717 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
718     if(ModuleState == CAN_UNINIT)\r
719     {\r
720         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_UNINIT);\r
721         return;\r
722     }\r
723     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
724     {\r
725         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_PARAM_CONTROLLER);\r
726         return;\r
727     }\r
728 #endif    \r
729     if(IntDisableCount[Controller] > 0)\r
730     {\r
731         if(IntDisableCount[Controller] == 1)\r
732         {\r
733             /* Set IE */\r
734             CanRegs[Controller]->CTL |= DCAN_IRQ_MASK;\r
735         }\r
736         IntDisableCount[Controller]--;\r
737     }\r
738 }\r
739 \r
740 \r
741 void Can_Cbk_CheckWakeup(uint8 Controller)\r
742 {\r
743         /* TODO not supported yet.\r
744 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
745     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
746     {\r
747         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0x0B, CAN_E_PARAM_CONTROLLER);\r
748         return CAN_NOT_OK;\r
749     }\r
750 #endif\r
751     // Check WakeUpPending\r
752     if(CanRegs[Controller]->SR & 0x00000200)\r
753     {\r
754         return E_OK;\r
755     }\r
756     else\r
757     {\r
758         return E_NOT_OK;\r
759     }\r
760     */\r
761 }\r
762 \r
763 \r
764 Can_ReturnType Can_Write(Can_Arc_HTHType Hth, Can_PduType *PduInfo)\r
765 {\r
766     uint32                 ErrCounter;\r
767     uint8                  ControllerId;\r
768     uint8                  MsgNr;\r
769     uint32                 ArbRegValue;\r
770     uint8                  DataByteIndex;\r
771     uint8                 *CurSduPtr;\r
772     Can_PduType           *CurPduArrayPtr;\r
773     uint8                 *CurCancelRqstPtr;\r
774     uint8                 *CurTxRqstPtr;\r
775 \r
776     CurSduPtr       = PduInfo->sdu;\r
777     ErrCounter      = CAN_TIMEOUT_DURATION;\r
778     \r
779 /* DET Error Check */\r
780 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
781     if(PduInfo == NULL || PduInfo->sdu == NULL)\r
782     {\r
783         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_POINTER);\r
784         return CAN_NOT_OK;\r
785     }\r
786     if(ModuleState == CAN_UNINIT)\r
787     {\r
788         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_UNINIT);\r
789         return CAN_NOT_OK;\r
790     }\r
791     if(PduInfo->length > 8)\r
792     {\r
793         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_DLC);\r
794         return CAN_NOT_OK;        \r
795     }\r
796 #endif\r
797 \r
798     ControllerId = Can_FindControllerId(Hth);\r
799     \r
800     const Can_HardwareObjectType *hoh = Can_FindTxHoh(Hth);\r
801 \r
802 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
803     if(hoh->CanObjectType != CAN_OBJECT_TYPE_TRANSMIT)\r
804         {\r
805                 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_HANDLE);\r
806                 return CAN_NOT_OK;\r
807         }\r
808 #endif\r
809     uint64 mbMask = hoh->Can_Arc_MbMask;\r
810     MsgNr = 0;\r
811     for(; mbMask != 0; mbMask >>= 1) {\r
812         MsgNr++;\r
813                 if (!(mbMask & 1)) {\r
814                         continue; // This message object is not part of this hoh.\r
815                 }\r
816     }\r
817 \r
818     CurPduArrayPtr   = ControllerConfig[ControllerId].PduPtr    + (MsgNr - 1);\r
819     CurCancelRqstPtr = ControllerConfig[ControllerId].CancelPtr + (MsgNr - 1);\r
820     CurTxRqstPtr     = ControllerConfig[ControllerId].TxPtr     + (MsgNr - 1);\r
821     \r
822     /* Bring Id Value to appropriate format and set ArbRegValue */\r
823     if(PduInfo->id & 0x80000000)\r
824     {\r
825         /* MsgVal, Ext, Transmit, Extended Id */ \r
826         ArbRegValue = 0xD0000000 | (PduInfo->id & 0x1FFFFFFF);\r
827     }\r
828     else\r
829     {\r
830         /* MsgVal, Std, Transmit, Standard Id */ \r
831         ArbRegValue = 0xA0000000 | ((PduInfo->id & 0x7FF) << 18);\r
832     }\r
833 \r
834     /* Check if TxRqst Bit of MsgObject is set */\r
835     if(CanRegs[ControllerId]->TRx[MsgNr >> 5] & (1 << (MsgNr & 0x1F)))\r
836     {\r
837         return CAN_BUSY;\r
838     }\r
839 \r
840     /* Wait until Busy Flag is 0 */\r
841     while(CanRegs[ControllerId]->IFx[IfRegId].COM & 0x00008000)\r
842     {\r
843         ErrCounter--;\r
844         if(ErrCounter == 0)\r
845         {\r
846             Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
847             ErrCounter = CAN_TIMEOUT_DURATION;\r
848             return CAN_NOT_OK;\r
849         }\r
850     }\r
851 \r
852     /* Set NewDat, TxIE (dep on ControllerConfig), TxRqst, EoB and DLC */\r
853     CanRegs[ControllerId]->IFx[IfRegId].MC =      0x00000100 // Tx request\r
854                                                                                         | 0x00000080 // Eob should be set to one for tx\r
855                                                                                         | (0x000F & PduInfo->length) // Set DLC\r
856                                                                                         | CanControllerConfigData[ControllerId].CanRxProcessing\r
857                                                                                         | (CanControllerConfigData[ControllerId].CanTxProcessing << 1); // Tx confirmation interrupt enabled\r
858 \r
859 \r
860     //CanRegs[ControllerId]->IFx[IfRegId].MC = 0x00000180 | (0x000F & PduInfo->length) | (CanControllerConfigData[ControllerId].CanTxProcessing);\r
861 \r
862     /* Set ArbitrationRegister */\r
863     CanRegs[ControllerId]->IFx[IfRegId].ARB = ArbRegValue;\r
864 \r
865     /* Set Databytes */\r
866     for(DataByteIndex = 0; DataByteIndex < PduInfo->length; DataByteIndex++)\r
867     {\r
868         CanRegs[ControllerId]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]] = *CurSduPtr++;\r
869     }\r
870 \r
871     /* Start transmission to MessageRAM */\r
872     CanRegs[ControllerId]->IFx[IfRegId].COM = 0x00BF0000 | MsgNr;\r
873     \r
874     /* Save the PduInfo in PduArray, so that messages can be identified later */\r
875     *CurPduArrayPtr = *PduInfo;\r
876     /* TxRqstArray-Elements are used to identifiy transmitted objects in polling mode */\r
877     *CurTxRqstPtr   = 1;\r
878     \r
879     IfRegId ^= 1;\r
880        \r
881     return CAN_OK;\r
882 }\r
883 \r
884 \r
885 void Can_MainFunction_Write()\r
886 {\r
887         // Not supported\r
888 }\r
889 \r
890 void Can_MainFunction_Read()\r
891 {\r
892         // Not supported\r
893 }\r
894 \r
895 void Can_MainFunction_BusOff()\r
896 {\r
897   // Not supported\r
898 }\r
899 \r
900 void Can_MainFunction_Wakeup()\r
901 {\r
902    // Not supported\r
903 }\r
904 \r
905 \r