diff --git a/LM4F.ld b/LM4F.ld index e347c9b..7458d81 100644 --- a/LM4F.ld +++ b/LM4F.ld @@ -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 . -* Version: 1.0.0. -* Description: Linker description file for LM4FXXX microcontrollers. +Thumb2 Newlib Toolchain example project +Written by Elias Önal , 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 = .; diff --git a/LM4F_startup.c b/LM4F_startup.c index 2cee0bf..177f907 100644 --- a/LM4F_startup.c +++ b/LM4F_startup.c @@ -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 @@ -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; } @@ -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){ } @@ -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){ } } diff --git a/Makefile b/Makefile index ae78105..37f4a5b 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -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= diff --git a/main.c b/main.c index d389068..8b3ec70 100644 --- a/main.c +++ b/main.c @@ -39,6 +39,10 @@ #include "driverlib/sysctl.h" #include "driverlib/interrupt.h" #include "driverlib/timer.h" +#include "driverlib/uart.h" + +#include +#include // Basically here I'm checking that everything works fine. volatile unsigned long count; @@ -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); @@ -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++; } diff --git a/newlib_stubs.c b/newlib_stubs.c index 6eb5f25..9835556 100644 --- a/newlib_stubs.c +++ b/newlib_stubs.c @@ -32,9 +32,6 @@ #undef errno extern int errno; -extern unsigned int _HEAP_START; -extern unsigned int _HEAP_END; -static caddr_t heap = NULL ; /* environ @@ -80,7 +77,6 @@ int _fork() { The `sys/stat.h' header file required is distributed in the `include' subdirectory for this C library. */ int _fstat(int file, struct stat *st) { - UARTprintf("_fstat\n"); st->st_mode = S_IFCHR; return 0; } @@ -99,7 +95,6 @@ int _getpid() { Query whether output stream is a terminal. For consistency with the other minimal implementations, */ int _isatty(int file) { - UARTprintf("_isatty\n"); switch (file){ case STDOUT_FILENO: case STDERR_FILENO: @@ -147,30 +142,28 @@ int _lseek(int file, int ptr, int dir) { Increase program data space. Malloc and related functions depend on this */ -caddr_t _sbrk(int increment) { - UARTprintf("_sbrk"); +caddr_t _sbrk(int incr) { + extern char _end; // Defined in linkerscript, end of .data and .bss - caddr_t prevHeap, nextHeap; + static char *heap_end; + char *prev_heap_end; + extern char _estack; + extern char _sstack; - if (heap == NULL) - { - heap = (caddr_t)&_HEAP_START; + if (heap_end == NULL) { + heap_end = &_end; } - - prevHeap = heap; - nextHeap = (caddr_t)(((unsigned int)(heap + increment) + 7) & ~7); - register caddr_t stackPtr __asm ("sp"); - - if ( (nextHeap > stackPtr) || - (nextHeap >= (caddr_t)&_HEAP_END)) + prev_heap_end = heap_end; + if((((uint32_t)heap_end) + ((uint32_t)incr)) + > ((uint32_t)&_sstack)) // stack protection { - return NULL; // error - no more memory - } else - { - heap = nextHeap; - return (caddr_t) prevHeap; + errno = ENOMEM; + return (void*) -1; } + heap_end += incr; + return (void*) prev_heap_end; + } /* @@ -184,7 +177,6 @@ int _read(int file, char *ptr, int len) { int n; int num = 0; char c; - UARTprintf("_read"); switch (file) { case STDIN_FILENO: @@ -251,7 +243,6 @@ int _wait(int *status) { int _write(int file, char *ptr, int len) { int n; - UARTprintf("_write\n"); switch (file) { case STDOUT_FILENO: /*stdout*/