1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
18 #include "core_cr4.h"
\r
19 #if defined(USE_DEM)
\r
23 #include "CanIf_Cbk.h"
\r
28 #define DCAN1_MAX_MESSAGEBOXES 64
\r
29 #define DCAN2_MAX_MESSAGEBOXES 64
\r
30 #define DCAN3_MAX_MESSAGEBOXES 32
\r
32 #define CAN_TIMEOUT_DURATION 0xFFFFFFFF
\r
33 #define CAN_INSTANCE 0
\r
35 #define DCAN_IRQ_MASK 0x00000006
\r
38 #if !defined(USE_DEM)
\r
39 // If compiled without the DEM, calls to DEM are simply ignored.
\r
40 #define Dem_ReportErrorStatus(...)
\r
43 /* Macro for waiting until busy flag is 0 */
\r
44 #define DCAN_WAIT_UNTIL_NOT_BUSY(ControllerId, IfRegId) \
\r
46 uint32 ErrCounter = CAN_TIMEOUT_DURATION; \
\r
47 while(CanRegs[ControllerId]->IFx[IfRegId].COM & 0x00008000) { \
\r
49 if(ErrCounter == 0) { \
\r
50 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED); \
\r
51 ErrCounter = CAN_TIMEOUT_DURATION; \
\r
52 return CAN_NOT_OK; \
\r
57 /* Macro for waiting until busy flag is 0 */
\r
58 #define DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(ControllerId, IfRegId) \
\r
60 uint32 ErrCounter = CAN_TIMEOUT_DURATION; \
\r
61 while(CanRegs[ControllerId]->IFx[IfRegId].COM & 0x00008000) { \
\r
63 if(ErrCounter == 0) { \
\r
64 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED); \
\r
65 ErrCounter = CAN_TIMEOUT_DURATION; \
\r
73 // Array for easy access to DCAN register definitions.
\r
74 static Can_RegisterType* CanRegs[]=
\r
92 Can_PduType *PduPtr;
\r
95 } Controller_PreConfigType;
\r
98 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
99 /* Module is in uninitialized state */
\r
100 static Can_StateType ModuleState = CAN_UNINIT;
\r
103 static CanIf_ControllerModeType ControllerMode[CAN_ARC_CTRL_CONFIG_CNT];
\r
105 /* Used to switch between IF1 and IF2 of DCAN */
\r
106 static uint8 IfRegId = 0;
\r
108 /* Used to order Data Bytes according to hardware registers in DCAN */
\r
109 static const uint8 ElementIndex[] = {3, 2, 1, 0, 7, 6, 5, 4};
\r
111 /* To save pointer to the configuration set */
\r
112 static const Can_ConfigType *CurConfig;
\r
114 /* To save the PduData of transmission objects */
\r
115 static Can_PduType PduInfoArray_1[DCAN1_MAX_MESSAGEBOXES];
\r
116 /* To save pending Cancel Requests of transmission objects */
\r
117 static uint8 CancelRqstArray_1[DCAN1_MAX_MESSAGEBOXES];
\r
118 /* To save pending Transmit Requests of transmission objects */
\r
119 static uint8 TxRqstArray_1[DCAN1_MAX_MESSAGEBOXES];
\r
121 static Can_PduType PduInfoArray_2[DCAN2_MAX_MESSAGEBOXES];
\r
122 static uint8 CancelRqstArray_2[DCAN2_MAX_MESSAGEBOXES];
\r
123 static uint8 TxRqstArray_2[DCAN2_MAX_MESSAGEBOXES];
\r
125 static Can_PduType PduInfoArray_3[DCAN3_MAX_MESSAGEBOXES];
\r
126 static uint8 CancelRqstArray_3[DCAN3_MAX_MESSAGEBOXES];
\r
127 static uint8 TxRqstArray_3[DCAN3_MAX_MESSAGEBOXES];
\r
130 /* Holds the Controller specific configuration */
\r
131 static Controller_PreConfigType ControllerConfig[] =
\r
134 .MaxBoxes = DCAN1_MAX_MESSAGEBOXES,
\r
136 .PduPtr = PduInfoArray_1,
\r
137 .CancelPtr = CancelRqstArray_1,
\r
138 .TxPtr = TxRqstArray_1
\r
141 .MaxBoxes = DCAN2_MAX_MESSAGEBOXES,
\r
143 .PduPtr = PduInfoArray_2,
\r
144 .CancelPtr = CancelRqstArray_2,
\r
145 .TxPtr = TxRqstArray_2
\r
148 .MaxBoxes = DCAN3_MAX_MESSAGEBOXES,
\r
150 .PduPtr = PduInfoArray_3,
\r
151 .CancelPtr = CancelRqstArray_3,
\r
152 .TxPtr = TxRqstArray_3
\r
157 /* Shadow Buffer is used for buffering of received data */
\r
158 static uint8 RxShadowBuf[CAN_ARC_CTRL_CONFIG_CNT][8];
\r
160 /* Driver must know how often Can_DisableControllerInterrupts() has been called */
\r
161 static uint32 IntDisableCount[CAN_ARC_CTRL_CONFIG_CNT];
\r
164 static inline const Can_HardwareObjectType * Can_FindTxHoh(Can_Arc_HTHType hth) {
\r
165 for (int i = 0; i < CAN_ARC_CTRL_CONFIG_CNT; i++) {
\r
166 const Can_HardwareObjectType * hoh = CanControllerConfigData[i].Can_Arc_Hoh;
\r
170 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {
\r
173 } while (!hoh->Can_Arc_EOL);
\r
178 static inline uint8 Can_FindControllerId(Can_Arc_HTHType hth) {
\r
179 for (int i = 0; i < CAN_ARC_CTRL_CONFIG_CNT; i++) {
\r
180 const Can_HardwareObjectType * hoh = CanControllerConfigData[i].Can_Arc_Hoh;
\r
184 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {
\r
187 } while (!hoh->Can_Arc_EOL);
\r
192 static inline const Can_HardwareObjectType * Can_FindRxHoh(CanControllerIdType Controller, uint8 msgNr) {
\r
193 const Can_HardwareObjectType * hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;
\r
197 if (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE
\r
198 && (hoh->Can_Arc_MbMask & (1 << (msgNr - 1))) ) {
\r
201 } while (!hoh->Can_Arc_EOL);
\r
205 uint32 usedBoxes[64] = {0};
\r
207 void Can_InterruptHandler(CanControllerIdType controller)
\r
212 uint8 DataByteIndex;
\r
215 Can_DisableControllerInterrupts(controller);
\r
217 uint32 ir = CanRegs[controller]->IR;
\r
221 uint32 sr = CanRegs[controller]->SR;
\r
222 /* WakeUp Pending */
\r
223 if(sr & 0x00000200) {
\r
224 /* Set Init Bit, so that Controller is in Stop state */
\r
225 CanRegs[controller]->CTL |= 0x1;
\r
226 // EcuM_CheckWakeUp(ControllerConfig[0].WakeupSrc);
\r
230 if(sr & 0x00000080) {
\r
231 Can_SetControllerMode(controller, CAN_T_STOP); // CANIF272
\r
232 //CanIf_ControllerBusOff(0); // Not implemented in Arctic Core
\r
242 usedBoxes[MsgNr]++;
\r
244 usedBoxes[MsgNr]++;
\r
248 /* Read Arbitration, Control and Data Bits and clear IntPnd and NewDat*/
\r
249 CanRegs[controller]->IFx[IfRegId].COM = 0x003F0000 | MsgNr;
\r
251 /* Wait until Busy Flag is 0 */
\r
252 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(controller, IfRegId);
\r
254 /* Transmit Object */
\r
255 if(CanRegs[controller]->IFx[IfRegId].ARB & 0x20000000)
\r
257 /* Reset TxRqst-Array Element */
\r
258 ControllerConfig[controller].TxPtr[MsgNr - 1] = 0;
\r
259 /* A Message was successfully transmitted */
\r
260 CanIf_TxConfirmation(ControllerConfig[controller].PduPtr[MsgNr - 1].swPduHandle);
\r
262 /* Receive Object */
\r
266 if(CanRegs[controller]->IFx[IfRegId].ARB & 0x40000000)
\r
268 /* Bring Id to standardized format (MSB marks extended Id) */
\r
269 MsgId = (CanRegs[controller]->IFx[IfRegId].ARB & 0x1FFFFFFF) | 0x80000000;
\r
274 /* Bring Id to standardized format (MSB marks extended Id) */
\r
275 MsgId = (CanRegs[controller]->IFx[IfRegId].ARB & 0x1FFC0000) >> 18;
\r
278 MsgDlc = CanRegs[controller]->IFx[IfRegId].MC & 0x000F;
\r
283 /* Let SduPtr point to Shadow Buffer */
\r
284 SduPtr = RxShadowBuf[controller];
\r
286 /* Copy Message Data to Shadow Buffer */
\r
287 for(DataByteIndex = 0; DataByteIndex < MsgDlc; DataByteIndex++)
\r
289 SduPtr[DataByteIndex] = CanRegs[controller]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]];
\r
291 /* Indicate successful Reception */
\r
292 const Can_HardwareObjectType *hoh = Can_FindRxHoh(controller, MsgNr);
\r
293 CanIf_RxIndication(hoh->CanObjectId, MsgId, MsgDlc, SduPtr);
\r
297 Can_EnableControllerInterrupts(controller);
\r
300 void Can1_InterruptHandler() {
\r
301 Can_InterruptHandler(DCAN1);
\r
304 void Can2_InterruptHandler() {
\r
305 Can_InterruptHandler(DCAN2);
\r
308 void Can3_InterruptHandler() {
\r
309 Can_InterruptHandler(DCAN3);
\r
312 uint32 Can_CalculateBTR(uint8 Controller) {
\r
314 uint32 clock = McuE_GetPeripheralClock(PERIPHERAL_CLOCK_CAN);
\r
315 uint32 tq1 = CanControllerConfigData[Controller].CanControllerPropSeg + CanControllerConfigData[Controller].CanControllerSeg1;
\r
316 uint32 tq2 = CanControllerConfigData[Controller].CanControllerSeg2;
\r
317 uint32 ntq = tq1 + tq2 + 1 + 1 + 1;
\r
318 uint32 brp = clock / (CanControllerConfigData[Controller].CanControllerBaudRate * 1000 * ntq) - 1;
\r
320 uint32 retVal = (brp | (tq1 << 8) | (tq2 << 12));
\r
325 void Can_Init(const Can_ConfigType *Config)
\r
332 /* DET Error Check */
\r
333 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
334 if(ModuleState != CAN_UNINIT)
\r
336 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_TRANSITION);
\r
341 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_PARAM_POINTER);
\r
346 // TODO This should be used instead of other variables in the Can_Lcfg file.
\r
347 CurConfig = Config;
\r
349 for(Controller = 0; Controller < CAN_ARC_CTRL_CONFIG_CNT; Controller++)
\r
351 ErrCounter = CAN_TIMEOUT_DURATION;
\r
353 /* Init, IE, AutomaticRetransmission, ConfChangeEnable, ABO Off,Parity On, SIE and EIE depending on ControllerConfig, loopback */
\r
354 #if(CAN_WAKEUP_SUPPORT == STD_ON)
\r
355 CanRegs[Controller]->CTL = 0x02001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);
\r
357 CanRegs[Controller]->CTL = 0x00001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);
\r
359 /* LEC 7, TxOk, RxOk, PER */
\r
360 CanRegs[Controller]->SR = 0x0000011F;
\r
362 /* Test Mode only for Development time: Silent Loopback */
\r
363 if (CanControllerConfigData[Controller].Can_Arc_Loopback) {
\r
364 CanRegs[Controller]->TR = 0x00000018;
\r
368 // Basic message object initialization
\r
369 for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MaxBoxes; MsgNr++) {
\r
370 /* Initialize the Arrays for Transmit and Cancellation handling */
\r
371 *(ControllerConfig[Controller].CancelPtr + MsgNr) = 0;
\r
372 *(ControllerConfig[Controller].TxPtr + MsgNr) = 0;
\r
374 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\r
376 // Initialize all message objects for this controller to invalid state.
\r
378 CanRegs[Controller]->IFx[IfRegId].ARB = 0x00000000;
\r
379 /* Start writing Arbitration Bits */
\r
380 CanRegs[Controller]->IFx[IfRegId].COM = 0x00A80000 | (MsgNr + 1);
\r
382 /* Use IFx[0] and IFx[1] alternating */
\r
387 /* Configure the HOHs for this controller. */
\r
388 const Can_HardwareObjectType* hoh;
\r
389 hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;
\r
393 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
395 uint32 nProcessedMb = 0;
\r
397 // For every message object in this hoh
\r
398 for(; mbMask != 0; mbMask >>= 1) {
\r
400 if (!(mbMask & 1)) {
\r
401 // This message object is not part of this hoh.
\r
406 // Check if this is the last message box for this hoh.
\r
407 if((mbMask != 1) &&
\r
408 (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)) {
\r
409 /* EndOfBlock Bit will not be set */
\r
414 /* EndOfBlock Bit will be set */
\r
418 /* DLC=8, Use Mask only for receive, Set RxIE/TxIE depending on pre-config settings, Eob */
\r
419 CanRegs[Controller]->IFx[IfRegId].MC = 0x00000008 // DLC = 8
\r
420 | 0x00001000 // umask = ON
\r
421 | CanControllerConfigData[Controller].CanRxProcessing // Rx interrupt enabled
\r
422 | (CanControllerConfigData[Controller].CanTxProcessing << 1) // Tx confirmation interrupt enabled
\r
423 | (Eob & ~(hoh->CanObjectType >> 22)); // Eob, only for Rx.
\r
425 //CanRegs[Controller]->IFx[IfRegId].MC = 0x00001008 | CanControllerConfigData[Controller].CanRxProcessing | (CanControllerConfigData[Controller].CanTxProcessing) | Eob & ~(hoh->CanObjectType >> 17);
\r
427 if(hoh->CanIdType == CAN_ID_TYPE_STANDARD) /* Standard Identifiers */
\r
429 /* Only Standard-Ids are accepted, Set Mask */
\r
430 CanRegs[Controller]->IFx[IfRegId].MASK = 0x80000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF);
\r
431 /* Message valid, Id, Direction */
\r
432 CanRegs[Controller]->IFx[IfRegId].ARB = 0x80000000 | ((hoh->CanIdValue & 0x7FF) << 18) | hoh->CanObjectType;
\r
434 else if(hoh->CanIdType == CAN_ID_TYPE_EXTENDED) /* Extended Identifiers */
\r
436 /* Only Extended-Ids are accepted, Set Mask */
\r
437 CanRegs[Controller]->IFx[IfRegId].MASK = 0x80000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF);
\r
438 /* Message valid, Id, Direction */
\r
439 CanRegs[Controller]->IFx[IfRegId].ARB = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFFF) | hoh->CanObjectType;
\r
441 else /* Mixed Identifiers */
\r
443 /* Standard- and Mixed-Ids are accepted, Set Mask */
\r
444 CanRegs[Controller]->IFx[IfRegId].MASK = 0x00000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFF);
\r
445 /* Message valid, Id, Direction */
\r
446 CanRegs[Controller]->IFx[IfRegId].ARB = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFF) | hoh->CanObjectType;
\r
448 /* Start writing Mask, Arb, Control and Id bits */
\r
449 CanRegs[Controller]->IFx[IfRegId].COM = 0x00F80000 | mbNr;
\r
451 /* Use IFx[0] and IFx[1] alternating */
\r
455 } while (!hoh->Can_Arc_EOL);
\r
458 /* Set Bit Timing Register */
\r
459 CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);
\r
461 /* Reset CCE Bit */
\r
462 CanRegs[Controller]->CTL &= ~0x00000040;
\r
464 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
465 /* Switch Controller State to CANIF_CS_STOPPED */
\r
466 ControllerMode[Controller] = CANIF_CS_STOPPED;
\r
469 // Install interrupt handlers
\r
471 if (CanControllerConfigData[Controller].CanControllerId == DCAN1) {
\r
472 tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2 ,"DCAN1Level0");
\r
473 Irq_AttachIsr2(tid, NULL, 16);
\r
475 tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2, "DCAN1Level1");
\r
476 Irq_AttachIsr2(tid, NULL, 29);
\r
478 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN2) {
\r
479 tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2 ,"DCAN2Level0");
\r
480 Irq_AttachIsr2(tid, NULL, 35);
\r
482 tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2, "DCAN2Level1");
\r
483 Irq_AttachIsr2(tid, NULL, 42);
\r
485 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN3) {
\r
486 tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2 ,"DCAN3Level0");
\r
487 Irq_AttachIsr2(tid, NULL, 45);
\r
489 tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2, "DCAN3Level1");
\r
490 Irq_AttachIsr2(tid, NULL, 55);
\r
495 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
496 /* Switch Module State to CAN_READY */
\r
497 ModuleState = CAN_READY;
\r
506 void Can_InitController(uint8 Controller, const Can_ControllerConfigType* Config)
\r
511 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
514 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_POINTER);
\r
517 if(ModuleState == CAN_UNINIT)
\r
519 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_UNINIT);
\r
522 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
524 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_CONTROLLER);
\r
527 if(ControllerMode[Controller] != CANIF_CS_STOPPED)
\r
529 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_TRANSITION);
\r
534 ErrCounter = CAN_TIMEOUT_DURATION;
\r
536 //for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MessageBoxCount; MsgNr++)
\r
537 const Can_HardwareObjectType* hoh;
\r
538 hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;
\r
539 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
540 uint32 nProcessedMb = 0;
\r
543 // For every message object in this hoh
\r
544 for(; mbMask != 0; mbMask >>= 1) {
\r
546 if (!(mbMask & 1)) {
\r
547 // This message object is not part of this hoh.
\r
552 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\r
554 /* Read actual MaskRegister value of MessageObject */
\r
555 CanRegs[Controller]->IFx[IfRegId].COM = 0x004C0000 | (MsgNr);
\r
557 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\r
559 CanRegs[Controller]->IFx[IfRegId].MASK &= 0xD0000000;
\r
561 CanRegs[Controller]->IFx[IfRegId].MASK |= (*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF;
\r
562 /* Write new Mask to MaskRegister */
\r
563 CanRegs[Controller]->IFx[IfRegId].COM = 0x00C80000 | (MsgNr);
\r
568 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\r
570 /* Set CCE Bit to allow access to BitTiming Register (Init already set, in mode "stopped") */
\r
571 CanRegs[Controller]->CTL |= 0x00000040;
\r
572 /* Set Bit Timing Register */
\r
573 CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);
\r
574 /* Clear CCE Bit */
\r
575 CanRegs[Controller]->CTL &= ~0x00000040;
\r
580 Can_ReturnType Can_SetControllerMode(uint8 Controller, Can_StateTransitionType Transition)
\r
582 Can_ReturnType Status = CAN_OK;
\r
583 uint32 ErrCounter = CAN_TIMEOUT_DURATION;
\r
586 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
587 if(ModuleState == CAN_UNINIT)
\r
589 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_UNINIT);
\r
592 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
594 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_PARAM_CONTROLLER);
\r
597 if(((Transition == CAN_T_START ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||
\r
598 ((Transition == CAN_T_STOP ) && (ControllerMode[Controller] != CANIF_CS_STARTED)) ||
\r
599 ((Transition == CAN_T_SLEEP ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||
\r
600 ((Transition == CAN_T_WAKEUP) && (ControllerMode[Controller] != CANIF_CS_SLEEP )))
\r
602 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);
\r
610 /* Clear Init Bit */
\r
611 CanRegs[Controller]->CTL &= ~0x00000001;
\r
612 /* Clear Status Register */
\r
613 CanRegs[Controller]->SR = 0x0000011F;
\r
615 ControllerMode[Controller] = CANIF_CS_STARTED;
\r
616 Can_EnableControllerInterrupts(Controller);
\r
621 CanRegs[Controller]->CTL |= 0x00000001;
\r
622 ControllerMode[Controller] = CANIF_CS_STOPPED;
\r
623 Can_DisableControllerInterrupts(Controller);
\r
628 CanRegs[Controller]->CTL |= 0x01000000;
\r
629 /* Save actual Register status */
\r
630 RegBuf = CanRegs[Controller]->CTL;
\r
631 /* Disable Status Interrupts and WUBA */
\r
632 CanRegs[Controller]->CTL &= ~0x02000004;
\r
633 /* Wait until Local Power Down Mode acknowledged */
\r
634 while(!(CanRegs[Controller]->SR & 0x00000400))
\r
636 /* Check if a WakeUp occurs */
\r
637 if(CanRegs[Controller]->SR & 0x00000200)
\r
639 Status = CAN_NOT_OK;
\r
643 if(ErrCounter == 0)
\r
645 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
646 ErrCounter = CAN_TIMEOUT_DURATION;
\r
647 Status = CAN_NOT_OK;
\r
651 /* Reset Control Register */
\r
652 CanRegs[Controller]->CTL = RegBuf;
\r
653 ControllerMode[Controller] = CANIF_CS_SLEEP;
\r
657 /* Clear PDR Bit */
\r
658 CanRegs[Controller]->CTL &= ~0x01000000;
\r
659 ControllerMode[Controller] = CANIF_CS_STOPPED;
\r
663 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
664 /* Invalid Transition */
\r
665 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);
\r
675 void Can_DisableControllerInterrupts(uint8 Controller)
\r
677 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
678 if(ModuleState == CAN_UNINIT)
\r
680 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_UNINIT);
\r
683 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
685 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_PARAM_CONTROLLER);
\r
690 CanRegs[Controller]->CTL &= ~DCAN_IRQ_MASK;
\r
691 /* Increment Disable Counter */
\r
692 IntDisableCount[Controller]++;
\r
695 void Can_EnableControllerInterrupts(uint8 Controller)
\r
697 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
698 if(ModuleState == CAN_UNINIT)
\r
700 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_UNINIT);
\r
703 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
705 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_PARAM_CONTROLLER);
\r
709 if(IntDisableCount[Controller] > 0)
\r
711 if(IntDisableCount[Controller] == 1)
\r
714 CanRegs[Controller]->CTL |= DCAN_IRQ_MASK;
\r
716 IntDisableCount[Controller]--;
\r
721 void Can_Cbk_CheckWakeup(uint8 Controller)
\r
723 /* TODO not supported yet.
\r
724 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
725 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
727 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0x0B, CAN_E_PARAM_CONTROLLER);
\r
731 // Check WakeUpPending
\r
732 if(CanRegs[Controller]->SR & 0x00000200)
\r
744 Can_ReturnType Can_Write(Can_Arc_HTHType Hth, Can_PduType *PduInfo)
\r
746 uint8 ControllerId;
\r
748 uint32 ArbRegValue;
\r
749 uint8 DataByteIndex;
\r
751 Can_PduType *CurPduArrayPtr;
\r
752 uint8 *CurCancelRqstPtr;
\r
753 uint8 *CurTxRqstPtr;
\r
755 CurSduPtr = PduInfo->sdu;
\r
758 /* DET Error Check */
\r
759 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
760 if(PduInfo == NULL || PduInfo->sdu == NULL)
\r
762 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_POINTER);
\r
765 if(ModuleState == CAN_UNINIT)
\r
767 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_UNINIT);
\r
770 if(PduInfo->length > 8)
\r
772 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_DLC);
\r
773 return CAN_NOT_OK;
\r
777 ControllerId = Can_FindControllerId(Hth);
\r
779 const Can_HardwareObjectType *hoh = Can_FindTxHoh(Hth);
\r
781 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
782 if(hoh->CanObjectType != CAN_OBJECT_TYPE_TRANSMIT)
\r
784 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_HANDLE);
\r
788 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
790 for(; mbMask != 0; mbMask >>= 1) {
\r
792 if (!(mbMask & 1)) {
\r
793 continue; // This message object is not part of this hoh.
\r
797 CurPduArrayPtr = ControllerConfig[ControllerId].PduPtr + (MsgNr - 1);
\r
798 CurCancelRqstPtr = ControllerConfig[ControllerId].CancelPtr + (MsgNr - 1);
\r
799 CurTxRqstPtr = ControllerConfig[ControllerId].TxPtr + (MsgNr - 1);
\r
801 /* Bring Id Value to appropriate format and set ArbRegValue */
\r
802 if(PduInfo->id & 0x80000000)
\r
804 /* MsgVal, Ext, Transmit, Extended Id */
\r
805 ArbRegValue = 0xD0000000 | (PduInfo->id & 0x1FFFFFFF);
\r
809 /* MsgVal, Std, Transmit, Standard Id */
\r
810 ArbRegValue = 0xA0000000 | ((PduInfo->id & 0x7FF) << 18);
\r
813 /* Check if TxRqst Bit of MsgObject is set */
\r
814 if(CanRegs[ControllerId]->TRx[MsgNr >> 5] & (1 << (MsgNr & 0x1F)))
\r
819 DCAN_WAIT_UNTIL_NOT_BUSY(ControllerId, IfRegId);
\r
822 /* Set NewDat, TxIE (dep on ControllerConfig), TxRqst, EoB and DLC */
\r
823 CanRegs[ControllerId]->IFx[IfRegId].MC = 0x00000100 // Tx request
\r
824 | 0x00000080 // Eob should be set to one for tx
\r
825 | (0x000F & PduInfo->length) // Set DLC
\r
826 | CanControllerConfigData[ControllerId].CanRxProcessing
\r
827 | (CanControllerConfigData[ControllerId].CanTxProcessing << 1); // Tx confirmation interrupt enabled
\r
830 /* Set ArbitrationRegister */
\r
831 CanRegs[ControllerId]->IFx[IfRegId].ARB = ArbRegValue;
\r
833 /* Set Databytes */
\r
834 for(DataByteIndex = 0; DataByteIndex < PduInfo->length; DataByteIndex++)
\r
836 CanRegs[ControllerId]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]] = *CurSduPtr++;
\r
839 /* Start transmission to MessageRAM */
\r
840 CanRegs[ControllerId]->IFx[IfRegId].COM = 0x00BF0000 | MsgNr;
\r
842 /* Save the PduInfo in PduArray, so that messages can be identified later */
\r
843 *CurPduArrayPtr = *PduInfo;
\r
844 /* TxRqstArray-Elements are used to identifiy transmitted objects in polling mode */
\r
853 void Can_MainFunction_Write()
\r
858 void Can_MainFunction_Read()
\r
863 void Can_MainFunction_BusOff()
\r
868 void Can_MainFunction_Wakeup()
\r