Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 52 additions & 98 deletions LM4F.ld
Original file line number Diff line number Diff line change
@@ -1,111 +1,65 @@
/*
* Copyright (c) 2012, Mauro Scomparin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Mauro Scomparin nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Mauro Scomparin ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Mauro Scomparin BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: LM4F.ld.
* Author: Mauro Scomparin <http://scompoprojects.worpress.com>.
* Version: 1.0.0.
* Description: Linker description file for LM4FXXX microcontrollers.
Thumb2 Newlib Toolchain example project
Written by Elias Önal <[email protected]>, released as public domain.

This is a minimal linkerscript that should be easy to port to new microcontrollers.
At this point it supports only C and will lead to weird behavior when used for C++.
*/

ENTRY(rst_handler)

/*
* Memory definition:
* FLASH: start point 0x00, lenght 0x40000.
* SRAM: start point 0x20000000 length 0x8000.
* STACK: start point 0x20007FFF lenght 0x0.
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
STACK (rwx) : ORIGIN = 0x20007FFF , LENGTH = 0x00000000
}

/*
* Sections definitions:
*
* .text - machine instructions.
* .data - initialized data defined in the program.
* .bss - un-initialized global and static variables (to be initialized to 0 before starting main).
* .stack - just contains the pointer to the stack end at the right place.
*/
SECTIONS
{
/* This section it's the code, containing the NVIC Vector table that must start at 0x0
* Look at the LM4F120H5QR datasheet for details. (Table 2-8. Exception Types)
*/
.text :
{
/*_start_text = .; /* This is an index to the beginning of .text segment. */
KEEP(*(.nvic_table)) /* I should keep the NVIC ISR Table because it's needed by the processor to start. */
*(.text.*) /* This contains the code after the ISR table. */
*(.rodata*) /* Read only data. */
/*_end_text = .; */ /* This is an index to the end of .text segment. */
}>FLASH

_end_text = ALIGN(8);

/*
* .data segment must be placed in RAM but it's originally stored in FLASH
* So I set the data segment in ram, but I specify the load address with the AT
* keyword to set that right after the .text section.
* (Look at the LD documentation. (Optional Section Attributes))
* Thanks https://github.com/utzig for the hints!
*/
.data :
{
_start_data = .; /* An index to the beginning of .data segment. */
*(vtable) /* vtable should be the volatile data I guess*/
*(.data.*) /* I should put there all my initialized data of my program. */
_end_data = .; /* And another index to the end of .data segment. */
}>RAM AT >FLASH

FLASH (rx) : ORIGIN = 0x0000000, LENGTH = 0x00040000
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

/*
* .bss contains the unitialized variables and must be set as 0x0 during runtime.
* It should be loaded in RAM and particula care should be taken initializing them in the startup file.
*/
.bss :
{
_start_bss = .; /* This is an index to the beginning of .bss segment. */
*(.bss.*) /* The un-initialized data should go there. */
*(COMMON) /* All the other stuff should be put there */
_end_bss = .; /* End index for .bss segment */
}>RAM
_estack = 0x20008000; /* Upper stack boundary */
_sstack = (_estack - 512); /* Lower stack boundary */

PROVIDE( _HEAP_START = _end_bss);
PROVIDE( _HEAP_END = ALIGN(ORIGIN(RAM) + LENGTH(RAM) -8,8) );
SECTIONS {
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH

/*
* .stack contains nothing, but I use it to set the first vector item (SP R13).
*/
.stack :
.text :
{
_stack_top = .; /* An index to the end of the stack */
}>STACK
. = ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
_etext = .;
_sidata = _etext;
} > FLASH

.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = . ;
_data = . ;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = . ;
} >RAM

.bss :
{
. = ALIGN(4);
_sbss = .;
_bss = .;
*(.bss)
*(.bss.*)
. = ALIGN(4);
_ebss = . ;
} >RAM
}

. = ALIGN(4);
end = .;
_end = .;
61 changes: 31 additions & 30 deletions LM4F_startup.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,26 @@ void hardfault_handler(unsigned int * hardfault_args) ;
//-----------------------------------------------------------------------------

// defined by the linker it's the stack top variable (End of ram)
extern unsigned long _stack_top;
extern unsigned long _estack;
// defined by the liker, this are just start and end marker for each section.
// .text (code)
extern unsigned long _start_text;
extern unsigned long _end_text;
extern unsigned long _stext;
extern unsigned long _etext;
// .data (data to be copied on ram)
extern unsigned long _start_data;
extern unsigned long _end_data;
extern unsigned long _sdata;
extern unsigned long _edata;
// .bss (uninitialized data to set to 0);
extern unsigned long _start_bss;
extern unsigned long _end_bss;
extern unsigned long _sbss;
extern unsigned long _ebss;

// NVIC ISR table
// the funny looking void(* myvectors[])(void) basically it's a way to make cc accept an array of function pointers.
__attribute__ ((section(".nvic_table")))
__attribute__ ((section(".isr_vector")))
void(* myvectors[])(void) = {
// This are the fixed priority interrupts and the stack pointer loaded at startup at R13 (SP).
// VECTOR N (Check Datasheet)
// here the compiler it's boring.. have to figure that out
(void (*)) &_stack_top,
(void (*)) &_estack,
// stack pointer should be
// placed here at startup. 0
rst_handler, // code entry point 1
Expand Down Expand Up @@ -255,18 +255,19 @@ void rst_handler(void){
unsigned long *dest;

//this should be good!
src = &_end_text;
dest = &_start_data;
src = &_etext;

dest = &_sdata;

//this too
while(dest < &_end_data)
while(dest < &_edata)
{
*dest++ = *src++;
}

// now set the .bss segment to 0!
dest = &_start_bss;
while(dest < &_end_bss){
dest = &_sbss;
while(dest < &_ebss){
*dest++ = 0;
}

Expand All @@ -293,7 +294,7 @@ void rst_handler(void){

// NMI Exception handler code NVIC 2
void nmi_handler(void){
UARTprintf("NMI Exception\n");
printf("NMI Exception\n");
// Just loop forever, so if you want to debug the processor it's running.
while(1){
}
Expand Down Expand Up @@ -323,27 +324,27 @@ void hardfault_handler( unsigned int * hardfault_args ){
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);

UARTprintf ("\n\n[Hard fault handler - all numbers in hex]\n");
UARTprintf ("R0 = %x\n", stacked_r0);
UARTprintf ("R1 = %x\n", stacked_r1);
UARTprintf ("R2 = %x\n", stacked_r2);
UARTprintf ("R3 = %x\n", stacked_r3);
UARTprintf ("R12 = %x\n", stacked_r12);
UARTprintf ("LR [R14] = %x subroutine call return address\n", stacked_lr);
UARTprintf ("PC [R15] = %x program counter\n", stacked_pc);
UARTprintf ("PSR = %x\n", stacked_psr);
UARTprintf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));
UARTprintf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));
UARTprintf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));
UARTprintf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));
UARTprintf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
printf ("\n\n[Hard fault handler - all numbers in hex]\n");
printf ("R0 = %x\n", stacked_r0);
printf ("R1 = %x\n", stacked_r1);
printf ("R2 = %x\n", stacked_r2);
printf ("R3 = %x\n", stacked_r3);
printf ("R12 = %x\n", stacked_r12);
printf ("LR [R14] = %x subroutine call return address\n", stacked_lr);
printf ("PC [R15] = %x program counter\n", stacked_pc);
printf ("PSR = %x\n", stacked_psr);
printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));
printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));
printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));
printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));
printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
while (1) { };
}

// Empty handler used as default.
void empty_def_handler(void){
// Just loop forever, so if you want to debug the processor it's running.
UARTprintf("UNKNOWN Exception\n");
printf("UNKNOWN Exception\n");
while(1){
}
}
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ CPU=-mcpu=cortex-m4
FPU=-mfpu=fpv4-sp-d16 -mfloat-abi=softfp

# Stellarisware path
STELLARISWARE_PATH=~/stellaris/stellaris/
STELLARISWARE_PATH=~/stellaris/stellarisware/

# Program name definition for ARM GNU C compiler.
CC = ${PREFIX_ARM}-gcc
Expand Down Expand Up @@ -72,13 +72,16 @@ ODFLAGS = -S
# I can get them from the gcc frontend, using some options.
# See gcc documentation
LIB_GCC_PATH=${shell ${CC} ${CFLAGS} -print-libgcc-file-name}
LIBC_PATH=${shell ${CC} ${CFLAGS} -print-file-name=libc.a}
LIBM_PATH=${shell ${CC} ${CFLAGS} -print-file-name=libm.a}
#LIBC_PATH=${shell ${CC} ${CFLAGS} -print-file-name=libc.a}
#LIBM_PATH=${shell ${CC} ${CFLAGS} -print-file-name=libm.a}
LIBC_PATH=/home/cypher/stellaris/newlib/arm-none-eabi/lib/thumb2/libc.a
LIBM_PATH=/home/cypher/stellaris/newlib/arm-none-eabi/lib/thumb2/libm.a


# Uploader tool path.
# Set a relative or absolute path to the upload tool program.
# I used this project: https://github.com/utzig/lm4tools
FLASHER=~/stellaris/lm4tools/lm4flash/lm4flash
FLASHER=lm4flash
# Flags for the uploader program.
FLASHER_FLAGS=

Expand Down
27 changes: 26 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"

#include <stdio.h>
#include <stdlib.h>

// Basically here I'm checking that everything works fine.
volatile unsigned long count;
Expand All @@ -49,7 +53,27 @@ void Timer1A_ISR(void);
// main function.
int main(void) {
SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

SysCtlPeripheralEnable( SYSCTL_PERIPH_UART0);
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
(UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE | UART_CONFIG_WLEN_8));
UARTEnable(UART0_BASE);


SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

unsigned char* test = malloc(1024); // ask for a kb
int i;
for (i=0; i<10; i++)
test[i] = i+0x30;
test[i]=0;
printf("test string: %s\r\n", test);
free(test); // didnt want it...

SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);
TimerControlStall(TIMER1_BASE, TIMER_A, true);
TimerLoadSet(TIMER1_BASE, TIMER_A, 2111);
Expand All @@ -66,5 +90,6 @@ int main(void) {
// The interrupt function definition.
void Timer1A_ISR(void){
TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
printf("Timer interrupt %d\r\n",count);
count++;
}
Loading