Files
zOS/startup/app_k64f_crt0.s

266 lines
12 KiB
ArmAsm

########################################################################################################
#
# Name: app_k64f_crt0.h
# Created: April 2020
# Author(s): Philip Smart
# Description: ZPUTA/zOS application startup code.
# This is the assembler startup file of any C compiled APPlication for the ZPUTA and
# zOS programs. It specifies the entry points into ZPUTA/zOS for standard functions
# and also the stack manipulation to handle parameters and return codes for the
# C APplication (ie. ZPUTA/zOS Calls APP with parameters and APP returns a result code).
#
# Credits:
# Copyright: (c) 2019-20 Philip Smart <philip.smart@net2net.org>
#
# History: April 2020 - Initial script based on zpu appcrt0.s.
#
########################################################################################################
# This source file is free software: you can redistribute it and#or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This source file is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http:#www.gnu.org;licenses;>.
########################################################################################################
.file "app_k64f_crt0.s"
.include "k64f_macros.s"
.syntax unified
.arch armv7-m
.thumb
.section .text,"ax"
.type _start, function
// Define symbols in C to be linked against this assembly startup code.
.extern __bss_section_begin__
.extern __bss_section_end__
.extern __data_section_begin__
.extern __data_section_end__
.extern __text_section_begin__
.extern __text_section_end__
.extern app
.extern G
.extern cfgSoC
.global _start
// Save registers normally preserved in a C call.
_start: stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
stmdb sp!, {r0, r1, r2, r3};
// Copy initialized data from text area to working RAM (data) area.
ldr r1, DATA_BEGIN
ldr r2, TEXT_END
ldr r3, DATA_END
subs r3, r3, r1 // Length of initialized data
beq zerobss // Skip if none
copydata: ldrb r4, [r2], #1 // Read byte from flash
strb r4, [r1], #1 // Store byte to RAM
subs r3, r3, #1 // Decrement counter
bgt copydata // Repeat until done
// Zero uninitialized data (bss)
ldr r1, BSS_BEGIN
ldr r3, BSS_END
subs r3, r3, r1 // Length of uninitialized data
beq exec_app // Skip if none
zerobss: mov r2, #0x00 // Initialise with 0
clearbss: strb r2, [r1], #1 // Store zero
subs r3, r3, #1 // Decrement counter
bgt clearbss // Repeat until done
// Call app(uint32_t param1, uint32_t param2)
exec_app: ldmia.w sp!, {r0, r1, r2, r3} // Get back the parameters ready to pass to app()
// Setup the G and cfgSoC variables using passed parameters.
ldr r4, =G // Setup the pointer for G in the app to G in zOS/ZPUTA.
str r2, [r4]
ldr r4, =cfgSoC // Setup the pointer for cfgSoC in the app to cfgSoC in zOS/ZPUTA.
str r3, [r4]
// r0 = param1, r1 = param2
bl app // Call the application.
// r0 = return code.
// Restore C call registers, load lr straight to PC, R0 = return code.
ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc}
fail_loop: b fail_loop // The pop pc above should never fail, just in case the stack gets corrupted, stay in a loop for safety.
#
#// These are filled in by the linker
#
TEXT_BEGIN: .word __text_section_begin__
TEXT_END: .word __text_section_end__
DATA_BEGIN: .word __data_section_begin__
DATA_END: .word __data_section_end__
BSS_BEGIN: .word __bss_section_begin__
BSS_END: .word __bss_section_end__
#
#-----------------------------------------------
# zOS/ZPUTA API Function Entry Points
#-----------------------------------------------
#
# Entry points in the parent program, zOS/ZPUTA, where the relevvant named functions can be accessed. The
# entry point in this table is used as the address for the specified function in the APPlication such that
# a call to a library function in the APPlication is actually using code in zOS/ZPUTA at runtime thus minimising
# code in the APPlication.
#
# This table doesnt consume space, just defines the addresses which will be called for the relevant function.
#
.equ funcNext, 0x04;
.equ funcAddr, OS_BASEADDR+0x420;
defapifunc break funcAddr
#
# putc and xprint calls.
#
.equ funcAddr, funcAddr+funcNext;
defapifunc putchar funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xputc funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xfputc funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xputs funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xgets funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xfgets funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xfputs funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xatoi funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc uxatoi funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xprintf funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xvprintf funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xsprintf funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xfprintf funcAddr
#
# getc calls
#
.equ funcAddr, funcAddr+funcNext;
defapifunc usb_serial_getchar funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc usb_serial_getchar funcAddr
#
# Util calls
#
# .equ funcAddr, funcAddr+funcNext;
# defapifunc crc32_init funcAddr
# .equ funcAddr, funcAddr+funcNext;
# defapifunc crc32_addword funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc get_dword funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc rtcSet funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc rtcGet funcAddr
#
#FatFS System Calls
#
.equ funcAddr, funcAddr+funcNext;
defapifunc f_open funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_close funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_read funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_write funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_lseek funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_truncate funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_sync funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_opendir funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_closedir funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_readdir funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_findfirst funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_findnext funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_mkdir funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_unlink funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_rename funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_stat funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_chmod funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_utime funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_chdir funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_chdrive funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_getcwd funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_getfree funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_getlabel funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_setlabel funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_forward funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_expand funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_mount funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_mkfs funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_fdisk funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_setcp funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_putc funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_puts funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_printf funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc f_gets funcAddr
#
# Low level disk calls.
#
.equ funcAddr, funcAddr+funcNext;
defapifunc disk_read funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc disk_write funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc disk_ioctl funcAddr
#
# Miscellaneous calls.
#
.equ funcAddr, funcAddr+funcNext;
defapifunc getStrParam funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc getUintParam funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc set_serial_output funcAddr
# .equ funcAddr, funcAddr+funcNext;
# defapifunc printBytesPerSec funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc printFSCode funcAddr
.end