Currently I'm working in a project in which I have to migrate assembly AVR code to C code. Of course, I'm doing it by hand as it's the most effective way. The problem is that I came across a problem that I can't figure out.
I don't know which is the correct order of execution of my program. Which I think that is the main file starts like this:
.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:
I don't understand wether the jmp instructions are executed or not...could you help me please? Thank you!
The lowest entries in flash must contain jump statements to the interrupt service routines. This is called the interrupt vector table. The reason for this is that the processor automatically goes to those locations when the interrupt of that type is triggered. This is determined by the hardware and can't be changed.
These interrupt vectors are only 4 bytes apart, so there is no room for the interrupt service routine itself, only enough for a single jump instruction. The labels in your table are also in the file int.asm
, so the structure of your code has the service routines at the front. This is a choice, but they don't have to be at the front necessarily.
When the device is turned on, the instruction at location 0 is run, just as if a reset interrupt was triggered. In your case, this is a jump to the RESET label.
As you noticed, there is some code in front of the main loop that gets run first, located in the file init.asm
. This is typically code that sets the RAM to 0 that represents global and static variables that have not been initialized, and also some code to copy the initial values of global and static variables from flash to RAM for those that do have initial values. (Local variables for functions are on the stack, and the code to initialize them is included in the function, along with code to save and restore values in the registers that are used by the function.)
After this initialization code runs, your main loop runs.
I can't see what your particular initialization code is. If it is as I suspect, then you won't have to code it in C. It is part of the C runtime (crt0
) that the compiler will add automatically. You also won't have to construct the interrupt table, either. Use the AVR macros to include the ones you want, and the compiler will do the rest.