Sync up MicroblazeV9 port with Xilinx tree (#220)

* MicroblazeV9: Add support for 64 bit microblaze
* MicroblazeV9: Add support for generation of run time task stats
* MicroblazeV9: Add default implementation for callback functions
---------
Signed-off-by: Mubin Usman Sayyed <mubin.usman.sayyed@xilinx.com>
This commit is contained in:
Mubin Sayyed 2024-01-26 08:51:44 +05:30 committed by GitHub
parent 8e664fc984
commit 5040a67939
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 508 additions and 298 deletions

View file

@ -54,6 +54,7 @@ bics
BISR BISR
BODIEN BODIEN
BODSTS BODSTS
brealid
BRGR BRGR
brhi brhi
brne brne

View file

@ -1,6 +1,13 @@
name: FreeRTOS-Kernel Demos name: FreeRTOS-Kernel Demos
on: [push, pull_request] on: [push, pull_request]
env:
# The bash escape character is \033
bashPass: \033[32;1mPASSED -
bashInfo: \033[33;1mINFO -
bashFail: \033[31;1mFAILED -
bashEnd: \033[0m
jobs: jobs:
WIN32-MSVC: WIN32-MSVC:
name: WIN32 MSVC name: WIN32 MSVC
@ -147,6 +154,92 @@ jobs:
working-directory: FreeRTOS/Demo/msp430_GCC working-directory: FreeRTOS/Demo/msp430_GCC
run: make -j run: make -j
MicroBlaze-GCC:
name: GCC MicroBlaze Toolchain
runs-on: ubuntu-latest
steps:
- name: Checkout the FreeRTOS/FreeRTOS Repository
uses: actions/checkout@v3
with:
ref: main
repository: FreeRTOS/FreeRTOS
fetch-depth: 1
- env:
stepName: Fetch Community-Supported-Demos Submodule
shell: bash
run: |
# Fetch Community-Supported-Demos Submodule
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
git submodule update --checkout --init --depth 1 FreeRTOS/Demo/ThirdParty/Community-Supported-Demos
# This repository contains the microblaze_instructions.h header file
git clone https://github.com/Xilinx/embeddedsw.git --branch xilinx_v2023.1
echo "::endgroup::"
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
# Checkout user pull request changes
- name: Checkout Pull Request
uses: actions/checkout@v3
with:
path: ./FreeRTOS/Source
- env:
stepName: Install Dependancies
shell: bash
run: |
# ${{ env.stepName }}
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
sudo apt update -y
sudo apt upgrade -y
sudo apt install -y build-essential m4 debhelper bison texinfo dejagnu flex
sudo apt install -y autogen gawk libgmp-dev libmpc-dev libmpfr-dev
sudo apt install -y patchutils sharutils zlib1g-dev autoconf2.64
# Download the mb-gcc toolchain from github
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/binutils-microblaze_2.35-2021-0623+1_amd64.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/gcc-microblaze_10.2.0-2021-0623+2_amd64.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze-dev_3.3.0-2021-0623+3_all.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze-doc_3.3.0-2021-0623+3_all.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze_3.3.0-2021-0623+3_all.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/newlib-source_3.3.0-2021-0623+3_all.deb;
# Install the packages for the toolchain
sudo apt install -y ./binutils-microblaze*.deb;
sudo apt install -y ./gcc-microblaze*.deb;
sudo apt install -y ./libnewlib-microblaze-dev*.deb;
sudo apt install -y ./libnewlib-microblaze-doc*.deb;
sudo apt install -y ./libnewlib-microblaze*.deb;
sudo apt install -y ./newlib-source*.deb;
# Validate that the toolchain is in the path and can be called
which mb-gcc
mb-gcc --version
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
- env:
stepName: Compile Microblaze Port
shell: bash
run: |
# ${{ env.stepName }}
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
# Compile MicroBlazeV9 Port files to validate they build
mb-gcc -mcpu=v9.5 -c \
FreeRTOS/Source/portable/GCC/MicroBlazeV9/port.c \
FreeRTOS/Source/portable/GCC/MicroBlazeV9/portasm.S \
FreeRTOS/Source/portable/GCC/MicroBlazeV9/port_exceptions.c \
FreeRTOS/Source/tasks.c \
FreeRTOS/Source/list.c \
-I embeddedsw/lib/bsp/standalone/src/microblaze \
-I FreeRTOS/Source/portable/GCC/MicroBlazeV9/ \
-I FreeRTOS/Source/include \
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src \
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/standalone_v5_4/src \
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/include \
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_5/src
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
ARM-GCC: ARM-GCC:
name: GNU ARM Toolchain name: GNU ARM Toolchain
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -164,7 +257,7 @@ jobs:
# Fetch Community-Supported-Demos Submodule # Fetch Community-Supported-Demos Submodule
echo "::group::Fetch Community-Supported-Demos Submodule" echo "::group::Fetch Community-Supported-Demos Submodule"
git submodule update --checkout --init --depth 1 FreeRTOS/Demo/ThirdParty/Community-Supported-Demos git submodule update --checkout --init --depth 1 FreeRTOS/Demo/ThirdParty/Community-Supported-Demos
echo "::engdroup::" echo "::endgroup::"
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
echo -e "\033[32;3mCloned the Community-Supported-Demos\033[0m" echo -e "\033[32;3mCloned the Community-Supported-Demos\033[0m"
else else

View file

@ -42,6 +42,7 @@
#include <xintc_i.h> #include <xintc_i.h>
#include <xil_exception.h> #include <xil_exception.h>
#include <microblaze_exceptions_g.h> #include <microblaze_exceptions_g.h>
#include <microblaze_instructions.h>
/* Tasks are started with a critical section nesting of 0 - however, prior to /* Tasks are started with a critical section nesting of 0 - however, prior to
* the scheduler being commenced interrupts should not be enabled, so the critical * the scheduler being commenced interrupts should not be enabled, so the critical
@ -58,6 +59,13 @@
* given to the FSR register when the initial context is set up for a task being * given to the FSR register when the initial context is set up for a task being
* created. */ * created. */
#define portINITIAL_FSR ( 0U ) #define portINITIAL_FSR ( 0U )
/*
* Global counter used for calculation of run time statistics of tasks.
* Defined only when the relevant option is turned on
*/
#if (configGENERATE_RUN_TIME_STATS==1)
volatile uint32_t ulHighFrequencyTimerTicks;
#endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -116,10 +124,11 @@ static XIntc xInterruptControllerInstance;
void * pvParameters ) void * pvParameters )
#endif #endif
{ {
extern void * _SDA2_BASE_; extern void *_SDA2_BASE_;
extern void * _SDA_BASE_; extern void *_SDA_BASE_;
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_; const UINTPTR ulR2 = ( UINTPTR ) &_SDA2_BASE_;
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_; const UINTPTR ulR13 = ( UINTPTR ) &_SDA_BASE_;
extern void _start1( void ); extern void _start1( void );
/* Place a few bytes of known values on the bottom of the stack. /* Place a few bytes of known values on the bottom of the stack.
@ -255,8 +264,8 @@ static XIntc xInterruptControllerInstance;
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void( vPortStartFirstTask )( void ); extern void ( vPortStartFirstTask )( void );
extern uint32_t _stack[]; extern UINTPTR _stack[];
/* Setup the hardware to generate the tick. Interrupts are disabled when /* Setup the hardware to generate the tick. Interrupts are disabled when
* this function is called. * this function is called.
@ -270,7 +279,7 @@ BaseType_t xPortStartScheduler( void )
vApplicationSetupTimerInterrupt(); vApplicationSetupTimerInterrupt();
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */ /* Reuse the stack from main() as the stack for the interrupts/exceptions. */
pulISRStack = ( uint32_t * ) _stack; pulISRStack = ( UINTPTR * ) _stack;
/* Ensure there is enough space for the functions called from the interrupt /* Ensure there is enough space for the functions called from the interrupt
* service routines to write back into the stack frame of the caller. */ * service routines to write back into the stack frame of the caller. */
@ -304,13 +313,18 @@ void vPortYield( void )
* not interrupted by the tick ISR. It is not a problem to do this as * not interrupted by the tick ISR. It is not a problem to do this as
* each task maintains its own interrupt status. */ * each task maintains its own interrupt status. */
portENTER_CRITICAL(); portENTER_CRITICAL();
{ {
/* Jump directly to the yield function to ensure there is no /* Jump directly to the yield function to ensure there is no
* compiler generated prologue code. */ * compiler generated prologue code. */
asm volatile ( "bralid r14, VPortYieldASM \n\t" \ #ifdef __arch64__
"or r0, r0, r0 \n\t" ); asm volatile ( "brealid r14, VPortYieldASM \n\t" \
} "or r0, r0, r0 \n\t" );
portEXIT_CRITICAL(); #else
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
"or r0, r0, r0 \n\t" );
#endif
}
portEXIT_CRITICAL();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -434,22 +448,34 @@ void vPortTickISR( void * pvUnused )
{ {
extern void vApplicationClearTimerInterrupt( void ); extern void vApplicationClearTimerInterrupt( void );
/* Ensure the unused parameter does not generate a compiler warning. */ /* Ensure the unused parameter does not generate a compiler warning. */
( void ) pvUnused; ( void ) pvUnused;
/* This port uses an application defined callback function to clear the tick /* The Xilinx implementation of generating run time task stats uses the same timer used for generating
* interrupt because the kernel will run on lots of different MicroBlaze and * FreeRTOS ticks. In case user decides to generate run time stats the tick handler is called more
* FPGA configurations - not all of which will have the same timer peripherals * frequently (10 times faster). The timer ick handler uses logic to handle the same. It handles
* defined or available. An example definition of * the FreeRTOS tick once per 10 interrupts.
* vApplicationClearTimerInterrupt() is provided in the official demo * For handling generation of run time stats, it increments a pre-defined counter every time the
* application that accompanies this port. */ * interrupt handler executes. */
vApplicationClearTimerInterrupt(); #if (configGENERATE_RUN_TIME_STATS == 1)
ulHighFrequencyTimerTicks++;
/* Increment the RTOS tick - this might cause a task to unblock. */ if (!(ulHighFrequencyTimerTicks % 10))
if( xTaskIncrementTick() != pdFALSE ) #endif
{ {
/* Force vTaskSwitchContext() to be called as the interrupt exits. */ /* This port uses an application defined callback function to clear the tick
ulTaskSwitchRequested = 1; * interrupt because the kernel will run on lots of different MicroBlaze and
* FPGA configurations - not all of which will have the same timer peripherals
* defined or available. An example definition of
* vApplicationClearTimerInterrupt() is provided in the official demo
* application that accompanies this port. */
vApplicationClearTimerInterrupt();
/* Increment the RTOS tick - this might cause a task to unblock. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
ulTaskSwitchRequested = 1;
}
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -495,4 +521,25 @@ static int32_t prvInitialiseInterruptController( void )
return lStatus; return lStatus;
} }
#if( configGENERATE_RUN_TIME_STATS == 1 )
/*
* For Xilinx implementation this is a dummy function that does a redundant operation
* of zeroing out the global counter.
* It is called by FreeRTOS kernel.
*/
void xCONFIGURE_TIMER_FOR_RUN_TIME_STATS (void)
{
ulHighFrequencyTimerTicks = 0;
}
/*
* For Xilinx implementation this function returns the global counter used for
* run time task stats calculation.
* It is called by FreeRTOS kernel task handling logic.
*/
uint32_t xGET_RUN_TIME_COUNTER_VALUE (void)
{
return ulHighFrequencyTimerTicks;
}
#endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -67,7 +67,7 @@
/* This variable is set in the exception entry code, before /* This variable is set in the exception entry code, before
* vPortExceptionHandler is called. */ * vPortExceptionHandler is called. */
uint32_t * pulStackPointerOnFunctionEntry = NULL; UINTPTR *pulStackPointerOnFunctionEntry = NULL;
/* This is the structure that is filled with the MicroBlaze context as it /* This is the structure that is filled with the MicroBlaze context as it
* existed immediately prior to the exception occurrence. A pointer to this * existed immediately prior to the exception occurrence. A pointer to this
@ -80,7 +80,6 @@
* in portasm.S. */ * in portasm.S. */
void vPortExceptionHandler( void * pvExceptionID ); void vPortExceptionHandler( void * pvExceptionID );
extern void vPortExceptionHandlerEntry( void * pvExceptionID ); extern void vPortExceptionHandlerEntry( void * pvExceptionID );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* vApplicationExceptionRegisterDump() is a callback function that the /* vApplicationExceptionRegisterDump() is a callback function that the
@ -149,7 +148,7 @@
xRegisterDump.ulR29 = mfgpr( R29 ); xRegisterDump.ulR29 = mfgpr( R29 );
xRegisterDump.ulR30 = mfgpr( R30 ); xRegisterDump.ulR30 = mfgpr( R30 );
xRegisterDump.ulR31 = mfgpr( R31 ); xRegisterDump.ulR31 = mfgpr( R31 );
xRegisterDump.ulR1_SP = ( ( uint32_t ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE; xRegisterDump.ulR1_SP = ( ( UINTPTR ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
xRegisterDump.ulEAR = mfear(); xRegisterDump.ulEAR = mfear();
xRegisterDump.ulESR = mfesr(); xRegisterDump.ulESR = mfesr();
xRegisterDump.ulEDR = mfedr(); xRegisterDump.ulEDR = mfedr();

View file

@ -33,63 +33,97 @@
#include "microblaze_exceptions_g.h" #include "microblaze_exceptions_g.h"
#include "xparameters.h" #include "xparameters.h"
#include "microblaze_instructions.h"
/* The context is oversized to allow functions called from the ISR to write
back into the caller stack. */
#if defined (__arch64__)
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
#define portCONTEXT_SIZE 272
#define portMINUS_CONTEXT_SIZE -272
#else
#define portCONTEXT_SIZE 264
#define portMINUS_CONTEXT_SIZE -264
#endif
#else
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
#define portCONTEXT_SIZE 136
#define portMINUS_CONTEXT_SIZE -136
#else
#define portCONTEXT_SIZE 132
#define portMINUS_CONTEXT_SIZE -132
#endif
#endif
/* Offsets from the stack pointer at which saved registers are placed. */ /* Offsets from the stack pointer at which saved registers are placed. */
#define portR31_OFFSET 4 #if defined (__arch64__)
#define portR30_OFFSET 8 #define portR31_OFFSET 8
#define portR29_OFFSET 12 #define portR30_OFFSET 16
#define portR28_OFFSET 16 #define portR29_OFFSET 24
#define portR27_OFFSET 20 #define portR28_OFFSET 32
#define portR26_OFFSET 24 #define portR27_OFFSET 40
#define portR25_OFFSET 28 #define portR26_OFFSET 48
#define portR24_OFFSET 32 #define portR25_OFFSET 56
#define portR23_OFFSET 36 #define portR24_OFFSET 64
#define portR22_OFFSET 40 #define portR23_OFFSET 72
#define portR21_OFFSET 44 #define portR22_OFFSET 80
#define portR20_OFFSET 48 #define portR21_OFFSET 88
#define portR19_OFFSET 52 #define portR20_OFFSET 96
#define portR18_OFFSET 56 #define portR19_OFFSET 104
#define portR17_OFFSET 60 #define portR18_OFFSET 112
#define portR16_OFFSET 64 #define portR17_OFFSET 120
#define portR15_OFFSET 68 #define portR16_OFFSET 128
#define portR14_OFFSET 72 #define portR15_OFFSET 136
#define portR13_OFFSET 76 #define portR14_OFFSET 144
#define portR12_OFFSET 80 #define portR13_OFFSET 152
#define portR11_OFFSET 84 #define portR12_OFFSET 160
#define portR10_OFFSET 88 #define portR11_OFFSET 168
#define portR9_OFFSET 92 #define portR10_OFFSET 176
#define portR8_OFFSET 96 #define portR9_OFFSET 184
#define portR7_OFFSET 100 #define portR8_OFFSET 192
#define portR6_OFFSET 104 #define portR7_OFFSET 200
#define portR5_OFFSET 108 #define portR6_OFFSET 208
#define portR4_OFFSET 112 #define portR5_OFFSET 216
#define portR3_OFFSET 116 #define portR4_OFFSET 224
#define portR2_OFFSET 120 #define portR3_OFFSET 232
#define portR2_OFFSET 240
#define portCRITICAL_NESTING_OFFSET 248
#define portMSR_OFFSET 256
#define portFSR_OFFSET 264
#else
#define portR31_OFFSET 4
#define portR30_OFFSET 8
#define portR29_OFFSET 12
#define portR28_OFFSET 16
#define portR27_OFFSET 20
#define portR26_OFFSET 24
#define portR25_OFFSET 28
#define portR24_OFFSET 32
#define portR23_OFFSET 36
#define portR22_OFFSET 40
#define portR21_OFFSET 44
#define portR20_OFFSET 48
#define portR19_OFFSET 52
#define portR18_OFFSET 56
#define portR17_OFFSET 60
#define portR16_OFFSET 64
#define portR15_OFFSET 68
#define portR14_OFFSET 72
#define portR13_OFFSET 76
#define portR12_OFFSET 80
#define portR11_OFFSET 84
#define portR10_OFFSET 88
#define portR9_OFFSET 92
#define portR8_OFFSET 96
#define portR7_OFFSET 100
#define portR6_OFFSET 104
#define portR5_OFFSET 108
#define portR4_OFFSET 112
#define portR3_OFFSET 116
#define portR2_OFFSET 120
#define portCRITICAL_NESTING_OFFSET 124 #define portCRITICAL_NESTING_OFFSET 124
#define portMSR_OFFSET 128 #define portMSR_OFFSET 128
#define portFSR_OFFSET 132
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
#define portFSR_OFFSET 132
#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
#define portSLR_OFFSET 136
#define portSHR_OFFSET 140
#define portCONTEXT_SIZE 144
#define portMINUS_CONTEXT_SIZE -144
#else
#define portCONTEXT_SIZE 136
#define portMINUS_CONTEXT_SIZE -136
#endif
#else
#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
#define portSLR_OFFSET 132
#define portSHR_OFFSET 136
#define portCONTEXT_SIZE 140
#define portMINUS_CONTEXT_SIZE -140
#else
#define portCONTEXT_SIZE 132
#define portMINUS_CONTEXT_SIZE -132
#endif
#endif #endif
.extern pxCurrentTCB .extern pxCurrentTCB
@ -109,54 +143,54 @@
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
/* Make room for the context on the stack. */ /* Make room for the context on the stack. */
addik r1, r1, portMINUS_CONTEXT_SIZE ADDLIK r1, r1, portMINUS_CONTEXT_SIZE
/* Stack general registers. */ /* Stack general registers. */
swi r31, r1, portR31_OFFSET SI r31, r1, portR31_OFFSET
swi r30, r1, portR30_OFFSET SI r30, r1, portR30_OFFSET
swi r29, r1, portR29_OFFSET SI r29, r1, portR29_OFFSET
swi r28, r1, portR28_OFFSET SI r28, r1, portR28_OFFSET
swi r27, r1, portR27_OFFSET SI r27, r1, portR27_OFFSET
swi r26, r1, portR26_OFFSET SI r26, r1, portR26_OFFSET
swi r25, r1, portR25_OFFSET SI r25, r1, portR25_OFFSET
swi r24, r1, portR24_OFFSET SI r24, r1, portR24_OFFSET
swi r23, r1, portR23_OFFSET SI r23, r1, portR23_OFFSET
swi r22, r1, portR22_OFFSET SI r22, r1, portR22_OFFSET
swi r21, r1, portR21_OFFSET SI r21, r1, portR21_OFFSET
swi r20, r1, portR20_OFFSET SI r20, r1, portR20_OFFSET
swi r19, r1, portR19_OFFSET SI r19, r1, portR19_OFFSET
swi r18, r1, portR18_OFFSET SI r18, r1, portR18_OFFSET
swi r17, r1, portR17_OFFSET SI r17, r1, portR17_OFFSET
swi r16, r1, portR16_OFFSET SI r16, r1, portR16_OFFSET
swi r15, r1, portR15_OFFSET SI r15, r1, portR15_OFFSET
/* R14 is saved later as it needs adjustment if a yield is performed. */ /* R14 is saved later as it needs adjustment if a yield is performed. */
swi r13, r1, portR13_OFFSET SI r13, r1, portR13_OFFSET
swi r12, r1, portR12_OFFSET SI r12, r1, portR12_OFFSET
swi r11, r1, portR11_OFFSET SI r11, r1, portR11_OFFSET
swi r10, r1, portR10_OFFSET SI r10, r1, portR10_OFFSET
swi r9, r1, portR9_OFFSET SI r9, r1, portR9_OFFSET
swi r8, r1, portR8_OFFSET SI r8, r1, portR8_OFFSET
swi r7, r1, portR7_OFFSET SI r7, r1, portR7_OFFSET
swi r6, r1, portR6_OFFSET SI r6, r1, portR6_OFFSET
swi r5, r1, portR5_OFFSET SI r5, r1, portR5_OFFSET
swi r4, r1, portR4_OFFSET SI r4, r1, portR4_OFFSET
swi r3, r1, portR3_OFFSET SI r3, r1, portR3_OFFSET
swi r2, r1, portR2_OFFSET SI r2, r1, portR2_OFFSET
/* Stack the critical section nesting value. */ /* Stack the critical section nesting value. */
lwi r18, r0, uxCriticalNesting LI r18, r0, uxCriticalNesting
swi r18, r1, portCRITICAL_NESTING_OFFSET SI r18, r1, portCRITICAL_NESTING_OFFSET
/* Stack MSR. */ /* Stack MSR. */
mfs r18, rmsr mfs r18, rmsr
swi r18, r1, portMSR_OFFSET SI r18, r1, portMSR_OFFSET
#if( XPAR_MICROBLAZE_USE_FPU != 0 ) #if( XPAR_MICROBLAZE_USE_FPU != 0 )
/* Stack FSR. */ /* Stack FSR. */
mfs r18, rfsr mfs r18, rfsr
swi r18, r1, portFSR_OFFSET SI r18, r1, portFSR_OFFSET
#endif #endif
#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION ) #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
/* Save the stack limits */ /* Save the stack limits */
@ -166,17 +200,17 @@
swi r18, r1, portSHR_OFFSET swi r18, r1, portSHR_OFFSET
#endif #endif
/* Save the top of stack value to the TCB. */ /* Save the top of stack value to the TCB. */
lwi r3, r0, pxCurrentTCB LI r3, r0, pxCurrentTCB
sw r1, r0, r3 STORE r1, r0, r3
.endm .endm
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
/* Load the top of stack value from the TCB. */ /* Load the top of stack value from the TCB. */
lwi r18, r0, pxCurrentTCB LI r18, r0, pxCurrentTCB
lw r1, r0, r18 LOAD r1, r0, r18
#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION ) #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
/* Restore the stack limits -- must not load from r1 (Stack Pointer) /* Restore the stack limits -- must not load from r1 (Stack Pointer)
@ -189,101 +223,112 @@
mts rshr, r12 mts rshr, r12
#endif #endif
/* Restore the general registers. */ /* Restore the general registers. */
lwi r31, r1, portR31_OFFSET LI r31, r1, portR31_OFFSET
lwi r30, r1, portR30_OFFSET LI r30, r1, portR30_OFFSET
lwi r29, r1, portR29_OFFSET LI r29, r1, portR29_OFFSET
lwi r28, r1, portR28_OFFSET LI r28, r1, portR28_OFFSET
lwi r27, r1, portR27_OFFSET LI r27, r1, portR27_OFFSET
lwi r26, r1, portR26_OFFSET LI r26, r1, portR26_OFFSET
lwi r25, r1, portR25_OFFSET LI r25, r1, portR25_OFFSET
lwi r24, r1, portR24_OFFSET LI r24, r1, portR24_OFFSET
lwi r23, r1, portR23_OFFSET LI r23, r1, portR23_OFFSET
lwi r22, r1, portR22_OFFSET LI r22, r1, portR22_OFFSET
lwi r21, r1, portR21_OFFSET LI r21, r1, portR21_OFFSET
lwi r20, r1, portR20_OFFSET LI r20, r1, portR20_OFFSET
lwi r19, r1, portR19_OFFSET LI r19, r1, portR19_OFFSET
lwi r17, r1, portR17_OFFSET LI r17, r1, portR17_OFFSET
lwi r16, r1, portR16_OFFSET LI r16, r1, portR16_OFFSET
lwi r15, r1, portR15_OFFSET LI r15, r1, portR15_OFFSET
lwi r14, r1, portR14_OFFSET LI r14, r1, portR14_OFFSET
lwi r13, r1, portR13_OFFSET LI r13, r1, portR13_OFFSET
lwi r12, r1, portR12_OFFSET LI r12, r1, portR12_OFFSET
lwi r11, r1, portR11_OFFSET LI r11, r1, portR11_OFFSET
lwi r10, r1, portR10_OFFSET LI r10, r1, portR10_OFFSET
lwi r9, r1, portR9_OFFSET LI r9, r1, portR9_OFFSET
lwi r8, r1, portR8_OFFSET LI r8, r1, portR8_OFFSET
lwi r7, r1, portR7_OFFSET LI r7, r1, portR7_OFFSET
lwi r6, r1, portR6_OFFSET LI r6, r1, portR6_OFFSET
lwi r5, r1, portR5_OFFSET LI r5, r1, portR5_OFFSET
lwi r4, r1, portR4_OFFSET LI r4, r1, portR4_OFFSET
lwi r3, r1, portR3_OFFSET LI r3, r1, portR3_OFFSET
lwi r2, r1, portR2_OFFSET LI r2, r1, portR2_OFFSET
/* Reload the rmsr from the stack. */ /* Reload the rmsr from the stack. */
lwi r18, r1, portMSR_OFFSET LI r18, r1, portMSR_OFFSET
mts rmsr, r18 mts rmsr, r18
#if( XPAR_MICROBLAZE_USE_FPU != 0 ) #if( XPAR_MICROBLAZE_USE_FPU != 0 )
/* Reload the FSR from the stack. */ /* Reload the FSR from the stack. */
lwi r18, r1, portFSR_OFFSET LI r18, r1, portFSR_OFFSET
mts rfsr, r18 mts rfsr, r18
#endif #endif
/* Load the critical nesting value. */ /* Load the critical nesting value. */
lwi r18, r1, portCRITICAL_NESTING_OFFSET LI r18, r1, portCRITICAL_NESTING_OFFSET
swi r18, r0, uxCriticalNesting SI r18, r0, uxCriticalNesting
/* Test the critical nesting value. If it is non zero then the task last /* Test the critical nesting value. If it is non zero then the task last
exited the running state using a yield. If it is zero, then the task exited the running state using a yield. If it is zero, then the task
last exited the running state through an interrupt. */ last exited the running state through an interrupt. */
xori r18, r18, 0 XORI r18, r18, 0
bnei r18, exit_from_yield BNEI r18, exit_from_yield
/* r18 was being used as a temporary. Now restore its true value from the /* r18 was being used as a temporary. Now restore its true value from the
stack. */ stack. */
lwi r18, r1, portR18_OFFSET LI r18, r1, portR18_OFFSET
/* Remove the stack frame. */ /* Remove the stack frame. */
addik r1, r1, portCONTEXT_SIZE ADDLIK r1, r1, portCONTEXT_SIZE
/* Return using rtid so interrupts are re-enabled as this function is /* Return using rtid so interrupts are re-enabled as this function is
exited. */ exited. */
rtid r14, 0 rtid r14, 0
or r0, r0, r0 OR r0, r0, r0
.endm .endm
/* This function is used to exit portRESTORE_CONTEXT() if the task being /* This function is used to exit portRESTORE_CONTEXT() if the task being
returned to last left the Running state by calling taskYIELD() (rather than returned to last left the Running state by calling taskYIELD() (rather than
being preempted by an interrupt). */ being preempted by an interrupt). */
.text .text
.align 4 #ifdef __arch64__
.align 8
#else
.align 4
#endif
exit_from_yield: exit_from_yield:
/* r18 was being used as a temporary. Now restore its true value from the /* r18 was being used as a temporary. Now restore its true value from the
stack. */ stack. */
lwi r18, r1, portR18_OFFSET LI r18, r1, portR18_OFFSET
/* Remove the stack frame. */ /* Remove the stack frame. */
addik r1, r1, portCONTEXT_SIZE ADDLIK r1, r1, portCONTEXT_SIZE
/* Return to the task. */ /* Return to the task. */
rtsd r14, 0 rtsd r14, 0
or r0, r0, r0 OR r0, r0, r0
.text .text
.align 4
#ifdef __arch64__
.align 8
#else
.align 4
#endif
_interrupt_handler: _interrupt_handler:
portSAVE_CONTEXT portSAVE_CONTEXT
/* Stack the return address. */ /* Stack the return address. */
swi r14, r1, portR14_OFFSET SI r14, r1, portR14_OFFSET
/* Switch to the ISR stack. */ /* Switch to the ISR stack. */
lwi r1, r0, pulISRStack LI r1, r0, pulISRStack
#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION ) #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
ori r18, r0, _stack_end ori r18, r0, _stack_end
@ -292,29 +337,29 @@ _interrupt_handler:
mts rshr, r18 mts rshr, r18
#endif #endif
/* The parameter to the interrupt handler. */ /* The parameter to the interrupt handler. */
ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE ORI r5, r0, configINTERRUPT_CONTROLLER_TO_USE
/* Execute any pending interrupts. */ /* Execute any pending interrupts. */
bralid r15, XIntc_DeviceInterruptHandler BRALID r15, XIntc_DeviceInterruptHandler
or r0, r0, r0 OR r0, r0, r0
/* See if a new task should be selected to execute. */ /* See if a new task should be selected to execute. */
lwi r18, r0, ulTaskSwitchRequested LI r18, r0, ulTaskSwitchRequested
or r18, r18, r0 OR r18, r18, r0
/* If ulTaskSwitchRequested is already zero, then jump straight to /* If ulTaskSwitchRequested is already zero, then jump straight to
restoring the task that is already in the Running state. */ restoring the task that is already in the Running state. */
beqi r18, task_switch_not_requested BEQI r18, task_switch_not_requested
/* Set ulTaskSwitchRequested back to zero as a task switch is about to be /* Set ulTaskSwitchRequested back to zero as a task switch is about to be
performed. */ performed. */
swi r0, r0, ulTaskSwitchRequested SI r0, r0, ulTaskSwitchRequested
/* ulTaskSwitchRequested was not 0 when tested. Select the next task to /* ulTaskSwitchRequested was not 0 when tested. Select the next task to
execute. */ execute. */
bralid r15, vTaskSwitchContext BRALID r15, vTaskSwitchContext
or r0, r0, r0 OR r0, r0, r0
task_switch_not_requested: task_switch_not_requested:
@ -322,19 +367,24 @@ task_switch_not_requested:
portRESTORE_CONTEXT portRESTORE_CONTEXT
.text .text
.align 4 #ifdef __arch64__
.align 8
#else
.align 4
#endif
VPortYieldASM: VPortYieldASM:
portSAVE_CONTEXT portSAVE_CONTEXT
/* Modify the return address so a return is done to the instruction after /* Modify the return address so a return is done to the instruction after
the call to VPortYieldASM. */ the call to VPortYieldASM. */
addi r14, r14, 8 ADDI r14, r14, 8
swi r14, r1, portR14_OFFSET SI r14, r1, portR14_OFFSET
/* Switch to use the ISR stack. */ /* Switch to use the ISR stack. */
lwi r1, r0, pulISRStack LI r1, r0, pulISRStack
#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION ) #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
ori r18, r0, _stack_end ori r18, r0, _stack_end
@ -343,15 +393,20 @@ VPortYieldASM:
mts rshr, r18 mts rshr, r18
#endif #endif
/* Select the next task to execute. */ /* Select the next task to execute. */
bralid r15, vTaskSwitchContext BRALID r15, vTaskSwitchContext
or r0, r0, r0 OR r0, r0, r0
/* Restore the context of the next task scheduled to execute. */ /* Restore the context of the next task scheduled to execute. */
portRESTORE_CONTEXT portRESTORE_CONTEXT
.text .text
.align 4 #ifdef __arch64__
.align 8
#else
.align 4
#endif
vPortStartFirstTask: vPortStartFirstTask:
portRESTORE_CONTEXT portRESTORE_CONTEXT
@ -360,14 +415,19 @@ vPortStartFirstTask:
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) #if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
.text .text
.align 4 #ifdef __arch64__
.align 8
#else
.align 4
#endif
vPortExceptionHandlerEntry: vPortExceptionHandlerEntry:
/* Take a copy of the stack pointer before vPortExecptionHandler is called, /* Take a copy of the stack pointer before vPortExecptionHandler is called,
storing its value prior to the function stack frame being created. */ storing its value prior to the function stack frame being created. */
swi r1, r0, pulStackPointerOnFunctionEntry SI r1, r0, pulStackPointerOnFunctionEntry
bralid r15, vPortExceptionHandler BRALID r15, vPortExceptionHandler
or r0, r0, r0 OR r0, r0, r0
#endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */ #endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */

View file

@ -50,20 +50,26 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #ifdef __arch64__
#define portBASE_TYPE long #define portSTACK_TYPE size_t
typedef uint64_t UBaseType_t;
#else
#define portSTACK_TYPE uint32_t
typedef unsigned long UBaseType_t;
#endif
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
@ -155,10 +161,14 @@ extern volatile uint32_t ulTaskSwitchRequested;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 4 #ifdef __arch64__
#define portSTACK_GROWTH ( -1 ) #define portBYTE_ALIGNMENT 8
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #else
#define portNOP() asm volatile ( "NOP" ) #define portBYTE_ALIGNMENT 4
#endif
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() asm volatile ( "NOP" )
#define portMEMORY_BARRIER() asm volatile ( "" ::: "memory" ) #define portMEMORY_BARRIER() asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -179,43 +189,43 @@ typedef struct PORT_REGISTER_DUMP
{ {
/* The following structure members hold the values of the MicroBlaze /* The following structure members hold the values of the MicroBlaze
* registers at the time the exception was raised. */ * registers at the time the exception was raised. */
uint32_t ulR1_SP; UINTPTR ulR1_SP;
uint32_t ulR2_small_data_area; UINTPTR ulR2_small_data_area;
uint32_t ulR3; UINTPTR ulR3;
uint32_t ulR4; UINTPTR ulR4;
uint32_t ulR5; UINTPTR ulR5;
uint32_t ulR6; UINTPTR ulR6;
uint32_t ulR7; UINTPTR ulR7;
uint32_t ulR8; UINTPTR ulR8;
uint32_t ulR9; UINTPTR ulR9;
uint32_t ulR10; UINTPTR ulR10;
uint32_t ulR11; UINTPTR ulR11;
uint32_t ulR12; UINTPTR ulR12;
uint32_t ulR13_read_write_small_data_area; UINTPTR ulR13_read_write_small_data_area;
uint32_t ulR14_return_address_from_interrupt; UINTPTR ulR14_return_address_from_interrupt;
uint32_t ulR15_return_address_from_subroutine; UINTPTR ulR15_return_address_from_subroutine;
uint32_t ulR16_return_address_from_trap; UINTPTR ulR16_return_address_from_trap;
uint32_t ulR17_return_address_from_exceptions; /* The exception entry code will copy the BTR into R17 if the exception occurred in the delay slot of a branch instruction. */ UINTPTR ulR17_return_address_from_exceptions; /* The exception entry code will copy the BTR into R17 if the exception occurred in the delay slot of a branch instruction. */
uint32_t ulR18; UINTPTR ulR18;
uint32_t ulR19; UINTPTR ulR19;
uint32_t ulR20; UINTPTR ulR20;
uint32_t ulR21; UINTPTR ulR21;
uint32_t ulR22; UINTPTR ulR22;
uint32_t ulR23; UINTPTR ulR23;
uint32_t ulR24; UINTPTR ulR24;
uint32_t ulR25; UINTPTR ulR25;
uint32_t ulR26; UINTPTR ulR26;
uint32_t ulR27; UINTPTR ulR27;
uint32_t ulR28; UINTPTR ulR28;
uint32_t ulR29; UINTPTR ulR29;
uint32_t ulR30; UINTPTR ulR30;
uint32_t ulR31; UINTPTR ulR31;
uint32_t ulPC; UINTPTR ulPC;
uint32_t ulESR; UINTPTR ulESR;
uint32_t ulMSR; UINTPTR ulMSR;
uint32_t ulEAR; UINTPTR ulEAR;
uint32_t ulFSR; UINTPTR ulFSR;
uint32_t ulEDR; UINTPTR ulEDR;
/* A human readable description of the exception cause. The strings used /* A human readable description of the exception cause. The strings used
* are the same as the #define constant names found in the * are the same as the #define constant names found in the