/** * @copyright 2021 Indie microcontroller. * * This file is proprietary to Indie microcontroller. * All rights reserved. Reproduction or distribution, in whole * or in part, is forbidden except by express written permission * of Indie microcontroller. * * @file linSlaveTask.c * @Author: Jack.Pan * @E-mail:jack.pan@indiemicro.com * @Date: 2021/07/06 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if LIN_STACK_TYPE == LIN_STACK_TYPE_LIN2_2A #define FID_LED_CTRL DEFAULT_LINS_FID0 #define FID_TFJR DEFAULT_LINS_FID1 #define FID_KEY DEFAULT_LINS_FID2 #define DIAG_RECV_DATA_BUFF_SIZE (128U) #define DIAG_SEND_DATA_BUFF_SIZE (128U) #define FID_TABLE_INDEX_0 (0) #define FID_TABLE_INDEX_1 (0) #define FID_TABLE_INDEX_2 (0) #define FID_LED_CTRL_INDEX (0) #define FID_TFJR_INDEX (1) #define FID_KEY_INDEX (2) /* ******************internal function declarations****************************/ void DiagnosticSubscribedCmdsHandleISR(const DiagSubscribeInfo_t * const frameInfo); void UnconditionalSubscribedCmdsHandle(LIN_Device_Frame_t const *frame); void UnconditionalPublishedCmdsISR(LIN_Device_Frame_t *const frame); void UnconditionalPublishedCmdsTxFinishedISR(uint8_t fid, uint8_t resvd); void DiagnosticSleepRequestHandle(SleepRequestType_t type); void BusWakeUpRequestHandle(BusWakeUpRequestResult_t result); /* *******************global variants declarations*****************************/ static TaskState_t linsTaskState = TASK_STATE_INIT; static uint8_t diagDataRspBuff[DIAG_SEND_DATA_BUFF_SIZE]; static uint8_t diagDataRecvBuff[DIAG_RECV_DATA_BUFF_SIZE]; static DiagMultiPduInfo_t diagMultiPduInfo = { .buffLength = sizeof(diagDataRecvBuff)/sizeof(diagDataRecvBuff[0]), .buff = diagDataRecvBuff, }; static uint8_t busWakeupRetryCount = 0U; void busWakeupRetryTimerExpired(SoftTimer_t *timer); static SoftTimer_t busWakeupRetryTimer = { .mode = TIMER_ONE_SHOT_MODE, .interval = 2250U, .handler = busWakeupRetryTimerExpired }; static uint8_t eventTriggeredLedOn = FALSE; static SystemParams_t systemParam; static uint8_t By3CSetMotorParam_State = 0U; static uint16_t SetMotorPhyParam[6]; static uint32_t crcValue ; /* LIN command handle callbacks declarations */ static ls_LinsFramesCallback_t linsFramesCallback ={ UnconditionalSubscribedCmdsHandle, /* received data from master */ UnconditionalPublishedCmdsISR, /* send data to master, it's an interrupt function, please fill the data as fast as possible */ UnconditionalPublishedCmdsTxFinishedISR, /* send data to master finished, it's an interrupt function, please fill the data as fast as possible */ DiagnosticSubscribedCmdsHandleISR, /* Diagnostic sigle PDU and MultiPDU received data from master,it's an interrupt function, please fill the data as fast as possible */ NULL, /* special functional NAD (0x7E) handler*/ DiagnosticSleepRequestHandle, /* Diagnostic sleep request from master */ BusWakeUpRequestHandle, /* Get the bus wake up result this would take effects after call API: ls_send_wake_up_bus_signal()*/ NULL, /* SAE J2602 -1 Configuration Messages */ NULL, /* 5.7.2.5 DNN Based Broadcast Messages */ }; /* **FID table declarations****/ static LIN_Device_Frame_t UnconditionalCmdsTable[DEFAULT_LINS_FID_SIZE] = { [FID_LED_CTRL_INDEX] = { .frame_id = FID_LED_CTRL, .msg_type = LIN_MSG_TYPE_RX, .checksum = LIN_CHECKSUM_ENHANCED, .length = 2, .frameIsValid = TRUE, }, [FID_TFJR_INDEX] = { .frame_id = FID_TFJR, /* status management frame */ .msg_type = LIN_MSG_TYPE_TX, .checksum = LIN_CHECKSUM_ENHANCED, .length = 2, .frameIsValid = TRUE, }, [FID_KEY_INDEX] = { .frame_id = FID_KEY, /* user data report */ .msg_type = LIN_MSG_TYPE_TX, .checksum = LIN_CHECKSUM_ENHANCED, .length = 8, .frameIsValid = TRUE, }, }; /* please don't do any changes for it would be used by lin stack */ LIN_Device_Frame_t volatile *LINS_GetUcndFramesTable(uint8_t *tableItemsCount) { *tableItemsCount = (uint8_t)(sizeof(UnconditionalCmdsTable)/sizeof(LIN_Device_Frame_t)); return UnconditionalCmdsTable; } /* Diagnostic subscribed frame received from LIN master */ void DiagnosticSubscribedCmdsHandleISR(const DiagSubscribeInfo_t *const diagReq) { DiagPublishInfo_t diagRsp={ .sid = diagReq->sid, .type = diagReq->type, .payload = diagDataRspBuff, }; if (diagReq->type == PDU_TYPE_SINGLE_PDU){ if (diagReq->sid >= LIN_SID_ASSIGN_NAD && diagReq->sid <= LIN_SID_ASSIGN_FRAME_ID_RANGE){ /* handle Node configuration and Identification commands*/ diagRsp.type = PDU_TYPE_SINGLE_PDU; if (LNCI_HandleNodeCfgIdentifyRequest(diagReq,&diagRsp)== TRUE){ ls_handle_diagnostic_response(&diagRsp); } }else{ if (diagReq->sid == LIN_SID_APP_DIAG_SINGLE_PDU_RECV_MULTI_RSP){ /* handle diagnostic single pdu, multi response, user defined diagnostic frame here for example: */ for (uint16_t i = 0U; i < 15U; i++){ diagDataRspBuff[i] = (uint8_t)i; } diagRsp.sid = diagReq->sid; diagRsp.packLength = 15U; diagRsp.type = (diagRsp.packLength > SF_MAX_DATA_LENGTH)? PDU_TYPE_MULTI_PDU:PDU_TYPE_SINGLE_PDU; ls_handle_diagnostic_response(&diagRsp); }else if(diagReq->sid == LIN_SID_APP_DIAG_MOTOR_GET_CONFIG){ diagRsp.sid = diagReq->sid; /*Read set paramers from flash*/ CRC32_Init(); SystemParams_t *param = (SystemParams_t *)FLASH_START_ADDRESS_SYSTEM_DATA; crcValue = CRC32_GetRunTimeCRC32((uint8_t *)¶m->info ,(uint16_t)sizeof(param->info)); if (crcValue == param->head.crc32){ systemParam = *param; diagDataRspBuff[2] = (uint8_t)systemParam.info.motorParams.Constantspeed; diagDataRspBuff[3] = (uint8_t)(systemParam.info.motorParams.Constantspeed >> 8); diagDataRspBuff[4] = (uint8_t)systemParam.info.motorParams.startspeed; diagDataRspBuff[5] = (uint8_t)(systemParam.info.motorParams.startspeed >> 8); diagDataRspBuff[6] = (uint8_t)systemParam.info.motorParams.Slowspeed; diagDataRspBuff[7] = (uint8_t)(systemParam.info.motorParams.Slowspeed >> 8); diagDataRspBuff[8] = (uint8_t)systemParam.info.motorParams.MotorlockAcoilvoltage; diagDataRspBuff[9] = (uint8_t)(systemParam.info.motorParams.MotorlockAcoilvoltage >> 8); diagDataRspBuff[10] = (uint8_t)systemParam.info.motorParams.MotorlockBcoilvoltage; diagDataRspBuff[11] = (uint8_t)(systemParam.info.motorParams.MotorlockBcoilvoltage >> 8); diagDataRspBuff[12] = (uint8_t)systemParam.info.motorParams.ClimbTime; diagDataRspBuff[13] = (uint8_t)systemParam.info.motorParams.SlowTime; } diagRsp.sid = diagReq->sid; diagRsp.packLength = 15U; diagRsp.type = (diagRsp.packLength > SF_MAX_DATA_LENGTH)? PDU_TYPE_MULTI_PDU:PDU_TYPE_SINGLE_PDU; ls_handle_diagnostic_response(&diagRsp); } #ifdef BOOTLOADER_EN else if (diagReq->sid == LIN_SID_APP_DIAG_BOOT_MODE && diagReq->packLength == sizeof(EnterBootloaderFrame_t)){ EnterBootloaderFrame_t *boot = (EnterBootloaderFrame_t *)((void*)diagReq->payload); if ( boot->command == BOOT_MODE_HANDSHAKE && boot->magicKey == BOOT_MODE_MAGIC_KEY_HANDSHAKE){ /* Reset Chip */ TRIMHV_SFRS->RETAIN.RETAIN0 = 0x05U; CRGA_SFRS->RESETCTRL.HARDRSTREQ = 1U; } } #endif } }else{ /* handle diagnostic multi pdu received sigle pdu response, user defined diagnostic frame here */ if (diagReq->sid == LIN_SID_APP_DIAG_MULTI_PDU_RECV_SINGLE_RSP){ /* handle diagnostic multi pdu received single pdu response, user defined diagnostic frame here */ /* handle response data here */ diagRsp.sid = diagReq->sid; diagRsp.packLength = 5U;/* Valid data length not includes sid*/ diagRsp.type = (diagRsp.packLength > SF_MAX_DATA_LENGTH)? PDU_TYPE_MULTI_PDU:PDU_TYPE_SINGLE_PDU; ls_handle_diagnostic_response(&diagRsp); }else if (diagReq->sid == LIN_SID_APP_DIAG_MULTI_PDU_RECV_MULTI_RSP){ /* handle diagnostic multi pdu received multi pdu response, user defined diagnostic frame here */ /* Package received finished */ diagRsp.sid = diagReq->sid; diagRsp.packLength = 15U; /* Valid data length not includes sid*/ diagRsp.type = (diagRsp.packLength > SF_MAX_DATA_LENGTH)? PDU_TYPE_MULTI_PDU:PDU_TYPE_SINGLE_PDU; ls_handle_diagnostic_response(&diagRsp); }else if (diagReq->sid == LIN_SID_APP_DIAG_MOTOR_SET_CONFIG){ /* handle diagnostic multi pdu received multi pdu response, user defined diagnostic frame here */ /* Package received finished */ for (uint16_t i = 0; i < diagReq->packLength; i++){// diagDataRspBuff[i] = diagReq->payload[i]; } //info->motorPhysicalParam.Constantspeed;//Constantspeed us/step SetMotorPhyParam[0] = diagDataRecvBuff[3]; SetMotorPhyParam[0] = ((SetMotorPhyParam[0]<<8)+diagDataRecvBuff[2]); //info->motorPhysicalParam.startspeed;//Motorlock startspeed us/step SetMotorPhyParam[1] = diagDataRecvBuff[5]; SetMotorPhyParam[1] = ((SetMotorPhyParam[1]<<8)+diagDataRecvBuff[4]); //info->motorPhysicalParam.Slowspeed;//Motorlock Slowspeed us/step SetMotorPhyParam[2] = diagDataRecvBuff[7]; SetMotorPhyParam[2] = ((SetMotorPhyParam[2]<<8)+diagDataRecvBuff[6]); //info->motorPhysicalParam.MotorlockAcoilvoltage;//Motorlock Acoil voltage SetMotorPhyParam[3] = diagDataRecvBuff[9]; SetMotorPhyParam[3] = ((SetMotorPhyParam[3]<<8)+diagDataRecvBuff[8]); //info->motorPhysicalParam.MotorlockBcoilvoltage;//Motorlock Bcoil voltage SetMotorPhyParam[4] = diagDataRecvBuff[11]; SetMotorPhyParam[4] = ((SetMotorPhyParam[4]<<8)+diagDataRecvBuff[10]); //info->motorPhysicalParam.SlowTime;//ClimbTime: ms low8bit, SlowTime: ms high8bit SetMotorPhyParam[5] = diagDataRecvBuff[12]; SetMotorPhyParam[5] = (SetMotorPhyParam[5] << 8) + diagDataRecvBuff[12];//info->motorPhysicalParam.ClimbTime; By3CSetMotorParam_State = 1; diagRsp.sid = diagReq->sid; diagRsp.packLength = 15U; /* Valid data length not includes sid*/ diagRsp.type = (diagRsp.packLength > SF_MAX_DATA_LENGTH)? PDU_TYPE_MULTI_PDU:PDU_TYPE_SINGLE_PDU; ls_handle_diagnostic_response(&diagRsp); } else{ /* intent to empty */ } } } /* Received sleep command from lin master or bus idle timeout occurs */ void DiagnosticSleepRequestHandle(SleepRequestType_t type) { // (void)ls_clr_go_to_sleep_flag(); // /* Set system to hibranate mode*/ // PMU_EnterDeepSleepMode(); } void busWakeupRetryTimerExpired(SoftTimer_t *timer) { ls_send_wake_up_bus_signal(); } /* Called timeout after bus wake up 3 tries, or called when bus recovery */ void BusWakeUpRequestHandle(BusWakeUpRequestResult_t result) { if (result == BUS_WAKEUP_REQ_RESULT_REQ_TIMEOUT){ if (busWakeupRetryCount == 1U){ busWakeupRetryCount++; SoftTimer_Start(&busWakeupRetryTimer); }else{ busWakeupRetryCount = 0U; } }else{ busWakeupRetryCount = 0U; SoftTimer_Stop(&busWakeupRetryTimer); } } void UnconditionalPublishedCmdsTxFinishedISR(uint8_t fid, uint8_t resvd) { if ( fid == UnconditionalCmdsTable[FID_TFJR_INDEX].frame_id){ (void)ls_ifc_clear_error_status(); (void)ls_clr_error_code_log(); (void)ls_clr_overrun_flag(); } } /* User defined published frame callback function which from LINS ISR please fill frame data[0-7] only, please don't do any changes on the left info except data[x]!!!! *///TODO void UnconditionalPublishedCmdsISR(LIN_Device_Frame_t *const frame) { /* feed buffer to frame */ if (frame->frame_id == UnconditionalCmdsTable[FID_TFJR_INDEX].frame_id){ /* status management frame */ // lin_status_t status = ls_ifc_read_status(); // frame->data[0] = (uint8_t)status.payload; // frame->data[1] = LINS_GetPIDFromFID(status.pid); // frame->data[2] = ls_read_error_code_log(); // for (uint8_t i = 2U; i < 8U; i++){ // frame->data[i] = 0xFFU; // } lin_status_t status = ls_ifc_read_status(); frame->data[0] = (uint8_t)status.payload; frame->data[1] = SAFM_TransferState(); frame->data[2] = (uint8_t)SAFM_GetMotorcurrent(); frame->data[3] = (uint8_t)SAFM_GetMotorcurrent()>>8; frame->data[4] = (uint8_t)SAFM_GetMotorcurrent(); frame->data[5] = (uint8_t)SAFM_GetMotorcurrent()>>8; frame->data[6] = Motor_GetCurrentPosition(); frame->data[7] = Motor_GetCurrentPosition() >> 8; }else if (frame->frame_id == UnconditionalCmdsTable[FID_KEY_INDEX].frame_id){ /* user defined data report */ frame->data[0] = (APPL_GetLEDState()) | (eventTriggeredLedOn << 1U) | 0xF8U; for (uint8_t i = 1U; i < LIN_BUFF_SIZE; i++){ frame->data[i] = 0xFFU; } }else{ /* intent to empty */ } } void LINS_EventTriggered_ISR(void) { if (eventTriggeredLedOn == TRUE){ eventTriggeredLedOn = FALSE; }else{ eventTriggeredLedOn = TRUE; } //UnconditionalCmdsTable[EVENT_TRIGGERED_INDEX].eventTriggered = TRUE; } uint8_t LINS_GetPIDFromFID(uint8_t frameId) { uint8_t id = frameId; uint8_t P0,P1; P0 = (uint8_t)(((id >> 0)&0x01U)^((id >> 1)&0x01U)^((id >> 2)&0x01U) ^ ((id>> 4)&0x01U)); P1 = (uint8_t)(~(((id >> 1)&0x01U)^((id >> 3)&0x01U)^((id >> 4)&0x01U) ^ ((id>> 5)&0x01U))) & 0x01U; id = frameId | (P0 << 6) | (P1 << 7); return id; } void LINS_SendWakeUpSignal_ISR(void) { if (busWakeupRetryCount == 0U){ busWakeupRetryCount++; ls_send_wake_up_bus_signal(); } } /* User defined subscribed frame received from LIN master */ void UnconditionalSubscribedCmdsHandle(LIN_Device_Frame_t const *frame) { /* if (frame->frame_id == UnconditionalCmdsTable[FID_COLOR_CTRL_INDEX].frame_id){ Get_MotorprafromLINM(frame); } */ } void LINS_TaskHandler(void) { switch(linsTaskState){ case TASK_STATE_ACTIVE: break; case TASK_STATE_INIT: ls_register_services(LIN_PROTOCOL_LIN2_2A,UnconditionalCmdsTable, (l_u8)(sizeof(UnconditionalCmdsTable)/sizeof(LIN_Device_Frame_t)),diagMultiPduInfo,&linsFramesCallback); (void)ls_set_tp_timeout(N_AS, N_CR); /* Note that please don't change the following glitch configuration!!!!*/ (void)ls_set_lins_rx_glitch_filter_1st(0x00U,0x08U); (void)ls_set_lins_rx_glitch_filter_2nd(0x0AU,0x10U); (void)ls_set_lins_rx_glitch_filter_3rd(0x30U,0x30U); (void)l_sys_init(); (void)ls_disable_lin_auto_sleep(TRUE); linsTaskState = TASK_STATE_ACTIVE; break; default: break; } } uint8_t LINS_TransferMotorPhyParamtobuffBy3C(uint16_t *buff,uint8_t leng) { static uint8_t resault = 0u; resault = By3CSetMotorParam_State; if(By3CSetMotorParam_State == 1U){ for (uint8_t i = 0U; i < leng; i++){ *buff = SetMotorPhyParam[i]; buff++; } By3CSetMotorParam_State = 0; } return resault; } void LINS_Transfer3CdataToPDS(uint16_t *buff,uint8_t leng) { for (uint8_t i = 0U; i < leng; i++){ *buff = SetMotorPhyParam[i]; buff++; } } #endif