]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cr4/drivers/Can.c
More work on rte_simple example.
[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 \r
380 /* DET Error Check */\r
381 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
382     if(ModuleState != CAN_UNINIT)\r
383     {\r
384         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_TRANSITION);\r
385         return;\r
386     }\r
387     if(Config == NULL)\r
388     {\r
389         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_PARAM_POINTER);\r
390         return;\r
391     }\r
392 #endif \r
393 \r
394     imask_t i_state = McuE_EnterCriticalSection();\r
395 \r
396     // TODO This should be used instead of other variables in the Can_Lcfg file.\r
397     CurConfig        = Config;\r
398 \r
399     for(Controller = 0; Controller < CAN_ARC_CTRL_CONFIG_CNT; Controller++)\r
400     {\r
401         ErrCounter = CAN_TIMEOUT_DURATION;\r
402 \r
403         /* Init, IE, AutomaticRetransmission, ConfChangeEnable, ABO Off,Parity On, SIE and EIE depending on ControllerConfig, loopback */\r
404 #if(CAN_WAKEUP_SUPPORT == STD_ON)\r
405         CanRegs[Controller]->CTL = 0x02001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);\r
406 #else\r
407         CanRegs[Controller]->CTL = 0x00001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);\r
408 #endif        \r
409         /* LEC 7, TxOk, RxOk, PER */\r
410         CanRegs[Controller]->SR  = 0x0000011F;\r
411 \r
412         /* Test Mode only for Development time: Silent Loopback */\r
413         if (CanControllerConfigData[Controller].Can_Arc_Loopback) {\r
414                 CanRegs[Controller]->TR   = 0x00000018;\r
415         }\r
416             \r
417 \r
418         // Basic message object initialization\r
419         for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MaxBoxes; MsgNr++) {\r
420             /* Initialize the Arrays for Transmit and Cancellation handling */\r
421             *(ControllerConfig[Controller].CancelPtr + MsgNr) = 0;\r
422             *(ControllerConfig[Controller].TxPtr     + MsgNr) = 0;\r
423             \r
424             DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);\r
425 \r
426             // Initialize all message objects for this controller to invalid state.\r
427             /* Valid = 0 */\r
428                         CanRegs[Controller]->IFx[IfRegId].ARB = 0x00000000;\r
429                         /* Start writing Arbitration Bits */\r
430                         CanRegs[Controller]->IFx[IfRegId].COM = 0x00A80000 | (MsgNr + 1);\r
431 \r
432                         /* Use IFx[0] and IFx[1] alternating */\r
433                         IfRegId ^= 1;\r
434 \r
435         }\r
436 \r
437                 /* Configure the HOHs for this controller. */\r
438                 const Can_HardwareObjectType* hoh;\r
439                 hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;\r
440                 hoh--;\r
441                 do {\r
442                         hoh++;\r
443                         uint64 mbMask = hoh->Can_Arc_MbMask;\r
444                         uint32 mbNr = 0;\r
445                         uint32 nProcessedMb = 0;\r
446 \r
447                         // For every message object in this hoh\r
448                         for(; mbMask != 0; mbMask >>= 1) {\r
449                                 mbNr++;\r
450                                 if (!(mbMask & 1)) {\r
451                                         // This message object is not part of this hoh.\r
452                                         continue;\r
453                                 }\r
454                                 nProcessedMb++;\r
455 \r
456                                 // Check if this is the last message box for this hoh.\r
457                                 if((mbMask != 1) &&\r
458                                    (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)) {\r
459                                         /* EndOfBlock Bit will not be set */\r
460                                         Eob = 0x00000000;\r
461                                 }\r
462                                 else\r
463                                 {\r
464                                         /* EndOfBlock Bit will be set */\r
465                                         Eob = 0x00000080;\r
466                                 }\r
467 \r
468                                 /* DLC=8, Use Mask only for receive, Set RxIE/TxIE depending on pre-config settings, Eob */\r
469                                 CanRegs[Controller]->IFx[IfRegId].MC =    0x00000008 // DLC = 8\r
470                                                                                                                 | 0x00001000 // umask = ON\r
471                                                                                                                 | CanControllerConfigData[Controller].CanRxProcessing // Rx interrupt enabled\r
472                                                                                                                 | (CanControllerConfigData[Controller].CanTxProcessing << 1) // Tx confirmation interrupt enabled\r
473                                                                                                                 | (Eob & ~(hoh->CanObjectType >> 22)); // Eob, only for Rx.\r
474 \r
475                                 //CanRegs[Controller]->IFx[IfRegId].MC = 0x00001008 | CanControllerConfigData[Controller].CanRxProcessing | (CanControllerConfigData[Controller].CanTxProcessing) | Eob & ~(hoh->CanObjectType >> 17);\r
476 \r
477                                 if(hoh->CanIdType == CAN_ID_TYPE_STANDARD)      /* Standard Identifiers */\r
478                                 {\r
479                                         /* Only Standard-Ids are accepted, Set Mask */\r
480                                         CanRegs[Controller]->IFx[IfRegId].MASK = 0x80000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF);\r
481                                         /* Message valid, Id, Direction */\r
482                                         CanRegs[Controller]->IFx[IfRegId].ARB  = 0x80000000 | ((hoh->CanIdValue & 0x7FF) << 18) | hoh->CanObjectType;\r
483                                 }\r
484                                 else if(hoh->CanIdType == CAN_ID_TYPE_EXTENDED) /* Extended Identifiers */\r
485                                 {\r
486                                         /* Only Extended-Ids are accepted, Set Mask */\r
487                                         CanRegs[Controller]->IFx[IfRegId].MASK = 0x80000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF);\r
488                                         /* Message valid, Id, Direction */\r
489                                         CanRegs[Controller]->IFx[IfRegId].ARB  = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFFF) | hoh->CanObjectType;\r
490                                 }\r
491                                 else /* Mixed Identifiers */\r
492                                 {\r
493                                         /* Standard- and Mixed-Ids are accepted, Set Mask */\r
494                                         CanRegs[Controller]->IFx[IfRegId].MASK = 0x00000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFF);\r
495                                         /* Message valid, Id, Direction */\r
496                                         CanRegs[Controller]->IFx[IfRegId].ARB  = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFF) | hoh->CanObjectType;\r
497                                 }\r
498                                 /* Start writing Mask, Arb, Control and Id bits */\r
499                                 CanRegs[Controller]->IFx[IfRegId].COM  = 0x00F80000 | mbNr;\r
500 \r
501                                 /* Use IFx[0] and IFx[1] alternating */\r
502                                 IfRegId ^= 1;\r
503 \r
504                         }\r
505                 } while (!hoh->Can_Arc_EOL);\r
506 \r
507 \r
508         /* Set Bit Timing Register */\r
509         CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);\r
510 \r
511         /* Reset CCE Bit */\r
512         CanRegs[Controller]->CTL &= ~0x00000040;\r
513 \r
514 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
515         /* Switch Controller State to CANIF_CS_STOPPED */\r
516         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
517 #endif\r
518 \r
519         // Install interrupt handlers\r
520                 if (CanControllerConfigData[Controller].CanControllerId == DCAN1) {\r
521                         ISR_INSTALL_ISR2("DCAN1Level0",Can1_InterruptHandler,CAN1_LEVEL_0,2,0);\r
522                         ISR_INSTALL_ISR2("DCAN1Level1",Can1_InterruptHandler,CAN1_LEVEL_1,2,0);\r
523 \r
524                 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN2) {\r
525                         ISR_INSTALL_ISR2("DCAN2Level0",Can2_InterruptHandler,CAN2_LEVEL_0,2,0);\r
526                         ISR_INSTALL_ISR2("DCAN2Level1",Can2_InterruptHandler,CAN2_LEVEL_1,2,0);\r
527 \r
528                 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN3) {\r
529                         ISR_INSTALL_ISR2("DCAN3Level0",Can3_InterruptHandler,CAN3_LEVEL_0,2,0);\r
530                         ISR_INSTALL_ISR2("DCAN3Level1",Can3_InterruptHandler,CAN3_LEVEL_1,2,0);\r
531 \r
532                 }\r
533 \r
534     }\r
535 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
536     /* Switch Module State to CAN_READY */\r
537     ModuleState = CAN_READY;\r
538 #endif\r
539 \r
540     McuE_ExitCriticalSection(i_state);\r
541 \r
542 }\r
543 \r
544 \r
545 \r
546 void Can_InitController(uint8 Controller, const Can_ControllerConfigType* Config)\r
547 {\r
548     uint8   MsgNr;\r
549     uint32  ErrCounter;\r
550 \r
551 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
552     if(Config == NULL)\r
553     {\r
554         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_POINTER);\r
555         return;\r
556     }\r
557     if(ModuleState == CAN_UNINIT)\r
558     {\r
559         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_UNINIT);\r
560         return;\r
561     }\r
562     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
563     {\r
564         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_CONTROLLER);\r
565         return;\r
566     }\r
567     if(ControllerMode[Controller] != CANIF_CS_STOPPED)\r
568     {\r
569         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_TRANSITION);\r
570         return;\r
571     }\r
572 #endif \r
573 \r
574     imask_t i_state = McuE_EnterCriticalSection();\r
575 \r
576     ErrCounter = CAN_TIMEOUT_DURATION;\r
577     \r
578     //for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MessageBoxCount; MsgNr++)\r
579         const Can_HardwareObjectType* hoh;\r
580         hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;\r
581         uint64 mbMask = hoh->Can_Arc_MbMask;\r
582         uint32 nProcessedMb = 0;\r
583         MsgNr = 0;\r
584 \r
585         // For every message object in this hoh\r
586         for(; mbMask != 0; mbMask >>= 1) {\r
587                 MsgNr++;\r
588                 if (!(mbMask & 1)) {\r
589                         // This message object is not part of this hoh.\r
590                         continue;\r
591                 }\r
592                 nProcessedMb++;\r
593 \r
594                 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);\r
595 \r
596                 /* Read actual MaskRegister value of MessageObject */\r
597         CanRegs[Controller]->IFx[IfRegId].COM = 0x004C0000 | (MsgNr);\r
598 \r
599         DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);\r
600 \r
601         CanRegs[Controller]->IFx[IfRegId].MASK &= 0xD0000000;\r
602         /* Set new Mask */\r
603         CanRegs[Controller]->IFx[IfRegId].MASK |= (*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF;\r
604         /* Write new Mask to MaskRegister */\r
605         CanRegs[Controller]->IFx[IfRegId].COM   = 0x00C80000 | (MsgNr);\r
606 \r
607         IfRegId ^= 1;\r
608     }\r
609 \r
610         DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);\r
611 \r
612     /* Set CCE Bit to allow access to BitTiming Register (Init already set, in mode "stopped") */\r
613     CanRegs[Controller]->CTL |= 0x00000040;\r
614     /* Set Bit Timing Register */\r
615     CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);\r
616     /* Clear CCE Bit */\r
617     CanRegs[Controller]->CTL &= ~0x00000040;\r
618 \r
619     McuE_ExitCriticalSection(i_state);\r
620 }\r
621 \r
622 \r
623 Can_ReturnType Can_SetControllerMode(uint8 Controller, Can_StateTransitionType Transition)\r
624 {\r
625     Can_ReturnType Status     = CAN_OK;\r
626     uint32         ErrCounter = CAN_TIMEOUT_DURATION;\r
627     uint32         RegBuf;\r
628     \r
629 #if(CAN_DEV_ERROR_DETECT == STD_ON)    \r
630     if(ModuleState == CAN_UNINIT)\r
631     {\r
632         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_UNINIT);\r
633         return CAN_NOT_OK;\r
634     }\r
635     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
636     {\r
637         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_PARAM_CONTROLLER);\r
638         return CAN_NOT_OK;\r
639     }\r
640     if(((Transition == CAN_T_START ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||\r
641        ((Transition == CAN_T_STOP  ) && (ControllerMode[Controller] != CANIF_CS_STARTED)) ||\r
642        ((Transition == CAN_T_SLEEP ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||\r
643        ((Transition == CAN_T_WAKEUP) && (ControllerMode[Controller] != CANIF_CS_SLEEP  )))\r
644     {\r
645         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);\r
646         return CAN_NOT_OK;\r
647     }\r
648 #endif \r
649 \r
650     switch(Transition)\r
651     {\r
652     case CAN_T_START:\r
653         /* Clear Init Bit */\r
654         CanRegs[Controller]->CTL  &= ~0x00000001;\r
655         /* Clear Status Register */\r
656         CanRegs[Controller]->SR    = 0x0000011F;\r
657 \r
658         ControllerMode[Controller] = CANIF_CS_STARTED;\r
659         Can_EnableControllerInterrupts(Controller);\r
660         break;\r
661 \r
662     case CAN_T_STOP:\r
663         /* Set Init Bit */\r
664         CanRegs[Controller]->CTL  |=  0x00000001;\r
665         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
666         Can_DisableControllerInterrupts(Controller);\r
667         break;\r
668 \r
669     case CAN_T_SLEEP:\r
670         /* Set PDR  Bit */\r
671         CanRegs[Controller]->CTL |=  0x01000000;\r
672         /* Save actual Register status */\r
673         RegBuf = CanRegs[Controller]->CTL;\r
674         /* Disable Status Interrupts and WUBA */\r
675         CanRegs[Controller]->CTL &= ~0x02000004;\r
676         /* Wait until Local Power Down Mode acknowledged */\r
677         while(!(CanRegs[Controller]->SR & 0x00000400))\r
678         {\r
679             /* Check if a WakeUp occurs */\r
680             if(CanRegs[Controller]->SR & 0x00000200)\r
681             {\r
682                 Status = CAN_NOT_OK;\r
683                 break;\r
684             }\r
685             ErrCounter--;\r
686             if(ErrCounter == 0)\r
687             {\r
688                 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
689                 ErrCounter = CAN_TIMEOUT_DURATION;\r
690                 Status     = CAN_NOT_OK;\r
691                 break;\r
692             }\r
693         }\r
694         /* Reset Control Register */\r
695         CanRegs[Controller]->CTL   = RegBuf;\r
696         ControllerMode[Controller] = CANIF_CS_SLEEP;\r
697         break;\r
698 \r
699     case CAN_T_WAKEUP:\r
700         /* Clear PDR Bit */\r
701         CanRegs[Controller]->CTL  &= ~0x01000000;\r
702         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
703         break;\r
704 \r
705     default:\r
706 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
707         /* Invalid Transition */\r
708         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);\r
709         return CAN_NOT_OK;\r
710 #endif\r
711         break;\r
712     }\r
713 \r
714     return Status;\r
715 }\r
716 \r
717 \r
718 void Can_DisableControllerInterrupts(uint8 Controller)\r
719 {\r
720 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
721     if(ModuleState == CAN_UNINIT)\r
722     {\r
723         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_UNINIT);\r
724         return;\r
725     }\r
726     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
727     {\r
728         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_PARAM_CONTROLLER);\r
729         return;\r
730     }\r
731 #endif \r
732     /* Clear IE */\r
733     CanRegs[Controller]->CTL &= ~DCAN_IRQ_MASK;\r
734     /* Increment Disable Counter */\r
735     IntDisableCount[Controller]++;\r
736 }\r
737 \r
738 void Can_EnableControllerInterrupts(uint8 Controller)\r
739 {\r
740 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
741     if(ModuleState == CAN_UNINIT)\r
742     {\r
743         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_UNINIT);\r
744         return;\r
745     }\r
746     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
747     {\r
748         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_PARAM_CONTROLLER);\r
749         return;\r
750     }\r
751 #endif    \r
752     if(IntDisableCount[Controller] > 0)\r
753     {\r
754         if(IntDisableCount[Controller] == 1)\r
755         {\r
756             /* Set IE */\r
757             CanRegs[Controller]->CTL |= DCAN_IRQ_MASK;\r
758         }\r
759         IntDisableCount[Controller]--;\r
760     }\r
761 }\r
762 \r
763 \r
764 void Can_Cbk_CheckWakeup(uint8 Controller)\r
765 {\r
766         /* TODO not supported yet.\r
767 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
768     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
769     {\r
770         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0x0B, CAN_E_PARAM_CONTROLLER);\r
771         return CAN_NOT_OK;\r
772     }\r
773 #endif\r
774     // Check WakeUpPending\r
775     if(CanRegs[Controller]->SR & 0x00000200)\r
776     {\r
777         return E_OK;\r
778     }\r
779     else\r
780     {\r
781         return E_NOT_OK;\r
782     }\r
783     */\r
784 }\r
785 \r
786 \r
787 Can_ReturnType Can_Write(Can_Arc_HTHType Hth, Can_PduType *PduInfo)\r
788 {\r
789     uint8                  ControllerId;\r
790     uint8                  MsgNr;\r
791     uint32                 ArbRegValue;\r
792     uint8                  DataByteIndex;\r
793     uint8                 *CurSduPtr;\r
794     Can_PduType           *CurPduArrayPtr;\r
795     uint8                 *CurCancelRqstPtr;\r
796     uint8                 *CurTxRqstPtr;\r
797 \r
798     CurSduPtr       = PduInfo->sdu;\r
799     \r
800 \r
801 /* DET Error Check */\r
802 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
803     if(PduInfo == NULL || PduInfo->sdu == NULL)\r
804     {\r
805         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_POINTER);\r
806         return CAN_NOT_OK;\r
807     }\r
808     if(ModuleState == CAN_UNINIT)\r
809     {\r
810         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_UNINIT);\r
811         return CAN_NOT_OK;\r
812     }\r
813     if(PduInfo->length > 8)\r
814     {\r
815         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_DLC);\r
816         return CAN_NOT_OK;        \r
817     }\r
818 #endif\r
819 \r
820     ControllerId = Can_FindControllerId(Hth);\r
821     \r
822     const Can_HardwareObjectType *hoh = Can_FindTxHoh(Hth);\r
823 \r
824 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
825     if(hoh->CanObjectType != CAN_OBJECT_TYPE_TRANSMIT)\r
826         {\r
827                 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_HANDLE);\r
828                 return CAN_NOT_OK;\r
829         }\r
830 #endif\r
831     uint64 mbMask = hoh->Can_Arc_MbMask;\r
832     MsgNr = 0;\r
833     for(; mbMask != 0; mbMask >>= 1) {\r
834         MsgNr++;\r
835                 if (!(mbMask & 1)) {\r
836                         continue; // This message object is not part of this hoh.\r
837                 }\r
838                 /* Check if TxRqst Bit of MsgObject is set */\r
839                 if(CanRegs[ControllerId]->TRx[MsgNr >> 5] & (1 << (MsgNr & 0x1F)))\r
840                 {\r
841                         continue;\r
842                 }\r
843                 break;\r
844     }\r
845 \r
846         /* Check if TxRqst Bit of MsgObject is set */\r
847         if(CanRegs[ControllerId]->TRx[MsgNr >> 5] & (1 << (MsgNr & 0x1F)))\r
848         {\r
849                 return CAN_BUSY;\r
850         }\r
851 \r
852     CurPduArrayPtr   = ControllerConfig[ControllerId].PduPtr    + (MsgNr - 1);\r
853     CurCancelRqstPtr = ControllerConfig[ControllerId].CancelPtr + (MsgNr - 1);\r
854     CurTxRqstPtr     = ControllerConfig[ControllerId].TxPtr     + (MsgNr - 1);\r
855     \r
856     /* Bring Id Value to appropriate format and set ArbRegValue */\r
857     if( hoh->CanIdType == CAN_ID_TYPE_EXTENDED ) {\r
858         /* MsgVal, Ext, Transmit, Extended Id */ \r
859         ArbRegValue = 0xE0000000 | (PduInfo->id & 0x1FFFFFFF);\r
860     } else {\r
861         /* MsgVal, Std, Transmit, Standard Id */ \r
862         ArbRegValue = 0xA0000000 | ((PduInfo->id & 0x7FF) << 18);\r
863     }\r
864 \r
865 \r
866     DCAN_WAIT_UNTIL_NOT_BUSY(ControllerId, IfRegId);\r
867 \r
868     // We cannot allow an interrupt or other task to play with the COM, MC and ARB registers here.\r
869     imask_t i_state = McuE_EnterCriticalSection();\r
870 \r
871 \r
872     /* Set NewDat, TxIE (dep on ControllerConfig), TxRqst, EoB and DLC */\r
873     CanRegs[ControllerId]->IFx[IfRegId].MC =      0x00000100 // Tx request\r
874                                                                                         | 0x00000080 // Eob should be set to one for tx\r
875                                                                                         | (0x000F & PduInfo->length) // Set DLC\r
876                                                                                         | (CanControllerConfigData[ControllerId].CanTxProcessing << 1); // Tx confirmation interrupt enabled\r
877 \r
878 \r
879     /* Set ArbitrationRegister */\r
880     CanRegs[ControllerId]->IFx[IfRegId].ARB = ArbRegValue;\r
881 \r
882     /* Set Databytes */\r
883     for(DataByteIndex = 0; DataByteIndex < PduInfo->length; DataByteIndex++)\r
884     {\r
885         CanRegs[ControllerId]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]] = *CurSduPtr++;\r
886     }\r
887 \r
888     /* Start transmission to MessageRAM */\r
889     CanRegs[ControllerId]->IFx[IfRegId].COM = 0x00BF0000 | MsgNr;\r
890     \r
891     /* Save the PduInfo in PduArray, so that messages can be identified later */\r
892     *CurPduArrayPtr = *PduInfo;\r
893     /* TxRqstArray-Elements are used to identifiy transmitted objects in polling mode */\r
894     *CurTxRqstPtr   = 1;\r
895     \r
896     IfRegId ^= 1;\r
897        \r
898     McuE_ExitCriticalSection(i_state);\r
899     return CAN_OK;\r
900 }\r
901 \r
902 \r
903 void Can_MainFunction_Write()\r
904 {\r
905         // Not supported\r
906 }\r
907 \r
908 void Can_MainFunction_Read()\r
909 {\r
910         // Not supported\r
911 }\r
912 \r
913 void Can_MainFunction_BusOff()\r
914 {\r
915   // Not supported\r
916 }\r
917 \r
918 void Can_MainFunction_Wakeup()\r
919 {\r
920    // Not supported\r
921 }\r
922 \r
923 \r