diff options
author | Perry Hung <iperry@alum.mit.edu> | 2010-08-04 08:52:30 -0400 |
---|---|---|
committer | Perry Hung <iperry@alum.mit.edu> | 2010-08-04 08:52:30 -0400 |
commit | d2494611156c4ba477a1bbd1b07ba0cfc14b29e4 (patch) | |
tree | 48782014152efa392ac0689c4098e089da52c82c | |
parent | 2b7a1b40c96525cd4c6324f6e9d53845fb07a55f (diff) | |
download | librambutan-d2494611156c4ba477a1bbd1b07ba0cfc14b29e4.tar.gz librambutan-d2494611156c4ba477a1bbd1b07ba0cfc14b29e4.zip |
Cleaned up wirish/time, some interrupt handling refactoring:
Fixed millis(), it was just wrong, before.
Added micros(), not extensively tested.
New implementation of delayMicroseconds(). Should be more consistent
now.
Added a handful of nvic routines to enable/disable interrupts.
Cleaned up systick
-rw-r--r-- | libmaple/nvic.c | 26 | ||||
-rw-r--r-- | libmaple/nvic.h | 21 | ||||
-rw-r--r-- | libmaple/systick.c | 18 | ||||
-rw-r--r-- | libmaple/systick.h | 25 | ||||
-rw-r--r-- | libmaple/timers.c | 9 | ||||
-rw-r--r-- | libmaple/usart.c | 2 | ||||
-rw-r--r-- | libmaple/util.h | 2 | ||||
-rw-r--r-- | wirish/time.c | 53 | ||||
-rw-r--r-- | wirish/time.h | 50 | ||||
-rw-r--r-- | wirish/wirish.c | 2 |
10 files changed, 86 insertions, 122 deletions
diff --git a/libmaple/nvic.c b/libmaple/nvic.c index d8745a4..56b9940 100644 --- a/libmaple/nvic.c +++ b/libmaple/nvic.c @@ -32,16 +32,6 @@ #include "nvic.h" #include "systick.h" -void nvic_disable_interrupts(void) { - /* Turn off all interrupts */ - REG_SET(NVIC_ICER0, 0xFFFFFFFF); - REG_SET(NVIC_ICER1, 0xFFFFFFFF); - - /* Turn off systick exception */ - REG_CLEAR_BIT(SYSTICK_CSR, 0); -} - - void nvic_set_vector_table(uint32 addr, uint32 offset) { __write(SCB_VTOR, (uint32)addr | (offset & 0x1FFFFF80)); } @@ -49,13 +39,9 @@ void nvic_set_vector_table(uint32 addr, uint32 offset) { /** * @brief turn on interrupt number n - * @param[in] n interrupt number + * @param n interrupt number */ -void nvic_enable_interrupt(uint32 n) { - if (n >= NVIC_NR_INTERRUPTS) { - return; - } - +void nvic_irq_enable(uint32 n) { if (n < 32) { REG_SET_BIT(NVIC_ISER0, n); } else { @@ -65,13 +51,9 @@ void nvic_enable_interrupt(uint32 n) { /** * @brief turn off interrupt number n - * @param[in] n interrupt number + * @param n interrupt number */ -void nvic_disable_interrupt(uint32 n) { - if (n >= NVIC_NR_INTERRUPTS) { - return; - } - +void nvic_irq_disable(uint32 n) { if (n < 32) { REG_SET_BIT(NVIC_ICER0, n); } else { diff --git a/libmaple/nvic.h b/libmaple/nvic.h index 6cad48d..d256610 100644 --- a/libmaple/nvic.h +++ b/libmaple/nvic.h @@ -52,8 +52,6 @@ #define NVIC_VectTab_RAM ((u32)0x20000000) #define NVIC_VectTab_FLASH ((u32)0x08000000) -#define NVIC_NR_INTERRUPTS 60 - /* Where to put code */ #define USER_ADDR_ROM 0x08005000 #define USER_ADDR_RAM 0x20000C00 @@ -63,15 +61,22 @@ extern "C"{ #endif enum { - NVIC_USART1 = 37, - NVIC_USART2 = 38, - NVIC_USART3 = 39, + NVIC_TIMER1 = 27, + NVIC_TIMER2 = 28, + NVIC_TIMER3 = 29, + NVIC_TIMER4 = 30, + NVIC_USART1 = 37, + NVIC_USART2 = 38, + NVIC_USART3 = 39, }; + +#define nvic_globalirq_enable() asm volatile("cpsid i") +#define nvic_globalirq_disable() asm volatile("cpsie i") + void nvic_init(void); -void nvic_disable_interrupts(void); -void nvic_enable_interrupt(uint32 device); -void nvic_disable_interrupt(uint32 device); +void nvic_irq_enable(uint32 device); +void nvic_irq_disable(uint32 device); #ifdef __cplusplus } diff --git a/libmaple/systick.c b/libmaple/systick.c index a333528..8b0d92a 100644 --- a/libmaple/systick.c +++ b/libmaple/systick.c @@ -31,23 +31,25 @@ #include "libmaple.h" #include "systick.h" -#define MILLIS_INC 1 +#define SYSTICK_RELOAD 0xE000E014 // Reload value register +#define SYSTICK_CNT 0xE000E018 // Current value register +#define SYSTICK_CALIB 0xE000E01C // Calibration value register + +#define SYSTICK_SRC_HCLK BIT(2) // Use core clock +#define SYSTICK_TICKINT BIT(1) // Interrupt on systick countdown +#define SYSTICK_ENABLE BIT(0) // Turn on the counter volatile uint32 systick_timer_millis = 0; -void systick_init(void) { +void systick_init(uint32 reload_val) { /* Set the reload counter to tick every 1ms */ - REG_SET_MASK(SYSTICK_RELOAD, MAPLE_RELOAD_VAL); -// SYSTICK_RELOAD = MAPLE_RELOAD_VAL; + __write(SYSTICK_RELOAD, reload_val); /* Clock the system timer with the core clock * and turn it on, interrrupt every 1ms to keep track of millis()*/ - REG_SET(SYSTICK_CSR, SYSTICK_SRC_HCLK | + __write(SYSTICK_CSR, SYSTICK_SRC_HCLK | SYSTICK_ENABLE | SYSTICK_TICKINT); -// SYSTICK_CSR = SYSTICK_SRC_HCLK | -// SYSTICK_ENABLE | -// SYSTICK_TICKINT; } void SysTickHandler(void) { diff --git a/libmaple/systick.h b/libmaple/systick.h index d0a623f..57b724a 100644 --- a/libmaple/systick.h +++ b/libmaple/systick.h @@ -33,30 +33,23 @@ #include "libmaple.h" -/* To the ARM technical manual... there's nearly nothing on the systick - * timer in the stm32 manual */ +#define SYSTICK_CSR 0xE000E010 // Control and status register +#define SYSTICK_CNT 0xE000E018 // Current value register -#define SYSTICK_CSR 0xE000E010 // Control and status register -#define SYSTICK_RELOAD 0xE000E014 // Reload value register -#define SYSTICK_CNT 0xE000E018 // Current value register -#define SYSTICK_CALIB 0xE000E01C // Calibration value register - -#define SYSTICK_SRC_HCLK BIT(2) // Use core clock -#define SYSTICK_TICKINT BIT(1) // Interrupt on systick countdown -#define SYSTICK_ENABLE BIT(0) // Turn on the counter - -/* We use the systick timer to tick once - * every millisecond */ -#define MAPLE_RELOAD_VAL 72000 +#define SYSTICK_CSR_COUNTFLAG BIT(16) #ifdef __cplusplus extern "C"{ #endif -void systick_init(void); +void systick_init(uint32 reload_val); static inline uint32 systick_get_count(void) { - return (uint32)*(volatile uint32*)SYSTICK_CNT; + return __read(SYSTICK_CNT); +} + +static inline uint32 systick_check_underflow(void) { + return (__read(SYSTICK_CSR) & SYSTICK_CSR_COUNTFLAG); } #ifdef __cplusplus diff --git a/libmaple/timers.c b/libmaple/timers.c index a3890d4..6e6653c 100644 --- a/libmaple/timers.c +++ b/libmaple/timers.c @@ -30,6 +30,7 @@ #include "libmaple.h" #include "rcc.h" +#include "nvic.h" #include "timers.h" typedef struct { @@ -476,25 +477,25 @@ void timer_attach_interrupt(uint8 timer_num, uint8 compare_num, voidFuncPtr hand case 1: timer = (Timer*)TIMER1_BASE; timer1_handlers[compare_num-1] = handler; - nvic_enable_interrupt(27); + nvic_irq_enable(NVIC_TIMER1); timer->DIER |= (1 << compare_num); // 1-indexed compare nums break; case 2: timer = (Timer*)TIMER2_BASE; timer2_handlers[compare_num-1] = handler; - nvic_enable_interrupt(28); + nvic_irq_enable(NVIC_TIMER2); timer->DIER |= (1 << compare_num); // 1-indexed compare nums break; case 3: timer = (Timer*)TIMER3_BASE; timer3_handlers[compare_num-1] = handler; - nvic_enable_interrupt(29); + nvic_irq_enable(NVIC_TIMER3); timer->DIER |= (1 << compare_num); // 1-indexed compare nums break; case 4: timer = (Timer*)TIMER4_BASE; timer4_handlers[compare_num-1] = handler; - nvic_enable_interrupt(30); + nvic_irq_enable(NVIC_TIMER4); timer->DIER |= (1 << compare_num); // 1-indexed compare nums break; } diff --git a/libmaple/usart.c b/libmaple/usart.c index 53a6150..296a1fb 100644 --- a/libmaple/usart.c +++ b/libmaple/usart.c @@ -93,7 +93,7 @@ void usart_init(uint8 usart_num, uint32 baud) { port = usart_dev_table[usart_num].base; rcc_clk_enable(usart_dev_table[usart_num].rcc_dev_num); - nvic_enable_interrupt(usart_dev_table[usart_num].nvic_dev_num); + nvic_irq_enable(usart_dev_table[usart_num].nvic_dev_num); /* usart1 is mad fast */ clk_speed = (usart_num == USART1) ? 72000000UL : 36000000UL; diff --git a/libmaple/util.h b/libmaple/util.h index 8cfc60c..c336e21 100644 --- a/libmaple/util.h +++ b/libmaple/util.h @@ -48,8 +48,6 @@ #define BITBAND_PERI_BASE 0x42000000 #define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4))) // Convert PERI address -#define COUNTFLAG *((volatile unsigned char*) (BITBAND_PERI(SYSTICK_CSR,2))) - #define REG_SET(reg, val) (*(volatile uint32*)(reg) = (val)) #define REG_SET_BIT(reg, bit) (*(volatile uint32*)(reg) |= BIT(bit)) #define REG_CLEAR_BIT(reg, bit) (*(volatile uint32*)(reg) &= ~BIT(bit)) diff --git a/wirish/time.c b/wirish/time.c index 69e962c..c0fd03e 100644 --- a/wirish/time.c +++ b/wirish/time.c @@ -23,8 +23,6 @@ * ****************************************************************************/ /** - * @file time.c - * * @brief */ @@ -32,46 +30,23 @@ #include "systick.h" #include "time.h" -#define CYCLES_PER_MICROSECOND 72 -#define FUDGE 42 - -extern volatile uint32 systick_timer_millis; - -uint32 millis() { - unsigned long m; - m = systick_timer_millis; - return m; -} - void delay(unsigned long ms) { - unsigned long start = millis(); - - while (millis() - start <= ms) - ; + uint32 i; + for (i = 0; i < ms; i++) { + delayMicroseconds(1000); + } } - - -#if 1 void delayMicroseconds(uint32 us) { - uint32 target; - uint32 last, cur, count; - /* fudge factor hacky hack hack for function overhead */ - target = us * CYCLES_PER_MICROSECOND - FUDGE; - - /* Get current count */ - last = systick_get_count(); - cur = systick_get_count(); - count = last; - while ((count-cur) <= target) { - cur = systick_get_count(); - - /* check for overflow */ - if (cur > last) { - count += MAPLE_RELOAD_VAL; - } - last = cur; - } + us *= 12; + + /* fudge for function call overhead */ + us--; + asm volatile(" mov r0, %[us] \n\t" + "1: subs r0, #1 \n\t" + " bhi 1b \n\t" + : + : [us] "r" (us) + : "r0"); } -#endif diff --git a/wirish/time.h b/wirish/time.h index 9e5536b..45e82dc 100644 --- a/wirish/time.h +++ b/wirish/time.h @@ -23,8 +23,6 @@ * ****************************************************************************/ /** - * @file time.h - * * @brief */ @@ -34,32 +32,42 @@ #ifdef __cplusplus extern "C"{ #endif -/* Returns time since boot in milliseconds */ -uint32 millis(void); + +#include "nvic.h" +#include "systick.h" + +#define CYCLES_PER_MICROSECOND 72 +#define US_PER_MS 1000 +#define MAPLE_RELOAD_VAL 72000 + +extern volatile uint32 systick_timer_millis; + +/* time in milliseconds since boot */ +static inline uint32 millis(void) { + return systick_timer_millis; +} /* Time in microseconds since boot */ -uint32 micros(void); +static inline uint32 micros(void) { + uint32 ms; + uint32 cycle_cnt; + uint32 res; -/* Delay for ms milliseconds */ -void delay(unsigned long ms); + nvic_globalirq_disable(); -/* Delay for us microseconds */ -void delayMicroseconds(uint32 us); + cycle_cnt = systick_get_count(); + ms = millis(); + + nvic_globalirq_enable(); -#if 0 -static inline void delay_us(uint32 us) { - us *= 12; - asm volatile("mov r0, %[us] \n\t" - "subs r0, #2 \n\t" -"1: \n\t" - "subs r0, r0, #1 \n\t" - "bne 1b" - : - : [us] "r" (us) - : "r0", "cc"); + res = (ms * US_PER_MS) + (MAPLE_RELOAD_VAL - cycle_cnt)/CYCLES_PER_MICROSECOND; + return res; } -#endif + +void delay(unsigned long ms); +void delayMicroseconds(uint32 us); + #ifdef __cplusplus } // extern "C" #endif diff --git a/wirish/wirish.c b/wirish/wirish.c index 1938ec9..4281875 100644 --- a/wirish/wirish.c +++ b/wirish/wirish.c @@ -53,7 +53,7 @@ void init(void) { rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1); nvic_init(); - systick_init(); + systick_init(MAPLE_RELOAD_VAL); gpio_init(); adc_init(); timer_init(1, 1); |