This commit is contained in:
2025-05-09 21:26:59 +03:00
commit 5e1364447e
2936 changed files with 2471676 additions and 0 deletions

View File

@@ -0,0 +1,169 @@
#define S_FUNCTION_NAME MCU
#define S_FUNCTION_LEVEL 2
#include "mcu_wrapper_conf.h"
double SIM_Sample_Time;
#define MDL_UPDATE
/* Function: mdlUpdate ====================================================
* 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, int_T tid)
{
// get time of simulation
time_T TIME = ssGetT(S);
//---------------SIMULATE MCU---------------
MCU_Step_Simulation(S, TIME); // SIMULATE MCU
//------------------------------------------
}//end mdlUpdate
/* Function: mdlOutputs ===================================================
* 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, int_T tid)
{
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)
/* Function: mdlStart =====================================================
* 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
/* Function: mdlInitializeSampleTimes =========================================
* 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)
{
// Шаг дискретизации
SIM_Sample_Time = mxGetPr(ssGetSFcnParam(S,NPARAMS-1))[0];
// Register one pair for each sample time
ssSetSampleTime(S, 0, SIM_Sample_Time);
ssSetOffsetTime(S, 0, 0.0);
}
/* Function: mdlTerminate =====================================================
* 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.MCU_Stop = 1;
ResumeThread(hmcu.hMCUThread);
WaitForSingleObject(hmcu.hMCUThread, 10000);
SIM_deInitialize_Simulation();
mexUnlock();
}
#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

View File

@@ -0,0 +1,151 @@
# MATLAB STM32 EMULATOR
**СОДЕРЖАНИЕ**
- [Общая структура эмулятора](#общая-структура-эмулятора)
- [Описание стуктуры эмулятора (пример для STM32)](#описание-стуктуры-эмулятора-пример-для-stm32)
- [Оболочка МК](#оболочка-мк)
- [Эмулятор STM для MATLAB](#эмулятор-stm-для-matlab)
- [Код пользователя](#код-пользователя)
- [Инструкция](#инструкция)
- [Портирование кода](#портирование-кода)
- [Как скомпилировать код](#как-скомпилировать-код)
- [Как запустить отладку](#как-запустить-отладку)
- [Ошибки при портировании](#ошибки)
## Общая структура эмулятора
Эмулятор состоит из блух блоков:
- приложение МК
- оболочка МК для MATLAB, которая запускает приложение МК и эмулирует его периферию
Приложение МК в свою очередь разделено еще на два блока:
- исходный код пользователя (код приложения)
- исходный код библиотек и драйверов
Для каждого блока своя папка. Всего три папки:
- Code ([од пользователя_](#код-пользователя))
- MCU_STM32xxx_Matlab ([_эмулятор STM для MATLAB_](#эмулятор-stm-для-matlab))
- MCU_Wrapper ([_оболочка МК_](#оболочка-мк))
_*в скобочках ссылки на подробное описание папки_
Далее приведена структура эмулятора. Инструкция для портирования кода в MATLAB приведена [ниже](#инструкция)
## Описание стуктуры эмулятора (пример для STM32)
Здесь содержиться описание трех блоков эмулятора:
- [Оболочка МК](#оболочка-мк)
- [Эмулятор STM для MATLAB](#эмулятор-stm-для-matlab)
- [Код пользователя](#код-пользователя)
#### Оболочка МК
В этой папке содержаться оболочка(англ. wrapper) для запуска и контроля эмуляции микроконтроллеров в MATLAB (любого МК, не только STM). Оболочка представляет собой S-Function - блок в Simulink, который работает по скомпилированому коду. Компиляция происходит с помощью MSVC-компилятора.
S-Function работает особым образом: на шаге _n_ она запускает скомпилированный код и ждет пока этот код выполниться. Только когда завершается выполнение кода, S-Function переходит на следующий шаг _n_+1.
Но программа МК это бесконечный цикл, который никогда не завершается. Поэтому есть несколько особенностей в выполнении такого кода в виде S-Function:
- Для эмуляции создается отдельный поток для программы МК. Этот поток запускается в начале текущего шага симуляции, выполняется какое-то время, а потом приостанавливается. Это позволяет коду S-Function завершиться и перейти на следующий шаг.
- Необходимо закрыть поток программы МК в конце симуляции. Для этого используется особый дефайн для while. Этот дефайн помимо условия while, проверяет условие окончания симуляции. И если симуляцию надо завершить, все бесконечные циклы _while()_ пропускаются и поток доходит до конца функции _main()_ и завершает себя.
Всего оболочка содержит 4 файла:
- mcu_wrapper.c &emsp;&emsp;&emsp; - файл, который запускает код МК и управляет его ходом. В нем содержаться функции для запуска/остановки потока программы МК, считывании входов и запись входов S-Function в соответствии с I/O портами МК.
- MCU.c &nbsp;&ensp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp; - базовый файл, который представляет собой исходный код для компиляции S-Function в MATLAB. Вызывает функции из "mcu_wrapper.c"
- mcu_wrapper_conf.h &ensp; - общий для mcu_wrapper.c и MCU.c заголовочный файл. Содержит настройки для блока S-Function, а также дефайны для управления ходом программы МК.
- run_mex.bat &nbsp;&emsp;&emsp;&emsp;&emsp; - скрипт для компиляции кода компилятором MSVC. В нем прописываются пути для заголовочных файлов ".h", указываются файлы исходного кода ".c" и прописываются дефайны для компиляции.
#### Эмулятор STM для MATLAB
В папке "_\MCU_STM32xxx_Matlab_" есть два файла "stm32fxxx_matlab_conf.c/.h".
В них задаётся используемая периферия и подключаются библиотеки для периферии. Также объявляются функкции для инициализации/деинициализации периферии МК и структуры для эмуляции периферии.
В папке "_\MCU_STM32xxx_Matlab\Drivers_" находяться стандартные библиотеки для STM/ARM, но переделанные под компилятор MSVC. Всего там три папки: [STM32F4xx_SIMULINK](#папка-stm32f4xx_simulink), [CMSIS](#папка-cmsis), [STM32F4xx_HAL_Driver](#папка-stm32f4xx_hal_driver).
###### Папка STM32F4xx_SIMULINK
В этой папке содержаться файлы для эмуляции периферии STM32 в MATLAB. Структура файлов такая же, как в библиотеки HAL:
- название серии МК, который эмулируется (matlab),
- идентификатор, что это для MATLAB (matlab),
- периферия, функции для эмуляции которой содержит конкретный файл (gpio, tim).
Пример: "stm32f4xx_matlab_tim.c/.h"
###### Папка CMSIS
"Порт" библиотеки CMSIS для MSVC. Ниже приведен перечень всех файлов и краткое описание зачем они нужны:
- **arm_defines.h**
Содержит ARM дефайны для компиляции в MSVC.
- **core_cm4_matlab.h**
Данный файл является копией "core_cm4.h" с некоторыми изменениями
- удалены первые ~160 строк, которые определяют компилятор ARM.
- добавлена структура **имитирующая память ядра***. Для того, чтобы при обращении по адресам регистров МК не было исключений при чтении по недоступному адресу.
- **stdint.h**
Данный файл является копией "stdint.h", из библиотеки для STM32. (_только все дефайны uint32_t передалны как uint64_t. Т.к. в MATLAB всё компилируется в 64-битном формате, то сохранении адресов в 32-битных переменных, адреса будут усекаться и будут ошибки._)
- **stm32f407xx_matlab.h**
Данный файл является копией "stm32f407xx.h" с некоторыми изменениями:
- добавлен кастомный "stdint.h" (через "", вместо <>)
- добавлен "arm_defines.h" с ARM дефайнами для MSVC
- добавлен матлабовский "cmsis_armcc_matlab.h" с вместо "cmsis_armcc.h"
- добавлена структура **имитирующая память ядра***. Для того, чтобы при обращении по адресам регистров МК не было исключений при чтении по недоступному адресу.
- **stm32f4xx.h** - оригинальный файл "stm32f4xx.h".
- **system_stm32f4xx.h** - оригинальный файл "system_stm32f4xx.h".
_*память ядра не имитируется в полной мере, потому что STM32 - это 32-битный процессор, он имеет 4 Гб памяти. А MATLAB/MSVC делает ограничение на использование не больше 4Гб оперативной памяти. При этом еще есть матлабовские переменные которые тоже занимают место. Поэтому память эмулируется лишь частично. Как имено - задается в дефайнах и структуруре stm32f407xx_matlab.h._
###### Папка STM32F4xx_HAL_Driver
Данная библиотека является копией HAL, за некоторыми исключениями. В основном касаются макросов для ожидания флага. Т.к. весь МК реализован програмно, то надо самому писать код, который будет выставлять флаги по определенным условиям. Только тогда библиотека HAL будет это считывать и выполнять свои функции. Но далеко не всегда есть необходимость так делать.
Поэтому, вместо того, чтобы пользоваться оригиальным HAL и писать эмулятор для всего 32-битного контроллера, можно переписать макросы или даже функции целиком под свои нужды.
#### Код пользователя
Данная папка содержит исходный код приложения МК. При этом драйверы и стандартные/HAL библиотеки, которые общие для всех проектов следует помещать в [папку с эмулятором МК](#эмулятор-stm-для-matlab). Чтобы не редактировать исходники общих библиотек (CMSIS/HAL) в каждом проекте.
## Инструкция
Общий алгоритм портирования кода для симуляции в MATLAB приведен ниже. В инструкции есть ссылки на более подробное описание действий.
1. [Портировать код для MATLAB](#портирование-кода) (можно начать с портирования без изменений и далее действовать от шага 2)
2. Проверить [компилируеться ли код](#как-скомпилировать-код). А далее:
- если есть ошибки при компиляции, [исправить их](#ошибки-при-компиляции) и вернуться на шаг 2.
- если ошибок нет, перейти на шаг 3.
3. Проверить нормально ли запускается и работает симуляция с МК. А далее:
- если симуляции вылетает, то необходимо [исправить ошибки](#ошибки-при-симуляции) в [режиме отладки](#как-запустить-отладку) и вернуться на шаг 3.
- если симуляция нормально запускается только один раз, и не завершается или не запускается второй раз, то необходимо [исправить ошибки](#ошибки-при-симуляции) в [режиме отладки](#как-запустить-отладку) и вернуться на шаг 3.
- если симуляция работает полностью корректно, перейти на шаг. 4.
4. Оценить результаты симуляции. А далее:
- если симуляция сходится с реальностью - то всё работает корректно.
- если нет - необходимо исправить ошибки в [драйверах](#эмулятор-и-периферия) и перейти на шаг 2.
#### Портирование кода
###### Код программы
Для начала необходимо весь пользовательский код портировать в отдельную папку для удобства. Например в "_\Code_".
Далее в "[run_bat.mex](#оболочка-мк)" надо прописать пути для заголовочных файлов (_\Includes_). Все файлы исходников "_*.c_" прописывать не обязательно. Можно прописать только папки с исходниками, как с заголовочными файлами. Далее скрипт сам сканирует и ищет все исходники.
###### Эмулятор и библиотеки
Эмулятор и библиотеки связаны в том плане, что необходимо выбрать через что будет реализована периферия
- полноценный эмулятор, тогда функции библиотек остаются без изменений и просто работает не с реальной периферией, а с её эмулятором
- упрощенный эмулятор, тогда функции библиотек тоже надо или упростить или сделать их-dummy.
- игнорирование периферии. Если периферия не важна для симуляции, можно просто в программе МК убрать все выховы функций, связанные с ней или сделать их dummy.
Скрипты для эмуляции периферии необходимо прописывать вручную. В случае STM32 руководствоваться следует только регистрами CMSIS, чтобы не привязываться к HAL, и была возможность симуляции кода без него. Или же пробовать делать универсальный через дефайны, которые будут определять доступ к конкретным регистрам конкретного МК.
###### Примеры эмуляции периферии
**Пример 1 (полноценный эмулятор):** можно написать полный эмулятор для таймеров, т.к. это очень важна часть МК. Плюс она часто корректируется: разные режимы таймеров, разная частота, разные каналы. И удобно, если всё это можно менять "на ходу", а не только во время компиляциию.
**Пример 2 (упрощенный эмулятор):** В случае, если не нужна эмуляция периферии. Например для протоколов общения, типа UART/MODBUS, можно просто сделать отдельные входы в S-Function, и напрямую брать значения оттуда и записывать в переменные программы, без приёма отдельных битов, парсинга и прочего. Но тогда надо будет редактировать библиотеки и делать dummy-функции, чтобы они не ждали ответа от периферии, которая не эмулируется. Или же редактировать пользовательский код.
**Пример 3 (игнорирование периферии):** CubeMX использует функции RCC_Config, которые настраивают тактирование МК. В HAL'e в функции инициализации постоянно используются bit-banding, который реализован аппаратно. Это некоторые адресса, которые могут переключать отдельные биты через присваивание (сродни BSRR у GPIO, только для всей периферии). Плюс еще HAL дополнительно проверяет реально ли выставились эти биты в регистрах, поэтому с этим надо что-то сделать. Т.к. регистры RCC не важны для симуляции большинства программ, можно просто убрать единственный вызов этой функции в main, или сделать её dummy - в HAL-библиотеке.
После портирования кода надо скомпилировать код МК и далее уже смотреть по [ошибкам](#ошибки-при-компиляции), что надо исправлять.
#### Как скомпилировать код
Для компиляции кода необходимо открыть файл mexing.m. Это MATLAB-скрипт, который запускает скрипт "[run_bat.mex](#оболочка-мк)" для компиляции. Также этот файл задает время дискретизации для симуляции и дает возможность компиляции кода для [отладки](#как-запустить-отладку)
#### Как запустить отладку
Для отладки симуляции необходимо приписать в mexing.m в вызове "run_mex.bat" слово debug, тогда код скомпилируется для дебага. После этого необходимо открыть любой(?) редактор кода, например Visual Studio. Открыть папку проекта (там должны быть все исходники программы и эмулятора). И подключиться к MATLAB.exe.
Теперь можно поставить точку в исходном коде эмулятора или программы МК и запустить симуляцию. Когда MATLAB дойдет до этого места, симуляция остановиться и в Visual Studio можно будет посмотреть все переменные, пройти код по строкам и в общем делать всё то, что можно делать в режиме отладки.
Но отладка рабоатет только один раз. При повторном запуске симуляции остановки не произойдет. Поэтому перед каждой отладкой надо перекомпилировать код.
#### Ошибки
##### Ошибки при компиляции
Самые распространеные ошибки компилятора при портировании нового кода - это ошибки переопределения. Связаны с weak-фукнциями. В MSVC их нет как таковых. Поэтому необходимо закомментировать все weak-функции в HAL или пользовательском коде, чтобы на весь код было только одно определение функции.
То же самое касается asm вставок. Их надо удалить или переписать.
##### Ошибки при симуляции
Обычно это исключения при чтении по недоступному адресу. Связано с разным адресным пространством МК и ПК. Поэтому надо выяснить на какой строке произошло исключение. И смотреть по какому адресу произошла попытка чтения и по какому адресу надо на самом деле считывать. И после этого скорректировать код так, чтобы адрес брался корректный.
Из общих решений - это может быть при попытки чтения по "экзотическим" адресам (bit-banding), для которых [не определено адресное пространство в симуляции](#папка-cmsis).

View File

@@ -0,0 +1,292 @@
#define __disable_irq()
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __IO
#define __IO volatile
#endif
#ifndef __inline
#define __inline inline
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static __inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE static __forceinline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __declspec(noreturn)
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __declspec(selectany)
// #define __weak __WEAK
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT __packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION __packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
#define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __weak
#define __weak
#endif
//#define __ASM()
//#define __DSB()
//#define __ISB()
//#define __NOP()
//#define __WFI()
//#define __SEV()
//#define __WFE()
//#define __DMB()
/**
\brief No Operation
\details No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP()
/**
\brief Wait For Interrupt
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
*/
#define __WFI()
/**
\brief Wait For Event
\details Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE()
/**
\brief Send Event
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV()
/**
\brief Instruction Synchronization Barrier
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or memory,
after the instruction has been completed.
*/
#define __ISB()
/**
\brief Data Synchronization Barrier
\details Acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB()
/**
\brief Data Memory Barrier
\details Ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB()
/**
\brief Reverse byte order (32 bit)
\details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV(value) value
/**
\brief Reverse byte order (16 bit)
\details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV16(value) value
/**
\brief Reverse byte order (16 bit)
\details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REVSH(value) value
/**
\brief Rotate Right in unsigned value (32 bit)
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] op1 Value to rotate
\param [in] op2 Number of Bits to rotate
\return Rotated value
*/
#define __ROR()
/**
\brief Breakpoint
\details Causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) value
/**
\brief Reverse bit order of value
\details Reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT() _byteswap_ulong(_rotr(value, 16))
/**
\brief Count leading zeros
\details Counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ() __lzcnt(value)
/**
\brief LDR Exclusive (8 bit)
\details Executes a exclusive LDR instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDREXB(ptr) (*(volatile uint8_t *)(ptr))
/**
\brief LDR Exclusive (16 bit)
\details Executes a exclusive LDR instruction for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDREXH(ptr) (*(volatile uint16_t *)(ptr))
/**
\brief LDR Exclusive (32 bit)
\details Executes a exclusive LDR instruction for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDREXW(ptr) (*(volatile uint32_t *)(ptr))
/**
\brief STR Exclusive (8 bit)
\details Executes a exclusive STR instruction for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXB(value, ptr) (*(volatile uint8_t *)(ptr) = (value), 0)
/**
\brief STR Exclusive (16 bit)
\details Executes a exclusive STR instruction for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXH(value, ptr) (*(volatile uint16_t *)(ptr) = (value), 0)
/**
\brief STR Exclusive (32 bit)
\details Executes a exclusive STR instruction for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXW(value, ptr) (*(volatile uint32_t *)(ptr) = (value), 0)
/**
\brief Remove the exclusive lock
\details Removes the exclusive lock which is created by LDREX.
*/
#define __CLREX
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
/**************************************************************************
Äàííûé ôàéë ñîäåðæèò ôóíêöèè äëÿ ñèìóëÿöèè ÌÊ â 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 */
//}
////----------------------------------

View File

@@ -0,0 +1,147 @@
/**************************************************************************
Ãëàâíûé çàãîëîâî÷íûé ôàéë äëÿ ìàòëàáà. Âêëþ÷àåò äåéôàéíû äëÿ S-Function,
îáúÿâëÿåò áàçîâûå ôóíêöèè äëÿ ñèìóëÿöèè ÌÊ è ïîäêëþ÷àåò áàçîâûå áèáëèîòåêè:
äëÿ ñèìóëÿöèè "stm32fxxx_matlab_conf.h"
äëÿ S-Function "simstruc.h"
äëÿ ïîòîêîâ <process.h>
**************************************************************************/
#ifndef _CONTROLLER_H_
#define _CONTROLLER_H_
// Includes
#include "stm32f4xx_matlab_conf.h" // For stm simulate functions
#include "simstruc.h" // For S-Function variables
#include <process.h> // For threads
// Parametrs of MCU simulator
#define CREATE_SUSPENDED 0x00000004 // define from WinBase.h
// We dont wanna include "Windows.h" or smth like this, because a lot of redefine errors appear.
#define DEKSTOP_CYCLES_FOR_MCU_APP 0xFFFF // number of for() cycles after which MCU thread would be suspended
#define PORT_WIDTH 16 // width of one port
#define PORT_NUMB 3 // amount of ports
// Parameters of S_Function
#define NPARAMS 1 // number of input parametrs (only Ts)
#define IN_PORT_WIDTH (8) // width of input ports
#define IN_PORT_NUMB 1 // number of input ports
#define OUT_PORT_WIDTH PORT_WIDTH // width of output ports
#define OUT_PORT_NUMB PORT_NUMB // number of output ports
#define DISC_STATES_WIDTH PORT_WIDTH*PORT_NUMB // width of discrete states array
// Externs
extern double SIM_Sample_Time; // sample time
/** MCU HANDLE STRUCTURE */
/**
* @brief MCU handle Structure definition.
* @vars MCU Thread - handle for MCUThread and id of MCUThread (unused).
* @vars Flags and counters - flags and counter that control MCU app.
*
*/
typedef void* HANDLE;
typedef struct _DEL_MCUHandleTypeDef {
// MCU Thread
HANDLE hMCUThread; /* Õåíäë äëÿ ïîòîêà ÌÊ */
uint32_t idMCUThread; /* id ïîòîêà ÌÊ (unused) */
// Flags
unsigned MCU_Stop : 1; /* ôëàã äëÿ âûõîäà èç ïîòîêà ïðîãðàììû ÌÊ */
}SIM__MCUHandleTypeDef;
extern SIM__MCUHandleTypeDef hmcu; /* extern äëÿ âèäèìîñòè ïåðåìåííîé âî âñåõ ôàéëàõ */
//-------------------------------------------------------------//
//------------------ SIMULINK WHILE DEFINES -----------------//
/** DEFINE TO WHILE WITH SIMULINK WHILE */
/**
* @brief Redefine C while statement with sim_while() macro.
* @param _expression_ - expression for while.
* @note @ref sim_while äëÿ ïîäðîáíîñòåé.
*/
#define while(_expression_) sim_while(_expression_) /* while êîòîðûé áóäåò èñïîëüçîâàòüñÿ â ñèìóëèíêå */
/** SIMULINK WHILE */
/**
* @brief While statement for emulate MCU code in Simulink.
* @param _expression_ - expression for while.
* @note Äàííûé while íåîáõîäèì, ÷òîáû â êîíöå ñèìóëÿöèè, çàâåðøèòü ïîòîê ÌÊ:
* Ïðè âûñòàâëåíèè ôëàãà îêîí÷àíèÿ ñèìóëÿöèè, âñå while áóäóò ïðîïóñêàòüñÿ
* è ïîòîê ñìîæåò äîéòè äî êîíöà ñâîåé ôóíêöèè è çàâåðøèòü ñåáÿ.
*/
#define sim_while(_expression_) while((_expression_)&&(hmcu.MCU_Stop == 0))
/** DEFAULT WHILE */
/**
* @brief Default/Native C while statement.
* @param _expression_ - expression for while.
* @note Äàííûé while - àíàëîã îáû÷íîãî while, áåç äîïîëíèòåëüíîãî ôóíêöèîíàëà.
*/
#define native_while(_expression_) for(; (_expression_); )
/***************************************************************/
//------------------ SIMULINK WHILE DEFINES -----------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//---------------- SIMULATE FUNCTIONS PROTOTYPES -------------//
/** SIMULATE MCU STEP */
/**
* @brief Read from simulink S-Block Inputs and write to MCU I/O ports.
* @param in - inputs of S-Function.
* @param disc - discrete array of S-Function. Outputs would be written from disc.
* @param time - current time of simulation (in second).
* @note Çàïóñêàåò ïîòîê, êîòîðûé âûïîëíÿåò êîä ÌÊ è óïðàâëÿåò õîäîì ïîòîêà:
* Åñëè ïðîøåë òàéìàóò, ïîòîê ïðåðûâàåòñÿ, ñèìóëèðóåòñÿ ïåðèôåðèÿ
* è íà ñëåäóþùåì øàãå ïîòîê âîçîáíàâëÿåòñÿ.
*/
void MCU_Step_Simulation(SimStruct *S, time_T time); /* step simulation */
/** SIMULATE MCU PERIPHERAL */
/**
* @brief Simulate peripheral of MCU
* @note Ïîëüçîâàòåëüñêèé êîä, êîòîðûé ñèìóëèðóåò ðàáîòó ïåðèôåðèè ÌÊ.
*/
void MCU_Periph_Simulation(void); /* MCU peripheral simulation */
/** MCU WRAPPER INITIALIZATION */
/**
* @brief Initialize structures and variables for simulating MCU.
* @note Ïîëüçîâàòåëüñêèé êîä, êîòîðûé áóäåò íàñòðàèâàòü âñå ñòðóêòóðû.
*/
void SIM_Initialize_Simulation(void); /* initialize MCU simulation */
/** MCU WRAPPER DEINITIALIZATION */
/**
* @brief Deinitialize structures and variables for simulating MCU.
* @note Ïîëüçîâàòåëüñêèé êîä, êîòîðûé áóäåò î÷èùàòü âñå ñòðóêòóðû.
*/
void SIM_deInitialize_Simulation(void); /* SIM_deInitialize_Simulation MCU simulation */
/** READ INPUTS S-FUNCTION */
/**
* @brief Read from simulink S-Block Inputs and write to MCU I/O ports.
* @param in - inputs of S-Function.
* @note Ïîëüçîâàòåëüñêèé êîä, êîòîðûé çàïèñûâàåò â ïîðòû ââîäà-âûâîäà èç disc.
*/
void MCU_readInputs(real_T* in);
/** WRITE OUTPUTS S-FUNCTION */
/**
* @brief Read from MCU I/O ports and write to simulink S-Block Outputs.
* @param disc - discrete array of S-Function. Outputs would be written from disc.
* @note Ïîëüçîâàòåëüñêèé êîä, êîòîðûé çàïèñûâàåò â disc ïîðòû ââîäà-âûâîäà.
*/
void MCU_writeOutputs(real_T* disc);
/** 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_writeOutput(SimStruct* S);
//---------------- SIMULATE FUNCTIONS PROTOTYPES -------------//
//-------------------------------------------------------------//
#endif // _CONTROLLER_H_

View File

@@ -0,0 +1,92 @@
@echo off
set defines=-D"STM32F407xx" -D"USE_HAL_DRIVER"^
-D"MATLAB"^
-D"__sizeof_ptr=8"
:: -------------------------USERS PATHS AND CODE---------------------------
:: заголовочные файлы (не добавлять CMSIS и HAL, они добавлены ниже)
set includes_USER= -I".\Code\Core\Inc" -I".\Code\GENERAL"^
-I".\Code\Modbus" -I".\Code\PWM"
:: исходный код
setlocal enabledelayedexpansion
set code_USER=
for %%f in (.\Code\Core\Src\*.c) do (
set code_USER=!code_USER! %%f
)
for %%f in (.\Code\GENERAL\*.c) do (
set code_USER=!code_USER! %%f
)
for %%f in (.\Code\Modbus\*.c) do (
set code_USER=!code_USER! %%f
)
for %%f in (.\Code\PWM\*.c) do (
set code_USER=!code_USER! %%f
)
::-------------------------------------------------------------------------
:: -----------------------MCU LIBRARIES & SIMULATOR------------------------
:: -----MCU LIBRARIES STUFF----
:: заголовочные файлы
set includes_MCU= -I".\MCU_STM32F4xx_Matlab"^
-I".\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_SIMULINK"^
-I".\MCU_STM32F4xx_Matlab\Drivers\CMSIS"^
-I".\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc"^
-I".\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy"
:: код библиотек МК, переделанный для матлаб
set code_MCU=.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_usart.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c
:: .\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c^
:: .\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c^
:: .\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c^
:: .\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c^
:: --------MCU SIMULATOR-------
:: код, которая будет симулировать перефирию МК в симулинке
set code_MCU_Sim= .\MCU_STM32F4xx_Matlab\stm32f4xx_matlab_conf.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_SIMULINK\stm32f4xx_matlab_gpio.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_SIMULINK\stm32f4xx_matlab_tim.c^
.\MCU_STM32F4xx_Matlab\Drivers\STM32F4xx_SIMULINK\stm32f4xx_periph_registers.c
::-------------------------------------------------------------------------
:: -------------------------WRAPPER PATHS AND CODE---------------------------
:: оболочка, которая будет моделировать работу МК в симулинке
set includes_WRAPPER= -I".\MCU_Wrapper"
set code_WRAPPER= .\MCU_Wrapper\MCU.c^
.\MCU_Wrapper\mcu_wrapper.c
::-------------------------------------------------------------------------
:: ---------------------SET PARAMS FOR MEX COMPILING-----------------------
:: --------ALL INCLUDES--------
set includes= %includes_USER% %includes_MCU% %includes_WRAPPER%
set codes= %code_WRAPPER% %code_USER% %code_MCU% %code_MCU_Sim%
:: -------OUTPUT FOLDER--------
set output= -outdir "."
:: если нужен дебаг, до запускаем run mex с припиской debug
IF [%1]==[debug] (set debug= -g)
::-------------------------------------------------------------------------
::------START COMPILING-------
echo Compiling...
mex %output% %defines% %includes% %codes% %debug%

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,328 @@
/**************************************************************************
Äàííûé ôàéë íàñòðàèâàåò ñòðóêòóðû äëÿ ñèìóëÿöèè ïåðèôåðèé, êîòîðûå âûáðàíû
äåôàéíàìè â stm32f4xx_matlab_conf.h.
**************************************************************************/
#include "mcu_wrapper_conf.h"
MCU_MemoryTypeDef MCU_MEM;
MCU_CortexMemoryTypeDef MCU_CORTEX_MEM;
DBGMCU_TypeDef DEBUG_MCU;
//-----------------------------------------------------------------------//
/*------------------------------FUNCTIONS--------------------------------*/
// MCU PERIPH INIT
void Initialize_Periph_Sim(void)
{
Init_TIM_SIM();
}
// MCU PERIPH DEINIT
void deInitialize_Periph_Sim(void)
{
TIM_SIM_DEINIT();
}
// MCU DEINIT
void deInitialize_MCU(void)
{
// îáíóëåíèå ñòðóêòóðû, óïðàâëÿþùåé ïðîãðàììîé ÌÊ
memset(&hmcu, 0, sizeof(hmcu));
// îáíóëåíèå ñòðóêòóð, ñèìóëèðóþùèõ ïàìÿòü ÌÊ
memset(&MCU_MEM, 0, sizeof(MCU_MEM));
memset(&MCU_CORTEX_MEM, 0, sizeof(MCU_CORTEX_MEM));
memset(&DEBUG_MCU, 0, sizeof(DEBUG_MCU));
}
/*------------------------------FUNCTIONS--------------------------------*/
//-----------------------------------------------------------------------//
//-----------------------------------------------------------------------//
/*-------------------------------TIMERS----------------------------------*/
// defines structure for simulate
#ifdef USE_TIM1
struct TIM_Sim tim1s;
#endif
#ifdef USE_TIM2
struct TIM_Sim tim2s;
#endif
#ifdef USE_TIM3
struct TIM_Sim tim3s;
#endif
#ifdef USE_TIM4
struct TIM_Sim tim4s;
#endif
#ifdef USE_TIM5
struct TIM_Sim tim5s;
#endif
#ifdef USE_TIM6
struct TIM_Sim tim6s;
#endif
#ifdef USE_TIM7
struct TIM_Sim tim7s;
#endif
#ifdef USE_TIM8
struct TIM_Sim tim8s;
#endif
#ifdef USE_TIM9
struct TIM_Sim tim9s;
#endif
#ifdef USE_TIM10
struct TIM_Sim tim10s;
#endif
#ifdef USE_TIM11
struct TIM_Sim tim11s;
#endif
#ifdef USE_TIM12
struct TIM_Sim tim12s;
#endif
#ifdef USE_TIM13
struct TIM_Sim tim13s;
#endif
#ifdef USE_TIM14
struct TIM_Sim tim14s;
#endif
// defines function for filling structure for simulate
void Init_TIM_SIM(void)
{
#ifdef USE_TIM1
tim1s.tx_cnt = TIM1->CNT;
tim1s.tx_step = SIM_Sample_Time * ABP2_TIMS_Value;
tim1s.Channels.OC1_GPIOx = GPIOE;
tim1s.Channels.OC1_PIN_SHIFT = 9;
tim1s.Channels.OC2_GPIOx = GPIOE;
tim1s.Channels.OC2_PIN_SHIFT = 11;
tim1s.Channels.OC3_GPIOx = GPIOE;
tim1s.Channels.OC3_PIN_SHIFT = 13;
tim1s.Channels.OC4_GPIOx = GPIOE;
tim1s.Channels.OC4_PIN_SHIFT = 14;
tim1s.Channels.OC1REF = 0;
tim1s.Channels.OC2REF = 0;
tim1s.Channels.OC3REF = 0;
tim1s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM2
tim2s.tx_cnt = TIM2->CNT;
tim2s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim2s.Channels.OC1_GPIOx = GPIOA;
tim2s.Channels.OC1_PIN_SHIFT = 5;
tim2s.Channels.OC2_GPIOx = GPIOA;
tim2s.Channels.OC2_PIN_SHIFT = 1;
tim2s.Channels.OC3_GPIOx = GPIOA;
tim2s.Channels.OC3_PIN_SHIFT = 2;
tim2s.Channels.OC4_GPIOx = GPIOA;
tim2s.Channels.OC4_PIN_SHIFT = 3;
tim2s.Channels.OC1REF = 0;
tim2s.Channels.OC2REF = 0;
tim2s.Channels.OC3REF = 0;
tim2s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM3
tim3s.tx_cnt = TIM3->CNT;
tim3s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim3s.Channels.OC1_GPIOx = GPIOA;
tim3s.Channels.OC1_PIN_SHIFT = 6;
tim3s.Channels.OC2_GPIOx = GPIOA;
tim3s.Channels.OC2_PIN_SHIFT = 7;
tim3s.Channels.OC3_GPIOx = GPIOB;
tim3s.Channels.OC3_PIN_SHIFT = 0;
tim3s.Channels.OC4_GPIOx = GPIOB;
tim3s.Channels.OC4_PIN_SHIFT = 1;
tim3s.Channels.OC1REF = 0;
tim3s.Channels.OC2REF = 0;
tim3s.Channels.OC3REF = 0;
tim3s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM4
tim4s.tx_cnt = TIM4->CNT;
tim4s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim4s.Channels.OC1_GPIOx = GPIOD;
tim4s.Channels.OC1_PIN_SHIFT = 12;
tim4s.Channels.OC2_GPIOx = GPIOD;
tim4s.Channels.OC2_PIN_SHIFT = 13;
tim4s.Channels.OC3_GPIOx = GPIOD;
tim4s.Channels.OC3_PIN_SHIFT = 14;
tim4s.Channels.OC4_GPIOx = GPIOD;
tim4s.Channels.OC4_PIN_SHIFT = 15;
tim4s.Channels.OC1REF = 0;
tim4s.Channels.OC2REF = 0;
tim4s.Channels.OC3REF = 0;
tim4s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM5
tim5s.tx_cnt = TIM5->CNT;
tim5s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim5s.Channels.OC1_GPIOx = GPIOA;
tim5s.Channels.OC1_PIN_SHIFT = 0;
tim5s.Channels.OC2_GPIOx = GPIOA;
tim5s.Channels.OC2_PIN_SHIFT = 1;
tim5s.Channels.OC3_GPIOx = GPIOA;
tim5s.Channels.OC3_PIN_SHIFT = 2;
tim5s.Channels.OC4_GPIOx = GPIOA;
tim5s.Channels.OC4_PIN_SHIFT = 3;
tim5s.Channels.OC1REF = 0;
tim5s.Channels.OC2REF = 0;
tim5s.Channels.OC3REF = 0;
tim5s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM6
tim6s.tx_cnt = TIM6->CNT;
tim6s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim6s.Channels.OC1_GPIOx = GPIOA;
tim6s.Channels.OC1_PIN_SHIFT = 6;
tim6s.Channels.OC2_GPIOx = GPIOA;
tim6s.Channels.OC2_PIN_SHIFT = 0;
tim6s.Channels.OC3_GPIOx = GPIOA;
tim6s.Channels.OC3_PIN_SHIFT = 0;
tim6s.Channels.OC4_GPIOx = GPIOA;
tim6s.Channels.OC4_PIN_SHIFT = 0;
tim6s.Channels.OC1REF = 0;
tim6s.Channels.OC2REF = 0;
tim6s.Channels.OC3REF = 0;
tim6s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM7
tim7s.tx_cnt = TIM7->CNT;
tim7s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim7s.Channels.OC1_GPIOx = GPIOA;
tim7s.Channels.OC1_PIN_SHIFT = 6;
tim7s.Channels.OC2_GPIOx = GPIOA;
tim7s.Channels.OC2_PIN_SHIFT = 0;
tim7s.Channels.OC3_GPIOx = GPIOA;
tim7s.Channels.OC3_PIN_SHIFT = 0;
tim7s.Channels.OC4_GPIOx = GPIOA;
tim7s.Channels.OC4_PIN_SHIFT = 0;
tim7s.Channels.OC1REF = 0;
tim7s.Channels.OC2REF = 0;
tim7s.Channels.OC3REF = 0;
tim7s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM8
tim8s.tx_cnt = TIM8->CNT;
tim8s.tx_step = SIM_Sample_Time * ABP2_TIMS_Value;
tim8s.Channels.OC1_GPIOx = GPIOA;
tim8s.Channels.OC1_PIN_SHIFT = 6;
tim8s.Channels.OC2_GPIOx = GPIOA;
tim8s.Channels.OC2_PIN_SHIFT = 0;
tim8s.Channels.OC3_GPIOx = GPIOA;
tim8s.Channels.OC3_PIN_SHIFT = 0;
tim8s.Channels.OC4_GPIOx = GPIOA;
tim8s.Channels.OC4_PIN_SHIFT = 0;
tim8s.Channels.OC1REF = 0;
tim8s.Channels.OC2REF = 0;
tim8s.Channels.OC3REF = 0;
tim8s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM9
tim9s.tx_cnt = TIM9->CNT;
tim9s.tx_step = SIM_Sample_Time * ABP2_TIMS_Value;
tim9s.Channels.OC1_GPIOx = GPIOA;
tim9s.Channels.OC1_PIN_SHIFT = 6;
tim9s.Channels.OC2_GPIOx = GPIOA;
tim9s.Channels.OC2_PIN_SHIFT = 0;
tim9s.Channels.OC3_GPIOx = GPIOA;
tim9s.Channels.OC3_PIN_SHIFT = 0;
tim9s.Channels.OC4_GPIOx = GPIOA;
tim9s.Channels.OC4_PIN_SHIFT = 0;
tim9s.Channels.OC1REF = 0;
tim9s.Channels.OC2REF = 0;
tim9s.Channels.OC3REF = 0;
tim9s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM10
tim10s.tx_cnt = TIM10->CNT;
tim10s.tx_step = SIM_Sample_Time * ABP2_TIMS_Value;
tim10s.Channels.OC1_GPIOx = GPIOA;
tim10s.Channels.OC1_PIN_SHIFT = 6;
tim10s.Channels.OC2_GPIOx = GPIOA;
tim10s.Channels.OC2_PIN_SHIFT = 0;
tim10s.Channels.OC3_GPIOx = GPIOA;
tim10s.Channels.OC3_PIN_SHIFT = 0;
tim10s.Channels.OC4_GPIOx = GPIOA;
tim10s.Channels.OC4_PIN_SHIFT = 0;
tim10s.Channels.OC1REF = 0;
tim10s.Channels.OC2REF = 0;
tim10s.Channels.OC3REF = 0;
tim10s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM11
tim11s.tx_cnt = TIM11->CNT;
tim11s.tx_step = SIM_Sample_Time * ABP2_TIMS_Value;
tim11s.Channels.OC1_GPIOx = GPIOA;
tim11s.Channels.OC1_PIN_SHIFT = 6;
tim11s.Channels.OC2_GPIOx = GPIOA;
tim11s.Channels.OC2_PIN_SHIFT = 0;
tim11s.Channels.OC3_GPIOx = GPIOA;
tim11s.Channels.OC3_PIN_SHIFT = 0;
tim11s.Channels.OC4_GPIOx = GPIOA;
tim11s.Channels.OC4_PIN_SHIFT = 0;
tim11s.Channels.OC1REF = 0;
tim11s.Channels.OC2REF = 0;
tim11s.Channels.OC3REF = 0;
tim11s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM12
tim12s.tx_cnt = TIM12->CNT;
tim12s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim12s.Channels.OC1_GPIOx = GPIOA;
tim12s.Channels.OC1_PIN_SHIFT = 6;
tim12s.Channels.OC2_GPIOx = GPIOA;
tim12s.Channels.OC2_PIN_SHIFT = 0;
tim12s.Channels.OC3_GPIOx = GPIOA;
tim12s.Channels.OC3_PIN_SHIFT = 0;
tim12s.Channels.OC4_GPIOx = GPIOA;
tim12s.Channels.OC4_PIN_SHIFT = 0;
tim12s.Channels.OC1REF = 0;
tim12s.Channels.OC2REF = 0;
tim12s.Channels.OC3REF = 0;
tim12s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM13
tim13s.tx_cnt = TIM13->CNT;
tim13s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim13s.Channels.OC1_GPIOx = GPIOA;
tim13s.Channels.OC1_PIN_SHIFT = 6;
tim13s.Channels.OC2_GPIOx = GPIOA;
tim13s.Channels.OC2_PIN_SHIFT = 0;
tim13s.Channels.OC3_GPIOx = GPIOA;
tim13s.Channels.OC3_PIN_SHIFT = 0;
tim13s.Channels.OC4_GPIOx = GPIOA;
tim13s.Channels.OC4_PIN_SHIFT = 0;
tim13s.Channels.OC1REF = 0;
tim13s.Channels.OC2REF = 0;
tim13s.Channels.OC3REF = 0;
tim13s.Channels.OC4REF = 0;
#endif
#ifdef USE_TIM14
tim14s.tx_cnt = TIM14->CNT;
tim14s.tx_step = SIM_Sample_Time * ABP1_TIMS_Value;
tim14s.Channels.OC1_GPIOx = GPIOA;
tim14s.Channels.OC1_PIN_SHIFT = 6;
tim14s.Channels.OC2_GPIOx = GPIOA;
tim14s.Channels.OC2_PIN_SHIFT = 0;
tim14s.Channels.OC3_GPIOx = GPIOA;
tim14s.Channels.OC3_PIN_SHIFT = 0;
tim14s.Channels.OC4_GPIOx = GPIOA;
tim14s.Channels.OC4_PIN_SHIFT = 0;
tim14s.Channels.OC1REF = 0;
tim14s.Channels.OC2REF = 0;
tim14s.Channels.OC3REF = 0;
tim14s.Channels.OC4REF = 0;
#endif
}
/*-------------------------------TIMERS----------------------------------*/
//-----------------------------------------------------------------------//

View File

@@ -0,0 +1,111 @@
/**************************************************************************
Äàííûé ôàéë íåîáõîäèì äëÿ îïðåäåëåíèÿ, êàêóþ ïåðèôåðèþ íàîáõîäèìî áóäåò
ñèìóëèðîâàòü.
**************************************************************************/
#ifndef _MATLAB_SETUP_H_
#define _MATLAB_SETUP_H_
// DEFINES (UNCOMMENT WHAT YOU WILL SIMULATE)
// TIMS
#define USE_TIM1
//#define USE_TIM2
#define USE_TIM3
#define USE_TIM4
//#define USE_TIM5
//#define USE_TIM6
#define USE_TIM7
//#define USE_TIM8
//#define USE_TIM9
//#define USE_TIM10
//#define USE_TIM11
#define USE_TIM12
//#define USE_TIM13
//#define USE_TIM14
// TIM'S HANDLERS
//#define USE_TIM1_UP_TIM10_HANDLER
//#define USE_TIM2_HANDLER
//#define USE_TIM3_HANDLER
#define USE_TIM4_HANDLER
//#define USE_TIM5_HANDLER
//#define USE_TIM6_HANDLER
#define USE_TIM7_HANDLER
//#define USE_TIM8_UP_TIM13_HANDLER
//#define USE_TIM1_BRK_TIM9_HANDLER
//#define USE_TIM1_TRG_COM_TIM11_HANDLER
#define USE_TIM8_BRK_TIM12_HANDLER
//#define USE_TIM8_TRG_COM_TIM14_HANDLER
//-----------------------------------------------------------------------//
/*------------------------------FUNCTIONS--------------------------------*/
void deInitialize_Periph_Sim(void);
void deInitialize_MCU(void);
void Initialize_Periph_Sim(void);
#include "stm32f4xx_matlab_rcc.h"
#include "stm32f4xx_matlab_gpio.h"
//-----------------------------------------------------------------------//
/*-------------------------------TIMERS----------------------------------*/
//#if defined(USE_TIM1) || defined(USE_TIM2) || defined(USE_TIM3) || defined(USE_TIM4) || defined(USE_TIM5) || \
// defined(USE_TIM6) || defined(USE_TIM7) || defined(USE_TIM8) || defined(USE_TIM9) || defined(USE_TIM10) || \
// defined(USE_TIM11) || defined(USE_TIM12) || defined(USE_TIM13) || defined(USE_TIM14)
#include "stm32f4xx_matlab_tim.h"
// CODE
void Init_TIM_SIM(void);
#ifdef USE_TIM1
extern struct TIM_Sim tim1s;
#endif
#ifdef USE_TIM2
extern struct TIM_Sim tim2s;
#endif
#ifdef USE_TIM3
extern struct TIM_Sim tim3s;
#endif
#ifdef USE_TIM4
extern struct TIM_Sim tim4s;
#endif
#ifdef USE_TIM5
extern struct TIM_Sim tim5s;
#endif
#ifdef USE_TIM6
extern struct TIM_Sim tim6s;
#endif
#ifdef USE_TIM7
extern struct TIM_Sim tim7s;
#endif
#ifdef USE_TIM8
extern struct TIM_Sim tim8s;
#endif
#ifdef USE_TIM9
extern struct TIM_Sim tim9s;
#endif
#ifdef USE_TIM10
extern struct TIM_Sim tim10s;
#endif
#ifdef USE_TIM11
extern struct TIM_Sim tim11s;
#endif
#ifdef USE_TIM12
extern struct TIM_Sim tim12s;
#endif
#ifdef USE_TIM13
extern struct TIM_Sim tim13s;
#endif
#ifdef USE_TIM14
extern struct TIM_Sim tim14s;
#endif
/*-------------------------------TIMERS----------------------------------*/
//-----------------------------------------------------------------------//
#endif // _MATLAB_SETUP_H_