new lib adapted to folder structure
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
|
||||
The following files extend or replace some of the the newlib functionality:
|
||||
|
||||
_startup.c: a customised startup sequence, written in C
|
||||
|
||||
_exit.c: a customised exit() implementation
|
||||
|
||||
_syscalls.c: local versions of the libnosys/librdimon code
|
||||
|
||||
_sbrk.c: a custom _sbrk() to match the actual linker scripts
|
||||
|
||||
assert.c: implementation for the asserion macros
|
||||
|
||||
_cxx.cpp: local versions of some C++ support, to avoid references to
|
||||
large functions.
|
||||
|
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// This file is part of the µOS++ III distribution.
|
||||
// Copyright (c) 2014 Liviu Ionescu.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// These functions are redefined locally, to avoid references to some
|
||||
// heavy implementations in the standard C++ library.
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sys/types.h>
|
||||
#include "diag/Trace.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
void
|
||||
__attribute__((noreturn))
|
||||
__verbose_terminate_handler();
|
||||
|
||||
void
|
||||
__verbose_terminate_handler()
|
||||
{
|
||||
trace_puts(__func__);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void
|
||||
__attribute__((noreturn))
|
||||
__cxa_pure_virtual();
|
||||
|
||||
void
|
||||
__cxa_pure_virtual()
|
||||
{
|
||||
trace_puts(__func__);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
59
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_exit.c
Normal file
59
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_exit.c
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// This file is part of the µOS++ III distribution.
|
||||
// Copyright (c) 2014 Liviu Ionescu.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "diag/Trace.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if !defined(DEBUG)
|
||||
extern void
|
||||
__attribute__((noreturn))
|
||||
__reset_hardware(void);
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Forward declaration
|
||||
|
||||
void
|
||||
_exit(int code);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// On Release, call the hardware reset procedure.
|
||||
// On Debug we just enter an infinite loop, to be used as landmark when halting
|
||||
// the debugger.
|
||||
//
|
||||
// It can be redefined in the application, if more functionality
|
||||
// is required.
|
||||
|
||||
void
|
||||
__attribute__((weak))
|
||||
_exit(int code __attribute__((unused)))
|
||||
{
|
||||
#if !defined(DEBUG)
|
||||
__reset_hardware();
|
||||
#endif
|
||||
|
||||
// TODO: write on trace
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
__attribute__((weak,noreturn))
|
||||
abort(void)
|
||||
{
|
||||
trace_puts("abort(), exiting...");
|
||||
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
65
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_sbrk.c
Normal file
65
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_sbrk.c
Normal file
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// This file is part of the µOS++ III distribution.
|
||||
// Copyright (c) 2014 Liviu Ionescu.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
caddr_t
|
||||
_sbrk(int incr);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// The definitions used here should be kept in sync with the
|
||||
// stack definitions in the linker script.
|
||||
|
||||
caddr_t
|
||||
_sbrk(int incr)
|
||||
{
|
||||
extern char _Heap_Begin; // Defined by the linker.
|
||||
extern char _Heap_Limit; // Defined by the linker.
|
||||
|
||||
static char* current_heap_end;
|
||||
char* current_block_address;
|
||||
|
||||
if (current_heap_end == 0)
|
||||
{
|
||||
current_heap_end = &_Heap_Begin;
|
||||
}
|
||||
|
||||
current_block_address = current_heap_end;
|
||||
|
||||
// Need to align heap to word boundary, else will get
|
||||
// hard faults on Cortex-M0. So we assume that heap starts on
|
||||
// word boundary, hence make sure we always add a multiple of
|
||||
// 4 to it.
|
||||
incr = (incr + 3) & (~3); // align value to 4
|
||||
if (current_heap_end + incr > &_Heap_Limit)
|
||||
{
|
||||
// Some of the libstdc++-v3 tests rely upon detecting
|
||||
// out of memory errors, so do not abort here.
|
||||
#if 0
|
||||
extern void abort (void);
|
||||
|
||||
_write (1, "_sbrk: Heap and stack collision\n", 32);
|
||||
|
||||
abort ();
|
||||
#else
|
||||
// Heap has overflowed
|
||||
errno = ENOMEM;
|
||||
return (caddr_t) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
current_heap_end += incr;
|
||||
|
||||
return (caddr_t) current_block_address;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
327
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_startup.c
Normal file
327
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_startup.c
Normal file
@@ -0,0 +1,327 @@
|
||||
//
|
||||
// This file is part of the µOS++ III distribution.
|
||||
// Copyright (c) 2014 Liviu Ionescu.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This module contains the startup code for a portable embedded
|
||||
// C/C++ application, built with newlib.
|
||||
//
|
||||
// Control reaches here from the reset handler via jump or call.
|
||||
//
|
||||
// The actual steps performed by _start are:
|
||||
// - copy the initialised data region(s)
|
||||
// - clear the BSS region(s)
|
||||
// - initialise the system
|
||||
// - run the preinit/init array (for the C++ static constructors)
|
||||
// - initialise the arc/argv
|
||||
// - branch to main()
|
||||
// - run the fini array (for the C++ static destructors)
|
||||
// - call _exit(), directly or via exit()
|
||||
//
|
||||
// If OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS is defined, the
|
||||
// code is capable of initialising multiple regions.
|
||||
//
|
||||
// The normal configuration is standalone, with all support
|
||||
// functions implemented locally.
|
||||
//
|
||||
// For this to be called, the project linker must be configured without
|
||||
// the startup sequence (-nostartfiles).
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if !defined(OS_INCLUDE_STARTUP_GUARD_CHECKS)
|
||||
#define OS_INCLUDE_STARTUP_GUARD_CHECKS (1)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if !defined(OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS)
|
||||
// Begin address for the initialisation values of the .data section.
|
||||
// defined in linker script
|
||||
extern unsigned int _sidata;
|
||||
// Begin address for the .data section; defined in linker script
|
||||
extern unsigned int _sdata;
|
||||
// End address for the .data section; defined in linker script
|
||||
extern unsigned int _edata;
|
||||
|
||||
// Begin address for the .bss section; defined in linker script
|
||||
extern unsigned int __bss_start__;
|
||||
// End address for the .bss section; defined in linker script
|
||||
extern unsigned int __bss_end__;
|
||||
#else
|
||||
// The following symbols are constructs generated by the linker, indicating
|
||||
// the location of various points in the "Memory regions initialisation arrays".
|
||||
// These arrays are created by the linker via the managed linker script
|
||||
// of each RW data mechanism. It contains the load address, execution address
|
||||
// and length section and the execution and length of each BSS (zero
|
||||
// initialised) section.
|
||||
extern unsigned int __data_regions_array_start;
|
||||
extern unsigned int __data_regions_array_end;
|
||||
extern unsigned int __bss_regions_array_start;
|
||||
extern unsigned int __bss_regions_array_end;
|
||||
#endif
|
||||
|
||||
extern void
|
||||
__initialize_args (int*, char***);
|
||||
|
||||
// main() is the entry point for newlib based applications.
|
||||
// By default, there are no arguments, but this can be customised
|
||||
// by redefining __initialize_args(), which is done when the
|
||||
// semihosting configurations are used.
|
||||
extern int
|
||||
main (int argc, char* argv[]);
|
||||
|
||||
// The implementation for the exit routine; for embedded
|
||||
// applications, a system reset will be performed.
|
||||
extern void
|
||||
__attribute__((noreturn))
|
||||
_exit (int);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Forward declarations
|
||||
|
||||
void
|
||||
_start (void);
|
||||
|
||||
void
|
||||
__initialize_data (unsigned int* from, unsigned int* region_begin,
|
||||
unsigned int* region_end);
|
||||
|
||||
void
|
||||
__initialize_bss (unsigned int* region_begin, unsigned int* region_end);
|
||||
|
||||
void
|
||||
__run_init_array (void);
|
||||
|
||||
void
|
||||
__run_fini_array (void);
|
||||
|
||||
void
|
||||
__initialize_hardware_early (void);
|
||||
|
||||
void
|
||||
__initialize_hardware (void);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
inline void
|
||||
__attribute__((always_inline))
|
||||
__initialize_data (unsigned int* from, unsigned int* region_begin,
|
||||
unsigned int* region_end)
|
||||
{
|
||||
// Iterate and copy word by word.
|
||||
// It is assumed that the pointers are word aligned.
|
||||
unsigned int *p = region_begin;
|
||||
while (p < region_end)
|
||||
*p++ = *from++;
|
||||
}
|
||||
|
||||
inline void
|
||||
__attribute__((always_inline))
|
||||
__initialize_bss (unsigned int* region_begin, unsigned int* region_end)
|
||||
{
|
||||
// Iterate and clear word by word.
|
||||
// It is assumed that the pointers are word aligned.
|
||||
unsigned int *p = region_begin;
|
||||
while (p < region_end)
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
// These magic symbols are provided by the linker.
|
||||
extern void
|
||||
(*__preinit_array_start[]) (void) __attribute__((weak));
|
||||
extern void
|
||||
(*__preinit_array_end[]) (void) __attribute__((weak));
|
||||
extern void
|
||||
(*__init_array_start[]) (void) __attribute__((weak));
|
||||
extern void
|
||||
(*__init_array_end[]) (void) __attribute__((weak));
|
||||
extern void
|
||||
(*__fini_array_start[]) (void) __attribute__((weak));
|
||||
extern void
|
||||
(*__fini_array_end[]) (void) __attribute__((weak));
|
||||
|
||||
// Iterate over all the preinit/init routines (mainly static constructors).
|
||||
inline void
|
||||
__attribute__((always_inline))
|
||||
__run_init_array (void)
|
||||
{
|
||||
int count;
|
||||
int i;
|
||||
|
||||
count = __preinit_array_end - __preinit_array_start;
|
||||
for (i = 0; i < count; i++)
|
||||
__preinit_array_start[i] ();
|
||||
|
||||
// If you need to run the code in the .init section, please use
|
||||
// the startup files, since this requires the code in crti.o and crtn.o
|
||||
// to add the function prologue/epilogue.
|
||||
//_init(); // DO NOT ENABE THIS!
|
||||
|
||||
count = __init_array_end - __init_array_start;
|
||||
for (i = 0; i < count; i++)
|
||||
__init_array_start[i] ();
|
||||
}
|
||||
|
||||
// Run all the cleanup routines (mainly static destructors).
|
||||
inline void
|
||||
__attribute__((always_inline))
|
||||
__run_fini_array (void)
|
||||
{
|
||||
int count;
|
||||
int i;
|
||||
|
||||
count = __fini_array_end - __fini_array_start;
|
||||
for (i = count; i > 0; i--)
|
||||
__fini_array_start[i - 1] ();
|
||||
|
||||
// If you need to run the code in the .fini section, please use
|
||||
// the startup files, since this requires the code in crti.o and crtn.o
|
||||
// to add the function prologue/epilogue.
|
||||
//_fini(); // DO NOT ENABE THIS!
|
||||
}
|
||||
|
||||
#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS)
|
||||
|
||||
// These definitions are used to check if the routines used to
|
||||
// clear the BSS and to copy the initialised DATA perform correctly.
|
||||
|
||||
#define BSS_GUARD_BAD_VALUE (0xCADEBABA)
|
||||
|
||||
static uint32_t volatile __attribute__ ((section(".bss_begin")))
|
||||
__bss_begin_guard;
|
||||
static uint32_t volatile __attribute__ ((section(".bss_end")))
|
||||
__bss_end_guard;
|
||||
|
||||
#define DATA_GUARD_BAD_VALUE (0xCADEBABA)
|
||||
#define DATA_BEGIN_GUARD_VALUE (0x12345678)
|
||||
#define DATA_END_GUARD_VALUE (0x98765432)
|
||||
|
||||
static uint32_t volatile __attribute__ ((section(".data_begin")))
|
||||
__data_begin_guard = DATA_BEGIN_GUARD_VALUE;
|
||||
|
||||
static uint32_t volatile __attribute__ ((section(".data_end")))
|
||||
__data_end_guard = DATA_END_GUARD_VALUE;
|
||||
|
||||
#endif // defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS)
|
||||
|
||||
// This is the place where Cortex-M core will go immediately after reset,
|
||||
// via a call or jump from the Reset_Handler.
|
||||
//
|
||||
// For the call to work, and for the call to __initialize_hardware_early()
|
||||
// to work, the reset stack must point to a valid internal RAM area.
|
||||
|
||||
void __attribute__ ((section(".after_vectors"),noreturn,weak))
|
||||
_start (void)
|
||||
{
|
||||
|
||||
// Initialise hardware right after reset, to switch clock to higher
|
||||
// frequency and have the rest of the initialisations run faster.
|
||||
//
|
||||
// Mandatory on platforms like Kinetis, which start with the watch dog
|
||||
// enabled and require an early sequence to disable it.
|
||||
//
|
||||
// Also useful on platform with external RAM, that need to be
|
||||
// initialised before filling the BSS section.
|
||||
|
||||
__initialize_hardware_early ();
|
||||
|
||||
// Use Old Style DATA and BSS section initialisation,
|
||||
// that will manage a single BSS sections.
|
||||
|
||||
#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS)
|
||||
__data_begin_guard = DATA_GUARD_BAD_VALUE;
|
||||
__data_end_guard = DATA_GUARD_BAD_VALUE;
|
||||
#endif
|
||||
|
||||
#if !defined(OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS)
|
||||
// Copy the DATA segment from Flash to RAM (inlined).
|
||||
__initialize_data(&_sidata, &_sdata, &_edata);
|
||||
#else
|
||||
|
||||
// Copy the data sections from flash to SRAM.
|
||||
for (unsigned int* p = &__data_regions_array_start;
|
||||
p < &__data_regions_array_end;)
|
||||
{
|
||||
unsigned int* from = (unsigned int *) (*p++);
|
||||
unsigned int* region_begin = (unsigned int *) (*p++);
|
||||
unsigned int* region_end = (unsigned int *) (*p++);
|
||||
|
||||
__initialize_data (from, region_begin, region_end);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS)
|
||||
if ((__data_begin_guard != DATA_BEGIN_GUARD_VALUE)
|
||||
|| (__data_end_guard != DATA_END_GUARD_VALUE))
|
||||
{
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS)
|
||||
__bss_begin_guard = BSS_GUARD_BAD_VALUE;
|
||||
__bss_end_guard = BSS_GUARD_BAD_VALUE;
|
||||
#endif
|
||||
|
||||
#if !defined(OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS)
|
||||
// Zero fill the BSS section (inlined).
|
||||
__initialize_bss(&__bss_start__, &__bss_end__);
|
||||
#else
|
||||
|
||||
// Zero fill all bss segments
|
||||
for (unsigned int *p = &__bss_regions_array_start;
|
||||
p < &__bss_regions_array_end;)
|
||||
{
|
||||
unsigned int* region_begin = (unsigned int*) (*p++);
|
||||
unsigned int* region_end = (unsigned int*) (*p++);
|
||||
__initialize_bss (region_begin, region_end);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS)
|
||||
if ((__bss_begin_guard != 0) || (__bss_end_guard != 0))
|
||||
{
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Hook to continue the initialisations. Usually compute and store the
|
||||
// clock frequency in the global CMSIS variable, cleared above.
|
||||
__initialize_hardware ();
|
||||
|
||||
// Get the argc/argv (useful in semihosting configurations).
|
||||
int argc;
|
||||
char** argv;
|
||||
__initialize_args (&argc, &argv);
|
||||
|
||||
// Call the standard library initialisation (mandatory for C++ to
|
||||
// execute the constructors for the static objects).
|
||||
__run_init_array ();
|
||||
|
||||
// Call the main entry point, and save the exit code.
|
||||
int code = main (argc, argv);
|
||||
|
||||
// Run the C++ static destructors.
|
||||
__run_fini_array ();
|
||||
|
||||
_exit (code);
|
||||
|
||||
// Should never reach this, _exit() should have already
|
||||
// performed a reset.
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
1219
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_syscalls.c
Normal file
1219
source/firmware/arch/stm32f4xx/lib/system/src/newlib/_syscalls.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// This file is part of the µOS++ III distribution.
|
||||
// Copyright (c) 2014 Liviu Ionescu.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "diag/Trace.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
__attribute__((noreturn))
|
||||
__assert_func (const char *file, int line, const char *func,
|
||||
const char *failedexpr)
|
||||
{
|
||||
trace_printf ("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
|
||||
failedexpr, file, line, func ? ", function: " : "",
|
||||
func ? func : "");
|
||||
abort ();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This is STM32 specific, but can be used on other platforms too.
|
||||
// If you need it, add the following to your application header:
|
||||
|
||||
//#ifdef USE_FULL_ASSERT
|
||||
//#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
//void assert_failed(uint8_t* file, uint32_t line);
|
||||
//#else
|
||||
//#define assert_param(expr) ((void)0)
|
||||
//#endif // USE_FULL_ASSERT
|
||||
|
||||
#if defined(USE_FULL_ASSERT)
|
||||
|
||||
void
|
||||
assert_failed (uint8_t* file, uint32_t line);
|
||||
|
||||
// Called from the assert_param() macro, usually defined in the stm32f*_conf.h
|
||||
void
|
||||
__attribute__((noreturn, weak))
|
||||
assert_failed (uint8_t* file, uint32_t line)
|
||||
{
|
||||
trace_printf ("assert_param() failed: file \"%s\", line %d\n", file, line);
|
||||
abort ();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#endif // defined(USE_FULL_ASSERT)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
@@ -0,0 +1 @@
|
||||
SRC_DIR += source/firmware/arch/stm32f4xx/lib/system/src/newlib
|
Reference in New Issue
Block a user