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

📄 binload.c

📁 完整的基于Xmodem协议的嵌入式系统侧FLASH Loader程序。该程序是基于三菱的M16C/60系列MCU
💻 C
📖 第 1 页 / 共 3 页
字号:
/*/ binload.c : BINFile的DownLoad和Flash写入。/*/
//Writemode         FLASH Vendor
//      0                     AMD, FUJITSU and so on
//      1                       SST
//      2                       WINBOND

#include "uapdef.h" 
#include "binload.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#pragma INTERRUPT OnUARTTxEnd
#pragma INTERRUPT OnUARTRxEnd


#pragma ADDRESS S0TIC   51H
#pragma ADDRESS S0RIC   52H
#pragma ADDRESS U0MR    3A0H
#pragma ADDRESS U0BRG   3A1H
#pragma ADDRESS U0TB    3A2H
#pragma ADDRESS U0C0    3A4H
#pragma ADDRESS U0C1    3A5H
#pragma ADDRESS U0RB    3A6H
#pragma ADDRESS UCON    3B0H
#pragma ADDRESS TA4IC   59H
#pragma ADDRESS TABSR   380H
#pragma ADDRESS ONSF    382H
#pragma ADDRESS TRGSR   383H
#pragma ADDRESS UDF     384H
#pragma ADDRESS TA4     38EH
#pragma ADDRESS TA4MR   39AH
#pragma ADDRESS CPSRF   381H
#pragma ADDRESS PM0     04H
#pragma ADDRESS PRCR    0AH
#pragma ADDRESS PD7     3EFH
#pragma ADDRESS P7      3EDH
#pragma ADDRESS PD9     3F3H
#pragma ADDRESS P9      3F1H
#pragma ADDRESS SYSCLK  40F9H
#pragma ADDRESS BANKEN  4128H
#pragma ADDRESS BANKREG 4129H
#pragma ADDRESS PRCR    000AH

struct _PORT {
	BYTE bit0:1;
	BYTE bit1:1;
	BYTE bit2:1;
	BYTE bit3:1;
	BYTE bit4:1;
	BYTE bit5:1;
	BYTE bit6:1;
	BYTE bit7:1;
};

WORD U0TB, U0RB, TA4;
BYTE S0TIC, S0RIC, U0MR, U0BRG, U0C0, U0C1, UCON;
BYTE TA4IC, TABSR, ONSF, TRGSR, UDF, TA4MR, CPSRF, PM0, PRCR;
BYTE PD9, P9, PD7, P7;
BYTE SYSCLK;
BYTE BANKEN, BANKREG;

#define MAXUARTTXBUFFER 255 /*/// 送信BufferSize。/*/
#define MAXUARTRXBUFFER 255 /*/// 受信BufferSize。/*/

#define FLASHTYPE_UNDEFINED 0
#define FLASHTYPE_8MTOPBOOT 1
#define FLASHTYPE_COMBOFALSH 2
#define FLASHTYPE_16MTOPBOOT 4
BYTE FlashType = FLASHTYPE_UNDEFINED;


RINGBUFF UARTTx, UARTRx;

BYTE abTxData[MAXUARTTXBUFFER];	/*/// 送信DataBuffer。/*/
BYTE abRxData[MAXUARTRXBUFFER];	/*/ 受信DataBuffer。/*/

BYTE bXModemSequenceBlockNumber;	/*/ 受信XModem的Sequence.Block号码/*/

BYTE cbXModemRxCharacter;	/*/ XModem的DataBlock受信Byte数/*/

BYTE far * npabXModemFileWrite;	/*/ 受信File的写入Pointer/*/
BYTE abXModemFileWrite[512];	/*/ 受信File的写入Buffer,每次256字节,乒乓工作/*/

BYTE abXModemFreeBlock[4];	/*/ File的写入Buffer中,空的Block/*/

BYTE bXModemWritingBlock;	/*/ 写入中的Buffer的Block号码/*/

BINFILEHEADER BinFileHeader;	/*/ BINFile的Header的保存Buffer/*/
BYTE SectorStartAddressIndex;       /*/边界地址的序号/*/

BYTE szDial[10];	/*/ 设为原状的程序中,工作使用的Buffer/*/
BYTE bStatus;	/*/ 现在的状态。 /*/
BYTE far * lpabFlashMemory;	/*/ 指向将要写入的FlashMemory的Pointer/*/
BYTE far * lpabFlashMemoryEnd;	/*/ 将要写入的FlashMemory的终了Address/*/
//BYTE bWriteMode;	/*/ 写入模式。 /*/

BYTE ManufacturerCode, DeviceCode;  /*/ 生产商代码和器件代码 /*/
DWORD WriteAddress;

/*/波特率为115200的下载程序版本号为3以上。/*/
/*/4.0版增加了对FLASH擦除时超时的处理/*/
//const BYTE szVersionMessage[] = "Welcome to flash downloader V3.0.\r\n";
const BYTE szExit[] = "Exit? (Yes/No/Reset)\r\n";
//const BYTE szDownloadPrompt[] = "Please send the bin file to flash by Xmodem protocol.\r\n";
const BYTE szProgramFailure[] = "Undefined Flash Type. Program failed\r\n";
const BYTE szVersion[] = "EPFLASHV3.0\r\n";

void CS0AddressTransform(DWORD dwPhysicalAddress);
BOOL DetectFlashType(void);
BOOL FlashEraseSector(DWORD sectoraddr);
void FlashReset(void);
void FlashChipErase(void);


/////////////////////////////////////////////////////////////////////////////
// main : binload的MainRoutine。

void main(void)
{
	BYTE c;	/*/ 为了数据的发送的变量。 /*/

	SYSCLK = 0x02;      /*/ 采用9.6M的时钟 /*/
	
    
    P9  &= 0x7f;    /*/ 关绿指示灯 /*/
    P9 |= 0x40;    /*/点亮红指示灯 /*/
    
    PRCR|=0x04;     /*/ PRCR 写入允许 /*/
    
    PD9 |= 0xc0;   /*/ 关红绿指示灯 /*/
    
   	PRCR&=0xfb;//PD9的操作的禁止/

    
   	BANKEN = 0x91;//10010001B;         /*/CS0\CS2扩展/*/

	UARTTx.abData = abTxData;	/*/ 送信Buffer的设定。 /*/
	UARTTx.cbData = 0;	/*/ Data数的清除。 /*/
	UARTTx.bWriteIndex = 0;	/*/ 写入位置设为先头。 /*/
	UARTTx.bReadIndex = 0;	/*/ 读入位置设为先头。 /*/
	UARTTx.bSize = MAXUARTTXBUFFER;	/*/ 送信BufferSize的设定。 /*/

	UARTRx.abData = abRxData;	/*/ 受信Buffer的设定。 /*/
	UARTRx.cbData = 0;	/*/ Data数的清除。 /*/
	UARTRx.bWriteIndex = 0;	/*/ 写入位置设为先头。 /*/
	UARTRx.bReadIndex = 0;	/*/ 读入位置设为先头。 /*/
	UARTRx.bSize = MAXUARTRXBUFFER;	/*/ 受信BufferSize的设定。 /*/

	U0MR = 0x05;	/*/ 流控无效、Parity无、Stop1、内部Clock、8Bit。 /*/
	U0C0 = 0x10;	/*/ TxD0为CMOS、CTS禁止、CountSource设为f1。LSB FIRST!!!!! /*/
	UCON = 0x00;	/*/ CTS和RTS设为共通端子。 /*/

	U0BRG = 4;	/*/ 设为5分频。9.6MHz/16/5 = 120000bps。 /*/

	U0C1 = 0x05;	/*/ 送受信许可。 /*/
	S0TIC = 0x03;	/*/ UART0送信中断控制Register的IPL设为3。 /*/
	S0RIC = 0x03;	/*/ UART0受信中断控制Register的IPL设为3。 /*/

	asm("fclr I");	/*/ 中断禁止。 /*/
	P9 &= 0xfd;		/*/ WP设为Low。	 /*/	 
	PRCR |= 0x04;	 /*/// ProtectRegister的Bit2设为1。 /*/
	PD9 |= 0x02;	/*/ WP设为输出Port。 /*/	// upd 2000.02.08 sawada 0x03(WR_PRT1、WR_PRT2) -> 0x02(WP)
	asm("fset I");	/*/ 中断许可。 /*/
	
        BinFileHeader.Struct.WriteMode = 0;     //default JDDEC command set
        
        
	bStatus = 1;	/*/ 现在的状态设为最初的CR等待状态。 /*/
	TA4IC = 0;	/*/ TimerA4中断要求的清除。 /*/
    
	while (TRUE) {	/*/ 无限Loop。 /*/
		if (UARTRx.cbData || TA4IC & 0x08) {	/*/ 受信Data有的时候、TimerA4为OneShortTimeOut时 /*/
			switch (bStatus) {	
				case 1 :	/*/ CR等待状态 /*/
					ReadUART(&c, 1);	/*/ 1Byte受信。 /*/
					if (c == CR) {	// CR detect
						FlashUART();	/*/ 送受信Buffer的Flash。 /*/
                                        DetectFlashType();      /*/判断FLASH类型,并将结果输出到超级终端/*/
						c = NAK;	/*/ NAK的装入。 /*/
						WriteUART(&c, 1);	/*/ NAK的送信。 /*/
						TA4MR = 0x82;	/*/ TimerA4以4.8/32MHz=150KHz设为OneShortTimer。 /*/
						TA4IC = 0;	/*/ TimerA4中断要求的清除。 /*/
						TA4 = 0xFFFF;	/*/ 0.43秒的TimeOut。 /*/
						CPSRF = 0x80;	/*/ 时钟用的Prescale的Reset。 /*/
						TABSR |= 0x10;	/*/ TimerA4Count开始Flag的Set /*/
						ONSF |= 0x10;	/*/ OneShort开始。 /*/
						c = 0;	/*/ 在NAKTimer的Count中使用。 /*/
						bStatus = 2;	/*/ XModem的开始等待状态。	 /*/
					}
					break;
				case 2 :	/*/ XModem的开始等待状态 /*/
					if (UARTRx.cbData) {	/*/ 受信Data有的时候 /*/
						bXModemSequenceBlockNumber = 0xFF;	/*/ 受信XModem的Sequence.Block号码进行初始化。 /*/
						cbXModemRxCharacter = 0;	/*/ XModem的DataBlock受信Byte数进行初始化。 /*/
						npabXModemFileWrite = abXModemFileWrite;	/*/ 写入受信File的Pointer设置到Buffer的先头。 /*/
						abXModemFreeBlock[0] = abXModemFreeBlock[1] = abXModemFreeBlock[2] = abXModemFreeBlock[3] = 0;	/*/ 写入File的Buffer的Block设为全Block空。 /*/
						bXModemWritingBlock = 0;	/*/ 写入中的Block号码设为先头。 /*/
						TABSR &= (~0x10);	/*/ TimerA4Count开始Flag进行Reset。 /*/
						TA4IC = 0;	/*/ TimerA4中断要求的清除。 /*/
						bStatus = 3;	/*/ BINHeader等待状态。 /*/
						break;	/*/ 跳出Loop,用XModem开始进行受信。 /*/
					} else if (TA4IC & 0x08) {	/*/ OneShortTimeOut时 /*/
						c ++;	/*/ TimeOut回数的增加。 /*/
						if (c == 5) {	/*/ 5回TimeOut时 /*/
							c = NAK;	/*/ NAK的装入。 /*/
							WriteUART(&c, 1);	/*/ NAK的送信。 /*/
							c = 0;	/*/ Counter的清除。 /*/
   						}
						TA4IC = 0;	/*/ TimerA4中断要求的清除。 /*/
						ONSF |= 0x10;	/*/ OneShort开始。 /*/
					}
					break;
				case 3 :	/*/ BINHeader等待状态 /*/
					c = OnRxXModem();	/*/ File的受信。 /*/
					switch (c) {	
						case 1 :	 /*/// 2Block受信时 /*/
							memcpy(BinFileHeader.abBINHeader, abXModemFileWrite, 256);	 /*/// BINFileHeader的拷贝。 /*/
							abXModemFreeBlock[0] = abXModemFreeBlock[1] = 0;	/*/ Block设为空。 /*/
							if (StartProgram(BinFileHeader.abBINHeader)) {	 /*/// Flash写入能够开始时 /*/
								c = ACK;	 /*/// ACK的装入。 /*/
								WriteUART(&c, 1);	 /*/// ACK的送信。 /*/
								bStatus = 4;	 /*/// Flash写入状态。 /*/
							} else {	/*/ Flash写入不能开始时 /*/
								c = CAN;	 /*/// CAN的装入。 /*/
								WriteUART(&c, 1);	/*/ CAN的送信。 /*/
								WriteUART(szProgramFailure, 16);	 /*/// 写入失败Message的输出。 /*/
								WriteUART(szExit, 22);	 /*/// 终了提示符的输出。 /*/
								bStatus = 5;	 /*/// 终了确认等待状态。 /*/
							}
							break;
						case 0 :
						case 2 :
						case 3 :	 /*/// 受信Block号码时 /*/
							c = ACK;	 /*/// ACK的装入。 /*/
							WriteUART(&c, 1);	 /*/// ACK的送信。 /*/
							break;
						case 4 :	 /*/// XModem终了时 /*/
							WriteUART("Unexpected EOF\r\n", 16);	 /*/// 异常File终了Message的输出。 /*/
							WriteUART(szProgramFailure, 16);	 /*/// 中断的Message的输出。 /*/
							WriteUART(szExit, 22);	 /*/// 终了提示符的输出。 /*/
							bStatus = 5;	 /*/// 终了确认等待状态。 /*/
							break;
					}
					break;
				case 4 :	 /*/// Flash写入状态 /*/
					c = OnRxXModem();	 /*/// File的受信。 /*/
					switch (c) {	 /*/// 返回值。 /*/
						case 1 :
							if (WritePage(abXModemFileWrite)) {	 /*/// 0、1Block写入到Flash中 /*/
								abXModemFreeBlock[0] = abXModemFreeBlock[1] = 0;	 /*/// Block设为空。 /*/
								c = ACK;	 /*/// ACK的装入。 /*/
								WriteUART(&c, 1);	 /*/// ACK的送信。 /*/
							} else {	 /*/// 写入失败时 /*/
								c = CAN;	 /*/// CAN的装入。 /*/
								WriteUART(&c, 1);	 /*/// CAN的送信。 /*/
								WriteUART(szProgramFailure, 16);	 /*/// 写入失败Message的输出。 /*/
								WriteUART(szExit, 22);	 /*/// 终了提示符的输出。 /*/
								bStatus = 5;	 /*/// 终了确认等待状态。 /*/
							}
							break;
						case 3 :	 /*/// 2Block受信时 /*/
							if (WritePage(abXModemFileWrite + 256)) {	 /*/// 2、3Block写入到Flash中 /*/
								abXModemFreeBlock[2] = abXModemFreeBlock[3] = 0;	 /*/// Block设为空。 /*/
								c = ACK;	 /*/// ACK的装入。 /*/
								WriteUART(&c, 1);	 /*/// ACK的送信。 /*/
							} else {	 /*/// 写入失败时 /*/
								c = CAN;	 /*/// CAN的装入。 /*/
								WriteUART(&c, 1);	 /*/// CAN的送信。 /*/
								WriteUART(szProgramFailure, 16);	 /*/// 写入失败Message的输出。 /*/
								WriteUART(szExit, 22);	 /*/// 终了提示符的输出。 /*/
								bStatus = 5;	 /*/// 终了确认等待状态。 /*/
							}
							break;
						case 0 :
						case 2 :	 /*/// 受信Block号码时 /*/
							c = ACK;	 /*/// ACK的装入。 /*/
							WriteUART(&c, 1);	 /*/// ACK的送信。 /*/
							break;
						case 4 :	 /*/// XModem终了时 /*/
							switch (bXModemWritingBlock) {	 /*/// 下一个写入Block号码。 /*/
								case 1 :	/*/// 下一个应该向Block1中写入时 /*/
									bzero(abXModemFileWrite + 128, 128);	 /*/// Block1的清除。 /*/
									c = WritePage(abXModemFileWrite);	 /*/// 0、1Block写入到Flash。 /*/
									break;
								case 3 :	 /*/// 下一个应该写入Block3时 /*/
									bzero(abXModemFileWrite + 384, 128);	 /*/// Block3的清除。 /*/
									c = WritePage(abXModemFileWrite + 256);	 /*/// 2、3Block写入到Flash。 /*/
									break;
							}
							if (c) {	 /*/// 写入成功时 /*/
								StopProgram();	 /*/// Flash写入的终了。 /*/
								WriteUART("Program Complete\r\n", 18);	 /*/// Program终了Message的输出。 /*/
								WriteUART("\r\n", 2);	 /*/// 1行改行。 /*/
							//	WriteUART(BinFileHeader.abBINHeader, 200);	 /*/// Header的输出。 /*/
							//	while (UARTTx.bSize - UARTTx.cbData < 100) {	 /*/// 空的UART送信Buffer到为止一直等待。 /*/
							//	}
							//	WriteUART(BinFileHeader.abBINHeader + 200, 56);	 /*/// Header的剩余的输出。 /*/
								WriteUART(szExit, 22);	 /*/// 终了提示符的输出。 /*/
								bStatus = 5;	 /*/// 终了确认等待状态。 /*/
							} else {	 /*/// 写入失败时 /*/
								c = CAN;	 /*/// CAN的装入。 /*/
								WriteUART(&c, 1);	 /*/// CAN的送信。 /*/
								WriteUART(szProgramFailure, 16);	 /*/// 写入失败Message的输出。 /*/
								WriteUART(szExit, 22);	 /*/// 终了提示符的输出。 /*/
								bStatus = 5;	 /*/// 终了确认等待状态。 /*/
							}
							break;
					}
					break;
				case 5 :	 /*/ 终了确认等待状态 /*/
					ReadUART(&c, 1);	 /*/// 1Byte受信。 /*/
					if (c == 'Y' || c == 'y') {	 /*/// Yes时 /*/
						return;	 /*/// 终了。 /*/
					} else if (c == 'N' || c == 'n') {	 /*/// No时 /*/
						FlashUART();	 /*/// 送受信Buffer的Flash。 /*/
//						WriteUART(szVersionMessage, 35);	 /*/// 起动Message的输出。 /*/
//						WriteUART(szDownloadPrompt, 43);	 /*/// BINFile的DownLoadMessage的输出。 /*/
						c = NAK;	 /*/// NAK的装入。 /*/
						WriteUART(&c, 1);	 /*/// NAK的送信。 /*/
						TA4MR = 0x82;	/*/ TimerA4以4.8/32MHz=150KHz设为OneShortTimer。 /*/
						TA4IC = 0;	/*/ TimerA4中断要求的清除。 /*/
						TA4 = 0xFFFF;	/*/ 0.43秒的TimeOut。 /*/
						CPSRF = 0x80;	/*/ 时钟用Prescale进行Reset。 /*/
						TABSR |= 0x10;	/*/ TimerA4Count开始Flag的SET。 /*/

⌨️ 快捷键说明

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