📄 updater_f02x.c
字号:
/*
可用于用户程序的空间共为122个扇区共62464个字节(0x0000-0xF3FF)
引导程序占用四个扇区(0xF400-0xFBFF) 2048字节
*/
#include <c8051f020.h> // SFR declarations
#include "crc.h"
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define TRUE 1
#define FALSE 0
#define SYSCLK 22118400 // SYSCLK frequency in Hz
#define BAUDRATE 115200 // Baud rate of UART in bps
#define BINCELL_LEN 518 //数据段大小
sbit Run = P3^7; // LED='1' means ON
unsigned char xdata Rec_Buf[600];
unsigned char xdata Send_Buf[512];
unsigned int P_RecBuf=0;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void main (void);
// Initialization Subroutines
void SYSCLK_Init (void);
void PORT_Init (void);
void UART0_Init (void);
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
void (*f)(); // function pointer declaration
bit code_erased = FALSE; // flag used to indicate that the FLASH
// erase operation is complete
bit f_valid = FALSE; // flag to indicate that the FLASH
// programming operation is complete
bit Need_Update=0;
unsigned char Update_Step=0;
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void DealRec();
void SendData(unsigned char *SendBuf,unsigned char SendLen);
void Erase_Flash(unsigned char Erase_Page);
void Write_Flash(unsigned char *Write_Buf,unsigned char Write_Page);
unsigned char Read_Flash(unsigned int Read_Address );
//延时1ms
void DelayMs(unsigned int TimeNum)
{
unsigned int i,j;
for(i=0;i<TimeNum;i++)
{
for(j=0;j<185;j++);
}
}
void JumpToRun()
{
IE=0;
CKCON=0;
PCON=0;
TMOD=0;
SCON0=0;
TH1=0;
TL1=0;
TR1=0;
((void(code *)(void))0xF400)();
}
void main (void)
{
unsigned int Update_OverTime=0;
WDTCN = 0xde; // disable watchdog timer
WDTCN = 0xad;
EA = 0; // disable interrupts (this statement
// is needed because the device is not
// neccesarily in a reset state prior
// to executing this code)
OSCXCN=0;
PORT_Init (); // initialize crossbar and GPIO
SYSCLK_Init (); // initialize oscillator
UART0_Init (); // initialize UART0
Run=0;
DelayMs(100);
Update_Step=1;
Send_Buf[0]=0x55;
Send_Buf[1]=0xAA;
Send_Buf[2]=0xA1;
SendData(Send_Buf,3);
/*while(RI0==0)
{
if(Update_OverTime>60000) //如果升级超时,则进入正常程序
{
JumpToRun();
}
else
{
Update_OverTime++;
}
}
Rec_Buf[P_RecBuf++]=SBUF0;
RI0=0;
Update_OverTime=0;*/
while (1)
{
while(RI0==0)
{
if(Need_Update==0)
{
if(Update_OverTime>60000) //如果升级超时,则进入正常程序
{
JumpToRun();
}
else
{
Update_OverTime++;
}
}
}
Rec_Buf[P_RecBuf++]=SBUF0;
RI0=0;
Update_OverTime=0;
DealRec();
} // end while
} // end main
void SendData(unsigned char *SendBuf,unsigned char SendLen)
{
unsigned char i;
for(i=0;i<SendLen;i++)
{
SBUF0=SendBuf[i];
while(TI0==0);
TI0=0;
}
}
void DealRec()
{
unsigned int i;
unsigned int CRC;
unsigned char CRC_H;
unsigned char CRC_L;
unsigned int Cell_No;
bit Write_Error=0;
if(P_RecBuf>=3) //至少收到三个字节。
{
if(Rec_Buf[0]==0x55&&Rec_Buf[1]==0xAA) //数据帧头有效
{
switch(Rec_Buf[2])
{
case 0xB1: //收到上位机应答升级请求的命令
if(Update_Step==1)
{
Update_Step=2;
Need_Update=1;
}
P_RecBuf=0;
break;
case 0xC1: //收到上位机要求升级的指令
if(Update_Step==2)
{
Update_Step=3;
Send_Buf[0]=0x55;
Send_Buf[1]=0xAA;
Send_Buf[2]=0xD1;
SendData(Send_Buf,3); //返回可以接收数据
}
P_RecBuf=0;
break;
case 0xE1: //收到上位机发送的数据帧
if(P_RecBuf<BINCELL_LEN) return; //帧未收全则返回
if(Update_Step!=3) {P_RecBuf=0;return;}
CRC=cal_crc(Rec_Buf+4,512);
CRC_H=CRC>>8;
CRC_L=CRC;
if(Rec_Buf[516]==CRC_H&&Rec_Buf[517]==CRC_L) //通过CRC校验,则写入数据
{
Cell_No=Rec_Buf[3]; //取出当前是第几个数据块
if(Cell_No==0) //如果当前是第一条数据,进行处理
{
for(i=1;i<123;i++)
{
Erase_Flash(i);
}
//Erase_Flash(122);
Write_Flash(Rec_Buf+4,122);
Rec_Buf[5]=Read_Flash(1);
Rec_Buf[6]=Read_Flash(2);
Erase_Flash(0);
Write_Flash(Rec_Buf+4,0);
}
else if(Cell_No<=121) //收到的数据没有超出可写范围则写入
{
//Erase_Flash(Cell_No);
Write_Flash(Rec_Buf+4,Cell_No);
}
for(i=0;i<512;i++)
{
if(Rec_Buf[4+i]!=Read_Flash(Cell_No*512+i))Write_Error=1;
}
if(!Write_Error)
{
Send_Buf[0]=0x55;
Send_Buf[1]=0xAA;
Send_Buf[2]=0xD2;
SendData(Send_Buf,3); //返回可以接收下一条数据
}
else
{
Send_Buf[0]=0x55;
Send_Buf[1]=0xAA;
Send_Buf[2]=0xD4;
SendData(Send_Buf,3); //返回升级失败
}
}
else
{
Send_Buf[0]=0x55;
Send_Buf[1]=0xAA;
Send_Buf[2]=0xD4;
SendData(Send_Buf,3); //返回升级失败
}
P_RecBuf=0;
break;
case 0xE2: //上位机给出升级成功指令,则开始运行正常程序
if(Update_Step!=3) {P_RecBuf=0;return;}
P_RecBuf=0;
JumpToRun();
break;
default :
P_RecBuf=0;
break;
}
}
else
{
P_RecBuf=0; //帧头无效则清除接收缓存
}
}
}
//-----------------------------------------------------------------------------
// erase_flash
//-----------------------------------------------------------------------------
//
// This routine erases the first 8 pages of FLASH (0x0000 to 0x0FFF).
//
void Erase_Flash(unsigned char Erase_Page)
{
char xdata* data pagePointer = 0;// a pointer to xdata located in data space
// points to the first FLASH page that
// will be erased
bit EA_state; // holds interrupt state
EA_state = EA; // save interrupt state
EA = 0; // disable interrupts
FLSCL |= 0x01; // enable FLASH write/erase
PSCTL = 0x03; // MOVX erases FLASH
// Erase the first 8 FLASH pages
pagePointer=Erase_Page*512;
*pagePointer = 0; // initiate the erase
PSCTL = 0x00; // MOVX writes target XRAM
FLSCL &= ~0x01; // disable FLASH write/erase
EA = EA_state; // restore interrupt state
f_valid = FALSE; // indicate that code is no longer valid
code_erased = TRUE; // indicate that FLASH has been erased
}
void Write_Flash(unsigned char *Write_Buf,unsigned char Write_Page)
{
char xdata* data pwrite;
unsigned int i;
EA = 0; // disable interrupts (precautionary)
FLSCL |= 0x01; // enable FLASH write/erase
PSCTL = 0x01; // MOVX writes FLASH
pwrite = Write_Page*512; // initialize the write pointer
// write the record into flash
for( i = 0; i < 512; i++)
{
*pwrite=Write_Buf[i];
pwrite++;
}
PSCTL = 0x00; // MOVX writes target XRAM
FLSCL &= ~0x01; // disable FLASH write/erase
}
unsigned char Read_Flash(unsigned int Read_Address )
{
char code* data pread;
unsigned char ReadTemp;
pread = (char code*)Read_Address;
ReadTemp=*pread;
return(ReadTemp);
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use an 22.1184MHz crystal
// as its clock source.
//
void SYSCLK_Init (void)
{
int i; // delay counter
OSCXCN = 0x67; // start external oscillator with
// 22.1184MHz crystal
for (i=0; i < 256; i++) ; // wait for osc to start
while (!(OSCXCN & 0x80)) ; // Wait for crystal osc. to settle
OSCICN = 0x88; // select external oscillator as SYSCLK
// source and enable missing clock
// detector
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports
//
void PORT_Init (void)
{
XBR0 = 0x17; // Enable UART0,SPI,I2C,CEX0,CEX1
XBR1 = 0x16; //使能两外部中断,TO输入口
P0MDOUT=0x15;
P1MDOUT=0x01;
P2MDOUT=0xC0;
P3MDOUT = 0xC0;
P74OUT = 0x00; //P4~P7设为开漏输出
EMI0CF = 0x2B; //XRAM的访问方式为带块选择分片方式。输入输出端口使用P4~P7,地址复用方式;
XBR2 = 0x44; // Enable crossbar and weak pull-ups ,UART1
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <baudrate> and 8-N-1.
//
void UART0_Init (void)
{
SCON0 = 0x50; // SCON0: mode 1, 8-bit UART, enable RX
TMOD = 0x20; // TMOD: timer 1, mode 2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16); // set Timer1 reload value for baudrate
TR1 = 1; // start Timer1
CKCON |= 0x10; // Timer1 uses SYSCLK as time base
PCON |= 0x80; // SMOD00 = 1
ES0=0;
TI0= 0;
RI0=0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -