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