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
25 #ifndef USE_CAN_STUB
\r
29 #include "CanIf_Cbk.h"
\r
31 #if defined(USE_DEM)
\r
41 #define USE_CAN_STATISTICS STD_OFF
\r
43 // bits in CANxCTL0:
\r
44 #define BM_INITRQ 0x01
\r
45 #define BM_SLPRQ 0x02
\r
46 #define BM_WUPE 0x04
\r
48 // bits in CANxCTL1:
\r
49 #define BM_INITAK 0x01
\r
50 #define BM_SLPAK 0x02
\r
51 #define BM_WUPM 0x04
\r
52 #define BM_LISTEN 0x10
\r
53 #define BM_LOOPB 0x20
\r
54 #define BM_CLKSRC 0x40
\r
55 #define BM_CANE 0x80
\r
57 // bits in CANxRFLG:
\r
58 // bits in CANxRIER:
\r
59 #define BM_WUPI 0x80
\r
60 #define BM_CSCI 0x40
\r
61 #define BM_RSTAT1 0x20
\r
62 #define BM_RSTAT0 0x10
\r
63 #define BM_TSTAT1 0x08
\r
64 #define BM_TSTAT0 0x04
\r
65 #define BM_OVRI 0x02
\r
68 // bits in CANxTFLG:
\r
69 // bits in CANxTBSEL:
\r
75 volatile uint8_t idr0; // Identifier Register 0
\r
76 volatile uint8_t idr1;
\r
77 volatile uint8_t idr2;
\r
78 volatile uint8_t idr3;
\r
79 volatile uint8_t ds0; // Data Segment Register 0
\r
80 volatile uint8_t ds1;
\r
81 volatile uint8_t ds2;
\r
82 volatile uint8_t ds3;
\r
83 volatile uint8_t ds4;
\r
84 volatile uint8_t ds5;
\r
85 volatile uint8_t ds6;
\r
86 volatile uint8_t ds7;
\r
87 volatile uint8_t dlr; // Data Length Register
\r
88 volatile uint8_t tbpr; // Transmit Buffer Priority Register
\r
89 volatile uint8_t tsr_hb; // Time Stamp Register (High Byte)
\r
90 volatile uint8_t tsr_lb; // Time Stamp Register (Low Byte)
\r
94 IDR0 : ID28 ID27 ID26 ID25 ID24 ID23 ID22 ID21
\r
95 IDR1 : ID20 ID19 ID18 SRR IDE ID17 ID16 ID15
\r
96 IDR2 : ID14 ID13 ID12 ID11 ID10 ID9 ID8 ID7
\r
97 IDR3 : ID6 ID5 ID4 ID3 ID2 ID1 ID0 RTR
\r
100 volatile uint8_t R[4];
\r
102 volatile uint8_t id28to21;
\r
103 volatile uint8_t id20to18:3;
\r
104 volatile uint8_t SRR:1;
\r
105 volatile uint8_t IDE:1;
\r
106 volatile uint8_t id17to15:3;
\r
107 volatile uint8_t id14to7;
\r
108 volatile uint8_t id6to0:7;
\r
109 volatile uint8_t RTR:1;
\r
115 volatile uint8_t CTL0; /* control register 0 */
\r
116 volatile uint8_t CTL1; /* control register 1 */
\r
117 volatile uint8_t BTR0; /* bus timing register 0 */
\r
118 volatile uint8_t BTR1; /* bus timing register 1 */
\r
119 volatile uint8_t RFLG; /* receiver flag register */
\r
120 volatile uint8_t RIER; /* receiver interrupt reg */
\r
121 volatile uint8_t TFLG; /* transmitter flag reg */
\r
122 volatile uint8_t TIER; /* transmitter control reg */
\r
123 volatile uint8_t TARQ; /* transmitter abort request */
\r
124 volatile uint8_t TAAK; /* transmitter abort acknowledge */
\r
125 volatile uint8_t TBSEL; /* transmit buffer selection */
\r
126 volatile uint8_t IDAC; /* identifier acceptance */
\r
127 volatile uint8_t NOTUSED1;
\r
128 volatile uint8_t NOTUSED2;
\r
129 volatile uint8_t RXERR; /* receive error counter */
\r
130 volatile uint8_t TXERR; /* transmit error counter */
\r
131 volatile uint8_t IDAR0; /* id acceptance reg 0 */
\r
132 volatile uint8_t IDAR1; /* id acceptance reg 1 */
\r
133 volatile uint8_t IDAR2; /* id acceptance reg 2 */
\r
134 volatile uint8_t IDAR3; /* id acceptance reg 3 */
\r
135 volatile uint8_t IDMR0; /* id mask register 0 */
\r
136 volatile uint8_t IDMR1; /* id mask register 1 */
\r
137 volatile uint8_t IDMR2; /* id mask register 2 */
\r
138 volatile uint8_t IDMR3; /* id mask register 3 */
\r
139 volatile uint8_t IDAR4; /* id acceptance reg 4 */
\r
140 volatile uint8_t IDAR5; /* id acceptance reg 5 */
\r
141 volatile uint8_t IDAR6; /* id acceptance reg 6 */
\r
142 volatile uint8_t IDAR7; /* id acceptance reg 7 */
\r
143 volatile uint8_t IDMR4; /* id mask register 4 */
\r
144 volatile uint8_t IDMR5; /* id mask register 5 */
\r
145 volatile uint8_t IDMR6; /* id mask register 6 */
\r
146 volatile uint8_t IDMR7; /* id mask register 7 */
\r
147 volatile RxTxBuf_t RXFG; /* receive buffer */
\r
148 volatile RxTxBuf_t TXFG; /* transmit buffer */
\r
151 /* CONFIGURATION NOTES
\r
152 * ------------------------------------------------------------------
\r
153 * - CanHandleType must be CAN_ARC_HANDLE_TYPE_BASIC
\r
154 * i.e. CanHandleType=CAN_ARC_HANDLE_TYPE_FULL NOT supported
\r
155 * i.e CanIdValue is NOT supported
\r
156 * - All CanXXXProcessing must be CAN_ARC_PROCESS_TYPE_INTERRUPT
\r
157 * ie CAN_ARC_PROCESS_TYPE_POLLED not supported
\r
158 * - HOH's for Tx are global and Rx are for each controller
\r
161 /* IMPLEMENTATION NOTES
\r
162 * -----------------------------------------------
\r
163 * - A HOH us unique for a controller( not a config-set )
\r
164 * - Hrh's are numbered for each controller from 0
\r
165 * - Only one transmit mailbox is used because otherwise
\r
166 * we cannot use tx_confirmation since there is no way to know
\r
167 * which mailbox caused the tx interrupt. TP will need this feature.
\r
168 * - Sleep,wakeup not fully implemented since other modules lack functionality
\r
172 * -----------------------------------------------
\r
173 * - Can Hardware unit - One or multiple Can controllers of the same type.
\r
174 * - Hrh - HOH with receive definitions
\r
175 * - Hth - HOH with transmit definitions
\r
179 //-------------------------------------------------------------------
\r
181 #define GET_CONTROLLER_CONFIG(_controller) \
\r
182 &Can_Global.config->CanConfigSet->CanController[(_controller)]
\r
184 #define GET_CALLBACKS() \
\r
185 (Can_Global.config->CanConfigSet->CanCallbacks)
\r
187 #define GET_PRIVATE_DATA(_controller) \
\r
188 &CanUnit[_controller]
\r
190 #define GET_CONTROLLER_CNT() (CAN_CONTROLLER_CNT)
\r
192 //-------------------------------------------------------------------
\r
194 #if ( CAN_DEV_ERROR_DETECT == STD_ON )
\r
195 #define VALIDATE(_exp,_api,_err ) \
\r
197 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
198 return CAN_NOT_OK; \
\r
201 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
203 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
207 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)
\r
209 #define VALIDATE(_exp,_api,_err )
\r
210 #define VALIDATE_NO_RV(_exp,_api,_err )
\r
211 #define DET_REPORTERROR(_x,_y,_z,_q)
\r
214 #if defined(USE_DEM)
\r
215 #define VALIDATE_DEM_NO_RV(_exp,_err ) \
\r
217 Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED); \
\r
221 #define VALIDATE_DEM_NO_RV(_exp,_err )
\r
224 //-------------------------------------------------------------------
\r
230 } Can_DriverStateType;
\r
232 // Mapping between HRH and Controller//HOH
\r
233 typedef struct Can_Arc_ObjectHOHMapStruct
\r
235 CanControllerIdType CanControllerRef; // Reference to controller
\r
236 const Can_HardwareObjectType* CanHOHRef; // Reference to HOH.
\r
237 } Can_Arc_ObjectHOHMapType;
\r
239 /* Type for holding global information used by the driver */
\r
241 Can_DriverStateType initRun;
\r
244 const Can_ConfigType *config;
\r
246 // One bit for each channel that is configured.
\r
247 // Used to determine if validity of a channel
\r
249 // 0 - NOT configured
\r
251 // Maps the a channel id to a configured channel id
\r
252 uint8 channelMap[CAN_CONTROLLER_CNT];
\r
254 // This is a map that maps the HTH:s with the controller and Hoh. It is built
\r
255 // during Can_Init and is used to make things faster during a transmit.
\r
256 Can_Arc_ObjectHOHMapType CanHTHMap[NUM_OF_HTHS];
\r
260 Can_GlobalType Can_Global =
\r
262 .initRun = CAN_UNINIT,
\r
265 /* Type for holding information about each controller */
\r
267 CanIf_ControllerModeType state;
\r
271 #if (USE_CAN_STATISTICS == STD_ON)
\r
272 Can_Arc_StatisticsType stats;
\r
275 // Data stored for Txconfirmation callbacks to CanIf
\r
276 PduIdType swPduHandle; //
\r
279 Can_UnitType CanUnit[CAN_CONTROLLER_CNT] =
\r
282 .state = CANIF_CS_UNINIT,
\r
284 .state = CANIF_CS_UNINIT,
\r
286 .state = CANIF_CS_UNINIT,
\r
288 .state = CANIF_CS_UNINIT,
\r
290 .state = CANIF_CS_UNINIT,
\r
294 //-------------------------------------------------------------------
\r
296 static CAN_HW_t * GetController(int unit)
\r
300 if(unit == CAN_CTRL_0)
\r
302 res = (CAN_HW_t *)CAN0_BASE;
\r
304 else if(unit == CAN_CTRL_1)
\r
306 res = (CAN_HW_t *)CAN1_BASE;
\r
308 else if(unit == CAN_CTRL_2)
\r
310 res = (CAN_HW_t *)CAN2_BASE;
\r
312 else if(unit == CAN_CTRL_3)
\r
314 res = (CAN_HW_t *)CAN3_BASE;
\r
316 else if(unit == CAN_CTRL_4)
\r
318 res = (CAN_HW_t *)CAN4_BASE;
\r
324 //-------------------------------------------------------------------
\r
326 * Function that finds the Hoh( HardwareObjectHandle ) from a Hth
\r
327 * A HTH may connect to one or several HOH's. Just find the first one.
\r
329 * @param hth The transmit handle
\r
330 * @returns Ptr to the Hoh
\r
332 static const Can_HardwareObjectType * Can_FindHoh( Can_Arc_HTHType hth , uint32* controller)
\r
334 const Can_HardwareObjectType *hohObj;
\r
335 const Can_Arc_ObjectHOHMapType *map;
\r
336 const Can_ControllerConfigType *canHwConfig;
\r
338 map = &Can_Global.CanHTHMap[hth];
\r
340 // Verify that this is the correct map
\r
341 if (map->CanHOHRef->CanObjectId != hth)
\r
343 DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);
\r
346 canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[map->CanControllerRef]);
\r
348 hohObj = map->CanHOHRef;
\r
350 // Verify that this is the correct Hoh type
\r
351 if ( hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
\r
353 *controller = map->CanControllerRef;
\r
357 DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);
\r
362 //-------------------------------------------------------------------
\r
364 static void Can_RxIsr( int unit );
\r
365 static void Can_TxIsr( int unit );
\r
366 static void Can_ErrIsr( int unit );
\r
367 static void Can_WakeIsr( int unit );
\r
369 void Can_0_RxIsr( void ) { Can_RxIsr(CAN_CTRL_0); }
\r
370 void Can_1_RxIsr( void ) { Can_RxIsr(CAN_CTRL_1); }
\r
371 void Can_2_RxIsr( void ) { Can_RxIsr(CAN_CTRL_2); }
\r
372 void Can_3_RxIsr( void ) { Can_RxIsr(CAN_CTRL_3); }
\r
373 void Can_4_RxIsr( void ) { Can_RxIsr(CAN_CTRL_4); }
\r
375 void Can_0_TxIsr( void ) { Can_TxIsr(CAN_CTRL_0); }
\r
376 void Can_1_TxIsr( void ) { Can_TxIsr(CAN_CTRL_1); }
\r
377 void Can_2_TxIsr( void ) { Can_TxIsr(CAN_CTRL_2); }
\r
378 void Can_3_TxIsr( void ) { Can_TxIsr(CAN_CTRL_3); }
\r
379 void Can_4_TxIsr( void ) { Can_TxIsr(CAN_CTRL_4); }
\r
381 void Can_0_ErrIsr( void ) { Can_ErrIsr(CAN_CTRL_0); }
\r
382 void Can_1_ErrIsr( void ) { Can_ErrIsr(CAN_CTRL_1); }
\r
383 void Can_2_ErrIsr( void ) { Can_ErrIsr(CAN_CTRL_2); }
\r
384 void Can_3_ErrIsr( void ) { Can_ErrIsr(CAN_CTRL_3); }
\r
385 void Can_4_ErrIsr( void ) { Can_ErrIsr(CAN_CTRL_4); }
\r
387 void Can_0_WakeIsr( void ) { Can_WakeIsr(CAN_CTRL_0); }
\r
388 void Can_1_WakeIsr( void ) { Can_WakeIsr(CAN_CTRL_1); }
\r
389 void Can_2_WakeIsr( void ) { Can_WakeIsr(CAN_CTRL_2); }
\r
390 void Can_3_WakeIsr( void ) { Can_WakeIsr(CAN_CTRL_3); }
\r
391 void Can_4_WakeIsr( void ) { Can_WakeIsr(CAN_CTRL_4); }
\r
393 //-------------------------------------------------------------------
\r
395 // Uses 25.4.5.1 Transmission Abort Mechanism
\r
396 static void Can_AbortTx( CAN_HW_t *canHw, Can_UnitType *canUnit ) {
\r
399 // Disable Transmit irq
\r
402 // check if mb's empty
\r
403 if((canHw->TFLG & BM_TX0) == 0){mask |= BM_TX0;}
\r
404 if((canHw->TFLG & BM_TX1) == 0){mask |= BM_TX1;}
\r
405 if((canHw->TFLG & BM_TX2) == 0){mask |= BM_TX2;}
\r
407 canHw->TARQ = mask; // Abort all pending mb's
\r
409 // Wait for mb's being emptied
\r
411 while(canHw->TFLG != (BM_TX0 | BM_TX1 | BM_TX2)){
\r
421 * Hardware wake ISR for CAN
\r
423 * @param unit CAN controller number( from 0 )
\r
425 static void Can_WakeIsr( int unit ) {
\r
426 if (GET_CALLBACKS()->ControllerWakeup != NULL)
\r
428 GET_CALLBACKS()->ControllerWakeup(unit);
\r
431 Can_SetControllerMode(unit, CAN_T_STOP);
\r
433 // TODO EcuM_CheckWakeup();
\r
437 * Hardware error ISR for CAN
\r
439 * @param unit CAN controller number( from 0 )
\r
441 static void Can_ErrIsr( int unit ) {
\r
442 CAN_HW_t *canHw = GetController(unit);
\r
443 Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
\r
444 Can_Arc_ErrorType err;
\r
446 uint8_t rflg = canHw->RFLG;
\r
448 if((rflg & BM_OVRI) == BM_OVRI){
\r
452 canHw->RFLG = BM_OVRI;
\r
455 if((rflg & BM_CSCI) == BM_CSCI){
\r
456 if( ((rflg & (BM_RSTAT0 | BM_RSTAT0)) == (BM_RSTAT0 | BM_RSTAT1)) ||
\r
457 ((rflg & (BM_TSTAT0 | BM_TSTAT0)) == (BM_TSTAT0 | BM_TSTAT1)) )
\r
459 #if (USE_CAN_STATISTICS == STD_ON)
\r
460 canUnit->stats.boffCnt++;
\r
462 if (GET_CALLBACKS()->ControllerBusOff != NULL)
\r
464 GET_CALLBACKS()->ControllerBusOff(unit);
\r
466 Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272
\r
468 Can_AbortTx( canHw, canUnit ); // CANIF273
\r
472 canHw->RFLG = BM_CSCI;
\r
477 if (GET_CALLBACKS()->Arc_Error != NULL)
\r
479 GET_CALLBACKS()->Arc_Error( unit, err );
\r
484 //-------------------------------------------------------------------
\r
487 * ISR for CAN. Normal Rx/operation
\r
489 * @param unit CAN controller number( from 0 )
\r
491 static void Can_RxIsr(int unit) {
\r
493 CAN_HW_t *canHw= GetController(unit);
\r
494 const Can_ControllerConfigType *canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]);
\r
495 #if (USE_CAN_STATISTICS == STD_ON)
\r
496 Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
\r
498 const Can_HardwareObjectType *hohObj;
\r
500 // Loop over all the Hoh's
\r
501 hohObj= canHwConfig->Can_Arc_Hoh;
\r
506 if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)
\r
510 idr = (IdrType *)&canHw->RXFG.idr0;
\r
512 // According to autosar MSB shuould be set if extended
\r
513 if (idr->Bit.IDE == 1) {
\r
514 id = ((uint32)idr->Bit.id28to21 << 21) | ((uint32)idr->Bit.id20to18 << 18) | ((uint32)idr->Bit.id17to15 << 15) |
\r
515 ((uint32)idr->Bit.id14to7 << 7) | idr->Bit.id6to0;
\r
518 id = ((uint32)idr->Bit.id28to21 << 3) | (uint32)idr->Bit.id20to18;
\r
521 if (GET_CALLBACKS()->RxIndication != NULL)
\r
523 GET_CALLBACKS()->RxIndication(hohObj->CanObjectId,
\r
525 canHw->RXFG.dlr & 0x0f,
\r
526 (uint8 *)&canHw->RXFG.ds0 ); // Next layer will copy
\r
528 #if (USE_CAN_STATISTICS == STD_ON)
\r
529 // Increment statistics
\r
530 canUnit->stats.rxSuccessCnt++;
\r
534 canHw->RFLG = BM_RXF; // clear RX flag
\r
536 } while ( !hohObj->Can_Arc_EOL);
\r
540 * ISR for CAN. Normal Tx operation
\r
542 * @param unit CAN controller number( from 0 )
\r
544 static void Can_TxIsr(int unit) {
\r
545 CAN_HW_t *canHw= GetController(unit);
\r
546 const Can_ControllerConfigType *canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]);
\r
547 Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
\r
548 const Can_HardwareObjectType *hohObj;
\r
550 // Loop over all the Hoh's
\r
551 hohObj= canHwConfig->Can_Arc_Hoh;
\r
556 if (hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
\r
558 if (GET_CALLBACKS()->TxConfirmation != NULL)
\r
560 GET_CALLBACKS()->TxConfirmation(canUnit->swPduHandle);
\r
562 canUnit->swPduHandle = 0; // Is this really necessary ??
\r
564 // Disable Tx interrupt
\r
567 } while ( !hohObj->Can_Arc_EOL);
\r
570 //-------------------------------------------------------------------
\r
572 #define INSTALL_HANDLERS(_can_name,_err,_wake,_rx,_tx) \
\r
574 ISR_INSTALL_ISR2("Can",_can_name ## _ErrIsr,_err,2,0); \
\r
575 ISR_INSTALL_ISR2("Can",_can_name ## _WakeIsr,_wake,2,0); \
\r
576 ISR_INSTALL_ISR2("Can",_can_name ## _RxIsr,_rx,2,0); \
\r
577 ISR_INSTALL_ISR2("Can",_can_name ## _TxIsr,_tx,2,0); \
\r
580 // This initiates ALL can controllers
\r
581 void Can_Init( const Can_ConfigType *config ) {
\r
582 Can_UnitType *canUnit;
\r
583 const Can_ControllerConfigType *canHwConfig;
\r
586 VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), 0x0, CAN_E_TRANSITION );
\r
587 VALIDATE_NO_RV( (config != NULL ), 0x0, CAN_E_PARAM_POINTER );
\r
590 Can_Global.config = config;
\r
591 Can_Global.initRun = CAN_READY;
\r
593 for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
594 canHwConfig = GET_CONTROLLER_CONFIG(configId);
\r
595 ctlrId = canHwConfig->CanControllerId;
\r
597 // Assign the configuration channel used later..
\r
598 Can_Global.channelMap[canHwConfig->CanControllerId] = configId;
\r
599 Can_Global.configured |= (1<<ctlrId);
\r
601 canUnit = GET_PRIVATE_DATA(ctlrId);
\r
602 canUnit->state = CANIF_CS_STOPPED;
\r
604 canUnit->lock_cnt = 0;
\r
607 #if (USE_CAN_STATISTICS == STD_ON)
\r
608 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
\r
612 // Could install handlers depending on HW objects to trap more errors
\r
613 // in configuration
\r
614 if( canHwConfig->CanControllerId == CAN_CTRL_0) {
\r
615 INSTALL_HANDLERS(Can_0, IRQ_TYPE_CAN0_ERR, IRQ_TYPE_CAN0_WAKE, IRQ_TYPE_CAN0_RX, IRQ_TYPE_CAN0_TX);
\r
617 else if( canHwConfig->CanControllerId == CAN_CTRL_1) {
\r
618 INSTALL_HANDLERS(Can_1, IRQ_TYPE_CAN1_ERR, IRQ_TYPE_CAN1_WAKE, IRQ_TYPE_CAN1_RX, IRQ_TYPE_CAN1_TX);
\r
620 else if( canHwConfig->CanControllerId == CAN_CTRL_2) {
\r
621 INSTALL_HANDLERS(Can_2, IRQ_TYPE_CAN2_ERR, IRQ_TYPE_CAN2_WAKE, IRQ_TYPE_CAN2_RX, IRQ_TYPE_CAN2_TX);
\r
623 else if( canHwConfig->CanControllerId == CAN_CTRL_3) {
\r
624 INSTALL_HANDLERS(Can_3, IRQ_TYPE_CAN3_ERR, IRQ_TYPE_CAN3_WAKE, IRQ_TYPE_CAN3_RX, IRQ_TYPE_CAN3_TX);
\r
626 else if( canHwConfig->CanControllerId == CAN_CTRL_4) {
\r
627 INSTALL_HANDLERS(Can_4, IRQ_TYPE_CAN4_ERR, IRQ_TYPE_CAN4_WAKE, IRQ_TYPE_CAN4_RX, IRQ_TYPE_CAN4_TX);
\r
630 Can_InitController(ctlrId, canHwConfig);
\r
632 // Loop through all Hoh:s and map them into the HTHMap
\r
633 const Can_HardwareObjectType* hoh;
\r
634 hoh = canHwConfig->Can_Arc_Hoh;
\r
640 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
\r
642 Can_Global.CanHTHMap[hoh->CanObjectId].CanControllerRef = canHwConfig->CanControllerId;
\r
643 Can_Global.CanHTHMap[hoh->CanObjectId].CanHOHRef = hoh;
\r
645 } while (!hoh->Can_Arc_EOL);
\r
650 // Unitialize the module
\r
653 Can_UnitType *canUnit;
\r
654 const Can_ControllerConfigType *canHwConfig;
\r
657 for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
658 canHwConfig = GET_CONTROLLER_CONFIG(configId);
\r
659 ctlrId = canHwConfig->CanControllerId;
\r
661 canUnit = GET_PRIVATE_DATA(ctlrId);
\r
662 canUnit->state = CANIF_CS_UNINIT;
\r
664 Can_DisableControllerInterrupts(ctlrId);
\r
666 canUnit->lock_cnt = 0;
\r
669 #if (USE_CAN_STATISTICS == STD_ON)
\r
670 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
\r
674 Can_Global.config = NULL;
\r
675 Can_Global.initRun = CAN_UNINIT;
\r
680 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config)
\r
688 Can_UnitType *canUnit;
\r
689 uint8 cId = controller;
\r
690 const Can_ControllerConfigType *canHwConfig;
\r
691 const Can_HardwareObjectType *hohObj;
\r
693 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), 0x2, CAN_E_UNINIT );
\r
694 VALIDATE_NO_RV( (config != NULL ), 0x2,CAN_E_PARAM_POINTER);
\r
695 VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x2, CAN_E_PARAM_CONTROLLER );
\r
697 canUnit = GET_PRIVATE_DATA(controller);
\r
699 VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), 0x2, CAN_E_TRANSITION );
\r
701 canHw = GetController(cId);
\r
702 canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[cId]);
\r
704 // Start this baby up
\r
705 canHw->CTL0 = BM_INITRQ; // request Init Mode
\r
706 while((canHw->CTL1 & BM_INITAK) == 0) ; // wait until Init Mode is established
\r
708 // set CAN enable bit, deactivate listen-only mode,
\r
709 // use Bus Clock as clock source and select loop back mode on/off
\r
710 canHw->CTL1 = BM_CANE | BM_CLKSRC | (config->Can_Arc_Loopback ? BM_LOOPB : 0x00);
\r
712 // acceptance filters
\r
713 hohObj = canHwConfig->Can_Arc_Hoh;
\r
717 if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)
\r
719 canHw->IDAC = hohObj->CanFilterMaskRef->idam;
\r
720 canHw->IDAR0 = hohObj->CanFilterMaskRef->idar[0];
\r
721 canHw->IDAR1 = hohObj->CanFilterMaskRef->idar[1];
\r
722 canHw->IDAR2 = hohObj->CanFilterMaskRef->idar[2];
\r
723 canHw->IDAR3 = hohObj->CanFilterMaskRef->idar[3];
\r
724 canHw->IDAR4 = hohObj->CanFilterMaskRef->idar[4];
\r
725 canHw->IDAR5 = hohObj->CanFilterMaskRef->idar[5];
\r
726 canHw->IDAR6 = hohObj->CanFilterMaskRef->idar[6];
\r
727 canHw->IDAR7 = hohObj->CanFilterMaskRef->idar[7];
\r
728 canHw->IDMR0 = hohObj->CanFilterMaskRef->idmr[0];
\r
729 canHw->IDMR1 = hohObj->CanFilterMaskRef->idmr[1];
\r
730 canHw->IDMR2 = hohObj->CanFilterMaskRef->idmr[2];
\r
731 canHw->IDMR3 = hohObj->CanFilterMaskRef->idmr[3];
\r
732 canHw->IDMR4 = hohObj->CanFilterMaskRef->idmr[4];
\r
733 canHw->IDMR5 = hohObj->CanFilterMaskRef->idmr[5];
\r
734 canHw->IDMR6 = hohObj->CanFilterMaskRef->idmr[6];
\r
735 canHw->IDMR7 = hohObj->CanFilterMaskRef->idmr[7];
\r
737 }while( !hohObj->Can_Arc_EOL );
\r
739 // Clock calucation
\r
740 // -------------------------------------------------------------------
\r
742 // * 1 TQ = Sclk period( also called SCK )
\r
743 // * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk
\r
744 // ( Fcanclk can come from crystal or from the peripheral dividers )
\r
747 // TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )
\r
748 // TQ is between 8 and 25
\r
749 clock = McuE_GetSystemClock()/2;
\r
751 tqSync = config->CanControllerPropSeg + 1;
\r
752 tq1 = config->CanControllerSeg1 + 1;
\r
753 tq2 = config->CanControllerSeg2 + 1;
\r
754 tq = tqSync + tq1 + tq2;
\r
756 // Check TQ limitations..
\r
757 VALIDATE_DEM_NO_RV(( (tq1>=1) && (tq1<=16)), CAN_E_TIMEOUT );
\r
758 VALIDATE_DEM_NO_RV(( (tq2>=1) && (tq2<=8)), CAN_E_TIMEOUT );
\r
759 VALIDATE_DEM_NO_RV(( (tq>=3) && (tq<25 )), CAN_E_TIMEOUT );
\r
761 canHw->BTR0 = (config->CanControllerPropSeg << 6) | (uint8)(clock/(config->CanControllerBaudRate*1000*tq) - 1); // Prescaler
\r
762 canHw->BTR1 = (config->CanControllerSeg2 << 4) | config->CanControllerSeg1;
\r
764 canHw->CTL0 &= ~BM_INITRQ; // exit Init Mode
\r
765 while((canHw->CTL1 & BM_INITAK) != 0) ;// wait until Normal Mode is established
\r
767 canHw->TBSEL = BM_TX0; // use (only) TX buffer 0
\r
769 canUnit->state = CANIF_CS_STOPPED;
\r
770 Can_EnableControllerInterrupts(cId);
\r
776 Can_ReturnType Can_SetControllerMode( uint8 controller, Can_StateTransitionType transition ) {
\r
779 Can_ReturnType rv = CAN_OK;
\r
780 VALIDATE( (controller < GET_CONTROLLER_CNT()), 0x3, CAN_E_PARAM_CONTROLLER );
\r
782 Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);
\r
784 VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), 0x3, CAN_E_UNINIT );
\r
785 canHw = GetController(controller);
\r
787 switch(transition )
\r
790 canUnit->state = CANIF_CS_STARTED;
\r
792 if (canUnit->lock_cnt == 0){ // REQ CAN196
\r
793 Can_EnableControllerInterrupts(controller);
\r
795 Irq_Restore(state);
\r
798 VALIDATE(canUnit->state == CANIF_CS_SLEEP, 0x3, CAN_E_TRANSITION);
\r
799 canHw->CTL0 &= ~BM_SLPRQ; // Clear Sleep request
\r
800 canHw->CTL0 &= ~BM_WUPE; // Clear Wake up enable
\r
801 canUnit->state = CANIF_CS_STOPPED;
\r
803 case CAN_T_SLEEP: //CAN258, CAN290
\r
804 // Should be reported to DEM but DET is the next best
\r
805 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
806 canHw->CTL0 |= BM_WUPE; // Set wake up enable
\r
807 canHw->CTL0 |= BM_SLPRQ; // Set sleep request
\r
808 canHw->RIER |= BM_WUPI; // Enable wake up irq
\r
809 canUnit->state = CANIF_CS_SLEEP;
\r
813 canUnit->state = CANIF_CS_STOPPED;
\r
814 Can_AbortTx( canHw, canUnit ); // CANIF282
\r
817 // Should be reported to DEM but DET is the next best
\r
818 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
825 void Can_DisableControllerInterrupts( uint8 controller )
\r
828 Can_UnitType *canUnit;
\r
831 VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x4, CAN_E_PARAM_CONTROLLER );
\r
833 canUnit = GET_PRIVATE_DATA(controller);
\r
835 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x4, CAN_E_UNINIT );
\r
838 if(canUnit->lock_cnt > 0 )
\r
840 // Interrupts already disabled
\r
841 canUnit->lock_cnt++;
\r
842 Irq_Restore(state);
\r
845 canUnit->lock_cnt++;
\r
846 Irq_Restore(state);
\r
848 /* Don't try to be intelligent, turn everything off */
\r
849 canHw = GetController(controller);
\r
851 /* Turn off the tx interrupt mailboxes */
\r
854 /* Turn off the bus off/tx warning/rx warning and error and rx */
\r
858 void Can_EnableControllerInterrupts( uint8 controller ) {
\r
860 Can_UnitType *canUnit;
\r
862 const Can_ControllerConfigType *canHwConfig;
\r
863 VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x5, CAN_E_PARAM_CONTROLLER );
\r
865 canUnit = GET_PRIVATE_DATA(controller);
\r
867 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x5, CAN_E_UNINIT );
\r
870 if( canUnit->lock_cnt > 1 )
\r
872 // IRQ should still be disabled so just decrement counter
\r
873 canUnit->lock_cnt--;
\r
874 Irq_Restore(state);
\r
876 } else if (canUnit->lock_cnt == 1)
\r
878 canUnit->lock_cnt = 0;
\r
880 Irq_Restore(state);
\r
882 canHw = GetController(controller);
\r
884 canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]);
\r
886 if( canHwConfig->CanRxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
\r
887 /* Turn on the rx interrupt */
\r
888 canHw->RIER |= BM_RXF;
\r
891 // BusOff here represents all errors and warnings
\r
892 if( canHwConfig->CanBusOffProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
\r
893 /* Turn off the bus off/tx warning/rx warning and error and rx */
\r
894 canHw->RIER |= BM_WUPI | BM_CSCI | BM_OVRI | BM_RXF | BM_RSTAT0 | BM_TSTAT0;
\r
900 static IdrType ConstructIdBytes(Can_IdType id, Can_IdTypeType idType)
\r
904 idr.R[3] = idr.R[2] = idr.R[1] = idr.R[0] = 0;
\r
906 if(idType == CAN_ID_TYPE_EXTENDED) {
\r
910 idr.Bit.id28to21 = id>>21;
\r
911 idr.Bit.id20to18 = id>>18 & 0x07;
\r
912 idr.Bit.id17to15 = id>>15 & 0x07;
\r
913 idr.Bit.id14to7 = id>>7;
\r
914 idr.Bit.id6to0 = id & 0x7F;
\r
915 } else if (idType == CAN_ID_TYPE_STANDARD) {
\r
917 idr.R[1] = id<<5 & 0xE0;
\r
919 // No support for mixed in this processor
\r
926 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo ) {
\r
927 Can_ReturnType rv = CAN_OK;
\r
929 const Can_HardwareObjectType *hohObj;
\r
930 const Can_ControllerConfigType *canHwConfig;
\r
935 VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );
\r
936 VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );
\r
937 VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );
\r
938 VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );
\r
940 hohObj = Can_FindHoh(hth, &controller);
\r
941 if (hohObj == NULL)
\r
944 Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);
\r
946 canHw = GetController(controller);
\r
949 // check for any free box
\r
950 if((canHw->TFLG & BM_TX0) == BM_TX0) {
\r
951 canHw->TBSEL = BM_TX0; // Select mb0
\r
953 idr = ConstructIdBytes(pduInfo->id, hohObj->CanIdType);
\r
955 canHw->TXFG.idr0 = idr.R[0];
\r
956 canHw->TXFG.idr1 = idr.R[1];
\r
957 canHw->TXFG.idr2 = idr.R[2];
\r
958 canHw->TXFG.idr3 = idr.R[3];
\r
960 memcpy((uint8 *)&canHw->TXFG.ds0, pduInfo->sdu, pduInfo->length);
\r
961 canHw->TXFG.dlr = pduInfo->length;
\r
962 canHw->TXFG.tbpr = 0; // Highest prio
\r
965 canHw->TFLG = BM_TX0;
\r
967 canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]);
\r
969 if( (canHwConfig->CanTxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT) &&
\r
970 (canUnit->lock_cnt == 0) ) {
\r
971 /* Turn on the tx interrupt mailboxes */
\r
972 canHw->TIER = BM_TX0; // We only use TX0
\r
975 // Increment statistics
\r
976 #if (USE_CAN_STATISTICS == STD_ON)
\r
977 canUnit->stats.txSuccessCnt++;
\r
980 // Store pdu handle in unit to be used by TxConfirmation
\r
981 canUnit->swPduHandle = pduInfo->swPduHandle;
\r
985 Irq_Restore(state);
\r
990 void Can_MainFunction_Read( void ) {
\r
992 /* NOT SUPPORTED */
\r
995 void Can_MainFunction_BusOff( void ) {
\r
996 /* Bus-off polling events */
\r
998 /* NOT SUPPORTED */
\r
1001 void Can_MainFunction_Wakeup( void ) {
\r
1002 /* Wakeup polling events */
\r
1004 /* NOT SUPPORTED */
\r
1008 void Can_MainFunction_Write( void ) {
\r
1009 /* NOT SUPPORTED */
\r
1012 void Can_MainFunction_Error( void ) {
\r
1013 /* NOT SUPPORTED */
\r
1018 * Get send/receive/error statistics for a controller
\r
1020 * @param controller The controller
\r
1021 * @param stats Pointer to data to copy statistics to
\r
1024 #if (USE_CAN_STATISTICS == STD_ON)
\r
1025 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType *stats)
\r
1027 Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);
\r
1028 *stats = canUnit->stats;
\r
1032 #else // Stub all functions for use in simulator environment
\r
1034 #include "debug.h"
\r
1036 void Can_Init( const Can_ConfigType *Config )
\r
1038 // Do initial configuration of layer here
\r
1041 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config)
\r
1043 // Do initialisation of controller here.
\r
1046 Can_ReturnType Can_SetControllerMode( uint8 Controller, Can_StateTransitionType transition )
\r
1048 // Turn on off controller here depending on transition
\r
1052 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo )
\r
1054 // Write to mailbox on controller here.
\r
1055 DEBUG(DEBUG_MEDIUM, "Can_Write(stub): Received data ");
\r
1056 for (int i = 0; i < pduInfo->length; i++) {
\r
1057 DEBUG(DEBUG_MEDIUM, "%d ", pduInfo->sdu[i]);
\r
1059 DEBUG(DEBUG_MEDIUM, "\n");
\r
1064 extern void CanIf_RxIndication(uint8 Hrh, Can_IdType CanId, uint8 CanDlc, const uint8 *CanSduPtr);
\r
1065 Can_ReturnType Can_ReceiveAFrame()
\r
1067 // This function is not part of autosar but needed to feed the stack with data
\r
1068 // from the mailboxes. Normally this is an interrup but probably not in the PCAN case.
\r
1069 uint8 CanSduData[] = {1,2,1,0,0,0,0,0};
\r
1070 CanIf_RxIndication(CAN_HRH_0_1, 3, 8, CanSduData);
\r
1075 void Can_DisableControllerInterrupts( uint8 controller )
\r
1079 void Can_EnableControllerInterrupts( uint8 controller )
\r
1084 // Hth - for Flexcan, the hardware message box number... .We don't care
\r
1085 void Can_Cbk_CheckWakeup( uint8 controller ){}
\r
1087 void Can_MainFunction_Write( void ){}
\r
1088 void Can_MainFunction_Read( void ){}
\r
1089 void Can_MainFunction_Error( void ){}
\r
1090 void Can_MainFunction_BusOff( void ){}
\r
1091 void Can_MainFunction_Wakeup( void ){}
\r
1093 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType * stat){}
\r