mcu_matlab/McuLib/templates/MCU_Wrapper/mcu_wrapper.c
Razvalyaev d983f2525a release 1.01
чуть доработано:
- добавлен перенос шаблонов в проект
- убрана линковка с библиотекой для изменения маски из конфига
- исправлено изменение названия бинарника S-Function
- исправлено некорректная запись из буфера в входы/выходы и обратно
2025-06-14 23:53:50 +03:00

251 lines
9.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
**************************************************************************
* @file mcu_wrapper.c
* @brief Исходный код оболочки МК.
**************************************************************************
@details
Данный файл содержит функции для симуляции МК в Simulink (S-Function).
**************************************************************************/
#include "mcu_wrapper_conf.h"
#include "app_wrapper.h"
/**
* @addtogroup WRAPPER_CONF
* @{
*/
SIM__MCUHandleTypeDef hmcu; ///< Хендл для управления потоком программы МК
// INPUT/OUTPUTS AUTO-PARAMS START
// INPUT/OUTPUTS AUTO-PARAMS END
/** MCU_WRAPPER
* @}
*/
//-------------------------------------------------------------//
//-----------------CONTROLLER SIMULATE FUNCTIONS---------------//
/* THREAD FOR MCU APP */
#ifdef RUN_APP_MAIN_FUNC_THREAD
/**
* @brief Главная функция приложения МК.
* @details Функция с которой начинается выполнение кода МК. Выход из данной функции происходит только в конце симуляции @ref mdlTerminate
*/
extern int main(void); // extern while from main.c
/**
* @brief Поток приложения МК.
* @details Поток, который запускает и выполняет код МК (@ref main).
*/
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
}
#endif //RUN_APP_MAIN_FUNC_THREAD
/* SIMULATE MCU FOR ONE SIMULATION STEP */
/**
* @brief Симуляция МК на один такт симуляции.
* @param S - указатель на структуру S-Function из "simstruc.h"
* @param time - текущее время симуляции.
* @details Запускает поток, который выполняет код МК и управляет ходом потока:
* Если прошел таймаут, поток прерывается, симулируется периферия
* и на следующем шаге поток возобнавляется.
*
* Вызывается из mdlUpdate()
*/
void MCU_Step_Simulation(SimStruct* S, time_T time)
{
hmcu.SystemClockDouble += hmcu.sSystemClock_step; // emulate core clock
hmcu.SystemClock = hmcu.SystemClockDouble;
hmcu.SimTime = time;
MCU_readInputs(S); // считывание портов
MCU_Periph_Simulation(S); // simulate peripheral
#ifdef RUN_APP_MAIN_FUNC_THREAD
ResumeThread(hmcu.hMCUThread);
for (int i = DEKSTOP_CYCLES_FOR_MCU_APP; i > 0; i--)
{
}
SuspendThread(hmcu.hMCUThread);
#else
app_step();
#endif //RUN_APP_MAIN_FUNC_THREAD
MCU_writeOutputs(S); // запись портов (по факту запись в буфер. запись в порты в mdlOutputs)
}
/* SIMULATE MCU PERIPHERAL */
/**
* @brief Симуляция периферии МК
* @details Пользовательский код, который симулирует работу периферии МК.
*/
void MCU_Periph_Simulation(SimStruct* S)
{
// PERIPH SIM START
// PERIPH SIM END
}
/* READ INPUTS S-FUNCTION TO MCU REGS */
/**
* @brief Считывание входов S-Function в порты ввода-вывода.
* @param S - указатель на структуру S-Function из "simstruc.h"
* @details Пользовательский код, который записывает входы МК из входов S-Function.
*/
void MCU_readInputs(SimStruct* S)
{
SIM_readInputs(S);
/* Get S-Function descrete array (IO buffer) */
real_T* In_Buff = ssGetDiscStates(S);
app_readInputs(In_Buff);
}
/* WRITE OUTPUTS BUFFER S-FUNCTION FROM MCU REGS*/
/**
* @brief Запись портов ввода-вывода в буфер выхода S-Function
* @param S - указатель на структуру S-Function из "simstruc.h"
* @details Пользовательский код, который записывает буфер выходов S-Function из портов ввода-вывода.
*/
void MCU_writeOutputs(SimStruct* S)
{
/* Get S-Function descrete array (IO buffer) */
real_T* Out_Buff = ssGetDiscStates(S);
app_writeOutputBuffer(Out_Buff);
}
//-----------------CONTROLLER SIMULATE FUNCTIONS---------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//----------------------SIMULINK FUNCTIONS---------------------//
/* MCU WRAPPER DEINITIALIZATION */
/**
* @brief Инициализация симуляции МК.
* @details Пользовательский код, который создает поток для приложения МК
и настраивает симулятор МК для симуляции.
*/
void SIM_Initialize_Simulation(SimStruct* S)
{
#ifdef RUN_APP_MAIN_FUNC_THREAD
// инициализация потока, который будет выполнять код МК
hmcu.hMCUThread = (HANDLE)CreateThread(NULL, 0, MCU_App_Thread, 0, CREATE_SUSPENDED, &hmcu.idMCUThread);
#endif //RUN_APP_MAIN_FUNC_THREAD
/* user initialization */
app_init();
// PERIPH INIT START
// PERIPH INIT END
/* clock step initialization */
hmcu.sSystemClock_step = MCU_CORE_CLOCK * hmcu.sSimSampleTime; // set system clock step
hmcu.fInitDone = 1;
}
/* MCU WRAPPER DEINITIALIZATION */
/**
* @brief Деинициализация симуляции МК.
* @details Пользовательский код, который будет очищать все структуры после окончания симуляции.
*/
void SIM_deInitialize_Simulation(SimStruct* S)
{
#ifdef DEINITIALIZE_AFTER_SIM
// deinitialize app
app_deinit();
// PERIPH DEINIT START
// PERIPH DEINIT END
#endif// DEINITIALIZE_AFTER_SIM
}
/* WORK WITH IN/OUT BUFFER OF S-BLOCK */
/**
* @brief Функция для записи переменной в буфер выходов в определенный массив
* @param xD - указатель на буфер состояний
* @param value - значение для записи
* @param array_index - индекс выходного массива
* @param value_index - индекс внутри массива
*/
void __WriteOutputArray(real_T* xD, float value, int array_index, int value_index)
{
if (array_index >= OUT_PORT_NUMB)
return;
if (value_index >= outLengths[array_index])
return;
int global_index = XD_OUTPUT_START + outOffsets[array_index] + value_index;
xD[global_index] = value;
}
/**
* @brief Функция для чтения значения из буфера входов из определенного массива
* @param xD - указатель на буфер состояний
* @param array_index - индекс входного массива
* @param value_index - индекс внутри массива
* @return - считанное значение или 0.0 при выходе за границы
*/
float __ReadInputArray(const real_T* xD, int array_index, int value_index)
{
if (array_index >= IN_PORT_NUMB)
return 0.0f;
if (value_index >= inLengths[array_index])
return 0.0f;
int global_index = XD_INPUT_START + inOffsets[array_index] + value_index;
return xD[global_index];
}
/**
* @brief Формирование выходов S-Function.
* @param S - указатель на структуру S-Function из "simstruc.h"
* @details Пользовательский код, который записывает выходы S-Function из буфера дискретных состояний.
*/
void SIM_writeOutputs(SimStruct* S)
{
real_T* Output = ssGetOutputPortRealSignal(S,0);
real_T* Out_Buff = ssGetDiscStates(S);
int global_index;
//-------------WRITTING OUTPUT--------------
for (int arr_ind = 0; arr_ind < OUT_PORT_NUMB; arr_ind++)
{
Output = ssGetOutputPortRealSignal(S, arr_ind);
for (int val_ind = 0; val_ind < outLengths[arr_ind]; val_ind++)
{
global_index = XD_OUTPUT_START + outOffsets[arr_ind] + val_ind;
Output[val_ind] = Out_Buff[global_index];
Out_Buff[global_index] = 0;
}
}
//------------------------------------------
}
/**
* @brief Формирование входов S-Function.
* @param S - указатель на структуру S-Function из "simstruc.h"
* @details Пользовательский код, который считывает входы S-Function в буфер дискретных состояний.
*/
void SIM_readInputs(SimStruct* S)
{
real_T* Input = ssGetInputPortRealSignal(S, 0);
real_T* In_Buff = ssGetDiscStates(S);
int global_index;
//-------------READING INPUTS---------------
for (int arr_ind = 0; arr_ind < IN_PORT_NUMB; arr_ind++)
{
Input = ssGetInputPortRealSignal(S, arr_ind);
for (int val_ind = 0; val_ind < inLengths[arr_ind]; val_ind++)
{
global_index = XD_INPUT_START + inOffsets[arr_ind] + val_ind;
In_Buff[global_index] = Input[val_ind];
}
}
//------------------------------------------
}
//-------------------------------------------------------------//