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
44 // Array for easy access to DCAN register definitions.
\r
45 static Can_RegisterType* CanRegs[]=
\r
63 Can_PduType *PduPtr;
\r
66 } Controller_PreConfigType;
\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
74 static CanIf_ControllerModeType ControllerMode[CAN_ARC_CTRL_CONFIG_CNT];
\r
76 /* Used to switch between IF1 and IF2 of DCAN */
\r
77 static uint8 IfRegId = 0;
\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
82 /* To save pointer to the configuration set */
\r
83 static const Can_ConfigType *CurConfig;
\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
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
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
101 /* Holds the Controller specific configuration */
\r
102 static Controller_PreConfigType ControllerConfig[] =
\r
105 .MaxBoxes = DCAN1_MAX_MESSAGEBOXES,
\r
107 .PduPtr = PduInfoArray_1,
\r
108 .CancelPtr = CancelRqstArray_1,
\r
109 .TxPtr = TxRqstArray_1
\r
112 .MaxBoxes = DCAN2_MAX_MESSAGEBOXES,
\r
114 .PduPtr = PduInfoArray_2,
\r
115 .CancelPtr = CancelRqstArray_2,
\r
116 .TxPtr = TxRqstArray_2
\r
119 .MaxBoxes = DCAN3_MAX_MESSAGEBOXES,
\r
121 .PduPtr = PduInfoArray_3,
\r
122 .CancelPtr = CancelRqstArray_3,
\r
123 .TxPtr = TxRqstArray_3
\r
128 /* Shadow Buffer is used for buffering of received data */
\r
129 static uint8 RxShadowBuf[CAN_ARC_CTRL_CONFIG_CNT][8];
\r
131 /* Driver must know how often Can_DisableControllerInterrupts() has been called */
\r
132 static uint32 IntDisableCount[CAN_ARC_CTRL_CONFIG_CNT];
\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
141 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {
\r
144 } while (!hoh->Can_Arc_EOL);
\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
155 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {
\r
158 } while (!hoh->Can_Arc_EOL);
\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
168 if (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE
\r
169 && (hoh->Can_Arc_MbMask & (1 << (msgNr - 1))) ) {
\r
172 } while (!hoh->Can_Arc_EOL);
\r
176 uint32 usedBoxes[64] = {0};
\r
178 void Can_InterruptHandler(CanControllerIdType controller)
\r
184 uint8 DataByteIndex;
\r
187 Can_DisableControllerInterrupts(controller);
\r
189 ErrCounter = CAN_TIMEOUT_DURATION;
\r
191 uint32 ir = CanRegs[controller]->IR;
\r
195 uint32 sr = CanRegs[controller]->SR;
\r
196 /* WakeUp Pending */
\r
197 if(sr & 0x00000200) {
\r
198 /* Set Init Bit, so that Controller is in Stop state */
\r
199 CanRegs[controller]->CTL |= 0x1;
\r
200 // EcuM_CheckWakeUp(ControllerConfig[0].WakeupSrc);
\r
204 if(sr & 0x00000080) {
\r
205 Can_SetControllerMode(controller, CAN_T_STOP); // CANIF272
\r
206 //CanIf_ControllerBusOff(0); // Not implemented in Arctic Core
\r
216 usedBoxes[MsgNr]++;
\r
218 usedBoxes[MsgNr]++;
\r
222 /* Read Arbitration, Control and Data Bits and clear IntPnd and NewDat*/
\r
223 CanRegs[controller]->IFx[IfRegId].COM = 0x003F0000 | MsgNr;
\r
225 /* Wait until Busy Flag is 0 */
\r
226 while(CanRegs[controller]->IFx[IfRegId].COM & 0x8000)
\r
229 if(ErrCounter == 0)
\r
231 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
232 ErrCounter = CAN_TIMEOUT_DURATION;
\r
237 /* Transmit Object */
\r
238 if(CanRegs[controller]->IFx[IfRegId].ARB & 0x20000000)
\r
240 /* Reset TxRqst-Array Element */
\r
241 ControllerConfig[controller].TxPtr[MsgNr - 1] = 0;
\r
242 /* A Message was successfully transmitted */
\r
243 CanIf_TxConfirmation(ControllerConfig[controller].PduPtr[MsgNr - 1].swPduHandle);
\r
245 /* Receive Object */
\r
249 if(CanRegs[controller]->IFx[IfRegId].ARB & 0x40000000)
\r
251 /* Bring Id to standardized format (MSB marks extended Id) */
\r
252 MsgId = (CanRegs[controller]->IFx[IfRegId].ARB & 0x1FFFFFFF) | 0x80000000;
\r
257 /* Bring Id to standardized format (MSB marks extended Id) */
\r
258 MsgId = (CanRegs[controller]->IFx[IfRegId].ARB & 0x1FFC0000) >> 18;
\r
261 MsgDlc = CanRegs[controller]->IFx[IfRegId].MC & 0x000F;
\r
266 /* Let SduPtr point to Shadow Buffer */
\r
267 SduPtr = RxShadowBuf[controller];
\r
269 /* Copy Message Data to Shadow Buffer */
\r
270 for(DataByteIndex = 0; DataByteIndex < MsgDlc; DataByteIndex++)
\r
272 SduPtr[DataByteIndex] = CanRegs[controller]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]];
\r
274 /* Indicate successful Reception */
\r
275 const Can_HardwareObjectType *hoh = Can_FindRxHoh(controller, MsgNr);
\r
276 CanIf_RxIndication(hoh->CanObjectId, MsgId, MsgDlc, SduPtr);
\r
280 Can_EnableControllerInterrupts(controller);
\r
283 void Can1_InterruptHandler() {
\r
284 Can_InterruptHandler(DCAN1);
\r
287 void Can2_InterruptHandler() {
\r
288 Can_InterruptHandler(DCAN2);
\r
291 void Can3_InterruptHandler() {
\r
292 Can_InterruptHandler(DCAN3);
\r
295 uint32 Can_CalculateBTR(uint8 Controller) {
\r
297 uint32 clock = McuE_GetPeripheralClock(PERIPHERAL_CLOCK_CAN);
\r
298 uint32 tq1 = CanControllerConfigData[Controller].CanControllerPropSeg + CanControllerConfigData[Controller].CanControllerSeg1;
\r
299 uint32 tq2 = CanControllerConfigData[Controller].CanControllerSeg2;
\r
300 uint32 ntq = tq1 + tq2 + 1 + 1 + 1;
\r
301 uint32 brp = clock / (CanControllerConfigData[Controller].CanControllerBaudRate * 1000 * ntq) - 1;
\r
303 uint32 retVal = (brp | (tq1 << 8) | (tq2 << 12));
\r
308 void Can_Init(const Can_ConfigType *Config)
\r
315 /* DET Error Check */
\r
316 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
317 if(ModuleState != CAN_UNINIT)
\r
319 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_TRANSITION);
\r
324 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_PARAM_POINTER);
\r
329 // TODO This should be used instead of other variables in the Can_Lcfg file.
\r
330 CurConfig = Config;
\r
332 for(Controller = 0; Controller < CAN_ARC_CTRL_CONFIG_CNT; Controller++)
\r
334 ErrCounter = CAN_TIMEOUT_DURATION;
\r
336 /* Init, IE, AutomaticRetransmission, ConfChangeEnable, ABO Off,Parity On, SIE and EIE depending on ControllerConfig, loopback */
\r
337 #if(CAN_WAKEUP_SUPPORT == STD_ON)
\r
338 CanRegs[Controller]->CTL = 0x02001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);
\r
340 CanRegs[Controller]->CTL = 0x00001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);
\r
342 /* LEC 7, TxOk, RxOk, PER */
\r
343 CanRegs[Controller]->SR = 0x0000011F;
\r
345 /* Test Mode only for Development time: Silent Loopback */
\r
346 if (CanControllerConfigData[Controller].Can_Arc_Loopback) {
\r
347 CanRegs[Controller]->TR = 0x00000018;
\r
351 // Basic message object initialization
\r
352 for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MaxBoxes; MsgNr++) {
\r
353 /* Initialize the Arrays for Transmit and Cancellation handling */
\r
354 *(ControllerConfig[Controller].CancelPtr + MsgNr) = 0;
\r
355 *(ControllerConfig[Controller].TxPtr + MsgNr) = 0;
\r
357 /* Wait until Busy Flag is 0 */
\r
358 while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)
\r
361 if(ErrCounter == 0)
\r
363 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
364 ErrCounter = CAN_TIMEOUT_DURATION;
\r
369 // Initialize all message objects for this controller to invalid state.
\r
371 CanRegs[Controller]->IFx[IfRegId].ARB = 0x00000000;
\r
372 /* Start writing Arbitration Bits */
\r
373 CanRegs[Controller]->IFx[IfRegId].COM = 0x00A80000 | (MsgNr + 1);
\r
375 /* Use IFx[0] and IFx[1] alternating */
\r
380 /* Configure the HOHs for this controller. */
\r
381 const Can_HardwareObjectType* hoh;
\r
382 hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;
\r
386 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
388 uint32 nProcessedMb = 0;
\r
390 // For every message object in this hoh
\r
391 for(; mbMask != 0; mbMask >>= 1) {
\r
393 if (!(mbMask & 1)) {
\r
394 // This message object is not part of this hoh.
\r
399 // Check if this is the last message box for this hoh.
\r
400 if((mbMask != 1) &&
\r
401 (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)) {
\r
402 /* EndOfBlock Bit will not be set */
\r
407 /* EndOfBlock Bit will be set */
\r
411 /* DLC=8, Use Mask only for receive, Set RxIE/TxIE depending on pre-config settings, Eob */
\r
412 CanRegs[Controller]->IFx[IfRegId].MC = 0x00000008 // DLC = 8
\r
413 | 0x00001000 // umask = ON
\r
414 | CanControllerConfigData[Controller].CanRxProcessing // Rx interrupt enabled
\r
415 | (CanControllerConfigData[Controller].CanTxProcessing << 1) // Tx confirmation interrupt enabled
\r
416 | (Eob & ~(hoh->CanObjectType >> 22)); // Eob, only for Rx.
\r
418 //CanRegs[Controller]->IFx[IfRegId].MC = 0x00001008 | CanControllerConfigData[Controller].CanRxProcessing | (CanControllerConfigData[Controller].CanTxProcessing) | Eob & ~(hoh->CanObjectType >> 17);
\r
420 if(hoh->CanIdType == CAN_ID_TYPE_STANDARD) /* Standard Identifiers */
\r
422 /* Only Standard-Ids are accepted, Set Mask */
\r
423 CanRegs[Controller]->IFx[IfRegId].MASK = 0x80000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF);
\r
424 /* Message valid, Id, Direction */
\r
425 CanRegs[Controller]->IFx[IfRegId].ARB = 0x80000000 | ((hoh->CanIdValue & 0x7FF) << 18) | hoh->CanObjectType;
\r
427 else if(hoh->CanIdType == CAN_ID_TYPE_EXTENDED) /* Extended Identifiers */
\r
429 /* Only Extended-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 = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFFF) | hoh->CanObjectType;
\r
434 else /* Mixed Identifiers */
\r
436 /* Standard- and Mixed-Ids are accepted, Set Mask */
\r
437 CanRegs[Controller]->IFx[IfRegId].MASK = 0x00000000 | ((*(hoh->CanFilterMaskRef)) & 0x1FFFFFF);
\r
438 /* Message valid, Id, Direction */
\r
439 CanRegs[Controller]->IFx[IfRegId].ARB = 0xC0000000 | (hoh->CanIdValue & 0x1FFFFFF) | hoh->CanObjectType;
\r
441 /* Start writing Mask, Arb, Control and Id bits */
\r
442 CanRegs[Controller]->IFx[IfRegId].COM = 0x00F80000 | mbNr;
\r
444 /* Use IFx[0] and IFx[1] alternating */
\r
448 } while (!hoh->Can_Arc_EOL);
\r
451 /* Set Bit Timing Register */
\r
452 CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);
\r
454 /* Reset CCE Bit */
\r
455 CanRegs[Controller]->CTL &= ~0x00000040;
\r
457 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
458 /* Switch Controller State to CANIF_CS_STOPPED */
\r
459 ControllerMode[Controller] = CANIF_CS_STOPPED;
\r
462 // Install interrupt handlers
\r
464 if (CanControllerConfigData[Controller].CanControllerId == DCAN1) {
\r
465 tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2 ,"DCAN1Level0");
\r
466 Irq_AttachIsr2(tid, NULL, 16);
\r
468 tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2, "DCAN1Level1");
\r
469 Irq_AttachIsr2(tid, NULL, 29);
\r
471 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN2) {
\r
472 tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2 ,"DCAN2Level0");
\r
473 Irq_AttachIsr2(tid, NULL, 35);
\r
475 tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2, "DCAN2Level1");
\r
476 Irq_AttachIsr2(tid, NULL, 42);
\r
478 } else if (CanControllerConfigData[Controller].CanControllerId == DCAN3) {
\r
479 tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2 ,"DCAN3Level0");
\r
480 Irq_AttachIsr2(tid, NULL, 45);
\r
482 tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2, "DCAN3Level1");
\r
483 Irq_AttachIsr2(tid, NULL, 55);
\r
488 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
489 /* Switch Module State to CAN_READY */
\r
490 ModuleState = CAN_READY;
\r
499 void Can_InitController(uint8 Controller, const Can_ControllerConfigType* Config)
\r
504 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
507 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_POINTER);
\r
510 if(ModuleState == CAN_UNINIT)
\r
512 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_UNINIT);
\r
515 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
517 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_CONTROLLER);
\r
520 if(ControllerMode[Controller] != CANIF_CS_STOPPED)
\r
522 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_TRANSITION);
\r
527 ErrCounter = CAN_TIMEOUT_DURATION;
\r
529 //for(MsgNr = 0; MsgNr < ControllerConfig[Controller].MessageBoxCount; MsgNr++)
\r
530 const Can_HardwareObjectType* hoh;
\r
531 hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;
\r
532 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
533 uint32 nProcessedMb = 0;
\r
536 // For every message object in this hoh
\r
537 for(; mbMask != 0; mbMask >>= 1) {
\r
539 if (!(mbMask & 1)) {
\r
540 // This message object is not part of this hoh.
\r
545 /* Wait until Busy Flag is 0 */
\r
546 while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)
\r
549 if(ErrCounter == 0)
\r
551 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
552 ErrCounter = CAN_TIMEOUT_DURATION;
\r
556 /* Read actual MaskRegister value of MessageObject */
\r
557 CanRegs[Controller]->IFx[IfRegId].COM = 0x004C0000 | (MsgNr);
\r
559 /* Wait until Busy Flag is 0 */
\r
560 while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)
\r
563 if(ErrCounter == 0)
\r
565 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
566 ErrCounter = CAN_TIMEOUT_DURATION;
\r
570 CanRegs[Controller]->IFx[IfRegId].MASK &= 0xD0000000;
\r
572 CanRegs[Controller]->IFx[IfRegId].MASK |= (*(hoh->CanFilterMaskRef)) & 0x1FFFFFFF;
\r
573 /* Write new Mask to MaskRegister */
\r
574 CanRegs[Controller]->IFx[IfRegId].COM = 0x00C80000 | (MsgNr);
\r
579 /* Wait until Busy Flag is 0 */
\r
580 while(CanRegs[Controller]->IFx[IfRegId].COM & 0x00008000)
\r
583 if(ErrCounter == 0)
\r
585 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
586 ErrCounter = CAN_TIMEOUT_DURATION;
\r
590 /* Set CCE Bit to allow access to BitTiming Register (Init already set, in mode "stopped") */
\r
591 CanRegs[Controller]->CTL |= 0x00000040;
\r
592 /* Set Bit Timing Register */
\r
593 CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);
\r
594 /* Clear CCE Bit */
\r
595 CanRegs[Controller]->CTL &= ~0x00000040;
\r
600 Can_ReturnType Can_SetControllerMode(uint8 Controller, Can_StateTransitionType Transition)
\r
602 Can_ReturnType Status = CAN_OK;
\r
603 uint32 ErrCounter = CAN_TIMEOUT_DURATION;
\r
606 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
607 if(ModuleState == CAN_UNINIT)
\r
609 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_UNINIT);
\r
612 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
614 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_PARAM_CONTROLLER);
\r
617 if(((Transition == CAN_T_START ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||
\r
618 ((Transition == CAN_T_STOP ) && (ControllerMode[Controller] != CANIF_CS_STARTED)) ||
\r
619 ((Transition == CAN_T_SLEEP ) && (ControllerMode[Controller] != CANIF_CS_STOPPED)) ||
\r
620 ((Transition == CAN_T_WAKEUP) && (ControllerMode[Controller] != CANIF_CS_SLEEP )))
\r
622 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);
\r
630 /* Clear Init Bit */
\r
631 CanRegs[Controller]->CTL &= ~0x00000001;
\r
632 /* Clear Status Register */
\r
633 CanRegs[Controller]->SR = 0x0000011F;
\r
635 ControllerMode[Controller] = CANIF_CS_STARTED;
\r
636 Can_EnableControllerInterrupts(Controller);
\r
641 CanRegs[Controller]->CTL |= 0x00000001;
\r
642 ControllerMode[Controller] = CANIF_CS_STOPPED;
\r
643 Can_DisableControllerInterrupts(Controller);
\r
648 CanRegs[Controller]->CTL |= 0x01000000;
\r
649 /* Save actual Register status */
\r
650 RegBuf = CanRegs[Controller]->CTL;
\r
651 /* Disable Status Interrupts and WUBA */
\r
652 CanRegs[Controller]->CTL &= ~0x02000004;
\r
653 /* Wait until Local Power Down Mode acknowledged */
\r
654 while(!(CanRegs[Controller]->SR & 0x00000400))
\r
656 /* Check if a WakeUp occurs */
\r
657 if(CanRegs[Controller]->SR & 0x00000200)
\r
659 Status = CAN_NOT_OK;
\r
663 if(ErrCounter == 0)
\r
665 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
666 ErrCounter = CAN_TIMEOUT_DURATION;
\r
667 Status = CAN_NOT_OK;
\r
671 /* Reset Control Register */
\r
672 CanRegs[Controller]->CTL = RegBuf;
\r
673 ControllerMode[Controller] = CANIF_CS_SLEEP;
\r
677 /* Clear PDR Bit */
\r
678 CanRegs[Controller]->CTL &= ~0x01000000;
\r
679 ControllerMode[Controller] = CANIF_CS_STOPPED;
\r
683 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
684 /* Invalid Transition */
\r
685 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);
\r
695 void Can_DisableControllerInterrupts(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, 4, CAN_E_UNINIT);
\r
703 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
705 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_PARAM_CONTROLLER);
\r
710 CanRegs[Controller]->CTL &= ~DCAN_IRQ_MASK;
\r
711 /* Increment Disable Counter */
\r
712 IntDisableCount[Controller]++;
\r
715 void Can_EnableControllerInterrupts(uint8 Controller)
\r
717 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
718 if(ModuleState == CAN_UNINIT)
\r
720 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_UNINIT);
\r
723 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
725 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_PARAM_CONTROLLER);
\r
729 if(IntDisableCount[Controller] > 0)
\r
731 if(IntDisableCount[Controller] == 1)
\r
734 CanRegs[Controller]->CTL |= DCAN_IRQ_MASK;
\r
736 IntDisableCount[Controller]--;
\r
741 void Can_Cbk_CheckWakeup(uint8 Controller)
\r
743 /* TODO not supported yet.
\r
744 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
745 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
747 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0x0B, CAN_E_PARAM_CONTROLLER);
\r
751 // Check WakeUpPending
\r
752 if(CanRegs[Controller]->SR & 0x00000200)
\r
764 Can_ReturnType Can_Write(Can_Arc_HTHType Hth, Can_PduType *PduInfo)
\r
767 uint8 ControllerId;
\r
769 uint32 ArbRegValue;
\r
770 uint8 DataByteIndex;
\r
772 Can_PduType *CurPduArrayPtr;
\r
773 uint8 *CurCancelRqstPtr;
\r
774 uint8 *CurTxRqstPtr;
\r
776 CurSduPtr = PduInfo->sdu;
\r
777 ErrCounter = CAN_TIMEOUT_DURATION;
\r
779 /* DET Error Check */
\r
780 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
781 if(PduInfo == NULL || PduInfo->sdu == NULL)
\r
783 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_POINTER);
\r
786 if(ModuleState == CAN_UNINIT)
\r
788 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_UNINIT);
\r
791 if(PduInfo->length > 8)
\r
793 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_DLC);
\r
794 return CAN_NOT_OK;
\r
798 ControllerId = Can_FindControllerId(Hth);
\r
800 const Can_HardwareObjectType *hoh = Can_FindTxHoh(Hth);
\r
802 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
803 if(hoh->CanObjectType != CAN_OBJECT_TYPE_TRANSMIT)
\r
805 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_HANDLE);
\r
809 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
811 for(; mbMask != 0; mbMask >>= 1) {
\r
813 if (!(mbMask & 1)) {
\r
814 continue; // This message object is not part of this hoh.
\r
818 CurPduArrayPtr = ControllerConfig[ControllerId].PduPtr + (MsgNr - 1);
\r
819 CurCancelRqstPtr = ControllerConfig[ControllerId].CancelPtr + (MsgNr - 1);
\r
820 CurTxRqstPtr = ControllerConfig[ControllerId].TxPtr + (MsgNr - 1);
\r
822 /* Bring Id Value to appropriate format and set ArbRegValue */
\r
823 if(PduInfo->id & 0x80000000)
\r
825 /* MsgVal, Ext, Transmit, Extended Id */
\r
826 ArbRegValue = 0xD0000000 | (PduInfo->id & 0x1FFFFFFF);
\r
830 /* MsgVal, Std, Transmit, Standard Id */
\r
831 ArbRegValue = 0xA0000000 | ((PduInfo->id & 0x7FF) << 18);
\r
834 /* Check if TxRqst Bit of MsgObject is set */
\r
835 if(CanRegs[ControllerId]->TRx[MsgNr >> 5] & (1 << (MsgNr & 0x1F)))
\r
840 /* Wait until Busy Flag is 0 */
\r
841 while(CanRegs[ControllerId]->IFx[IfRegId].COM & 0x00008000)
\r
844 if(ErrCounter == 0)
\r
846 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
847 ErrCounter = CAN_TIMEOUT_DURATION;
\r
852 /* Set NewDat, TxIE (dep on ControllerConfig), TxRqst, EoB and DLC */
\r
853 CanRegs[ControllerId]->IFx[IfRegId].MC = 0x00000100 // Tx request
\r
854 | 0x00000080 // Eob should be set to one for tx
\r
855 | (0x000F & PduInfo->length) // Set DLC
\r
856 | CanControllerConfigData[ControllerId].CanRxProcessing
\r
857 | (CanControllerConfigData[ControllerId].CanTxProcessing << 1); // Tx confirmation interrupt enabled
\r
860 //CanRegs[ControllerId]->IFx[IfRegId].MC = 0x00000180 | (0x000F & PduInfo->length) | (CanControllerConfigData[ControllerId].CanTxProcessing);
\r
862 /* Set ArbitrationRegister */
\r
863 CanRegs[ControllerId]->IFx[IfRegId].ARB = ArbRegValue;
\r
865 /* Set Databytes */
\r
866 for(DataByteIndex = 0; DataByteIndex < PduInfo->length; DataByteIndex++)
\r
868 CanRegs[ControllerId]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]] = *CurSduPtr++;
\r
871 /* Start transmission to MessageRAM */
\r
872 CanRegs[ControllerId]->IFx[IfRegId].COM = 0x00BF0000 | MsgNr;
\r
874 /* Save the PduInfo in PduArray, so that messages can be identified later */
\r
875 *CurPduArrayPtr = *PduInfo;
\r
876 /* TxRqstArray-Elements are used to identifiy transmitted objects in polling mode */
\r
885 void Can_MainFunction_Write()
\r
890 void Can_MainFunction_Read()
\r
895 void Can_MainFunction_BusOff()
\r
900 void Can_MainFunction_Wakeup()
\r