avr-oxide 0.0.6

An extremely simple Rusty operating system for AVR microcontrollers
.section .ivr, "ax", @progbits
.align 1

ivr:
        jmp _init_cpu
        jmp _ivr_crcscan_nmi
        jmp _ivr_bod_vlm
        jmp _ivr_rtc_cnt
        jmp _ivr_rtc_pit
        jmp _ivr_ccl_ccl
        jmp _ivr_porta_port
        jmp _ivr_tca0_ovf
        jmp _ivr_tca0_hunf
        jmp _ivr_tca0_cmp0
        jmp _ivr_tca0_cmp1
        jmp _ivr_tca0_cmp2
        jmp _ivr_tcb0_int
        jmp _ivr_tcb1_int
        jmp _ivr_twi0_twis
        jmp _ivr_twi0_twim
        jmp _ivr_spi0_int
        jmp _ivr_usart0_rcx
        jmp _ivr_usart0_dre
        jmp _ivr_usart0_tcx
        jmp _ivr_portd_port
        jmp _ivr_ac0_ac
        jmp _ivr_adc0_resrdy
        jmp _ivr_adc0_wcomp
        jmp _ivr_portc_port
        jmp _ivr_tcb2_int
        jmp _ivr_usart1_rcx
        jmp _ivr_usart1_dre
        jmp _ivr_usart1_tcx
        jmp _ivr_portf_port
        jmp _ivr_nvmctrl_ee
        jmp _ivr_usart2_rcx
        jmp _ivr_usart2_dre
        jmp _ivr_usart2_tcx
        jmp _ivr_portb_port
        jmp _ivr_porte_port
        jmp _ivr_tcb3_int
        jmp _ivr_usart3_rcx
        jmp _ivr_usart3_dre
        jmp _ivr_usart3_tcx

_ivr_undefined:
        reti

;;; CPU flags initialisation
_init_cpu:
        cli             ;;; Disable interrupts (the application will reenable when it wants)
        ldi r16,0x01    ;;; Sleep = IDLE mode, ENABLED
        sts 0x50,r16    ;;; Write sleep control flag
        eor r1, r1      ;;; The compiler runtime expects 0 in r1


;;; Clear the BSS region
_init_zero_bss:
        ldi r31, hi8(__bss_start) ;;; load BSS start into Z
        ldi r30, lo8(__bss_start)

        ldi r29, hi8(__bss_end)   ;;; load BSS end into Y
        ldi r28, lo8(__bss_end)

        sub r28, r30              ;;; Y = Y-Z (== length in bytes)
        sbc r29, r31
        rjmp _init_zero_bss_loop_check

_init_zero_bss_loop:
        st Z+, r1                 ;;; Store zero @Z and postincrement

        subi r28, 1               ;;; Decrement counter Y
        sbci r29, 0

_init_zero_bss_loop_check:
        brne _init_zero_bss_loop  ;;; Loop iff Y != 0


;;; Inititalise RAM
_init_copy_memory:
        ldi r31, hi8(__data_load_start) ;;; data segment start into Z
        ldi r30, lo8(__data_load_start)

        ldi r29, hi8(__data_load_end)   ;;; data segment end into Y
        ldi r28, lo8(__data_load_end)

        ldi r27, hi8(__data_start)      ;;; destination address into X
        ldi r26, lo8(__data_start)

        sub r28, r30                    ;;; Y = Y-Z (== length in bytes)
        sbc r29, r31
        rjmp _init_copy_memory_loop_check

_init_copy_memory_loop:
        lpm r0, Z+                     ;;; Load from @Z and incremenent pointer
        st X+, r0                      ;;; Store to @X, increment pointer

        subi r28, 1                    ;;; Decrement counter Y
        sbci r29, 0

_init_copy_memory_loop_check:
        brne _init_copy_memory_loop    ;;; Loop iff Y != 0

;;; Now jump into the application
_init_runtime:
        ;;; @todo reset the stack pointer
        jmp _oxide_boot ;;; Jump to the application entry point





;;; By default, start all interrupt handlers as doing a no-op
;;; return. Since these symbols are weakly linked, user code can
;;; override each one on demand.
.macro _ivr_default name target=_ivr_undefined
.weak \name
.set  \name, \target
.endm

_ivr_default _ivr_crcscan_nmi
_ivr_default _ivr_bod_vlm
_ivr_default _ivr_rtc_cnt
_ivr_default _ivr_rtc_pit
_ivr_default _ivr_ccl_ccl
_ivr_default _ivr_porta_port
_ivr_default _ivr_tca0_ovf
_ivr_default _ivr_tca0_hunf
_ivr_default _ivr_tca0_cmp0
_ivr_default _ivr_tca0_cmp1
_ivr_default _ivr_tca0_cmp2
_ivr_default _ivr_tcb0_int
_ivr_default _ivr_tcb1_int
_ivr_default _ivr_twi0_twis
_ivr_default _ivr_twi0_twim
_ivr_default _ivr_spi0_int
_ivr_default _ivr_usart0_rcx
_ivr_default _ivr_usart0_dre
_ivr_default _ivr_usart0_tcx
_ivr_default _ivr_portd_port
_ivr_default _ivr_ac0_ac
_ivr_default _ivr_adc0_resrdy
_ivr_default _ivr_adc0_wcomp
_ivr_default _ivr_portc_port
_ivr_default _ivr_tcb2_int
_ivr_default _ivr_usart1_rcx
_ivr_default _ivr_usart1_dre
_ivr_default _ivr_usart1_tcx
_ivr_default _ivr_portf_port
_ivr_default _ivr_nvmctrl_ee
_ivr_default _ivr_usart2_rcx
_ivr_default _ivr_usart2_dre
_ivr_default _ivr_usart2_tcx
_ivr_default _ivr_portb_port
_ivr_default _ivr_porte_port
_ivr_default _ivr_tcb3_int
_ivr_default _ivr_usart3_rcx
_ivr_default _ivr_usart3_dre
_ivr_default _ivr_usart3_tcx