__text_start: __start: F05B E001 LDI R16,1 F05C BF05 OUT 0x35,R16 F05D E002 LDI R16,2 F05E BF05 OUT 0x35,R16 F05F EFCF LDI R28,0xFF F060 E1D0 LDI R29,0x10 F061 BFCD OUT 0x3D,R28 F062 BFDE OUT 0x3E,R29 F063 51C0 SUBI R28,0x10 F064 40D0 SBCI R29,0 F065 EA0A LDI R16,0xAA F066 8308 STD Y+0,R16 F067 2400 CLR R0 F068 E0E4 LDI R30,4 F069 E0F1 LDI R31,1 F06A E012 LDI R17,2 F06B 30E4 CPI R30,4 F06C 07F1 CPC R31,R17 F06D F011 BEQ 0xF070 F06E 9201 ST R0,Z+ F06F CFFB RJMP 0xF06B F070 8300 STD Z+0,R16 F071 EBE2 LDI R30,0xB2 F072 EEF0 LDI R31,0xE0 F073 E0A0 LDI R26,0 F074 E0B1 LDI R27,1 F075 EE10 LDI R17,0xE0 F076 E001 LDI R16,1 F077 BF0B OUT 0x3B,R16 F078 3BE6 CPI R30,0xB6 F079 07F1 CPC R31,R17 F07A F021 BEQ 0xF07F F07B 95D8 ELPM F07C 9631 ADIW R30,1 F07D 920D ST R0,X+ F07E CFF9 RJMP 0xF078 F07F 940EF13A CALL _main _exit: F081 CFFF RJMP _exit _boot_page_ew: code --> Y+4 p_address --> Y+0 F082 940EF203 CALL push_arg4 FILE: C:\DOCUME~1\Administrator\桌面\avrboot\avrboot.c (0001) /***************************************************** (0002) 采用串行接口实现Boot_load应用的实例 (0003) 华东师大电子系 马 潮 2004.07 (0004) Compiler: ICC-AVR 6.31 (0005) Target: Mega128 (0006) Crystal: 16Mhz (0007) Used: T/C0,USART0 (0008) *****************************************************/ (0009) #include (0010) #define SPM_PAGESIZE 256 //M128的一个Flash页为256字节(128字) (0011) #define BAUD 38400 //波特率采用38400bps (0012) #define CRYSTAL 8000000 //系统时钟16MHz (0013) //计算和定义M128的波特率设置参数 (0014) #define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1) (0015) #define BAUD_H (unsigned char)(BAUD_SETTING>>8) (0016) #define BAUD_L (unsigned char)BAUD_SETTING (0017) #define DATA_BUFFER_SIZE SPM_PAGESIZE //定义接收缓冲区长度 (0018) //定义Xmoden控制字符 (0019) #define XMODEM_NUL 0x00 (0020) #define XMODEM_SOH 0x01 (0021) #define XMODEM_STX 0x02 (0022) #define XMODEM_EOT 0x04 (0023) #define XMODEM_ACK 0x06 (0024) #define XMODEM_NAK 0x15 (0025) #define XMODEM_CAN 0x18 (0026) #define XMODEM_EOF 0x1A (0027) #define XMODEM_RECIEVING_WAIT_CHAR 'C' (0028) //定义全局变量 (0029) const char startupString[]="Type 'd' download, Others run app.\n\r\0"; (0030) char data[DATA_BUFFER_SIZE]; (0031) long address = 0; (0032) //擦除(code=0x03)和写入(code=0x05)一个Flash页 (0033) void boot_page_ew(long p_address,char code) (0034) { (0035) asm("mov r30,r16\n" F084 2FE0 MOV R30,R16 F085 2FF1 MOV R31,R17 F086 BF2B OUT 0x3B,R18 (0036) "mov r31,r17\n" (0037) "out 0x3b,r18\n"); //将页地址放入Z寄存器和RAMPZ的Bit0中 (0038) SPMCSR = code; //寄存器SPMCSR中为操作码 F087 800C LDD R0,Y+4 F088 92000068 STS 0x68,R0 (0039) asm("spm\n"); //对指定Flash页进行操作 F08A 95E8 SPM F08B 9624 ADIW R28,4 F08C 9508 RET (0040) } (0041) //填充Flash缓冲页中的一个字 (0042) void boot_page_fill(unsigned int address,int data) (0043) { (0044) asm("mov r30,r16\n" _boot_page_fill: data --> R18 address --> R16 F08D 2FE0 MOV R30,R16 F08E 2FF1 MOV R31,R17 F08F 2E02 MOV R0,R18 F090 2E13 MOV R1,R19 (0045) "mov r31,r17\n" //Z寄存器中为填冲页内地址 (0046) "mov r0,r18\n" (0047) "mov r1,r19\n"); //R0R1中为一个指令字 (0048) SPMCSR = 0x01; F091 E081 LDI R24,1 F092 93800068 STS 0x68,R24 (0049) asm("spm\n"); F094 95E8 SPM F095 9508 RET (0050) } (0051) //等待一个Flash页的写完成 (0052) void wait_page_rw_ok(void) (0053) { _wait_page_rw_ok: F096 C008 RJMP 0xF09F (0054) while(SPMCSR & 0x40) (0055) { (0056) while(SPMCSR & 0x01); F097 90200068 LDS R2,0x68 F099 FC20 SBRC R2,0 F09A CFFC RJMP 0xF097 (0057) SPMCSR = 0x11; F09B E181 LDI R24,0x11 F09C 93800068 STS 0x68,R24 (0058) asm("spm\n"); F09E 95E8 SPM F09F 90200068 LDS R2,0x68 F0A1 FC26 SBRC R2,6 F0A2 CFF4 RJMP 0xF097 F0A3 9508 RET _write_one_page: i --> R20 F0A4 940EF212 CALL push_gset1 F0A6 9721 SBIW R28,1 (0059) } (0060) } (0061) //更新一个Flash页的完整处理 (0062) void write_one_page(void) (0063) { (0064) int i; (0065) boot_page_ew(address,0x03); //擦除一个Flash页 F0A7 E083 LDI R24,3 F0A8 8388 STD Y+0,R24 F0A9 91200102 LDS R18,address+2 F0AB 91300103 LDS R19,address+3 F0AD 91000100 LDS R16,address F0AF 91100101 LDS R17,address+1 F0B1 DFD0 RCALL _boot_page_ew (0066) wait_page_rw_ok(); //等待擦除完成 F0B2 DFE3 RCALL _wait_page_rw_ok (0067) for(i=0;i R16 F0DF 9B5D SBIS 0x0B,5 F0E0 CFFE RJMP _uart_putchar (0078) UDR0 = c; F0E1 B90C OUT 0x0C,R16 F0E2 9508 RET (0079) } (0080) //从RS232接收一个字节 (0081) int uart_getchar(void) (0082) { (0083) unsigned char status,res; (0084) if(!(UCSR0A & 0x80)) return -1; //no data to be received _uart_getchar: res --> R16 status --> R18 F0E3 995F SBIC 0x0B,7 F0E4 C003 RJMP 0xF0E8 F0E5 EF0F LDI R16,0xFF F0E6 EF1F LDI R17,0xFF F0E7 C009 RJMP 0xF0F1 (0085) status = UCSR0A; F0E8 B12B IN R18,0x0B (0086) res = UDR0; F0E9 B10C IN R16,0x0C (0087) if (status & 0x1c) return -1; // If error, return -1 F0EA 2F82 MOV R24,R18 F0EB 718C ANDI R24,0x1C F0EC F019 BEQ 0xF0F0 F0ED EF0F LDI R16,0xFF F0EE EF1F LDI R17,0xFF F0EF C001 RJMP 0xF0F1 (0088) return res; F0F0 2711 CLR R17 F0F1 9508 RET _uart_waitchar: c --> R20 F0F2 940EF212 CALL push_gset1 (0089) } (0090) //等待从RS232接收一个有效的字节 (0091) char uart_waitchar(void) (0092) { (0093) int c; (0094) while((c=uart_getchar())==-1); F0F4 DFEE RCALL _uart_getchar F0F5 01A8 MOVW R20,R16 F0F6 3F4F CPI R20,0xFF F0F7 EFEF LDI R30,0xFF F0F8 075E CPC R21,R30 F0F9 F3D1 BEQ 0xF0F4 (0095) return (char)c; F0FA 940EF215 CALL pop_gset1 F0FC 9508 RET _calcrc: i --> R22 crc --> R20 count --> R18 ptr --> R16 F0FD 940EF210 CALL push_gset2 (0096) } (0097) //计算CRC (0098) int calcrc(char *ptr, int count) (0099) { (0100) int crc = 0; F0FF 2744 CLR R20 F100 2755 CLR R21 F101 C01B RJMP 0xF11D (0101) char i; (0102) (0103) while (--count >= 0) (0104) { (0105) crc = crc ^ (int) *ptr++ << 8; F102 01F8 MOVW R30,R16 F103 9021 LD R2,Z+ F104 018F MOVW R16,R30 F105 2433 CLR R3 F106 2C32 MOV R3,R2 F107 2422 CLR R2 F108 2542 EOR R20,R2 F109 2553 EOR R21,R3 (0106) i = 8; F10A E068 LDI R22,0x8 (0107) do (0108) { (0109) if (crc & 0x8000) F10B FF57 SBRS R21,7 F10C C009 RJMP 0xF116 (0110) crc = crc << 1 ^ 0x1021; F10D E281 LDI R24,0x21 F10E E190 LDI R25,0x10 F10F 011A MOVW R2,R20 F110 0C22 LSL R2 F111 1C33 ROL R3 F112 2628 EOR R2,R24 F113 2639 EOR R3,R25 F114 01A1 MOVW R20,R2 F115 C002 RJMP 0xF118 (0111) else (0112) crc = crc << 1; F116 0F44 LSL R20 F117 1F55 ROL R21 (0113) } while(--i); F118 2F86 MOV R24,R22 F119 5081 SUBI R24,1 F11A 2F68 MOV R22,R24 F11B 2388 TST R24 F11C F771 BNE 0xF10B F11D 01C9 MOVW R24,R18 F11E 9701 SBIW R24,1 F11F 019C MOVW R18,R24 F120 3020 CPI R18,0 F121 E0E0 LDI R30,0 F122 073E CPC R19,R30 F123 F6F4 BGE 0xF102 (0114) } (0115) return (crc); F124 018A MOVW R16,R20 F125 940EF208 CALL pop_gset2 F127 9508 RET (0116) } (0117) //退出Bootloader程序,从0x0000处执行应用程序 (0118) void quit(void) (0119) { (0120) uart_putchar('O');uart_putchar('K'); _quit: F128 E40F LDI R16,0x4F F129 DFB5 RCALL _uart_putchar F12A E40B LDI R16,0x4B F12B DFB3 RCALL _uart_putchar (0121) uart_putchar(0x0d);uart_putchar(0x0a); F12C E00D LDI R16,0xD F12D DFB1 RCALL _uart_putchar F12E E00A LDI R16,0xA F12F DFAF RCALL _uart_putchar (0122) while(!(UCSR0A & 0x20)); //等待结束提示信息回送完成 F130 9B5D SBIS 0x0B,5 F131 CFFE RJMP 0xF130 (0123) MCUCR = 0x01; F132 E081 LDI R24,1 F133 BF85 OUT 0x35,R24 (0124) MCUCR = 0x00; //将中断向量表迁移到应用程序区头部 F134 2422 CLR R2 F135 BE25 OUT 0x35,R2 (0125) RAMPZ = 0x00; //RAMPZ清零初始化 F136 BE2B OUT 0x3B,R2 (0126) asm("jmp 0x0000\n"); //跳转到Flash的0x0000处,执行用户的应用程序 F137 940C0000 JMP 0x0 F139 9508 RET _main: timercount --> Y+2 crc --> R10 packNO --> R14 i --> Y+0 bufferPoint --> R12 F13A 9723 SBIW R28,3 (0127) } (0128) //主程序 (0129) void main(void) (0130) { (0131) int i = 0; F13B 2400 CLR R0 F13C 2411 CLR R1 F13D 8219 STD Y+1,R1 F13E 8208 STD Y+0,R0 (0132) unsigned char timercount = 0; F13F 820A STD Y+2,R0 (0133) unsigned char packNO = 1; F140 24EE CLR R14 F141 94E3 INC R14 (0134) int bufferPoint = 0; F142 24CC CLR R12 F143 24DD CLR R13 (0135) unsigned int crc; (0136) //初始化M128的USART0 (0137) UBRR0H = BAUD_H; F144 2422 CLR R2 F145 92200090 STS 0x90,R2 (0138) UBRR0L = BAUD_L; //Set baud rate F147 E08C LDI R24,0xC F148 B989 OUT 0x09,R24 (0139) UCSR0B = 0x18; //Enable Receiver and Transmitter F149 E188 LDI R24,0x18 F14A B98A OUT 0x0A,R24 (0140) UCSR0C = 0x0E; //Set frame. format: 8data, 2stop bit F14B E08E LDI R24,0xE F14C 93800095 STS 0x95,R24 (0141) //初始化M128的T/C0,15ms自动重载 (0142) OCR0 = 0xEA; F14E EE8A LDI R24,0xEA F14F BF81 OUT 0x31,R24 (0143) TCCR0 = 0x0F; F150 E08F LDI R24,0xF F151 BF83 OUT 0x33,R24 F152 C00D RJMP 0xF160 (0144) //向PC机发送开始提示信息 (0145) while(startupString[i]!='\0') (0146) { (0147) uart_putchar(startupString[i]); F153 E88C LDI R24,0x8C F154 EE90 LDI R25,0xE0 F155 81E8 LDD R30,Y+0 F156 81F9 LDD R31,Y+1 F157 0FE8 ADD R30,R24 F158 1FF9 ADC R31,R25 F159 9104 LPM R16,0(Z) F15A DF84 RCALL _uart_putchar (0148) i++; F15B 8188 LDD R24,Y+0 F15C 8199 LDD R25,Y+1 F15D 9601 ADIW R24,1 F15E 8399 STD Y+1,R25 F15F 8388 STD Y+0,R24 F160 E88C LDI R24,0x8C F161 EE90 LDI R25,0xE0 F162 81E8 LDD R30,Y+0 F163 81F9 LDD R31,Y+1 F164 0FE8 ADD R30,R24 F165 1FF9 ADC R31,R25 F166 91E4 LPM R30,0(Z) F167 23EE TST R30 F168 F751 BNE 0xF153 F169 C014 RJMP 0xF17E (0149) } (0150) //3秒种等待PC下发"d",否则退出Bootloader程序,从0x0000处执行应用程序 (0151) while(1) (0152) { (0153) if(uart_getchar()== 'd') break; F16A DF78 RCALL _uart_getchar F16B 3604 CPI R16,0x64 F16C E0E0 LDI R30,0 F16D 071E CPC R17,R30 F16E F409 BNE 0xF170 F16F C020 RJMP 0xF190 (0154) if (TIFR & 0x02) //timer0 over flow F170 B626 IN R2,0x36 F171 FE21 SBRS R2,1 F172 C00B RJMP 0xF17E (0155) { (0156) if (++timercount > 200) quit(); //200*15ms = 3s F173 818A LDD R24,Y+2 F174 5F8F SUBI R24,0xFF F175 2E28 MOV R2,R24 F176 822A STD Y+2,R2 F177 EC88 LDI R24,0xC8 F178 1582 CP R24,R2 F179 F408 BCC 0xF17B F17A DFAD RCALL _quit (0157) TIFR = TIFR|0x02; F17B B786 IN R24,0x36 F17C 6082 ORI R24,2 F17D BF86 OUT 0x36,R24 F17E CFEB RJMP 0xF16A (0158) } (0159) } (0160) //每秒向PC机发送一个控制字符"C",等待控制字〈soh〉 (0161) while(uart_getchar()!=XMODEM_SOH) //receive the start of Xmodem (0162) { (0163) if(TIFR & 0x02) //timer0 over flow F17F B626 IN R2,0x36 F180 FE21 SBRS R2,1 F181 C00E RJMP 0xF190 (0164) { (0165) if(++timercount > 67) //wait about 1 second F182 818A LDD R24,Y+2 F183 5F8F SUBI R24,0xFF F184 2E28 MOV R2,R24 F185 822A STD Y+2,R2 F186 E483 LDI R24,0x43 F187 1582 CP R24,R2 F188 F420 BCC 0xF18D (0166) { (0167) uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //send a "C" F189 E403 LDI R16,0x43 F18A DF54 RCALL _uart_putchar (0168) timercount=0; F18B 2400 CLR R0 F18C 820A STD Y+2,R0 (0169) } (0170) TIFR=TIFR | 0x02; F18D B786 IN R24,0x36 F18E 6082 ORI R24,2 F18F BF86 OUT 0x36,R24 F190 DF52 RCALL _uart_getchar F191 3001 CPI R16,1 F192 E0E0 LDI R30,0 F193 071E CPC R17,R30 F194 F751 BNE 0xF17F (0171) } (0172) } (0173) //开始接收数据块 (0174) do (0175) { (0176) if ((packNO == uart_waitchar()) && (packNO ==(~uart_waitchar()))) F195 DF5C RCALL _uart_waitchar F196 16E0 CP R14,R16 F197 F009 BEQ 0xF199 F198 C05A RJMP 0xF1F3 F199 DF58 RCALL _uart_waitchar F19A 2E20 MOV R2,R16 F19B 9420 COM R2 F19C 14E2 CP R14,R2 F19D F009 BEQ 0xF19F F19E C054 RJMP 0xF1F3 (0177) { //核对数据块编号正确 (0178) for(i=0;i<128;i++) //接收128个字节数据 F19F 2400 CLR R0 F1A0 2411 CLR R1 F1A1 8219 STD Y+1,R1 F1A2 8208 STD Y+0,R0 (0179) { (0180) data[bufferPoint]= uart_waitchar(); F1A3 DF4E RCALL _uart_waitchar F1A4 E084 LDI R24,4 F1A5 E091 LDI R25,1 F1A6 01F6 MOVW R30,R12 F1A7 0FE8 ADD R30,R24 F1A8 1FF9 ADC R31,R25 F1A9 8300 STD Z+0,R16 (0181) bufferPoint++; F1AA 01C6 MOVW R24,R12 F1AB 9601 ADIW R24,1 F1AC 016C MOVW R12,R24 F1AD 8188 LDD R24,Y+0 F1AE 8199 LDD R25,Y+1 F1AF 9601 ADIW R24,1 F1B0 8399 STD Y+1,R25 F1B1 8388 STD Y+0,R24 F1B2 3880 CPI R24,0x80 F1B3 E0E0 LDI R30,0 F1B4 079E CPC R25,R30 F1B5 F36C BLT 0xF1A3 (0182) } (0183) crc = (uart_waitchar()<<8); F1B6 DF3B RCALL _uart_waitchar F1B7 2EA0 MOV R10,R16 F1B8 24BB CLR R11 F1B9 2CBA MOV R11,R10 F1BA 24AA CLR R10 (0184) crc += uart_waitchar(); //接收2个字节的CRC效验字 F1BB DF36 RCALL _uart_waitchar F1BC 2E20 MOV R2,R16 F1BD 2433 CLR R3 F1BE 0CA2 ADD R10,R2 F1BF 1CB3 ADC R11,R3 (0185) if(calcrc(&data[bufferPoint-128],128)==crc) //CRC校验验证 F1C0 E820 LDI R18,0x80 F1C1 E030 LDI R19,0 F1C2 E884 LDI R24,0x84 F1C3 E090 LDI R25,0 F1C4 0186 MOVW R16,R12 F1C5 0F08 ADD R16,R24 F1C6 1F19 ADC R17,R25 F1C7 DF35 RCALL _calcrc F1C8 150A CP R16,R10 F1C9 051B CPC R17,R11 F1CA F529 BNE 0xF1F0 (0186) { //正确接收128个字节数据 F1CB C01B RJMP 0xF1E7 (0187) while(bufferPoint >= SPM_PAGESIZE) (0188) { //正确接受256个字节的数据 (0189) write_one_page(); //收到256字节写入一页Flash中 F1CC DED7 RCALL _write_one_page (0190) address += SPM_PAGESIZE; //Flash页加1 F1CD E040 LDI R20,0 F1CE E051 LDI R21,1 F1CF E060 LDI R22,0 F1D0 E070 LDI R23,0 F1D1 90400102 LDS R4,address+2 F1D3 90500103 LDS R5,address+3 F1D5 90200100 LDS R2,address F1D7 90300101 LDS R3,address+1 F1D9 0E24 ADD R2,R20 F1DA 1E35 ADC R3,R21 F1DB 1E46 ADC R4,R22 F1DC 1E57 ADC R5,R23 F1DD 92300101 STS address+1,R3 F1DF 92200100 STS address,R2 F1E1 92500103 STS address+3,R5 F1E3 92400102 STS address+2,R4 (0191) bufferPoint = 0; F1E5 24CC CLR R12 F1E6 24DD CLR R13 F1E7 01C6 MOVW R24,R12 F1E8 3080 CPI R24,0 F1E9 E0E1 LDI R30,1 F1EA 079E CPC R25,R30 F1EB F704 BGE 0xF1CC (0192) } (0193) uart_putchar(XMODEM_ACK); //正确收到一个数据块 F1EC E006 LDI R16,6 F1ED DEF1 RCALL _uart_putchar (0194) packNO++; //数据块编号加1 F1EE 94E3 INC R14 (0195) } F1EF C005 RJMP 0xF1F5 (0196) else (0197) { (0198) uart_putchar(XMODEM_NAK); //要求重发数据块 F1F0 E105 LDI R16,0x15 F1F1 DEED RCALL _uart_putchar (0199) } (0200) } F1F2 C002 RJMP 0xF1F5 (0201) else (0202) { (0203) uart_putchar(XMODEM_NAK); //要求重发数据块 F1F3 E105 LDI R16,0x15 F1F4 DEEA RCALL _uart_putchar (0204) } (0205) }while(uart_waitchar()!=XMODEM_EOT); //循环接收,直到全部发完 F1F5 DEFC RCALL _uart_waitchar F1F6 3004 CPI R16,4 F1F7 F009 BEQ 0xF1F9 F1F8 CF9C RJMP 0xF195 (0206) uart_putchar(XMODEM_ACK); //通知PC机全部收到 F1F9 E006 LDI R16,6 F1FA DEE4 RCALL _uart_putchar (0207) (0208) if(bufferPoint) write_one_page(); //把剩余的数据写入Flash中 F1FB 20CC TST R12 F1FC F411 BNE 0xF1FF F1FD 20DD TST R13 F1FE F009 BEQ 0xF200 F1FF DEA4 RCALL _write_one_page (0209) quit(); //退出Bootloader程序,从0x0000处执行应用程序 FILE: F200 DF27 RCALL _quit F201 9623 ADIW R28,3 F202 9508 RET push_arg4: F203 933A ST R19,-Y F204 932A ST R18,-Y push_arg2: F205 931A ST R17,-Y F206 930A ST R16,-Y F207 9508 RET pop_gset2: F208 E0E2 LDI R30,2 F209 C00C RJMP pop push_gset5: F20A 92FA ST R15,-Y F20B 92EA ST R14,-Y push_gset4: F20C 92DA ST R13,-Y F20D 92CA ST R12,-Y push_gset3: F20E 92BA ST R11,-Y F20F 92AA ST R10,-Y push_gset2: F210 937A ST R23,-Y F211 936A ST R22,-Y push_gset1: F212 935A ST R21,-Y F213 934A ST R20,-Y F214 9508 RET pop_gset1: F215 E0E1 LDI R30,1 pop: F216 9149 LD R20,Y+ F217 9159 LD R21,Y+ F218 FDE0 SBRC R30,0 F219 9508 RET F21A 9169 LD R22,Y+ F21B 9179 LD R23,Y+ F21C FDE1 SBRC R30,1 F21D 9508 RET F21E 90A9 LD R10,Y+ F21F 90B9 LD R11,Y+ F220 FDE2 SBRC R30,2 F221 9508 RET F222 90C9 LD R12,Y+ F223 90D9 LD R13,Y+ F224 FDE3 SBRC R30,3 F225 9508 RET F226 90E9 LD R14,Y+ F227 90F9 LD R15,Y+ F228 9508 RET