⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 epic.c

📁 PowerPC 8240 的ucosII 移植代码 开发平台为 DiabData
💻 C
字号:
/*
 * file: epic.c
 *
 * PowerPC 8240  interrupt controller support
 * for UCOS-II
 *
 * Author: Ernie Price
 * eprice@bitwise.net
 *
 */
#include "includes.h"

#define PRIO (--pri << 16)      // used by epic_InitEPIC

typedef struct irqHandler_t
{
    INT32U arg;
    void (*handler)(INT32U);
} irqHandler_t;

static irqHandler_t interruptHandlers[MAX_HANDLERS + 1];

#define epicwd(x) \
    INT32U x; \
    INT32U dum##x[3]
#define epicres(n, x) \
    INT32U res##n[x]
/***********************************************************************

   The EPIC hardware structure 

   It is broken into three parts to avoid indexes over 64 Kb

*/
#pragma pack (0,0,1)    // treat as little-endian

volatile struct epicA
{
    epicwd  (FRR);      // Feature reporting register (FRR) NIRQ, NCPU, VID
    epicres (1, 4);     // Reserved
    epicwd  (GCR);      // Global configuration register (GCR) R (reset), M (mode)
#define EPIC_RESET (1 << 31)
#define EPIC_MODE  (1 << 29)
    epicwd  (EICR);     // epic interrupt configuration register (EICR) R (clock ratio), SIE
    epicres (2, 16);    // 0x4_1040 - 0x4_1070 Reserved
    epicwd  (EVI);      // epic vendor identification register (EVI) STEP, DEVICE_ID, VENDOR_ID
    epicwd  (PI);       // Processor initialization register (PI) P0
    epicres (3, 16);    // 0x4_10A0 - 0x4_10D0 Reserved
    epicwd  (SVR);      // Spurious vector register (SVR) VECTOR
    epicwd  (TFRR);     // Timer frequency reporting register (TFRR) TIMER_FREQ
    struct
    {
        epicwd (GTCCR); // Global timer current count register (GTCCR0) T (toggle), COUNT
        epicwd (GTBCR); // Global timer base count register (GTBCR0) CI, BASE_COUNT
        epicwd (GTVPR); // Global timer vector/priority register (GTVPR0) M, A, PRIORITY, VECTOR
        epicwd (GTDR);  // Global timer destination register (GTDR0) P0
    } tmr[4];
}; 

volatile struct epicB
{
    union
    {
        struct
        {
            epicwd (IVPR); // IRQ0 vector/priority register (IVPR0) M, A, P, S, PRIORITY, VECTOR
#define IMASK        (1 << 31)
#define ACTIVE       (1 << 30)
#define ACT_HIGH     (1 << 23)
#define LVL_SENS     (1 << 22) 
#define DEF_LOW   (IMASK | LVL_SENS) 

            epicwd (IDR);  // IRQ0 destination register (IDR0) P0
        } Irq[5];
        struct 
        {
            epicwd (SVPR); // Serial interrupt 0 vector/priority register (SVPR0) M, A, P, S, PRIORITY, VECTOR
            epicwd (SDR);  // Serial interrupt 0 destination register (SDR0) P0
        } Ser[16];
    } x;

    epicres (1, 776);    // 0x5_0400 - 0x5_1010 Reserved 
    struct
    {
        epicwd (IIVPR);  // I2C interrupt vector/priority register (IIVPR0) M, A, PRIORITY, VECTOR
        epicwd (IIDR);   // I2C interrupt destination register (IIDR0) P0
    } IDM[10];
}; 

volatile struct epicC
{
    epicwd  (PCTPR);     // Processor current task priority register (PCTPR) TASKP
    epicres (1, 4);
    epicwd  (IACK);      // Processor interrupt acknowledge register (IACK) VECTOR
    epicwd  (EOI);       // Processor end-of-interrupt register (EOI) EOI_CODE
}; 

#pragma pack (0)

static struct epicA *epicA = (struct epicA *)(EUMB_BASE + 0x41000);
static struct epicB *epicB = (struct epicB *)(EUMB_BASE + 0x50200);
static struct epicC *epicC = (struct epicC *)(EUMB_BASE + 0x60080);

// End EPIC hardware structure

/*
    \brief Initializes the EPIC
*/
void epic_InitEPIC(void)
{
    INT32S  i, pri = 16;

    epicA->GCR = EPIC_RESET;                        // reset the controller
    DelayNusec(10);

    for (i = 0; i < 5; i++)                
        epicB->x.Irq[i].IVPR = DEF_LOW | PRIO;      // set IRQ0 - IRQ4 behavior

    epicB->x.Irq[IRQ3].IVPR |= ACT_HIGH;            // for the 16C550 on SBC8240

    epicB->IDM[I2C   - I2C].IIVPR = IMASK | PRIO;   // set I2C  behavior
    epicB->IDM[DMA0  - I2C].IIVPR = IMASK | PRIO;   // set DMA0  behavior
    epicB->IDM[MSGU  - I2C].IIVPR = IMASK | PRIO;   // set Msg Unit behavior
    epicB->IDM[UART0 - I2C].IIVPR = IMASK | PRIO;   // set UART0 behavior on 8241/5

    epicA->tmr[TMR0 - TMR0].GTVPR = IMASK | PRIO;   // set TMR0 behavior

    epicA->SVR   = MAX_HANDLERS;
    epicA->GCR   = EPIC_MODE;                       // mixed mode
    epicC->PCTPR = 0;                               // allow interrupts
}

/*
    \brief Returns a pointer to the specified vector priority register
*/
static INT32U *GetAddrVPR(INT32U intLevel)
{
    if (intLevel < I2C)                            // irq0 - irq4
        return &epicB->x.Irq[intLevel].IVPR;

    if (intLevel < TMR0)                           // internal I2C, DMA, UART, etc
        return &epicB->IDM[intLevel - I2C].IIVPR;

    if (intLevel < MAX_HANDLERS)                   // timers
        return &epicA->tmr[intLevel - TMR0].GTVPR;

    return (INT32U*)0;                             // no such interrupt
}


/*
    \brief Fetches the IRQ vector from the epic and invokes the handler
*/
void EIE_Hdlr(void)
{
    INT32U epicIntSrc;

    epicIntSrc = epicC->IACK;           // fetch highest priority vector

    if (epicIntSrc != MAX_HANDLERS)
    {
        irqHandler_t *hndlentry;
        hndlentry = &interruptHandlers[epicIntSrc];
        (*hndlentry->handler) (hndlentry->arg);
    }
    epicC->EOI = 0;
}

/*
    \brief Enables the interrupt for the specified vector
*/
void epic_EnableInterrupt(INT32U vector)
{
    INT32U  *ptrVPR, value;
    MSR_SAVE;

    ptrVPR = GetAddrVPR(vector);
    if (ptrVPR)
    {
        OS_ENTER_CRITICAL();

        value  = RE_LONG(ptrVPR);
        value |= vector;
        value &= ~IMASK;
        RE_LONG(ptrVPR) = value;
        OS_EXIT_CRITICAL();
    }
}

/*
    \brief Disables the interrupt for the specified vector
*/
void epic_DisbleInterrupt(INT32U vector)
{
    INT32U *ptrVPR, value;
    MSR_SAVE;

    ptrVPR = GetAddrVPR(vector);
    if (ptrVPR)
    {
        OS_ENTER_CRITICAL();
        value  = RE_LONG(ptrVPR);
        value |= IMASK;
        RE_LONG(ptrVPR) = value;
        OS_EXIT_CRITICAL();
    }
}

/*
    \brief Adds an IRQ handler and enables the interrupt for it
*/
void epic_AddHandler(
    INT32U  id,             // Interrupt vector number
    void    (*handler) (),  // Pointer to Interrupt Handler Function
    INT32U  arg             // Argument to pass to the Handler
)
{
    MSR_SAVE;

    if (id >= MAX_HANDLERS)
        return;

    OS_ENTER_CRITICAL();

    interruptHandlers[id].handler = handler;
    interruptHandlers[id].arg     = arg;

    epic_EnableInterrupt(id);
    OS_EXIT_CRITICAL();
}

/* End of Source */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -