// // Created by cfif on 05.04.2024. // #include #include "LinTasks.h" #include "CmsisRtosThreadUtils.h" #include "CanPorts.h" #include "fc7xxx_driver_lin.h" #include "Lins.h" //начало----------------------------------------- LIN 0 ---------------------------------------------------------------- //начало----------------------------------------- LIN 0 ---------------------------------------------------------------- //начало----------------------------------------- LIN 0 ---------------------------------------------------------------- //начало----------------------------------------- LIN 0 ---------------------------------------------------------------- void GetLin0CallbackHandler(tLinData *env, uint8_t u8LinIndex, void *state) { lin_xfer_state_t *pXferState = state; //uint32_t s_countIndex = 0U; //bool s_rxError = false; //LIN_DrvSetTimeOutCounter(u8LinIndex, 500); switch (pXferState->currentEventId) { case LIN_PID_OK: if (env->direction == LIN_DIRECTION_SET) { LIN_DrvSendFrameNonBlocking(u8LinIndex, env->g_aTxBuffer, env->g_aTxBufferLen); return; } else if (env->direction == LIN_DIRECTION_GET) { LIN_DrvReceiveFrameNonBlocking(u8LinIndex, env->g_aRxBuffer, env->g_aRxBufferLen); return; } else { // Misra check. uint8_t data = LIN_TIMEOUT; osMessageQueuePut(env->rxDataQueue, &data, 0x0, 0U); return; } break; case LIN_PID_ERROR: // Go to idle mode // LIN_DrvGoToIdleMode(u8LinIndex); // FCUART_Printf(DEBUG_FCUART_INSTANCE, "Receive PID error!\r\n"); break; case LIN_TX_COMPLETED: // Go to IDLE state. // LIN_DrvGoToIdleMode(u8LinIndex); // FCUART_Printf(DEBUG_FCUART_INSTANCE, "This test case will send data to slave node. Send data: \r\n"); // for (s_countIndex = 0U; s_countIndex < sizeof(g_aTxBuffer); s_countIndex++) { // FCUART_Printf(DEBUG_FCUART_INSTANCE, " 0x%x ", g_aTxBuffer[s_countIndex]); // } // FCUART_Printf(DEBUG_FCUART_INSTANCE, "\r\nMaster node send complete! \r\n"); break; case LIN_RX_COMPLETED: // Go to idle mode // LIN_DrvGoToIdleMode(u8LinIndex); // FCUART_Printf(DEBUG_FCUART_INSTANCE, "Master node receive data:\r\n"); //for (s_countIndex = 0U; s_countIndex < sizeof(env->g_aRxBuffer); s_countIndex++) { // FCUART_Printf(DEBUG_FCUART_INSTANCE, " 0x%x ", g_aRxBuffer[s_countIndex]); //if (env->g_aRxBuffer[s_countIndex] != (env->g_aTxBuffer[s_countIndex] + 1U)) { // s_rxError = true; //} //env->g_aRxBuffer[s_countIndex] = 0U; //} //if (true == s_rxError) { // FCUART_Printf(DEBUG_FCUART_INSTANCE, "\r\nReceived data Error\r\n"); //} else { // FCUART_Printf(DEBUG_FCUART_INSTANCE, "\r\nReveiced data matched!\r\n"); //} break; case LIN_CHECKSUM_ERROR: // FCUART_Printf(DEBUG_FCUART_INSTANCE, "Receive checksum byte error!\r\n"); break; case LIN_READBACK_ERROR: // FCUART_Printf(DEBUG_FCUART_INSTANCE, "Read back error!\r\n"); break; case LIN_FRAME_ERROR: break; case LIN_RECV_BREAK_FIELD_OK: break; case LIN_WAKEUP_SIGNAL: // FCUART_Printf(DEBUG_FCUART_INSTANCE, "Wake up signal received!\r\n"); //LIN_DrvGoToIdleMode(u8LinIndex); break; case LIN_TIMEOUT: // FCUART_Printf(DEBUG_FCUART_INSTANCE, "LIN transfer timeout occurred!\r\n"); break; case LIN_SYNC_ERROR: break; case LIN_BAUDRATE_ADJUSTED: break; case LIN_NO_EVENT: break; case LIN_SYNC_OK: break; default: // do nothing break; } osMessageQueuePut(env->rxDataQueue, (uint8_t *) &pXferState->currentEventId, 0x0, 0U); } static lin_event_id_t SEND_ACTUATOR_COM_x(tLinIO *linIo, uint8_t COM_ADR) { lin_event_id_t res = linIo->runCommand(linIo->env, COM_ADR, 40); SystemDelayMs(30); return res; } lin_event_id_t DFR_PRG_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADR) { lin_event_id_t res; linData->direction = LIN_DIRECTION_SET; linData->g_aTxBufferLen = sizeof(ACT_DFR_PRG); linData->g_aRxBufferLen = 0; ACT_DFR_PRG *ACT_DFR_PRG_ = (ACT_DFR_PRG *) linData->g_aTxBuffer; ACT_DFR_PRG_->BUS_ADR = BUS_ADR; ACT_DFR_PRG_->Data1_DFR_PRG = 0xFF; uint8_t retry = 1; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, DFR_PRG); SystemDelayMs(50); if (res == LIN_TX_COMPLETED) { break; } --retry; } return res; } lin_event_id_t RFR_PRG_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADDRESS, uint8_t *BUS_ADR, uint8_t *BUS_NEW_ADR, uint8_t *NOTL_DREH_Master, uint8_t *NOTL_ENAB_Master, uint8_t *DREH_Slave, uint8_t *ParitySlave, uint8_t *Version_CFR) { lin_event_id_t res; ACT_RFR_PRG *ACT_RFR_PRG_ = (ACT_RFR_PRG *) linData->g_aRxBuffer; uint8_t retry = 3; while (retry) { res = DFR_PRG_x(linIo, linData, BUS_ADDRESS); if (res == LIN_TX_COMPLETED) { linData->direction = LIN_DIRECTION_GET; linData->g_aTxBufferLen = 0; linData->g_aRxBufferLen = sizeof(ACT_RFR_PRG); res = SEND_ACTUATOR_COM_x(linIo, RFR_PRG); if (res == LIN_RX_COMPLETED) { *BUS_ADR = ACT_RFR_PRG_->BUS_ADR; *BUS_NEW_ADR = ACT_RFR_PRG_->BUS_NEW_ADR; *NOTL_DREH_Master = ACT_RFR_PRG_->NOTL_DREH_Master; *NOTL_ENAB_Master = ACT_RFR_PRG_->NOTL_ENAB_Master; *DREH_Slave = ACT_RFR_PRG_->DREH_Slave; *ParitySlave = ACT_RFR_PRG_->ParitySlave; *Version_CFR = ACT_RFR_PRG_->Version_CFR; break; } } --retry; } return res; } lin_event_id_t DFR_IDE_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADR) { lin_event_id_t res; linData->direction = LIN_DIRECTION_SET; linData->g_aTxBufferLen = sizeof(ACT_DFR_IDE); linData->g_aRxBufferLen = 0; ACT_DFR_IDE *ACT_DFR_IDE_ = (ACT_DFR_IDE *) linData->g_aTxBuffer; ACT_DFR_IDE_->BUS_ADR = BUS_ADR; ACT_DFR_IDE_->Data1_DFR_IDE = 0xFF; uint8_t retry = 1; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, DFR_IDE); if (res == LIN_TX_COMPLETED) { break; } --retry; } return res; } lin_event_id_t RFR_IDE_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADDRESS, uint8_t *BUS_ADR, uint8_t *IDE_ref, uint8_t *IDE_Sup, uint8_t *IDE_Har) { lin_event_id_t res; ACT_RFR_IDE *ACT_RFR_IDE_ = (ACT_RFR_IDE *) linData->g_aRxBuffer; uint8_t retry = 3; while (retry) { res = DFR_IDE_x(linIo, linData, BUS_ADDRESS); if (res == LIN_TX_COMPLETED) { linData->direction = LIN_DIRECTION_GET; linData->g_aTxBufferLen = 0; linData->g_aRxBufferLen = sizeof(ACT_RFR_IDE); res = SEND_ACTUATOR_COM_x(linIo, RFR_IDE); if (res == LIN_RX_COMPLETED) { *BUS_ADR = ACT_RFR_IDE_->BUS_ADR; *IDE_ref = ACT_RFR_IDE_->IDE_ref; *IDE_Sup = ACT_RFR_IDE_->IDE_Sup; *IDE_Har = ACT_RFR_IDE_->IDE_Har; break; } } --retry; } return res; } lin_event_id_t DFR_STA_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADR) { lin_event_id_t res; linData->direction = LIN_DIRECTION_SET; linData->g_aTxBufferLen = sizeof(ACT_DFR_STA); linData->g_aRxBufferLen = 0; ACT_DFR_STA *ACT_DFR_STA_ = (ACT_DFR_STA *) linData->g_aTxBuffer; ACT_DFR_STA_->BUS_ADR = BUS_ADR; ACT_DFR_STA_->Data1_DFR_STA = 0xFF; uint8_t retry = 1; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, DFR_STA); if (res == LIN_TX_COMPLETED) { break; } --retry; } return res; } lin_event_id_t RFR_STA_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADDRESS, uint8_t *BUS_ADR, uint16_t *CPOS_ALL, eEmrf_Slave_STA *Emrf_Slave, eMode_Mod *Mode_Slave, uint8_t *Error1_Supply_Slave, uint8_t *Error2_Communication_Slave, uint8_t *Error3_Temperature_Slave, uint8_t *Error4_Permanent_Electrical_Slave, eStall_STA *Stall_Slave, eReset_STA *Reset_Slave) { lin_event_id_t res; ACT_RFR_STA *ACT_RFR_STA_ = (ACT_RFR_STA *) linData->g_aRxBuffer; uint8_t retry = 1; while (retry) { res = DFR_STA_x(linIo, linData, BUS_ADDRESS); if (res == LIN_TX_COMPLETED) { linData->direction = LIN_DIRECTION_GET; linData->g_aTxBufferLen = 0; linData->g_aRxBufferLen = sizeof(ACT_RFR_STA); res = SEND_ACTUATOR_COM_x(linIo, RFR_STA); if (res == LIN_RX_COMPLETED) { *BUS_ADR = ACT_RFR_STA_->BUS_ADR; *CPOS_ALL = ACT_RFR_STA_->CPOS_ALL; *Emrf_Slave = ACT_RFR_STA_->Emrf_Slave; *Mode_Slave = ACT_RFR_STA_->Mode_Slave; *Error1_Supply_Slave = ACT_RFR_STA_->Error1_Supply_Slave; *Error2_Communication_Slave = ACT_RFR_STA_->Error2_Communication_Slave; *Error3_Temperature_Slave = ACT_RFR_STA_->Error3_Temperature_Slave; *Error4_Permanent_Electrical_Slave = ACT_RFR_STA_->Error4_Permanent_Electrical_Slave; *Stall_Slave = ACT_RFR_STA_->Stall_Slave; *Reset_Slave = ACT_RFR_STA_->Reset_Slave; break; } } --retry; } return res; } lin_event_id_t ISSR_x(tLinIO *linIo, tLinData *linData, uint8_t COM, uint8_t *BLOCK_MT, uint16_t *CPOS_ALL, uint8_t *DIAGNOSE_MT) { lin_event_id_t res; linData->direction = LIN_DIRECTION_GET; linData->g_aTxBufferLen = 0; linData->g_aRxBufferLen = sizeof(ACT_RFR_ISSR); uint8_t retry = 3; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, COM); if (res == LIN_RX_COMPLETED) { ACT_RFR_ISSR *ACT_RFR_ISSR_ = (ACT_RFR_ISSR *) linData->g_aRxBuffer; *BLOCK_MT = ACT_RFR_ISSR_->BLOCK_MT; *CPOS_ALL = ACT_RFR_ISSR_->CPOS_1_LSB_MT | (ACT_RFR_ISSR_->CPOS_1_MSB_MT << 7); *DIAGNOSE_MT = ACT_RFR_ISSR_->DIAGNOSE_MT; break; } --retry; } return res; } lin_event_id_t CFR_MOD_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADDRESS, eMode_Mod Mode_Slave) { lin_event_id_t res; linData->direction = LIN_DIRECTION_SET; linData->g_aTxBufferLen = sizeof(ACT_CFR_MOD); linData->g_aRxBufferLen = 0; ACT_CFR_MOD *ACT_CFR_MOD_ = (ACT_CFR_MOD *) linData->g_aTxBuffer; ACT_CFR_MOD_->BUS_ADR = BUS_ADDRESS; ACT_CFR_MOD_->Mode_Slave = Mode_Slave; ACT_CFR_MOD_->Unused = 0xFF; ACT_CFR_MOD_->Data2_Mod = 0xFF; ACT_CFR_MOD_->Data3_Mod = 0xFF; uint8_t retry = 3; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, CFR_MOD); if (res == LIN_TX_COMPLETED) { break; } --retry; } return res; } lin_event_id_t CFR_INI_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADDRESS, uint16 INI_CPOS) { lin_event_id_t res; linData->direction = LIN_DIRECTION_SET; linData->g_aTxBufferLen = sizeof(ACT_CFR_INI); linData->g_aRxBufferLen = 0; ACT_CFR_INI *ACT_CFR_INI_ = (ACT_CFR_INI *) linData->g_aTxBuffer; ACT_CFR_INI_->BUS_ADR = BUS_ADDRESS; ACT_CFR_INI_->INI_CPOS = INI_CPOS; ACT_CFR_INI_->unused = 0xFF; ACT_CFR_INI_->Not_Used_INI = 0xFF; uint8_t retry = 3; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, CFR_INI); if (res == LIN_TX_COMPLETED) { break; } --retry; } return res; } lin_event_id_t CFR_SET_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADDRESS, uint16 FINAL_POS, eStall_SET Stall_SET, eLnoise_SET Lnoise_SET, eAutos_SET Autos_SET, eSpeed_SET Speed_SET, eCoils_Stop_SET Coils_Stop_SET) { lin_event_id_t res; linData->direction = LIN_DIRECTION_SET; linData->g_aTxBufferLen = sizeof(ACT_CFR_SET); linData->g_aRxBufferLen = 0; ACT_CFR_SET *ACT_CFR_SET_ = (ACT_CFR_SET *) linData->g_aTxBuffer; ACT_CFR_SET_->BUS_ADR = BUS_ADDRESS; ACT_CFR_SET_->FINAL_POS = FINAL_POS; ACT_CFR_SET_->unused = 0xFF; ACT_CFR_SET_->Unused_SET = 0xFF; ACT_CFR_SET_->Stall_SET = Stall_SET; ACT_CFR_SET_->Lnoise_SET = Lnoise_SET; ACT_CFR_SET_->Autos_SET = Autos_SET; ACT_CFR_SET_->Speed_SET = Speed_SET; ACT_CFR_SET_->Coils_Stop_SET = Coils_Stop_SET; uint8_t retry = 3; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, CFR_SET); if (res == LIN_TX_COMPLETED) { break; } --retry; } return res; } /* lin_event_id_t CFR_PRG_x(tLinIO *linIo, tLinData *linData, uint8_t BUS_ADDRESS, uint16_t BUS_NEW_ADR, uint8_t NOTL_DREH_Master, uint8_t NOTL_ENAB_Master, uint8_t DREH_Master, uint8_t Motor, uint8_t Baudrate, uint8_t Version_CFR) { lin_event_id_t res; linData->direction = LIN_DIRECTION_SET; linData->g_aTxBufferLen = sizeof(ACT_CFR_SET); linData->g_aRxBufferLen = 0; ACT_CFR_PRG *ACT_CFR_PRG_ = (ACT_CFR_PRG *) linData->g_aTxBuffer; ACT_CFR_PRG_->BUS_ADR = BUS_ADDRESS; ACT_CFR_PRG_->BUS_NEW_ADR = BUS_NEW_ADR; ACT_CFR_PRG_->NOTL_DREH_Master = NOTL_DREH_Master; ACT_CFR_PRG_->NOTL_ENAB_Master = NOTL_ENAB_Master; ACT_CFR_PRG_->DREH_Master = DREH_Master; ACT_CFR_PRG_->Motor = Motor; ACT_CFR_PRG_->Baudrate = Baudrate; ACT_CFR_PRG_->Free = 0xFF; ACT_CFR_PRG_->Version_CFR = Version_CFR; uint8_t retry = 3; while (retry) { res = SEND_ACTUATOR_COM_x(linIo, CFR_PRG); if (res == LIN_TX_COMPLETED) { break; } --retry; } return res; } */ void Lin_0_Init(tLinTaskActuator *env, tLinData *linData, tLinIO *linIO) { env->linIo = linIO; env->linData = linData; env->access = osMutexNew(NULL); InitThreadAtrStatic(&env->thread.attr, "Lin0", env->thread.controlBlock, env->thread.stack, osPriorityNormal); } static bool setState20(tLinTaskActuator *env, bool isError, uint8_t index) { if (isError) { env->linStateActuator[index].error_connect = 1; } else { env->linStateActuator[index].error_connect = 0; } if (env->linCommandActuator[index].BUS_ADR == 0x20) { for (uint8_t j = 0; j < LIN0_ISSR_ALL; ++j) { env->linCommandActuator[j].COM = LIN_ACT_CFR_NONE; if (isError) { env->linStateActuator[j].error_connect = 1; } else { env->linStateActuator[j].error_connect = 0; } } return true; } return false; } lin_event_id_t Lin0_Scheduler(tLinTaskActuator *env) { lin_event_id_t ret; for (uint8_t i = 0; i < LIN0_ISSR_ALL; ++i) { env->linCommandActuator[i].isRFR_STA = 1; if (env->linCommandActuator[i].COM == LIN_ACT_CFR_MOD) { ret = CFR_MOD_x(env->linIo, env->linData, env->linCommandActuator[i].BUS_ADR, env->linCommandActuator[i].MODE); if (ret == LIN_TX_COMPLETED) { if (env->linCommandActuator[i].BUS_ADR == 0x20) { for (uint8_t j = 0; j < LIN0_ISSR_ALL; ++j) { env->linCommandActuator[j].isRFR_STA = 1; } } } else { if (setState20(env, true, i)) break; } if (setState20(env, false, i)) break; } } for (uint8_t i = 0; i < LIN0_ISSR_ALL; ++i) { if (env->linCommandActuator[i].COM == LIN_ACT_CFR_INI) { ret = CFR_INI_x(env->linIo, env->linData, env->linCommandActuator[i].BUS_ADR, env->linCommandActuator[i].POS); if (ret == LIN_TX_COMPLETED) { } else { if (setState20(env, true, i)) break; } if (setState20(env, false, i)) break; } } for (uint8_t i = 0; i < LIN0_ISSR_ALL; ++i) { if (env->linCommandActuator[i].COM == LIN_ACT_CFR_SET) { ret = CFR_SET_x(env->linIo, env->linData, env->linCommandActuator[i].BUS_ADR, env->linCommandActuator[i].POS, env->linCommandActuator[i].Stall_SET, env->linCommandActuator[i].Lnoise_SET, env->linCommandActuator[i].Autos_SET, env->linCommandActuator[i].Speed_SET, env->linCommandActuator[i].Coils_Stop_SET); if (ret == LIN_TX_COMPLETED) { } else { if (setState20(env, true, i)) break; } if (setState20(env, false, i)) break; } } for (uint8_t i = 0; i < LIN0_ISSR_ALL; ++i) { uint8_t BLOCK_MT; uint8_t DIAGNOSE_MT; uint16_t CPOS_ALL; ret = ISSR_x(env->linIo, env->linData, i, &BLOCK_MT, &CPOS_ALL, &DIAGNOSE_MT); if (ret == LIN_RX_COMPLETED) { env->linStateActuator[i].BLOCK_MT = BLOCK_MT; env->linStateActuator[i].CPOS_ALL = CPOS_ALL << 1; env->linStateActuator[i].DIAGNOSE_MT = DIAGNOSE_MT; if ((env->linStateActuator[i].DIAGNOSE_MT) || (env->linCommandActuator[i].isRFR_STA)) { env->linCommandActuator[i].isRFR_STA = 0; uint8_t BUS_ADR; eEmrf_Slave_STA Emrf_Slave; eMode_Mod Mode_Slave; uint8_t Error1_Supply_Slave; uint8_t Error2_Communication_Slave; uint8_t Error3_Temperature_Slave; uint8_t Error4_Permanent_Electrical_Slave; eStall_STA Stall_Slave; eReset_STA Reset_Slave; ret = RFR_STA_x(env->linIo, env->linData, i | 0x20, &BUS_ADR, &CPOS_ALL, &Emrf_Slave, &Mode_Slave, &Error1_Supply_Slave, &Error2_Communication_Slave, &Error3_Temperature_Slave, &Error4_Permanent_Electrical_Slave, &Stall_Slave, &Reset_Slave); if (ret == LIN_RX_COMPLETED) { BUS_ADR &= 0x1F; if (BUS_ADR != i) { asm("nop"); } if (BUS_ADR < LIN0_ISSR_ALL) { env->linStateActuator[BUS_ADR].CPOS_ALL = CPOS_ALL; env->linStateActuator[BUS_ADR].Emrf_Slave = Emrf_Slave; env->linStateActuator[BUS_ADR].Mode_Slave = Mode_Slave; env->linStateActuator[BUS_ADR].Error1_Supply_Slave = Error1_Supply_Slave; env->linStateActuator[BUS_ADR].Error2_Communication_Slave = Error2_Communication_Slave; env->linStateActuator[BUS_ADR].Error3_Temperature_Slave = Error3_Temperature_Slave; env->linStateActuator[BUS_ADR].Error4_Permanent_Electrical_Slave = Error4_Permanent_Electrical_Slave; env->linStateActuator[BUS_ADR].Stall_Slave = Stall_Slave; env->linStateActuator[BUS_ADR].Reset_Slave = Reset_Slave; } else { asm("nop"); } } else { env->linStateActuator[i].error_connect = 1; } } } else { env->linStateActuator[i].error_connect = 1; } } if ((ret == LIN_TX_COMPLETED) || (ret == LIN_RX_COMPLETED)) { } else { return ret; } return LIN_NO_EVENT; } static _Noreturn void Lin0_Thread(tLinTaskActuator *env) { for (;;) { if (osMutexAcquire(env->access, 1000) == osOK) { lin_event_id_t res = Lin0_Scheduler(env); uint8_t isError = 0; for (uint8_t i = 0; i < LIN0_ISSR_ALL; ++i) { if (env->linStateActuator[i].error_connect == 1) ++isError; } if (isError == LIN0_ISSR_ALL) { env->error_connect = 1; } else { env->error_connect = 0; } osMutexRelease(env->access); } SystemDelayMs(100); } } void Lin0_StartThread(tLinTaskActuator *env) { if (!env->thread.id) { env->thread.id = osThreadNew((osThreadFunc_t) (Lin0_Thread), (void *) (env), &env->thread.attr); } } //конец----------------------------------------- LIN 0 ---------------------------------------------------------------- //конец----------------------------------------- LIN 0 ---------------------------------------------------------------- //конец----------------------------------------- LIN 0 ---------------------------------------------------------------- //конец----------------------------------------- LIN 0 ----------------------------------------------------------------