; ARM assembly tutorial for Asmonite, example 22: a template for your own programs (Raspberry Pi Pico 2,
; Arm Cortex-M33).
; Adapted from the ARM-ASM-Tutorial by Niklas Guertler (example ProjectTemplate); see LICENSE.txt.
;
; Copy this file and write your program at "main". It runs in the RAM (F7 loads it and stops at _start);
; for the flash change .imagebase to 0x10000000 and put the IMAGE_DEF block of 08_blink_flash.asm behind
; the vector table. What is here:
;   - the vector table with a handler for every exception of the core (they end in "hang", where the
;     debugger shows you which one it was: look at the register IPSR, the low bits of xPSR)
;   - VTOR, the stack pointer and the start-up of the "data" and "bss" variables are not needed in the RAM:
;     the variables are part of the program, see 07_ram_variables.asm
;   - setup_led and the delay function, and the constants of the blocks used so far
.target pico2
.arch thumb
.imagebase 0x20000000

RESETS_BASE         equ 0x40020000
RESETS_RESET_DONE   equ 0x08
RESET_BITS          equ (1 << 6) | (1 << 9)     ; IO_BANK0, PADS_BANK0
IO_BANK0_BASE       equ 0x40028000
GPIO25_CTRL         equ 0xcc
FUNCSEL_SIO         equ 5
PADS_BANK0_BASE     equ 0x40038000
PADS_GPIO25         equ 0x68
PAD_ISO             equ 1 << 8
SIO_BASE            equ 0xd0000000
SIO_GPIO_OUT_SET    equ 0x18
SIO_GPIO_OUT_CLR    equ 0x20
SIO_GPIO_OUT_XOR    equ 0x28
SIO_GPIO_OE_SET     equ 0x38
ALIAS_CLR           equ 0x3000
SCS_BASE            equ 0xe000e000
SCB_VTOR            equ 0xd08
SRAM_END            equ 0x20082000

vectors:
    dd SRAM_END                 ;  0: the stack pointer at the start
    dd _start + 1               ;  1: reset
    dd hang + 1                 ;  2: NMI
    dd hang + 1                 ;  3: HardFault
    dd hang + 1, hang + 1, hang + 1, hang + 1   ; 4 .. 7: MemManage, BusFault, UsageFault, SecureFault
    dd 0, 0, 0                  ;  8 .. 10: reserved
    dd hang + 1, hang + 1, 0    ; 11 .. 13: SVCall, DebugMonitor, reserved
    dd hang + 1, hang + 1       ; 14, 15: PendSV, SysTick

_start:
    ldr  r0, lit_scs
    adr  r1, vectors
    str  r1, [r0, #SCB_VTOR]    ; our vector table
    bl   setup_led

main:
    ; ---- your program ----
    ldr  r4, lit_sio
    ldr  r5, lit_led_bit
main_loop:
    str  r5, [r4, #SIO_GPIO_OUT_XOR]
    ldr  r0, lit_delay_value
    bl   delay
    b    main_loop

; ---- delay(r0 = iterations) ----
delay:
    subs r0, r0, #1
    bne  delay
    bx   lr

; ---- IO_BANK0 and PADS_BANK0 out of reset, GPIO 25: SIO, output; changes r0 .. r2 ----
setup_led:
    ldr  r1, lit_resets_clr
    ldr  r0, lit_reset_bits
    str  r0, [r1]
    ldr  r1, lit_resets
setup_wait:
    ldr  r2, [r1, #RESETS_RESET_DONE]
    and  r2, r2, r0
    cmp  r2, r0
    bne  setup_wait
    ldr  r1, lit_pads_clr
    mov  r0, #PAD_ISO
    str  r0, [r1, #PADS_GPIO25]
    ldr  r1, lit_io_bank0
    movs r0, #FUNCSEL_SIO
    str  r0, [r1, #GPIO25_CTRL]
    ldr  r1, lit_sio
    ldr  r0, lit_led_bit
    str  r0, [r1, #SIO_GPIO_OE_SET]
    bx   lr

hang:
    b    hang                   ; an exception without its own handler

    align 4
lit_resets:      dd RESETS_BASE
lit_resets_clr:  dd RESETS_BASE + ALIAS_CLR
lit_reset_bits:  dd RESET_BITS
lit_pads_clr:    dd PADS_BANK0_BASE + ALIAS_CLR
lit_io_bank0:    dd IO_BANK0_BASE
lit_sio:         dd SIO_BASE
lit_led_bit:     dd 1 << 25
lit_scs:         dd SCS_BASE
lit_delay_value: dd 1000000

; ---- variables ----
counter: dd 0
