📄 atmega128iap.lst
字号:
__start:
__text_start:
FC5B E001 LDI R16,1
FC5C BF05 OUT 0x35,R16
FC5D E002 LDI R16,2
FC5E BF05 OUT 0x35,R16
FC5F EFCF LDI R28,0xFF
FC60 E1D0 LDI R29,0x10
FC61 BFCD OUT 0x3D,R28
FC62 BFDE OUT 0x3E,R29
FC63 51C0 SUBI R28,0x10
FC64 40D0 SBCI R29,0
FC65 EA0A LDI R16,0xAA
FC66 8308 STD Y+0,R16
FC67 2400 CLR R0
FC68 E0E4 LDI R30,4
FC69 E0F1 LDI R31,1
FC6A E012 LDI R17,2
FC6B 30E4 CPI R30,4
FC6C 07F1 CPC R31,R17
FC6D F011 BEQ 0xFC70
FC6E 9201 ST R0,Z+
FC6F CFFB RJMP 0xFC6B
FC70 8300 STD Z+0,R16
FC71 EBE2 LDI R30,0xB2
FC72 EFF8 LDI R31,0xF8
FC73 E0A0 LDI R26,0
FC74 E0B1 LDI R27,1
FC75 EF18 LDI R17,0xF8
FC76 E001 LDI R16,1
FC77 BF0B OUT 0x3B,R16
FC78 3BE6 CPI R30,0xB6
FC79 07F1 CPC R31,R17
FC7A F021 BEQ 0xFC7F
FC7B 95D8 ELPM
FC7C 9631 ADIW R30,1
FC7D 920D ST R0,X+
FC7E CFF9 RJMP 0xFC78
FC7F D0B9 RCALL _main
_exit:
FC80 CFFF RJMP _exit
_boot_page_ew:
code --> Y+4
p_address --> Y+0
FC81 940EFE02 CALL push_arg4
FILE: E:\宇能工作盘\YN3010\IAP\ATEMGA128IAP.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 <iom128v.h>
(0010) #define SPM_PAGESIZE 256
(0011) //M128/的一个Flash页为256字节(128字)
(0012) #define BAUD 38400
(0013) //波特率采用38400bps
(0014) #define CRYSTAL 16000000
(0015) //系统时钟16MHz
(0016) //计算和定义M128的波特率设置参数
(0017) #define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)
(0018) #define BAUD_H (unsigned char)(BAUD_SETTING>>8)
(0019) #define BAUD_L (unsigned char)BAUD_SETTING
(0020)
(0021) #define DATA_BUFFER_SIZE SPM_PAGESIZE
(0022) //定义接收缓冲区长度
(0023) //定义Xmoden控制字符
(0024) #define XMODEM_NUL 0x00
(0025) #define XMODEM_SOH 0x01
(0026) #define XMODEM_STX 0x02
(0027) #define XMODEM_EOT 0x04
(0028) #define XMODEM_ACK 0x06
(0029) #define XMODEM_NAK 0x15
(0030) #define XMODEM_CAN 0x18
(0031) #define XMODEM_EOF 0x1A
(0032) #define XMODEM_RECIEVING_WAIT_CHAR 'C'
(0033) //定义全局变量
(0034) const char startupString[]="Type 'd' download, Others run app.\n\r\0";
(0035) char data[DATA_BUFFER_SIZE];
(0036) long address = 0;
(0037) //擦除(code=0x03)和写入(code=0x05)一个Flash页
(0038) void boot_page_ew(long p_address,char code)
(0039) {
(0040) asm("mov r30,r16\n"
FC83 2FE0 MOV R30,R16
FC84 2FF1 MOV R31,R17
FC85 BF2B OUT 0x3B,R18
(0041) "mov r31,r17\n"
(0042) "out 0x3b,r18\n"); //将页地址放入Z寄存器和RAMPZ的Bit0中
(0043) SPMCSR = code; //寄存器SPMCSR中为操作码
FC86 800C LDD R0,Y+4
FC87 92000068 STS 0x68,R0
(0044) asm("spm\n"); //对指定Flash页进行操作
FC89 95E8 SPM
(0045) }
FC8A 9624 ADIW R28,4
FC8B 9508 RET
(0046) //填充Flash缓冲页中的一个字
(0047) void boot_page_fill(unsigned int address,int data)
(0048) {
(0049) asm("mov r30,r16\n"
_boot_page_fill:
data --> R18
address --> R16
FC8C 2FE0 MOV R30,R16
FC8D 2FF1 MOV R31,R17
FC8E 2E02 MOV R0,R18
FC8F 2E13 MOV R1,R19
(0050) "mov r31,r17\n" //Z/寄存器中为填冲页内地址
(0051) "mov r0,r18\n"
(0052) "mov r1,r19\n"); //R0R1/中为一个指令字
(0053) SPMCSR = 0x01;
FC90 E081 LDI R24,1
FC91 93800068 STS 0x68,R24
(0054) asm("spm\n");
FC93 95E8 SPM
(0055) }
FC94 9508 RET
(0056) //等待一个Flash页的写完成
(0057) void wait_page_rw_ok(void)
(0058) {
_wait_page_rw_ok:
FC95 C008 RJMP 0xFC9E
(0059) while(SPMCSR & 0x40)
(0060) {
(0061) while(SPMCSR & 0x01);
FC96 90200068 LDS R2,0x68
FC98 FC20 SBRC R2,0
FC99 CFFC RJMP 0xFC96
(0062) SPMCSR = 0x11;
FC9A E181 LDI R24,0x11
FC9B 93800068 STS 0x68,R24
(0063) asm("spm\n");
FC9D 95E8 SPM
FC9E 90200068 LDS R2,0x68
FCA0 FC26 SBRC R2,6
FCA1 CFF4 RJMP 0xFC96
(0064) }
(0065) }
FCA2 9508 RET
_write_one_page:
i --> R20
FCA3 940EFE09 CALL push_gset1
FCA5 9721 SBIW R28,1
(0066) //更新一个Flash页的完整处理
(0067) void write_one_page(void)
(0068) {
(0069) int i;
(0070) boot_page_ew(address,0x03); //擦除一个Flash页
FCA6 E083 LDI R24,3
FCA7 8388 STD Y+0,R24
FCA8 91200102 LDS R18,0x102
FCAA 91300103 LDS R19,0x103
FCAC 91000100 LDS R16,0x100
FCAE 91100101 LDS R17,0x101
FCB0 DFD0 RCALL _boot_page_ew
(0071) wait_page_rw_ok(); //等待擦除完成
FCB1 DFE3 RCALL _wait_page_rw_ok
(0072) for(i=0;i<SPM_PAGESIZE;i+=2) //将数据填入Flash缓冲页中
FCB2 2744 CLR R20
FCB3 2755 CLR R21
(0073) {
(0074) boot_page_fill(i, data[i]+(data[i+1]<<8));
FCB4 E085 LDI R24,5
FCB5 E091 LDI R25,1
FCB6 01FA MOVW R30,R20
FCB7 0FE8 ADD R30,R24
FCB8 1FF9 ADC R31,R25
FCB9 8020 LDD R2,Z+0
FCBA 2433 CLR R3
FCBB 2C32 MOV R3,R2
FCBC 2422 CLR R2
FCBD E084 LDI R24,4
FCBE E091 LDI R25,1
FCBF 01FA MOVW R30,R20
FCC0 0FE8 ADD R30,R24
FCC1 1FF9 ADC R31,R25
FCC2 8120 LDD R18,Z+0
FCC3 2733 CLR R19
FCC4 0D22 ADD R18,R2
FCC5 1D33 ADC R19,R3
FCC6 018A MOVW R16,R20
FCC7 DFC4 RCALL _boot_page_fill
FCC8 5F4E SUBI R20,0xFE
FCC9 4F5F SBCI R21,0xFF
FCCA 3040 CPI R20,0
FCCB E0E1 LDI R30,1
FCCC 075E CPC R21,R30
FCCD F334 BLT 0xFCB4
(0075) }
(0076) boot_page_ew(address,0x05); //将缓冲页数据写入一个Flash页
FCCE E085 LDI R24,5
FCCF 8388 STD Y+0,R24
FCD0 91200102 LDS R18,0x102
FCD2 91300103 LDS R19,0x103
FCD4 91000100 LDS R16,0x100
FCD6 91100101 LDS R17,0x101
FCD8 DFA8 RCALL _boot_page_ew
(0077) wait_page_rw_ok(); //等待写入完成
FCD9 DFBB RCALL _wait_page_rw_ok
(0078) }
FCDA 9621 ADIW R28,1
FCDB 940EFE0C CALL pop_gset1
FCDD 9508 RET
(0079) //从RS232发送一个字节
(0080) void uart_putchar(char c)
(0081) {
(0082) while(!(UCSR0A & 0x20));
_uart_putchar:
c --> R16
FCDE 9B5D SBIS 0x0B,5
FCDF CFFE RJMP _uart_putchar
(0083) UDR0 = c;
FCE0 B90C OUT 0x0C,R16
(0084) }
FCE1 9508 RET
(0085) //从RS232接收一个字节
(0086) int uart_getchar(void)
(0087) {
(0088) unsigned char status,res;
(0089) if(!(UCSR0A & 0x80)) return -1; //no/ data to be received
_uart_getchar:
res --> R16
status --> R18
FCE2 995F SBIC 0x0B,7
FCE3 C003 RJMP 0xFCE7
FCE4 EF0F LDI R16,0xFF
FCE5 EF1F LDI R17,0xFF
FCE6 C009 RJMP 0xFCF0
(0090) status = UCSR0A;
FCE7 B12B IN R18,0x0B
(0091) res = UDR0;
FCE8 B10C IN R16,0x0C
(0092) if (status & 0x1c) return -1; // If error, return -1
FCE9 2F82 MOV R24,R18
FCEA 718C ANDI R24,0x1C
FCEB F019 BEQ 0xFCEF
FCEC EF0F LDI R16,0xFF
FCED EF1F LDI R17,0xFF
FCEE C001 RJMP 0xFCF0
(0093) return res;
FCEF 2711 CLR R17
FCF0 9508 RET
_uart_waitchar:
c --> R20
FCF1 940EFE09 CALL push_gset1
(0094) }
(0095) //等待从RS232接收一个有效的字节
(0096) char uart_waitchar(void)
(0097) {
(0098) int c;
(0099) while((c=uart_getchar())==-1);
FCF3 DFEE RCALL _uart_getchar
FCF4 01A8 MOVW R20,R16
FCF5 3F4F CPI R20,0xFF
FCF6 EFEF LDI R30,0xFF
FCF7 075E CPC R21,R30
FCF8 F3D1 BEQ 0xFCF3
(0100) return (char)c;
FCF9 940EFE0C CALL pop_gset1
FCFB 9508 RET
_calcrc:
i --> R22
crc --> R20
count --> R18
ptr --> R16
FCFC 940EFE20 CALL push_gset2
(0101) }
(0102) //计算CRC
(0103) int calcrc(char *ptr, int count)
(0104) {
(0105) int crc = 0;
FCFE 2744 CLR R20
FCFF 2755 CLR R21
FD00 C01B RJMP 0xFD1C
(0106) char i;
(0107)
(0108) while (--count >= 0)
(0109) {
(0110) crc = crc ^ (int) *ptr++ << 8;
FD01 01F8 MOVW R30,R16
FD02 9021 LD R2,Z+
FD03 018F MOVW R16,R30
FD04 2433 CLR R3
FD05 2C32 MOV R3,R2
FD06 2422 CLR R2
FD07 2542 EOR R20,R2
FD08 2553 EOR R21,R3
(0111) i = 8;
FD09 E068 LDI R22,0x8
(0112) do
(0113) {
(0114) if (crc & 0x8000)
FD0A FF57 SBRS R21,7
FD0B C009 RJMP 0xFD15
(0115) crc = crc << 1 ^ 0x1021;
FD0C E281 LDI R24,0x21
FD0D E190 LDI R25,0x10
FD0E 011A MOVW R2,R20
FD0F 0C22 LSL R2
FD10 1C33 ROL R3
FD11 2628 EOR R2,R24
FD12 2639 EOR R3,R25
FD13 01A1 MOVW R20,R2
FD14 C002 RJMP 0xFD17
(0116) else
(0117) crc = crc << 1;
FD15 0F44 LSL R20
FD16 1F55 ROL R21
(0118) } while(--i);
FD17 2F86 MOV R24,R22
FD18 5081 SUBI R24,1
FD19 2F68 MOV R22,R24
FD1A 2388 TST R24
FD1B F771 BNE 0xFD0A
FD1C 01C9 MOVW R24,R18
FD1D 9701 SBIW R24,1
FD1E 019C MOVW R18,R24
FD1F 3020 CPI R18,0
FD20 E0E0 LDI R30,0
FD21 073E CPC R19,R30
FD22 F6F4 BGE 0xFD01
(0119) }
(0120) return (crc);
FD23 018A MOVW R16,R20
FD24 940EFE07 CALL pop_gset2
FD26 9508 RET
(0121) }
(0122) //退出Bootloader程序,从0x0000处执行应用程序
(0123) void quit(void)
(0124) {
(0125) uart_putchar('O');uart_putchar('K');
_quit:
FD27 E40F LDI R16,0x4F
FD28 DFB5 RCALL _uart_putchar
FD29 E40B LDI R16,0x4B
FD2A DFB3 RCALL _uart_putchar
(0126) uart_putchar(0x0d);uart_putchar(0x0a);
FD2B E00D LDI R16,0xD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -