|
小弟这几天在用mega48做IAP,mega48本是不支持BOOT功能的;
用软件的方法实现BOOT区的划分(0x0B00开始为BOOT区)
APP程序(转为BIN格式)利用UART可以下载成功,但是程序却不能跳进APP程序区,还一直在执行BOOT区程序。
请高手帮帮忙啊!
(ICC AVR中project->option->Target->other option设置为-bmy_text:0x0b00)
程序如下:
#include <iom48v.h>
#include <string.h>
#include <macros.h>
#define SPM_PAGESIZE 64 //M48的一个Flash页为64字节(32字)
#define BAUD 9600 //波特率采用9600bps
#define CRYSTAL 1000000 //系统时钟1MHz
//计算和定义M128的波特率设置参数
#define BAUD_H 0x00
#define BAUD_L 0x06
#define DATA_BUFFER_SIZE 128 //定义接收缓冲区长度
//定义Xmoden控制字符
#define XMODEM_NUL 0x00
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_EOF 0x1A
#define XMODEM_RECIEVING_WAIT_CHAR 'C'
//主程序
#pragma text:my_text
//定义全局变量
char data[DATA_BUFFER_SIZE];
long address=0;
//擦除(code=0x03)和写入(code=0x05)一个Flash页
void boot_page_ew(long p_address,char code)
{
asm("mov r30,r16
"
"mov r31,r17
"); //将页地址放入Z寄存器和RAMPZ的Bit0中
SPMCSR=code; //寄存器SPMCSR中为操作码
asm("spm
"); //对指定Flash页进行操作
}
//填充Flash缓冲页中的一个字
void boot_page_fill(unsigned int address,int data)
{
asm("mov r30,r16
"
"mov r31,r17
" //Z寄存器中为填冲页内地址
"mov r0,r18
"
"mov r1,r19
"); //R0R1中为一个指令字
SPMCSR=0x01;
asm("spm
");
}
void wait_page() //等待Flash写完
{
while(SPMCSR&0X01);
SPMCSR=0X11;
asm("spm
");
while(SPMCSR&0X01);
}
//更新一个Flash页的完整处理
void write_two_page(void)
{
unsigned char i;
boot_page_ew(address,0x03);
wait_page();
boot_page_ew((address+SPM_PAGESIZE),0x03); //擦除两个Flash页
wait_page(); //等待擦除完成
for(i=0;i<SPM_PAGESIZE;i+=2) //将数据填入Flash缓冲页中
{
boot_page_fill(i,data+(data[i+1]<<8));
}
boot_page_ew(address,0x05); //将缓冲页数据写入一个Flash页
wait_page();
for(i=0;i<SPM_PAGESIZE;i+=2) //将数据填入Flash缓冲页中
{
boot_page_fill(i,data[64+i]+(data[i+65]<<8));
}
boot_page_ew((address+SPM_PAGESIZE),0X05); //将缓冲页数据写入一个Flash页
wait_page(); //等待写入完成
}
//从RS232发送一个字节
void uart_putchar(char c)
{
while(!(UCSR0A&0x20));
UDR0=c;
}
//从RS232接收一个字节
int uart_getchar(void)
{
unsigned char status,res;
if(!(UCSR0A&0x80))return -1; //no data to be received
status=UCSR0A;
res=UDR0;
if (status&0x1c)return -1; // If error, return -1
return res;
}
//等待从RS232接收一个有效的字节
char uart_waitchar(void)
{
int c;
while((c=uart_getchar())==-1);
return (char)c;
}
//计算CRC
int calcrc(char *ptr,int count)
{
int crc=0;
char i;
while(--count>=0)
{
crc=crc^(int)*ptr++<<8;
i=8;
do
{
if(crc&0x8000)
crc=crc<<1^0x1021;
else
crc=crc<<1;
}while(--i);
}
return(crc);
}
void quit(void)
{
uart_putchar('O');uart_putchar('K');
uart_putchar(0x0d);uart_putchar(0x0a);
while(!(UCSR0A&0x20)); //等待结束提示信息回送完成
asm("ldi r30,00
"
"ldi r31,00
"
"ijmp
"); //跳转到Flash的0x0000处,执行用户的应用程序
}
//退出Bootloader程序,从0x0000处执行应用程序
void main()
{
unsigned char t=0;
unsigned char b=0;
unsigned char i=0;
unsigned char timercount=0;
unsigned char packNO=1;
int bufferPoint=0;
unsigned int crc;
char startupString[]="Type'd'download,OR run app.
\r\0";
//初始化M128的USART0
UBRR0H=BAUD_H;
UBRR0L=BAUD_L; //Set baud rate
UCSR0B=0x18; //Enable Receiver and Transmitter
UCSR0C=0x0E; //Set frame format: 8data, 2stop bit
DDRB=0xff;
PORTB=0xff;
//向PC机发送开始提示信息
while(startupString!='\0')
{
uart_putchar(startupString);
i++;
}
//3秒种等待PC下发“d”,否则退出Bootloader程序,从0x0064处执行应用程序
while(1)
{
if(uart_getchar()=='d')break;
for(t=0;t<255;t++); //if(TIFR0&0x02) //timer0 over flow
t=0;
if (++timercount>200)
{
timercount=0;
quit();
} //200*15ms = 3s
// TIFR0=TIFR0|0x02;
}
//每秒向PC机发送一个控制字符“C”,等待控制字〈soh〉
while(uart_getchar()!=XMODEM_SOH) //receive the start of Xmodem
{
for(t=0;t<255;t++); // if(TIFR0&0x02) //timer0 over flow
t=0;
if(++timercount>67) //wait about 1 second
{
uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //send a "C"
timercount=0;
}
// TIFR0=TIFR0|0x02;
}
//开始接收数据块
do
{
if((packNO==uart_waitchar())&&(packNO==(~uart_waitchar())))
//核对数据块编号正确
{
for(b=1;b<100;b++);
b=0;
for(i=0;i<128;i++) //接收128个字节数据
{
data[bufferPoint]=uart_waitchar();
bufferPoint++;
}
crc=(uart_waitchar()<<8);
crc+=uart_waitchar(); //接收2个字节的CRC效验字
if(calcrc(&data[bufferPoint-128],128)==crc) //CRC校验验证
{ //正确接收128个字节数据
write_two_page(); //收到128字节写入两页Flash中
address+=2*SPM_PAGESIZE; //Flash页加2
bufferPoint=0;
uart_putchar(XMODEM_ACK); //正确收到一个数据块
packNO++; //数据块编号加1
}
else
{
uart_putchar(XMODEM_NAK); //要求重发数据块
}
}
else
{
uart_putchar(XMODEM_NAK); //要求重发数据块
}
}while(uart_waitchar()!=XMODEM_EOT); //循环接收,直到全部发完
uart_putchar(XMODEM_ACK); //通知PC机全部收到
if(bufferPoint)write_two_page(); //把剩余的数据写入Flash中
quit(); //退出Bootloader程序,从0x0000处执行应用程序
}
#pragma text:text
-----此内容被zywang33于2007-04-09,17:03:04编辑过
-----此内容被zywang33于2007-04-09,17:52:26编辑过 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|