summaryrefslogtreecommitdiffstats
path: root/libopencm3/lib/cm3
diff options
context:
space:
mode:
Diffstat (limited to 'libopencm3/lib/cm3')
-rw-r--r--libopencm3/lib/cm3/assert.c34
-rw-r--r--libopencm3/lib/cm3/dwt.c77
-rw-r--r--libopencm3/lib/cm3/nvic.c199
-rw-r--r--libopencm3/lib/cm3/scb.c47
-rw-r--r--libopencm3/lib/cm3/sync.c73
-rw-r--r--libopencm3/lib/cm3/systick.c203
-rw-r--r--libopencm3/lib/cm3/vector.c121
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 &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
+ * @author @htmlonly &copy; @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 &copy; @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
+