[Cortex] Add preliminary support for core-dependent defines ARMv6m / ARMv7m, ARMv7em
This commit is contained in:
committed by
Piotr Esden-Tempski
parent
2a588f11aa
commit
e1ebcc9da8
176
lib/cm3/nvic.c
176
lib/cm3/nvic.c
@@ -19,26 +19,27 @@
|
||||
* 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
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
@@ -47,11 +48,11 @@ LGPL License Terms @ref lgpl_license
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Enable Interrupt
|
||||
|
||||
Enables a user interrupt.
|
||||
|
||||
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
|
||||
*/
|
||||
*
|
||||
* Enables a user interrupt.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
|
||||
*/
|
||||
|
||||
void nvic_enable_irq(uint8_t irqn)
|
||||
{
|
||||
@@ -60,11 +61,11 @@ void nvic_enable_irq(uint8_t irqn)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Disable Interrupt
|
||||
|
||||
Disables a user interrupt.
|
||||
|
||||
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
|
||||
*/
|
||||
*
|
||||
* Disables a user interrupt.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
|
||||
*/
|
||||
|
||||
void nvic_disable_irq(uint8_t irqn)
|
||||
{
|
||||
@@ -73,12 +74,12 @@ void nvic_disable_irq(uint8_t irqn)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @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.
|
||||
*/
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -87,12 +88,12 @@ uint8_t nvic_get_pending_irq(uint8_t irqn)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @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
|
||||
*/
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -101,38 +102,26 @@ void nvic_set_pending_irq(uint8_t irqn)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @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
|
||||
*/
|
||||
*
|
||||
* 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 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 Return Enabled Interrupt
|
||||
|
||||
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
|
||||
@return Boolean. Interrupt enabled.
|
||||
*/
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
|
||||
* @return Boolean. Interrupt enabled.
|
||||
*/
|
||||
|
||||
uint8_t nvic_get_irq_enabled(uint8_t irqn)
|
||||
{
|
||||
@@ -141,16 +130,24 @@ uint8_t nvic_get_irq_enabled(uint8_t irqn)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Set Interrupt Priority
|
||||
|
||||
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.
|
||||
|
||||
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
|
||||
@param[in] priority Unsigned int8. Interrupt priority (0 ... 255 in steps of 16)
|
||||
*/
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -166,15 +163,31 @@ void nvic_set_priority(uint8_t irqn, uint8_t 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)
|
||||
*/
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -182,4 +195,5 @@ void nvic_generate_software_interrupt(uint16_t irqn)
|
||||
NVIC_STIR |= irqn;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
@@ -35,7 +38,10 @@ void scb_reset_system(void)
|
||||
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
|
||||
|
||||
@@ -19,8 +19,15 @@
|
||||
|
||||
#include <libopencm3/cm3/sync.h>
|
||||
|
||||
#if defined(LPC43XX_M0)
|
||||
#warning "Currently sync is not supported on Cortex-M0"
|
||||
/* DMB is supported on CM0 */
|
||||
void __dmb()
|
||||
{
|
||||
__asm__ volatile ("dmb");
|
||||
}
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_6M__)
|
||||
#warning "sync not supported on ARMv6-M arch"
|
||||
#else
|
||||
|
||||
uint32_t __ldrex(volatile uint32_t *addr)
|
||||
@@ -38,11 +45,6 @@ uint32_t __strex(uint32_t val, volatile uint32_t *addr)
|
||||
return res;
|
||||
}
|
||||
|
||||
void __dmb()
|
||||
{
|
||||
__asm__ volatile ("dmb");
|
||||
}
|
||||
|
||||
void mutex_lock(mutex_t *m)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
|
||||
@@ -18,23 +18,23 @@
|
||||
* 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
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
@@ -42,121 +42,117 @@ LGPL License Terms @ref lgpl_license
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Set the Automatic Reload Value.
|
||||
|
||||
The counter is set to the reload value when the counter starts and after it
|
||||
reaches zero.
|
||||
|
||||
@param[in] value uint32_t. 24 bit reload value.
|
||||
*/
|
||||
*
|
||||
* The counter is set to the reload value when the counter starts and after it
|
||||
* reaches zero.
|
||||
*
|
||||
* @param[in] value uint32_t. 24 bit reload value.
|
||||
*/
|
||||
|
||||
void systick_set_reload(uint32_t value)
|
||||
{
|
||||
STK_LOAD = (value & 0x00FFFFFF);
|
||||
STK_RVR = (value & STK_RVR_RELOAD);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Read the Automatic Reload Value.
|
||||
|
||||
@returns 24 bit reload value as uint32_t.
|
||||
*/
|
||||
*
|
||||
* @returns 24 bit reload value as uint32_t.
|
||||
*/
|
||||
|
||||
uint32_t systick_get_reload(void)
|
||||
{
|
||||
return STK_LOAD & 0x00FFFFFF;
|
||||
return STK_RVR & STK_RVR_RELOAD;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Get the current SysTick counter value.
|
||||
|
||||
@returns 24 bit current value as uint32_t.
|
||||
*/
|
||||
*
|
||||
* @returns 24 bit current value as uint32_t.
|
||||
*/
|
||||
|
||||
uint32_t systick_get_value(void)
|
||||
{
|
||||
return STK_VAL & 0x00FFFFFF;
|
||||
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.
|
||||
*/
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
if (clocksource < 2) {
|
||||
STK_CTRL |= (clocksource << STK_CTRL_CLKSOURCE_LSB);
|
||||
STK_CSR |= clocksource;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable SysTick Interrupt.
|
||||
|
||||
*/
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_interrupt_enable(void)
|
||||
{
|
||||
STK_CTRL |= STK_CTRL_TICKINT;
|
||||
STK_CSR |= STK_CSR_TICKINT;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Disable SysTick Interrupt.
|
||||
|
||||
*/
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_interrupt_disable(void)
|
||||
{
|
||||
STK_CTRL &= ~STK_CTRL_TICKINT;
|
||||
STK_CSR &= ~STK_CSR_TICKINT;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable SysTick Counter.
|
||||
|
||||
*/
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_counter_enable(void)
|
||||
{
|
||||
STK_CTRL |= STK_CTRL_ENABLE;
|
||||
STK_CSR |= STK_CSR_ENABLE;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Disable SysTick Counter.
|
||||
|
||||
*/
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_counter_disable(void)
|
||||
{
|
||||
STK_CTRL &= ~STK_CTRL_ENABLE;
|
||||
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.
|
||||
*/
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
if (STK_CTRL & STK_CTRL_COUNTFLAG) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return (STK_CSR & STK_CSR_COUNTFLAG) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Get Calibration Value
|
||||
|
||||
@returns Current calibration value
|
||||
*/
|
||||
*
|
||||
* @returns Current calibration value
|
||||
*/
|
||||
uint32_t systick_get_calib(void)
|
||||
{
|
||||
return STK_CALIB & 0x00FFFFFF;
|
||||
return STK_CALIB & STK_CALIB_TENMS;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
||||
@@ -42,10 +42,15 @@ vector_table_t vector_table = {
|
||||
.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,
|
||||
@@ -102,10 +107,15 @@ void null_handler(void)
|
||||
|
||||
#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 sv_call_handler = null_handler
|
||||
#pragma weak debug_monitor_handler = null_handler
|
||||
#pragma weak pend_sv_handler = null_handler
|
||||
#pragma weak sys_tick_handler = null_handler
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user