note: - модбас не моделируется, в s-function просто передаются константы режимов. - лишние файлы убраны в outdate. - два канала одной фазы переключаются немного криво: на один такт симуляции проскакивает высокий уровень предыдущего канала и только потом включается текущий канал
		
			
				
	
	
		
			195 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**************************************************************************
 | 
						|
Äàííûé ôàéë ñîäåðæèò ôóíêöèè äëÿ ñèìóëÿöèè ÌÊ â Simulink (S-Function).
 | 
						|
 | 
						|
**************************************************************************/
 | 
						|
#include "simstruc.h"
 | 
						|
#include "mcu_wrapper_conf.h"
 | 
						|
//#include <windows.h>
 | 
						|
//#include <synchapi.h>
 | 
						|
 | 
						|
DEL_MCUHandleTypeDef hmcu;          // äëÿ óïðàâëåíèÿ êîíòåêñòîì ïðîãðàììû ÌÊ
 | 
						|
HANDLE hThread;
 | 
						|
uint32_t idThreads;
 | 
						|
unsigned flag_to_end;
 | 
						|
 | 
						|
double SystemClockDouble = 0;       // äëÿ ñèìóëÿöèè ñèñòåìíûõ òèêîâ, ïðîêà ïðîñòî ïî ïðèêîëó
 | 
						|
uint64_t SystemClock;               // äëÿ ñèìóëÿöèè ñèñòåìíûõ òèêîâ, ïðîêà ïðîñòî ïî ïðèêîëó
 | 
						|
 | 
						|
/* Extern function of control MCU App from asmjmp.asm */
 | 
						|
extern void GET_RSP_ORIGIN(DEL_MCUHandleTypeDef* hmcu);
 | 
						|
extern void RESTORE_CONTEXT_AND_JUMP(DEL_MCUHandleTypeDef* hmcu);
 | 
						|
extern void READ_REGS(_JUMP_BUFFER* hmcu);
 | 
						|
 | 
						|
//-------------------------------------------------------------//
 | 
						|
//-----------------CONTROLLER SIMULATE FUNCTIONS---------------//
 | 
						|
/** 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 */
 | 
						|
extern int main(void); // extern while from main.c
 | 
						|
unsigned __stdcall MCU_App_Thread(void) {
 | 
						|
    main(); // ñèìóëÿöèÿ êîäà ÌÊ 
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
void MCU_Step_Simulation(SimStruct* S, real_T* in, real_T* disc, time_T time)
 | 
						|
{
 | 
						|
    //-----------INIT WRAPPER-----------
 | 
						|
    if (hmcu.Get_RSP_Origin)    // åñëè íàäî ïîëó÷òü óêàçàòåëü íà "íà÷àëî" ñòåêà
 | 
						|
    {
 | 
						|
        hmcu.Get_RSP_Origin = 0;    // ñáðîñ ôëàãà, ÷òîáû ñþäà áîëüøå íå ïîïàäàòü
 | 
						|
        // óêàçàòåëü íà "íà÷àëî" ñòåêà - áåðåòñÿ â íà÷àëå ãëàâíîé óïðàâëÿþùåé ôóíêöèè
 | 
						|
        //GET_RSP_ORIGIN(&hmcu);
 | 
						|
 | 
						|
        // èíèöèàëèçàöèÿ ïîòîêà, êîòîðûé áóäåò âûïîëíÿòü êîä ÌÊ
 | 
						|
        hThread = (HANDLE)_beginthreadex(NULL, 0, MCU_App_Thread, 0, 0x00000004, &idThreads);
 | 
						|
 | 
						|
        ResumeThread(hThread);
 | 
						|
 | 
						|
        //Sleep(100);
 | 
						|
        for (int i = TIME_FOR_MCU_APP*10000; i > 0; i--)
 | 
						|
        {
 | 
						|
        }
 | 
						|
 | 
						|
        SuspendThread(hThread);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    //----------------------------------
 | 
						|
 | 
						|
    // Get uwTick (in ms)
 | 
						|
    //uwTick = time * 1000; // from simulation time 
 | 
						|
 | 
						|
    SystemClockDouble += SystemCoreClock * SIM_Sample_Time; // emulate core clock 
 | 
						|
    SystemClock = SystemClockDouble;
 | 
						|
    uwTick = SystemClock / (SystemCoreClock / 1000);
 | 
						|
 | 
						|
    MCU_readInputs(in); // ñ÷èòûâàíèå ïîðòîâ
 | 
						|
 | 
						|
    MCU_Periph_Simulation(); // simulate peripheral
 | 
						|
 | 
						|
    //// Return to MCU app at line, where it was stopped
 | 
						|
    //if (hmcu.Resume_MCU_App) // åñëè íåîáõîäèìî âåðíóòñÿ â êîä ÌÊ
 | 
						|
    //{
 | 
						|
    //    // Ñáðîñ ôëàãîâ
 | 
						|
    //    hmcu.Resume_MCU_App = 0;
 | 
						|
    //    hmcu.Stop_MCU_App = 0;
 | 
						|
    //    // Âîçâðàò â êîä ÌÊ
 | 
						|
    //    RESTORE_CONTEXT_AND_JUMP(&hmcu);
 | 
						|
    //}
 | 
						|
 | 
						|
    //// ñîõðàíåíèå êîíòåêñòà äî ïåðåõîäà â êîä ÌÊ
 | 
						|
    //if (!hmcu.Stop_MCU_App && (setjmp(hmcu.main_start) == 0))
 | 
						|
    //{   // åñëè êîíòåêñò ñîõðàíåí (setjmp == 0) è ÌÊ íå îñòàíîâëåí
 | 
						|
    //    main(); // ñèìóëÿöèÿ êîäà ÌÊ 
 | 
						|
    //}
 | 
						|
    // note: ïðè âûçîâå longjmp, setjmp != 0, ïîýòîìó ïðîãðàììà íå âîéäåò çàíîâî â main_loop
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    ResumeThread(hThread);
 | 
						|
    for (int i = TIME_FOR_MCU_APP; i > 0; i--)
 | 
						|
    {
 | 
						|
    }
 | 
						|
    SuspendThread(hThread);
 | 
						|
 | 
						|
 | 
						|
    MCU_writeOutputs(disc); // çàïèñü ïîðòîâ (ïî ôàêòó çàïèñü â áóôåð. çàïèñü â ïîðòû â mdlOutputs)
 | 
						|
}
 | 
						|
 | 
						|
/** SIMULATE MCU PERIPHERAL */
 | 
						|
/**
 | 
						|
  * @brief  Simulate peripheral of MCU
 | 
						|
  * @note   Ïîëüçîâàòåëüñêèé êîä, êîòîðûé ñèìóëèðóåò ðàáîòó ïåðèôåðèè ÌÊ.
 | 
						|
  */
 | 
						|
void MCU_Periph_Simulation(void)
 | 
						|
{
 | 
						|
    Simulate_TIMs();
 | 
						|
}
 | 
						|
 | 
						|
/** 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)
 | 
						|
{
 | 
						|
    SFUNC_to_GPIO(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)
 | 
						|
{		
 | 
						|
    GPIO_to_SFUNC(disc);
 | 
						|
}
 | 
						|
//-----------------CONTROLLER SIMULATE FUNCTIONS---------------//
 | 
						|
//-------------------------------------------------------------//
 | 
						|
 | 
						|
 | 
						|
//-------------------------------------------------------------//
 | 
						|
//----------INITIALIZE/DEINITIALIZE SIMULATE FUNCTIONS---------//
 | 
						|
/** 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.Get_RSP_Origin = 1;                        // set flag to store pionter to "beginning" pf the stack
 | 
						|
}
 | 
						|
/** 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();
 | 
						|
}
 | 
						|
//-------------------------------------------------------------//
 | 
						|
 | 
						|
 | 
						|
//-------------------------------------------------------------//
 | 
						|
//-------------------  SAVE CONTEXT FUNCTIONS -----------------//
 | 
						|
/** SAVE CONTEXT OF PROGRAMM */
 | 
						|
/**
 | 
						|
  * @brief  Save context (stack, registers) of running program.
 | 
						|
  * @note   Äàííàÿ ôóíêöèÿ óñòàíàâëèâàåò ñ÷åò÷èê êîììàíä íà íà÷àëî ôóíêöèè.
 | 
						|
  *         Òàê ÷òî âîçâðàò áóäåò ïðîèçâåäåí â íà÷àëî ýòîé ôóíêöèè.
 | 
						|
  */
 | 
						|
void saveProgramContext(void)
 | 
						|
{
 | 
						|
    _SAVE_RIP_(hmcu);
 | 
						|
    hmcu.REGS.Rip -= 5;     // Ñäâèã RIP ñ ýòîé êîìàíäû íà ïåðâóþ êîìàíäó â ôóíêöèè: sizeof(call getNextAddr) = 5
 | 
						|
    READ_REGS(&hmcu.REGS);  // Ñ÷èòûâàíèå ðåãèñòðîâ
 | 
						|
    _SAVE_STACK_(hmcu);     // Ñ÷èòûâàíèå ðåãèñòðîâ
 | 
						|
}
 | 
						|
 | 
						|
/** GET NEXT INSTRUCTION ADDRESS */
 | 
						|
/**
 | 
						|
  * @brief  Gives the address where this function will return.
 | 
						|
  */
 | 
						|
void* getNextAddr(void) {
 | 
						|
    return _ReturnAddress();
 | 
						|
}
 | 
						|
//-------------------------------------------------------------//
 |