From aa3fd9876abe2131d2ebda9a418ade6a4b89f72c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka <gniibe@fsij.org> Date: Wed, 22 May 2013 16:43:58 +0900 Subject: Implement interrupt as thread --- ChangeLog | 9 +++++++ chopstx.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- chopstx.h | 3 ++- entry.c | 23 +++++++++++++++--- 4 files changed, 101 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index e8f77e2..19274fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2013-05-22 Niibe Yutaka <gniibe@fsij.org> + + * chopstx.c (chx_enable_intr, chx_disable_intr): Implement. + (chx_set_intr_prio): New. + (chx_handle_intr): Use list to register interrupt threads. + (chx_init): Set PendSV priority (as minimum: bigger). + + * entry.c (vector_table): set chx_handle_intr for all interrupts. + 2013-05-21 Niibe Yutaka <gniibe@fsij.org> * Initial commit. diff --git a/chopstx.c b/chopstx.c index cb46f80..80df272 100644 --- a/chopstx.c +++ b/chopstx.c @@ -99,6 +99,31 @@ struct chx_stack_regs { #define INITIAL_XPSR 0x01000000 /* T=1 */ +/* + * NVIC: Nested Vectored Interrupt Controller + */ +struct NVIC { + uint32_t ISER[8]; + uint32_t unused1[24]; + uint32_t ICER[8]; + uint32_t unused2[24]; + uint32_t ISPR[8]; + uint32_t unused3[24]; + uint32_t ICPR[8]; + uint32_t unused4[24]; + uint32_t IABR[8]; + uint32_t unused5[56]; + uint32_t IPR[60]; +}; + +static struct NVIC *const NVICBase = (struct NVIC *const)0xE000E100; +#define NVIC_ISER(n) (NVICBase->ISER[n >> 5]) +#define NVIC_ICER(n) (NVICBase->ICER[n >> 5]) +#define NVIC_ICPR(n) (NVICBase->ICPR[n >> 5]) +#define NVIC_IPR(n) (NVICBase->IPR[n >> 2]) + +#define USB_LP_CAN1_RX0_IRQn 20 + /* * SysTick registers. */ @@ -465,21 +490,51 @@ chx_timer_expired (void) static void chx_enable_intr (uint8_t irq_num) { + NVIC_ISER (irq_num) = 1 << (irq_num & 0x1f); } static void chx_disable_intr (uint8_t irq_num) { + NVIC_ICER (irq_num) = 1 << (irq_num & 0x1f); } -void -chx_handle_intr (chopstix_intr_t *intr) +#define INTR_PRIO (11<<4) + +static void +chx_set_intr_prio (uint8_t n) { - chx_disable_intr (intr->irq_num); - asm volatile ("cpsid i" : : : "memory"); - intr->ready++; - if (intr->t) + unsigned int sh = (n & 3) << 3; + + NVIC_IPR (n) = (NVIC_IPR(n) & ~(0xFF << sh)) | (INTR_PRIO << sh); +} + +static chopstix_intr_t *intr_top; + +void +chx_handle_intr (void) +{ + chopstix_intr_t *intr; + register uint32_t irq_num; + + asm volatile ("cpsid i\n\t" + "mrs %0, IPSR\n\t" + "sub %0, #16" /* Exception # - 16 = interrupt number. */ + : "=r" (irq_num) : /* no input */ : "memory"); + chx_disable_intr (irq_num); + for (intr = intr_top; intr; intr = intr->next) + if (intr->irq_num == irq_num) + break; + + if (intr == NULL) + { /* Interrupt from unregistered source. */ + asm volatile ("cpsie i" : : : "memory"); + return; + } + + if (intr->t && intr->t->v == THREAD_WAIT_INT) { + intr->ready++; chx_ready_enqueue (intr->t); chx_preempt (); } @@ -494,11 +549,16 @@ chx_systick_init (void) *SYST_CSR = 7; } +static uint32_t *const SHPR3 = (uint32_t *const)0xE000ED20; +#define INTR_PRIO_PENDSV (15<<4) + #define PRIO_DEFAULT 1 void chx_init (struct chx_thread *tp) { + *SHPR3 = (INTR_PRIO_PENDSV << 16); + memset (&tp->tc, 0, sizeof (tp->tc)); q_ready.next = q_ready.prev = (struct chx_thread *)&q_ready; q_timer.next = q_timer.prev = (struct chx_thread *)&q_timer; @@ -784,14 +844,13 @@ chopstx_cond_broadcast (chopstx_cond_t *cond) } -#define MAX_INTR_NUM 16 - -chopstix_intr_t *intr_table[MAX_INTR_NUM]; - void chopstx_intr_register (chopstix_intr_t *intr, uint8_t irq_num) { - intr_table[irq_num] = intr; + chx_disable_intr (irq_num); + chx_set_intr_prio (irq_num); + intr->next = intr_top; + intr_top = intr; intr->irq_num = irq_num; intr->t = running; intr->ready = 0; @@ -801,8 +860,8 @@ chopstx_intr_register (chopstix_intr_t *intr, uint8_t irq_num) void chopstx_wait_intr (chopstix_intr_t *intr) { - chx_enable_intr (intr->irq_num); asm volatile ("cpsid i" : : : "memory"); + chx_enable_intr (intr->irq_num); while (intr->ready == 0) { intr->t = running; diff --git a/chopstx.h b/chopstx.h index 6ab9b87..83c9999 100644 --- a/chopstx.h +++ b/chopstx.h @@ -77,8 +77,9 @@ void chopstx_cond_signal (chopstx_cond_t *cond); void chopstx_cond_broadcast (chopstx_cond_t *cond); typedef struct chx_intr { - struct chx_thread *t; + struct chx_intr *next; struct chx_spinlock lock; + struct chx_thread *t; uint8_t irq_num; uint8_t ready; } chopstix_intr_t; diff --git a/entry.c b/entry.c index 45f0da6..0eceaca 100644 --- a/entry.c +++ b/entry.c @@ -314,6 +314,7 @@ extern uint8_t __main_stack_end__; extern void svc (void); extern void preempt (void); extern void chx_timer_expired (void); +extern void chx_handle_intr (void); handler vector_table[] __attribute__ ((section(".startup.vectors"))) = { (handler)&__main_stack_end__, @@ -333,11 +334,25 @@ handler vector_table[] __attribute__ ((section(".startup.vectors"))) = { preempt, /* PendSV */ chx_timer_expired, /* SysTick */ /* 0x40 */ - none, none, none, none, none, none, none, none, + chx_handle_intr /* WWDG */, chx_handle_intr /* PVD */, + chx_handle_intr /* TAMPER */, chx_handle_intr /* RTC */, + chx_handle_intr /* FLASH */, chx_handle_intr /* RCC */, + chx_handle_intr /* EXTI0 */, chx_handle_intr /* EXTI1 */, /* 0x60 */ - none, none, none, none, none, none, none, none, + chx_handle_intr /* EXTI2 */, chx_handle_intr /* EXTI3 */, + chx_handle_intr /* EXTI4 */, chx_handle_intr /* DMA1 CH1 */, + chx_handle_intr /* DMA1 CH2 */, chx_handle_intr /* DMA1 CH3 */, + chx_handle_intr /* DMA1 CH4 */, chx_handle_intr /* DMA1 CH5 */, /* 0x80 */ - none, none, none, none, + chx_handle_intr /* DMA1 CH6 */, chx_handle_intr /* DMA1 CH7 */, + chx_handle_intr /* ADC1_2 */, chx_handle_intr /* USB HP */, /* 0x90 */ - none, + chx_handle_intr, /* USB LP */ + /* ... and more. CAN, EXT9_5, TIMx, I2C, SPI, USART, EXT15_10 */ + chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr, + chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr, + chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr, + chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr, + chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr, + chx_handle_intr, chx_handle_intr, }; -- cgit v1.2.3