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