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