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

📄 isp.c

📁 关于LPC23**的FLASH的ISP程序
💻 C
字号:
/* execute update code,the address is maybe 0xe000 */

#include "LPC23xx.h"                       
#include "type.h"
#include "target.h"
#include "irq.h"
#include "uart.h"

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

//IAP命令
								 //指令           	参数
#define IAP_CMD_PREPARE 	50   //选择扇区       	【起始扇区号、结束扇区号】
#define IAP_CMD_COPY 		51	 //拷贝数据			【FLASH目标地址、RAM源地址、写入字节数、系统时钟频率】
#define IAP_CMD_ERASE 		52	 //擦出扇区			【起始扇区号、结束扇区号、系统时钟频率】
#define IAP_CMD_CHECK 		53	 //查空扇区			【起始扇区号、结束扇区号】
#define IAP_CMD_ID 			54	 //读器件ID			【无】
#define IAP_CMD_VERSION 	55	 //读BOOT版本号		【无】
#define IAP_CMD_COMPARE 	56	 //比较命令			【FLASH起始地址、RAM起始地址、需要比较的字节数】
#define ISP_PC_NOUPDATE 0x20
#define ISP_PC_UPDATE 0x21
#define ISP_PC_DOWNLOAD 0x22
#define ISP_PC_FILE_LEN 0x23
#define ISP_MCU_UPDATE_OK 0x24
#define ISP_MCU_UPDATE_FAIL 0x25

//IAP返回状态字
#define IAP_RET_CMD_SUCCESS          						0
#define IAP_RET_INVALID_COMMAND      						1
#define IAP_RET_SRC_ADDR_ERROR       						2 
#define IAP_RET_DST_ADDR_ERROR       						3
#define IAP_RET_SRC_ADDR_NOT_MAPPED  						4
#define IAP_RET_DST_ADDR_NOT_MAPPED  						5
#define IAP_RET_COUNT_ERROR          						6
#define IAP_RET_INVALID_SECTOR       						7
#define IAP_RET_SECTOR_NOT_BLANK     						8
#define IAP_RET_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 	9
#define IAP_RET_COMPARE_ERROR        						10
#define IAP_RET_BUSY                 						11

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

volatile DWORD UART0Status, UART1Status;
volatile BYTE UART0TxEmpty = 1; 
volatile BYTE *UART0Buffer;
volatile DWORD UART0Count = 0;

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

DWORD  command[8];                         // IAP入口参数缓冲区
DWORD  result[8];                        // IAP出口参数缓冲区 

void LedPort(char state)
{
	PINSEL7  &= 0xFF00FFFF;	//config P3.24-P3.27 as GPIO
	FIO3DIR  |= 0x0F000000;	//make P3.24-P3.27 as output
	FIO3MASK &= ~(0xF << 24);
	FIO3PIN   = (FIO3PIN & 0xF0FFFFFF)|(state &0x0F)<<24 ;
	FIO3MASK |= 0xF << 24;
}

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

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

/*
*******************************************************************************************************
** 函数名称:EraseSector()
** 函数功能:扇区擦除,命令代码52。
** 入口参数:sec1       起始扇区
**           sec2       终止扇区
** 出口参数:IAP操作状态码
**           IAP返回值(result缓冲区)
*******************************************************************************************************
*/
DWORD  EraseSector(BYTE sec1, BYTE sec2)
{  
    command[0] = IAP_CMD_ERASE;            // 设置命令字
    command[1] = sec1;                       // 设置参数
    command[2] = sec2;
    command[3] = IAP_FCCLK;
    (*IAP_Entry)(command, result);         // 调用IAP服务程序
   
    return(result[0]);                     // 返回状态码
}

/*
*******************************************************************************************************
** 函数名称:BlankCHK()
** 函数功能:扇区查空,命令代码53。
** 入口参数:sec1       起始扇区
**           sec2       终止扇区
** 出口参数:IAP操作状态码
**           IAP返回值(result缓冲区)
*******************************************************************************************************
*/
DWORD  BlankCHK(BYTE sec1, BYTE sec2)
{  
    command[0] = IAP_CMD_CHECK;               // 设置命令字
    command[1] = sec1;                       // 设置参数
    command[2] = sec2;
    (*IAP_Entry)(command, result);         // 调用IAP服务程序

    return(result[0]);                     // 返回状态码
}

/*
*******************************************************************************************************
** 函数名称:ReadParID()
** 函数功能:扇区查空,命令代码53。
** 入口参数:无
** 出口参数:IAP操作状态码
**           IAP返回值(result缓冲区)
*******************************************************************************************************
*/
DWORD  ReadParID(void)
{  
    command[0] = IAP_CMD_ID;             // 设置命令字
    (*IAP_Entry)(command, result);         // 调用IAP服务程序

    return(result[0]);                     // 返回状态码
}

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

    return(result[0]);                     		 // 返回状态码
}
int main(void)
{
	DWORD err;
	BYTE fileCount0;
	BYTE fileCount1;
	BYTE fileCount2;
	BYTE fileCount3;
	DWORD fileCount;
														//1. 确定更新的情况下,擦除对应代码区域
	IAP_Entry = (void(*)())IAP_LOCATION; 				//初始化函数指针

	SelSector(0x1,0x1);                                 // 选择扇区1
    EraseSector(0x1,0x1);                               // 擦除扇区1 (4k)
    BlankCHK(0x1,0x1) ;                       			// 查空扇区
														 
														//2. 发送0x22准备字节给PC
	U0IER = IER_THRE | IER_RLS;							// 发送时disable RBR
	while(!(UART0TxEmpty & 0x01));
	U0THR = ISP_PC_DOWNLOAD;							// 0x22 means bootloader is ready to update 
	UART0Count = 0;
	U0IER = IER_THRE | IER_RLS | IER_RBR;				//	REenable RBR
														
														//3. 发送0x23表示请求PC发送文件的长度,DWORD
	U0IER = IER_THRE | IER_RLS;							// 发送时disable RBR
	while(!(UART0TxEmpty & 0x01));
	U0THR = ISP_PC_FILE_LEN;							// 0x23 means order PC to confirm the fileLen
	UART0Count = 0;
	U0IER = IER_THRE | IER_RLS | IER_RBR;				//	REenable RBR

														//4. 接收文件长度
	while(UART0Count < 5)
	{
		if(UART0Count == 4)
		{
			fileCount0 = *(volatile BYTE*)(DWORD)(&UART0Buffer);
			fileCount1 = *(volatile BYTE*)((DWORD)(&UART0Buffer)+1);
			fileCount2 = *(volatile BYTE*)((DWORD)(&UART0Buffer)+2);
			fileCount3 = *(volatile BYTE*)((DWORD)(&UART0Buffer)+3);
			
			UART0Count = 5;		
		}			
	}
	UART0Count = 0;
	
	fileCount = (fileCount0 << 24) + (fileCount1 << 16) + (fileCount2 << 8) + (fileCount3);				 //fileCount is the the length of the HEX file

														 		//5.等待PC发送的文件到on-chip RAM
	while(UART0Count < fileCount)						 		//等待数据传输完毕
	{
		if(UART0Count != 0)
		{
			U0IER = IER_THRE | IER_RLS;
			while(!(UART0TxEmpty & 0x01));		   		
			U0IER = IER_THRE | IER_RLS | IER_RBR;
		}
	}
	UART0Count = 0;
														 		//6.从RAM写入FLASH的指定扇区
	SelSector(0x1,0x1);                                  		// 选择扇区1
   	RamToFlash(0x00001000, (DWORD)&UART0Buffer, (UART0Count/512)*512+512); 
			
	err = Compare(0x00001000,(DWORD)&UART0Buffer,(UART0Count/512)*512+512);
														 		//7.想串口发送更新操作结果,0x24表示成功,0x25表示失败
	if(err == IAP_RET_CMD_SUCCESS)
	{
		U0IER = IER_THRE | IER_RLS;								// 发送时disable RBR
		while(!(UART0TxEmpty & 0x01));
		U0THR = ISP_MCU_UPDATE_OK;							 	// 0x24 means bootloader has finished the update process
		UART0Count = 0;
		U0IER = IER_THRE | IER_RLS | IER_RBR;	
	}
	else
	{
		U0IER = IER_THRE | IER_RLS;							 	// 发送时disable RBR
		while(!(UART0TxEmpty & 0x01));
		U0THR = ISP_MCU_UPDATE_OK;							 	// 0x25 means bootloader is failed to update
		UART0Count = 0;
		U0IER = IER_THRE | IER_RLS | IER_RBR;
	}
		
	

}

⌨️ 快捷键说明

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