wrapper init
This commit is contained in:
parent
24fa4d17ec
commit
aa27973f61
63
.gitignore
vendored
Normal file
63
.gitignore
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
# ---> MATLAB
|
||||
# Windows default autosave extension
|
||||
*.asv
|
||||
|
||||
# OSX / *nix default autosave extension
|
||||
*.m~
|
||||
|
||||
# Compiled MEX binaries (all platforms)
|
||||
*.mex*
|
||||
|
||||
# Packaged app and toolbox files
|
||||
*.mlappinstall
|
||||
*.mltbx
|
||||
|
||||
# Generated helpsearch folders
|
||||
helpsearch*/
|
||||
|
||||
# Simulink code generation folders
|
||||
slprj/
|
||||
sccprj/
|
||||
|
||||
# Matlab code generation folders
|
||||
codegen/
|
||||
|
||||
# Simulink autosave extension
|
||||
*.autosave
|
||||
|
||||
# Simulink cache files
|
||||
*.slxc
|
||||
|
||||
# Octave session info
|
||||
octave-workspace
|
||||
|
||||
|
||||
/.vs/Inu_im_2wnd_3lvl_23550/v16/.suo
|
||||
/.vs/Inu_im_2wnd_3lvl_23550/v16/Browse.VC.db
|
||||
/.vs/Inu_im_2wnd_3lvl_23550/v16/Browse.VC.db-shm
|
||||
/.vs/Inu_im_2wnd_3lvl_23550/v16/Browse.VC.db-wal
|
||||
/.vs/Inu_im_2wnd_3lvl_23550/v16/Browse.VC.opendb
|
||||
/.vs/ProjectSettings.json
|
||||
/.vs/slnx.sqlite
|
||||
/slprj/_cgxe/inu_im_2wnd_3lvl/inu_im_2wnd_3lvl_Cache.mat
|
||||
/slprj/_jitprj/4jSHq6tpkAOru8OWjpPNFB.l
|
||||
/slprj/_jitprj/4jSHq6tpkAOru8OWjpPNFB.mat
|
||||
/slprj/accel/inu_im_2wnd_3lvl/amsi_serial.mat
|
||||
/slprj/accel/inu_im_2wnd_3lvl/inu_im_2wnd_3lvl_instrumentation_settings.mat
|
||||
/slprj/accel/inu_im_2wnd_3lvl/inu_im_2wnd_3lvl_SolverChangeInfo.mat
|
||||
/slprj/accel/inu_im_2wnd_3lvl/inu_im_2wnd_3lvl_top_vm.bc
|
||||
/slprj/accel/inu_im_2wnd_3lvl/inu_im_2wnd_3lvl_top_vm.ll
|
||||
/slprj/accel/inu_im_2wnd_3lvl/tmwinternal/simulink_cache.xml
|
||||
/slprj/sim/varcache/inu_im_2wnd_3lvl/checksumOfCache.mat
|
||||
/slprj/sim/varcache/inu_im_2wnd_3lvl/tmwinternal/simulink_cache.xml
|
||||
/slprj/sim/varcache/inu_im_2wnd_3lvl/varInfo.mat
|
||||
/slprj/sl_proj.tmw
|
||||
|
||||
|
||||
|
||||
/slprj/
|
||||
/.vs/
|
||||
|
||||
|
||||
init.m
|
||||
inu_23550.slx
|
205
Inu/MCU.c
Normal file
205
Inu/MCU.c
Normal file
@ -0,0 +1,205 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file MCU.c
|
||||
* @brief Исходный код S-Function.
|
||||
**************************************************************************
|
||||
@details
|
||||
Данный файл содержит функции S-Function, который вызывает MATLAB.
|
||||
**************************************************************************
|
||||
@note
|
||||
Описание функций по большей части сгенерировано MATLAB'ом, поэтому на английском
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup WRAPPER_SFUNC S-Function funtions
|
||||
* @ingroup MCU_WRAPPER
|
||||
* @brief Дефайны и функции блока S-Function
|
||||
* @details Здесь собраны функции, с которыми непосредственно работает S-Function
|
||||
* @note Описание функций по большей части сгенерировано MATLAB'ом, поэтому на английском
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define S_FUNCTION_NAME wrapper_inu
|
||||
#define S_FUNCTION_LEVEL 2
|
||||
|
||||
#include "mcu_wrapper_conf.h"
|
||||
|
||||
#define MDL_UPDATE ///< для подключения mdlUpdate()
|
||||
/**
|
||||
* @brief Update S-Function at every step of simulation
|
||||
* @param S - pointer to S-Function (library struct from "simstruc.h")
|
||||
* @details Abstract:
|
||||
* This function is called once for every major integration time step.
|
||||
* Discrete states are typically updated here, but this function is useful
|
||||
* for performing any tasks that should only take place once per
|
||||
* integration step.
|
||||
*/
|
||||
static void mdlUpdate(SimStruct *S)
|
||||
{
|
||||
// get time of simulation
|
||||
time_T TIME = ssGetT(S);
|
||||
|
||||
//---------------SIMULATE MCU---------------
|
||||
MCU_Step_Simulation(S, TIME); // SIMULATE MCU
|
||||
//------------------------------------------
|
||||
}//end mdlUpdate
|
||||
|
||||
/**
|
||||
* @brief Writting outputs of S-Function
|
||||
* @param S - pointer to S-Function (library struct from "simstruc.h")
|
||||
* @details Abstract:
|
||||
* In this function, you compute the outputs of your S-function
|
||||
* block. Generally outputs are placed in the output vector(s),
|
||||
* ssGetOutputPortSignal.
|
||||
*/
|
||||
static void mdlOutputs(SimStruct *S)
|
||||
{
|
||||
SIM_writeOutputs(S);
|
||||
}//end mdlOutputs
|
||||
|
||||
#define MDL_CHECK_PARAMETERS /* Change to #undef to remove function */
|
||||
#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)
|
||||
static void mdlCheckParameters(SimStruct *S)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Проверяем и принимаем параметры и разрешаем или запрещаем их менять
|
||||
// в процессе моделирования
|
||||
for (i=0; i<1; i++)
|
||||
{
|
||||
// Input parameter must be scalar or vector of type double
|
||||
if (!mxIsDouble(ssGetSFcnParam(S,i)) || mxIsComplex(ssGetSFcnParam(S,i)) ||
|
||||
mxIsEmpty(ssGetSFcnParam(S,i)))
|
||||
{
|
||||
ssSetErrorStatus(S,"Input parameter must be of type double");
|
||||
return;
|
||||
}
|
||||
// Параметр м.б. только скаляром, вектором или матрицей
|
||||
if (mxGetNumberOfDimensions(ssGetSFcnParam(S,i)) > 2)
|
||||
{
|
||||
ssSetErrorStatus(S,"Параметр м.б. только скаляром, вектором или матрицей");
|
||||
return;
|
||||
}
|
||||
// sim_dt = mxGetPr(ssGetSFcnParam(S,0))[0];
|
||||
// Parameter not tunable
|
||||
// ssSetSFcnParamTunable(S, i, SS_PRM_NOT_TUNABLE);
|
||||
// Parameter tunable (we must create a corresponding run-time parameter)
|
||||
ssSetSFcnParamTunable(S, i, SS_PRM_TUNABLE);
|
||||
// Parameter tunable only during simulation
|
||||
// ssSetSFcnParamTunable(S, i, SS_PRM_SIM_ONLY_TUNABLE);
|
||||
|
||||
}//for (i=0; i<NPARAMS; i++)
|
||||
|
||||
}//end mdlCheckParameters
|
||||
#endif //MDL_CHECK_PARAMETERS
|
||||
static void mdlInitializeSizes(SimStruct *S)
|
||||
{
|
||||
ssSetNumSFcnParams(S, 1);
|
||||
// Кол-во ожидаемых и фактических параметров должно совпадать
|
||||
if(ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S))
|
||||
{
|
||||
// Проверяем и принимаем параметры
|
||||
mdlCheckParameters(S);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;// Parameter mismatch will be reported by Simulink
|
||||
}
|
||||
|
||||
// set up discrete states
|
||||
ssSetNumContStates(S, 0); // number of continuous states
|
||||
ssSetNumDiscStates(S, DISC_STATES_WIDTH); // number of discrete states
|
||||
|
||||
// set up input port
|
||||
if (!ssSetNumInputPorts(S, 1)) return;
|
||||
for (int i = 0; i < IN_PORT_NUMB; i++)
|
||||
ssSetInputPortWidth(S, i, IN_PORT_WIDTH);
|
||||
ssSetInputPortDirectFeedThrough(S, 0, 0);
|
||||
ssSetInputPortRequiredContiguous(S, 0, 1); // direct input signal access
|
||||
|
||||
// set up output port
|
||||
if (!ssSetNumOutputPorts(S, OUT_PORT_NUMB)) return;
|
||||
for (int i = 0; i < OUT_PORT_NUMB; i++)
|
||||
ssSetOutputPortWidth(S, i, OUT_PORT_WIDTH);
|
||||
|
||||
|
||||
ssSetNumSampleTimes(S, 1);
|
||||
|
||||
|
||||
ssSetNumRWork( S, 5); // number of real work vector elements
|
||||
ssSetNumIWork( S, 5); // number of integer work vector elements
|
||||
ssSetNumPWork( S, 0); // number of pointer work vector elements
|
||||
ssSetNumModes( S, 0); // number of mode work vector elements
|
||||
ssSetNumNonsampledZCs( S, 0); // number of nonsampled zero crossings
|
||||
|
||||
|
||||
ssSetRuntimeThreadSafetyCompliance(S, RUNTIME_THREAD_SAFETY_COMPLIANCE_TRUE);
|
||||
/* Take care when specifying exception free code - see sfuntmpl.doc */
|
||||
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#define MDL_START /* Change to #undef to remove function */
|
||||
#if defined(MDL_START)
|
||||
/**
|
||||
* @brief Initialize S-Function at start of simulation
|
||||
* @param S - pointer to S-Function (library struct from "simstruc.h")
|
||||
* @details Abstract:
|
||||
* This function is called once at start of model execution. If you
|
||||
* have states that should be initialized once, this is the place
|
||||
* to do it.
|
||||
*/
|
||||
static void mdlStart(SimStruct *S)
|
||||
{
|
||||
SIM_Initialize_Simulation();
|
||||
}
|
||||
#endif // MDL_START
|
||||
|
||||
/**
|
||||
* @brief Initialize Sample Time of Simulation
|
||||
* @param S - pointer to S-Function (library struct from "simstruc.h")
|
||||
* @details Abstract:
|
||||
* This function is used to specify the sample time(s) for your
|
||||
* S-function. You must register the same number of sample times as
|
||||
* specified in ssSetNumSampleTimes.
|
||||
*/
|
||||
static void mdlInitializeSampleTimes(SimStruct *S)
|
||||
{
|
||||
// Шаг дискретизации
|
||||
hmcu.sSimSampleTime = mxGetPr(ssGetSFcnParam(S,NPARAMS-1))[0];
|
||||
|
||||
// Register one pair for each sample time
|
||||
ssSetSampleTime(S, 0, hmcu.sSimSampleTime);
|
||||
ssSetOffsetTime(S, 0, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Terminate S-Function at the end of simulation
|
||||
* @param S - pointer to S-Function (library struct from "simstruc.h")
|
||||
* @details Abstract:
|
||||
* In this function, you should perform any actions that are necessary
|
||||
* at the termination of a simulation. For example, if memory was
|
||||
* allocated in mdlStart, this is the place to free it.
|
||||
*/
|
||||
static void mdlTerminate(SimStruct *S)
|
||||
{
|
||||
hmcu.fMCU_Stop = 1;
|
||||
ResumeThread(hmcu.hMCUThread);
|
||||
WaitForSingleObject(hmcu.hMCUThread, 10000);
|
||||
SIM_deInitialize_Simulation();
|
||||
mexUnlock();
|
||||
}
|
||||
|
||||
|
||||
/** WRAPPER_SFUNC
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a
|
||||
MEX-file? */
|
||||
#include "simulink.c" /* MEX-file interface mechanism */
|
||||
#else
|
||||
#include "cg_sfun.h" /* Code generation registration
|
||||
function */
|
||||
#endif
|
1
Inu/app_wrapper
Submodule
1
Inu/app_wrapper
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 876b8d9f9a896d524b3945ec346f2708a627feba
|
176
Inu/mcu_wrapper.c
Normal file
176
Inu/mcu_wrapper.c
Normal file
@ -0,0 +1,176 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file mcu_wrapper.c
|
||||
* @brief Исходный код оболочки МК.
|
||||
**************************************************************************
|
||||
@details
|
||||
Данный файл содержит функции для симуляции МК в Simulink (S-Function).
|
||||
**************************************************************************/
|
||||
#include "mcu_wrapper_conf.h"
|
||||
#include "app_init.h"
|
||||
#include "app_io.h"
|
||||
#include "pwm_sim.h"
|
||||
|
||||
/**
|
||||
* @addtogroup WRAPPER_CONF
|
||||
* @{
|
||||
*/
|
||||
|
||||
SIM__MCUHandleTypeDef hmcu; ///< Хендл для управления потоком программы МК
|
||||
|
||||
/** 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(); // 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);
|
||||
#endif //RUN_APP_MAIN_FUNC_THREAD
|
||||
|
||||
MCU_writeOutputs(S); // запись портов (по факту запись в буфер. запись в порты в mdlOutputs)
|
||||
}
|
||||
|
||||
/* SIMULATE MCU PERIPHERAL */
|
||||
/**
|
||||
* @brief Симуляция периферии МК
|
||||
* @details Пользовательский код, который симулирует работу периферии МК.
|
||||
*/
|
||||
void MCU_Periph_Simulation(void)
|
||||
{
|
||||
Simulate_PWM();
|
||||
}
|
||||
|
||||
/* READ INPUTS S-FUNCTION TO MCU REGS */
|
||||
/**
|
||||
* @brief Считывание входов S-Function в порты ввода-вывода.
|
||||
* @param S - указатель на структуру S-Function из "simstruc.h"
|
||||
* @details Пользовательский код, который записывает входы МК из входов S-Function.
|
||||
*/
|
||||
void MCU_readInputs(SimStruct* S)
|
||||
{
|
||||
/* Get S-Function inputs */
|
||||
real_T* IN = ssGetInputPortRealSignal(S, 0);
|
||||
|
||||
readInputParameters(IN);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
real_T* Out_Buff = ssGetDiscStates(S);
|
||||
|
||||
writeOutputParameters(Out_Buff);
|
||||
}
|
||||
//-----------------CONTROLLER SIMULATE FUNCTIONS---------------//
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------//
|
||||
//----------------------SIMULINK FUNCTIONS---------------------//
|
||||
/* MCU WRAPPER DEINITIALIZATION */
|
||||
/**
|
||||
* @brief Инициализация симуляции МК.
|
||||
* @details Пользовательский код, который создает поток для приложения МК
|
||||
и настраивает симулятор МК для симуляции.
|
||||
*/
|
||||
void SIM_Initialize_Simulation(void)
|
||||
{
|
||||
#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 */
|
||||
Init_PWM_Simulation();
|
||||
app_init();
|
||||
|
||||
/* clock step initialization */
|
||||
hmcu.sSystemClock_step = MCU_CORE_CLOCK * hmcu.sSimSampleTime; // set system clock step
|
||||
}
|
||||
/* MCU WRAPPER DEINITIALIZATION */
|
||||
/**
|
||||
* @brief Деинициализация симуляции МК.
|
||||
* @details Пользовательский код, который будет очищать все структуры после окончания симуляции.
|
||||
*/
|
||||
void SIM_deInitialize_Simulation(void)
|
||||
{
|
||||
//// simulate structures of peripheral deinitialization
|
||||
//deInitialize_Periph_Sim();
|
||||
//// mcu peripheral memory deinitialization
|
||||
//deInitialize_MCU();
|
||||
}
|
||||
/* WRITE OUTPUTS OF S-BLOCK */
|
||||
/**
|
||||
* @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);
|
||||
|
||||
//-------------WRITTING OUTPUT--------------
|
||||
for (int i = 0; i < OUT_PORT_WIDTH; i++)
|
||||
Output[i] = Out_Buff[i];
|
||||
//for (int j = 0; j < OUT_PORT_NUMB; j++)
|
||||
//{
|
||||
// GPIO = ssGetOutputPortRealSignal(S, j);
|
||||
// for (int i = 0; i < OUT_PORT_WIDTH; i++)
|
||||
// {
|
||||
// GPIO[i] = Out_Buff[j * OUT_PORT_WIDTH + i];
|
||||
// Out_Buff[j * OUT_PORT_WIDTH + i] = 0;
|
||||
// }
|
||||
//}
|
||||
//------------------------------------------
|
||||
}
|
||||
//-------------------------------------------------------------//
|
180
Inu/mcu_wrapper_conf.h
Normal file
180
Inu/mcu_wrapper_conf.h
Normal file
@ -0,0 +1,180 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @dir ../MCU_Wrapper
|
||||
* @brief <b> Папка с исходным кодом оболочки МК. </b>
|
||||
* @details
|
||||
В этой папке содержаться оболочка(англ. wrapper) для запуска и контроля
|
||||
эмуляции микроконтроллеров в MATLAB (любого МК, не только STM).
|
||||
Оболочка представляет собой S-Function - блок в Simulink, который работает
|
||||
по скомпилированому коду. Компиляция происходит с помощью MSVC-компилятора.
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file mcu_wrapper_conf.h
|
||||
* @brief Заголовочный файл для оболочки МК.
|
||||
**************************************************************************
|
||||
@details
|
||||
Главный заголовочный файл для матлаба. Включает дейфайны для S-Function,
|
||||
объявляет базовые функции для симуляции МК и подключает базовые библиотеки:
|
||||
- для симуляции "stm32fxxx_matlab_conf.h"
|
||||
- для S-Function "simstruc.h"
|
||||
- для потоков <process.h>
|
||||
**************************************************************************/
|
||||
#ifndef _WRAPPER_CONF_H_
|
||||
#define _WRAPPER_CONF_H_
|
||||
|
||||
// Includes
|
||||
#include "simstruc.h" // For S-Function variables
|
||||
#include <process.h> // For threads
|
||||
|
||||
#include "app_includes.h"
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup MCU_WRAPPER MCU Wrapper
|
||||
* @brief Всякое для оболочки МК
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup WRAPPER_CONF Wrapper Configuration
|
||||
* @ingroup MCU_WRAPPER
|
||||
* @brief Параметры конфигурации для оболочки МК
|
||||
* @details Здесь дефайнами задается параметры оболочки, которые определяют как она будет работать
|
||||
* @{
|
||||
*/
|
||||
|
||||
// Parametrs of MCU simulator
|
||||
//#define RUN_APP_MAIN_FUNC_THREAD ///< Enable using thread for MCU main() func
|
||||
#define DEKSTOP_CYCLES_FOR_MCU_APP 0xFFFF ///< number of for() cycles after which MCU thread would be suspended
|
||||
#define MCU_CORE_CLOCK 150000000 ///< MCU clock rate for simulation
|
||||
|
||||
// Parameters of S_Function
|
||||
#define IN_PORT_WIDTH 20 ///< width of input ports
|
||||
#define IN_PORT_NUMB 1 ///< number of input ports
|
||||
#define OUT_PORT_WIDTH 51 ///< width of output ports
|
||||
#define OUT_PORT_NUMB 1 ///< number of output ports
|
||||
|
||||
|
||||
#define RWORK_0_WIDTH 5 //width of the real-work vector
|
||||
#define IWORK_0_WIDTH 5 //width of the integer-work vector
|
||||
|
||||
|
||||
/** WRAPPER_CONF
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup MCU_WRAPPER
|
||||
* @{
|
||||
*/
|
||||
|
||||
// Fixed parameters(?) of S_Function
|
||||
#define NPARAMS 1 ///< number of input parametrs (only Ts)
|
||||
#define DISC_STATES_WIDTH OUT_PORT_WIDTH*OUT_PORT_NUMB ///< width of discrete states array (outbup buffer)
|
||||
/**
|
||||
* @brief Define for creating thread in suspended state.
|
||||
* @details Define from WinBase.h. We dont wanna include "Windows.h" or smth like this, because of HAL there are a lot of redefine errors.
|
||||
*/
|
||||
#define CREATE_SUSPENDED 0x00000004
|
||||
typedef void* HANDLE; ///< MCU handle typedef
|
||||
|
||||
/**
|
||||
* @brief MCU handle Structure definition.
|
||||
* @note Prefixes: h - handle, s - settings, f - flag
|
||||
*/
|
||||
typedef struct {
|
||||
// MCU Thread
|
||||
HANDLE hMCUThread; ///< Хендл для потока МК
|
||||
int idMCUThread; ///< id потока МК (unused)
|
||||
// Flags
|
||||
unsigned fMCU_Stop : 1; ///< флаг для выхода из потока программы МК
|
||||
|
||||
double SimTime; ///< Текущее время симуляции
|
||||
long SystemClock; ///< Счетчик тактов для симуляции системных тиков (в целочисленном формате)
|
||||
|
||||
double SystemClockDouble; ///< Счетчик в формате double для точной симуляции системных тиков С промежуточными значений
|
||||
double sSystemClock_step; ///< Шаг тиков для их симуляции, в формате double
|
||||
double sSimSampleTime; ///< Период дискретизации симуляции
|
||||
}SIM__MCUHandleTypeDef;
|
||||
extern SIM__MCUHandleTypeDef hmcu; // extern для видимости переменной во всех файлах
|
||||
|
||||
//-------------------------------------------------------------//
|
||||
//------------------ SIMULINK WHILE DEFINES -----------------//
|
||||
#ifdef RUN_APP_MAIN_FUNC_THREAD
|
||||
/* DEFINE TO WHILE WITH SIMULINK WHILE */
|
||||
/**
|
||||
* @brief Redefine C while statement with sim_while() macro.
|
||||
* @param _expression_ - expression for while.
|
||||
* @details Это while который будет использоваться в симулинке @ref sim_while для подробностей.
|
||||
*/
|
||||
#define while(_expression_) sim_while(_expression_)
|
||||
#endif
|
||||
|
||||
/* SIMULINK WHILE */
|
||||
/**
|
||||
* @brief While statement for emulate MCU code in Simulink.
|
||||
* @param _expression_ - expression for while.
|
||||
* @details Данный while необходим, чтобы в конце симуляции, завершить поток МК:
|
||||
* При выставлении флага окончания симуляции, все while будут пропускаться
|
||||
* и поток сможет дойти до конца функции main и завершить себя.
|
||||
*/
|
||||
#define sim_while(_expression_) while((_expression_)&&(hmcu.fMCU_Stop == 0))
|
||||
|
||||
/* DEFAULT WHILE */
|
||||
/**
|
||||
* @brief Default/Native C while statement.
|
||||
* @param _expression_ - expression for while.
|
||||
* @details Данный while - аналог обычного while, без дополнительного функционала.
|
||||
*/
|
||||
#define native_while(_expression_) for(; (_expression_); )
|
||||
/***************************************************************/
|
||||
|
||||
//------------------ SIMULINK WHILE DEFINES -----------------//
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------//
|
||||
//---------------- SIMULATE FUNCTIONS PROTOTYPES -------------//
|
||||
/* Step simulation */
|
||||
void MCU_Step_Simulation(SimStruct *S, time_T time);
|
||||
|
||||
/* MCU peripheral simulation */
|
||||
void MCU_Periph_Simulation(void);
|
||||
|
||||
/* Initialize MCU simulation */
|
||||
void SIM_Initialize_Simulation(void);
|
||||
|
||||
/* Deinitialize MCU simulation */
|
||||
void SIM_deInitialize_Simulation(void);
|
||||
|
||||
/* Read inputs S-function */
|
||||
void MCU_readInputs(SimStruct* S);
|
||||
|
||||
/* Write pre-outputs S-function (out_buff states) */
|
||||
void MCU_writeOutputs(SimStruct* S);
|
||||
|
||||
/* Write outputs of block of S-Function*/
|
||||
void SIM_writeOutput(SimStruct* S);
|
||||
//---------------- SIMULATE FUNCTIONS PROTOTYPES -------------//
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
/** MCU_WRAPPER
|
||||
* @}
|
||||
*/
|
||||
#endif // _WRAPPER_CONF_H_
|
||||
|
||||
|
||||
//-------------------------------------------------------------//
|
||||
//---------------------BAT FILE DESCRIBTION--------------------//
|
||||
/**
|
||||
* @file run_mex.bat
|
||||
* @brief Батник для компиляции оболочки МК.
|
||||
* @details
|
||||
* Вызывается в матлабе из allmex.m.
|
||||
*
|
||||
* Исходный код батника:
|
||||
* @include run_mex.bat
|
||||
*/
|
3
Inu/xilinx_wrapper/adc_sim.c
Normal file
3
Inu/xilinx_wrapper/adc_sim.c
Normal file
@ -0,0 +1,3 @@
|
||||
#include "adc_sim.h"
|
||||
|
||||
AdcSimHandle adcsim;
|
12
Inu/xilinx_wrapper/adc_sim.h
Normal file
12
Inu/xilinx_wrapper/adc_sim.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef PWM_SIM
|
||||
#define PWM_SIM
|
||||
|
||||
// Äëÿ ìîäåëèðîâàíèÿ ADC
|
||||
typedef struct
|
||||
{
|
||||
int tAdc;
|
||||
int Tadc;
|
||||
int nAdc;
|
||||
}AdcSimHandle;
|
||||
|
||||
#endif //PWM_SIM
|
291
Inu/xilinx_wrapper/pwm_sim.c
Normal file
291
Inu/xilinx_wrapper/pwm_sim.c
Normal file
@ -0,0 +1,291 @@
|
||||
#include "pwm_sim.h"
|
||||
|
||||
TimerSimHandle t1sim;
|
||||
TimerSimHandle t2sim;
|
||||
TimerSimHandle t3sim;
|
||||
TimerSimHandle t4sim;
|
||||
TimerSimHandle t5sim;
|
||||
TimerSimHandle t6sim;
|
||||
TimerSimHandle t7sim;
|
||||
TimerSimHandle t8sim;
|
||||
TimerSimHandle t9sim;
|
||||
TimerSimHandle t10sim;
|
||||
TimerSimHandle t11sim;
|
||||
TimerSimHandle t12sim;
|
||||
|
||||
PWMPhaseSimHandle PWMPhaseA1;
|
||||
PWMPhaseSimHandle PWMPhaseB1;
|
||||
PWMPhaseSimHandle PWMPhaseC1;
|
||||
PWMPhaseSimHandle PWMPhaseA2;
|
||||
PWMPhaseSimHandle PWMPhaseB2;
|
||||
PWMPhaseSimHandle PWMPhaseC2;
|
||||
|
||||
void Simulate_PWM(void)
|
||||
{
|
||||
Simulate_PWMPhase(&PWMPhaseA1, xpwm_time.Ta0_1, xpwm_time.Ta0_0);
|
||||
Simulate_PWMPhase(&PWMPhaseB1, xpwm_time.Tb0_1, xpwm_time.Tb0_0);
|
||||
Simulate_PWMPhase(&PWMPhaseC1, xpwm_time.Tc0_1, xpwm_time.Tc0_0);
|
||||
Simulate_PWMPhase(&PWMPhaseA2, xpwm_time.Ta1_1, xpwm_time.Ta1_0);
|
||||
Simulate_PWMPhase(&PWMPhaseB2, xpwm_time.Tb1_1, xpwm_time.Tb1_0);
|
||||
Simulate_PWMPhase(&PWMPhaseC2, xpwm_time.Tc1_1, xpwm_time.Tc1_0);
|
||||
}
|
||||
|
||||
void Init_PWM_Simulation(void)
|
||||
{
|
||||
Init_PWMPhase_Simulation(&PWMPhaseA1, &t1sim, &t2sim,
|
||||
PWM_PERIOD, PWM_TICK_STEP);
|
||||
|
||||
Init_PWMPhase_Simulation(&PWMPhaseB1, &t3sim, &t4sim,
|
||||
PWM_PERIOD, PWM_TICK_STEP);
|
||||
|
||||
Init_PWMPhase_Simulation(&PWMPhaseC1, &t5sim, &t6sim,
|
||||
PWM_PERIOD, PWM_TICK_STEP);
|
||||
|
||||
Init_PWMPhase_Simulation(&PWMPhaseA2, &t7sim, &t8sim,
|
||||
PWM_PERIOD, PWM_TICK_STEP);
|
||||
|
||||
Init_PWMPhase_Simulation(&PWMPhaseB2, &t9sim, &t10sim,
|
||||
PWM_PERIOD, PWM_TICK_STEP);
|
||||
|
||||
Init_PWMPhase_Simulation(&PWMPhaseC2, &t11sim, &t12sim,
|
||||
PWM_PERIOD, PWM_TICK_STEP);
|
||||
|
||||
|
||||
t1sim.simulatePwm = (void (*)())Simulate_MainTIM;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Simulate_PWMPhase(PWMPhaseSimHandle* tksim, int T1, int T0)
|
||||
{
|
||||
tksim->tsim1->simulatePwm(tksim->tsim1, T1);
|
||||
tksim->tsim2->simulatePwm(tksim->tsim2, T0);
|
||||
|
||||
#ifdef PWM_SIMULATION_MODE_TK_LINES
|
||||
convertSVGenTimesToTkLines(tksim);
|
||||
xilinxPwm3LevelSimulation(tksim);
|
||||
#endif
|
||||
|
||||
#ifdef PWM_SIMULATION_MODE_REGULAR_PWM
|
||||
simulateActionActionQualifierSubmodule(tksim->tsim1);
|
||||
simulateDeadBendSubmodule(tksim->tsim1, &tksim->pwmOut.ci1A, &tksim->pwmOut.ci1B);
|
||||
simulateTripZoneSubmodule(tksim->tsim1);
|
||||
|
||||
simulateActionActionQualifierSubmodule(tksim->tsim2);
|
||||
simulateDeadBendSubmodule(tksim->tsim2, &tksim->pwmOut.ci2A, &tksim->pwmOut.ci2B);
|
||||
simulateTripZoneSubmodule(tksim->tsim2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Simulate_MainTIM(TimerSimHandle* tsim, int compare)
|
||||
{
|
||||
#ifdef ENABLE_UNITED_COUNTER_FOR_ALL_PWM
|
||||
tsim->tcntAuxPrev = tsim->tcntAux;
|
||||
tsim->tcntAux += tsim->TxCntPlus;
|
||||
#endif
|
||||
if (simulateTimAndGetCompare(tsim, compare))
|
||||
mcu_simulate_step();
|
||||
}
|
||||
|
||||
void Simulate_SimpleTIM(TimerSimHandle* tsim, int compare)
|
||||
{
|
||||
simulateTimAndGetCompare(tsim, compare);
|
||||
}
|
||||
|
||||
|
||||
int simulateTimAndGetCompare(TimerSimHandle* tsim, int compare)
|
||||
{
|
||||
int interruptflag = 0;
|
||||
|
||||
#ifdef ENABLE_UNITED_COUNTER_FOR_ALL_PWM
|
||||
tsim->tcntAuxPrev = t1sim.tcntAuxPrev;
|
||||
tsim->tcntAux = t1sim.tcntAux;
|
||||
#else
|
||||
tsim->tcntAuxPrev = tsim->tcntAux;
|
||||
tsim->tcntAux += tsim->TxCntPlus;
|
||||
#endif
|
||||
|
||||
if (tsim->tcntAux > tsim->TxPeriod) {
|
||||
tsim->tcntAux -= tsim->TxPeriod * 2.;
|
||||
tsim->cmpA = compare;
|
||||
interruptflag = 1;
|
||||
}
|
||||
if ((tsim->tcntAuxPrev < 0) && (tsim->tcntAux >= 0)) {
|
||||
tsim->cmpA = compare;
|
||||
interruptflag = 1;
|
||||
}
|
||||
tsim->tcnt = fabs(tsim->tcntAux);
|
||||
return interruptflag;
|
||||
}
|
||||
|
||||
|
||||
void convertSVGenTimesToTkLines(PWMPhaseSimHandle *tksim) {
|
||||
TimerSimHandle* tsim1 = tksim->tsim1;
|
||||
TimerSimHandle* tsim2 = tksim->tsim2;
|
||||
//Phase Uni
|
||||
if ((tsim1->cmpA < tsim1->tcnt) && (tsim2->cmpA < tsim2->tcnt)) {
|
||||
tksim->tkLineA = 0;
|
||||
tksim->tkLineB = 1;
|
||||
}
|
||||
else if ((tsim1->cmpA > tsim1->tcnt) && (tsim2->cmpA > tsim2->tcnt)) {
|
||||
tksim->tkLineA = 1;
|
||||
tksim->tkLineB = 0;
|
||||
}
|
||||
else if ((tsim1->cmpA < tsim1->tcnt) && (tsim2->cmpA > tsim2->tcnt)) {
|
||||
//Îøèáêà. Çàäàíèå íà îòêðûòèå âåðõíèõ è íèæíèõ êëþ÷åé îäíîâðåìåííî. Çàêðûâàåì.
|
||||
tksim->tkLineA = 1;
|
||||
tksim->tkLineB = 1;
|
||||
}
|
||||
else {
|
||||
tksim->tkLineA = 0;
|
||||
tksim->tkLineB = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void xilinxPwm3LevelSimulation(PWMPhaseSimHandle *tksim) {
|
||||
TimerSimHandle* tsim1 = tksim->tsim1;
|
||||
TimerSimHandle* tsim2 = tksim->tsim2;
|
||||
DeadTimeSimHandle* deadtime = &tksim->deadtime;
|
||||
PWMPhaseOutput* pwmOut = &tksim->pwmOut;
|
||||
|
||||
//Ïðåîáðàçóåì ñîñòîÿíèå ëèíèé ÒÊ â ñèãíàëû óïðàâëåíèÿ êëþ÷àìè
|
||||
//PhaseA Uni1
|
||||
if (tksim->tkLineB == 0 && tksim->tkLineA == 1) {
|
||||
if ((pwmOut->ci1A == 0 || pwmOut->ci2A == 0) && deadtime->stateDt == stateDtReady) {
|
||||
pwmOut->ci1B = 0;
|
||||
pwmOut->ci2B = 0;
|
||||
deadtime->dtcnt = deadtime->DtPeriod;
|
||||
deadtime->stateDt = stateDtWait;
|
||||
}
|
||||
if (deadtime->stateDt == stateDtWait) {
|
||||
if (deadtime->dtcnt > 0)
|
||||
deadtime->dtcnt--;
|
||||
else
|
||||
deadtime->stateDt = stateDtReady;
|
||||
}
|
||||
if (deadtime->stateDt == stateDtReady) {
|
||||
pwmOut->ci1A = 1;
|
||||
pwmOut->ci2A = 1;
|
||||
pwmOut->ci1B = 0;
|
||||
pwmOut->ci2B = 0;
|
||||
}
|
||||
}
|
||||
else if (tksim->tkLineB == 1 && tksim->tkLineA == 0) {
|
||||
if ((pwmOut->ci1B == 0 || pwmOut->ci2B == 0) && deadtime->stateDt == stateDtReady) {
|
||||
pwmOut->ci1A = 0;
|
||||
pwmOut->ci2B = 0;
|
||||
deadtime->dtcnt = deadtime->DtPeriod;
|
||||
deadtime->stateDt = stateDtWait;
|
||||
}
|
||||
if (deadtime->stateDt == stateDtWait) {
|
||||
if (deadtime->dtcnt > 0)
|
||||
deadtime->dtcnt--;
|
||||
else
|
||||
deadtime->stateDt = stateDtReady;
|
||||
}
|
||||
if (deadtime->stateDt == stateDtReady) {
|
||||
pwmOut->ci1A = 0;
|
||||
pwmOut->ci2A = 0;
|
||||
pwmOut->ci1B = 1;
|
||||
pwmOut->ci2B = 1;
|
||||
}
|
||||
}
|
||||
else if (tksim->tkLineA == 0 && tksim->tkLineB == 0) {
|
||||
if ((pwmOut->ci1B == 0 || pwmOut->ci2A == 0) && deadtime->stateDt == stateDtReady) {
|
||||
pwmOut->ci1A = 0;
|
||||
pwmOut->ci2B = 0;
|
||||
deadtime->dtcnt = deadtime->DtPeriod;
|
||||
deadtime->stateDt = stateDtWait;
|
||||
}
|
||||
if (deadtime->stateDt == stateDtWait) {
|
||||
if (deadtime->dtcnt > 0)
|
||||
deadtime->dtcnt--;
|
||||
else
|
||||
deadtime->stateDt = stateDtReady;
|
||||
}
|
||||
if (deadtime->stateDt == stateDtReady) {
|
||||
pwmOut->ci1A = 0;
|
||||
pwmOut->ci2A = 1;
|
||||
pwmOut->ci1B = 1;
|
||||
pwmOut->ci2B = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pwmOut->ci1A = 0;
|
||||
pwmOut->ci2A = 0;
|
||||
pwmOut->ci1B = 0;
|
||||
pwmOut->ci2B = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void simulateActionActionQualifierSubmodule(TimerSimHandle* tsim)
|
||||
{
|
||||
// Ìîäåëèðóåì Action-Qualifier Submodule
|
||||
if (tsim->cmpA > tsim->tcnt) {
|
||||
tsim->deadtime.pre_ciA = 0;
|
||||
tsim->deadtime.pre_ciB = 1;
|
||||
}
|
||||
else if (tsim->cmpA < tsim->tcnt) {
|
||||
tsim->deadtime.pre_ciA = 1;
|
||||
tsim->deadtime.pre_ciB = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void simulateDeadBendSubmodule(TimerSimHandle* tsim, int* ciA, int* ciB)
|
||||
{
|
||||
// Ìîäåëèðóåì Dead-Band Submodule
|
||||
if (tsim->deadtime.stateDt == 0) {
|
||||
*ciA = tsim->deadtime.pre_ciA;
|
||||
*ciB = 0;
|
||||
if (tsim->deadtime.pre_ciA == 1)
|
||||
tsim->deadtime.dtcnt = tsim->deadtime.DtPeriod;
|
||||
if (tsim->deadtime.dtcnt > 0)
|
||||
tsim->deadtime.dtcnt--;
|
||||
else
|
||||
tsim->deadtime.stateDt = 1;
|
||||
}
|
||||
else if (tsim->deadtime.stateDt == 1) {
|
||||
*ciA = 0;
|
||||
*ciB = tsim->deadtime.pre_ciB;
|
||||
if (tsim->deadtime.pre_ciB == 1)
|
||||
tsim->deadtime.dtcnt = tsim->deadtime.DtPeriod;
|
||||
if (tsim->deadtime.dtcnt > 0)
|
||||
tsim->deadtime.dtcnt--;
|
||||
else
|
||||
tsim->deadtime.stateDt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void simulateTripZoneSubmodule(TimerSimHandle* tsim)
|
||||
{
|
||||
// Ìîäåëèðóåì Trip-Zone Submodule
|
||||
// ... clear flag for one-shot trip latch
|
||||
// // ... clear flag for one-shot trip latch
|
||||
//if (EPwm1Regs.TZCLR.all == 0x0004) {
|
||||
// EPwm1Regs.TZCLR.all = 0x0000;
|
||||
// EPwm1Regs.TZFRC.all = 0x0000;
|
||||
//} // ... forces a one-shot trip event
|
||||
//if (EPwm1Regs.TZFRC.all == 0x0004)
|
||||
// ci1A_DT = ci1B_DT = 0;
|
||||
}
|
||||
|
||||
|
||||
void Init_PWMPhase_Simulation(PWMPhaseSimHandle* tksim, TimerSimHandle* tsim1, TimerSimHandle* tsim2, int period, double step)
|
||||
{
|
||||
tksim->tsim1 = tsim1;
|
||||
tksim->tsim2 = tsim2;
|
||||
|
||||
Init_TIM_Simulation(tksim->tsim1, period, step);
|
||||
Init_TIM_Simulation(tksim->tsim2, period, step);
|
||||
}
|
||||
|
||||
void Init_TIM_Simulation(TimerSimHandle* tsim, int period, double step)
|
||||
{
|
||||
tsim->deadtime.stateDt = stateDtWait;
|
||||
tsim->TxPeriod = period;
|
||||
tsim->TxCntPlus = step * 2;
|
||||
tsim->deadtime.DtPeriod = (int)(DT / hmcu.sSimSampleTime);
|
||||
tsim->simulatePwm = (void (*)())Simulate_SimpleTIM;
|
||||
}
|
116
Inu/xilinx_wrapper/pwm_sim.h
Normal file
116
Inu/xilinx_wrapper/pwm_sim.h
Normal file
@ -0,0 +1,116 @@
|
||||
#include "mcu_wrapper_conf.h"
|
||||
|
||||
#ifndef PWM_SIM
|
||||
#define PWM_SIM
|
||||
|
||||
|
||||
|
||||
#define ENABLE_UNITED_COUNTER_FOR_ALL_PWM
|
||||
|
||||
|
||||
#define PWM_SIMULATION_MODE_TK_LINES
|
||||
//#define PWM_SIMULATION_MODE_REGULAR_PWM
|
||||
|
||||
#define PWM_PERIOD (FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM)
|
||||
#define PWM_TICK_STEP (FREQ_INTERNAL_GENERATOR_XILINX_TMS * hmcu.sSimSampleTime)
|
||||
|
||||
// Для моделирования ШИМ
|
||||
/**
|
||||
* @brief 3lvl PWM One Phase Simulation handle
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int ci1A;
|
||||
int ci1B;
|
||||
int ci2A;
|
||||
int ci2B;
|
||||
|
||||
}PWMPhaseOutput;
|
||||
/**
|
||||
* @brief DeadTime Simulation Handle
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int DtPeriod;
|
||||
int stateDt;
|
||||
int dtcnt;
|
||||
int pre_ciA;
|
||||
int pre_ciB;
|
||||
}DeadTimeSimHandle;
|
||||
enum StateDeadTime {
|
||||
stateDtWait = 0,
|
||||
stateDtReady
|
||||
};
|
||||
/**
|
||||
* @brief Tim Simulation Handle
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double TxCntPlus;
|
||||
double TxPeriod;
|
||||
double tcntAux;
|
||||
double tcntAuxPrev;
|
||||
double tcnt;
|
||||
double cmpA;
|
||||
double cmpB;
|
||||
DeadTimeSimHandle deadtime;
|
||||
|
||||
void (*simulatePwm)();
|
||||
}TimerSimHandle;
|
||||
|
||||
/**
|
||||
* @brief PWM Phase Simulation Handle
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
PWMPhaseOutput pwmOut;
|
||||
TimerSimHandle* tsim1;
|
||||
TimerSimHandle* tsim2;
|
||||
int tkLineA;
|
||||
int tkLineB;
|
||||
DeadTimeSimHandle deadtime;
|
||||
}PWMPhaseSimHandle;
|
||||
|
||||
extern TimerSimHandle t1sim;
|
||||
extern TimerSimHandle t2sim;
|
||||
extern TimerSimHandle t3sim;
|
||||
extern TimerSimHandle t4sim;
|
||||
extern TimerSimHandle t5sim;
|
||||
extern TimerSimHandle t6sim;
|
||||
extern TimerSimHandle t7sim;
|
||||
extern TimerSimHandle t8sim;
|
||||
extern TimerSimHandle t9sim;
|
||||
extern TimerSimHandle t10sim;
|
||||
extern TimerSimHandle t11sim;
|
||||
extern TimerSimHandle t12sim;
|
||||
|
||||
extern PWMPhaseSimHandle PWMPhaseA1;
|
||||
extern PWMPhaseSimHandle PWMPhaseB1;
|
||||
extern PWMPhaseSimHandle PWMPhaseC1;
|
||||
extern PWMPhaseSimHandle PWMPhaseA2;
|
||||
extern PWMPhaseSimHandle PWMPhaseB2;
|
||||
extern PWMPhaseSimHandle PWMPhaseC2;
|
||||
|
||||
void Simulate_PWM(void);
|
||||
void Init_PWM_Simulation(void);
|
||||
|
||||
void Simulate_PWMPhase(PWMPhaseSimHandle* tksim, int T1, int T0);
|
||||
|
||||
void Simulate_MainTIM(TimerSimHandle* tsim, int compare);
|
||||
void Simulate_SimpleTIM(TimerSimHandle* tsim, int compare);
|
||||
|
||||
int simulateTimAndGetCompare(TimerSimHandle* tsim, int compare);
|
||||
void simulateActionActionQualifierSubmodule(TimerSimHandle* tsim);
|
||||
void simulateDeadBendSubmodule(TimerSimHandle* tsim, int* ciA, int* ciB);
|
||||
void simulateTripZoneSubmodule(TimerSimHandle* tsim);
|
||||
|
||||
|
||||
void Init_TIM_Simulation(TimerSimHandle* tsim, int period, double step);
|
||||
void Init_PWMPhase_Simulation(PWMPhaseSimHandle* tksim, TimerSimHandle* tsim1, TimerSimHandle* tsim2, int period, double step);
|
||||
void convertSVGenTimesToTkLines(PWMPhaseSimHandle* tksim);
|
||||
void xilinxPwm3LevelSimulation(PWMPhaseSimHandle* tksim);
|
||||
|
||||
#if defined(PWM_SIMULATION_MODE_REGULAR_PWM) && defined(PWM_SIMULATION_MODE_TK_LINES)
|
||||
#error Choose only one PWM simulation mode!
|
||||
#endif
|
||||
#endif //PWM_SIM
|
126
README.md
126
README.md
@ -1,2 +1,126 @@
|
||||
# test_branches
|
||||
# MATLAB 23550
|
||||
**СОДЕРЖАНИЕ**
|
||||
- [Общая структура симулятора](#общая-структура-симулятора)
|
||||
- [Описание стуктуры симулятора](#описание-стуктуры-симулятора)
|
||||
- [Оболочка МК](#оболочка-мк)
|
||||
- [Оболочка программы](#оболочка-программы)
|
||||
- [Код пользователя](#код-пользователя)
|
||||
- [Симуляция плат](#симуляция-плат)
|
||||
- [Инструкция](#инструкция)
|
||||
- [Портирование кода](#портирование-кода)
|
||||
- [Как скомпилировать код](#как-скомпилировать-код)
|
||||
- [Как запустить отладку](#как-запустить-отладку)
|
||||
- [Ошибки при портировании](#ошибки)
|
||||
|
||||
## Общая структура симулятора
|
||||
Код для компиляции S-Function лежит в папке ***Inu***. В ней содержатся:
|
||||
- **Оболочка МК ([файлы в корне](#оболочка-мк))**: код S-Function, который запускает код программы
|
||||
- **Оболочка программы ([_app_wrapper_](#оболочка-программы))**: связывает программу и S-Function
|
||||
- **Программа МК ([_Src_](#код-пользователя))**: программа для симуляции
|
||||
- **Симуляция плат (beta) ([_xilinx_wrapper_](#симуляция-плат))**: моделирует внешние платы (пока только ШИМ)
|
||||
|
||||
Далее приведена структура симулятора. Инструкция для портирования другого кода в MATLAB приведена [ниже](#инструкция)
|
||||
|
||||
## Описание стуктуры симулятора
|
||||
Здесь содержиться описание трех блоков симулятора:
|
||||
- [Оболочка МК](#оболочка-мк)
|
||||
- [Оболочка программы](#оболочка-программы)
|
||||
- [Код пользователя](#код-пользователя)
|
||||
- [Симуляция плат (beta)](#симуляция-плат)
|
||||
|
||||
### Оболочка МК
|
||||
В этой папке содержиться оболочка (англ. wrapper) для запуска и контроля симуляции микроконтроллеров в MATLAB (любого МК, не только TMS). Оболочка представляет собой S-Function - блок в Simulink, который работает по скомпилированому коду. Компиляция происходит с помощью MSVC-компилятора.
|
||||
|
||||
S-Function работает особым образом: на шаге `n` она запускает скомпилированный код и ждет пока этот код выполниться. Только когда завершается выполнение кода, S-Function переходит на следующий шаг `n+1`.
|
||||
|
||||
Но программа МК это бесконечный цикл, который никогда не завершается. Поэтому есть несколько особенностей в выполнении такого кода в виде S-Function:
|
||||
- Для симуляции создается отдельный поток для программы МК. Этот поток запускается в начале текущего шага симуляции, выполняется какое-то время, а потом приостанавливается. Это позволяет коду S-Function завершиться и перейти на следующий шаг.
|
||||
- Необходимо закрыть поток программы МК в конце симуляции. Для этого используется особый дефайн для while. Этот дефайн помимо условия while, проверяет условие окончания симуляции. И если симуляцию надо завершить, все бесконечные циклы `while()` пропускаются и поток доходит до конца функции `main()` и завершает себя.
|
||||
|
||||
Всего оболочка содержит 4 файла:
|
||||
- ***mcu_wrapper.c***     - код, который запускает код МК и симулирует периферию. В нем содержаться функции для запуска/остановки потока программы МК, считывании входов и запись входов S-Function.
|
||||
- ***MCU.c***         - код для компиляции S-Function в MATLAB. Вызывает функции из ***mcu_wrapper.c***
|
||||
- ***mcu_wrapper_conf.h***   - общий для ***mcu_wrapper.c*** и ***MCU.c*** заголовочный файл. Содержит настройки для блока S-Function, а также дефайны для управления потоком программы МК.
|
||||
- ***run_mex.bat***      - скрипт для компиляции кода компилятором MSVC. В нем прописываются пути для заголовочных файлов ***.h***, указываются файлы исходного кода ***.c*** и прописываются дефайны для компиляции.
|
||||
|
||||
Конфигурации оболочки:
|
||||
- `RUN_APP_MAIN_FUNC_THREAD` - создание и запуск отдельного потока для main()
|
||||
- `DEKSTOP_CYCLES_FOR_MCU_APP` - количество циклов пустого for(;;), в течении которого будет работать поток main()
|
||||
- `MCU_CORE_CLOCK` - частота симулируемого процессора (пока нигде не используется)
|
||||
- `IN_PORT_WIDTH` - размерность входного вектора S-Function
|
||||
- `IN_PORT_NUMB` - количество входных векторов S-Function
|
||||
- `OUT_PORT_WIDTH` - размерность выходного вектора S-Function
|
||||
- `OUT_PORT_NUMB` - количество выходных векторов S-Function
|
||||
|
||||
_Note: дефайн `RUN_APP_MAIN_FUNC_THREAD` пока выключен и поток для main() не используется)_
|
||||
|
||||
_Note for future: разные вектора можно использовать для разных плат_
|
||||
|
||||
### Оболочка программы
|
||||
Оболочка для программы позволяет имитировать реальный алгоритм программы. Она инициализирует её, запускает необходимые для её работы функции и связывает её с входами/выходами S-Function
|
||||
|
||||
Ниже приведен перечень всех файлов и краткое описание зачем они нужны:
|
||||
- ***app_includes.h***     - Содержит ARM дефайны для компиляции в MSVC.
|
||||
- ***app_init.c/.h***      - инициализация программы
|
||||
- ***app_io.c/.h***       - запись/считывание входов/выходов S-Function в программу
|
||||
- ***app_wrapper.c/.h***    - вызов функций из программы и создание заглушек для ненужных функций
|
||||
- ***def.h***          - дефайны для симуляции программы в симулинке (осталось от улитковского)
|
||||
|
||||
Также в папке ***\app_wrapper\device_support*** находяться стандартные библиотеки для TMS, но переделанные под компилятор MSVC (удален `volatile`, добавлены заглушки для `interrupt`, `asm`, `cregister`, добавлен код для симуляции IQlib).
|
||||
|
||||
### Код пользователя
|
||||
Данная папка содержит исходный код приложения МК. При этом стандартные библиотеки, которые общие для всех проектов следует помещать в [папку с оболочкой программы](#оболочка-программы). Чтобы не редактировать исходники общих библиотек в каждом проекте.
|
||||
|
||||
### Симуляция плат
|
||||
Модули в этой папке моделируют внешние платы. Пока более-менее сделан только ШИМ, но в будущем планируется расширение и вывод их в отельные S-Function. Чтобы сделать подобие корзины.
|
||||
|
||||
###### adc_sim
|
||||
***adc_sim.c/.h*** - симуляция АЦП (пока просто заготовка)
|
||||
|
||||
###### pwm_sim
|
||||
***pwm_sim.c/.h*** - симуляция ШИМ
|
||||
Поддерживает два режимы формирования ШИМ:
|
||||
- для каждого таймера отдельно (PWM_SIMULATION_MODE_REGULAR_PWM)
|
||||
- через линии ТК для всей фазы разом (PWM_SIMULATION_MODE_TK_LINES).
|
||||
|
||||
|
||||
## Инструкция
|
||||
Общий алгоритм портирования кода для симуляции в MATLAB приведен ниже. В инструкции есть ссылки на более подробное описание действий.
|
||||
1. [Портировать код для MATLAB](#портирование-кода) (можно начать с портирования без изменений и далее действовать от шага 2)
|
||||
2. Проверить [компилируеться ли код](#как-скомпилировать-код). А далее:
|
||||
- если есть ошибки при компиляции, [исправить их](#ошибки-при-компиляции) и вернуться на шаг 2.
|
||||
- если ошибок нет, перейти на шаг 3.
|
||||
3. Проверить нормально ли запускается и работает симуляция с МК. А далее:
|
||||
- если симуляции вылетает, то необходимо [исправить ошибки](#ошибки-при-симуляции) в [режиме отладки](#как-запустить-отладку) и вернуться на шаг 3.
|
||||
- если симуляция нормально запускается только один раз, и не завершается или не запускается второй раз, то необходимо [исправить ошибки](#ошибки-при-симуляции) в [режиме отладки](#как-запустить-отладку) и вернуться на шаг 3.
|
||||
- если симуляция работает, не вылетает и перезапускается, то перейти на шаг 4.
|
||||
4. Оценить результаты симуляции. А далее:
|
||||
- если симуляция сходится с реальностью - то всё работает корректно.
|
||||
- если нет - необходимо разбираться в алгоритме и после исправить его и перейти на шаг 2.
|
||||
|
||||
#### Портирование кода
|
||||
Для начала необходимо весь пользовательский код портировать в отдельную папку для удобства. Например в "***\Src***".
|
||||
|
||||
Далее в "[run_bat.mex](#оболочка-мк)" надо прописать пути для заголовочных файлов (***\Includes***) и все необходимые для симуляции программы исходники. Все файлы исходников "***.c***" прописывать не обязательно. Если нужно отладить какой-то отдельный модуль программы, можно попробовать ограничиться им, и при возникновении ошибок подключать новые исходники.
|
||||
|
||||
#### Как скомпилировать код
|
||||
Для компиляции кода необходимо открыть файл ***mexing.m***. Это MATLAB-скрипт, который запускает скрипт "[***run_bat.mex***](#оболочка-мк)" для компиляции. Есть возможность компиляции кода для [отладки](#как-запустить-отладку)
|
||||
|
||||
#### Как запустить отладку
|
||||
Для отладки симуляции необходимо приписать в ***mexing.m*** в вызове ***run_mex.bat*** слово `debug`, тогда код скомпилируется для дебага. После этого необходимо открыть Visual Studio, открыть папку проекта (там должны быть все исходники программы и симулятора). И подключиться к ***MATLAB.exe***.
|
||||
|
||||
Теперь можно поставить точку в исходном коде симулятора или программы МК и запустить симуляцию. Когда MATLAB дойдет до этого места, симуляция остановиться и в Visual Studio можно будет посмотреть все переменные, пройти код по строкам и в общем делать всё то, что можно делать в режиме отладки.
|
||||
|
||||
Для отладки необходимо сначала подключится к процессу, а потом уже запускать симуляцию. Также отладка рабоатет только один раз. При повторном запуске симуляции остановки не произойдет. Поэтому перед каждой отладкой надо перекомпилировать код.
|
||||
|
||||
|
||||
#### Ошибки
|
||||
##### Ошибки при компиляции
|
||||
Самые распространеные ошибки компилятора при портировании нового кода - это ошибки из-за неподключенных исходных файлов. Для исправления ошибок необходимо подключить требуемые модули или создавать заглушки.
|
||||
|
||||
Также еще могут быть ошибки связанные с разными компиляторами и отсутствия ключевых слов в MSVC, например, ошибки с `volatile`, `interrupt`, `asm`... в библиотеках DPS. Для исправления ошибок надо или удалять эти ключевые слова или создавать для них заглушки-define
|
||||
|
||||
##### Ошибки при симуляции
|
||||
Обычно это исключения при чтении по недоступному адресу. Надо выяснить на какой строке произошло исключение и смотреть по какому адресу произошла попытка чтения и по какому адресу надо на самом деле считывать. И после этого скорректировать код так, чтобы адрес брался корректный.
|
||||
|
||||
Это обычно неинициализированные указатели или некоторые функции (напр. `ReadMemory`/`WriteMemory` когда пытаются считать что-то по адрессам "несуществующей" шины)
|
16
allmex.m
Normal file
16
allmex.m
Normal file
@ -0,0 +1,16 @@
|
||||
clc
|
||||
% Êîìïèëèðóåò S-function
|
||||
currFolder = cd;
|
||||
%cd([currFolder, '\Inu']);
|
||||
|
||||
delete("wrapper_inu.mexw64")
|
||||
delete("*.mexw64.pdb")
|
||||
|
||||
status=system('Inu\run_mex.bat debug')
|
||||
|
||||
|
||||
if status==0
|
||||
beep
|
||||
else
|
||||
error('Error!');
|
||||
end
|
BIN
asynchronous_machine.p
Normal file
BIN
asynchronous_machine.p
Normal file
Binary file not shown.
BIN
electr_mach.slx
Normal file
BIN
electr_mach.slx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user