Implement interrupt as thread
This commit is contained in:
@@ -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.
|
||||
|
||||
83
chopstx.c
83
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
23
entry.c
23
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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user