⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iapboot.c

📁 使用LPC2134 CPU,IAP功能
💻 C
字号:
/****************************************************************************
* File:IAPTEST.C
* 功能:LPC210x的IAP功能测试。
* 说明:调用IAP服务程序,完成FLASH编程操作。
****************************************************************************/
#include <string.h>
#include <stdlib.h>
//#include "basic.h"
#include  "config.h"
#include "smartcard.h"


#define APP_MAIN_ADDRESS	0X00004000		//主程序入口地址

#define LAMP 		0x01000000		//P0.24 状态指示灯
#define Bright      IO1CLR = LAMP;  //
#define Drown       IO1SET = LAMP;

#define IAP_ENTER_ADR   0x7FFFFFF1          /* IAP入口地址定义 */

/* 定义IAP命令字 */
#define  IAP_SELSECTOR        50
#define  IAP_RAMTOFLASH       51
#define  IAP_ERASESECTOR      52
#define  IAP_BLANKCHK         53
#define  IAP_READPARTID       54
#define  IAP_BOOTCODEID       55
#define  IAP_COMPARE          56

/* 定义IAP返回状态字 */
#define  CMD_SUCCESS          0
#define  INVALID_COMMAND      1
#define  SRC_ADDR_ERROR       2 
#define  DST_ADDR_ERROR       3
#define  SRC_ADDR_NOT_MAPPED  4
#define  DST_ADDR_NOT_MAPPED  5
#define  COUNT_ERROR          6
#define  INVALID_SECTOR       7
#define  SECTOR_NOT_BLANK     8
#define  SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9
#define  COMPARE_ERROR        10
#define  BUSY                 11
#define  PARAM_ERROR          12 /* Insufficient number of parameters */
#define  ADDR_ERROR           13 /* Address not on word boundary */
#define  ADDR_NOT_MAPPED      14
#define  CMD_LOCKED           15 /* Command is locked */
#define  INVALID_CODE         16 /* Unlock code is invalid */
#define  INVALID_BAUD_RATE    17
#define  INVALID_STOP_BIT     18

#define  IAP_ERR			  -1 /*自定义错误值*/

/* 定义CCLK值大小,单位为KHz */
#define  IAP_FCCLK           11059

//定义用户应用程序所用扇区范围
#define EE_SEC_L 4
#define EE_SEC_H 10
#define   ICFileBlockSize 0x8000;


//升级应用程序的
int32	FileSumNum = 0;		//应用程序文件的总块数
int32    LastFileSize = 0;		//最后一个文件的大小

/* 定义函数指针 */
void (*IAP_Entry)(uint32 param_tab[], uint32 result_tab[]);


//应用程序入口
void (*run_app)(void)=(void (*)(void))APP_MAIN_ADDRESS;

uint32  paramin[8];                         // IAP入口参数缓冲区
uint32  paramout[8];                        // IAP出口参数缓冲区
uint8  psData[520];						// 升级数据

/****************************************************************************
* 名称:SelSector()
* 功能:IAP操作扇区选择,命令代码50。
* 入口参数:sec1        起始扇区
*          sec2        终止扇区
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void  SelSector(uint8 sec1, uint8 sec2)
{  paramin[0] = IAP_SELSECTOR;              // 设置命令字
paramin[1] = sec1;                       // 设置参数
paramin[2] = sec2;
(*IAP_Entry)(paramin, paramout);         // 调用IAP服务程序
}


/****************************************************************************
* 名称:RamToFlash()
* 功能:复制RAM的数据到FLASH,命令代码51。
* 入口参数:dst        目标地址,即FLASH起始地址。以512字节为分界
*          src        源地址,即RAM地址。地址必须字对齐
*          no         复制字节个数,为512/1024/4096/8192
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void  RamToFlash(uint32 dst, uint32 src, uint32 no)
{  paramin[0] = IAP_RAMTOFLASH;             // 设置命令字
paramin[1] = dst;                        // 设置参数
paramin[2] = src;
paramin[3] = no;
paramin[4] = IAP_FCCLK;
(*IAP_Entry)(paramin, paramout);         // 调用IAP服务程序
}


/****************************************************************************
* 名称:EraseSector()
* 功能:扇区擦除,命令代码52。
* 入口参数:sec1       起始扇区
*          sec2       终止扇区
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void  EraseSector(uint8 sec1, uint8 sec2)
{  paramin[0] = IAP_ERASESECTOR;            // 设置命令字
paramin[1] = sec1;                       // 设置参数
paramin[2] = sec2;
paramin[3] = IAP_FCCLK;
(*IAP_Entry)(paramin, paramout);         // 调用IAP服务程序
}

/****************************************************************************
* 名称:BlankCHK()
* 功能:扇区查空,命令代码53。
* 入口参数:sec1       起始扇区
*          sec2       终止扇区
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void  BlankCHK(uint8 sec1, uint8 sec2)
{  paramin[0] = IAP_BLANKCHK;               // 设置命令字
paramin[1] = sec1;                       // 设置参数
paramin[2] = sec2;
(*IAP_Entry)(paramin, paramout);         // 调用IAP服务程序
}


/****************************************************************************
* 名称:ReadParID()
* 功能:扇区查空,命令代码53。
* 入口参数:无
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void  ReadParID(void)
{  paramin[0] = IAP_READPARTID;             // 设置命令字
(*IAP_Entry)(paramin, paramout);         // 调用IAP服务程序
}


/****************************************************************************
* 名称:BootCodeID()
* 功能:读取boot代码版本号,命令代码55。
* 入口参数:无
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void  BootCodeID(void)
{  paramin[0] = IAP_BOOTCODEID;             // 设置命令字
(*IAP_Entry)(paramin, paramout);         // 调用IAP服务程序
}


/****************************************************************************
* 名称:Compare()
* 功能:校验数据,命令代码56。
* 入口参数:dst        目标地址,即RAM/FLASH起始地址。地址必须字对齐
*          src        源地址,即FLASH/RAM地址。地址必须字对齐
*          no         复制字节个数,必须能被4整除
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void  Compare(uint32 dst, uint32 src, uint32 no)
{  paramin[0] = IAP_COMPARE;                // 设置命令字
paramin[1] = dst;                        // 设置参数
paramin[2] = src;
paramin[3] = no;
(*IAP_Entry)(paramin, paramout);         // 调用IAP服务程序
}


void delay()
{
	volatile uint32 i = 0x4ffff; 
	while(i--){};
}

//擦除整个应用程序存储FLASH
int iap_entire_erase()
{	

	SelSector(EE_SEC_L,EE_SEC_H);

	EraseSector(EE_SEC_L,EE_SEC_H);                        // 擦除扇区1

	BlankCHK(EE_SEC_L,EE_SEC_H);

	if(paramout[0] != CMD_SUCCESS){
		return IAP_ERR;
	}

	return 0;
}

//写入数据到ROM FLASH
int32 iap_copyto(uint32 dst, uint8 *src, uint32 len)
{	
	int start, end;
	if((uint32) dst < 0x8000){
		start = (uint32) dst >> 12;
		if(((uint32) dst & 0xfff) + len > 0x1000){
			end = start + 1;
		}else{
			end = start;
		}
	}else if((uint32) dst < 0x78000){
		start = ((uint32) dst >> 15) + 7;
		if(((uint32) dst & 0x7fff) + len > 0x8000){
			end = start + 1;
		}else{
			end = start;
		}
	}else if((uint32) dst < 0x7d000){
		start = ((uint32) dst >> 12) - 0x62;
		if(((uint32) dst & 0xfff) + len > 0x1000){
			end = start + 1;
			if(end > 26) return IAP_ERR;
		}else{
			end = start;
		}
	}else{
		return IAP_ERR;
	}

	SelSector(start,end);

	if(paramout[0] != CMD_SUCCESS){
		return IAP_ERR;
	}

	if(len < 256)
		len = 256;

	RamToFlash(dst, (uint32)src, len);

	if(paramout[0] != CMD_SUCCESS){
		return IAP_ERR;
	}

	return 0;
}



void LampStateFlash(int time)
{
	while(time --){
		Bright;
		delay();
		Drown;
		delay();
	}
}


int CheckUpdateFlag()
{
	char cTemp[8];
	
	if( UserCardStart() )
		return 0;
	
	if( UserCardSelect(0x01, 0x00) )//选择USER卡分户编号文件
		return 0;
	
	if( UserCardReadBin(0, 75, psData) )//读USER卡分户编号文件
		return 0;		
	
	memset(cTemp, 0, 8);
	memcpy(cTemp, psData+68, 2);
	FileSumNum = atoi(cTemp)-1;
	memset(cTemp, 0, 8);
	memcpy(cTemp, psData+70, 5);
	LastFileSize = atoi(cTemp);
	
	if(FileSumNum <= 0)
		return 0;
	
	return 1;
}


int UpdateDataFromIC( )
{
	int i;
	int offset = 0;
	int filelen = 0;
	int readlen;

	int offsetrom = 0;
	for(i=0; i<FileSumNum; i++)
	{
		if(i == FileSumNum-1)
			filelen = LastFileSize;
		else
			filelen = ICFileBlockSize;

		if( UserCardSelect(i+2, 0x00) )//选择USER卡分户编号文件
			return -1;
		
		offset = 0;
		//写入一个文件块
		while(offset < filelen)
		{			
			memset(psData, 0xFF, 512);
			//读入512个字节,写入一次ROM
			while(1)
			{			
				if( (filelen - offset) < 128)
					readlen =  (filelen - offset);
				else 
					readlen = 128;				
				if( UserCardReadBin(offset, readlen, psData+(offset & 0x1FF) ) )//读USER卡分户编号文件
					return -1;
				
				offset += readlen;
				if( (offset & 0x1FF) == 0x00 || filelen == offset)
					break;					
			}

			//执行IAP写入flash
			if( iap_copyto(APP_MAIN_ADDRESS+offsetrom, psData, 512) != 0)
				return -1;
			LampStateFlash(1);
			offsetrom += 512;			

		}
	}

	return 0;		
}



/****************************************************************************
* 名称:main()
* 功能:IAP函数调用,测试。
****************************************************************************/
int  main(void)
{ 	
	
	PINSEL0 = 0x000A0055;                // 设置I/O连接到UART0,使用I2C口,pwm4,pwm6
	IO1DIR |= LAMP; //指示灯信号输出 	
	
	SMARTCARD_Ini();			         // 初始化智能卡端口

	IAP_Entry = (void(*)())IAP_ENTER_ADR;    // 初始化函数指针IAP_Entry

	//读取升级标志
	//读取用户卡检测升级标志
	if(CheckUpdateFlag() == 0)
	{
		//不需要升级转入应用程序入口		
		Useoff();
		run_app();
		
	}
	
	//擦除应用存储FLASH
	if(iap_entire_erase() != 0)
		goto ERR;

	//读取升级数据
	if( UpdateDataFromIC() != 0)
		goto ERR;	
	
	//读取文件总长度和校验和

	//检查校验和	

	//转入应用程序入口	
	Useoff();
	run_app();
	while(1);

ERR:
	Useoff();
	while(1)
	{
		LampStateFlash(1);
		
	}
	return(0);
}







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -