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
29 #define DCAN1_MAX_MESSAGEBOXES 64
\r
30 #define DCAN2_MAX_MESSAGEBOXES 64
\r
31 #define DCAN3_MAX_MESSAGEBOXES 32
\r
33 #define CAN_TIMEOUT_DURATION 0xFFFFFFFF
\r
34 #define CAN_INSTANCE 0
\r
36 #define DCAN_IRQ_MASK 0x00000006
\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
44 /* Macro for waiting until busy flag is 0 */
\r
45 #define DCAN_WAIT_UNTIL_NOT_BUSY(ControllerId, IfRegId) \
\r
47 uint32 ErrCounter = CAN_TIMEOUT_DURATION; \
\r
48 while(CanRegs[ControllerId]->IFx[IfRegId].COM & 0x00008000) { \
\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
58 /* Macro for waiting until busy flag is 0 */
\r
59 #define DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(ControllerId, IfRegId) \
\r
61 uint32 ErrCounter = CAN_TIMEOUT_DURATION; \
\r
62 while(CanRegs[ControllerId]->IFx[IfRegId].COM & 0x00008000) { \
\r
64 if(ErrCounter == 0) { \
\r
65 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED); \
\r
66 ErrCounter = CAN_TIMEOUT_DURATION; \
\r
74 // Array for easy access to DCAN register definitions.
\r
75 static Can_RegisterType* CanRegs[]=
\r
93 Can_PduType *PduPtr;
\r
96 } Controller_PreConfigType;
\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
104 static CanIf_ControllerModeType ControllerMode[CAN_ARC_CTRL_CONFIG_CNT];
\r
106 /* Used to switch between IF1 and IF2 of DCAN */
\r
107 static uint8 IfRegId = 0;
\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
112 /* To save pointer to the configuration set */
\r
113 static const Can_ConfigType *CurConfig;
\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
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
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
131 /* Holds the Controller specific configuration */
\r
132 static Controller_PreConfigType ControllerConfig[] =
\r
135 .MaxBoxes = DCAN1_MAX_MESSAGEBOXES,
\r
137 .PduPtr = PduInfoArray_1,
\r
138 .CancelPtr = CancelRqstArray_1,
\r
139 .TxPtr = TxRqstArray_1
\r
142 .MaxBoxes = DCAN2_MAX_MESSAGEBOXES,
\r
144 .PduPtr = PduInfoArray_2,
\r
145 .CancelPtr = CancelRqstArray_2,
\r
146 .TxPtr = TxRqstArray_2
\r
149 .MaxBoxes = DCAN3_MAX_MESSAGEBOXES,
\r
151 .PduPtr = PduInfoArray_3,
\r
152 .CancelPtr = CancelRqstArray_3,
\r
153 .TxPtr = TxRqstArray_3
\r
158 /* Shadow Buffer is used for buffering of received data */
\r
159 static uint8 RxShadowBuf[CAN_ARC_CTRL_CONFIG_CNT][8];
\r
161 /* Driver must know how often Can_DisableControllerInterrupts() has been called */
\r
162 static uint32 IntDisableCount[CAN_ARC_CTRL_CONFIG_CNT];
\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
171 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {
\r
174 } while (!hoh->Can_Arc_EOL);
\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
185 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT && hoh->CanObjectId == hth) {
\r
188 } while (!hoh->Can_Arc_EOL);
\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
198 if (hoh->CanObjectType == CAN_OBJECT_TYPE_RECEIVE
\r
199 && (hoh->Can_Arc_MbMask & (1 << (msgNr - 1))) ) {
\r
202 } while (!hoh->Can_Arc_EOL);
\r
206 #define DCAN_MC_NEWDAT 15
\r
207 #define DCAN_MC_EOB 7
\r
209 uint32 usedRxBoxes[64] = {0};
\r
210 uint32 usedTxBoxes[64] = {0};
\r
212 static inline Can_ReturnType handleRxMsgObject(uint8 MsgNr, const Can_HardwareObjectType *hoh, CanControllerIdType controller) {
\r
215 uint8 DataByteIndex;
\r
218 /* Wait until Busy Flag is 0 */
\r
219 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(controller, IfRegId);
\r
221 // Read message control
\r
222 uint32 mc = CanRegs[controller]->IFx[IfRegId].MC;
\r
223 uint32 arb = CanRegs[controller]->IFx[IfRegId].ARB;
\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
232 usedRxBoxes[MsgNr]++;
\r
234 usedRxBoxes[MsgNr]++;
\r
239 if(arb & 0x40000000) {
\r
240 /* Bring Id to standardized format (MSB marks extended Id) */
\r
241 MsgId = (arb & 0x1FFFFFFF) | 0x80000000;
\r
243 } else { /* Standard Id */
\r
244 /* Bring Id to standardized format (MSB marks extended Id) */
\r
245 MsgId = (arb & 0x1FFC0000) >> 18;
\r
249 MsgDlc = mc & 0x000F;
\r
254 /* Let SduPtr point to Shadow Buffer */
\r
255 SduPtr = RxShadowBuf[controller];
\r
257 /* Copy Message Data to Shadow Buffer */
\r
258 for(DataByteIndex = 0; DataByteIndex < MsgDlc; DataByteIndex++)
\r
260 SduPtr[DataByteIndex] = CanRegs[controller]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]];
\r
263 /* Indicate successful Reception */
\r
264 CanIf_RxIndication(hoh->CanObjectId, MsgId, MsgDlc, SduPtr);
\r
266 // Is this the last message object of the FIFO?
\r
267 if (mc & (1 << DCAN_MC_EOB)) {
\r
275 void Can_InterruptHandler(CanControllerIdType controller)
\r
279 uint32 ir = CanRegs[controller]->IR;
\r
282 if(ir == 0x8000) { // This is an error interrupt
\r
284 uint32 sr = CanRegs[controller]->SR;
\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
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
299 } else if (ir > 0 && ir < 0x8000){ // This interrupt is from a message object.
\r
302 /* Read Arbitration and control */
\r
303 CanRegs[controller]->IFx[IfRegId].COM = 0x003F0000 | MsgNr;
\r
305 /* Wait until Busy Flag is 0 */
\r
306 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(controller, IfRegId);
\r
308 /* Transmit Object */
\r
309 if(CanRegs[controller]->IFx[IfRegId].ARB & 0x20000000)
\r
313 usedTxBoxes[MsgNr]++;
\r
315 usedTxBoxes[MsgNr]++;
\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
323 /* Receive Object */
\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
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
339 if (handleRxMsgObject(MsgNr, hoh, controller) == CAN_NOT_OK) {
\r
340 break; // We have parsed the last object of this FIFO.
\r
348 void Can1_InterruptHandler() {
\r
349 Can_InterruptHandler(DCAN1);
\r
352 void Can2_InterruptHandler() {
\r
353 Can_InterruptHandler(DCAN2);
\r
356 void Can3_InterruptHandler() {
\r
357 Can_InterruptHandler(DCAN3);
\r
360 uint32 Can_CalculateBTR(uint8 Controller) {
\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
368 uint32 retVal = (brp | (tq1 << 8) | (tq2 << 12));
\r
373 void Can_Init(const Can_ConfigType *Config)
\r
380 /* DET Error Check */
\r
381 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
382 if(ModuleState != CAN_UNINIT)
\r
384 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_TRANSITION);
\r
389 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0, CAN_E_PARAM_POINTER);
\r
394 imask_t i_state = McuE_EnterCriticalSection();
\r
396 // TODO This should be used instead of other variables in the Can_Lcfg file.
\r
397 CurConfig = Config;
\r
399 for(Controller = 0; Controller < CAN_ARC_CTRL_CONFIG_CNT; Controller++)
\r
401 ErrCounter = CAN_TIMEOUT_DURATION;
\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
407 CanRegs[Controller]->CTL = 0x00001641 | DCAN_IRQ_MASK | (CanControllerConfigData[Controller].Can_Arc_Loopback << 7);// | (CanControllerConfigData[Controller].CanWakeupProcessing >> 8) | (CanControllerConfigData[Controller].CanBusOffProcessing >> 7);
\r
409 /* LEC 7, TxOk, RxOk, PER */
\r
410 CanRegs[Controller]->SR = 0x0000011F;
\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
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
424 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\r
426 // Initialize all message objects for this controller to invalid state.
\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
432 /* Use IFx[0] and IFx[1] alternating */
\r
437 /* Configure the HOHs for this controller. */
\r
438 const Can_HardwareObjectType* hoh;
\r
439 hoh = CanControllerConfigData[Controller].Can_Arc_Hoh;
\r
443 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
445 uint32 nProcessedMb = 0;
\r
447 // For every message object in this hoh
\r
448 for(; mbMask != 0; mbMask >>= 1) {
\r
450 if (!(mbMask & 1)) {
\r
451 // This message object is not part of this hoh.
\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
464 /* EndOfBlock Bit will be set */
\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
475 //CanRegs[Controller]->IFx[IfRegId].MC = 0x00001008 | CanControllerConfigData[Controller].CanRxProcessing | (CanControllerConfigData[Controller].CanTxProcessing) | Eob & ~(hoh->CanObjectType >> 17);
\r
477 if(hoh->CanIdType == CAN_ID_TYPE_STANDARD) /* Standard Identifiers */
\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
484 else if(hoh->CanIdType == CAN_ID_TYPE_EXTENDED) /* Extended Identifiers */
\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
491 else /* Mixed Identifiers */
\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
498 /* Start writing Mask, Arb, Control and Id bits */
\r
499 CanRegs[Controller]->IFx[IfRegId].COM = 0x00F80000 | mbNr;
\r
501 /* Use IFx[0] and IFx[1] alternating */
\r
505 } while (!hoh->Can_Arc_EOL);
\r
508 /* Set Bit Timing Register */
\r
509 CanRegs[Controller]->BTR = Can_CalculateBTR(Controller);
\r
511 /* Reset CCE Bit */
\r
512 CanRegs[Controller]->CTL &= ~0x00000040;
\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
519 // Install interrupt handlers
\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
525 tid = Os_Arc_CreateIsr(Can1_InterruptHandler, 2, "DCAN1Level1");
\r
526 Irq_AttachIsr2(tid, NULL, 29);
\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
532 tid = Os_Arc_CreateIsr(Can2_InterruptHandler, 2, "DCAN2Level1");
\r
533 Irq_AttachIsr2(tid, NULL, 42);
\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
539 tid = Os_Arc_CreateIsr(Can3_InterruptHandler, 2, "DCAN3Level1");
\r
540 Irq_AttachIsr2(tid, NULL, 55);
\r
545 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
546 /* Switch Module State to CAN_READY */
\r
547 ModuleState = CAN_READY;
\r
550 McuE_ExitCriticalSection(i_state);
\r
556 void Can_InitController(uint8 Controller, const Can_ControllerConfigType* Config)
\r
561 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
564 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_POINTER);
\r
567 if(ModuleState == CAN_UNINIT)
\r
569 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_UNINIT);
\r
572 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
574 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_PARAM_CONTROLLER);
\r
577 if(ControllerMode[Controller] != CANIF_CS_STOPPED)
\r
579 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 2, CAN_E_TRANSITION);
\r
584 imask_t i_state = McuE_EnterCriticalSection();
\r
586 ErrCounter = CAN_TIMEOUT_DURATION;
\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
595 // For every message object in this hoh
\r
596 for(; mbMask != 0; mbMask >>= 1) {
\r
598 if (!(mbMask & 1)) {
\r
599 // This message object is not part of this hoh.
\r
604 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\r
606 /* Read actual MaskRegister value of MessageObject */
\r
607 CanRegs[Controller]->IFx[IfRegId].COM = 0x004C0000 | (MsgNr);
\r
609 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\r
611 CanRegs[Controller]->IFx[IfRegId].MASK &= 0xD0000000;
\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
620 DCAN_WAIT_UNTIL_NOT_BUSY_NO_RV(Controller, IfRegId);
\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
629 McuE_ExitCriticalSection(i_state);
\r
633 Can_ReturnType Can_SetControllerMode(uint8 Controller, Can_StateTransitionType Transition)
\r
635 Can_ReturnType Status = CAN_OK;
\r
636 uint32 ErrCounter = CAN_TIMEOUT_DURATION;
\r
639 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
640 if(ModuleState == CAN_UNINIT)
\r
642 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_UNINIT);
\r
645 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
647 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_PARAM_CONTROLLER);
\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
655 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 3, CAN_E_TRANSITION);
\r
663 /* Clear Init Bit */
\r
664 CanRegs[Controller]->CTL &= ~0x00000001;
\r
665 /* Clear Status Register */
\r
666 CanRegs[Controller]->SR = 0x0000011F;
\r
668 ControllerMode[Controller] = CANIF_CS_STARTED;
\r
669 Can_EnableControllerInterrupts(Controller);
\r
674 CanRegs[Controller]->CTL |= 0x00000001;
\r
675 ControllerMode[Controller] = CANIF_CS_STOPPED;
\r
676 Can_DisableControllerInterrupts(Controller);
\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
689 /* Check if a WakeUp occurs */
\r
690 if(CanRegs[Controller]->SR & 0x00000200)
\r
692 Status = CAN_NOT_OK;
\r
696 if(ErrCounter == 0)
\r
698 Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
\r
699 ErrCounter = CAN_TIMEOUT_DURATION;
\r
700 Status = CAN_NOT_OK;
\r
704 /* Reset Control Register */
\r
705 CanRegs[Controller]->CTL = RegBuf;
\r
706 ControllerMode[Controller] = CANIF_CS_SLEEP;
\r
710 /* Clear PDR Bit */
\r
711 CanRegs[Controller]->CTL &= ~0x01000000;
\r
712 ControllerMode[Controller] = CANIF_CS_STOPPED;
\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
728 void Can_DisableControllerInterrupts(uint8 Controller)
\r
730 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
731 if(ModuleState == CAN_UNINIT)
\r
733 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_UNINIT);
\r
736 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
738 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 4, CAN_E_PARAM_CONTROLLER);
\r
743 CanRegs[Controller]->CTL &= ~DCAN_IRQ_MASK;
\r
744 /* Increment Disable Counter */
\r
745 IntDisableCount[Controller]++;
\r
748 void Can_EnableControllerInterrupts(uint8 Controller)
\r
750 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
751 if(ModuleState == CAN_UNINIT)
\r
753 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_UNINIT);
\r
756 if(Controller >= CAN_ARC_CTRL_CONFIG_CNT)
\r
758 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 5, CAN_E_PARAM_CONTROLLER);
\r
762 if(IntDisableCount[Controller] > 0)
\r
764 if(IntDisableCount[Controller] == 1)
\r
767 CanRegs[Controller]->CTL |= DCAN_IRQ_MASK;
\r
769 IntDisableCount[Controller]--;
\r
774 void Can_Cbk_CheckWakeup(uint8 Controller)
\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
780 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 0x0B, CAN_E_PARAM_CONTROLLER);
\r
784 // Check WakeUpPending
\r
785 if(CanRegs[Controller]->SR & 0x00000200)
\r
797 Can_ReturnType Can_Write(Can_Arc_HTHType Hth, Can_PduType *PduInfo)
\r
799 uint8 ControllerId;
\r
801 uint32 ArbRegValue;
\r
802 uint8 DataByteIndex;
\r
804 Can_PduType *CurPduArrayPtr;
\r
805 uint8 *CurCancelRqstPtr;
\r
806 uint8 *CurTxRqstPtr;
\r
808 CurSduPtr = PduInfo->sdu;
\r
811 /* DET Error Check */
\r
812 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
813 if(PduInfo == NULL || PduInfo->sdu == NULL)
\r
815 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_POINTER);
\r
818 if(ModuleState == CAN_UNINIT)
\r
820 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_UNINIT);
\r
823 if(PduInfo->length > 8)
\r
825 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_DLC);
\r
826 return CAN_NOT_OK;
\r
830 ControllerId = Can_FindControllerId(Hth);
\r
832 const Can_HardwareObjectType *hoh = Can_FindTxHoh(Hth);
\r
834 #if(CAN_DEV_ERROR_DETECT == STD_ON)
\r
835 if(hoh->CanObjectType != CAN_OBJECT_TYPE_TRANSMIT)
\r
837 Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 6, CAN_E_PARAM_HANDLE);
\r
841 uint64 mbMask = hoh->Can_Arc_MbMask;
\r
843 for(; mbMask != 0; mbMask >>= 1) {
\r
845 if (!(mbMask & 1)) {
\r
846 continue; // This message object is not part of this hoh.
\r
848 /* Check if TxRqst Bit of MsgObject is set */
\r
849 if(CanRegs[ControllerId]->TRx[MsgNr >> 5] & (1 << (MsgNr & 0x1F)))
\r
856 /* Check if TxRqst Bit of MsgObject is set */
\r
857 if(CanRegs[ControllerId]->TRx[MsgNr >> 5] & (1 << (MsgNr & 0x1F)))
\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
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
871 /* MsgVal, Std, Transmit, Standard Id */
\r
872 ArbRegValue = 0xA0000000 | ((PduInfo->id & 0x7FF) << 18);
\r
876 DCAN_WAIT_UNTIL_NOT_BUSY(ControllerId, IfRegId);
\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
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
889 /* Set ArbitrationRegister */
\r
890 CanRegs[ControllerId]->IFx[IfRegId].ARB = ArbRegValue;
\r
892 /* Set Databytes */
\r
893 for(DataByteIndex = 0; DataByteIndex < PduInfo->length; DataByteIndex++)
\r
895 CanRegs[ControllerId]->IFx[IfRegId].DATx[ElementIndex[DataByteIndex]] = *CurSduPtr++;
\r
898 /* Start transmission to MessageRAM */
\r
899 CanRegs[ControllerId]->IFx[IfRegId].COM = 0x00BF0000 | MsgNr;
\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
908 McuE_ExitCriticalSection(i_state);
\r
913 void Can_MainFunction_Write()
\r
918 void Can_MainFunction_Read()
\r
923 void Can_MainFunction_BusOff()
\r
928 void Can_MainFunction_Wakeup()
\r