void MIPS32 IntConfigureSystem(u8 mode) { unsigned int temp; asm("di"); // Disable all interrupts temp = _CP0_GET_STATUS(); // Get Status temp |= 0x00400000; // Set BEV bit _CP0_SET_STATUS(temp); // Update Status #if defined(PIC32_PINGUINO_220) || defined(GENERIC32MX250F128) || defined(GENERIC32MX220F032) _CP0_SET_EBASE(0xBD003000); // Set an EBase value of 0xBD003000 #else _CP0_SET_EBASE(0xBD005000); // Set an EBase value of 0xBD005000 #endif _CP0_SET_INTCTL(0x00000020); // Set the Vector Spacing to non-zero value temp = _CP0_GET_CAUSE(); // Get Cause temp |= 0x00800000; // Set IV _CP0_SET_CAUSE(temp); // Update Cause temp = _CP0_GET_STATUS(); // Get Status temp &= 0xFFBFFFFD; // Clear BEV and EXL _CP0_SET_STATUS(temp); // Update Status switch (mode) { case INT_SYSTEM_CONFIG_MULT_VECTOR: // Set the CP0 registers for multi-vector interrupt INTCONSET = 0x1000; // Set MVEC bit break; case INT_SYSTEM_CONFIG_SINGLE_VECTOR: // Set the CP0 registers for single-vector interrupt INTCONCLR = 0x1000; // Clear MVEC bit break; } asm("ei"); // Enable all interrupts }
unsigned int MIPS32 IntEnableInterrupts() { unsigned int intStatus; intStatus = _CP0_GET_STATUS(); // Get Status asm("ei"); // Enable all interrupts return intStatus; }
void interruptSetIPL(U8 wantedIPL) { U32 temp_CP0; temp_CP0 = (_CP0_GET_STATUS() & 0xFFFFE3FF ); // Get the actual Status content striping out the IPL value temp_CP0 |= (wantedIPL<<10); //Offset the new IPL _CP0_SET_STATUS(temp_CP0); //Save and apply the new IPL }
unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR( void ) { unsigned portBASE_TYPE uxSavedStatusRegister; asm volatile ( "di" ); uxSavedStatusRegister = _CP0_GET_STATUS() | 0x01; _CP0_SET_STATUS( ( uxSavedStatusRegister | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); return uxSavedStatusRegister; }
/* * This optional function does a "fast" set of critical region protection to the * value specified by pval. See the documentation for sys_arch_protect() for * more information. This function is only required if your port is supporting * an operating system. */ void sys_arch_unprotect(sys_prot_t lev) { uint32_t ulStatus; /* Get the CP0 status */ ulStatus = _CP0_GET_STATUS(); /* Unmask all interrupts. */ ulStatus &= ~portALL_IPL_BITS; /* Mask interrupt to the last level */ ulStatus |= lev; _CP0_SET_STATUS( ulStatus ); }
/* * This optional function does a "fast" critical region protection and returns * the previous protection level. This function is only called during very short * critical regions. An embedded system which supports ISR-based drivers might * want to implement this function by disabling interrupts. Task-based systems * might want to implement this by using a mutex or disabling tasking. This * function should support recursive calls from the same task or interrupt. In * other words, sys_arch_protect() could be called while already protected. In * that case the return value indicates that it is already protected. * sys_arch_protect() is only required if your port is supporting an operating * system. */ sys_prot_t sys_arch_protect() { sys_prot_t cur; /* Mask interrupts at and below the kernel interrupt priority. */ cur = _CP0_GET_STATUS(); /* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ if( ( ( cur & portALL_IPL_BITS ) >> portIPL_SHIFT ) < 3 ) { cur &= ~portALL_IPL_BITS; _CP0_SET_STATUS( ( cur | ( 3 << portIPL_SHIFT ) ) ); } return cur & portALL_IPL_BITS; }
UBaseType_t uxPortSetInterruptMaskFromISR( void ) { UBaseType_t uxSavedStatusRegister; __builtin_disable_interrupts(); uxSavedStatusRegister = _CP0_GET_STATUS() | 0x01; /* This clears the IPL bits, then sets them to configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called from an interrupt that has a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY so, when used correctly, the action can only result in the IPL being unchanged or raised, and therefore never lowered. */ _CP0_SET_STATUS( ( ( uxSavedStatusRegister & ( ~portALL_IPL_BITS ) ) ) | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ); return uxSavedStatusRegister; }
/* Exception Handling */ /******************************************************************************/ /* This function overrides the normal _weak_ _generic_exception_handler which is defined in the C32 User's Guide. The _weak_ _generic_exception_handler just does an infinite loop. */ void _general_exception_handler(void) { // unsigned long t0 = _CP0_GET_COUNT(); /* Used for NVMOP 6 us Delay */ /* Mask off Mask of the ExcCode Field from the Cause Register Refer to the MIPs M4K Software User's manual */ _excep_code=_CP0_GET_CAUSE() & 0x0000007C >> 2; _excep_addr=_CP0_GET_EPC(); _CP0_SET_STATUS(_CP0_GET_STATUS()&0xFFFFFFE); /* Disable Interrupts */ #ifdef WRITE_EXCEPTION_CAUSE_TO_FLASH /* Store the exception causes in program memory in case the part exhibited the problem in release mode. Gives user a place to start debugging the problem. */ NVMCON = 0x4001; /* set WREN and Word Programing mode */ NVMADDR = EXCEPTION_CAUSE; /* PM Address at which we'll store the */ /* cause register */ NVMDATA = _excep_code; /* wait at least 6 us for LVD start-up assume we're running at max frequency (80 MHz) so we're always safe */
int InsideISR(void) { return ((_CP0_GET_STATUS()&0xfc00)?1:0); }
/* This function overrides the normal _weak_ _generic_exception_handler which is defined in the C32 User's Guide. The _weak_ _generic_exception_handler just does an infinite loop. */ void _general_exception_handler(void) { unsigned long t0 = _CP0_GET_COUNT(); /* Used for NVMOP 6 us Delay */ /* Mask off Mask of the ExcCode Field from the Cause Register Refer to the MIPs M4K Software User's manual */ _excep_code=_CP0_GET_CAUSE() & 0x0000007C >> 2; _excep_addr=_CP0_GET_EPC(); _CP0_SET_STATUS(_CP0_GET_STATUS()&0xFFFFFFE); /* Disable Interrupts */ #ifdef WRITE_EXCEPTION_CAUSE_TO_FLASH /* Store the exception causes in program memory in case the part exhibited the problem in release mode. Gives user a place to start debugging the problem. */ NVMCON = 0x4001; /* set WREN and Word Programing mode */ NVMADDR = EXCEPTION_CAUSE; /* PM Address at which we'll store the */ /* cause register */ NVMDATA = _excep_code; /* wait at least 6 us for LVD start-up assume we're running at max frequency (80 MHz) so we're always safe */ { while (_CP0_GET_COUNT() - t0 < (80/2)*6); } NVMKEY = 0xAA996655; NVMKEY = 0x556699AA; /* unlock sequence */ NVMCONSET = NVMCON_WR; while(NVMCON & NVMCON_WR); /* wait on write to finish */ NVMCON = 0x4001; /* set WREN and Word Programing mode */ NVMADDR = EXCEPTION_ADDR; /* PM Address at which we'll store the */ /* exception address register */ NVMDATA = _excep_addr; /* wait at least 6 us for LVD start-up assume we're running at max frequency (80 MHz) so we're always safe */ { while (_CP0_GET_COUNT() - t0 < (80/2)*6); } NVMKEY = 0xAA996655; NVMKEY = 0x556699AA; /* unlock sequence */ NVMCONSET = NVMCON_WR; while(NVMCON & NVMCON_WR); /* Write the exception cause and address to the part can be read and the cause determined. */ NVMWriteWord((void*)EXCEPTION_CAUSE, _excep_code); NVMWriteWord((void*)EXCEPTION_ADDR, _excep_addr); #endif while (1) { /* Examine _excep_code to identify the type of exception */ /* Examine _excep_addr to find the address that caused the exception */ } }