Extend the exception handling functionality in the new MicroBlaze port.

This commit is contained in:
Richard Barry 2011-06-29 08:50:13 +00:00
parent 71b359154b
commit 832bbd38e1
4 changed files with 111 additions and 43 deletions

View File

@ -71,10 +71,12 @@
#define portexR12_STACK_OFFSET 13
#define portexR15_STACK_OFFSET 16
#define portexR18_STACK_OFFSET 18
#define portexMSR_STACK_OFFSET 19
#define portexR19_STACK_OFFSET -1
#define portexESR_DS_MASK 0x00001000UL
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL
/* Exclude the entire file if the MicroBlaze is not configured to handle
exceptions, or the application defined configuration item
@ -82,13 +84,22 @@ configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
/* These are global volatiles to allow their inspection by a debugger. */
unsigned long *pulStackPointerOnFunctionEntry = NULL;
unsigned long *pulStackPointerOnFunctionEntry = NULL, ulBTROnFunctionEntry = 0UL;
static xPortRegisterDump xRegisterDump;
void vPortExceptionHandler( void *pvExceptionID );
extern void vPortExceptionHandlerEntry( void *pvExceptionID );
/*-----------------------------------------------------------*/
extern void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ) __attribute__((weak));
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
{
for( ;; )
{
portNOP();
}
}
/*-----------------------------------------------------------*/
void vPortExceptionHandler( void *pvExceptionID )
@ -112,14 +123,14 @@ extern void *pxCurrentTCB;
xRegisterDump.ulR10 = pulStackPointerOnFunctionEntry[ portexR10_STACK_OFFSET ];
xRegisterDump.ulR11 = pulStackPointerOnFunctionEntry[ portexR11_STACK_OFFSET ];
xRegisterDump.ulR12 = pulStackPointerOnFunctionEntry[ portexR12_STACK_OFFSET ];
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];
/* Obtain the value of all other registers. */
//xRegisterDump.ulR1 =
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );
xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 );
xRegisterDump.ulR14_return_address_from_interrupt = mfgpr( R14 );
xRegisterDump.ulR15_return_address_from_subroutine = mfgpr( R15 );
xRegisterDump.ulR16_return_address_from_trap = mfgpr( R16 );
xRegisterDump.ulR17_return_address_from_some_exceptions = mfgpr( R17 );
xRegisterDump.ulR18 = mfgpr( R18 );
@ -135,8 +146,15 @@ extern void *pxCurrentTCB;
xRegisterDump.ulR29 = mfgpr( R29 );
xRegisterDump.ulR30 = mfgpr( R30 );
xRegisterDump.ulR31 = mfgpr( R31 );
xRegisterDump.ulR1_SP = ( ( unsigned long ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
xRegisterDump.ulBTR = ulBTROnFunctionEntry;
xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];
xRegisterDump.ulEAR = mfear();
xRegisterDump.ulESR = mfesr();
xRegisterDump.ulEDR = mfedr();
#ifdef THIS_IS_PROBABLY_INCORRECT
if( ( xRegisterDump.ulESR * portexESR_DS_MASK ) != 0UL )
{
xRegisterDump.ulPC = mfbtr();
@ -145,12 +163,20 @@ extern void *pxCurrentTCB;
{
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - 4;
}
#else
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - 4;
#endif
// xRegisterDump.ulSP =;
// PC changes
// MSR changes
// BTR changes
#if XPAR_MICROBLAZE_0_USE_FPU == 1
{
xRegisterDump.ulFSR = mffsr();
}
#else
{
xRegisterDump.ulFSR = 0UL;
}
#endif
switch( ( unsigned long ) pvExceptionID )
{
@ -178,16 +204,22 @@ extern void *pxCurrentTCB;
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_DIV_BY_ZERO";
break;
case XEXC_ID_FPU :
/*_RB_ More decoding required here and in other exceptions. */
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_FPU";
break;
case XEXC_ID_STACK_VIOLATION :
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_STACK_VIOLATION or XEXC_ID_MMU";
break;
#if XPAR_MICROBLAZE_0_USE_FPU == 1
case XEXC_ID_FPU :
/*_RB_ More decoding required here and in other exceptions. */
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_FPU see ulFSR value";
break;
#endif /* XPAR_MICROBLAZE_0_USE_FPU */
}
vApplicationExceptionRegisterDump( &xRegisterDump );
/* Must not attempt to leave this function! */
for( ;; )
{
@ -198,6 +230,12 @@ extern void *pxCurrentTCB;
void vPortExceptionsInstallHandlers( void )
{
static unsigned long ulHandlersAlreadyInstalled = pdFALSE;
if( ulHandlersAlreadyInstalled == pdFALSE )
{
ulHandlersAlreadyInstalled = pdTRUE;
#if XPAR_MICROBLAZE_0_UNALIGNED_EXCEPTIONS == 1
microblaze_register_exception_handler( XEXC_ID_UNALIGNED_ACCESS, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_UNALIGNED_ACCESS );
#endif /* XPAR_MICROBLAZE_0_UNALIGNED_EXCEPTIONS*/
@ -233,8 +271,8 @@ void vPortExceptionsInstallHandlers( void )
#if XPAR_MICROBLAZE_0_FSL_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_FSL, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FSL );
#endif /* XPAR_MICROBLAZE_0_FSL_EXCEPTION*/
}
}
/*-----------------------------------------------------------*/
/* Exclude the entire file if the MicroBlaze is not configured to handle
exceptions, or the application defined configuration item

View File

@ -112,6 +112,7 @@ back into the caller stack. */
.extern ulTaskSwitchRequested
.extern vPortExceptionHandler
.extern pulStackPointerOnFunctionEntry
.extern ulBTROnFunctionEntry
.global _interrupt_handler
.global VPortYieldASM
@ -347,8 +348,9 @@ vPortExceptionHandlerEntry:
/* Take a copy of the stack pointer before vPortExecptionHandler is called,
storing its value prior to the function stack frame being created. */
lwi r18, r0, pulStackPointerOnFunctionEntry
swi r1, r0, pulStackPointerOnFunctionEntry
mfs r18, RBTR
swi r18, r0, ulBTROnFunctionEntry
bralid r15, vPortExceptionHandler
or r0, r0, r0

View File

@ -148,7 +148,9 @@ extern volatile unsigned long ulTaskSwitchRequested;
typedef struct PORT_REGISTER_DUMP
{
unsigned long ulSP;
/* The following structure members hold the values of the MicroBlaze
registers at the time the exception was raised. */
unsigned long ulR1_SP;
unsigned long ulR2_small_data_area;
unsigned long ulR3;
unsigned long ulR4;
@ -181,12 +183,30 @@ typedef struct PORT_REGISTER_DUMP
unsigned long ulR31;
unsigned long ulPC;
unsigned long ulESR;
unsigned long ulBTR;
unsigned long ulMSR;
unsigned long ulEAR;
unsigned long ulFSR;
unsigned long ulEDR;
/* A human readable description of the exception cause. The strings used
are the same as the #define constant names found in the
microblaze_exceptions_i.h header file */
signed char *pcExceptionCause;
/* The human readable name of the task that was running at the time the
exception occurred. This is the name that was given to the task when the
task was created using the FreeRTOS xTaskCreate() API function. */
signed char *pcCurrentTaskName;
/* The handle of the task that was running a the time the exception
occurred. */
void * xCurrentTaskHandle;
} xPortRegisterDump;
void vPortExceptionsInstallHandlers( void );
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump );
#ifdef __cplusplus
}

View File

@ -550,3 +550,11 @@ static void prvSetupHardware( void )
}
/*-----------------------------------------------------------*/
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
{
for( ;; )
{
portNOP();
}
}