чуть доработано: - добавлен перенос шаблонов в проект - убрана линковка с библиотекой для изменения маски из конфига - исправлено изменение названия бинарника S-Function - исправлено некорректная запись из буфера в входы/выходы и обратно
251 lines
9.7 KiB
C
251 lines
9.7 KiB
C
/**
|
||
**************************************************************************
|
||
* @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];
|
||
}
|
||
}
|
||
//------------------------------------------
|
||
}
|
||
//-------------------------------------------------------------//
|