/*品智科技S32K118开发板*/


/* bootloader实验
 * 实验目的：
 * 将bootloader 和 app 工程烧录进入开发板，在bootloader程序里，使用按键KEY1，跳转进入APP程序
 *
 * BOOTLOADRT程序内存分配：
 * 中断向量表
 * 0x00000000 - 0x000000C0
 * flash配置信息
 * 0x00000400 - 0x00000410
 * bootloader程序 占用31.728k空间
 * 0x00000410 - 0x00008000
 *
 * APP程序内存分配：
 * 中断向量表
 * 0x00008000 - 0x00008400
 * flash配置信息
 * 0x00008400 - 0x00008410
 * bootloader程序 占用256k空间
 * 0x00008410 - 0x00048410
 * 内存配置文件在工程文件夹内的Project Setting/Linker Files/S32K144_64_flash下
 *
 * 操作方法，将两个应用同时烧录进开发板内即可。
 * KEY1 PTC14
 * KEY2 PTC15
 * KEY3 PTC16
 * LED1 PTD16
 * LED2 PTD15
 * LED3 PTE9
 * LED4 PTE8
 * 开发板采用无外部晶振设计,时钟走FIRC 48mhz,配置时钟时需要注意
 */


#include "Cpu.h"
#include "delay.h"
#include "uart.h"
#include "oled.h"
#include "key.h"

  volatile int exit_code = 0;

/* User includes (#include below this line is not maintained by Processor Expert) */

#define LED1(x)  PINS_DRV_WritePin(PTD,16,!x);
#define LED2(x)  PINS_DRV_WritePin(PTD,15,!x);
#define LED3(x)  PINS_DRV_WritePin(PTE,9,!x);
#define LED4(x)  PINS_DRV_WritePin(PTE,8,!x);

#define APP_START_ADDRESS	0x00008000 //app开始地址

  void JumpToUserApplication( unsigned int userSP,  unsigned int userStartup)
  {
	(void)userSP; //使参数不报警告信息
	(void)userStartup;
  	/* 设置栈指针  */
  	__asm("msr msp, r0");
  	__asm("msr psp, r0");

  	/* 重新定向中断向量表 */
  	S32_SCB->VTOR = (uint32_t)APP_START_ADDRESS;

  	/* 跳转至APP */
  	__asm("mov pc, r1");
  }

  void Bootup_Application(uint32_t appEntry, uint32_t appStack)
  {
  	static void (*jump_to_application)(void);
  	static uint32_t stack_pointer;
  	/*把应用程序入口地址赋值给函数指针*/
  	jump_to_application = (void (*)(void))appEntry;
  	stack_pointer = appStack;
  	/* 重新定向中断向量表 */
  	S32_SCB->VTOR = (uint32_t)APP_START_ADDRESS;
  	/* 设置栈指针  */
  	__asm volatile ("MSR msp, %0\n" : : "r" (stack_pointer) : "sp");
  	__asm volatile ("MSR psp, %0\n" : : "r" (stack_pointer) : "sp");
  	/*跳转*/
  	jump_to_application();
  }



int main(void)
{

  /* Write your local variable definition here */
	int MCU_Freq;
	uint8_t pinstate;
	uint32_t appEntry, appStack;
  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of Processor Expert internal initialization.                    ***/
    CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
                   g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
    MCU_Freq = delay_init();//初始化delay函数


    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);

	LED1(0);
	LED2(0);
	LED3(0);
	LED4(0);

    I2C_MasterInit(&i2c1_instance, &i2c1_MasterConfig0);//初始化I2C外设,用于OLED通讯
	LPUART_DRV_Init(INST_LPUART1, &lpuart1_State, &lpuart1_InitConfig0); //初始化串口

	oled_init(); //OLED配置参数初始化
	OLED_TITLE((uint8_t*)"S32K118",(uint8_t*)"BLOADER");//OLED显示标题
	OLED_ShowString(0,2,(uint8_t*)"  BOOTLOADER",16,0); //OLED显示字符串
	u1_printf("当前进入BOOTLOADER程序,MCU运行频率为 %d Mhz \r\n",MCU_Freq);



    while(1)
    {
    	pinstate = KEY_Proc (1);
    		if(pinstate ==BTN1_PRES )
    				{
    				u1_printf("KEY1 按下 2秒后进入app \r\n");
    				OLED_ShowString(0,4,(uint8_t*)"   ENTER APP",16,0); //OLED显示字符串
    				OLED_ShowString(0,6,(uint8_t*)" in 2 seconds",16,0); //OLED显示字符串
    				delay_ms(1000);
    				OLED_ShowString(0,6,(uint8_t*)" in 1 seconds",16,0); //OLED显示字符串
    				delay_ms(1000);
    				OLED_ShowString(0,6,(uint8_t*)" in 0 seconds",16,0); //OLED显示字符串


						appStack = *(uint32_t *)(APP_START_ADDRESS);
						appEntry = *(uint32_t *)(APP_START_ADDRESS + 4);
						Bootup_Application(appEntry, appStack);


    				//JumpToUserApplication(*((uint32_t*)APP_START_ADDRESS), *((uint32_t*)(APP_START_ADDRESS + 4)));
    				}

    			else
    			{
    				LCD_clear_L(0,4); //OLED清行
    				LCD_clear_L(0,5);
    			}
    	    	delay_ms(100);
    	    	PINS_DRV_TogglePins(PTE, 1 << 8);
    	    	PINS_DRV_TogglePins(PTE, 1 << 9);
    }




  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;) {
    if(exit_code != 0) {
      break;
    }
  }
  return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END main */
/*!
** @}
*/
/*
** ###################################################################
**
**     This file was created by Processor Expert 10.1 [05.21]
**     for the NXP S32K series of microcontrollers.
**
** ###################################################################
*/
