📄 iq80310_misc.c
字号:
// Read current state of ECC register
eccr_reg = *ECCR_REG;
// Turn off all ecc error reporting
*ECCR_REG = 0x4;
// Check for ECC Error 0
if(*MCISR_REG & 0x1) {
#ifdef DEBUG_NMI
diag_printf("ELOG0 = 0x%X\n", *ELOG0_REG);
diag_printf("ECC Error Detected at Address 0x%X\n",*ECAR0_REG);
#endif
// Check for single-bit error
if(!(*ELOG0_REG & 0x00000100)) {
// call ECC restoration function
_scrub_ecc(*ECAR0_REG);
// Clear the MCISR
*MCISR_REG = 0x1;
} else {
#ifdef DEBUG_NMI
diag_printf("Multi-bit or nibble error\n");
#endif
}
}
// Check for ECC Error 1
if(*MCISR_REG & 0x2) {
#ifdef DEBUG_NMI
diag_printf("ELOG0 = 0x%X\n",*ELOG1_REG);
diag_printf("ECC Error Detected at Address 0x%X\n",*ECAR1_REG);
#endif
// Check for single-bit error
if(!(*ELOG1_REG & 0x00000100)) {
// call ECC restoration function
_scrub_ecc(*ECAR1_REG);
// Clear the MCISR
*MCISR_REG = 0x2;
}
else {
#ifdef DEBUG_NMI
diag_printf("Multi-bit or nibble error\n");
#endif
}
}
// Check for ECC Error N
if(*MCISR_REG & 0x4) {
// Clear the MCISR
*MCISR_REG = 0x4;
diag_printf("Uncorrectable error during RMW\n");
}
// Restore ECCR register
*ECCR_REG = eccr_reg;
// clear the interrupt condition
*MCISR_REG = *MCISR_REG & 7;
return CYG_ISR_HANDLED;
}
static cyg_uint32 nmi_patu_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_uint32 status;
status = *PATUISR_REG;
#ifdef DEBUG_NMI
if (status & 0x001) diag_printf ("PPCI Master Parity Error\n");
if (status & 0x002) diag_printf ("PPCI Target Abort (target)\n");
if (status & 0x004) diag_printf ("PPCI Target Abort (master)\n");
if (status & 0x008) diag_printf ("PPCI Master Abort\n");
if (status & 0x010) diag_printf ("Primary P_SERR# Detected\n");
if (status & 0x080) diag_printf ("Internal Bus Master Abort\n");
if (status & 0x100) diag_printf ("PATU BIST Interrupt\n");
if (status & 0x200) diag_printf ("PPCI Parity Error Detected\n");
if (status & 0x400) diag_printf ("Primary P_SERR# Asserted\n");
#endif
*PATUISR_REG = status & 0x79f;
*PATUSR_REG |= 0xf900;
return CYG_ISR_HANDLED;
}
static cyg_uint32 nmi_satu_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_uint32 status;
status = *SATUISR_REG;
#ifdef DEBUG_NMI
if (status & 0x001) diag_printf ("SPCI Master Parity Error\n");
if (status & 0x002) diag_printf ("SPCI Target Abort (target)\n");
if (status & 0x004) diag_printf ("SPCI Target Abort (master)\n");
if (status & 0x008) diag_printf ("SPCI Master Abort\n");
if (status & 0x010) diag_printf ("Secondary P_SERR# Detected\n");
if (status & 0x080) diag_printf ("Internal Bus Master Abort\n");
if (status & 0x200) diag_printf ("SPCI Parity Error Detected\n");
if (status & 0x400) diag_printf ("Secondary P_SERR# Asserted\n");
#endif
*SATUISR_REG = status & 0x69f;
*SATUSR_REG |= 0xf900;
return CYG_ISR_HANDLED;
}
static cyg_uint32 nmi_pb_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_uint32 status;
status = *PBISR_REG;
#ifdef DEBUG_NMI
if (status & 0x001) diag_printf ("PPCI Master Parity Error\n");
if (status & 0x002) diag_printf ("PPCI Target Abort (target)\n");
if (status & 0x004) diag_printf ("PPCI Target Abort (master)\n");
if (status & 0x008) diag_printf ("PPCI Master Abort\n");
if (status & 0x010) diag_printf ("Primary P_SERR# Asserted\n");
if (status & 0x020) diag_printf ("PPCI Parity Error Detected\n");
#endif
*PBISR_REG = status & 0x3f;
*PSR_REG |= 0xf900;
return CYG_ISR_HANDLED;
}
static cyg_uint32 nmi_sb_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_uint32 status;
status = *SBISR_REG;
*SBISR_REG = status & 0x7f;
*SSR_REG |= 0xf900;
return CYG_ISR_HANDLED;
}
static cyg_uint32 nfiq_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_uint32 sources;
int i, isr_ret;
// Check NMI
sources = *NISR_REG;
for (i = 0; i < 12; i++) {
if (sources & (1<<i)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MCU_ERR + i);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
return isr_ret;
}
}
return 0;
}
static cyg_uint32 nirq_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_uint32 sources;
int i, isr_ret;
// Check XINT3
sources = *X3ISR_REG & ~(*X3MASK_REG);
for (i = 0; i < 5; i++) {
if (sources & (1 << i)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_TIMER + i);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
return isr_ret;
}
}
// What to do about S_INTA-S_INTC?
// Check XINT6
sources = *X6ISR_REG;
for (i = 0; i < 3; i++) {
// check DMA irqs
if (sources & (1<<i)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_DMA_0 + i);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
return isr_ret;
}
}
if (sources & 0x10) {
// performance monitor
_80312_EMISR = *EMISR_REG;
if (_80312_EMISR & 1) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_GTSC);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (_80312_EMISR & 0x7ffe) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_PEC);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
return 0;
}
if (sources & 0x20) {
// Application Accelerator Unit
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_AAIP);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
return isr_ret;
}
// Check XINT7
sources = *X7ISR_REG;
if (sources & 2) {
// I2C Unit
cyg_uint32 i2c_sources = *ISR_REG;
if (i2c_sources & (1<<7)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_RX_FULL);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (i2c_sources & (1<<6)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (i2c_sources & (1<<10)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_BUS_ERR);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (i2c_sources & (1<<4)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_STOP);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (i2c_sources & (1<<5)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_LOSS);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (i2c_sources & (1<<9)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_ADDRESS);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
return 0;
}
if (sources & 4) {
// Messaging Unit
cyg_uint32 inb_sources = *IISR_REG;
if (inb_sources & (1<<0)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MESSAGE_0);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (inb_sources & (1<<1)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MESSAGE_1);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (inb_sources & (1<<2)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_DOORBELL);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (inb_sources & (1<<4)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_QUEUE_POST);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
if (inb_sources & (1<<6)) {
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_INDEX_REGISTER);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
return 0;
}
if (sources & 8) {
// BIST
isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_BIST);
CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
}
return 0;
}
// This routine is called to respond to a hardware interrupt (IRQ). It
// should interrogate the hardware and return the IRQ vector number.
int hal_IRQ_handler(void)
{
int sources, masks;
asm volatile ( // read the interrupt source reg INTSRC
"mrc p13,0,%0,c4,c0,0;"
: "=r"(sources)
:
/*:*/
);
asm volatile ( // read the interrupt control reg INTCTL
"mrc p13,0,%0,c0,c0,0;"
: "=r"(masks)
:
/*:*/
);
// is a source both unmasked and active?
if ( (0 != (1 & masks)) && (0 != ((8 << 28) & sources)) )
return CYGNUM_HAL_INTERRUPT_NFIQ;
if ( (0 != (2 & masks)) && (0 != ((4 << 28) & sources)) )
return CYGNUM_HAL_INTERRUPT_NIRQ;
if ( (0 != (8 & masks)) && (0 != ((2 << 28) & sources)) )
return CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT;
if ( (0 != (4 & masks)) && (0 != ((1 << 28) & sources)) ) {
// more complicated; it's the PMU.
asm volatile ( // read the PMNC perfmon control reg
"mrc p14,0,%0,c0,c0,0;"
: "=r"(sources)
:
/*:*/
);
// sources is now the PMNC performance monitor control register
// enable bits are 4..6, status bits are 8..10
sources = (sources >> 4) & (sources >> 8);
if ( 1 & sources )
return CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL;
if ( 2 & sources )
return CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL;
if ( 4 & sources )
return CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL;
}
return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
}
//
// Interrupt control
//
void hal_interrupt_mask(int vector)
{
int mask = 0;
int submask = 0;
switch ( vector ) {
case CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL:
case CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL:
case CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL:
submask = vector - CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; // 0 to 2
// select interrupt enable bit and also enable the perfmon per se
submask = (1 << (submask + 4)); // bits 4-6 are masks
asm volatile (
"mrc p14,0,r1,c0,c0,0;"
"bic r1, r1, #0x700;" // clear the overflow/interrupt flags
"bic r1, r1, #0x006;" // clear the reset bits
"bic %0, r1, %0;" // preserve r1; better for debugging
"tsts %0, #0x070;" // are all 3 sources now off?
"biceq %0, %0, #1;" // if so, disable entirely.
"mcr p14,0,%0,c0,c0,0;"
:
: "r"(submask)
: "r1"
);
mask = 4;
break;
case CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT:
// Nothing specific to do here
mask = 8;
break;
case CYGNUM_HAL_INTERRUPT_NIRQ :
mask = 2;
break;
case CYGNUM_HAL_INTERRUPT_NFIQ :
mask = 1;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -