目前,我正在一个项目中,我必须将程序集AVR代码迁移到C代码。当然,由于它是最有效的方法,所以我是手工完成的。问题是我遇到了一个我无法解决的问题。
我不知道哪个是我程序的正确执行顺序。我认为这是主文件开始这样:
.INCLUDE "m8def.inc" ; NO SE QUE SIGNIFICA ESTO
.INCLUDE "macro.asm" ;
.INCLUDE "options.asm"
.LISTMAC
;***************************************************************************
.INCLUDE "define.asm" ; port bits, constants
.INCLUDE "ram.asm" ; ram definitions
;***************************************************************************
;***************************************************************************
;*
;* Start of code
;*
;***************************************************************************
;***************************************************************************
.cseg ;Indicates that the next segment refers to program memory;
.org 0 ; The ORG directive is used to specify a location in program memory where the program following directive is to be placed.
; Interrupt vectors
rjmp RESET ; Reset
rjmp EXT_INT0 ; INT0 (not used)
rjmp EXT_INT1 ; INT1 (not used)
rjmp TIM2_COMP ; Timer2 compare (not used)
rjmp TIM2_OVF ; Timer2 overflow (not used)
rjmp TIM1_CAPT ; Timer1 capture (zero crossing input)
rjmp TIM1_COMPA ; Timer1 compareA (ZX detector timing)
rjmp TIM1_COMPB ; Timer1 compareB (not used)
rjmp TIM1_OVF ; Timer1 overflow (not used)
rjmp TIM0_OVF ; Timer0 overflow
rjmp SPI_INT ; SPI interrupt (not used)
rjmp UART_RX ; UART Rx complete
rjmp UART_TX ; UART UDR empty
rjmp UART_TX ; UART Tx complete (not used)
rjmp ADC_INT ; ADC interupt (not used)
rjmp EERDY_INT ; EEPROM ready interrupt (not used)
rjmp ANA_COMP ; Analog Comparator (not used)
rjmp TWI ; TWI (not used)
rjmp SPM_RDY ; SPM_RDY (not used)
;---------------------------------------------------------------------------
.INCLUDE "int.asm" ; interrupt service routines
RESET:
.INCLUDE "init.asm" ; initialisation
;***************************************************************************
;***************************************************************************
;*
;* Main loop
;*
;***************************************************************************
;***************************************************************************
; .IF $ != ENDINIT
; error "main.asm must follow init.asm"
; .ENDIF
sbi PORTD, PD_LED ; 1 = LED on
nop
cbi PORTD, PD_LED
; ldi uart_char, 'Z' ; 0x5A for test only
; rcall snd_echo
; Main loop
main_lp:
我不知道是否执行了jmp指令...您能帮我吗?谢谢!
闪存中最低的条目必须包含到中断服务程序的跳转语句。这称为中断向量表。这样做的原因是,当触发该类型的中断时,处理器会自动转到那些位置。这由硬件决定,无法更改。
这些中断向量仅相隔4个字节,因此中断服务程序本身没有空间,仅足以容纳一条跳转指令。表中的标签也位于文件int.asm
中,因此代码的结构位于服务例程的前面。这是一个选择,但不必一定要放在最前面。
打开设备电源时,将运行位置0的指令,就像触发了复位中断一样。就您而言,这是跳转到RESET标签的信息。
您注意到,在主循环前面有一些代码首先运行,位于文件init.asm
中。这通常是将RAM设置为0(代表尚未初始化的全局变量和静态变量)的代码,也是一些将具有初始值的全局变量和静态变量的初始值从闪存复制到RAM的代码。 (用于函数的局部变量位于堆栈中,用于初始化它们的代码包括在函数中,以及用于在函数所使用的寄存器中保存和恢复值的代码。)
此初始化代码运行后,您的主循环运行。
我看不到您的特定初始化代码是什么。如果是我所怀疑的,那么您就不必用C编写代码。编译器将自动添加它作为C运行时(crt0
)的一部分。您也不必构造中断表。使用AVR宏来包含所需的宏,其余的将由编译器完成。
上面的注释表示这些是interrupt vectors。当第n个中断触发时,采用第n个向量(跳转)。
这些总是在地址0,这就是为什么您事先看到.org 0
的原因。
当微处理器复位时,它跳到复位向量。在您的代码中,rjmp
指向RESET
标签,该标签正好在.INCLUDE "init.asm"
之前。最有可能的是,此文件中包含首先运行的初始化代码,然后进入主循环代码(sbi
指令)。查看此init.asm
文件。