搜索
bottom↓
回复: 1

请教马潮老师bootloader的问题

[复制链接]

出0入0汤圆

发表于 2005-12-26 23:02:17 | 显示全部楼层 |阅读模式
马老师,您好,我按照你的M128的IAP例程改了一下用在M8上,用xmodem传输bin文件的时候出了点问题,一些时候文件好象传输不结束,上位机收不到回复信息来结束文件传输,而且这种情况总是出现在最后,如果手动结束的话,通过回读会发现文件已经正确烧写,有些时候烧写别的bin文件情况又会比较正常,请教马老师,这个问题是怎么回事呢?在写最后一页好象结束不了.源代码如下:

/****************************************************

采用串行接口实现Boot_load应用的实例

华东师大电子系 马 潮 2004.07

Compiler:    ICC-AVR 6.31

Target:    Mega8

Crystal:    7.3728Mhz

Used:        T/C0,USART0

*****************************************************/

#include <iom8v.h>

#define SPM_PAGESIZE 64              //M8的一个Flash页为64字节(32字)

#define BAUD 9600                //波特率采用9600bps

#define CRYSTAL 7372800           //系统时钟16MHz

//计算和定义M128的波特率设置参数

#define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)

#define BAUD_H (unsigned char)(BAUD_SETTING>>8)

#define BAUD_L (unsigned char)BAUD_SETTING



#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'

//定义全局变量

//const char startupString[]="Type 'd' download, Others run app.
\r\0";

char data[DATA_BUFFER_SIZE];

unsigned char PageBuffer[SPM_PAGESIZE];

long address = 0;



//擦除(code=0x03)和写入(code=0x05)一个Flash页

void boot_page_ew(long p_address,char code)

{

    asm("mov r30,r16
"

        "mov r31,r17
"

        "out 0x3b,r18
");            //将页地址放入Z寄存器和RAMPZ的Bit0中

    SPMCR = 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中为一个指令字

    SPMCR = 0x01;

    asm("spm
");

}

//等待一个Flash页的写完成

void wait_page_rw_ok(void)

{

      while(SPMCR & 0x40)

     {

         while(SPMCR & 0x01);

         SPMCR = 0x11;

         asm("spm
");

     }

}

//更新一个Flash页的完整处理

void write_one_page(char *data)

{

    int i=0;

        boot_page_ew(address,0x03);                    //擦除一个Flash页

    wait_page_rw_ok();                             //等待擦除完成

    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_rw_ok();                             //等待写入完成

          

}     



//从RS232发送一个字节

void uart_putchar(char c)

{

    while(!(UCSRA&(1<<UDRE)));

    UDR = c;

}

//从RS232接收一个字节

int uart_getchar(void)

{

    unsigned char status,res;

    if(!(UCSRA& (1<<RXC))) return -1;       //no data to be received

    status = UCSRA;

    res = UDR;

    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;

}



void erase_flash(void)

{

    int i=0;

        printf("
*** Erasing flash from 0x0000 to 0x1C00 (0x70 pages)");

        for(i=0;i<70;i++)

        {

            boot_page_ew(i*SPM_PAGESIZE,0x03);                    //擦除一个Flash页

        wait_page_rw_ok();  

                uart_putchar('#');

        }

}

//字符串输出函数

void printf(char str[])

{

    if (!str) return;

    while (*str)

       uart_putchar(*str++);

}

//计算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);

}

//退出Bootloader程序,从0x0000处执行应用程序

void quit(void)

{

     printf("...OK");

         //uart_putchar('O');uart_putchar('K');

     //uart_putchar(0x0d);uart_putchar(0x0a);

     //while(!(UCSRA & 0x20));           //等待结束提示信息回送完成

     //MCUCR = 0x01;

     //MCUCR = 0x00;                   //将中断向量表迁移到应用程序区头部

     //RAMPZ = 0x00;                    //RAMPZ清零初始化

         GICR = (1<<IVCE);

     GICR = (0<<IVCE)|(0<<IVSEL);        //将中断向量表迁移到应用程序区头部

     asm("jmp 0x0000
");               //跳转到Flash的0x0000处,执行用户的应用程序

}

//主程序

void main(void)

{

    int i = 0;

        int j;

        char tmp;

    unsigned char timercount = 0;

    unsigned char packNO = 1;

    int bufferPoint = 0;

    unsigned int crc;



//初始化M128的USART0

    UCSRB=(1<<RXEN)|(1<<TXEN);//允许发送和接收

    UBRRL=BAUD_L;

    UBRRH=BAUD_H;

    UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//8位数据+1位STOP位

//初始化M128的T/C0,15ms自动重载

  //OCR0 = 0xEA;

    TCCR0 = 0x05;  //1024分频

        TCNT0 = 0x6C;

        TIMSK |=0x01;   

       

//向PC机发送开始提示信息



    //while(startupString!='\0')

    //{

    //    uart_putchar(startupString);

    //    i++;

    //}

        printf("
Type 'd' download, Others run app.
");

        printf("
Type 'e' erase flash
");

        printf("
Type 'g' to app code
");

//3秒种等待PC下发"d",否则退出Bootloader程序,从0x0000处执行应用程序

    while(1)

    {

        if((tmp=uart_getchar())== 'd')

                     break;

                else if(tmp=='e')

                     {

                             printf("erase flash");

                                 erase_flash();

                         }

                else if(tmp=='g')

                     quit();

/*        if (TIFR & 0x02)                        //timer0 over flow

        {

               if (++timercount > 200) quit();       //200*15ms = 3s

            TIFR = TIFR|0x02;

        }

*/    }

    //每秒向PC机发送一个控制字符"C",等待控制字〈soh〉

    while(uart_getchar()!=XMODEM_SOH)        //receive the start of Xmodem

    {

         if(TIFR & 0x01)                    //timer0 over flow

        {

                    TCNT0 = 0x6C;

            if(++timercount > 67)                        //wait about 1 second

            {

                uart_putchar(XMODEM_RECIEVING_WAIT_CHAR);    //send a "C"

                timercount=0;

            }

            TIFR=TIFR | 0x02;

        }

    }



  //开始接收数据块

    do

    {

        if ((packNO == uart_waitchar()) && (packNO ==(~uart_waitchar())))

        {    //核对数据块编号正确

            for(j=0;j<128;j++)                //接收128个字节数据

            {

                data[j]= uart_waitchar();

                bufferPoint++;     

            }

            crc = (uart_waitchar()<<8);

            crc += uart_waitchar();            //接收2个字节的CRC效验字

            if(calcrc(data,128)==crc)    //CRC校验验证

            {   //正确接收128个字节数据

                while(bufferPoint >= SPM_PAGESIZE)

             {   

                    write_one_page(&data[128-bufferPoint]);            

                    address += SPM_PAGESIZE;   

                    bufferPoint -=SPM_PAGESIZE ;

                }     



                                       

                                  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机全部收到

   

        //当SPM_PAGE>128的时候是需要的

    //if(bufferPoint) write_one_page();                //把剩余的数据写入Flash中

    quit();                  //退出Bootloader程序,从0x0000处执行应用程序



}
-----此内容被icecool于2005-12-26,23:14:37编辑过

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2005-12-27 13:16:03 | 显示全部楼层
这里面有个现象,依照xmodem协议传输后,最后用来填充满128字节的数据烧写到flash里面是0X1A,比较奇怪
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 01:45

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表