I am trying to use LLVM to generate code for baremetal ARM Cortex M4 development. The creation of the IR is going well and LLVM is generating (in my oppinion) correct ARM Thumb ASM.
I have purchased an Arm dev kit to do some testing: an Atmel SAM4L-EK http://www.atmel.com/tools/SAM4L-EK.aspx
I created an application that turns on the yellow led on the dev board. (I just want to get something out of the board) I ran an included app with Atmel Studio and the LED works fine. But my application seems to do nothing...
Acording to the manual the LED is connected to PC10 In the datasheet of the ATSAM4LC4C MCU it says that address of the GPIO ports is 0x400E1000, one port takes 0x0200 byes of address space so port C is on 0x400E1000 + 0x0400.
So this is the program output I have (LLVM Output):
.syntax unified
.eabi_attribute 6, 10
.eabi_attribute 9, 2
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 44, 1
.file ""
.text
.globl main
.align 2
.type main,%function
.code 16
.thumb_func
main:
movw r0, #5120
movw r2, #5184
movw r3, #5200
mov.w r1, #1024
movt r0, #16398
movt r2, #16398
movt r3, #16398
.LBB0_1:
str r1, [r0]
str r1, [r2]
str r1, [r3]
b .LBB0_1
.Ltmp0:
.size main, .Ltmp0-main
This code sets bit 10 in GPIOEnableRegister to 1
then bit 10 in OutputDriverEnableRegister to 1
then bit 10 in OutputValueRegister to 1
At that point the LED should turn on...
This is the startup code I used:
.section INTERRUPT_VECTOR, "x"
.global _Reset
_Reset:
B Reset_Handler /* Reset */
B . /* Undefined */
B . /* SWI */
B . /* Prefetch Abort */
B . /* Data Abort */
B . /* reserved */
B . /* IRQ */
B . /* FIQ */
Reset_Handler:
#mov r0, stack_top
MOV sp,r0
BL main
B .
Both assembler files were compiled to object files like this:
as -mcpu=cortex-m4 -g startup.s -o startup.o
Using the GNU ARM assembler
This is the linker script I used:
ENTRY(_Reset)
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* flash, 256K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */
}
SECTIONS
{
. = 0x0;
.text : {
startup.o (INTERRUPT_VECTOR)
*(.text)
}
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);0
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}
Then the object files were linked to an ELF binary like this:
ld -T linkerscript.ld armtest.o startup.o -o armtest.elf
using the GNU Arm Linker
I then uploaded the ELF binary to the board using Atmel Studio
Bot nothing happens (also not after a reset)
Any insights would greatly appreciated!
the cortex-m series does not boot like a non-cortex-m series arm. the cortex-m has a (non arm) traditional interrupt vector table approach rather than a table of instructions like the full sized arms.
/* vectors.s */
.thumb
.word 0x20020000 /* stack top address */
.word _start /* 1 Reset */
.word hang /* 2 NMI */
.word hang /* 3 HardFault */
.word hang /* 4 MemManage */
.word hang /* 5 BusFault */
.word hang /* 6 UsageFault */
.word hang /* 7 RESERVED */
.word hang /* 8 RESERVED */
.word hang /* 9 RESERVED*/
.word hang /* 10 RESERVED */
.word hang /* 11 SVCall */
.word hang /* 12 Debug Monitor */
.word hang /* 13 RESERVED */
.word hang /* 14 PendSV */
.word hang /* 15 SysTick */
.word hang /* 16 External Interrupt(0) */
.word hang /* 17 External Interrupt(1) */
.word hang /* 18 External Interrupt(2) */
.word hang /* 19 ... */
.thumb_func
.global _start
_start:
/*ldr r0,stacktop */
/*mov sp,r0*/
bl notmain
b hang
.thumb_func
hang: b .
You need to set the stack top address as the first item specific to your processor. And using llvm you might need to tweak a few directives here, the above was for gnu.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With