iap.c 4.1 KB
#include "iap.h" 
#include "usart.h"
#include "crc.h"
#include "flash.h"
#include "delay.h"
#include "usart1.h"    
#include "uart5.h" 

iapfun 	jump2app; 


//跳转到应用程序段
//appxaddr:用户代码起始地址.
void Run_Flash_App(u32 appxaddr)
{
	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.
	{ 
		jump2app=(iapfun)*(vu32*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		
		MSR_MSP(*(vu32*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		jump2app();									//跳转到APP.
	}
}		 












/****************************************************
* @brief:	通过RS485接口,本地下载固件
* @param:	
* @retva:
* @note:	
******************************************************/
uint8_t 	Success[] 	= "FireWare Check Success\r\n";
uint8_t		Fail[]	  	= "FireWare Check Fail\r\n";
uint8_t		Incorrect[] = "Input Command Incorrect\r\n";

uint8_t		Manual_Labal[]	= "CMD				Description\r\n";
uint8_t		Manual_Start[]	= "START			Start Up Transmit FireWare\r\n";
uint8_t 	Manual_Ack[]	= "ACK:			Confirm The FireWare\r\n";
uint8_t		Manual_Cancel[]	= "CANCEL			Cancel The Update Program\r\n";
uint8_t		Manual_Line[]	= "\r\n*******************************************\r\n";

uint8_t		Ok[]	= "OK\r\n";

void Local_Update(void)
{
	Clear_Uart5_Cache();
	
	uint16_t 	crc = 0xFFFF;
	uint32_t	handle;
	
	delay_ms(70);
	Uart5_Send(Manual_Line,sizeof(Manual_Line));
	delay_ms(70);
	Uart5_Send(Manual_Labal,sizeof(Manual_Labal));
	delay_ms(70);
	Uart5_Send(Manual_Start,sizeof(Manual_Start));
	delay_ms(70);
	Uart5_Send(Manual_Ack,sizeof(Manual_Ack));
	delay_ms(70);
	Uart5_Send(Manual_Cancel,sizeof(Manual_Cancel));
	delay_ms(70);
	Uart5_Send(Manual_Line,sizeof(Manual_Line));
	
	
	while(1)
	{
		if(UART_FINISH)
		{
			if(strncmp((char *)UART_RX_BUF,"ACK",sizeof("ACK")) == 0)			//确认数据
			{
				Uart5_Send(Ok,sizeof(Ok));
				handle = BOOTLOADER_RUN;
				STMFLASH_Write(FLAG_BASE_ADDR,(uint32_t *)&handle,4);
			}
			else if(strncmp((char *)UART_RX_BUF,"START",sizeof("START")) == 0)	//启动传输
			{
				Uart5_Send(Ok,sizeof(Ok));
				Clear_Uart5_Cache();
				UART_FINISH = false;
				
				while(UART_FINISH != true);
				
				printf("receive %d Bytes msg\r\n",&UART_RX_CNT);
				Uart5_Send(Ok,sizeof(Ok));
				
				crc = GenerateCRC16(UART_RX_BUF,UART_RX_CNT-2);
				printf("CACL = %x\r\n",crc);
				
				if(crc == ((UART_RX_BUF[UART_RX_CNT-2] << 8 ) | UART_RX_BUF[UART_RX_CNT-1]))
				{
					STMFLASH_Write(APP_RUN_ADDR,(uint32_t *)UART_RX_BUF,UART_RX_CNT - 2);
					
					Uart5_Send(Success,sizeof(Success));
				}
				else 
				{
					Uart5_Send(Fail,sizeof(Fail));
				}
				printf("CRC = %x\r\n",crc);
			}
			else if(strncmp((char *)UART_RX_BUF,"CANCEL",sizeof("CANCEL")) == 0 )	//返回
			{
				Uart5_Send(Ok,sizeof(Ok));
				break;
			}
			else 
			{
				Uart5_Send(Incorrect,sizeof(Incorrect));
			}
			
			Clear_Uart5_Cache();
			UART_FINISH = false;
			UART5_Mode(RS485_READ);
		}
	}
}




/******************************************************
* @brief:	检测是否有触发本地升级
* @param:
* @retva:
* @note:	
********************************************************/
uint8_t 	Update[]	= "Enter Local Update\r\n";
void 	Detection_Update(void)
{
	uint8_t i ; 
	
	for(i=0;i<WAIT_TIME;i++)
	{
		delay_ms(1000);
		if(UART_FINISH)
		{
			UART_FINISH= false;
			if(strncmp((char *)UART_RX_BUF,"UPDATE",sizeof("UPDATE")) == 0)//F12
			{
				Uart5_Send(Update,sizeof(Update));
				Local_Update();
				break;
			}
		}
	}
}

#define VERSION		"Bootloader version: MFGW2.0\r\n"

uint8_t uart_boot_detect(void)
{
	uint8_t retry_cnt=0;
	printf(WELCOME);
	printf(VERSION);
	for(retry_cnt=0;retry_cnt<LOCAL_WAITE_TIME;retry_cnt++)
	{
		printf("Run application after %d second(s)...........\r\n",LOCAL_WAITE_TIME-retry_cnt);
		printf("Input any key and Enter to stay in bootloader\r\n");
		delay_ms(1000);
		
		if((u5.rx_status == RX_FINISHED)&&
		((u5.rx_buf[0]=='b')||(u5.rx_buf[0]=='B'))&&
		(u5.rx_len == 2))
		{
			return LOCAL_BOOT_FROM_UART5;
		}
		else if((u1.rx_status == RX_FINISHED)&&
		((u1.rx_buf[0]=='b')||(u1.rx_buf[0]=='B'))&&
		(u1.rx_len == 2))
		{
			return LOCAL_BOOT_FROM_USART1;
		}
		else
		{
		// not detected
		}
	}
	return LOCAL_BOOT_NONE;
}