implemented interrupt controller handling in register_interrupt_handler()

This commit is contained in:
Markus Fröschle
2013-12-15 08:44:28 +00:00
parent 324657ffbc
commit e6c8cc36bd
3 changed files with 27 additions and 49 deletions

View File

@@ -77,5 +77,5 @@
#define INT_SOURCE_GPT0 62 // GPT0 timer interrupt #define INT_SOURCE_GPT0 62 // GPT0 timer interrupt
extern int register_interrupt_handler(uint8_t priority, uint8_t intr, void (*func)()); extern int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void));
#endif /* _INTERRUPTS_H_ */ #endif /* _INTERRUPTS_H_ */

View File

@@ -25,77 +25,55 @@
#include <stdint.h> #include <stdint.h>
#include "MCF5475.h" #include "MCF5475.h"
#include "bas_utils.h" #include "bas_utils.h"
#include "exceptions.h"
#include "interrupts.h" #include "interrupts.h"
extern uint32_t rt_vbr[]; extern void (*rt_vbr[])(void);
#define VBR rt_vbr #define VBR rt_vbr
/* /*
* register an interrupt handler at the Coldfire interrupt controller and add the handler to * register an interrupt handler at the Coldfire interrupt controller and add the handler to
* the interrupt vector table * the interrupt vector table
*/ */
int register_interrupt_handler(uint8_t priority, uint8_t source, void (*func)()) int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void))
{ {
int ipl;
int i; int i;
uint8_t level = 0b01111111; uint8_t *ICR = &MCF_INTC_ICR01 - 1;
uint32_t **adr = &VBR[0]; uint8_t lp;
source &= 63; source &= 63;
priority &= 7; priority &= 7;
if (source <= 0) if (source < 1 || source > 63)
{
xprintf("%s: interrupt source %d not defined\r\n", __FUNCTION__, source);
return -1; return -1;
}
lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority);
/* check if this combination is already set somewhere */
for (i = 1; i < 64; i++) for (i = 1; i < 64; i++)
{ {
if (i != source) if (ICR[i] == lp)
{ {
if ((MCF_INTC_ICR(i) & 7) == priority) xprintf("%s: level %d and priority %d already used for interrupt source %d!\r\n", __FUNCTION__,
CLEAR_BIT_NO(level, (MCF_INTC_ICR(i) >> 3) & 7); level, priority, i);
return -1;
} }
} }
for (i = 0; i <= 7; i++) /* disable interrupts */
if (level & (1 << i)) ipl = set_ipl(7);
break;
if (i > 7) VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
return -1;
/* /* set level and priority in interrupt controller */
* Make sure priority level is high, before changing registers ICR[source] = lp;
*/
__asm__ volatile (
"move.w sr,d0\n\t"
"move.w d0,srsave \n\t"
"move.w #0x2700,sr\n\t"
" .bss\n\t"
"srsave: ds.w 1\n\t"
" .text\n\t"
:
:
: "d0","memory"
);
if (source < 32) /* set interrupt mask to where it was before */
CLEAR_BIT(MCF_INTC_IMRL, (1 << source)); set_ipl(ipl);
else
CLEAR_BIT(MCF_INTC_IMRH, (1 << (source - 32)));
MCF_INTC_ICR(source) = MCF_INTC_ICR_IP(priority) | MCF_INTC_ICR_IL(i);
adr[64 + source] = (uint32_t *) func; /* first 64 vectors are system exceptions */
/*
* Return the saved priority level
*/
__asm__ volatile (
"move.w srsave,d2\n\t"
"move.w d2,sr\n\t"
:
:
: "d2","memory"
);
return 0; return 0;
} }

View File

@@ -699,10 +699,10 @@ void init_pci(void)
xprintf("initializing PCI bridge:\r\n"); xprintf("initializing PCI bridge:\r\n");
(void) res; /* for now */ (void) res; /* for now */
res = register_interrupt_handler(0, INT_SOURCE_PCIARB, pci_arb_interrupt); res = register_interrupt_handler(0, INT_SOURCE_PCIARB, 5, 5, pci_arb_interrupt);
debug_printf("registered interrupt handler for PCI arbiter: %s\r\n", debug_printf("registered interrupt handler for PCI arbiter: %s\r\n",
(res < 0 ? "failed" : "succeeded")); (res < 0 ? "failed" : "succeeded"));
register_interrupt_handler(0, INT_SOURCE_XLBPCI, xlb_pci_interrupt); register_interrupt_handler(0, INT_SOURCE_XLBPCI, 5, 5, xlb_pci_interrupt);
debug_printf("registered interrupt handler for XLB PCI: %s\r\n", debug_printf("registered interrupt handler for XLB PCI: %s\r\n",
(res < 0 ? "failed" : "succeeded")); (res < 0 ? "failed" : "succeeded"));