1 /* -------------------------------- Arctic Core ------------------------------
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
6 * This source code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by the
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * -------------------------------- Arctic Core ------------------------------*/
19 #include "stm32f10x.h"
\r
20 #include "stm32f10x_can.h"
23 #include "CanIf_Cbk.h"
24 #if defined(USE_DET)
\r
38 /* CONFIGURATION NOTES
\r
39 * ------------------------------------------------------------------
\r
40 * - CanHandleType must be CAN_ARC_HANDLE_TYPE_BASIC
\r
41 * i.e. CanHandleType=CAN_ARC_HANDLE_TYPE_FULL NOT supported
\r
42 * i.e CanIdValue is NOT supported
\r
43 * - All CanXXXProcessing must be CAN_ARC_PROCESS_TYPE_INTERRUPT
\r
44 * ie CAN_ARC_PROCESS_TYPE_POLLED not supported
\r
45 * - HOH's for Tx are global and Rx are for each controller
\r
48 /* IMPLEMENTATION NOTES
\r
49 * -----------------------------------------------
\r
50 * - A HOH us unique for a controller( not a config-set )
\r
51 * - Hrh's are numbered for each controller from 0
\r
52 * - loopback in HW NOT supported
53 * - Only one transmit mailbox is used because otherwise
54 * we cannot use tx_confirmation since there is no way to know
55 * which mailbox caused the tx interrupt. TP will need this feature.
56 * - Sleep,wakeup not fully implemented since other modules lack functionality
\r
60 * -----------------------------------------------
\r
61 * - Can Hardware unit - One or multiple Can controllers of the same type.
\r
62 * - Hrh - HOH with receive definitions
\r
63 * - Hth - HOH with transmit definitions
\r
67 typedef CAN_TypeDef CAN_HW_t;
\r
68 //-------------------------------------------------------------------
\r
70 #define GET_CONTROLLER_CONFIG(_controller) \
\r
71 &Can_Global.config->CanConfigSet->CanController[(_controller)]
\r
73 #define GET_CALLBACKS() \
\r
74 (Can_Global.config->CanConfigSet->CanCallbacks)
\r
76 #define GET_PRIVATE_DATA(_controller) \
\r
77 &CanUnit[_controller]
\r
79 #define GET_CONTROLLER_CNT() (CAN_CONTROLLER_CNT)
\r
81 //-------------------------------------------------------------------
\r
83 #if ( CAN_DEV_ERROR_DETECT == STD_ON )
\r
84 #define VALIDATE(_exp,_api,_err ) \
\r
86 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
87 return CAN_NOT_OK; \
\r
90 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
92 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
96 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)
\r
98 #define VALIDATE(_exp,_api,_err )
\r
99 #define VALIDATE_NO_RV(_exp,_api,_err )
\r
100 #define DET_REPORTERROR(_x,_y,_z,_q)
\r
104 #define VALIDATE_DEM_NO_RV(_exp,_err ) \
106 Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED); \
110 #define VALIDATE_DEM_NO_RV(_exp,_err )
113 //-------------------------------------------------------------------
\r
119 } Can_DriverStateType;
\r
121 // Mapping between HRH and Controller//HOH
\r
122 typedef struct Can_Arc_ObjectHOHMapStruct
\r
124 CanControllerIdType CanControllerRef; // Reference to controller
\r
125 const Can_HardwareObjectType* CanHOHRef; // Reference to HOH.
\r
126 } Can_Arc_ObjectHOHMapType;
\r
128 /* Type for holding global information used by the driver */
\r
130 Can_DriverStateType initRun;
\r
133 const Can_ConfigType *config;
\r
135 // One bit for each channel that is configured.
\r
136 // Used to determine if validity of a channel
\r
138 // 0 - NOT configured
\r
140 // Maps the a channel id to a configured channel id
\r
141 uint8 channelMap[CAN_CONTROLLER_CNT];
\r
143 // This is a map that maps the HTH:s with the controller and Hoh. It is built
\r
144 // during Can_Init and is used to make things faster during a transmit.
\r
145 Can_Arc_ObjectHOHMapType CanHTHMap[NUM_OF_HTHS];
\r
149 Can_GlobalType Can_Global =
\r
151 .initRun = CAN_UNINIT,
\r
154 /* Type for holding information about each controller */
\r
156 CanIf_ControllerModeType state;
\r
160 Can_Arc_StatisticsType stats;
\r
162 // Data stored for Txconfirmation callbacks to CanIf
\r
163 PduIdType swPduHandle; //
\r
166 Can_UnitType CanUnit[CAN_CONTROLLER_CNT] =
\r
169 .state = CANIF_CS_UNINIT,
\r
172 .state = CANIF_CS_UNINIT,
\r
176 //-------------------------------------------------------------------
\r
177 static CAN_HW_t * GetController(int unit)
179 return ((CAN_HW_t *)(CAN1_BASE + unit*0x400));
182 //-------------------------------------------------------------------
\r
184 * Function that finds the Hoh( HardwareObjectHandle ) from a Hth
\r
185 * A HTH may connect to one or several HOH's. Just find the first one.
\r
187 * @param hth The transmit handle
\r
188 * @returns Ptr to the Hoh
\r
190 static const Can_HardwareObjectType * Can_FindHoh( Can_Arc_HTHType hth , uint32* controller)
\r
192 const Can_HardwareObjectType *hohObj;
\r
193 const Can_Arc_ObjectHOHMapType *map;
\r
194 const Can_ControllerConfigType *canHwConfig;
\r
196 map = &Can_Global.CanHTHMap[hth];
\r
198 // Verify that this is the correct map
\r
199 if (map->CanHOHRef->CanObjectId != hth)
\r
201 DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);
\r
204 canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[map->CanControllerRef]);
\r
206 hohObj = map->CanHOHRef;
\r
208 // Verify that this is the correct Hoh type
\r
209 if ( hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
\r
211 *controller = map->CanControllerRef;
\r
215 DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);
\r
220 //-------------------------------------------------------------------
\r
222 static void Can_RxIsr( int unit );
223 static void Can_TxIsr( int unit );
224 static void Can_ErrIsr( int unit );
\r
226 void Can_1_RxIsr( void ) { Can_RxIsr(CAN_CTRL_1); }
227 void Can_2_RxIsr( void ) { Can_RxIsr(CAN_CTRL_2); }
229 void Can_1_TxIsr( void ) { Can_TxIsr(CAN_CTRL_1); }
230 void Can_2_TxIsr( void ) { Can_TxIsr(CAN_CTRL_2); }
232 void Can_1_ErrIsr( void ) { Can_ErrIsr(CAN_CTRL_1); }
233 void Can_2_ErrIsr( void ) { Can_ErrIsr(CAN_CTRL_2); }
236 //-------------------------------------------------------------------
\r
238 // Uses 25.4.5.1 Transmission Abort Mechanism
239 static void Can_AbortTx( CAN_HW_t *canHw, Can_UnitType *canUnit ) {
240 // Disable Transmit irq
242 // check if mb's empty
244 // Abort all pending mb's
246 // Wait for mb's being emptied
250 * Hardware wake ISR for CAN
252 * @param unit CAN controller number( from 0 )
254 static void Can_WakeIsr( int unit ) {
255 if (GET_CALLBACKS()->ControllerWakeup != NULL)
257 GET_CALLBACKS()->ControllerWakeup(unit);
260 Can_SetControllerMode(unit, CAN_T_STOP);
262 // TODO EcuM_CheckWakeup();
266 * Hardware error ISR for CAN
\r
268 * @param unit CAN controller number( from 0 )
\r
270 static void Can_ErrIsr( int unit ) {
\r
271 CAN_HW_t *canHw = GetController(unit);
\r
272 Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
273 Can_Arc_ErrorType err;
\r
277 if(SET == CAN_GetITStatus(canHw, CAN_IT_WKU)){
\r
279 CAN_ClearITPendingBit(canHw, CAN_IT_WKU);
282 if(SET == CAN_GetITStatus(canHw, CAN_IT_BOF)){
283 canUnit->stats.boffCnt++;
284 if (GET_CALLBACKS()->ControllerBusOff != NULL)
286 GET_CALLBACKS()->ControllerBusOff(unit);
288 Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272
290 Can_AbortTx( canHw, canUnit ); // CANIF273
293 CAN_ClearITPendingBit(canHw, CAN_IT_BOF);
298 if (GET_CALLBACKS()->Arc_Error != NULL)
300 GET_CALLBACKS()->Arc_Error( unit, err );
305 //-------------------------------------------------------------------
\r
308 * ISR for CAN. Normal Rx/operation
\r
310 * @param unit CAN controller number( from 0 )
\r
312 static void Can_RxIsr(int unit) {
\r
314 CAN_HW_t *canHw= GetController(unit);
\r
315 const Can_ControllerConfigType *canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]);
\r
316 Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
\r
317 const Can_HardwareObjectType *hohObj;
321 RxMessage.StdId=0x00;
322 RxMessage.ExtId=0x00;
326 RxMessage.Data[0]=0x00;
327 RxMessage.Data[1]=0x00;
328 CAN_Receive(canHw,CAN_FIFO0, &RxMessage);
\r
330 // Loop over all the Hoh's
\r
331 hohObj= canHwConfig->Can_Arc_Hoh;
\r
336 if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)
\r
340 // According to autosar MSB shuould be set if extended
\r
341 if (RxMessage.IDE != CAN_ID_STD) {
342 id = RxMessage.ExtId;
345 id = RxMessage.StdId;
348 if (GET_CALLBACKS()->RxIndication != NULL)
\r
350 GET_CALLBACKS()->RxIndication(hohObj->CanObjectId,
\r
353 (uint8 *)&RxMessage.Data[0] ); // Next layer will copy
\r
355 // Increment statistics
\r
356 canUnit->stats.rxSuccessCnt++;
\r
358 } while ( !hohObj->Can_Arc_EOL);
\r
362 * ISR for CAN. Normal Tx operation
364 * @param unit CAN controller number( from 0 )
366 static void Can_TxIsr(int unit) {
367 CAN_HW_t *canHw= GetController(unit);
368 const Can_ControllerConfigType *canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]);
369 Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
370 const Can_HardwareObjectType *hohObj;
372 // Loop over all the Hoh's
373 hohObj= canHwConfig->Can_Arc_Hoh;
378 if (hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
380 if (GET_CALLBACKS()->TxConfirmation != NULL)
382 GET_CALLBACKS()->TxConfirmation(canUnit->swPduHandle);
384 canUnit->swPduHandle = 0; // Is this really necessary ??
386 // Clear Tx interrupt
387 CAN_ClearITPendingBit(canHw,CAN_IT_RQCP0);
388 CAN_ClearITPendingBit(canHw,CAN_IT_RQCP1);
389 CAN_ClearITPendingBit(canHw,CAN_IT_RQCP2);
391 } while ( !hohObj->Can_Arc_EOL);
394 //-------------------------------------------------------------------
\r
396 #define INSTALL_HANDLERS(_can_name,_sce,_rx,_tx) \
\r
398 ISR_INSTALL_ISR2( "Can_Err", _can_name ## _ErrIsr, _sce, 2, 0 ); \
399 ISR_INSTALL_ISR2( "Can_Rx", _can_name ## _RxIsr, _rx, 2, 0 ); \
400 ISR_INSTALL_ISR2( "Can_Tx", _can_name ## _TxIsr, _tx, 2, 0 ); \
403 // This initiates ALL can controllers
\r
404 void Can_Init( const Can_ConfigType *config ) {
\r
405 Can_UnitType *canUnit;
\r
406 const Can_ControllerConfigType *canHwConfig;
\r
409 VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), 0x0, CAN_E_TRANSITION );
\r
410 VALIDATE_NO_RV( (config != NULL ), 0x0, CAN_E_PARAM_POINTER );
\r
413 Can_Global.config = config;
\r
414 Can_Global.initRun = CAN_READY;
\r
416 for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
417 canHwConfig = GET_CONTROLLER_CONFIG(configId);
\r
418 ctlrId = canHwConfig->CanControllerId;
\r
420 // Assign the configuration channel used later..
\r
421 Can_Global.channelMap[canHwConfig->CanControllerId] = configId;
\r
422 Can_Global.configured |= (1<<ctlrId);
\r
424 canUnit = GET_PRIVATE_DATA(ctlrId);
\r
425 canUnit->state = CANIF_CS_STOPPED;
\r
427 canUnit->lock_cnt = 0;
\r
430 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
433 // Could install handlers depending on HW objects to trap more errors
435 switch( canHwConfig->CanControllerId ) {
438 INSTALL_HANDLERS(Can_1, CAN1_SCE_IRQn, USB_LP_CAN1_RX0_IRQn, USB_HP_CAN1_TX_IRQn); break;
441 INSTALL_HANDLERS(Can_1, CAN1_SCE_IRQn, CAN1_RX0_IRQn, CAN1_TX_IRQn); break;
443 INSTALL_HANDLERS(Can_2, CAN2_SCE_IRQn, CAN2_RX0_IRQn, CAN2_TX_IRQn); break;
449 Can_InitController(ctlrId, canHwConfig);
\r
451 // Loop through all Hoh:s and map them into the HTHMap
\r
452 const Can_HardwareObjectType* hoh;
\r
453 hoh = canHwConfig->Can_Arc_Hoh;
\r
459 if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
\r
461 Can_Global.CanHTHMap[hoh->CanObjectId].CanControllerRef = canHwConfig->CanControllerId;
\r
462 Can_Global.CanHTHMap[hoh->CanObjectId].CanHOHRef = hoh;
\r
464 } while (!hoh->Can_Arc_EOL);
\r
469 // Unitialize the module
\r
472 Can_UnitType *canUnit;
\r
473 const Can_ControllerConfigType *canHwConfig;
\r
476 for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
477 canHwConfig = GET_CONTROLLER_CONFIG(configId);
\r
478 ctlrId = canHwConfig->CanControllerId;
\r
480 canUnit = GET_PRIVATE_DATA(ctlrId);
\r
481 canUnit->state = CANIF_CS_UNINIT;
\r
483 Can_DisableControllerInterrupts(ctlrId);
\r
485 canUnit->lock_cnt = 0;
\r
488 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
\r
491 Can_Global.config = NULL;
\r
492 Can_Global.initRun = CAN_UNINIT;
\r
497 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config)
505 Can_UnitType *canUnit;
\r
506 uint8 cId = controller;
\r
507 const Can_ControllerConfigType *canHwConfig;
\r
508 const Can_HardwareObjectType *hohObj;
\r
510 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), 0x2, CAN_E_UNINIT );
\r
511 VALIDATE_NO_RV( (config != NULL ), 0x2,CAN_E_PARAM_POINTER);
\r
512 VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x2, CAN_E_PARAM_CONTROLLER );
\r
514 canUnit = GET_PRIVATE_DATA(controller);
\r
516 VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), 0x2, CAN_E_TRANSITION );
\r
518 canHw = GetController(cId);
\r
519 canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[cId]);
\r
521 // Start this baby up
524 /* CAN filter init. We set up two filters - one for the master (CAN1) and
525 * one for the slave (CAN2)
527 * CAN_SlaveStartBank(n) denotes which filter is the first of the slave.
529 * The filter registers reside in CAN1 and is shared to CAN2, so we only need
530 * to set up this once.
533 // We let all frames in and do the filtering in software.
534 CAN_FilterInitTypeDef CAN_FilterInitStructure;
535 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
536 CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
537 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
538 CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
539 CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
540 CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
541 CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
542 CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
544 // Init filter 0 (CAN1/master)
545 CAN_FilterInitStructure.CAN_FilterNumber=0;
546 CAN_FilterInit(&CAN_FilterInitStructure);
548 // Init filter 1 (CAN2/slave)
549 CAN_FilterInitStructure.CAN_FilterNumber=1;
550 CAN_FilterInit(&CAN_FilterInitStructure);
552 // Set which filter to use for CAN2.
553 CAN_SlaveStartBank(1);
555 // acceptance filters
556 hohObj = canHwConfig->Can_Arc_Hoh;
560 if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)
564 }while( !hohObj->Can_Arc_EOL );
\r
566 // Clock calucation
\r
567 // -------------------------------------------------------------------
\r
569 // * 1 TQ = Sclk period( also called SCK )
\r
570 // * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk
\r
571 // ( Fcanclk can come from crystal or from the peripheral dividers )
\r
574 // TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )
\r
575 // TQ is between 8 and 25
\r
576 clock = McuE_GetSystemClock()/2;
578 tqSync = config->CanControllerPropSeg + 1;
579 tq1 = config->CanControllerSeg1 + 1;
\r
580 tq2 = config->CanControllerSeg2 + 1;
\r
581 tq = tqSync + tq1 + tq2;
583 CAN_InitTypeDef CAN_InitStructure;
584 CAN_StructInit(&CAN_InitStructure);
587 CAN_InitStructure.CAN_TTCM=DISABLE;
588 CAN_InitStructure.CAN_ABOM=ENABLE;
589 CAN_InitStructure.CAN_AWUM=ENABLE;
590 CAN_InitStructure.CAN_NART=DISABLE;
591 CAN_InitStructure.CAN_RFLM=DISABLE;
592 CAN_InitStructure.CAN_TXFP=DISABLE;
593 if(config->Can_Arc_Loopback){
594 CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
596 CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
599 CAN_InitStructure.CAN_SJW=config->CanControllerPropSeg;
600 CAN_InitStructure.CAN_BS1=config->CanControllerSeg1;
601 CAN_InitStructure.CAN_BS2=config->CanControllerSeg2;
602 CAN_InitStructure.CAN_Prescaler= clock/(config->CanControllerBaudRate*1000*tq);
604 if(CANINITOK != CAN_Init(canHw,&CAN_InitStructure))
609 canUnit->state = CANIF_CS_STOPPED;
\r
610 Can_EnableControllerInterrupts(cId);
\r
616 Can_ReturnType Can_SetControllerMode( uint8 controller, Can_StateTransitionType transition ) {
\r
619 Can_ReturnType rv = CAN_OK;
\r
620 VALIDATE( (controller < GET_CONTROLLER_CNT()), 0x3, CAN_E_PARAM_CONTROLLER );
\r
622 Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);
\r
624 VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), 0x3, CAN_E_UNINIT );
\r
625 canHw = GetController(controller);
\r
627 switch(transition )
\r
630 canUnit->state = CANIF_CS_STARTED;
\r
632 if (canUnit->lock_cnt == 0){ // REQ CAN196
\r
633 Can_EnableControllerInterrupts(controller);
638 VALIDATE(canUnit->state == CANIF_CS_SLEEP, 0x3, CAN_E_TRANSITION);
640 canUnit->state = CANIF_CS_STOPPED;
642 case CAN_T_SLEEP: //CAN258, CAN290
\r
643 // Should be reported to DEM but DET is the next best
\r
644 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
646 canUnit->state = CANIF_CS_SLEEP;
650 canUnit->state = CANIF_CS_STOPPED;
\r
651 Can_AbortTx( canHw, canUnit ); // CANIF282
\r
654 // Should be reported to DEM but DET is the next best
\r
655 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
662 void Can_DisableControllerInterrupts( uint8 controller )
\r
665 Can_UnitType *canUnit;
\r
668 VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x4, CAN_E_PARAM_CONTROLLER );
\r
670 canUnit = GET_PRIVATE_DATA(controller);
\r
672 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x4, CAN_E_UNINIT );
\r
675 if(canUnit->lock_cnt > 0 )
\r
677 // Interrupts already disabled
\r
678 canUnit->lock_cnt++;
\r
682 canUnit->lock_cnt++;
\r
685 /* Don't try to be intelligent, turn everything off */
\r
686 canHw = GetController(controller);
\r
688 /* Turn off the tx interrupt mailboxes */
\r
689 CAN_ITConfig(canHw, CAN_IT_TME, DISABLE);
\r
691 /* Turn off the bus off/tx warning/rx warning and error and rx */
\r
692 CAN_ITConfig(canHw, CAN_IT_FMP0 | CAN_IT_BOF | CAN_IT_ERR | CAN_IT_WKU, DISABLE);
695 void Can_EnableControllerInterrupts( uint8 controller ) {
697 Can_UnitType *canUnit;
\r
699 const Can_ControllerConfigType *canHwConfig;
\r
700 VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x5, CAN_E_PARAM_CONTROLLER );
\r
702 canUnit = GET_PRIVATE_DATA(controller);
\r
704 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x5, CAN_E_UNINIT );
\r
707 if( canUnit->lock_cnt > 1 )
\r
709 // IRQ should still be disabled so just decrement counter
\r
710 canUnit->lock_cnt--;
\r
713 } else if (canUnit->lock_cnt == 1)
\r
715 canUnit->lock_cnt = 0;
\r
719 canHw = GetController(controller);
\r
721 canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]);
\r
723 if( canHwConfig->CanRxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
\r
724 /* Turn on the rx interrupt */
\r
725 CAN_ITConfig(canHw, CAN_IT_FMP0, ENABLE);
727 if( canHwConfig->CanTxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
728 /* Turn on the tx interrupt mailboxes */
729 CAN_ITConfig(canHw, CAN_IT_TME, ENABLE);
732 // BusOff here represents all errors and warnings
\r
733 if( canHwConfig->CanBusOffProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
\r
734 /* Turn on the bus off/tx warning/rx warning and error and rx */
735 CAN_ITConfig(canHw, CAN_IT_BOF | CAN_IT_ERR | CAN_IT_WKU, ENABLE);
741 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo ) {
\r
742 Can_ReturnType rv = CAN_OK;
\r
744 const Can_HardwareObjectType *hohObj;
\r
745 const Can_ControllerConfigType *canHwConfig;
749 VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );
\r
750 VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );
\r
751 VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );
\r
752 VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );
\r
754 hohObj = Can_FindHoh(hth, &controller);
\r
755 if (hohObj == NULL)
\r
758 Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);
\r
760 canHw = GetController(controller);
\r
765 TxMessage.RTR=CAN_RTR_DATA;
766 TxMessage.DLC=pduInfo->length;
768 memcpy(TxMessage.Data, pduInfo->sdu, pduInfo->length);
770 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
771 TxMessage.IDE=CAN_ID_EXT;
772 TxMessage.ExtId=pduInfo->id;
774 TxMessage.IDE=CAN_ID_STD;
775 TxMessage.StdId=pduInfo->id;
778 // check for any free box
\r
779 if(CAN_Transmit(canHw,&TxMessage) != CAN_NO_MB) {
780 canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]);
782 if( canHwConfig->CanTxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
783 /* Turn on the tx interrupt mailboxes */
784 CAN_ITConfig(canHw,CAN_IT_TME, ENABLE);
787 // Increment statistics
788 canUnit->stats.txSuccessCnt++;
\r
790 // Store pdu handle in unit to be used by TxConfirmation
\r
791 canUnit->swPduHandle = pduInfo->swPduHandle;
\r
800 void Can_MainFunction_Read( void ) {
\r
802 /* NOT SUPPORTED */
\r
805 void Can_MainFunction_BusOff( void ) {
\r
806 /* Bus-off polling events */
\r
808 /* NOT SUPPORTED */
\r
811 void Can_MainFunction_Wakeup( void ) {
\r
812 /* Wakeup polling events */
\r
814 /* NOT SUPPORTED */
\r
819 * Get send/receive/error statistics for a controller
\r
821 * @param controller The controller
\r
822 * @param stats Pointer to data to copy statistics to
\r
825 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType *stats)
\r
827 Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);
\r
828 *stats = canUnit->stats;
\r
831 #else // Stub all functions for use in simulator environment
\r
835 void Can_Init( const Can_ConfigType *Config )
\r
837 // Do initial configuration of layer here
\r
840 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config)
\r
842 // Do initialisation of controller here.
\r
845 Can_ReturnType Can_SetControllerMode( uint8 Controller, Can_StateTransitionType transition )
\r
847 // Turn on off controller here depending on transition
\r
851 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo )
\r
853 // Write to mailbox on controller here.
\r
854 DEBUG(DEBUG_MEDIUM, "Can_Write(stub): Received data ");
\r
855 for (int i = 0; i < pduInfo->length; i++) {
\r
856 DEBUG(DEBUG_MEDIUM, "%d ", pduInfo->sdu[i]);
\r
858 DEBUG(DEBUG_MEDIUM, "\n");
\r
863 extern void CanIf_RxIndication(uint8 Hrh, Can_IdType CanId, uint8 CanDlc, const uint8 *CanSduPtr);
\r
864 Can_ReturnType Can_ReceiveAFrame()
\r
866 // This function is not part of autosar but needed to feed the stack with data
\r
867 // from the mailboxes. Normally this is an interrup but probably not in the PCAN case.
\r
868 uint8 CanSduData[] = {1,2,1,0,0,0,0,0};
\r
869 CanIf_RxIndication(CAN_HRH_0_1, 3, 8, CanSduData);
\r
874 void Can_DisableControllerInterrupts( uint8 controller )
\r
878 void Can_EnableControllerInterrupts( uint8 controller )
\r
883 // Hth - for Flexcan, the hardware message box number... .We don't care
\r
884 void Can_Cbk_CheckWakeup( uint8 controller ){}
\r
886 void Can_MainFunction_Write( void ){}
\r
887 void Can_MainFunction_Read( void ){}
\r
888 void Can_MainFunction_BusOff( void ){}
\r
889 void Can_MainFunction_Wakeup( void ){}
\r
891 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType * stat){}
\r