summaryrefslogtreecommitdiff
path: root/firmware/src
diff options
context:
space:
mode:
authorlaforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-09-13 16:02:52 +0000
committerlaforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-09-13 16:02:52 +0000
commita97e460bea62375c9c870fb3e3650fbff20c5ad1 (patch)
tree64c0de524a604015a367aa979c777325765fbfa3 /firmware/src
parent8bd3d51b23e328e91c209dbebe8cfe002b0b0042 (diff)
Completely separate DFU from application program, we now have a real bootloader.
DFU occupies 0x00100000 - 0x00100fff in flash, application starts at 0x00101000. DFU also occupies the first couple of bytes in SRAM, application starts at 0x00200024. In order to produce a samba-flashable image, first build dfu.bin by typing 'make -f Makefule.dfu', succeeded by 'make TARGET=... DEBUG=... BOARD=...' and then concatenating the two files together, e.g. cat dfu.bin main_reqa.bin > flash.bin. Actual flashing via DFU is still not operational, but will be implemented next git-svn-id: https://svn.openpcd.org:2342/trunk@194 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'firmware/src')
-rw-r--r--firmware/src/dfu/dfu.c (renamed from firmware/src/os/dfu.c)12
-rw-r--r--firmware/src/dfu/dfu.h (renamed from firmware/src/os/dfu.h)11
-rw-r--r--firmware/src/os/main.c2
-rw-r--r--firmware/src/os/pcd_enumerate.c5
-rw-r--r--firmware/src/os/pcd_enumerate.h2
-rw-r--r--firmware/src/start/Cstartup.S348
-rw-r--r--firmware/src/start/Cstartup_app.S81
7 files changed, 268 insertions, 193 deletions
diff --git a/firmware/src/os/dfu.c b/firmware/src/dfu/dfu.c
index f2bc0ca..f50b564 100644
--- a/firmware/src/os/dfu.c
+++ b/firmware/src/dfu/dfu.c
@@ -11,9 +11,8 @@
#include <usb_dfu.h>
#include <lib_AT91SAM7.h>
-#include <os/dfu.h>
+#include <dfu/dfu.h>
#include <os/pcd_enumerate.h>
-#include <os/req_ctx.h>
#include "../openpcd.h"
/* If debug is enabled, we need to access debug functions from flash
@@ -29,7 +28,7 @@
#endif
-void __dfufunc udp_init(void)
+static void __dfufunc udp_init(void)
{
/* Set the PLL USB Divider */
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
@@ -107,7 +106,7 @@ static void __dfufunc udp_ep0_send_stall(void)
static u_int8_t status;
static u_int8_t *ptr;
-static u_int8_t dfu_state;
+static __dfudata u_int32_t dfu_state;
static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
{
@@ -149,7 +148,7 @@ static __dfufunc int handle_upload(u_int16_t val, u_int16_t len)
{
DEBUGE("upload ");
if (len > AT91C_IFLASH_PAGE_SIZE
- || ptr > AT91C_IFLASH_SIZE) {
+ || ptr > AT91C_IFLASH_SIZE - 0x1000) {
/* Too big */
dfu_state = DFU_STATE_dfuERROR;
status = DFU_STATUS_errADDRESS;
@@ -226,7 +225,7 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
handle_dnload(val, len);
break;
case USB_REQ_DFU_UPLOAD:
- ptr = 0;
+ ptr = 0x00101000; /* Flash base address for app */
dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
handle_upload(val, len);
break;
@@ -667,6 +666,7 @@ void __dfufunc dfu_main(void)
}
const struct dfuapi __dfufunctab dfu_api = {
+ .udp_init = &udp_init,
.ep0_send_data = &udp_ep0_send_data,
.ep0_send_zlp = &udp_ep0_send_zlp,
.ep0_send_stall = &udp_ep0_send_stall,
diff --git a/firmware/src/os/dfu.h b/firmware/src/dfu/dfu.h
index 8786044..992a4f2 100644
--- a/firmware/src/os/dfu.h
+++ b/firmware/src/dfu/dfu.h
@@ -13,8 +13,6 @@
#include <usb_ch9.h>
#include <usb_dfu.h>
-#include "dbgu.h"
-
/* USB DFU functional descriptor */
#define DFU_FUNC_DESC { \
.bLength = USB_DT_DFU_SIZE, \
@@ -38,9 +36,10 @@
.iInterface = 1, \
}
-#define __dfufunc __attribute__ ((long_call, section (".dfu.func")))
-#define __dfustruct __attribute__ ((section (".dfu.struct"))) const
#define __dfufunctab __attribute__ ((section (".dfu.functab")))
+#define __dfudata __attribute__ ((section (".data.shared")))
+#define __dfufunc
+#define __dfustruct const
#if 0
extern void __dfufunc udp_ep0_send_data(const char *data, u_int32_t length);
@@ -55,9 +54,6 @@ extern static u_int8_t dfu_state;
struct udp_pcd;
#endif
-
-extern void __dfufunc udp_init(void);
-
struct _dfu_desc {
struct usb_config_descriptor ucfg;
struct usb_interface_descriptor uif[2];
@@ -65,6 +61,7 @@ struct _dfu_desc {
};
struct dfuapi {
+ void (*udp_init)(void);
void (*ep0_send_data)(const char *data, u_int32_t len);
void (*ep0_send_zlp)(void);
void (*ep0_send_stall)(void);
diff --git a/firmware/src/os/main.c b/firmware/src/os/main.c
index 4b7a7a2..878fdbf 100644
--- a/firmware/src/os/main.c
+++ b/firmware/src/os/main.c
@@ -3,7 +3,6 @@
#include <include/lib_AT91SAM7.h>
#include <os/dbgu.h>
#include <os/led.h>
-#include <os/dfu.h>
#include <os/main.h>
#include <os/power.h>
#include <os/pcd_enumerate.h>
@@ -20,7 +19,6 @@ int main(void)
_init_func();
/* initialize USB */
- udp_init();
udp_open();
// Enable User Reset and set its minimal assertion to 960 us
diff --git a/firmware/src/os/pcd_enumerate.c b/firmware/src/os/pcd_enumerate.c
index cded8c8..40bd88e 100644
--- a/firmware/src/os/pcd_enumerate.c
+++ b/firmware/src/os/pcd_enumerate.c
@@ -23,7 +23,7 @@
#include <os/pcd_enumerate.h>
#include <os/req_ctx.h>
-#include <os/dfu.h>
+#include <dfu/dfu.h>
#include "../openpcd.h"
#include <os/dbgu.h>
@@ -41,6 +41,7 @@
#ifdef CONFIG_DFU
#define DFU_API_LOCATION ((const struct dfuapi *) 0x00102100)
static const struct dfuapi *dfu = DFU_API_LOCATION;
+#define udp_init dfu->udp_init
#define udp_ep0_send_data dfu->ep0_send_data
#define udp_ep0_send_zlp dfu->ep0_send_zlp
#define udp_ep0_send_stall dfu->ep0_send_stall
@@ -328,6 +329,7 @@ static void udp_irq(void)
void udp_open(void)
{
DEBUGPCRF("entering");
+ udp_init();
upcd.pUdp = AT91C_BASE_UDP;
upcd.cur_config = 0;
upcd.cur_rcv_bank = AT91C_UDP_RX_DATA_BK0;
@@ -340,7 +342,6 @@ void udp_open(void)
/* End-of-Bus-Reset is always enabled */
/* Set the Pull up resistor */
- AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
}
diff --git a/firmware/src/os/pcd_enumerate.h b/firmware/src/os/pcd_enumerate.h
index 57ff88c..813243e 100644
--- a/firmware/src/os/pcd_enumerate.h
+++ b/firmware/src/os/pcd_enumerate.h
@@ -5,7 +5,7 @@
#include <sys/types.h>
#include <asm/atomic.h>
#include "openpcd.h"
-#include "dfu.h"
+#include <dfu/dfu.h>
struct req_ctx;
diff --git a/firmware/src/start/Cstartup.S b/firmware/src/start/Cstartup.S
index e91fd86..e7d5714 100644
--- a/firmware/src/start/Cstartup.S
+++ b/firmware/src/start/Cstartup.S
@@ -76,165 +76,22 @@
.text
.arm
.section .vectram, "ax"
-resetvecR: B resetvecR
-undefvecR: B undefvecR
-swivecR: B swivecR
-pabtvecR: B pabtvecR
-dabtvecR: B dabtvecR
-rsvdvecR: B rsvdvecR
-irqvecR: B IRQ_Handler_EntryR
-fiqvecR:
-FIQ_Handler_EntryR:
-
-/*- Switch in SVC/User Mode to allow User Stack access for C code */
-/* because the FIQ is not yet acknowledged*/
-
-/*- Save and r0 in FIQ_Register */
- mov r9,r0
- ldr r0 , [r8, #AIC_FVR]
- msr CPSR_c,#I_BIT | F_BIT | ARM_MODE_SVC
-
-/*- Save scratch/used registers and LR in User Stack */
- stmfd sp!, { r1-r3, r12, lr}
-
-/*- Branch to the routine pointed by the AIC_FVR */
- mov r14, pc
- bx r0
-
-/*- Restore scratch/used registers and LR from User Stack */
- ldmia sp!, { r1-r3, r12, lr}
-
-/*- Leave Interrupts disabled and switch back in FIQ mode */
- msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ
-
-/*- Restore the R0 ARM_MODE_SVC register */
- mov r0,r9
-
-/*- Restore the Program Counter using the LR_fiq directly in the PC */
- subs pc,lr,#4
-
- .global IRQ_Handler_EntryR
- .func IRQ_Handler_EntryR
-
-IRQ_Handler_EntryR:
-
-/*- Manage Exception Entry */
-/*- Adjust and save LR_irq in IRQ stack */
- sub lr, lr, #4
- stmfd sp!, {lr}
-
-/*- Save SPSR need to be saved for nested interrupt */
- mrs r14, SPSR
- stmfd sp!, {r14}
-
-/*- Save and r0 in IRQ stack */
- stmfd sp!, {r0}
-
-/*- Write in the IVR to support Protect Mode */
-/*- No effect in Normal Mode */
-/*- De-assert the NIRQ and clear the source in Protect Mode */
- ldr r14, =AT91C_BASE_AIC
- ldr r0 , [r14, #AIC_IVR]
- str r14, [r14, #AIC_IVR]
-
-/*- Enable Interrupt and Switch in Supervisor Mode */
- msr CPSR_c, #ARM_MODE_SVC
-
-/*- Save scratch/used registers and LR in User Stack */
- stmfd sp!, { r1-r3, r12, r14}
-
-/*- Branch to the routine pointed by the AIC_IVR */
- mov r14, pc
- bx r0
-/*- Restore scratch/used registers and LR from User Stack*/
- ldmia sp!, { r1-r3, r12, r14}
-
-/*- Disable Interrupt and switch back in IRQ mode */
- msr CPSR_c, #I_BIT | ARM_MODE_IRQ
-
-/*- Mark the End of Interrupt on the AIC */
- ldr r14, =AT91C_BASE_AIC
- str r14, [r14, #AIC_EOICR]
-
-/*- Restore SPSR_irq and r0 from IRQ stack */
- ldmia sp!, {r0}
-
-/*- Restore SPSR_irq and r0 from IRQ stack */
- ldmia sp!, {r14}
- msr SPSR_cxsf, r14
-
-/*- Restore adjusted LR_irq from IRQ stack directly in the PC */
- ldmia sp!, {pc}^
-
- .size IRQ_Handler_EntryR, . - IRQ_Handler_EntryR
- .endfunc
-
- .global remap
- .func remap
-_remap:
-# led1on
-# Remap RAM to 0x00000000 for DFU
+ .global _remap_call_dfu
+ .func _remap_call_dfu
+_remap_call_dfu:
+ led1on
+ /* Remap RAM to 0x00000000 for DFU */
ldr r1, =AT91C_BASE_AIC
mov r2, #0x01
str r2, [r1, #AIC_MCR_RCR]
+
+ ldr r4, =dfu_main
+ bx r4
- /* prepare c function call to main */
- mov r0, #0 /* argc = 0 */
- ldr lr,=exit
- ldr r10,=main
-
-#ifdef CONFIG_DFU_SWITCH
- /* check whether bootloader button is pressed */
- ldr r1, =AT91C_PMC_PCER
- mov r2, #(1 << AT91C_ID_PIOA)
- str r2, [r1]
-
- ldr r1, =AT91C_BASE_PIOA
- ldr r2, [r1, #PIOA_PDSR]
- tst r2, #PIO_BOOTLDR
- ldrne r10,=dfu_main
-#endif
-
- bx r10
- .size remap, . - remap
+ .size _remap_call_dfu, . - _remap_call_dfu
.endfunc
-/* "exit" dummy added by mthomas to avoid sbrk write read etc. needed
- by the newlib default "exit" */
- .global exit
- .func exit
-exit:
- b .
- .size exit, . - exit
- .endfunc
-
-/*---------------------------------------------------------------
-//* ?EXEPTION_VECTOR
-//* This module is only linked if needed for closing files.
-//*---------------------------------------------------------------*/
- .global AT91F_Default_FIQ_handler
- .func AT91F_Default_FIQ_handler
-AT91F_Default_FIQ_handler:
- b AT91F_Default_FIQ_handler
- .size AT91F_Default_FIQ_handler, . - AT91F_Default_FIQ_handler
- .endfunc
-
- .global AT91F_Default_IRQ_handler
- .func AT91F_Default_IRQ_handler
-AT91F_Default_IRQ_handler:
- b AT91F_Default_IRQ_handler
- .size AT91F_Default_IRQ_handler, . - AT91F_Default_IRQ_handler
- .endfunc
-
- .global AT91F_Spurious_handler
- .func AT91F_Spurious_handler
-AT91F_Spurious_handler:
- b AT91F_Spurious_handler
- .size AT91F_Spurious_handler, . - AT91F_Spurious_handler
- .endfunc
-
-
#;------------------------------------------------------------------------------
#;- Section Definition
@@ -255,9 +112,6 @@ Top_Stack:
* .text is used instead of .section .text so it works with arm-aout too. */
.section .reset
.text
- .global _startup
- .func _startup
-_startup:
reset:
/*------------------------------------------------------------------------------
//*- Exception vectors
@@ -277,17 +131,108 @@ swivec:
pabtvec:
B pabtvec /* 0x0C Prefetch Abort */
dabtvec:
- B dabtvec /* 0x10 Data Abort */
+ b dabtvec /* 0x10 Data Abort */
rsvdvec:
- B rsvdvec /* 0x14 reserved */
+ b rsvdvec /* 0x14 reserved */
irqvec:
- B irqvec /* 0x18 IRQ */
-fiqvec:
- B fiqvec /* 0x1c FIQ */
+ b IRQ_Handler_Entry /* 0x18 IRQ */
+fiqvec:
+ b FIQ_Handler_Entry
+ /* 0x1c FIQ */
+dfu_state_dummy:
+ .word 0
+
+FIQ_Handler_Entry:
+
+/*- Switch in SVC/User Mode to allow User Stack access for C code */
+/* because the FIQ is not yet acknowledged*/
+
+/*- Save and r0 in FIQ_Register */
+ mov r9, r0
+ ldr r0, [r8, #AIC_FVR]
+ msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_SVC
+
+ /*- Save scratch/used registers and LR in User Stack */
+ stmfd sp!, { r1-r3, r12, lr}
+
+ /*- Branch to the routine pointed by the AIC_FVR */
+ mov r14, pc
+ bx r0
+
+ /*- Restore scratch/used registers and LR from User Stack */
+ ldmia sp!, { r1-r3, r12, lr}
+
+ /*- Leave Interrupts disabled and switch back in FIQ mode */
+ msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ
+
+ /*- Restore the R0 ARM_MODE_SVC register */
+ mov r0,r9
+
+ /*- Restore the Program Counter using the LR_fiq directly in the PC */
+ subs pc, lr, #4
+
+ .global IRQ_Handler_Entry
+ .func IRQ_Handler_Entry
+
+IRQ_Handler_Entry:
+
+ /*- Manage Exception Entry */
+ /*- Adjust and save LR_irq in IRQ stack */
+ sub lr, lr, #4
+ stmfd sp!, {lr}
+
+ /*- Save SPSR need to be saved for nested interrupt */
+ mrs r14, SPSR
+ stmfd sp!, {r14}
+
+ /*- Save and r0 in IRQ stack */
+ stmfd sp!, {r0}
+
+ /*- Write in the IVR to support Protect Mode */
+ /*- No effect in Normal Mode */
+ /*- De-assert the NIRQ and clear the source in Protect Mode */
+ ldr r14, =AT91C_BASE_AIC
+ ldr r0 , [r14, #AIC_IVR]
+ str r14, [r14, #AIC_IVR]
+
+ /*- Enable Interrupt and Switch in Supervisor Mode */
+ msr CPSR_c, #ARM_MODE_SVC
+
+ /*- Save scratch/used registers and LR in User Stack */
+ stmfd sp!, { r1-r3, r12, r14}
+
+ /*- Branch to the routine pointed by the AIC_IVR */
+ mov r14, pc
+ bx r0
+
+ /*- Restore scratch/used registers and LR from User Stack*/
+ ldmia sp!, { r1-r3, r12, r14}
+
+ /*- Disable Interrupt and switch back in IRQ mode */
+ msr CPSR_c, #I_BIT | ARM_MODE_IRQ
+
+ /*- Mark the End of Interrupt on the AIC */
+ ldr r14, =AT91C_BASE_AIC
+ str r14, [r14, #AIC_EOICR]
+
+ /*- Restore SPSR_irq and r0 from IRQ stack */
+ ldmia sp!, {r0}
+
+ /*- Restore SPSR_irq and r0 from IRQ stack */
+ ldmia sp!, {r14}
+ msr SPSR_cxsf, r14
+
+ /*- Restore adjusted LR_irq from IRQ stack directly in the PC */
+ ldmia sp!, {pc}^
+
+ .size IRQ_Handler_Entry, . - IRQ_Handler_Entry
+ .endfunc
.align 0
.RAM_TOP:
.word Top_Stack
+ .global _startup
+ .func _startup
InitReset:
/*------------------------------------------------------------------------------
/*- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit
@@ -348,16 +293,7 @@ InitReset:
msr CPSR_c, #ARM_MODE_SVC
mov r13, r0 /* Init stack Sup */
-/*- Relocate DFU .data section (Copy from ROM to RAM)*/
- ldr r1, =_etext_dfu
- ldr r2, =_data_dfu
- ldr r3, =_edata_dfu
-LoopRelDFU: cmp r2, r3
- ldrlo r0, [r1], #4
- strlo r0, [r2], #4
- blo LoopRelDFU
-
-# Relocate .data section (Copy from ROM to RAM)
+# Relocate DFU .data section (Copy from ROM to RAM)
LDR R1, =_etext
LDR R2, =_data
LDR R3, =_edata
@@ -366,7 +302,7 @@ LoopRel: CMP R2, R3
STRLO R0, [R2], #4
BLO LoopRel
-# Clear .bss section (Zero init)
+# Clear DFU .bss section (Zero init)
MOV R0, #0
LDR R1, =__bss_start__
LDR R2, =__bss_end__
@@ -374,13 +310,75 @@ LoopZI: CMP R1, R2
STRLO R0, [R1], #4
BLO LoopZI
- led1on
+ /* prepare c function call to main */
+ mov r0, #0 /* argc = 0 */
+ ldr lr, =exit
+ ldr r10, =0x00101000
- ldr r0, =_remap
- bx r0
+#ifdef CONFIG_DFU_SWITCH
+ /* check whether bootloader button is pressed */
+ ldr r1, =AT91C_PMC_PCER
+ mov r2, #(1 << AT91C_ID_PIOA)
+ str r2, [r1]
+ ldr r1, =AT91C_BASE_PIOA
+ ldr r2, [r1, #PIOA_PDSR]
+ tst r2, #PIO_BOOTLDR
+ bne _reloc_dfu_text
+#endif
+
+ bx r10
+
+_reloc_dfu_text:
+
+ ldr r1, =0x00100000
+ ldr r2, =0x00200000
+ ldr r3, =_etext
+ add r3, r3, r2
+loop_rel_t: cmp r2, r3
+ ldrlo r4, [r1], #4
+ strlo r4, [r2], #4
+ blo loop_rel_t
+ ldr r4, =_remap_call_dfu
+ bx r4
+
.size _startup, . - _startup
.endfunc
-
+
+/* "exit" dummy to avoid sbrk write read etc. needed by the newlib default "exit" */
+ .global exit
+ .func exit
+exit:
+ b .
+ .size exit, . - exit
+ .endfunc
+
+/*---------------------------------------------------------------
+//* ?EXEPTION_VECTOR
+//* This module is only linked if needed for closing files.
+//*---------------------------------------------------------------*/
+ .global AT91F_Default_FIQ_handler
+ .func AT91F_Default_FIQ_handler
+AT91F_Default_FIQ_handler:
+ b AT91F_Default_FIQ_handler
+ .size AT91F_Default_FIQ_handler, . - AT91F_Default_FIQ_handler
+ .endfunc
+
+ .global AT91F_Default_IRQ_handler
+ .func AT91F_Default_IRQ_handler
+AT91F_Default_IRQ_handler:
+ b AT91F_Default_IRQ_handler
+ .size AT91F_Default_IRQ_handler, . - AT91F_Default_IRQ_handler
+ .endfunc
+
+ .global AT91F_Spurious_handler
+ .func AT91F_Spurious_handler
+AT91F_Spurious_handler:
+ b AT91F_Spurious_handler
+ .size AT91F_Spurious_handler, . - AT91F_Spurious_handler
+ .endfunc
+
+
+
.end
diff --git a/firmware/src/start/Cstartup_app.S b/firmware/src/start/Cstartup_app.S
new file mode 100644
index 0000000..4a2187a
--- /dev/null
+++ b/firmware/src/start/Cstartup_app.S
@@ -0,0 +1,81 @@
+/* Cstartup header for the application to be started by at91dfu
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> */
+
+//#define DEBUG_LL
+
+#ifdef DEBUG_LL
+/* Debugging macros for switching on/off LED1 (green) */
+#define PIOA_PER 0xFFFFF400
+#define PIOA_OER 0xFFFFF410
+#define PIOA_SODR 0xFFFFF430
+#define PIOA_CODR 0xFFFFF434
+#define LED1 25 /* this only works on OpenPICC, not Olimex */
+ .macro led1on
+ ldr r2, =PIOA_CODR
+ mov r1, #(1 << LED1)
+ str r1, [r2]
+ .endm
+ .macro led1off
+ ldr r2, =PIOA_SODR
+ mov r1, #(1 << LED1)
+ str r1, [r2]
+ .endm
+ .macro ledinit
+ ldr r2, =PIOA_PER
+ mov r1, #(1 << LED1)
+ str r1, [r2]
+ ldr r2, =PIOA_OER
+ str r1, [r2]
+ led1off
+ .endm
+#else
+ .macro ledinit
+ .endm
+ .macro led1on
+ .endm
+ .macro led1off
+ .endm
+#endif
+
+ .global _startup
+ .func _startup
+_startup:
+ /* Relocate .data section (copy from Flash to RAM) */
+ ldr r1, =_etext
+ ldr r2, =_data
+ ldr r3, =_edata
+loop_r: cmp r2, r3
+ ldrlo r0, [r1], #4
+ strlo r0, [r2], #4
+ blo loop_r
+
+ /* Clear .bss section (Zero init) */
+ mov r0, #0
+ ldr r1, =__bss_start__
+ ldr r2, =__bss_end__
+loop_z: cmp r1, r2
+ strlo r0, [r1], #4
+ blo loop_z
+
+ led1on
+
+ /* prepare C function call to main */
+ mov r0, #0 /* argc = 0 */
+ ldr lr, =exit
+ ldr r10, =main
+
+ bx r10
+
+ .size _startup, . - _startup
+ .endfunc
+
+/* "exit" dummy to avoid sbrk write read etc. needed by the newlib default "exit" */
+ .global exit
+ .func exit
+exit:
+ b .
+ .size exit, . - exit
+ .endfunc
+
+ .end
+
personal git repositories of Harald Welte. Your mileage may vary