nes-proj/arch/cpu/simplelink-cc13xx-cc26xx/dev/startup_cc13xx_cc26xx_gcc.c
2018-08-31 16:39:20 +02:00

312 lines
9.9 KiB
C

/*
* Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the copyright holder 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``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 THE
* COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*/
/**
* \addtogroup cc13xx-cc26xx-cpu
* @{
*
* \file
* Startup file for GCC for CC13xx/CC26xx.
*/
/*---------------------------------------------------------------------------*/
/* Check if compiler is GNU Compiler. */
#if !(defined(__GNUC__))
#error "startup_cc13xx_cc26xx_gcc.c: Unsupported compiler!"
#endif
/*---------------------------------------------------------------------------*/
#include <string.h>
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(inc/hw_types.h)
#include DeviceFamily_constructPath(driverlib/interrupt.h)
#include DeviceFamily_constructPath(driverlib/setup.h)
/*---------------------------------------------------------------------------*/
/* Forward declaration of the default fault handlers. */
void resetISR(void);
static void nmiISR(void);
static void faultISR(void);
static void defaultHandler(void);
static void busFaultHandler(void);
/*---------------------------------------------------------------------------*/
/*
* External declaration for the reset handler that is to be called when the
* processor is started.
*/
extern void _c_int00(void);
/* The entry point for the application. */
extern int main(void);
/*---------------------------------------------------------------------------*/
/* Linker variable that marks the top of stack. */
extern unsigned long _stack_end;
/*
* The vector table. Note that the proper constructs must be placed on this to
* ensure that it ends up at physical address 0x0000.0000.
*/
__attribute__((section(".resetVecs"))) __attribute__((used))
static void(*const resetVectors[16])(void) =
{
(void(*)(void))((uint32_t)&_stack_end),
/* The initial stack pointer */
resetISR, /* The reset handler */
nmiISR, /* The NMI handler */
faultISR, /* The hard fault handler */
defaultHandler, /* The MPU fault handler */
busFaultHandler, /* The bus fault handler */
defaultHandler, /* The usage fault handler */
0, /* Reserved */
0, /* Reserved */
0, /* Reserved */
0, /* Reserved */
defaultHandler, /* SVCall handler */
defaultHandler, /* Debug monitor handler */
0, /* Reserved */
defaultHandler, /* The PendSV handler */
defaultHandler /* The SysTick handler */
};
/*---------------------------------------------------------------------------*/
/*
* The following are arrays of pointers to constructor functions that need to
* be called during startup to initialize global objects.
*/
extern void (*__init_array_start[])(void);
extern void (*__init_array_end[])(void);
/* The following global variable is required for C++ support. */
void *__dso_handle = (void *)&__dso_handle;
/*---------------------------------------------------------------------------*/
/*
* The following are constructs created by the linker, indicating where the
* the "data" and "bss" segments reside in memory. The initializers for the
* for the "data" segment resides immediately following the "text" segment.
*/
extern uint32_t __bss_start__;
extern uint32_t __bss_end__;
extern uint32_t __data_load__;
extern uint32_t __data_start__;
extern uint32_t __data_end__;
/*---------------------------------------------------------------------------*/
/*
* \brief Entry point of the startup code.
*
* Initialize the .data and .bss sections, and call main.
*/
void
localProgramStart(void)
{
uint32_t *bs;
uint32_t *be;
uint32_t *dl;
uint32_t *ds;
uint32_t *de;
uint32_t count;
uint32_t i;
IntMasterDisable();
/* Final trim of device */
SetupTrimDevice();
/* initiailize .bss to zero */
bs = &__bss_start__;
be = &__bss_end__;
while(bs < be) {
*bs = 0;
bs++;
}
/* relocate the .data section */
dl = &__data_load__;
ds = &__data_start__;
de = &__data_end__;
if(dl != ds) {
while(ds < de) {
*ds = *dl;
dl++;
ds++;
}
}
/* Run any constructors */
count = (uint32_t)(__init_array_end - __init_array_start);
for(i = 0; i < count; i++) {
__init_array_start[i]();
}
/* Call the application's entry point. */
main();
/* If we ever return signal Error */
faultISR();
}
/*---------------------------------------------------------------------------*/
/*
* \brief Reset ISR.
*
* This is the code that gets called when the processor first starts execution
* following a reset event. Only the absolutely necessary set is performed,
* after which the application supplied entry() routine is called. Any fancy
* actions (such as making decisions based on the reset cause register, and
* resetting the bits in that register) are left solely in the hands of the
* application.
*/
void __attribute__((naked))
resetISR(void)
{
__asm__ __volatile__
(
"movw r0, #:lower16:resetVectors \n"
"movt r0, #:upper16:resetVectors \n"
"ldr r0, [r0] \n"
"mov sp, r0 \n"
"bx %0 \n"
: /* output */
: /* input */
"r"(localProgramStart)
);
}
/*---------------------------------------------------------------------------*/
/*
* \brief Non-Maskable Interrupt (NMI) ISR.
*
* This is the code that gets called when the processor receives a NMI. This
* simply enters an infinite loop, preserving the system state for examination
* by a debugger.
*/
static void
nmiISR(void)
{
/* Enter an infinite loop. */
for(;;) { /* hang */ }
}
/*---------------------------------------------------------------------------*/
/*
* \brief Debug stack pointer.
* \param sp Stack pointer.
*
* Provide a view into the CPU state from the provided stack pointer.
*/
static void
debugHardfault(uint32_t *sp)
{
volatile uint32_t r0; /**< R0 register */
volatile uint32_t r1; /**< R1 register */
volatile uint32_t r2; /**< R2 register */
volatile uint32_t r3; /**< R3 register */
volatile uint32_t r12; /**< R12 register */
volatile uint32_t lr; /**< LR register */
volatile uint32_t pc; /**< PC register */
volatile uint32_t psr; /**< PSR register */
(void)(r0 = sp[0]);
(void)(r1 = sp[1]);
(void)(r2 = sp[2]);
(void)(r3 = sp[3]);
(void)(r12 = sp[4]);
(void)(lr = sp[5]);
(void)(pc = sp[6]);
(void)(psr = sp[7]);
/* Enter an infinite loop. */
for(;;) { /* hang */ }
}
/*---------------------------------------------------------------------------*/
/*
* \brief CPU Fault ISR.
*
* This is the code that gets called when the processor receives a fault
* interrupt. Setup a call to debugStackPointer with the current stack pointer.
* The stack pointer in this case would be the CPU state which caused the CPU
* fault.
*/
static void
faultISR(void)
{
__asm__ __volatile__
(
"tst lr, #4 \n"
"ite eq \n"
"mrseq r0, msp \n"
"mrsne r0, psp \n"
"bx %0 \n"
: /* output */
: /* input */
"r"(debugHardfault)
);
}
/*---------------------------------------------------------------------------*/
/* Dummy variable */
volatile int x__;
/*
* \brief Bus Fault Handler.
*
* This is the code that gets called when the processor receives an unexpected
* interrupt. This simply enters an infinite loop, preserving the system state
* for examination by a debugger.
*/
static void
busFaultHandler(void)
{
x__ = 0;
/* Enter an infinite loop. */
for(;;) { /* hang */ }
}
/*---------------------------------------------------------------------------*/
/*
* \brief Default Handler.
*
* This is the code that gets called when the processor receives an unexpected
* interrupt. This simply enters an infinite loop, preserving the system state
* for examination by a debugger.
*/
static void
defaultHandler(void)
{
/* Enter an infinite loop. */
for(;;) { /* hang */ }
}
/*---------------------------------------------------------------------------*/
/*
* \brief Finalize object function.
*
* This function is called by __libc_fini_array which gets called when exit()
* is called. In order to support exit(), an empty _fini() stub function is
* required.
*/
void
_fini(void)
{
/* Function body left empty intentionally */
}
/*---------------------------------------------------------------------------*/
/** @} */