📄 bootldr.c
字号:
#include "bootcfg.h"
#include "bootldr.h"
#include "bord_sel.h"
unsigned long int FlashAddr;
unsigned long int pgm_addr_start;
unsigned long int pgm_addr_end;
#define RX_BUFFER_SIZE 150
volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
volatile uint8_t rx_wr_index,rx_rd_index,rx_counter;
volatile uint8_t rx_buffer_overflow;
SIGNAL(SIG_USART0_RECV)
{
uint8_t status,data;
status=UCSR0A;
data=UDR0;
//if ((status & (_BV(FE) | _BV(DOR) | _BV(UPE)))==0)
{
rx_buffer[rx_wr_index]=data;
if (++rx_wr_index == RX_BUFFER_SIZE)
{
rx_wr_index=0;
}
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
}
}
}
#define wait_char() (rx_counter)
unsigned char get_char(void)
{
uint8_t data;
uint8_t sreg;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE)
{
rx_rd_index=0;
}
sreg = SREG;
cli();
--rx_counter;
sei();
SREG = sreg;
return (data);
}
//更新一个Flash页
unsigned char write_one_page_addr(unsigned long int addr,unsigned char *wbuf)
{
unsigned int tmp_cnt;
if(addr<pgm_addr_start||addr>pgm_addr_end){return 2;}//不在地此范围
boot_page_erase(addr); //擦除一个Flash页
boot_spm_busy_wait();
for(tmp_cnt = 0; tmp_cnt < 256; tmp_cnt += 2) //数据填入Flash缓冲页
{
boot_page_fill(tmp_cnt,((wbuf[tmp_cnt + 1] << 8)+wbuf[tmp_cnt]));
}
boot_page_write(addr); //将缓冲页数据写入一个Flash页
boot_spm_busy_wait(); //等待页编程完成
//检验
boot_rww_enable(); //允许读用户程序
for(tmp_cnt = 0; tmp_cnt < 256; tmp_cnt++)
{
if(pgm_read_byte_far(addr+ tmp_cnt) != wbuf[tmp_cnt])
{
return 1;
}
}
return 0;
}
//写入数据到串口
void WriteCom(unsigned char dat)
{
UDR0=dat;
while(!(UCSR0A&(1<<5)));
}
#if VERBOSE
void putstr(const char *str)
{
while(*str)
WriteCom(*str++);
}
unsigned char hex_to_ascii(unsigned char i)
{
i=i&0xf;
if(i<10)return i+'0';
else return i+'A'-10;
}
#endif
void put_data_to_arm(unsigned char *xor_buf,unsigned char size)//与ARM通信数据包
{
unsigned char i;
unsigned char check;
WriteCom(0x7e);
WriteCom(0x81);
WriteCom(size);
WriteCom(size);
check=0;
for(i=0;i<size;i++)
{
WriteCom(xor_buf[i]);
check^=xor_buf[i];
}
WriteCom(check);
}
//当前Flash地址指针
unsigned char boot_first;
unsigned char cmd_long;
#define cmd_buf_size 256
unsigned char cmd_buf[cmd_buf_size];
unsigned char cmd_buf_check;
unsigned int cmd_buf_i;
#define pgm_buf_size 256
unsigned int pgm_ptr;
unsigned char pgm_cnt;
unsigned char pgm_buf[pgm_buf_size];
unsigned char xiazai_mode;
unsigned char read_flag_pgm(void)
{
int i;
boot_rww_enable(); //允许读用户程序
for(i = 0; i < 256; i++)
{
pgm_buf[i]=pgm_read_byte_far(0x1df00+ i);
}
if( pgm_buf[0]==0x55&&
pgm_buf[1]==0xaa&&
pgm_buf[2]==0x11&&
pgm_buf[3]==0x22&&
pgm_buf[4]==0x33&&
pgm_buf[5]==0x44&&
pgm_buf[6]==0x55
)//有应用程序,直接运行程序
{
return 0x0;//延时后运行程序
}
else//没有程序一直运行BOOT
{
return 0x1;
}
}
unsigned char write_flag_pgm(void)
{
FlashAddr = 0x1df00;
pgm_addr_start=FlashAddr;
pgm_addr_end=0x1e000;
return write_one_page_addr(FlashAddr,pgm_buf);
}
//跳转到用户程序
void quit(void)
{
boot_rww_enable(); //允许用户程序区读写
cli();
MCUCR = 0x80|0x01;
MCUCR = 0x80|0x00; //将中断向量表迁移到应用程序区头部
RAMPZ = 0x00; //RAMPZ清零初始化
(*((void(*)(void))0))(); //跳转,这样比'jmp 0'节省空间
}
//UART0 initialize
// desired baud rate: 38400
// actual: baud rate:38400 (0.0%)
// char size: 8 bit
// parity: Even
void uart0_init(void)
{
UCSR0B = 0x00; //disable while setting baud rate
UCSR0A = 0x00;
UCSR0C = 0x26;
UBRR0L = 0x0B; //set baud rate lo
UBRR0H = 0x00; //set baud rate hi
UCSR0B = 0x98;
}
void uart0_init1(void)
{
UCSR0B = 0x00; //disable while setting baud rate
UCSR0A = 0x00;
UCSR0C = 0x06;
UBRR0L = 0x0B; //set baud rate lo
UBRR0H = 0x00; //set baud rate hi
UCSR0B = 0x98;
}
//char boot_xmoden_buf[10];
//char boot_xmoen_cnt;
int main(void)
{
int led_cnt;
int uart_reset_cnt;
int boot_start_cnt;
unsigned char data_tmp;
unsigned char boot_flag;
unsigned int pack_down=0,pack_save=0;
unsigned char cnt;
unsigned char error_tmp;
unsigned char ch,cl,pack_no;
//--------------------------------------------
//禁止看门狗
#ifndef MCUSR
#define MCUSR MCUCSR
#endif
MCUSR = 0;
wdt_disable();
//--------------------------------------------
//关闭中断,异常情况下的保护
cli();
MCUCR = 0x80|0x01;
MCUCR = 0x80|0x02; //将中断向量表迁移到Boot区头部
cpuinit();
//串口初始化
uart0_init();
sei();
boot_flag=read_flag_pgm();
xiazai_mode=0;
led_cnt=0;
uart_reset_cnt=0;
boot_start_cnt=0;
boot_first=0;
while(1)
{
if(++led_cnt>=20000)
{ led_cnt=0;
RUN_lED_CPL;
if(++boot_start_cnt>=100)
{ boot_start_cnt=0;
break;
}
}
if(wait_char())
{ uart_reset_cnt=0;
data_tmp=get_char();
if(data_tmp=='d'||data_tmp=='D')
{
goto xmoden_down_loop;
}
if(data_tmp==0x7e)
{
goto xhj_arm_boot;
}
}
}
while(1)
{
if(++led_cnt>=20000)
{ led_cnt=0;
if(boot_first!=0)
{
if(++uart_reset_cnt>=20)
{ uart_reset_cnt=0;
boot_first=0;
}
}
RUN_lED_CPL;
if(boot_flag==0)//启动运行程序
{
if(++boot_start_cnt>=80)
{ boot_start_cnt=0;
quit();//程序运行不成功则运行BOOT
}
}
}
if(wait_char())
{ uart_reset_cnt=0;
boot_start_cnt=0;
data_tmp=get_char();
if(boot_first==4)
{
cmd_buf[cmd_buf_i++]=data_tmp;
if(cmd_buf_i>cmd_long)
{
boot_first=0;
if(cmd_buf_check==data_tmp)
{
switch(cmd_buf[0])
{
case 0xcb://数据包 128
pack_down=cmd_buf[1];
pack_down<<=8;
pack_down|=cmd_buf[2];
if(pack_down==(pack_save+1))
{
pack_save=pack_down;
for(pgm_cnt=0;pgm_cnt<128;pgm_cnt++)
{
pgm_buf[pgm_ptr++]=cmd_buf[3+pgm_cnt];
}
if(pgm_ptr>128)
{
//unsigned char wr_tmp;
pgm_loop1:;
pgm_ptr=0;
error_tmp=write_one_page_addr(FlashAddr,pgm_buf);
FlashAddr+=256;
//cmd_buf[0]=0xcb;
if(error_tmp==0)
{
cmd_buf[1]=0x80;//写对
}
else
{
cmd_buf[1]=0x8f;//写错
}
cmd_buf[2]=pack_save>>8;
cmd_buf[3]=pack_save;
put_data_to_arm(cmd_buf,4);
if(xiazai_mode==0x55)
{
pgm_buf[0]=0x55;
pgm_buf[1]=0xaa;
pgm_buf[2]=0x11;
pgm_buf[3]=0x22;
pgm_buf[4]=0x33;
pgm_buf[5]=0x44;
pgm_buf[6]=0x55;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -