Implementing exception handling in the new MicroBlaze port - still a work in progress.

pull/4/head
Richard Barry 14 years ago
parent 8b0ccf1444
commit 71b359154b

@ -96,6 +96,7 @@
#define configUSE_COUNTING_SEMAPHORES 1
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 200 )
#define configINTERRUPT_STACK_SIZE configMINIMAL_STACK_SIZE
#define configINSTALL_EXCEPTION_HANDLERS 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0

@ -1005,6 +1005,19 @@ portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION;
*/
unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* <PRE>signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );</PRE>
*
* @return The text (human readable) name of the task referenced by the handle
* xTaskToQueury. A task can query its own name by either passing in its own
* handle, or by setting xTaskToQuery to NULL.
*
* \page uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
* \ingroup TaskUtils
*/
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );
/**
* task. h
* <PRE>void vTaskList( char *pcWriteBuffer );</PRE>

@ -66,7 +66,6 @@
/* Hardware includes. */
#include <xintc_i.h>
#include <xil_exception.h>
#include <microblaze_exceptions_i.h>
#include <microblaze_exceptions_g.h>
/* Tasks are started with a critical section nesting of 0 - however prior
@ -85,8 +84,6 @@ to reach zero, so it is initialised to a high value. */
*/
static portBASE_TYPE prvInitialiseInterruptController( void );
static void prvExceptionHandler( void *pvExceptionID );
/*
* Call an application provided callback to set up the periodic interrupt used
* for the RTOS tick. Using an application callback allows the application
@ -344,20 +341,6 @@ extern void vApplicationClearTimerInterrupt( void );
}
/*-----------------------------------------------------------*/
static void prvExceptionHandler( void *pvExceptionID )
{
volatile unsigned long ulExceptionID;
ulExceptionID = ( unsigned long ) pvExceptionID;
for( ;; )
{
portNOP();
}
( void ) ulExceptionID;
}
/*-----------------------------------------------------------*/
static portBASE_TYPE prvInitialiseInterruptController( void )
{
portBASE_TYPE xStatus;
@ -372,45 +355,13 @@ portBASE_TYPE xStatus;
/* Service all pending interrupts each time the handler is entered. */
XIntc_SetIntrSvcOption( xInterruptControllerInstance.BaseAddress, XIN_SVC_ALL_ISRS_OPTION );
/* Install exception handlers. */
#if MICROBLAZE_EXCEPTIONS_ENABLED == 1
#if XPAR_MICROBLAZE_0_UNALIGNED_EXCEPTIONS == 1
microblaze_register_exception_handler( XEXC_ID_UNALIGNED_ACCESS, prvExceptionHandler, ( void * ) XEXC_ID_UNALIGNED_ACCESS );
#endif /* XPAR_MICROBLAZE_0_UNALIGNED_EXCEPTIONS*/
#if XPAR_MICROBLAZE_0_ILL_OPCODE_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_ILLEGAL_OPCODE, prvExceptionHandler, ( void * ) XEXC_ID_ILLEGAL_OPCODE );
#endif /* XPAR_MICROBLAZE_0_ILL_OPCODE_EXCEPTION*/
#if XPAR_MICROBLAZE_0_M_AXI_I_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_M_AXI_I_EXCEPTION, prvExceptionHandler, ( void * ) XEXC_ID_M_AXI_I_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_M_AXI_I_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_M_AXI_D_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_M_AXI_D_EXCEPTION, prvExceptionHandler, ( void * ) XEXC_ID_M_AXI_D_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_M_AXI_D_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_IPLB_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_IPLB_EXCEPTION, prvExceptionHandler, ( void * ) XEXC_ID_IPLB_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_IPLB_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_DPLB_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_DPLB_EXCEPTION, prvExceptionHandler, ( void * ) XEXC_ID_DPLB_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_DPLB_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_DIV_ZERO_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_DIV_BY_ZERO, prvExceptionHandler, ( void * ) XEXC_ID_DIV_BY_ZERO );
#endif /* XPAR_MICROBLAZE_0_DIV_ZERO_EXCEPTION*/
#if XPAR_MICROBLAZE_0_FPU_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_FPU, prvExceptionHandler, ( void * ) XEXC_ID_FPU );
#endif /* XPAR_MICROBLAZE_0_FPU_EXCEPTION*/
#if XPAR_MICROBLAZE_0_FSL_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_FSL, prvExceptionHandler, ( void * ) XEXC_ID_FSL );
#endif /* XPAR_MICROBLAZE_0_FSL_EXCEPTION*/
/* Install exception handlers if the MicroBlaze is configured to handle
exceptions, and the application defined constant
configINSTALL_EXCEPTION_HANDLERS is set to 1. */
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
{
vPortExceptionsInstallHandlers();
}
#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */
/* Start the interrupt controller. Interrupts are enabled when the
@ -424,12 +375,17 @@ portBASE_TYPE xStatus;
configASSERT( ( xStatus == ( portBASE_TYPE ) XST_SUCCESS ) )
/*_RB_ Exception test code.
/*_RB_ Exception test code. */
#if 0
This does not cause the bralid address to be in the r17 register.
__asm volatile (
"bralid r15, 1234 \n"
"or r0, r0, r0 \n"
);
*/
#endif
#if 0
xStatus /= 0;
#endif
return xStatus;
}

@ -0,0 +1,245 @@
/*
FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
>>>NOTE<<< The modification to the GPL is included to allow you to
distribute a combined work that includes FreeRTOS without being obliged to
provide the source code for proprietary components outside of the FreeRTOS
kernel. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Hardware includes. */
#include <microblaze_exceptions_i.h>
#include <microblaze_exceptions_g.h>
#define portexR3_STACK_OFFSET 4
#define portexR4_STACK_OFFSET 5
#define portexR5_STACK_OFFSET 6
#define portexR6_STACK_OFFSET 7
#define portexR7_STACK_OFFSET 8
#define portexR8_STACK_OFFSET 9
#define portexR9_STACK_OFFSET 10
#define portexR10_STACK_OFFSET 11
#define portexR11_STACK_OFFSET 12
#define portexR12_STACK_OFFSET 13
#define portexR15_STACK_OFFSET 16
#define portexR18_STACK_OFFSET 18
#define portexR19_STACK_OFFSET -1
#define portexESR_DS_MASK 0x00001000UL
/* Exclude the entire file if the MicroBlaze is not configured to handle
exceptions, or the application defined configuration item
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;
static xPortRegisterDump xRegisterDump;
void vPortExceptionHandler( void *pvExceptionID );
extern void vPortExceptionHandlerEntry( void *pvExceptionID );
/*-----------------------------------------------------------*/
void vPortExceptionHandler( void *pvExceptionID )
{
extern void *pxCurrentTCB;
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;
xRegisterDump.pcCurrentTaskName = pcTaskGetTaskName( NULL );
configASSERT( pulStackPointerOnFunctionEntry );
/* Obtain the values of registers that were stacked prior to this function
being called, and may have changed since they were stacked. */
xRegisterDump.ulR3 = pulStackPointerOnFunctionEntry[ portexR3_STACK_OFFSET ];
xRegisterDump.ulR4 = pulStackPointerOnFunctionEntry[ portexR4_STACK_OFFSET ];
xRegisterDump.ulR5 = pulStackPointerOnFunctionEntry[ portexR5_STACK_OFFSET ];
xRegisterDump.ulR6 = pulStackPointerOnFunctionEntry[ portexR6_STACK_OFFSET ];
xRegisterDump.ulR7 = pulStackPointerOnFunctionEntry[ portexR7_STACK_OFFSET ];
xRegisterDump.ulR8 = pulStackPointerOnFunctionEntry[ portexR8_STACK_OFFSET ];
xRegisterDump.ulR9 = pulStackPointerOnFunctionEntry[ portexR9_STACK_OFFSET ];
xRegisterDump.ulR10 = pulStackPointerOnFunctionEntry[ portexR10_STACK_OFFSET ];
xRegisterDump.ulR11 = pulStackPointerOnFunctionEntry[ portexR11_STACK_OFFSET ];
xRegisterDump.ulR12 = pulStackPointerOnFunctionEntry[ portexR12_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 );
xRegisterDump.ulR20 = mfgpr( R20 );
xRegisterDump.ulR21 = mfgpr( R21 );
xRegisterDump.ulR22 = mfgpr( R22 );
xRegisterDump.ulR23 = mfgpr( R23 );
xRegisterDump.ulR24 = mfgpr( R24 );
xRegisterDump.ulR25 = mfgpr( R25 );
xRegisterDump.ulR26 = mfgpr( R26 );
xRegisterDump.ulR27 = mfgpr( R27 );
xRegisterDump.ulR28 = mfgpr( R28 );
xRegisterDump.ulR29 = mfgpr( R29 );
xRegisterDump.ulR30 = mfgpr( R30 );
xRegisterDump.ulR31 = mfgpr( R31 );
xRegisterDump.ulESR = mfesr();
if( ( xRegisterDump.ulESR * portexESR_DS_MASK ) != 0UL )
{
xRegisterDump.ulPC = mfbtr();
}
else
{
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - 4;
}
// xRegisterDump.ulSP =;
// PC changes
// MSR changes
// BTR changes
switch( ( unsigned long ) pvExceptionID )
{
case XEXC_ID_FSL :
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_FSL";
break;
case XEXC_ID_UNALIGNED_ACCESS :
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_UNALIGNED_ACCESS";
break;
case XEXC_ID_ILLEGAL_OPCODE :
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_ILLEGAL_OPCODE";
break;
case XEXC_ID_M_AXI_I_EXCEPTION :
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_M_AXI_I_EXCEPTION or XEXC_ID_IPLB_EXCEPTION";
break;
case XEXC_ID_M_AXI_D_EXCEPTION :
xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_M_AXI_D_EXCEPTION or XEXC_ID_DPLB_EXCEPTION";
break;
case XEXC_ID_DIV_BY_ZERO :
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;
}
/* Must not attempt to leave this function! */
for( ;; )
{
portNOP();
}
}
/*-----------------------------------------------------------*/
void vPortExceptionsInstallHandlers( void )
{
#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*/
#if XPAR_MICROBLAZE_0_ILL_OPCODE_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_ILLEGAL_OPCODE, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_ILLEGAL_OPCODE );
#endif /* XPAR_MICROBLAZE_0_ILL_OPCODE_EXCEPTION*/
#if XPAR_MICROBLAZE_0_M_AXI_I_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_M_AXI_I_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_I_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_M_AXI_I_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_M_AXI_D_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_M_AXI_D_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_D_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_M_AXI_D_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_IPLB_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_IPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_IPLB_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_IPLB_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_DPLB_BUS_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_DPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DPLB_EXCEPTION );
#endif /* XPAR_MICROBLAZE_0_DPLB_BUS_EXCEPTION*/
#if XPAR_MICROBLAZE_0_DIV_ZERO_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_DIV_BY_ZERO, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DIV_BY_ZERO );
#endif /* XPAR_MICROBLAZE_0_DIV_ZERO_EXCEPTION*/
#if XPAR_MICROBLAZE_0_FPU_EXCEPTION == 1
microblaze_register_exception_handler( XEXC_ID_FPU, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FPU );
#endif /* XPAR_MICROBLAZE_0_FPU_EXCEPTION*/
#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
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
#endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */

@ -58,6 +58,7 @@
*/
#include "FreeRTOSConfig.h"
#include "microblaze_exceptions_g.h"
#include "xparameters.h"
/* The context is oversized to allow functions called from the ISR to write
@ -109,10 +110,13 @@ back into the caller stack. */
.extern uxCriticalNesting
.extern pulISRStack
.extern ulTaskSwitchRequested
.extern vPortExceptionHandler
.extern pulStackPointerOnFunctionEntry
.global _interrupt_handler
.global VPortYieldASM
.global vPortStartFirstTask
.global vPortExceptionHandlerEntry
.macro portSAVE_CONTEXT
@ -335,6 +339,20 @@ vPortStartFirstTask:
#if MICROBLAZE_EXCEPTIONS_ENABLED == 1
.text
.align 2
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
bralid r15, vPortExceptionHandler
or r0, r0, r0
#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */

@ -146,6 +146,48 @@ extern volatile unsigned long ulTaskSwitchRequested;
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
typedef struct PORT_REGISTER_DUMP
{
unsigned long ulSP;
unsigned long ulR2_small_data_area;
unsigned long ulR3;
unsigned long ulR4;
unsigned long ulR5;
unsigned long ulR6;
unsigned long ulR7;
unsigned long ulR8;
unsigned long ulR9;
unsigned long ulR10;
unsigned long ulR11;
unsigned long ulR12;
unsigned long ulR13_read_write_small_data_area;
unsigned long ulR14_return_address_from_interrupt;
unsigned long ulR15_return_address_from_subroutine;
unsigned long ulR16_return_address_from_trap;
unsigned long ulR17_return_address_from_some_exceptions;
unsigned long ulR18;
unsigned long ulR19;
unsigned long ulR20;
unsigned long ulR21;
unsigned long ulR22;
unsigned long ulR23;
unsigned long ulR24;
unsigned long ulR25;
unsigned long ulR26;
unsigned long ulR27;
unsigned long ulR28;
unsigned long ulR29;
unsigned long ulR30;
unsigned long ulR31;
unsigned long ulPC;
unsigned long ulESR;
signed char *pcExceptionCause;
signed char *pcCurrentTaskName;
void * xCurrentTaskHandle;
} xPortRegisterDump;
void vPortExceptionsInstallHandlers( void );
#ifdef __cplusplus
}
#endif

@ -1281,6 +1281,17 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
}
/*-----------------------------------------------------------*/
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery )
{
tskTCB *pxTCB;
/* If null is passed in here then we are suspending ourselves. */
pxTCB = prvGetTCBFromHandle( xTaskToQuery );
configASSERT( pxTCB );
return &( pxTCB->pcTaskName[ 0 ] );
}
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
void vTaskList( signed char *pcWriteBuffer )

Loading…
Cancel
Save