📄 19boot.lst
字号:
__text_start:
__start:
F84B E001 LDI R16,1
F84C BF05 OUT 0x35,R16
F84D E002 LDI R16,2
F84E BF05 OUT 0x35,R16
F84F EFCF LDI R28,0xFF
F850 E1D0 LDI R29,0x10
F851 BFCD OUT 0x3D,R28
F852 BFDE OUT 0x3E,R29
F853 51C0 SUBI R28,0x10
F854 40D0 SBCI R29,0
F855 EA0A LDI R16,0xAA
F856 8308 STD Y+0,R16
F857 2400 CLR R0
F858 E0EA LDI R30,0xA
F859 E0F1 LDI R31,1
F85A E012 LDI R17,2
F85B 34E5 CPI R30,0x45
F85C 07F1 CPC R31,R17
F85D F011 BEQ 0xF860
F85E 9201 ST R0,Z+
F85F CFFB RJMP 0xF85B
F860 8300 STD Z+0,R16
F861 E8EC LDI R30,0x8C
F862 EFF0 LDI R31,0xF0
F863 E0A0 LDI R26,0
F864 E0B1 LDI R27,1
F865 EF10 LDI R17,0xF0
F866 E001 LDI R16,1
F867 BF0B OUT 0x3B,R16
F868 39E6 CPI R30,0x96
F869 07F1 CPC R31,R17
F86A F021 BEQ 0xF86F
F86B 95D8 ELPM
F86C 9631 ADIW R30,1
F86D 920D ST R0,X+
F86E CFF9 RJMP 0xF868
F86F 940EF911 CALL _main
_exit:
F871 CFFF RJMP _exit
_boot_page_ew:
code --> Y+4
pageAddr --> Y+0
F872 940EFC6F CALL push_arg4
FILE: E:\ICCAVR\project\AVRMEG~3\icc\019-BOOT\self_prog.c
(0001) #include "init.h"
(0002)
(0003) /**********************************************************************
(0004) 擦除(code=0x03)和写入(code=0x05)一个Flash页
(0005) 特别说明,MEGA128为128K容量,分为两个64K空间。
(0006) 两个空间之间的选择通过RAMPZ的Bit0位来实现。
(0007) **********************************************************************/
(0008) void boot_page_ew(unsigned long pageAddr,unsigned char code) {
(0009)
(0010) asm("mov r30,r16\n"
F874 2FE0 MOV R30,R16
F875 2FF1 MOV R31,R17
F876 BF2B OUT 0x3B,R18
(0011) "mov r31,r17\n"
(0012) "out 0x3b,r18\n"); /*将页地址放入Z寄存器和RAMPZ的Bit0中*/
(0013)
(0014) SPMCSR = code; /*寄存器SPMCSR中为操作码*/
F877 800C LDD R0,Y+4
F878 92000068 STS 0x68,R0
(0015) asm("spm\n"); /*对指定Flash页进行操作 */
F87A 95E8 SPM
F87B 9624 ADIW R28,4
F87C 9508 RET
(0016) }
(0017)
(0018) /*填充Flash缓冲页中的一个字*/
(0019) void boot_page_fill(unsigned int address,unsigned int data) {
(0020)
(0021) asm("mov r30,r16\n"
_boot_page_fill:
data --> R18
address --> R16
F87D 2FE0 MOV R30,R16
F87E 2FF1 MOV R31,R17
F87F 2E02 MOV R0,R18
F880 2E13 MOV R1,R19
(0022) "mov r31,r17\n" /*Z寄存器中为填冲页内地址*/
(0023) "mov r0,r18\n"
(0024) "mov r1,r19\n"); /*R0R1中为一个指令字*/
(0025) SPMCSR = (1 << SPMEN); /*SPM使能位*/
F881 E081 LDI R24,1
F882 93800068 STS 0x68,R24
(0026) asm("spm\n"); /*执行SPM操作*/
F884 95E8 SPM
F885 9508 RET
(0027) }
(0028)
(0029) /*等待一个Flash页的写完成 */
(0030) void wait_page_rw_ok(void) {
_wait_page_rw_ok:
F886 C008 RJMP 0xF88F
(0031)
(0032) while (SPMCSR & (1 << RWWSB)) { /*等待忙信号*/
(0033) while (SPMCSR & (1 << SPMEN)); /*等待EN信号完成*/
F887 90200068 LDS R2,0x68
F889 FC20 SBRC R2,0
F88A CFFC RJMP 0xF887
(0034) SPMCSR = (1 << RWWSRE) | (1 << SPMEN);/*SPM读使能*/
F88B E181 LDI R24,0x11
F88C 93800068 STS 0x68,R24
(0035) asm("spm\n"); /*执行SPM操作*/
F88E 95E8 SPM
F88F 90200068 LDS R2,0x68
F891 FC26 SBRC R2,6
F892 CFF4 RJMP 0xF887
F893 9508 RET
(0036) }
(0037) }
(0038)
(0039) /*写锁定位*/
(0040) void write_lock_bits (unsigned char val) {
(0041)
(0042) asm("mov r0,r16\n");
_write_lock_bits:
val --> R16
F894 2E00 MOV R0,R16
(0043) SPMCSR=(1 << BLBSET) | (1 << SPMEN);
F895 E089 LDI R24,0x9
F896 93800068 STS 0x68,R24
(0044) asm("spm\n");
F898 95E8 SPM
(0045) while (SPMCSR & (1 << SPMEN)); /*等待EN信号完成*/
F899 90200068 LDS R2,0x68
F89B FC20 SBRC R2,0
F89C CFFC RJMP 0xF899
(0046) SPMCSR = (1 << RWWSRE) | (1 << SPMEN); /*SPM读使能*/
F89D E181 LDI R24,0x11
F89E 93800068 STS 0x68,R24
(0047) asm("spm\n");
F8A0 95E8 SPM
F8A1 9508 RET
(0048) }
(0049)
(0050) /**********************************************************************
(0051) functionName:unsigned char read_program_memory (unsigned int addr,unsigned char cmd)
(0052) description: 返回addr地址数据,以字节为单位
(0053) cmd:
(0054) 0:读flashrom
(0055) 1:读熔丝位或者锁定位
(0056) addr=0x0001 锁定位
(0057) addr=0x0000 熔丝位低字节
(0058) addr=0x0003 熔丝位高字节
(0059) **********************************************************************/
(0060) unsigned char read_program_memory(unsigned int addr,unsigned char cmd) {
(0061)
(0062) asm("mov r30,r16\n"
_read_program_memory:
cmd --> R18
addr --> R16
F8A2 2FE0 MOV R30,R16
F8A3 2FF1 MOV R31,R17
(0063) "mov r31,r17\n");
(0064) if (cmd) {
F8A4 2322 TST R18
F8A5 F019 BEQ 0xF8A9
(0065) SPMCSR=(1 << BLBSET) | (1 << SPMEN);
F8A6 E089 LDI R24,0x9
F8A7 93800068 STS 0x68,R24
(0066) }
(0067) asm("lpm r0,z\n");
F8A9 9004 LPM R0,0(Z)
(0068) return(R0);
F8AA 91000000 LDS R16,0x0
F8AC 9508 RET
FILE: E:\ICCAVR\project\AVRMEG~3\icc\019-BOOT\uart.c
(0001) #include "init.h"
(0002)
(0003) /*串口初始化函数*/
(0004) void uart0_init(void) {
(0005)
(0006) UCSR0A = 0x00;
_uart0_init:
F8AD 2422 CLR R2
F8AE B82B OUT 0x0B,R2
(0007) UCSR0B = (1 << TXEN0) | (1 << RXEN0); /*允许接收和发送*/
F8AF E188 LDI R24,0x18
F8B0 B98A OUT 0x0A,R24
(0008) UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /*8位数据、1 位停止、异步、无校验*/
F8B1 E086 LDI R24,6
F8B2 93800095 STS 0x95,R24
(0009) UBRR0H = 0;
F8B4 92200090 STS 0x90,R2
(0010) UBRR0L = 1; /*波特率115200*/
F8B6 E081 LDI R24,1
F8B7 B989 OUT 0x09,R24
F8B8 9508 RET
(0011) }
(0012)
(0013) /*数据发送,查询方式*/
(0014) void putChar(unsigned char i) {
(0015)
(0016) while (!(UCSR0A & (1<<UDRE0))); /* 等待发送缓冲器为空*/
_putChar:
i --> R16
F8B9 9B5D SBIS 0x0B,5
F8BA CFFE RJMP _putChar
(0017) UDR0 = i; /* 发送数据*/
F8BB B90C OUT 0x0C,R16
F8BC 9508 RET
(0018) }
(0019)
(0020) /*数据接收,等待查询方式*/
(0021) unsigned char getChar(void) {
_getChar:
F8BD C012 RJMP 0xF8D0
(0022)
(0023) while (!(UCSR0A & (1<<RXC0))) { /* 等待接收数据*/
(0024) if (TCNT1 > 3000) { /*以下6行代码为指示灯显示*/
F8BE EB88 LDI R24,0xB8
F8BF E09B LDI R25,0xB
F8C0 B42C IN R2,0x2C
F8C1 B43D IN R3,0x2D
F8C2 1582 CP R24,R2
F8C3 0593 CPC R25,R3
F8C4 F458 BCC 0xF8D0
(0025) TCNT1 = 0x00;
F8C5 2422 CLR R2
F8C6 2433 CLR R3
F8C7 BC3D OUT 0x2D,R3
F8C8 BC2C OUT 0x2C,R2
(0026) PORTB ^= (1 << PB7);
F8C9 E880 LDI R24,0x80
F8CA E090 LDI R25,0
F8CB B228 IN R2,0x18
F8CC 2433 CLR R3
F8CD 2628 EOR R2,R24
F8CE 2639 EOR R3,R25
F8CF BA28 OUT 0x18,R2
F8D0 9B5F SBIS 0x0B,7
F8D1 CFEC RJMP 0xF8BE
(0027) }
(0028) }
(0029) PORTB ^= (1 << PB7);
F8D2 E880 LDI R24,0x80
F8D3 E090 LDI R25,0
F8D4 B228 IN R2,0x18
F8D5 2433 CLR R3
F8D6 2628 EOR R2,R24
F8D7 2639 EOR R3,R25
F8D8 BA28 OUT 0x18,R2
(0030) return UDR0; /* 获取并返回数据*/
F8D9 B10C IN R16,0x0C
F8DA 9508 RET
FILE: E:\ICCAVR\project\AVRMEG~3\icc\019-BOOT\init.c
(0001) #include "init.h"
(0002)
(0003) /*参数声明*/
(0004) unsigned char msg_buffer[300]; //消息体
(0005) unsigned char seqNumber; //顺序数
(0006) unsigned char checkSum; //和校验
(0007) unsigned char clockSpeed; //时钟速度
(0008) unsigned char resetPolarity; //复位极性
(0009) unsigned char paramControllerInit; //参数控制器初始化
(0010) unsigned char prgMode; //编程模式
(0011) unsigned char statusMachine; //状态机
(0012) unsigned int msgSize; //消息尺寸
(0013) unsigned char flag = 0; //接收到消息
(0014)
(0015) unsigned long address; //地址
(0016)
(0017) /*IO口初始化函数*/
(0018) void io_init(void) {
(0019)
(0020) DDRA = 0x00; /*方向输入*/
_io_init:
F8DB 2422 CLR R2
F8DC BA2A OUT 0x1A,R2
(0021) PORTA = 0xFF; /*打开上拉*/
F8DD EF8F LDI R24,0xFF
F8DE BB8B OUT 0x1B,R24
(0022) DDRB = 0x00; /*方向输出*/
F8DF BA27 OUT 0x17,R2
(0023) PORTB = 0xFF; /*输出高电平*/
F8E0 BB88 OUT 0x18,R24
(0024) DDRC = 0x00; /*不用的IO口建议设置为输入带上拉*/
F8E1 BA24 OUT 0x14,R2
(0025) PORTC = 0xFF;
F8E2 BB85 OUT 0x15,R24
(0026) DDRD = 0x00;
F8E3 BA21 OUT 0x11,R2
(0027) PORTD = 0xFF;
F8E4 BB82 OUT 0x12,R24
(0028) DDRE = 0x00;
F8E5 B822 OUT 0x02,R2
(0029) PORTE = 0xFF;
F8E6 B983 OUT 0x03,R24
(0030) DDRF = 0x00;
F8E7 92200061 STS 0x61,R2
(0031) PORTF = 0xFF;
F8E9 93800062 STS 0x62,R24
(0032) DDRG = 0x00;
F8EB 92200064 STS 0x64,R2
(0033) PORTG = 0xFF;
F8ED 93800065 STS 0x65,R24
F8EF 9508 RET
(0034) }
(0035)
(0036) void timer1_init(void) {
(0037) TCCR1B = 0x00;
_timer1_init:
F8F0 2422 CLR R2
F8F1 BC2E OUT 0x2E,R2
(0038) TCNT1H = 0x00;
F8F2 BC2D OUT 0x2D,R2
(0039) TCNT1L = 0x00;
F8F3 BC2C OUT 0x2C,R2
(0040) TCCR1A = 0x00;
F8F4 BC2F OUT 0x2F,R2
(0041) TCCR1B = 0x05;
F8F5 E085 LDI R24,5
F8F6 BD8E OUT 0x2E,R24
F8F7 9508 RET
(0042) }
(0043) void init(void) {
(0044)
(0045) CLI(); /*关闭中断源 */
_init:
F8F8 94F8 BCLR 7
(0046) statusMachine = ST_START; /*变量初始化*/
F8F9 EF80 LDI R24,0xF0
F8FA 93800110 STS statusMachine,R24
(0047) paramControllerInit=0x00;
F8FC 2422 CLR R2
F8FD 92200112 STS paramControllerInit,R2
(0048) prgMode=0;
F8FF 92200111 STS prgMode,R2
(0049)
(0050) io_init();
F901 DFD9 RCALL _io_init
(0051)
(0052) /*入口判断*/
(0053) /*
(0054) 在执行强行跳转指令"jmp 0x0000"前,对寄存器MCUCR的操作是将中断向量地址
(0055) 迁移回应用程序区的头部,因为在ICCAVR环境中编译Bootloader程序时,其自动
(0056) 把中断向量地址迁移到了Bootloader区的头部。
(0057) */
(0058) if (PINE & (1 << PE7)) { /*判断按键是否按下*/
F902 9B0F SBIS 0x01,7
F903 C007 RJMP 0xF90B
(0059) MCUCR = 0x01;
F904 E081 LDI R24,1
F905 BF85 OUT 0x35,R24
(0060) MCUCR = 0x00; /*将中断向量表迁移到应用程序区头部*/
F906 2422 CLR R2
F907 BE25 OUT 0x35,R2
(0061) RAMPZ = 0x00; /*RAMPZ清零初始化*/
F908 BE2B OUT 0x3B,R2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -