diplom/научка/code/matlab_stm_emulate/.outdate/MCU_Wrapper/controller.h
2025-05-09 21:26:59 +03:00

251 lines
13 KiB
C

/**************************************************************************
Ãëàâíûé çàãîëîâî÷íûé ôàéë äëÿ ìàòëàáà. Âêëþ÷àåò äåéôàéíû äëÿ S-Function,
îáúÿâëÿåò áàçîâûå ôóíêöèè äëÿ ñèìóëÿöèè ÌÊ è ïîäêëþ÷àåò áàçîâûå áèáëèîòåêè:
äëÿ S-Function "simstruc.h"
äëÿ ÌÊ "main.h"
äëÿ ñèìóëÿöèè "stm32f4xx_matlab_conf.h"
**************************************************************************/
#ifndef _CONTROLLER_H_
#define _CONTROLLER_H_
typedef void* HANDLE;
#include "mcu_wrapper_conf.h" // For stm simulate functions
#include "simstruc.h" // For S-Function variables
#include <process.h> // For threads
// Parameters of S_Function
#define NPARAMS 1 // number of input parametrs (only Ts)
#define PORT_WIDTH 16 // width of one port
#define PORT_NUMB 2 // amount of ports
// Parametrs of MCU simulation
#define MAX_STACK_SIZE 0xFFFF // If stack is bigger than this number - exit simulations.
#define MAX_WHILE_TIMEOUT 0xFFF // timeout for while. If after this amount of cycles app stil in while - stop app and go to wrapper
#define TIME_FOR_MCU_APP 0xFF //
/** MCU HANDLE STRUCTURE */
/**
* @brief MCU handle Structure definition.
* @var pStackPtr_Origin - pointer to the "beginning" of the stack (RSP before go to MCU app)
* @vars Main stop context - context of MCU app at stop point.
Included: registers, pointer to stack and saved stack.
* @var Main start context - context of wrapper, before go to MCU app @ref setjmp/longjmp.
* @vars Flags and counters - flags and counter that control MCU app.
* @note Do not change stucrure before Stack_Buff, the assembly code uses fixed address offsets.
*/
typedef struct _DEL_MCUHandleTypeDef {
uint64_t* pStackPtr_Origin; /* óêàçàòåëü íà "íà÷àëî" ñòåêà - êîíåö ñòåêà ó óïðàâëÿþùåé ÌÊîì ôóíêöèè */
// Main stop context
_JUMP_BUFFER REGS; /* ðåãèñòðû âî âðåìÿ ïðèîñòàíîâêè ïðîãðàììû ÌÊ */
int long Stack_Size; /* ðàçìåð ñòåêà - îò "íà÷àëà" äî "âåðõíóøêè" */
uint64_t* pStackPtr_Current; /* óêàçàòåëü íà ïîñëåäíèé ýëåìåíò ñòåêà */
uint64_t Stack_Buff[MAX_STACK_SIZE]; /* ñîäåðæèìîå ñòåêà îò "íà÷àëà" äî "âåðõíóøêè" âî âðåìÿ ïðèîñòàíîâêè */
// Main start context
jmp_buf main_start; /* áóôôåð, äëÿ âûõîäà èç ïðîãðàììû ÌÊ - longjmp(main_start) */
// Flags and counters
int While_Timeout; /* ñ÷åò÷èê, ïîñëå èñòå÷åíèÿ êîòîðîãî while ïðåðûâàåòñÿ */
unsigned Stop_MCU_App : 1; /* ôëàã äëÿ îñòàíîâêè ïðîãðàììû ÌÊ */
unsigned Resume_MCU_App : 1; /* ôëàã äëÿ âîçîáíîâëåíèÿ ðàáîòû ïðîãðàììû ÌÊ */
unsigned Get_RSP_Origin : 1; /* ôëàã äëÿ ïîëó÷åíèÿ óêàçàòåëÿ íà "íà÷àëî" ñòåêà */
}DEL_MCUHandleTypeDef;
extern DEL_MCUHandleTypeDef hmcu; /* extern äëÿ âèäèìîñòè ïåðåìåííîé âî âñåõ ôàéëàõ */
// Variable for param of S-Function
extern double SIM_Sample_Time; // sample time
//-------------------------------------------------------------//
//------------------- SAVE CONTEXT DEFINES ------------------//
/** SAVE STACK */
/**
* @brief Save stack of running program.
* @param _hmcu_ - MCU Handle structure with registers and stack buff for filling.
*
* @code @ref _SAVE_STACK_CODE_ to see for replace _SAVE_STACK_ macros (for debug).
*/
#define _SAVE_STACK_(_hmcu_) if(1){ \
/* Ñáðîñ èíäåêñà áóôåðà äëÿ ñòåêà */ _hmcu_.Stack_Size = 0; \
/* Ïîêà âåñü íåîáõîäèìûé ñòåê íå ñîõðàíåí */ native_while( _hmcu_.pStackPtr_Current != _hmcu_.pStackPtr_Origin) \
/* Åñëè áóôåð íå ïåðåïîëíåí: */ if(_hmcu_.Stack_Size <= MAX_STACK_SIZE) \
/* Ñîõðàíåíèå ñòåêà */ _hmcu_.Stack_Buff[_hmcu_.Stack_Size++] = *_hmcu_.pStackPtr_Current++; \
/* Åñëè áóôåð ïåðåïîëíåí: */ else { \
/* Ñîîáùåíèå îá îøèáêå è âûõîä èç ïðîãðàììû */ printf("Max stack size is reached\n"); \
exit(0); \
}}else
/***************************************************************/
/** SAVE PROGRAMM COUNTER */
/**
* @brief Save programm counter (RIP register) of running program.
* @param _hmcu_ - MCU Handle structure with registers and stack buff for filling
* @note Èñïîëüçóåòñÿ âìåñòå ñ @ref _SAVE_CONTEXT_ äëÿ îïðåäåëåíèÿ òî÷êè âîçâðàòà.
* Âûçûâàåòñÿ äî èëè ïîñëå _SAVE_CONTEXT_, êàê âàì íóæíî.
* @ret Store address of next instruction after this macros in Rip
*/
#define _SAVE_RIP_(_hmcu_) _hmcu_.REGS.Rip = getNextAddr()
/***************************************************************/
//------------------- SAVE CONTEXT DEFINES ------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//------------------ 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 êîòîðûé áóäåò èñïîëüçîâàòüñÿ â ñèìóëèíêå */
/** DEFAULT WHILE */
/**
* @brief Default/Native C while statement.
* @param _expression_ - expression for while.
* @note Äàííûé while - àíàëîã îáû÷íîãî while, áåç äîïîëíèòåëüíîãî ôóíêöèîíàëà.
*/
#define native_while(_expression_) for(; (_expression_); )
/***************************************************************/
/** SIMULINK WHILE */
/**
* @brief While statement for emulate MCU code in Simulink.
* @param _expression_ - expression for while.
* @note Äàííûé while, ïðè óñëîâèè, ÷òî ïðîãðàììà â íåãî âõîäèò (_expression_ != 0)
* ñîõðàíÿåò êîíòåêñò ïðîãðàììû è óñòàíàâëèâàåò òàéìàóò (îïðåäåëåííîå êîë-âî öèêëîâ).
* Åñëè òàéìàóò èñòåêàåò ïðîèñõîäèò ïðåðûâàíèå ïðîãðàììû. È îíà âîçâðàùàåòñÿ â îáîëî÷êó,
* êîòîðàÿ ïåðåéäåò íà ñëåäóþùèé òàêò è ñíîâà ïîïðîáóåò ïðîéòè óñëîâèå. È òàê äàëåå
* Òàêèì îáðàçîì ïðîãðàììà ÌÊ çàâèñíåò íà ýòîì while, íî ïåðåôèðèÿ ïðîäîëæèò ðàáîòàòü.
*
* @code @ref sim_while_CODE_ to see for replace while sim_while (for debug).
*/
extern unsigned flag_to_end;
#define sim_while(_expression_) while((_expression_)&&(flag_to_end == 0))
//#define sim_while(_expression_) while(0);if(_expression_&&(hmcu.While_Timeout>-5)){ \
///* Óñòàíîâêà òàéìàóòà äëÿ while */ hmcu.While_Timeout = MAX_WHILE_TIMEOUT; \
// } \
///* Öèêë while - for(;_expression_;) */ native_while(_expression_) \
///* Åñëè òàéìàóò èñòåê */ if(hmcu.While_Timeout-- < 0 ) { \
///* Cáðîñ òàéìàóòà, ÷òîáû íà ñëåä øàãå âîéòè â òåëî öèêëà */ hmcu.While_Timeout = 0; \
///* Óñòàíîâêà ôëàãà äëÿ îñòàíîâêè ïðîãðàììû */ hmcu.Stop_MCU_App = 1; \
///* Óñòàíîâêà ôëàãà äëÿ âîçâðàòà â êîä ÌÊ íà ñëåä øàãå */ hmcu.Resume_MCU_App = 1; \
///* Ñîõðàíåíèå êîíòåêñòà */ saveProgramContext(); \
// if(hmcu.Stop_MCU_App) \
///* Âîçâðàò â îáîëî÷êó */ longjmp(hmcu.main_start, 1); \
// } \
///* Èíà÷å - âûïîëíåíèå òåëà öèêëà */ else
//------------------ SIMULINK WHILE DEFINES -----------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//---------------- SIMULATE FUNCTIONS PROTOTYPES -------------//
/** MCU STEP SIMULATION */
/**
* @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 Âûçûâàåò ãëàâíóþ ôóíêöèþ main èç ïîëüçîâàòåëüñêîãî êîäà è óïðàâëÿåò å¸ õîäîì:
* Ïðåðûâàåò å¸, åñëè îíà ïîïàëà â áåñêîíå÷íûé while, ñèìóëèðóåò ïåðèôåðèþ
* è âîçâðàùàåò â òî÷êó îñòàíîâêè íà ñëåäóþùåì øàãå.
*/
/* simulate controller step */
void MCU_Step_Simulation(SimStruct *S, const real_T *in,
real_T *disc, 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);
/** SAVE CONTEXT OF PROGRAMM */
/**
* @brief Save context (stack, registers) of running program.
* @note Äàííàÿ ôóíêöèÿ óñòàíàâëèâàåò ñ÷åò÷èê êîììàíä íà íà÷àëî ôóíêöèè.
* Òàê ÷òî âîçâðàò áóäåò ïðîèçâåäåí â íà÷àëî ýòîé ôóíêöèè.
*/
void saveProgramContext(void);
/** GET NEXT INSTRUCTION ADDRESS */
/**
* @brief Gives the address where this function will return.
*/
void* getNextAddr(void);
//---------------- SIMULATE FUNCTIONS PROTOTYPES -------------//
//-------------------------------------------------------------//
#endif // _CONTROLLER_H_
/** MACROSES REPLACEMENT CODE */
/** _SAVE_STACK_CODE_
* CODE TO REPLACE _SAVE_STACK_() MACROS (FOR DEBUG) */
/*
hmcu.Stack_Size = 0; // Ñáðîñ èíäåêñà áóôåðà äëÿ ñòåêà
// Ïîêà âåñü íåîáõîäèìûé ñòåê íå ñîõðàíåí
native_while(hmcu.pStackPtr_Current != hmcu.pStackPtr_Origin)
if (hmcu.Stack_Size <= MAX_STACK_SIZE) // Åñëè áóôåð íå ïåðåïîëíåí
hmcu.Stack_Buff[hmcu.Stack_Size++] = *hmcu.pStackPtr_Current++; // Ñîõðàíåíèå ñòåêà
else { // Åñëè áóôåð ïåðåïîëíåí
printf("Max stack size is reached\n"); // Ñîîáùåíèå îá îøèáêå è âûõîä èç ïðîãðàììû
exit(0); }
*/
/***************************************************************/
/** sim_while_CODE_
* CODE TO REPLACE sim_while() MACROS (FOR DEBUG) */
/*
while(0);if(_expression_&&(hmcu.While_Timeout>-5)){
hmcu.While_Timeout = MAX_WHILE_TIMEOUT; // Óñòàíîâêà òàéìàóòà äëÿ while
}
native_while(_expression_) // Öèêë while - for(;_expression_;)
if (hmcu.While_Timeout-- < 0) { // Åñëè òàéìàóò èñòåê
hmcu.While_Timeout = 0; // Ñáðîñ òàéìàóòà, ÷òîáû íà ñëåä øàãå âîéòè â òåëî öèêëà
hmcu.Stop_MCU_App = 1; // Óñòàíîâêà ôëàãà äëÿ îñòàíîâêè ïðîãðàììû
hmcu.Resume_MCU_App = 1; // Óñòàíîâêà ôëàãà äëÿ âîçâðàòà â êîä ÌÊ íà ñëåä øàãå
saveProgramContext(); // Ñîõðàíåíèå êîíòåêñòà
if(hmcu.Stop_MCU_App) // Åñëè ïðèëîæåíèå áûëî îñòàíîâëåíî
longjmp(hmcu.main_start, 1); // Âîçâðàò â îáîëî÷êó
// èíà÷å (ïðè âîçâðàùåíèè â êîä ÌÊ) ïðîäîëæèòü âûïîëíåíèå êîäà
}
else // Èíà÷å - âûïîëíåíèå òåëà öèêëà
*/
/***************************************************************/