diff options
Diffstat (limited to 'libopencm3/lib/cm3')
-rw-r--r-- | libopencm3/lib/cm3/assert.c | 34 | ||||
-rw-r--r-- | libopencm3/lib/cm3/dwt.c | 77 | ||||
-rw-r--r-- | libopencm3/lib/cm3/nvic.c | 199 | ||||
-rw-r--r-- | libopencm3/lib/cm3/scb.c | 47 | ||||
-rw-r--r-- | libopencm3/lib/cm3/sync.c | 73 | ||||
-rw-r--r-- | libopencm3/lib/cm3/systick.c | 203 | ||||
-rw-r--r-- | libopencm3/lib/cm3/vector.c | 121 |
7 files changed, 754 insertions, 0 deletions
diff --git a/libopencm3/lib/cm3/assert.c b/libopencm3/lib/cm3/assert.c new file mode 100644 index 0000000..82def0d --- /dev/null +++ b/libopencm3/lib/cm3/assert.c @@ -0,0 +1,34 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Tomaz Solc <tomaz.solc@tablix.org> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libopencm3/cm3/assert.h> + +void __attribute__((weak)) cm3_assert_failed(void) +{ + while (1); +} + +void __attribute__((weak)) cm3_assert_failed_verbose( + const char *file __attribute__((unused)), + int line __attribute__((unused)), + const char *func __attribute__((unused)), + const char *assert_expr __attribute__((unused))) +{ + cm3_assert_failed(); +} diff --git a/libopencm3/lib/cm3/dwt.c b/libopencm3/lib/cm3/dwt.c new file mode 100644 index 0000000..fe7c261 --- /dev/null +++ b/libopencm3/lib/cm3/dwt.c @@ -0,0 +1,77 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libopencm3/cm3/scs.h> +#include <libopencm3/cm3/dwt.h> + +/*---------------------------------------------------------------------------*/ +/** @brief DebugTrace Enable the CPU cycle counter + * + * This function will try to enable the CPU cycle counter that is intended for + * benchmarking performance of the code. If function fails, the cycle counter + * isn't available on this architecture. + * + * @returnd true, if success + */ +bool dwt_enable_cycle_counter(void) +{ +#if defined(__ARM_ARCH_6M__) + return false; /* Not supported on ARMv6M */ +#endif /* defined(__ARM_ARCH_6M__) */ + +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + /* Note TRCENA is for 7M and above*/ + SCS_DEMCR |= SCS_DEMCR_TRCENA; + if (DWT_CTRL & DWT_CTRL_NOCYCCNT) { + return false; /* Not supported in implementation */ + } + + DWT_CYCCNT = 0; + DWT_CTRL |= DWT_CTRL_CYCCNTENA; + return true; +#endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */ + + /* not supported on other architectures */ + return false; +} +/*---------------------------------------------------------------------------*/ +/** @brief DebugTrace Read the CPU cycle counter + * + * This function reads the core cycle counter if it is enabled. It is the + * fastest clock running on the system. + * + * @note The CPU cycle counter must be enabled by @ref dwt_enable_cycle_counter + * + * @returns 0 if cycle counter is not supported or enabled, the cycle counter + * value otherwise. + */ +uint32_t dwt_read_cycle_counter(void) +{ +#if defined(__ARM_ARCH_6M__) + return 0; /* Not supported on ARMv6M */ +#endif /* defined(__ARM_ARCH_6M__) */ + +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + if (DWT_CTRL & DWT_CTRL_CYCCNTENA) { + return DWT_CYCCNT; + } else { + return 0; /* not supported or enabled */ + } +#endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */ +} diff --git a/libopencm3/lib/cm3/nvic.c b/libopencm3/lib/cm3/nvic.c new file mode 100644 index 0000000..6c2188a --- /dev/null +++ b/libopencm3/lib/cm3/nvic.c @@ -0,0 +1,199 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org> + * Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com> + * Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ +/** @defgroup CM3_nvic_file NVIC + * + * @ingroup CM3_files + * + * @brief <b>libopencm3 Cortex Nested Vectored Interrupt Controller</b> + * + * @version 1.0.0 + * + * @author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org> + * @author @htmlonly © @endhtmlonly 2012 Fergus Noble + * <fergusnoble@gmail.com> + * + * @date 18 August 2012 + * + * Cortex processors provide 14 cortex-defined interrupts (NMI, usage faults, + * systicks etc.) and varying numbers of implementation defined interrupts + * (typically peripherial interrupts and DMA). + * + * @see Cortex-M3 Devices Generic User Guide + * @see STM32F10xxx Cortex-M3 programming manual + * + * LGPL License Terms @ref lgpl_license +*/ +/**@{*/ + +#include <libopencm3/cm3/nvic.h> +#include <libopencm3/cm3/scs.h> + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Enable Interrupt + * + * Enables a user interrupt. + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + */ + +void nvic_enable_irq(uint8_t irqn) +{ + NVIC_ISER(irqn / 32) = (1 << (irqn % 32)); +} + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Disable Interrupt + * + * Disables a user interrupt. + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + */ + +void nvic_disable_irq(uint8_t irqn) +{ + NVIC_ICER(irqn / 32) = (1 << (irqn % 32)); +} + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Return Pending Interrupt + * + * True if the interrupt has occurred and is waiting for service. + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + * @return Boolean. Interrupt pending. + */ + +uint8_t nvic_get_pending_irq(uint8_t irqn) +{ + return NVIC_ISPR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Set Pending Interrupt + * + * Force a user interrupt to a pending state. This has no effect if the + * interrupt is already pending. + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + */ + +void nvic_set_pending_irq(uint8_t irqn) +{ + NVIC_ISPR(irqn / 32) = (1 << (irqn % 32)); +} + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Clear Pending Interrupt + * + * Force remove a user interrupt from a pending state. This has no effect if + * the interrupt is actively being serviced. + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + */ + +void nvic_clear_pending_irq(uint8_t irqn) +{ + NVIC_ICPR(irqn / 32) = (1 << (irqn % 32)); +} + + + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Return Enabled Interrupt + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + * @return Boolean. Interrupt enabled. + */ + +uint8_t nvic_get_irq_enabled(uint8_t irqn) +{ + return NVIC_ISER(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Set Interrupt Priority + * + * CM3, CM4: + * + * There are 16 priority levels only, given by the upper four bits of the + * priority byte, as required by ARM standards. The priority levels are + * interpreted according to the pre-emptive priority grouping set in the + * SCB Application Interrupt and Reset Control Register (SCB_AIRCR), as done + * in @ref scb_set_priority_grouping. + * + * CM0: + * + * There are 4 priority levels only, given by the upper two bits of the + * priority byte, as required by ARM standards. No grouping available. + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + * @param[in] priority Unsigned int8. Interrupt priority (0 ... 255 in steps of + * 16) + */ + +void nvic_set_priority(uint8_t irqn, uint8_t priority) +{ + /* code from lpc43xx/nvic.c -- this is quite a hack and alludes to the + * negative interrupt numbers assigned to the system interrupts. better + * handling would mean signed integers. */ + if (irqn >= NVIC_IRQ_COUNT) { + /* Cortex-M system interrupts */ + SCS_SHPR((irqn & 0xF) - 4) = priority; + } else { + /* Device specific interrupts */ + NVIC_IPR(irqn) = priority; + } +} + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Return Active Interrupt + * + * Interrupt has occurred and is currently being serviced. + * + * @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint + * @return Boolean. Interrupt active. + */ + +uint8_t nvic_get_active_irq(uint8_t irqn) +{ + return NVIC_IABR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief NVIC Software Trigger Interrupt + * + * Generate an interrupt from software. This has no effect for unprivileged + * access unless the privilege level has been elevated through the System + * Control Registers. + * + * @param[in] irqn Unsigned int16. Interrupt number (0 ... 239) + */ + +void nvic_generate_software_interrupt(uint16_t irqn) +{ + if (irqn <= 239) { + NVIC_STIR |= irqn; + } +} +#endif +/**@}*/ diff --git a/libopencm3/lib/cm3/scb.c b/libopencm3/lib/cm3/scb.c new file mode 100644 index 0000000..8c5a2f3 --- /dev/null +++ b/libopencm3/lib/cm3/scb.c @@ -0,0 +1,47 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> + +#include <libopencm3/cm3/scb.h> + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) +void scb_reset_core(void) +{ + SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET; + + while (1); +} +#endif + +void scb_reset_system(void) +{ + SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ; + + while (1); +} + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) +void scb_set_priority_grouping(uint32_t prigroup) +{ + SCB_AIRCR = SCB_AIRCR_VECTKEY | prigroup; +} +#endif diff --git a/libopencm3/lib/cm3/sync.c b/libopencm3/lib/cm3/sync.c new file mode 100644 index 0000000..906138a --- /dev/null +++ b/libopencm3/lib/cm3/sync.c @@ -0,0 +1,73 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libopencm3/cm3/sync.h> + +/* DMB is supported on CM0 */ +void __dmb() +{ + __asm__ volatile ("dmb"); +} + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + +uint32_t __ldrex(volatile uint32_t *addr) +{ + uint32_t res; + __asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr)); + return res; +} + +uint32_t __strex(uint32_t val, volatile uint32_t *addr) +{ + uint32_t res; + __asm__ volatile ("strex %0, %2, [%1]" + : "=&r" (res) : "r" (addr), "r" (val)); + return res; +} + +void mutex_lock(mutex_t *m) +{ + uint32_t status = 0; + + do { + /* Wait until the mutex is unlocked. */ + while (__ldrex(m) != MUTEX_UNLOCKED); + + /* Try to acquire it. */ + status = __strex(MUTEX_LOCKED, m); + + /* Did we get it? If not then try again. */ + } while (status != 0); + + /* Execute the mysterious Data Memory Barrier instruction! */ + __dmb(); +} + +void mutex_unlock(mutex_t *m) +{ + /* Ensure accesses to protected resource are finished */ + __dmb(); + + /* Free the lock. */ + *m = MUTEX_UNLOCKED; +} + +#endif diff --git a/libopencm3/lib/cm3/systick.c b/libopencm3/lib/cm3/systick.c new file mode 100644 index 0000000..a99593b --- /dev/null +++ b/libopencm3/lib/cm3/systick.c @@ -0,0 +1,203 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org> + * Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ +/** @defgroup CM3_systick_file SysTick + * + * @ingroup CM3_files + * + * @brief <b>libopencm3 Cortex System Tick Timer</b> + * + * @version 1.0.0 + * + * @author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org> + * + * @date 19 August 2012 + * + * This library supports the System Tick timer in ARM Cortex Microcontrollers. + * + * The System Tick timer is part of the ARM Cortex core. It is a 24 bit + * down counter that can be configured with an automatical reload value. + * + * LGPL License Terms @ref lgpl_license + */ + +/**@{*/ +#include <libopencm3/cm3/systick.h> + +/*---------------------------------------------------------------------------*/ +/** @brief SysTick Set the Automatic Reload Value. + * + * The counter is set to the reload value when the counter starts and after it + * reaches zero. + * + * @note The systick counter value might be undefined upon startup. To get + * predictable behavior, it is a good idea to set or clear the counter after + * set reload. @seealso systick_clear + * + * @param[in] value uint32_t. 24 bit reload value. + */ + +void systick_set_reload(uint32_t value) +{ + STK_RVR = (value & STK_RVR_RELOAD); +} + +/*---------------------------------------------------------------------------*/ +/** @brief SysTick Read the Automatic Reload Value. + * + * @returns 24 bit reload value as uint32_t. + */ + +uint32_t systick_get_reload(void) +{ + return STK_RVR & STK_RVR_RELOAD; +} + +/** @brief SysTick Set clock and frequency of overflow + * + * This function sets the systick to AHB clock source, and the prescaler to + * generate interrupts with the desired frequency. The function fails, if + * the frequency is too low. + * + * @param[in] freq uint32_t The desired frequency in Hz + * @param[in] ahb uint32_t The current AHB frequency in Hz + * @returns true, if success, false if the desired frequency cannot be set. + */ +bool systick_set_frequency(uint32_t freq, uint32_t ahb) +{ + uint32_t ratio = ahb / freq; + +#if defined(__ARM_ARCH_6M__) + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); +#else + if (ratio >= (STK_RVR_RELOAD * 8)) { + /* This frequency is too slow */ + return false; + } else if (ratio >= STK_RVR_RELOAD) { + ratio /= 8; + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); + } else { + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); + } +#endif + systick_set_reload(ratio - 1); + return true; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Get the current SysTick counter value. + * + * @returns 24 bit current value as uint32_t. + */ + +uint32_t systick_get_value(void) +{ + return STK_CVR & STK_CVR_CURRENT; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Set the SysTick Clock Source. + * + * The clock source can be either the AHB clock or the same clock divided by 8. + * + * @param[in] clocksource uint8_t. Clock source from @ref systick_clksource. + */ + +void systick_set_clocksource(uint8_t clocksource) +{ + STK_CSR = (STK_CSR & ~STK_CSR_CLKSOURCE) | + (clocksource & STK_CSR_CLKSOURCE); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Enable SysTick Interrupt. + * + */ + +void systick_interrupt_enable(void) +{ + STK_CSR |= STK_CSR_TICKINT; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Disable SysTick Interrupt. + * + */ + +void systick_interrupt_disable(void) +{ + STK_CSR &= ~STK_CSR_TICKINT; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Enable SysTick Counter. + * + */ + +void systick_counter_enable(void) +{ + STK_CSR |= STK_CSR_ENABLE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Disable SysTick Counter. + * + */ + +void systick_counter_disable(void) +{ + STK_CSR &= ~STK_CSR_ENABLE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief SysTick Read the Counter Flag. + * + * The count flag is set when the timer count becomes zero, and is cleared when + * the flag is read. + * + * @returns Boolean if flag set. + */ + +uint8_t systick_get_countflag(void) +{ + return (STK_CSR & STK_CSR_COUNTFLAG) ? 1 : 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief SysTick Clear counter Value. + * + * The counter value is cleared. Useful for well defined startup. + */ + +void systick_clear(void) +{ + STK_CVR = 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief SysTick Get Calibration Value + * + * @returns Current calibration value + */ +uint32_t systick_get_calib(void) +{ + return STK_CALIB & STK_CALIB_TENMS; +} +/**@}*/ + diff --git a/libopencm3/lib/cm3/vector.c b/libopencm3/lib/cm3/vector.c new file mode 100644 index 0000000..4523d31 --- /dev/null +++ b/libopencm3/lib/cm3/vector.c @@ -0,0 +1,121 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>, + * Copyright (C) 2012 chrysn <chrysn@fsfe.org> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libopencm3/cm3/vector.h> + +/* load optional platform dependent initialization routines */ +#include "../dispatch/vector_chipset.c" +/* load the weak symbols for IRQ_HANDLERS */ +#include "../dispatch/vector_nvic.c" + +/* Symbols exported by the linker script(s): */ +extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack; +typedef void (*funcp_t) (void); +extern funcp_t __preinit_array_start, __preinit_array_end; +extern funcp_t __init_array_start, __init_array_end; +extern funcp_t __fini_array_start, __fini_array_end; + +void main(void); +void blocking_handler(void); +void null_handler(void); + +__attribute__ ((section(".vectors"))) +vector_table_t vector_table = { + .initial_sp_value = &_stack, + .reset = reset_handler, + .nmi = nmi_handler, + .hard_fault = hard_fault_handler, + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + .memory_manage_fault = mem_manage_handler, + .bus_fault = bus_fault_handler, + .usage_fault = usage_fault_handler, + .debug_monitor = debug_monitor_handler, +#endif + + .sv_call = sv_call_handler, + .pend_sv = pend_sv_handler, + .systick = sys_tick_handler, + .irq = { + IRQ_HANDLERS + } +}; + +void WEAK __attribute__ ((naked)) reset_handler(void) +{ + volatile unsigned *src, *dest; + funcp_t *fp; + + for (src = &_data_loadaddr, dest = &_data; + dest < &_edata; + src++, dest++) { + *dest = *src; + } + + while (dest < &_ebss) { + *dest++ = 0; + } + + /* Constructors. */ + for (fp = &__preinit_array_start; fp < &__preinit_array_end; fp++) { + (*fp)(); + } + for (fp = &__init_array_start; fp < &__init_array_end; fp++) { + (*fp)(); + } + + /* might be provided by platform specific vector.c */ + pre_main(); + + /* Call the application's entry point. */ + main(); + + /* Destructors. */ + for (fp = &__fini_array_start; fp < &__fini_array_end; fp++) { + (*fp)(); + } + +} + +void blocking_handler(void) +{ + while (1); +} + +void null_handler(void) +{ + /* Do nothing. */ +} + +#pragma weak nmi_handler = null_handler +#pragma weak hard_fault_handler = blocking_handler +#pragma weak sv_call_handler = null_handler +#pragma weak pend_sv_handler = null_handler +#pragma weak sys_tick_handler = null_handler + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) +#pragma weak mem_manage_handler = blocking_handler +#pragma weak bus_fault_handler = blocking_handler +#pragma weak usage_fault_handler = blocking_handler +#pragma weak debug_monitor_handler = null_handler +#endif + |