]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cr4/drivers/Can.c
Merge with cortex-r4 branch
[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 #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_NO_RV(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                 TaskType tid;\r
521                 if (CanControllerConfigData[Controller].CanControllerId == DCAN1) {\r
522                         tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2 ,"DCAN1Level0");\r
523                         Irq_AttachIsr2(tid, NULL, 16);\r
524 \r
525                         tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2, "DCAN1Level1");\r
526                         Irq_AttachIsr2(tid, NULL, 29);\r
527 \r
528                 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN2) {\r
529                         tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2 ,"DCAN2Level0");\r
530                         Irq_AttachIsr2(tid, NULL, 35);\r
531 \r
532                         tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2, "DCAN2Level1");\r
533                         Irq_AttachIsr2(tid, NULL, 42);\r
534 \r
535                 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN3) {\r
536                         tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2 ,"DCAN3Level0");\r
537                         Irq_AttachIsr2(tid, NULL, 45);\r
538 \r
539                         tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2, "DCAN3Level1");\r
540                         Irq_AttachIsr2(tid, NULL, 55);\r
541 \r
542                 }\r
543 \r
544     }\r
545 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
546     /* Switch Module State to CAN_READY */\r
547     ModuleState = CAN_READY;\r
548 #endif\r
549 \r
550     McuE_ExitCriticalSection(i_state);\r
551 \r
552 }\r
553 \r
554 \r
555 \r
556 void Can_InitController(uint8 Controller, const Can_ControllerConfigType* Config)\r
557 {\r
558     uint8   MsgNr;\r
559     uint32  ErrCounter;\r
560 \r
561 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
562     if(Config == NULL)\r
563     {\r
564         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_POINTER);\r
565         return;\r
566     }\r
567     if(ModuleState == CAN_UNINIT)\r
568     {\r
569         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_UNINIT);\r
570         return;\r
571     }\r
572     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
573     {\r
574         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_CONTROLLER);\r
575         return;\r
576     }\r
577     if(ControllerMode[Controller] != CANIF_CS_STOPPED)\r
578     {\r
579         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_TRANSITION);\r
580         return;\r
581     }\r
582 #endif \r
583 \r
584     imask_t i_state = McuE_EnterCriticalSection();\r
585 \r
586     ErrCounter = CAN_TIMEOUT_DURATION;\r
587     \r
588     //for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MessageBoxCount; MsgNr++)\r
589         const Can_HardwareObjectType* hoh;\r
590         hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;\r
591         uint64 mbMask = hoh->Can_Arc_MbMask;\r
592         uint32 nProcessedMb = 0;\r
593         MsgNr = 0;\r
594 \r
595         // For every message object in this hoh\r
596         for(; mbMask != 0; mbMask >>= 1) {\r
597                 MsgNr++;\r
598                 if (!(mbMask & 1)) {\r
599                         // This message object is not part of this hoh.\r
600                         continue;\r
601                 }\r
602                 nProcessedMb++;\r
603 \r
604                 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);\r
605 \r
606                 /* Read actual MaskRegister value of MessageObject */\r
607         CanRegs[Controller]->IFx[IfRegId].COM = 0x004C0000 | (MsgNr);\r
608 \r
609         DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);\r
610 \r
611         CanRegs[Controller]->IFx[IfRegId].MASK &= 0xD0000000;\r
612         /* Set new Mask */\r
613         CanRegs[Controller]->IFx[IfRegId].MASK |= (*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF;\r
614         /* Write new Mask to MaskRegister */\r
615         CanRegs[Controller]->IFx[IfRegId].COM   = 0x00C80000 | (MsgNr);\r
616 \r
617         IfRegId ^= 1;\r
618     }\r
619 \r
620         DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);\r
621 \r
622     /* Set CCE Bit to allow access to BitTiming Register (Init already set, in mode "stopped") */\r
623     CanRegs[Controller]->CTL |= 0x00000040;\r
624     /* Set Bit Timing Register */\r
625     CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);\r
626     /* Clear CCE Bit */\r
627     CanRegs[Controller]->CTL &= ~0x00000040;\r
628 \r
629     McuE_ExitCriticalSection(i_state);\r
630 }\r
631 \r
632 \r
633 Can_ReturnType Can_SetControllerMode(uint8 Controller, Can_StateTransitionType Transition)\r
634 {\r
635     Can_ReturnType Status     = CAN_OK;\r
636     uint32         ErrCounter = CAN_TIMEOUT_DURATION;\r
637     uint32         RegBuf;\r
638     \r
639 #if(CAN_DEV_ERROR_DETECT == STD_ON)    \r
640     if(ModuleState == CAN_UNINIT)\r
641     {\r
642         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_UNINIT);\r
643         return CAN_NOT_OK;\r
644     }\r
645     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
646     {\r
647         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_PARAM_CONTROLLER);\r
648         return CAN_NOT_OK;\r
649     }\r
650     if(((Transition == CAN_T_START ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||\r
651        ((Transition == CAN_T_STOP  ) && (ControllerMode[Controller] != CANIF_CS_STARTED)) ||\r
652        ((Transition == CAN_T_SLEEP ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||\r
653        ((Transition == CAN_T_WAKEUP) && (ControllerMode[Controller] != CANIF_CS_SLEEP  )))\r
654     {\r
655         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);\r
656         return CAN_NOT_OK;\r
657     }\r
658 #endif \r
659 \r
660     switch(Transition)\r
661     {\r
662     case CAN_T_START:\r
663         /* Clear Init Bit */\r
664         CanRegs[Controller]->CTL  &= ~0x00000001;\r
665         /* Clear Status Register */\r
666         CanRegs[Controller]->SR    = 0x0000011F;\r
667 \r
668         ControllerMode[Controller] = CANIF_CS_STARTED;\r
669         Can_EnableControllerInterrupts(Controller);\r
670         break;\r
671 \r
672     case CAN_T_STOP:\r
673         /* Set Init Bit */\r
674         CanRegs[Controller]->CTL  |=  0x00000001;\r
675         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
676         Can_DisableControllerInterrupts(Controller);\r
677         break;\r
678 \r
679     case CAN_T_SLEEP:\r
680         /* Set PDR  Bit */\r
681         CanRegs[Controller]->CTL |=  0x01000000;\r
682         /* Save actual Register status */\r
683         RegBuf = CanRegs[Controller]->CTL;\r
684         /* Disable Status Interrupts and WUBA */\r
685         CanRegs[Controller]->CTL &= ~0x02000004;\r
686         /* Wait until Local Power Down Mode acknowledged */\r
687         while(!(CanRegs[Controller]->SR & 0x00000400))\r
688         {\r
689             /* Check if a WakeUp occurs */\r
690             if(CanRegs[Controller]->SR & 0x00000200)\r
691             {\r
692                 Status = CAN_NOT_OK;\r
693                 break;\r
694             }\r
695             ErrCounter--;\r
696             if(ErrCounter == 0)\r
697             {\r
698                 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
699                 ErrCounter = CAN_TIMEOUT_DURATION;\r
700                 Status     = CAN_NOT_OK;\r
701                 break;\r
702             }\r
703         }\r
704         /* Reset Control Register */\r
705         CanRegs[Controller]->CTL   = RegBuf;\r
706         ControllerMode[Controller] = CANIF_CS_SLEEP;\r
707         break;\r
708 \r
709     case CAN_T_WAKEUP:\r
710         /* Clear PDR Bit */\r
711         CanRegs[Controller]->CTL  &= ~0x01000000;\r
712         ControllerMode[Controller] = CANIF_CS_STOPPED;\r
713         break;\r
714 \r
715     default:\r
716 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
717         /* Invalid Transition */\r
718         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);\r
719         return CAN_NOT_OK;\r
720 #endif\r
721         break;\r
722     }\r
723 \r
724     return Status;\r
725 }\r
726 \r
727 \r
728 void Can_DisableControllerInterrupts(uint8 Controller)\r
729 {\r
730 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
731     if(ModuleState == CAN_UNINIT)\r
732     {\r
733         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_UNINIT);\r
734         return;\r
735     }\r
736     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
737     {\r
738         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_PARAM_CONTROLLER);\r
739         return;\r
740     }\r
741 #endif \r
742     /* Clear IE */\r
743     CanRegs[Controller]->CTL &= ~DCAN_IRQ_MASK;\r
744     /* Increment Disable Counter */\r
745     IntDisableCount[Controller]++;\r
746 }\r
747 \r
748 void Can_EnableControllerInterrupts(uint8 Controller)\r
749 {\r
750 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
751     if(ModuleState == CAN_UNINIT)\r
752     {\r
753         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_UNINIT);\r
754         return;\r
755     }\r
756     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
757     {\r
758         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_PARAM_CONTROLLER);\r
759         return;\r
760     }\r
761 #endif    \r
762     if(IntDisableCount[Controller] > 0)\r
763     {\r
764         if(IntDisableCount[Controller] == 1)\r
765         {\r
766             /* Set IE */\r
767             CanRegs[Controller]->CTL |= DCAN_IRQ_MASK;\r
768         }\r
769         IntDisableCount[Controller]--;\r
770     }\r
771 }\r
772 \r
773 \r
774 void Can_Cbk_CheckWakeup(uint8 Controller)\r
775 {\r
776         /* TODO not supported yet.\r
777 #if(CAN_DEV_ERROR_DETECT == STD_ON)\r
778     if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)\r
779     {\r
780         Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0x0B, CAN_E_PARAM_CONTROLLER);\r
781         return CAN_NOT_OK;\r
782     }\r
783 #endif\r
784     // Check WakeUpPending\r
785     if(CanRegs[Controller]->SR & 0x00000200)\r
786     {\r
787         return E_OK;\r
788     }\r
789     else\r
790     {\r
791         return E_NOT_OK;\r
792     }\r
793     */\r
794 }\r
795 \r
796 \r
797 Can_ReturnType Can_Write(Can_Arc_HTHType Hth, Can_PduType *PduInfo)\r
798 {\r
799     uint8                  ControllerId;\r
800     uint8                  MsgNr;\r
801     uint32                 ArbRegValue;\r
802     uint8                  DataByteIndex;\r
803     uint8                 *CurSduPtr;\r
804     Can_PduType           *CurPduArrayPtr;\r
805     uint8                 *CurCancelRqstPtr;\r
806     uint8                 *CurTxRqstPtr;\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     imask_t i_state = McuE_EnterCriticalSection();\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     McuE_ExitCriticalSection(i_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