aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@leaflabs.com>2011-04-01 02:33:53 -0400
committerMarti Bolivar <mbolivar@leaflabs.com>2011-04-05 13:59:33 -0400
commit6229da7a3ec40fb7d87c0c4edd38bc32da36ef13 (patch)
tree07db7db1761445bba73c58f98b79502708574874 /libmaple
parentcf4322804a94ab81b057ec1c0e2f397338b5ab69 (diff)
downloadlibrambutan-6229da7a3ec40fb7d87c0c4edd38bc32da36ef13.tar.gz
librambutan-6229da7a3ec40fb7d87c0c4edd38bc32da36ef13.zip
NVIC and SCB refactor
Diffstat (limited to 'libmaple')
-rw-r--r--libmaple/nvic.c83
-rw-r--r--libmaple/nvic.h239
-rw-r--r--libmaple/rules.mk2
-rw-r--r--libmaple/scb.h48
-rw-r--r--libmaple/util.c4
5 files changed, 197 insertions, 179 deletions
diff --git a/libmaple/nvic.c b/libmaple/nvic.c
index 28ca169..28db96a 100644
--- a/libmaple/nvic.c
+++ b/libmaple/nvic.c
@@ -26,89 +26,54 @@
* @brief Nested interrupt controller routines
*/
-#include "libmaple.h"
-#include "scb.h"
#include "nvic.h"
-#include "systick.h"
-
-void nvic_set_vector_table(uint32 addr, uint32 offset) {
- __write(SCB_VTOR, (uint32)addr | (offset & 0x1FFFFF80));
-}
-
-/**
- * @brief turn on interrupt number n
- * @param n interrupt number
- */
-void nvic_irq_enable(uint32 n) {
- uint32 *iser = &((uint32*)NVIC_ISER0)[(n/32)];
- __write(iser, BIT(n % 32));
-}
-
-/**
- * @brief turn off interrupt number n
- * @param n interrupt number
- */
-void nvic_irq_disable(uint32 n) {
- uint32 *icer = &((uint32*)NVIC_ICER0)[(n/32)];
- __write(icer, BIT(n % 32));
-}
-
-void nvic_irq_disable_all(void) {
- /* Each ICER register contains 1 bit per interrupt. Writing a 1
- to that bit disables the corresponding interrupt. So each of
- the following lines disables up to 32 interrupts at a time.
- Since low, medium, and high-density devices all have less than
- 64 interrupts, this suffices. */
- /* TODO: fix for connectivity line: __write(NVIC_ICER2,1),
- requires connectivity line support in libmaple.h */
- __write(NVIC_ICER0, 0xFFFFFFFF);
- __write(NVIC_ICER1, 0xFFFFFFFF);
-}
-
+#include "scb.h"
+#include "stm32.h"
/**
* @brief Set interrupt priority for an interrupt line
- * Note: The STM32 only implements 4 bits of priority, ignoring
- * the lower 4 bits. This means there are only 16 levels of priority.
- * Bits[3:0] read as zero and ignore writes.
+ *
+ * Note: The STM32 only implements 4 bits of priority, ignoring the
+ * lower 4 bits. This means there are only 16 levels of priority.
+ * Bits[3:0] read as zero and ignore writes.
+ *
* @param irqn device to set
- * @param priority priority to set, 0 being highest priority and 15 being
- * lowest.
+ * @param priority Priority to set, 0 being highest priority and 15
+ * being lowest.
*/
-void nvic_irq_set_priority(int32 irqn, uint8 priority) {
+void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority) {
if (irqn < 0) {
/* This interrupt is in the system handler block */
- SCB->SHP[((uint32)irqn & 0xF) - 4] = (priority & 0xF) << 4;
+ SCB_BASE->SHP[((uint32)irqn & 0xF) - 4] = (priority & 0xF) << 4;
} else {
- NVIC->IP[irqn] = (priority & 0xF) << 4;
+ NVIC_BASE->IP[irqn] = (priority & 0xF) << 4;
}
}
/**
- * @brief Initialize the NVIC according to VECT_TAB_FLASH,
- * VECT_TAB_RAM, or VECT_TAB_BASE.
+ * @brief Initialize the NVIC
+ * @param vect_table_address Vector table base address.
*/
-void nvic_init(void) {
+void nvic_init(uint32 vector_table_address, uint32 offset) {
uint32 i;
-#ifdef VECT_TAB_FLASH
- nvic_set_vector_table(USER_ADDR_ROM, 0x0);
-#elif defined VECT_TAB_RAM
- nvic_set_vector_table(USER_ADDR_RAM, 0x0);
-#elif defined VECT_TAB_BASE
- nvic_set_vector_table(((uint32)0x08000000), 0x0);
-#else
-#error "You must set a base address for the vector table!"
-#endif
+ nvic_set_vector_table(vector_table_address, offset);
/*
* Lower priority level for all peripheral interrupts to lowest
* possible.
*/
for (i = 0; i < NR_INTERRUPTS; i++) {
- nvic_irq_set_priority(i, 0xF);
+ nvic_irq_set_priority((nvic_irq_num)i, 0xF);
}
/* Lower systick interrupt priority to lowest level */
nvic_irq_set_priority(NVIC_SYSTICK, 0xF);
}
+
+/**
+ * Reset the vector table address.
+ */
+void nvic_set_vector_table(uint32 addr, uint32 offset) {
+ SCB_BASE->VTOR = addr | (offset & 0x1FFFFF80);
+}
diff --git a/libmaple/nvic.h b/libmaple/nvic.h
index cbcd49c..a889f4b 100644
--- a/libmaple/nvic.h
+++ b/libmaple/nvic.h
@@ -24,115 +24,170 @@
/**
* @file nvic.h
- * @brief Nested interrupt controller defines and prototypes
+ * @brief Nested vector interrupt controller support.
*/
#ifndef _NVIC_H_
#define _NVIC_H_
+#include "libmaple_types.h"
+
#ifdef __cplusplus
extern "C"{
#endif
-#define NVIC_INT_USBHP 19
-#define NVIC_INT_USBLP 20
-
-/* NVIC Interrupt Enable registers */
-#define NVIC_ISER0 0xE000E100
-#define NVIC_ISER1 0xE000E104
-/* NVIC_ISER2 only on connectivity line */
+/** NVIC register map type. */
+typedef struct nvic_reg_map {
+ __io uint32 ISER[8]; /**< Interrupt Set Enable Registers */
+ uint32 RESERVED0[24]; /**< Reserved */
+ __io uint32 ICER[8]; /**< Interrupt Clear Enable Registers */
+ uint32 RSERVED1[24]; /**< Reserved */
+ __io uint32 ISPR[8]; /**< Interrupt Set Pending Registers */
+ uint32 RESERVED2[24]; /**< Reserved */
+ __io uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */
+ uint32 RESERVED3[24]; /**< Reserved */
+ __io uint32 IABR[8]; /**< Interrupt Active bit Registers */
+ uint32 RESERVED4[56]; /**< Reserved */
+ __io uint8 IP[240]; /**< Interrupt Priority Registers */
+ uint32 RESERVED5[644]; /**< Reserved */
+ __io uint32 STIR; /**< Software Trigger Interrupt Registers */
+} nvic_reg_map;
-/* NVIC Interrupt Clear registers */
-#define NVIC_ICER0 0xE000E180
-#define NVIC_ICER1 0xE000E184
-/* NVIC_ICER2 only on connectivity line */
+/** NVIC register map base pointer. */
+#define NVIC_BASE ((nvic_reg_map*)0xE000E100)
-/* NVIC Priority */
-#define NVIC_PRI_BASE 0xE000E400
+/**
+ * Interrupt vector table interrupt numbers. Each enumerator is the
+ * position of the corresponding interrupt in the vector table. */
+typedef enum nvic_irq_num {
+ NVIC_NMI = -14, /**< Non-maskable interrupt */
+ NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */
+ NVIC_MEM_MANAGE = -12, /**< Memory management */
+ NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory
+ access fault. */
+ NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction or
+ illegal state. */
+ NVIC_SVC = -5, /**< System service call via SWI insruction */
+ NVIC_DEBUG_MON = -4, /**< Debug monitor */
+ NVIC_PEND_SVC = -2, /**< Pendable request for system service */
+ NVIC_SYSTICK = -1, /**< System tick timer */
+ NVIC_WWDG = 0, /**< Window watchdog interrupt */
+ NVIC_PVD = 1, /**< PVD through EXTI line detection */
+ NVIC_TAMPER = 2, /**< Tamper */
+ NVIC_RTC = 3, /**< Real-time clock */
+ NVIC_FLASH = 4, /**< Flash */
+ NVIC_RCC = 5, /**< Reset and clock control */
+ NVIC_EXTI0 = 6, /**< EXTI line 0 */
+ NVIC_EXTI1 = 7, /**< EXTI line 1 */
+ NVIC_EXTI2 = 8, /**< EXTI line 2 */
+ NVIC_EXTI3 = 9, /**< EXTI line 3 */
+ NVIC_EXTI4 = 10, /**< EXTI line 4 */
+ NVIC_DMA_CH1 = 11, /**< DMA1 channel 1 */
+ NVIC_DMA_CH2 = 12, /**< DMA1 channel 2 */
+ NVIC_DMA_CH3 = 13, /**< DMA1 channel 3 */
+ NVIC_DMA_CH4 = 14, /**< DMA1 channel 4 */
+ NVIC_DMA_CH5 = 15, /**< DMA1 channel 5 */
+ NVIC_DMA_CH6 = 16, /**< DMA1 channel 6 */
+ NVIC_DMA_CH7 = 17, /**< DMA1 channel 7 */
+ NVIC_ADC1_2 = 18, /**< ADC1 and ADC2 */
+ NVIC_USB_HP_CAN_TX = 19, /**< USB high priority or CAN TX */
+ NVIC_USB_LP_CAN_RX0 = 20, /**< USB low priority or CAN RX0 */
+ NVIC_CAN_RX1 = 21, /**< CAN RX1 */
+ NVIC_CAN_SCE = 22, /**< CAN SCE */
+ NVIC_EXTI9_5 = 23, /**< EXTI line [9:5] */
+ NVIC_TIMER1_BRK = 24, /**< Timer 1 break */
+ NVIC_TIMER1_UP = 25, /**< Timer 1 update */
+ NVIC_TIMER1_TRG_COM = 26, /**< Timer 1 trigger and commutation */
+ NVIC_TIMER1_CC = 27, /**< Timer 1 capture/compare */
+ NVIC_TIMER2 = 28, /**< Timer 2 */
+ NVIC_TIMER3 = 29, /**< Timer 3 */
+ NVIC_TIMER4 = 30, /**< Timer 4 */
+ NVIC_I2C1_EV = 31, /**< I2C1 event */
+ NVIC_I2C1_ER = 32, /**< I2C1 error */
+ NVIC_I2C2_EV = 33, /**< I2C2 event */
+ NVIC_I2C2_ER = 34, /**< I2C2 error */
+ NVIC_SPI1 = 35, /**< SPI1 */
+ NVIC_SPI2 = 36, /**< SPI2 */
+ NVIC_USART1 = 37, /**< USART1 */
+ NVIC_USART2 = 38, /**< USART2 */
+ NVIC_USART3 = 39, /**< USART3 */
+ NVIC_EXTI15_10 = 40, /**< EXTI line [15:10] */
+ NVIC_RTCALARM = 41, /**< RTC alarm through EXTI line */
+ NVIC_USBWAKEUP = 42, /**< USB wakeup from suspend through
+ EXTI line */
+ NVIC_TIMER8_BRK = 43, /**< Timer 8 break */
+ NVIC_TIMER8_UP = 44, /**< Timer 8 update */
+ NVIC_TIMER8_TRG_COM = 45, /**< Timer 8 trigger and commutation */
+ NVIC_TIMER8_CC = 46, /**< Timer 8 capture/compare */
+#ifdef STM32_HIGH_DENSITY
+ NVIC_ADC3 = 47, /**< ADC3 */
+ NVIC_FSMC = 48, /**< FSMC */
+ NVIC_SDIO = 49, /**< SDIO */
+ NVIC_TIMER5 = 50, /**< Timer 5 */
+ NVIC_SPI3 = 51, /**< SPI3 */
+ NVIC_UART4 = 52, /**< UART4 */
+ NVIC_UART5 = 53, /**< UART5 */
+ NVIC_TIMER6 = 54, /**< Timer 6 */
+ NVIC_TIMER7 = 55, /**< Timer 7 */
+ NVIC_DMA2_CH1 = 56, /**< DMA2 channel 1 */
+ NVIC_DMA2_CH2 = 57, /**< DMA2 channel 2 */
+ NVIC_DMA2_CH3 = 58, /**< DMA2 channel 3 */
+ NVIC_DMA2_CH4_5 = 59, /**< DMA2 channels 4 and 5 */
+#endif
+} nvic_irq_num;
-/* System control registers */
-#define SCB_VTOR 0xE000ED08 // Vector table offset register
+void nvic_init(uint32 vector_table_address, uint32 offset);
+void nvic_set_vector_table(uint32 address, uint32 offset);
+void nvic_set_priority(nvic_irq_num irqn, uint8 priority);
-#define NVIC_BASE 0xE000E100
-#define NVIC ((nvic_reg_map*)NVIC_BASE)
+/**
+ * Enables interrupts and configurable fault handlers (clear PRIMASK).
+ */
+static inline void nvic_globalirq_enable() {
+ asm volatile("cpsie i");
+}
-typedef struct nvic_reg_map {
- __io uint32 ISER[8]; // Interrupt Set Enable Registers
- uint32 RESERVED0[24];
- __io uint32 ICER[8]; // Interrupt Clear Enable Registers
- uint32 RSERVED1[24];
- __io uint32 ISPR[8]; // Interrupt Set Pending Registers
- uint32 RESERVED2[24];
- __io uint32 ICPR[8]; // Interrupt Clear Pending Registers
- uint32 RESERVED3[24];
- __io uint32 IABR[8]; // Interrupt Active bit Registers
- uint32 RESERVED4[56];
- __io uint8 IP[240]; // Interrupt Priority Registers
- uint32 RESERVED5[644];
- __io uint32 STIR; // Software Trigger Interrupt Registers
-} nvic_reg_map;
+/**
+ * Disable interrupts and configurable fault handlers (set PRIMASK).
+ */
+static inline void nvic_globalirq_disable() {
+ asm volatile("cpsid i");
+}
-typedef enum nvic_irq_num {
- NVIC_NMI = -14,
- NVIC_MEM_MANAGE = -12,
- NVIC_BUS_FAULT = -11,
- NVIC_USAGE_FAULT = -10,
- NVIC_SVC = -5,
- NVIC_DEBUG_MON = -4,
- NVIC_PEND_SVC = -2,
- NVIC_SYSTICK = -1,
-
- NVIC_TIMER1_BRK = 24,
- NVIC_TIMER1_UP = 25,
- NVIC_TIMER1_TRG_COM = 26,
- NVIC_TIMER1_CC = 27,
- NVIC_TIMER2 = 28,
- NVIC_TIMER3 = 29,
- NVIC_TIMER4 = 30,
- NVIC_TIMER5 = 50,
- NVIC_TIMER6 = 54,
- NVIC_TIMER7 = 55,
- NVIC_TIMER8_BRK = 43,
- NVIC_TIMER8_UP = 44,
- NVIC_TIMER8_TRG_COM = 45,
- NVIC_TIMER8_CC = 46,
-
- NVIC_USART1 = 37,
- NVIC_USART2 = 38,
- NVIC_USART3 = 39,
- NVIC_UART4 = 52,
- NVIC_UART5 = 53,
-
- NVIC_EXTI0 = 6,
- NVIC_EXTI1 = 7,
- NVIC_EXTI2 = 8,
- NVIC_EXTI3 = 9,
- NVIC_EXTI4 = 10,
- NVIC_EXTI9_5 = 23,
- NVIC_EXTI15_10 = 40,
-
- NVIC_DMA_CH1 = 11,
- NVIC_DMA_CH2 = 12,
- NVIC_DMA_CH3 = 13,
- NVIC_DMA_CH4 = 14,
- NVIC_DMA_CH5 = 15,
- NVIC_DMA_CH6 = 16,
- NVIC_DMA_CH7 = 17,
-
- NVIC_I2C1_EV = 31,
- NVIC_I2C1_ER = 32,
- NVIC_I2C2_EV = 33,
- NVIC_I2C2_ER = 34
-} nvic_irq_num;
+/**
+ * @brief Enable interrupt irq_num
+ * @param irq_num Interrupt to enable
+ */
+static inline void nvic_irq_enable(nvic_irq_num irq_num) {
+ NVIC_BASE->ISER[irq_num / 32] = BIT(irq_num % 32);
+}
-#define nvic_globalirq_enable() asm volatile("cpsie i")
-#define nvic_globalirq_disable() asm volatile("cpsid i")
+/**
+ * @brief Disable interrupt irq_num
+ * @param irq_num Interrupt to disable
+ */
+static inline void nvic_irq_disable(nvic_irq_num irq_num) {
+ NVIC_BASE->ICER[irq_num / 32] = BIT(irq_num % 32);
+}
-void nvic_init(void);
-void nvic_irq_enable(uint32 device);
-void nvic_irq_disable(uint32 device);
-void nvic_irq_disable_all(void);
-void nvic_set_priority(int32 irqn, uint8 priority);
+/**
+ * @brief Quickly disable all interrupts.
+ *
+ * Calling this function is significantly faster than calling
+ * nvic_irq_disable() in a loop.
+ */
+static inline void nvic_irq_disable_all(void) {
+ /* Note: This only works up to XL density. The fix for
+ * connectivity line is:
+ *
+ * NVIC_BASE->ICER[2] = 0xF;
+ *
+ * We don't support connectivity line devices (yet), so leave it
+ * alone for now.
+ */
+ NVIC_BASE->ICER[0] = 0xFFFFFFFF;
+ NVIC_BASE->ICER[1] = 0xFFFFFFFF;
+}
#ifdef __cplusplus
}
diff --git a/libmaple/rules.mk b/libmaple/rules.mk
index a9d7e50..2eaea55 100644
--- a/libmaple/rules.mk
+++ b/libmaple/rules.mk
@@ -9,7 +9,7 @@ BUILDDIRS += $(BUILD_PATH)/$(d)/usb/usb_lib
LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH) -I$(LIBMAPLE_PATH)/usb -I$(LIBMAPLE_PATH)/usb/usb_lib
# Local flags
-CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -D$(VECT_BASE_ADDR)
+CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES)
# Local rules and targets
cSRCS_$(d) := adc.c \
diff --git a/libmaple/scb.h b/libmaple/scb.h
index 8bfdda3..1911435 100644
--- a/libmaple/scb.h
+++ b/libmaple/scb.h
@@ -29,34 +29,32 @@
#ifndef _SCB_H_
#define _SCB_H_
-/* FIXME this definition is missing doxygen comments */
-
+/** System control block register map */
typedef struct scb_reg_map {
- __io uint32 CPUID; // CPU ID Base Register
- __io uint32 ICSR; // Interrupt Control State Register
- __io uint32 VTOR; // Vector Table Offset Register
- __io uint32 AIRCR; // Application Interrupt / Reset Control Register
- __io uint32 SCR; // System Control Register
- __io uint32 CCR; // Configuration Control Register
- __io uint8 SHP[12]; // System Handlers Priority Registers (4-7, 8-11, 12-15)
- __io uint32 SHCSR; // System Handler Control and State Register
- __io uint32 CFSR; // Configurable Fault Status Register
- __io uint32 HFSR; // Hard Fault Status Register
- __io uint32 DFSR; // Debug Fault Status Register
- __io uint32 MMFAR; // Mem Manage Address Register
- __io uint32 BFAR; // Bus Fault Address Register
- __io uint32 AFSR; // Auxiliary Fault Status Register
- __io uint32 PFR[2]; // Processor Feature Register
- __io uint32 DFR; // Debug Feature Register
- __io uint32 ADR; // Auxiliary Feature Register
- __io uint32 MMFR[4]; // Memory Model Feature Register
- __io uint32 ISAR[5]; // ISA Feature Register
+ __io uint32 CPUID; /**< CPU ID Base Register */
+ __io uint32 ICSR; /**< Interrupt Control State Register */
+ __io uint32 VTOR; /**< Vector Table Offset Register */
+ __io uint32 AIRCR; /**< Application Interrupt / Reset Control Register */
+ __io uint32 SCR; /**< System Control Register */
+ __io uint32 CCR; /**< Configuration Control Register */
+ __io uint8 SHP[12]; /**< System Handlers Priority Registers
+ (4-7, 8-11, 12-15) */
+ __io uint32 SHCSR; /**< System Handler Control and State Register */
+ __io uint32 CFSR; /**< Configurable Fault Status Register */
+ __io uint32 HFSR; /**< Hard Fault Status Register */
+ __io uint32 DFSR; /**< Debug Fault Status Register */
+ __io uint32 MMFAR; /**< Mem Manage Address Register */
+ __io uint32 BFAR; /**< Bus Fault Address Register */
+ __io uint32 AFSR; /**< Auxiliary Fault Status Register */
+ __io uint32 PFR[2]; /**< Processor Feature Register */
+ __io uint32 DFR; /**< Debug Feature Register */
+ __io uint32 ADR; /**< Auxiliary Feature Register */
+ __io uint32 MMFR[4]; /**< Memory Model Feature Register */
+ __io uint32 ISAR[5]; /**< ISA Feature Register */
} scb_reg_map;
-/* FIXME these names violate the libmaple naming conventions */
-
-#define SCB_BASE 0xE000ED00
-#define SCB ((scb_reg_map*)(SCB_BASE))
+/** System control block register map base pointer */
+#define SCB_BASE ((struct scb_reg_map*)0xE000ED00)
#endif
diff --git a/libmaple/util.c b/libmaple/util.c
index 6b4f216..77af5b8 100644
--- a/libmaple/util.c
+++ b/libmaple/util.c
@@ -69,8 +69,8 @@ void __error(void) {
usart_disable_all();
/* Turn the USB interrupt back on so the bootloader keeps on functioning */
- nvic_irq_enable(NVIC_INT_USBHP);
- nvic_irq_enable(NVIC_INT_USBLP);
+ nvic_irq_enable(NVIC_USB_HP_CAN_TX);
+ nvic_irq_enable(NVIC_USB_LP_CAN_RX0);
/* Reenable global interrupts */
nvic_globalirq_enable();