|
本帖最后由 guew 于 2013-5-23 21:01 编辑
参照马老师的程序,用cvavr给mega32写bootloader,上位机通讯正常,数据传送成功,单步调试确认接受到的数据也正常。但从0x0000开始的flash就是没有数据,那三个加载、页写,等待函数看不出有什么问题,好心人帮帮我。。。- /*****************************************************
- This program was produced by the
- CodeWizardAVR V2.05.0 Professional
- Automatic Program Generator
- ?Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
- http://www.hpinfotech.com
- Chip type : ATmega32
- Program type : Boot Loader - Size:512words
- AVR Core Clock frequency: 12.000000 MHz
- Memory model : Small
- External RAM size : 0
- Data Stack size : 512
- *****************************************************/
- #include <mega32.h>
- #include <dtype.h>
- #define PAGE_SIZE 128
- #define DATA_BUFFER_SIZE PAGE_SIZE
- #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'
- flash uint8 startup_message[] = "type 'd' download, others run app.\0";
- uint8 data[DATA_BUFFER_SIZE];
- uint16 address = 0;
- //擦除(code = 0x03)和写入(code = 0x05)一个flash页
- void write_page(uint16 p_address,uint8 p_code)
- {
- #asm("lds r30,$025a"); //将p_address的低八位放入Y寄存器的低八位
- #asm("lds r31,$025b"); //将p_address的高八位放入Y寄存器的高八位
- SPMCR = p_code; //给SPMCR寄存器赋擦除控制指令
- #asm("spm"); //擦除指令生效
- }
- // 填充一个flash缓冲页中的一个字
- void page_fill(uint16 p_address,uint16 p_data)
- {
- #asm("lds r30,$025a"); //将p_address的低八位放入Y寄存器的低八位
- #asm("lds r31,$025b"); //将p_address的高八位放入Y寄存器的高八位
- #asm("lds r0,$0258"); //将data的低八位放入r0寄存器
- #asm("lds r1,$0259"); //将data的高八位放入r1寄存器
- SPMCR = 0x01; //给SPMCR寄存器赋加载页指令
- #asm("spm"); //加载页指令生效
- }
- //等待一个flash页的写完成
- void wait_page_write_done(void)
- {
- while(SPMCR & 0x40) //如果正在擦除或页写RWWSB置位,执行while
- {
- while(SPMCR & 0x01); //如果正在擦除,等待
- SPMCR = 0x11; //给SPMCR寄存器写入RWW区使能(读)命令 ,并清除RWWSB,while结束,跳出等待
- #asm("spm"); //使能指令生效
- }
- }
- //更新一个flash页的完整处理
- void write_one_page(void)
- {
- uint16 i;
- write_page(address,0x03); //擦除一个flash页
- wait_page_write_done(); //等待擦除完成
- for(i = 0;i < PAGE_SIZE;i += 2) //将数据填入flash缓冲页中
- {
- page_fill(i,data[i]+(data[i+1] << 8));
-
- }
- write_page(address,0x05); //将缓冲数据写入一个flash页
- wait_page_write_done(); //等待写入完成
- }
- //从RS232发送一个字节
- void uart_putchar(uint8 c)
- {
- while(!(UCSRA & 0x20)); //等待上一个发送完成
- UDR = c; //发送一个数据
- }
- //从RS232接受一个字节
- int16 uart_getchar(void)
- {
- uint8 status,res;
- if(!(UCSRA & 0x80)) //如果没有数据,返回-1
- return -1;
- status = UCSRA;
- res = UDR;
- if(status & 0x1c) //如果通信硬件有错误
- return -1;
- return res; //如果没有错误,返回收到的结果
- }
- //等待从RS232接收一个有效字节
- uint8 uart_waitchar(void)
- {
- int16 c;
- while((c = uart_getchar()) == -1);
- return (uint8)c;
- }
- //计算CRC
- int16 cal_crc(uint8 *ptr, int16 counter)
- {
- int16 crc = 0;
- uint8 i;
- while(--counter >= 0)
- {
- crc = crc^(int16)*ptr++ << 8;
- i = 8;
- do
- {
- if(crc & 0x8000)
- crc = crc << 1^0x1021;
- else
- crc = crc << 1;
- }while(--i);
- }
- return crc;
- }
- //退出bootlaoder程序,从0x0000处执行应用程序
- void quit(void)
- {
- uart_putchar('O');
- uart_putchar('K');
- uart_putchar(0x0d);
- uart_putchar(0x0a);
- while(!(UCSRA & 0x20));//等待结束提示信息发送完成
- GICR = 0x01; //打开中断迁移允许开关
- GICR = 0x00; //将中断向量表迁回到应用程序区头部
- #asm("jmp $0000"); //转跳到flash的0x0000处,执行用户的应用程序
- }
- void main(void)
- {
- uint8 i = 0;
- uint8 timercount = 0;
- uint8 pack_no = 1;
- uint16 buffer_pointer = 0;
- uint16 crc;
- //GICR = 0x01; //打开中断迁移允许开关
- //GICR = 0x02; //将中断向量表迁回到应用程序区头部
- UBRRL = 0x4d; //波特率9600
- UCSRB = 0x18; //使能传输与发送
- UCSRC = 0x86; //8个数据位,1个stop位
- OCR0 = 0xea; //(234+1) 30ms计时
- TCCR0 = 0x0d; //CTC模式,1024分频
- //#asm("sei");
-
- //向PC发送开始提示信息
- while(startup_message[i] != '\0')
- {
- uart_putchar(startup_message[i]);
- i++;
- }
-
- //3秒钟等待PC下发'd',否则退出bootloader程序,从0x0000处执行应用程序
- while(1)
- {
- if(uart_getchar() == 'd')
- break;
- if(TIFR & 0x02) //timer0 overflow
- {
- if(++timercount > 250) //100*30ms = 3s到点
- quit();
- TIFR = TIFR | 0x02;
- }
- }
-
- //每秒向PC机发送一个控制字符'C',等待控制字符 <soh>
- while(uart_getchar() != XMODEM_SOH) //没有收到开始字符就等待
- {
- if(TIFR & 0x02)
- {
- if(++timercount > 100)
- {
- uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //发送'C'
- timercount = 0;
- }
- TIFR |= 0x02;
- }
- }
-
- do
- {
- if((pack_no == uart_waitchar()) && (pack_no == (~uart_waitchar())))//校对阴阳两个数据包号
- {
- for(i = 0; i < 128;i++)
- {
- data[buffer_pointer] = uart_waitchar();
- buffer_pointer++;
- }
- crc = (uart_waitchar() << 8);
- crc += uart_waitchar();
- if(cal_crc(&data[buffer_pointer - 128],128) == crc) //CRC校验
- {
- while(buffer_pointer >= PAGE_SIZE)
- {
- write_one_page();
- address += PAGE_SIZE;
- buffer_pointer = 0;
- }
- uart_putchar(XMODEM_ACK);
- pack_no++;
- }
- else
- {
- uart_putchar(XMODEM_NAK); //要求重发数据块
- }
- }
-
- else
- {
- uart_putchar(XMODEM_ACK); //要求重发数据块
- }
- }
- while(uart_waitchar() != XMODEM_EOT);
-
- uart_putchar(XMODEM_ACK); //通知PC全部数据收到
-
- if(buffer_pointer)
- write_one_page(); //写最后一页零散数据???
- quit(); //退出bootloader程序,从0x0000处执行应用程序
- }
复制代码 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|