contiki/cpu/cc2538/startup-gcc.c

329 lines
13 KiB
C
Raw Normal View History

/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 Texas Instruments Incorporated 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
* OWNER 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 cc2538
* @{
*
* \file
* Startup code for the cc2538 chip, to be used when building with gcc
*/
#include "contiki.h"
#include "reg.h"
#include "flash.h"
#include "sys-ctrl.h"
#include "rom-util.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
extern int main(void);
/*---------------------------------------------------------------------------*/
/* System handlers provided here */
void reset_handler(void);
void nmi_handler(void);
void default_handler(void);
/* System Handler and ISR prototypes implemented elsewhere */
void clock_isr(void); /* SysTick Handler */
void gpio_port_a_isr(void);
void gpio_port_b_isr(void);
void gpio_port_c_isr(void);
void gpio_port_d_isr(void);
void rtimer_isr(void);
void cc2538_rf_rx_tx_isr(void);
void cc2538_rf_err_isr(void);
void udma_isr(void);
void udma_err_isr(void);
void crypto_isr(void);
void pka_isr(void);
cc2538: Build without the Contiki target library The GNU linker ld searches and processes libraries and object files in the order they are specified. Library files are archive files whose members are object files. The linker handles an archive file by scanning through it for members that define symbols that have so far been referenced but not defined. But an ordinary object file is linked in the usual fashion. The C library is implicitly linked after all object files and libraries specified on the command line. Because of that, if the C library depends on the Contiki target library, e.g. for the implementation of system calls, then these dependencies are not linked, which results in undefined references. Actually, the Contiki target library also needs the C library, hence a circular dependency between these libraries, which means that explicitly adding -lc anywhere on the command line can not help. The only solution in that case is to pass these libraries to ld between --start-group and --end-group. Archives grouped in this way are searched repeatedly by the linker until no new undefined references are created. This archive grouping option has a significant performance cost for the linking stage. Moreover, having to use it and to pass -lc explicitly on the command line is unusual, which is disturbing and more complicated for users needing the C library to depend on the Contiki target library. The same would be true for circular dependencies between the Contiki target library and any other library. Another issue with the Contiki target library is that it may alter the apparent behavior of the weak vs. strong symbols, because of the way ld handles archives, which may make it discard archive object files containing strong versions of referenced symbols: - If a symbol has a weak and a strong version in this library, both inside the same object file, then the linker uses the strong definition. - If a weak symbol in this library has a strong counterpart in an object file outside, then the linker uses the strong definition. - If a strong symbol in this library is inside an object file containing other referenced symbols, and has a weak counterpart anywhere, then the linker uses the strong definition. - If a strong symbol in this library is the only symbol referenced in its object file, and has a weak counterpart in an object file outside, then the linker uses the strong definition if this library is linked first, and the weak one otherwise. - If a strong symbol in this library is the only symbol referenced in its object file, and has a weak counterpart in another object file in this library, then the linker uses the definition from the first of these objects added when creating this archive. - If a symbol has a weak and a strong version, one in this library, and the other in another library, then the rules are the same as if both were in the Contiki target library. The existence of cases where the linker uses a weak symbol despite the presence of its strong counterpart in the sources compiled then passed to the linker is very error-prone, all the more this behavior depends on the order the object and archive files are passed on the command lines, which may just result from the order of source files in lists where it apparently does not matter. Such cases would be needed in the future, e.g. to define weak default implementations of some system calls that can be overridden by platform-specific implementations, both ending up in the Contiki target library. There was already such a case used to define the UART and USB ISRs as weak aliases of default_handler(), relying on this implicit unusual behavior to keep default_handler() if the UART or USB driver was unused, which was dangerous. Since the Contiki target library was only used as an intermediate file during the build, the current commit fixes these issues by simply directly using the object files instead of building an intermediate archive from them. The CONTIKI_OBJECTFILES make variable would be incomplete if it were used as a simple prerequisite in the %.elf rule in Makefile.cc2538, because other object files are added to it after this rule. That's why .SECONDEXPANSION is used to defer its expansion. Another solution would have been to split Makefile.cc2538, with the variable assignments kept in it, and the rule definitions moved to Makefile.customrules-cc2538, but this would have required to add Makefile.customrules-<target> files to all CC2538 platforms, only to include Makefile.customrules-cc2538. The solution used here is much simpler. Because the UART and USB ISRs were weak aliases of default_handler(), this change would imply that these ISRs would always be used by the linker instead of default_handler(), even if their drivers were configured as unused with UART_CONF_ENABLE and USB_SERIAL_CONF_ENABLE, which would be wrong. This commit fixes this issue by removing these weak aliases and putting either these ISRs or default_handler() in the vector table, depending on the configuration. Weak aliases are elegant, but Contiki's build system does not currently allow to automatically build or not source files depending on the configuration, so keeping these weak aliases would have required to add #if constructs somewhere in the source code, which would have broken their elegance and made them pointless. Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2015-06-01 21:27:23 +00:00
/* Link in the USB ISR only if USB is enabled */
#if USB_SERIAL_CONF_ENABLE
void usb_isr(void);
#else
#define usb_isr default_handler
#endif
/* Likewise for the UART[01] ISRs */
#if UART_CONF_ENABLE
void uart0_isr(void);
void uart1_isr(void);
#else /* UART_CONF_ENABLE */
#define uart0_isr default_handler
#define uart1_isr default_handler
#endif /* UART_CONF_ENABLE */
/* Boot Loader Backdoor selection */
#if FLASH_CCA_CONF_BOOTLDR_BACKDOOR
2014-04-17 14:39:00 +00:00
/* Backdoor enabled */
2014-04-18 14:29:47 +00:00
#if FLASH_CCA_CONF_BOOTLDR_BACKDOOR_ACTIVE_HIGH
#define FLASH_CCA_BOOTLDR_CFG_ACTIVE_LEVEL FLASH_CCA_BOOTLDR_CFG_ACTIVE_HIGH
#else
#define FLASH_CCA_BOOTLDR_CFG_ACTIVE_LEVEL 0
2014-04-17 14:39:00 +00:00
#endif
#if ((FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN < 0) || (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN > 7))
2014-04-17 14:39:00 +00:00
#error Invalid boot loader backdoor pin. Please set FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN between 0 and 7 (indicating PA0 - PA7).
#endif
#define FLASH_CCA_BOOTLDR_CFG (FLASH_CCA_BOOTLDR_CFG_ENABLE \
2014-04-18 14:29:47 +00:00
| FLASH_CCA_BOOTLDR_CFG_ACTIVE_LEVEL \
| (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN << FLASH_CCA_BOOTLDR_CFG_PORT_A_PIN_S))
#else
#define FLASH_CCA_BOOTLDR_CFG FLASH_CCA_BOOTLDR_CFG_DISABLE
#endif
/*---------------------------------------------------------------------------*/
/* Allocate stack space */
static uint64_t stack[256] __attribute__ ((section(".stack")));
/*---------------------------------------------------------------------------*/
__attribute__((__section__(".vectors")))
void(*const vectors[])(void) =
{
(void (*)(void))((unsigned long)stack + sizeof(stack)), /* Stack pointer */
reset_handler, /* Reset handler */
nmi_handler, /* The NMI handler */
default_handler, /* The hard fault handler */
default_handler, /* 4 The MPU fault handler */
default_handler, /* 5 The bus fault handler */
default_handler, /* 6 The usage fault handler */
0, /* 7 Reserved */
0, /* 8 Reserved */
0, /* 9 Reserved */
0, /* 10 Reserved */
default_handler, /* 11 SVCall handler */
default_handler, /* 12 Debug monitor handler */
0, /* 13 Reserved */
default_handler, /* 14 The PendSV handler */
clock_isr, /* 15 The SysTick handler */
gpio_port_a_isr, /* 16 GPIO Port A */
gpio_port_b_isr, /* 17 GPIO Port B */
gpio_port_c_isr, /* 18 GPIO Port C */
gpio_port_d_isr, /* 19 GPIO Port D */
0, /* 20 none */
uart0_isr, /* 21 UART0 Rx and Tx */
uart1_isr, /* 22 UART1 Rx and Tx */
default_handler, /* 23 SSI0 Rx and Tx */
default_handler, /* 24 I2C Master and Slave */
0, /* 25 Reserved */
0, /* 26 Reserved */
0, /* 27 Reserved */
0, /* 28 Reserved */
0, /* 29 Reserved */
default_handler, /* 30 ADC Sequence 0 */
0, /* 31 Reserved */
0, /* 32 Reserved */
0, /* 33 Reserved */
default_handler, /* 34 Watchdog timer, timer 0 */
default_handler, /* 35 Timer 0 subtimer A */
default_handler, /* 36 Timer 0 subtimer B */
default_handler, /* 37 Timer 1 subtimer A */
default_handler, /* 38 Timer 1 subtimer B */
default_handler, /* 39 Timer 2 subtimer A */
default_handler, /* 40 Timer 2 subtimer B */
default_handler, /* 41 Analog Comparator 0 */
default_handler, /* 42 RFCore Rx/Tx (Alternate) */
default_handler, /* 43 RFCore Error (Alternate) */
default_handler, /* 44 System Control */
default_handler, /* 45 FLASH Control */
default_handler, /* 46 AES (Alternate) */
default_handler, /* 47 PKA (Alternate) */
default_handler, /* 48 SM Timer (Alternate) */
default_handler, /* 49 MacTimer (Alternate) */
default_handler, /* 50 SSI1 Rx and Tx */
default_handler, /* 51 Timer 3 subtimer A */
default_handler, /* 52 Timer 3 subtimer B */
0, /* 53 Reserved */
0, /* 54 Reserved */
0, /* 55 Reserved */
0, /* 56 Reserved */
0, /* 57 Reserved */
0, /* 58 Reserved */
0, /* 59 Reserved */
0, /* 60 Reserved */
0, /* 61 Reserved */
udma_isr, /* 62 uDMA */
udma_err_isr, /* 63 uDMA Error */
0, /* 64 64-155 are not in use */
0, /* 65 */
0, /* 66 */
0, /* 67 */
0, /* 68 */
0, /* 69 */
0, /* 70 */
0, /* 71 */
0, /* 72 */
0, /* 73 */
0, /* 74 */
0, /* 75 */
0, /* 76 */
0, /* 77 */
0, /* 78 */
0, /* 79 */
0, /* 80 */
0, /* 81 */
0, /* 82 */
0, /* 83 */
0, /* 84 */
0, /* 85 */
0, /* 86 */
0, /* 87 */
0, /* 88 */
0, /* 89 */
0, /* 90 */
0, /* 91 */
0, /* 92 */
0, /* 93 */
0, /* 94 */
0, /* 95 */
0, /* 96 */
0, /* 97 */
0, /* 98 */
0, /* 99 */
0, /* 100 */
0, /* 101 */
0, /* 102 */
0, /* 103 */
0, /* 104 */
0, /* 105 */
0, /* 106 */
0, /* 107 */
0, /* 108 */
0, /* 109 */
0, /* 110 */
0, /* 111 */
0, /* 112 */
0, /* 113 */
0, /* 114 */
0, /* 115 */
0, /* 116 */
0, /* 117 */
0, /* 118 */
0, /* 119 */
0, /* 120 */
0, /* 121 */
0, /* 122 */
0, /* 123 */
0, /* 124 */
0, /* 125 */
0, /* 126 */
0, /* 127 */
0, /* 128 */
0, /* 129 */
0, /* 130 */
0, /* 131 */
0, /* 132 */
0, /* 133 */
0, /* 134 */
0, /* 135 */
0, /* 136 */
0, /* 137 */
0, /* 138 */
0, /* 139 */
0, /* 140 */
0, /* 141 */
0, /* 142 */
0, /* 143 */
0, /* 144 */
0, /* 145 */
0, /* 146 */
0, /* 147 */
0, /* 148 */
0, /* 149 */
0, /* 150 */
0, /* 151 */
0, /* 152 */
0, /* 153 */
0, /* 154 */
0, /* 155 */
usb_isr, /* 156 USB */
cc2538_rf_rx_tx_isr, /* 157 RFCORE RX/TX */
cc2538_rf_err_isr, /* 158 RFCORE Error */
crypto_isr, /* 159 AES */
pka_isr, /* 160 PKA */
rtimer_isr, /* 161 SM Timer */
default_handler, /* 162 MACTimer */
};
/*---------------------------------------------------------------------------*/
__attribute__((__section__(".flashcca")))
const flash_cca_lock_page_t flash_cca_lock_page = {
FLASH_CCA_BOOTLDR_CFG, /* Boot loader backdoor configuration */
FLASH_CCA_IMAGE_VALID, /* Image valid */
&vectors, /* Vector table */
/* Unlock all pages and debug */
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
};
/*---------------------------------------------------------------------------*/
/* Linker constructs indicating .data and .bss segment locations */
extern uint8_t _ldata;
extern uint8_t _data;
extern uint8_t _edata;
extern uint8_t _bss;
extern uint8_t _ebss;
/*---------------------------------------------------------------------------*/
/* Weak interrupt handlers. */
void
nmi_handler(void)
{
reset_handler();
while(1);
}
/*---------------------------------------------------------------------------*/
void
default_handler(void)
{
while(1);
}
/*---------------------------------------------------------------------------*/
void
reset_handler(void)
{
REG(SYS_CTRL_EMUOVR) = 0xFF;
/* Copy the data segment initializers from flash to SRAM. */
rom_util_memcpy(&_data, &_ldata, &_edata - &_data);
/* Zero-fill the bss segment. */
rom_util_memset(&_bss, 0, &_ebss - &_bss);
/* call the application's entry point. */
main();
/* End here if main () returns */
while(1);
}
/*---------------------------------------------------------------------------*/
/** @} */