/** * ISR for CAN. Normal Tx operation * * @param unit CAN controller number( from 0 ) */ static void Can_TxIsr(int unit) { CAN_HW_t *canHw= GetController(unit); const Can_ControllerConfigType *canHwConfig= CAN_GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]); Can_UnitType *canUnit = CAN_GET_PRIVATE_DATA(unit); const Can_HardwareObjectType *hohObj; // Loop over all the Hoh's hohObj= canHwConfig->Can_Hoh; --hohObj; do { ++hohObj; if (hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT) { CanIf_TxConfirmation(canUnit->swPduHandle); canUnit->swPduHandle = 0; // Is this really necessary ?? // Clear Tx interrupt CAN_ClearITPendingBit(canHw,CAN_IT_RQCP0); CAN_ClearITPendingBit(canHw,CAN_IT_RQCP1); CAN_ClearITPendingBit(canHw,CAN_IT_RQCP2); } } while ( !hohObj->Can_EOL); }
EXPORT void Can_Hw_DisableControllerInterrupts(uint8 controller) { imask_t state; Can_UnitType *canUnit; CAN_HW_t *canHw; canUnit = CAN_GET_PRIVATE_DATA(controller); VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x4, CAN_E_UNINIT ); Irq_Save(state); if(canUnit->lock_cnt > 0 ) { // Interrupts already disabled canUnit->lock_cnt++; Irq_Restore(state); return; } canUnit->lock_cnt++; Irq_Restore(state); /* Don't try to be intelligent, turn everything off */ canHw = GetController(controller); /* Turn off the tx interrupt mailboxes */ CAN_ITConfig(canHw, CAN_IT_TME, DISABLE); /* Turn off the bus off/tx warning/rx warning and error and rx */ CAN_ITConfig(canHw, CAN_IT_FMP0 | CAN_IT_BOF | CAN_IT_ERR | CAN_IT_WKU, DISABLE); }
/** * Hardware error ISR for CAN * * @param unit CAN controller number( from 0 ) */ static void Can_ErrIsr( int unit ) { CAN_HW_t *canHw = GetController(unit); Can_UnitType *canUnit = CAN_GET_PRIVATE_DATA(unit); Can_Arc_ErrorType err; err.R = 0; // Check wake up if(SET == CAN_GetITStatus(canHw, CAN_IT_WKU)){ Can_WakeIsr(unit); CAN_ClearITPendingBit(canHw, CAN_IT_WKU); } if(SET == CAN_GetITStatus(canHw, CAN_IT_BOF)){ canUnit->stats.boffCnt++; CanIf_ControllerBusOff(unit); Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272 Can_AbortTx( canHw, canUnit ); // CANIF273 // Clear int CAN_ClearITPendingBit(canHw, CAN_IT_BOF); } if (err.R != 0) { CanIf_Arc_Error( unit, err ); } }
EXPORT void Can_InitController(uint8 Controller,const Can_ControllerConfigType* Config) { Can_UnitType *canUnit; StatusType ercd; canUnit = CAN_GET_PRIVATE_DATA(Controller); #if(CAN_DEV_ERROR_DETECT == STD_ON) if(CAN_UNINIT == Can_Global.driverState) { Det_ReportError(MODULE_ID_CAN,0,CAN_INITCONTROLLER_SERVICE_ID,CAN_E_UNINIT); return; } if(NULL == Config) { Det_ReportError(MODULE_ID_CAN,0,CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_POINTER); return; } if(Controller >= CAN_CONTROLLER_CNT) { Det_ReportError(MODULE_ID_CAN,0,CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_CONTROLLER); return; } if(canUnit->state!=CANIF_CS_STOPPED) { Det_ReportError(MODULE_ID_CAN,0,CAN_INITCONTROLLER_SERVICE_ID,CAN_E_TRANSITION); return; } #endif ercd = Can_Hw_InitController(Controller,Config); if(ercd != E_OK) { return; } canUnit->state = CANIF_CS_STOPPED; Can_EnableControllerInterrupts(Controller); }
// Unitialize the module EXPORT void Can_DeInit() { Can_UnitType *canUnit; int configId; const Can_ControllerConfigType *canHwConfig; uint32 ctlrId; for (configId=0; configId < CAN_CTRL_CONFIG_CNT; configId++) { canHwConfig = CAN_GET_CONTROLLER_CONFIG(configId); ctlrId = canHwConfig->CanControllerId; canUnit = CAN_GET_PRIVATE_DATA(ctlrId); canUnit->state = CANIF_CS_UNINIT; Can_DisableControllerInterrupts(ctlrId); canUnit->lock_cnt = 0; // Clear stats memset(&canUnit->stats, 0, sizeof(Can_StatisticsType)); } Can_Global.config = NULL; Can_Global.driverState = CAN_UNINIT; return; }
/* ####################### FUNCTIONs ########################### */ EXPORT void Can_Init(const Can_ConfigType* Config) { Can_UnitType *canUnit; const Can_ControllerConfigType *canHwConfig; const Can_HardwareObjectType* hoh; uint8 ctlrId; int configId; #if(CAN_DEV_ERROR_DETECT == STD_ON) if(CAN_UNINIT != Can_Global.driverState) { Det_ReportError(MODULE_ID_CAN,0,CAN_INIT_SERVICE_ID,CAN_E_TRANSITION); return; } if(NULL == Config) { Det_ReportError(MODULE_ID_CAN,0,CAN_INIT_SERVICE_ID,CAN_E_PARAM_POINTER); return; } #endif /* save config */ Can_Global.config = Config; Can_Global.driverState = CAN_READY; Can_Hw_Init(Config); for (configId=0; configId < CAN_CTRL_CONFIG_CNT; configId++) { canHwConfig = CAN_GET_CONTROLLER_CONFIG(configId); ctlrId = canHwConfig->CanControllerId; // Assign the configuration channel used later.. Can_Global.channelMap[ctlrId] = configId; Can_Global.configured |= (1<<ctlrId); canUnit = CAN_GET_PRIVATE_DATA(ctlrId); canUnit->state = CANIF_CS_STOPPED; canUnit->lock_cnt = 0; // Clear stats memset(&canUnit->stats, 0, sizeof(Can_StatisticsType)); //This can be done by CanIf //Can_InitController(ctlrId, canHwConfig); // Loop through all Hohs and map them into the HTHMap hoh = canHwConfig->Can_Hoh; hoh--; do { hoh++; if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT) { Can_Global.CanHTHMap[hoh->CanObjectId].CanControllerRef = canHwConfig->CanControllerId; Can_Global.CanHTHMap[hoh->CanObjectId].CanHOHRef = hoh; } } while (!hoh->Can_EOL); } }
EXPORT Can_ReturnType Can_Hw_Write( Can_HwHandleType/* Can_HTHType */ hth, const Can_PduType *pduInfo ) { Can_ReturnType rv = CAN_OK; CAN_HW_t *canHw; const Can_HardwareObjectType *hohObj; const Can_ControllerConfigType *canHwConfig; uint32 controller; imask_t state; hohObj = Can_FindHoh(hth, &controller); if (hohObj == NULL) return CAN_NOT_OK; Can_UnitType *canUnit = CAN_GET_PRIVATE_DATA(controller); canHw = GetController(controller); Irq_Save(state); CanTxMsg TxMessage; TxMessage.RTR=CAN_RTR_DATA; TxMessage.DLC=pduInfo->length; memcpy(TxMessage.Data, pduInfo->sdu, pduInfo->length); if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) { TxMessage.IDE=CAN_ID_EXT; TxMessage.ExtId=pduInfo->id; } else { TxMessage.IDE=CAN_ID_STD; TxMessage.StdId=pduInfo->id; } // check for any free box if(CAN_Transmit(canHw,&TxMessage) != CAN_NO_MB) { canHwConfig = CAN_GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]); if( canHwConfig->CanTxProcessing == CAN_PROCESS_TYPE_INTERRUPT ) { /* Turn on the tx interrupt mailboxes */ CAN_ITConfig(canHw,CAN_IT_TME, ENABLE); } // Increment statistics canUnit->stats.txSuccessCnt++; // Store pdu handle in unit to be used by TxConfirmation canUnit->swPduHandle = pduInfo->swPduHandle; } else { rv = CAN_BUSY; } Irq_Restore(state); return rv; }
/** * ISR for CAN. Normal Rx/operation * * @param unit CAN controller number( from 0 ) */ static void Can_RxIsr(int unit) { CAN_HW_t *canHw= GetController(unit); const Can_ControllerConfigType *canHwConfig= CAN_GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]); Can_UnitType *canUnit = CAN_GET_PRIVATE_DATA(unit); const Can_HardwareObjectType *hohObj; CanRxMsg RxMessage; RxMessage.StdId=0x00; RxMessage.ExtId=0x00; RxMessage.IDE=0; RxMessage.DLC=0; RxMessage.FMI=0; RxMessage.Data[0]=0x00; RxMessage.Data[1]=0x00; CAN_Receive(canHw,CAN_FIFO0, &RxMessage); // Loop over all the Hoh's hohObj= canHwConfig->Can_Hoh; --hohObj; do { ++hohObj; if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) { Can_IdType id=0; // According to autosar MSB shuould be set if extended if (RxMessage.IDE != CAN_ID_STD) { id = RxMessage.ExtId; id |= 0x80000000; } else { id = RxMessage.StdId; } CanIf_RxIndication(hohObj->CanObjectId, id, RxMessage.DLC, (uint8 *)&RxMessage.Data[0] ); // Next layer will copy // Increment statistics canUnit->stats.rxSuccessCnt++; } } while ( !hohObj->Can_EOL); }
EXPORT void Can_Hw_EnableControllerInterrupts( uint8 controller ) { imask_t state; Can_UnitType *canUnit; CAN_HW_t *canHw; const Can_ControllerConfigType *canHwConfig; canUnit = CAN_GET_PRIVATE_DATA(controller); VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x5, CAN_E_UNINIT ); Irq_Save(state); if( canUnit->lock_cnt > 1 ) { // IRQ should still be disabled so just decrement counter canUnit->lock_cnt--; Irq_Restore(state); return; } else if (canUnit->lock_cnt == 1) { canUnit->lock_cnt = 0; } Irq_Restore(state); canHw = GetController(controller); canHwConfig = CAN_GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]); if( canHwConfig->CanRxProcessing == CAN_PROCESS_TYPE_INTERRUPT ) { /* Turn on the rx interrupt */ CAN_ITConfig(canHw, CAN_IT_FMP0, ENABLE); } if( canHwConfig->CanTxProcessing == CAN_PROCESS_TYPE_INTERRUPT ) { /* Turn on the tx interrupt mailboxes */ CAN_ITConfig(canHw, CAN_IT_TME, ENABLE); } // BusOff here represents all errors and warnings if( canHwConfig->CanBusOffProcessing == CAN_PROCESS_TYPE_INTERRUPT ) { /* Turn on the bus off/tx warning/rx warning and error and rx */ CAN_ITConfig(canHw, CAN_IT_BOF | CAN_IT_ERR | CAN_IT_WKU, ENABLE); } return; }
EXPORT Can_ReturnType Can_Hw_SetControllerMode(uint8 controller,Can_StateTransitionType transition) { imask_t state; CAN_HW_t *canHw; Can_ReturnType rv = CAN_OK; Can_UnitType *canUnit = CAN_GET_PRIVATE_DATA(controller); VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), 0x3, CAN_E_UNINIT ); canHw = GetController(controller); switch(transition ) { case CAN_T_START: canUnit->state = CANIF_CS_STARTED; Irq_Save(state); if (canUnit->lock_cnt == 0){ // REQ CAN196 Can_EnableControllerInterrupts(controller); } Irq_Restore(state); break; case CAN_T_WAKEUP: VALIDATE(canUnit->state == CANIF_CS_SLEEP, 0x3, CAN_E_TRANSITION); CAN_WakeUp(canHw); canUnit->state = CANIF_CS_STOPPED; break; case CAN_T_SLEEP: //CAN258, CAN290 // Should be reported to DEM but DET is the next best VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION); CAN_Sleep(canHw); canUnit->state = CANIF_CS_SLEEP; break; case CAN_T_STOP: // Stop canUnit->state = CANIF_CS_STOPPED; Can_AbortTx( canHw, canUnit ); // CANIF282 break; default: // Should be reported to DEM but DET is the next best VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION); break; } return rv; }
EXPORT Std_ReturnType Can_Hw_InitController(uint8 controller,const Can_ControllerConfigType* config) { CAN_HW_t *canHw; uint8_t tq; uint8_t tqSync; uint8_t tq1; uint8_t tq2; uint32_t clock; Can_UnitType *canUnit; uint8 cId = controller; const Can_ControllerConfigType *canHwConfig; const Can_HardwareObjectType *hohObj; canUnit = CAN_GET_PRIVATE_DATA(controller); canHw = GetController(cId); canHwConfig = CAN_GET_CONTROLLER_CONFIG(Can_Global.channelMap[cId]); // Start this baby up CAN_DeInit(canHw); /* CAN filter init. We set up two filters - one for the master (CAN1) and * one for the slave (CAN2) * * CAN_SlaveStartBank(n) denotes which filter is the first of the slave. * * The filter registers reside in CAN1 and is shared to CAN2, so we only need * to set up this once. */ // We let all frames in and do the filtering in software. CAN_FilterInitTypeDef CAN_FilterInitStructure; CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0; CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; // Init filter 0 (CAN1/master) CAN_FilterInitStructure.CAN_FilterNumber=0; CAN_FilterInit(&CAN_FilterInitStructure); // Init filter 1 (CAN2/slave) CAN_FilterInitStructure.CAN_FilterNumber=1; CAN_FilterInit(&CAN_FilterInitStructure); // Set which filter to use for CAN2. CAN_SlaveStartBank(1); // acceptance filters hohObj = canHwConfig->Can_Hoh; --hohObj; do { ++hohObj; if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) { // TODO Hw filtering } }while( !hohObj->Can_EOL ); // Clock calucation // ------------------------------------------------------------------- // // * 1 TQ = Sclk period( also called SCK ) // * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk // ( Fcanclk can come from crystal or from the peripheral dividers ) // // --> // TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 ) // TQ is between 8 and 25 clock = McuE_GetSystemClock()/2; tqSync = config->CanControllerPropSeg + 1; tq1 = config->CanControllerSeg1 + 1; tq2 = config->CanControllerSeg2 + 1; tq = tqSync + tq1 + tq2; CAN_InitTypeDef CAN_InitStructure; CAN_StructInit(&CAN_InitStructure); /* CAN cell init */ CAN_InitStructure.CAN_TTCM=DISABLE; CAN_InitStructure.CAN_ABOM=ENABLE; CAN_InitStructure.CAN_AWUM=ENABLE; CAN_InitStructure.CAN_NART=DISABLE; CAN_InitStructure.CAN_RFLM=DISABLE; CAN_InitStructure.CAN_TXFP=DISABLE; if(config->Can_Loopback){ CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; }else{ CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; } CAN_InitStructure.CAN_SJW=config->CanControllerPropSeg; CAN_InitStructure.CAN_BS1=config->CanControllerSeg1; CAN_InitStructure.CAN_BS2=config->CanControllerSeg2; CAN_InitStructure.CAN_Prescaler= clock/(config->CanControllerBaudRate*1000*tq); if(CANINITOK != CAN_Init(canHw,&CAN_InitStructure)) { return E_NOT_OK; } canUnit->state = CANIF_CS_STOPPED; Can_EnableControllerInterrupts(cId); return E_OK; }