NextVOD_Baremetal_Hello/startup_stx7105.S

411 lines
10 KiB
ArmAsm

/* Startup code, we can't use non-PIC code nor RAM before the LMI is initialized:
* The CPU starts with physical address 0x0, however the linker is linked to virtual
* addresses and LMI.
* Non-PIC code means any indirect addressing other than relative to PC.
*/
.section .text.init, "ax"
.global _start
_start:
nop
nop
/* Initialize Blue LED P0_4 */
mov #16, r0
mov.l _gpio_clr_k, r1
mov.l r0, @r1
mov.l _gpio_clr_pc0_k, r1
mov.l r0, @r1
mov.l _gpio_set_pc1_k, r1
mov.l r0, @r1
mov.l _gpio_clr_pc2_k, r1
mov.l r0, @r1
/* Initialize Red LED P0_5 */
mov #32, r0
mov.l _gpio_clr_k, r1
mov.l r0, @r1
mov.l _gpio_clr_pc0_k, r1
mov.l r0, @r1
mov.l _gpio_set_pc1_k, r1
mov.l r0, @r1
mov.l _gpio_clr_pc2_k, r1
mov.l r0, @r1
mov.l _sr_k, r0
ldc r0, sr
mov.l _stack_k, sp /* Setup R15(SP) */
_disable_wdt:
mov.l _cpg_wdt_wtcsr_k, r0
mov.l _cpg_wdt_wtcsr_value_k, r1
mov.w r1, @r0
_configure_spinor:
mov.l _emi_spinor_config_data_k, r0
mov.l _emi_spinor_config_data_value_k, r1
mov.l r1, @r0
mov.l _emi_spinor_modeselect_k, r0
mov.l _emi_spinor_modeselect_value_k, r1
mov.l r1, @r0
/* TODO: Initialize PMB, setup caches !! */
/*
* We need PMBs for LMI and EMI, both cached and uncached.
* To configure an PMB region, two register writes need to be issued:
* 1: Write to PMB address array, with region virtual address.
* The PMB address array entry is calculated as follows:
* - PMB_SLOT_X_ADDR=0xF610_0X00, X=0-F, with a maximum of 16 regions.
* The slot contents are defined as follows:
* - 0xAA00_0100, AA=Virtual page number, bit 31:30 has to be 0b10
* i.e. VA should located in range 0x8000_0000 - 0xBFFF_FFFF
* Note: VA needs to align with its configured size.
* 2: Write to PMB data array, with region size and cache modes.
* The PMB data array entry is calculated as follows:
* PMB_SLOT_X_DATA=0xF710_0X00, X=0-F, with a maximum of 16 regions.
*/
_invalidate_pmb:
mov.l _pmb_address_base, r1 /* PMB address slot base address */
mov #0, r2 /* Value to be written to PMB address slot */
mov #1, r3 /* PMB address stride, 0x100 */
shll8 r3 /* See above */
mov #0, r0 /* Counter */
_loop_invalid_pmb:
mov.l r2, @r1 /* Clear slot N */
add r3, r1 /* Slot += 1 */
cmp/eq #15, r0 /* Counter == 15? */
bf/s _loop_invalid_pmb /* Note: this is a delayed branch, be careful. */
add #1, r0 /* Counter += 1 */
_setup_pmb:
mova _pmb_poke_start_k, r0
mov r0, r1
mova _pmb_poke_end_k, r0
mov r0, r2
_loop_setup_pmb:
mov.l @r1+, r0 /* 1st word, register address */
mov.l @r1+, r3 /* 2nd word, register value */
mov.l r3, @r0
cmp/gt r1, r2
bt _loop_setup_pmb
_invalidate_caches:
mov.l _ccn_ccr_k, r0
mov #0, r1
mov.l r1, @r0 /* Clear all bits */
nop
nop
nop
nop
nop
nop
nop
nop
nop
_setup_caches:
mov.l _ccn_ccr_value_k, r1
mov.l r1, @r0
nop
nop
nop
nop
nop
nop
nop
nop
nop
_enter_p0:
mova _init_lmi, r0
mov #0xE0, r1
shll16 r1
shll8 r1
not r1, r1 /* MASK is 0x1fffffff */
and r1, r0 /* unset top 3-bits */
jmp @r0
nop
.balign 4
/* TODO: Initialize LMI */
_init_lmi:
mov.l _init_ram_k, r1 /* Load actual function address to r1 */
jsr @r1 /* Jump to the init_ram function */
nop
/* TODO: Switch to 32-bit mode */
_enable_se_mode:
mov.l _ccn_mmucr_k, r0
mov #4, r1 /* SH4_MMUCR_TI */
mov.l r1, @r0
mov.l _ccn_pascr_k, r0
mov.l _ccn_pascr_value_k, r1
mov.l r1, @r0
_setup_irq:
mov.l _exc_base_k, r0
ldc r0, vbr
_go_non_privileged:
mov.l _crt0_entry, r0
ldc r0, spc
stc sr, r0
ldc r0, ssr
rte
nop
/* RTE has to be aligned */
.align 4
_copy_data:
mov.l _sidata_k, r0
mov.l _sdata_k, r1
mov.l _edata_k, r2
_loop_copy_data:
mov.l @r0+, r3 /* Load a word to r3 from [sidata], with post-increment of 4 */
mov.l r3, @r1 /* Store the word in r3 to [sdata] */
add #4, r1 /* Increment sdata pointer */
cmp/gt r1, r2 /* r2 greater or equal than r1? */
bt _loop_copy_data
_zero_bss:
mov.l _edata_k, r0
mov.l _end_k, r1
mov #0, r2
_loop_zero_bss:
mov.l r2, @r0
add #4, r0
cmp/gt r0, r1
bt _loop_zero_bss
/* Turn on Blue LED */
mov #16, r7
mov.l _gpio_set_k, r8
mov.l r7, @r8
_setup_fpu:
mov.l _set_fpscr_k, r1
jsr @r1
mov #0, r4
lds r3, fpscr
/* Try to enable UART from Assembly... */
mov.l _system_config_34_k, r0
mov.l _system_config_34_value_k, r1
mov.l r1, @r0
mov.l _gpio4_clr_pc0_k, r0
mov #1, r1
mov.b r1, @r0
mov.l _gpio4_set_pc1_k, r0
mov.b r1, @r0
mov.l _gpio4_set_pc2_k, r0
mov.b r1, @r0
mov.l _asc2_baud_k, r0
mov.l _asc2_baud_value_k, r1
mov.l r1, @r0
mov.l _asc2_ctrl_k, r0
mov.l _asc2_ctrl_value_k, r1
mov.l r1, @r0
mov.l _asc2_tx_buf_k, r0
mov #65, r1
mov.b r1, @r0
_memory_test:
mov.l _sdata_k, r0
mov.l _stack_k, r1
_loop_memory_write:
mov.l r1, @-r1
cmp/gt r0, r1
bt _loop_memory_write
_memory_compare:
mov.l _stack_k, r1
_loop_memory_compare:
mov r1, r3
mov.l @r1+, r2
cmp/eq r2, r3
bt _loop_memory_compare_addr
mova _memory_fail_set_led, r0
jmp @r0
nop
_loop_memory_compare_addr:
cmp/gt r0, r1
bt _loop_memory_compare
mova _main_entry, r0
jmp @r0
nop
.align 2
_memory_fail_set_led:
/* Turn on Red LED */
mov #32, r7
mov.l _gpio_set_k, r8
mov.l r7, @r8
.align 2
_main_entry:
/* Turn off Blue LED */
mov #16, r7
mov.l _gpio_clr_k, r8
mov.l r7, @r8
mov.l _main_k, r0
jsr @r0
or r0, r0
mov r0, r4
mov.l _exit_k, r0
jsr @r0
or r0, r0
/* It would be more efficient by using indirect addressing instead of 8 instructions... */
/* Align to 4 byte boundary since we are loading the whole word */
.align 4
/* PMB address register */
_pmb_address_base:
.long 0xF6100000
/* PMB poke tables */
_pmb_poke_start_k:
.long 0xF6100000 /* Address entry #0 register : LMI lower half, 128MB, mapped to 0x8000_0000 */
.long 0x80000100 /* Address entry #0 data : LMI lower half, 128MB, mapped to 0x8000_0000 */
.long 0xF6100100 /* Address entry #1 register : LMI higher half, 128MB, mapped to 0x8800_0000 */
.long 0x88000100 /* Address entry #1 data : LMI higher half, 128MB, mapped to 0x8800_0000 */
.long 0xF6100200 /* Address entry #2 register : LMI lower half, 128MB, mapped to 0x9000_0000 */
.long 0x90000100 /* Address entry #2 data : LMI lower half, 128MB, mapped to 0x9000_0000 */
.long 0xF6100300 /* Address entry #3 register : LMI higher half, 128MB, mapped to 0x9800_0000 */
.long 0x98000100 /* Address entry #3 data : LMI higher half, 128MB, mapped to 0x9800_0000 */
.long 0xF6100400 /* Address entry #4 register : EMI NOR uncached, 64MB, mapped to 0xA000_0000 */
.long 0xA0000100 /* Address entry #4 data : EMI NOR uncached, 64MB, mapped to 0xA000_0000 */
.long 0xF6100500 /* Address entry #5 register : EMI NOR cached, 64MB, mapped to 0xA400_0000 */
.long 0xA4000100 /* Address entry #5 data : EMI NOR cached, 64MB, mapped to 0xA400_0000 */
.long 0xF7100000 /* Data entry #0 register : LMI lower half, 128MB, uncached, unbuffered */
.long 0x40000380 /* Data entry #0 data : LMI lower half, 128MB, uncached, unbuffered */
.long 0xF7100100 /* Data entry #1 register : LMI higher half, 128MB, uncached, unbuffered */
.long 0x48000380 /* Data entry #1 data : LMI higher half, 128MB, uncached, unbuffered */
.long 0xF7100200 /* Data entry #2 register : LMI lower half, 128MB, uncached, unbuffered */
.long 0x40000380 /* Data entry #2 data : LMI lower half, 128MB, uncached, unbuffered */
.long 0xF7100300 /* Data entry #3 register : LMI higher half, 128MB, uncached, unbuffered */
.long 0x48000380 /* Data entry #3 data : LMI higher half, 128MB, uncached, unbuffered */
.long 0xF7100400 /* Data entry #4 register : EMI NOR uncached, 64MB, uncached, unbuffered */
.long 0x00000310 /* Data entry #4 data : EMI NOR uncached, 64MB, uncached, unbuffered */
.long 0xF7100500 /* Data entry #5 register : EMI NOR cached, 64MB, cached, buffered */
.long 0x00000118 /* Data entry #5 data : EMI NOR cached, 64MB, cached, buffered */
_pmb_poke_end_k:
.long 0x0000000
/* CCN CCR address */
_ccn_ccr_k:
.long 0xFF00001C
_ccn_ccr_value_k:
.long 0x8000090D
_ccn_mmucr_k:
.long 0xFF000010
_ccn_pascr_k:
.long 0xFF000070
_ccn_pascr_value_k:
.long 0x80000000
/* SR content */
_sr_k:
.long 0x400000F0
/* WDT */
_cpg_wdt_wtcsr_k:
.long 0xFFC0000C
_cpg_wdt_wtcsr_value_k:
.long 0x0000A500
/* EMI SPI NOR configuration registers */
_emi_spinor_config_data_k:
.long 0xFE702020
_emi_spinor_config_data_value_k:
.long 0x00020011
_emi_spinor_modeselect_k:
.long 0xFE702018
_emi_spinor_modeselect_value_k:
.long 0x00000002
/* PIO registers for debugging */
_gpio_set_k:
.long 0xFD020004
_gpio_clr_k:
.long 0xFD020008
_gpio_clr_pc0_k:
.long 0xFD020028
_gpio_set_pc1_k:
.long 0xFD020034
_gpio_clr_pc2_k:
.long 0xFD020048
_system_config_34_k:
.long 0xFE001188
_system_config_34_value_k:
.long 0x00000F00
_gpio4_clr_pc0_k:
.long 0xFD024028
_gpio4_set_pc1_k:
.long 0xFD024034
_gpio4_set_pc2_k:
.long 0xFD024044
_asc2_baud_k:
.long 0xFD032000
_asc2_baud_value_k:
.long 0x000004B8
_asc2_tx_buf_k:
.long 0xFD032004
_asc2_ctrl_k:
.long 0xFD03200C
_asc2_ctrl_value_k:
.long 0x00001589
_crt0_entry:
.long _copy_data
/* libc FPU routine */
_set_fpscr_k:
.long ___set_fpscr
/* C library consts */
_stack_k:
.long _stack
_sidata_k:
.long _sidata
_sdata_k:
.long _sdata
_edata_k:
.long _edata
_end_k:
.long _end
/* Function pointers */
_init_ram_k:
.long _memory_setup_init_ram
_main_k:
.long _main /* Same address as main */
_exit_k:
.long _exit
_exc_base_k:
.long _exc_base
.section .text.exc, "ax"
.align 4
_exc_base:
.org 0x100, 0x00
_exc_grnl_vector:
mov.l _exc_grnl_entry, r0
jmp @r0
nop
.align 4
_exc_grnl_entry:
.long _general_exc_handler