/************************************************************************** Данный файл содержит функции для симуляции МК в Simulink (S-Function). **************************************************************************/ #include "mcu_wrapper_conf.h" SIM__MCUHandleTypeDef hmcu; // для управления контекстом программы МК double SystemClockDouble = 0; // для симуляции системных тиков, прока просто по приколу double SystemClock_step = 0; // для симуляции системных тиков, прока просто по приколу uint64_t SystemClock; // для симуляции системных тиков, прока просто по приколу //-------------------------------------------------------------// //-----------------CONTROLLER SIMULATE FUNCTIONS---------------// /** THREAD FOR MCU APP */ /** * @brief Thread that run MCU code. * @note Поток, который запускает и выполняет код МК. */ extern int main(void); // extern while from main.c unsigned __stdcall MCU_App_Thread(void) { main(); // run MCU code return 0; // end thread // note: this return will reached only at the end of simulation, when all whiles will be skipped due to @ref sim_while } /** SIMULATE MCU FOR ONE SIMULATION STEP */ /** * @brief Read from simulink S-Block Inputs and write to MCU I/O ports. * @param time - current time of simulation (in second). * @note Вызывает главную функцию main из пользовательского кода и управляет её ходом: * Прерывает её, если она попала в бесконечный while, симулирует периферию * и возвращает в точку остановки на следующем шаге. */ void MCU_Step_Simulation(SimStruct* S, time_T time) { MCU_readInputs(S); // считывание портов MCU_Periph_Simulation(); // simulate peripheral ResumeThread(hmcu.hMCUThread); for (int i = DEKSTOP_CYCLES_FOR_MCU_APP; i > 0; i--) { } SuspendThread(hmcu.hMCUThread); MCU_writeOutputs(S); // запись портов (по факту запись в буфер. запись в порты в mdlOutputs) } /** SIMULATE MCU PERIPHERAL */ /** * @brief Simulate peripheral of MCU * @note Пользовательский код, который симулирует работу периферии МК. */ void MCU_Periph_Simulation(void) { SystemClockDouble += SystemClock_step; // emulate core clock SystemClock = SystemClockDouble; uwTick = SystemClock / (SystemCoreClock / 1000); Simulate_TIMs(); } /** READ INPUTS S-FUNCTION TO MCU REGS */ /** * @brief Read from simulink S-Block Inputs and write to MCU I/O ports. * @note Пользовательский код, который записывает в порты ввода-вывода из disc. */ void MCU_readInputs(SimStruct* S) { /* Get S-Function inputs */ real_T* IN = ssGetInputPortRealSignal(S, 0); SFUNC_to_GPIO(IN); } /** WRITE OUTPUTS BUFFER S-FUNCTION FROM MCU REGS*/ /** * @brief Read from MCU I/O ports and write to simulink S-Block Outputs Buffer. * @note Пользовательский код, который записывает в disc порты ввода-вывода. */ void MCU_writeOutputs(SimStruct* S) { /* Get S-Function descrete array */ real_T* DISC = ssGetDiscStates(S); GPIO_to_SFUNC(DISC); } //-----------------CONTROLLER SIMULATE FUNCTIONS---------------// //-------------------------------------------------------------// //-------------------------------------------------------------// //----------------------SIMULINK FUNCTIONS---------------------// /** WRITE OUTPUTS OF S-BLOCK */ /** * @brief Write S-Function Output ports to inputs. * @param disc - discrete array of S-Function. Outputs would be written from disc. * @note Пользовательский код, который записывает выходы S-Function. */ void SIM_writeOutputs(SimStruct* S) { real_T* GPIO; real_T* DISC = ssGetDiscStates(S); //-------------WRITTING GPIOS--------------- for (int j = 0; j < PORT_NUMB; j++) { GPIO = ssGetOutputPortRealSignal(S, j); for (int i = 0; i < PORT_WIDTH; i++) { GPIO[i] = DISC[j * PORT_WIDTH + i]; DISC[j * PORT_WIDTH + i] = 0; } } //------------------------------------------ } /** MCU WRAPPER DEINITIALIZATION */ /** * @brief Initialize structures and variables for simulating MCU. * @note Пользовательский код, который будет настраивать все структуры для симуляции. */ void SIM_Initialize_Simulation(void) { /* user initialization */ Initialize_Periph_Sim(); /* wrapper initialization */ SystemClock_step = SystemCoreClock * SIM_Sample_Time; // set system clock step // инициализация потока, который будет выполнять код МК hmcu.hMCUThread = (HANDLE)CreateThread(NULL, 0, MCU_App_Thread, 0, CREATE_SUSPENDED, &hmcu.idMCUThread); } /** MCU WRAPPER DEINITIALIZATION */ /** * @brief Deinitialize structures and variables for simulating MCU. * @note Пользовательский код, который будет очищать все структуры после окончания симуляции. */ void SIM_deInitialize_Simulation(void) { // simulate structures of peripheral deinitialization deInitialize_Periph_Sim(); // mcu peripheral memory deinitialization deInitialize_MCU(); } //-------------------------------------------------------------// ////-----------INIT WRAPPER----------- //if (hmcu.MCU_Start) // если надо получть указатель на "начало" стека //{ // сброс флаша, чтобы сюда больше не попадать // hmcu.MCU_Start = 0; // // инициализация потока, который будет выполнять код МК // hmcu.hMCUThread = (HANDLE)_beginthreadex(NULL, 0, MCU_App_Thread, 0, 0x00000004, &hmcu.idMCUThread); /* 0x00000004 - CREATE_SUSPENDED */ //} ////----------------------------------