Skip to content

Commit

Permalink
Sync up MicroblazeV9 port with Xilinx tree (#220)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
mubinsyed authored Jan 26, 2024
1 parent 8e664fc commit 5040a67
Show file tree
Hide file tree
Showing 6 changed files with 522 additions and 312 deletions.
1 change: 1 addition & 0 deletions .github/.cSpellWords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ bics
BISR
BODIEN
BODSTS
brealid
BRGR
brhi
brne
Expand Down
95 changes: 94 additions & 1 deletion .github/workflows/kernel-demos.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
name: FreeRTOS-Kernel Demos
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:
WIN32-MSVC:
name: WIN32 MSVC
Expand Down Expand Up @@ -147,6 +154,92 @@ jobs:
working-directory: FreeRTOS/Demo/msp430_GCC
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:
name: GNU ARM Toolchain
runs-on: ubuntu-latest
Expand All @@ -164,7 +257,7 @@ jobs:
# 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
echo "::engdroup::"
echo "::endgroup::"
if [ "$?" = "0" ]; then
echo -e "\033[32;3mCloned the Community-Supported-Demos\033[0m"
else
Expand Down
105 changes: 76 additions & 29 deletions portable/GCC/MicroBlazeV9/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <xintc_i.h>
#include <xil_exception.h>
#include <microblaze_exceptions_g.h>
#include <microblaze_instructions.h>

/* 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
Expand All @@ -58,6 +59,13 @@
* given to the FSR register when the initial context is set up for a task being
* created. */
#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

/*-----------------------------------------------------------*/

Expand Down Expand Up @@ -116,10 +124,11 @@ static XIntc xInterruptControllerInstance;
void * pvParameters )
#endif
{
extern void * _SDA2_BASE_;
extern void * _SDA_BASE_;
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
extern void *_SDA2_BASE_;
extern void *_SDA_BASE_;
const UINTPTR ulR2 = ( UINTPTR ) &_SDA2_BASE_;
const UINTPTR ulR13 = ( UINTPTR ) &_SDA_BASE_;

extern void _start1( void );

/* Place a few bytes of known values on the bottom of the stack.
Expand Down Expand Up @@ -255,8 +264,8 @@ static XIntc xInterruptControllerInstance;

BaseType_t xPortStartScheduler( void )
{
extern void( vPortStartFirstTask )( void );
extern uint32_t _stack[];
extern void ( vPortStartFirstTask )( void );
extern UINTPTR _stack[];

/* Setup the hardware to generate the tick. Interrupts are disabled when
* this function is called.
Expand All @@ -270,7 +279,7 @@ BaseType_t xPortStartScheduler( void )
vApplicationSetupTimerInterrupt();

/* 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
* service routines to write back into the stack frame of the caller. */
Expand Down Expand Up @@ -304,13 +313,18 @@ void vPortYield( void )
* not interrupted by the tick ISR. It is not a problem to do this as
* each task maintains its own interrupt status. */
portENTER_CRITICAL();
{
/* Jump directly to the yield function to ensure there is no
* compiler generated prologue code. */
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
"or r0, r0, r0 \n\t" );
}
portEXIT_CRITICAL();
{
/* Jump directly to the yield function to ensure there is no
* compiler generated prologue code. */
#ifdef __arch64__
asm volatile ( "brealid r14, VPortYieldASM \n\t" \
"or r0, r0, r0 \n\t" );
#else
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
"or r0, r0, r0 \n\t" );
#endif
}
portEXIT_CRITICAL();
}
/*-----------------------------------------------------------*/

Expand Down Expand Up @@ -434,22 +448,34 @@ void vPortTickISR( void * pvUnused )
{
extern void vApplicationClearTimerInterrupt( void );

/* Ensure the unused parameter does not generate a compiler warning. */
( void ) pvUnused;

/* This port uses an application defined callback function to clear the tick
* 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 )
/* Ensure the unused parameter does not generate a compiler warning. */
( void ) pvUnused;

/* The Xilinx implementation of generating run time task stats uses the same timer used for generating
* FreeRTOS ticks. In case user decides to generate run time stats the tick handler is called more
* frequently (10 times faster). The timer ick handler uses logic to handle the same. It handles
* the FreeRTOS tick once per 10 interrupts.
* For handling generation of run time stats, it increments a pre-defined counter every time the
* interrupt handler executes. */
#if (configGENERATE_RUN_TIME_STATS == 1)
ulHighFrequencyTimerTicks++;
if (!(ulHighFrequencyTimerTicks % 10))
#endif
{
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
ulTaskSwitchRequested = 1;
/* This port uses an application defined callback function to clear the tick
* 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;
}
}
}
/*-----------------------------------------------------------*/
Expand Down Expand Up @@ -495,4 +521,25 @@ static int32_t prvInitialiseInterruptController( void )

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
/*-----------------------------------------------------------*/
5 changes: 2 additions & 3 deletions portable/GCC/MicroBlazeV9/port_exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@

/* This variable is set in the exception entry code, before
* vPortExceptionHandler is called. */
uint32_t * pulStackPointerOnFunctionEntry = NULL;
UINTPTR *pulStackPointerOnFunctionEntry = NULL;

/* This is the structure that is filled with the MicroBlaze context as it
* existed immediately prior to the exception occurrence. A pointer to this
Expand All @@ -80,7 +80,6 @@
* in portasm.S. */
void vPortExceptionHandler( void * pvExceptionID );
extern void vPortExceptionHandlerEntry( void * pvExceptionID );

/*-----------------------------------------------------------*/

/* vApplicationExceptionRegisterDump() is a callback function that the
Expand Down Expand Up @@ -149,7 +148,7 @@
xRegisterDump.ulR29 = mfgpr( R29 );
xRegisterDump.ulR30 = mfgpr( R30 );
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.ulESR = mfesr();
xRegisterDump.ulEDR = mfedr();
Expand Down
Loading

0 comments on commit 5040a67

Please sign in to comment.