Skip to content

Commit 5040a67

Browse files
authored
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 <[email protected]>
1 parent 8e664fc commit 5040a67

File tree

6 files changed

+522
-312
lines changed

6 files changed

+522
-312
lines changed

.github/.cSpellWords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ bics
5454
BISR
5555
BODIEN
5656
BODSTS
57+
brealid
5758
BRGR
5859
brhi
5960
brne

.github/workflows/kernel-demos.yml

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
name: FreeRTOS-Kernel Demos
22
on: [push, pull_request]
33

4+
env:
5+
# The bash escape character is \033
6+
bashPass: \033[32;1mPASSED -
7+
bashInfo: \033[33;1mINFO -
8+
bashFail: \033[31;1mFAILED -
9+
bashEnd: \033[0m
10+
411
jobs:
512
WIN32-MSVC:
613
name: WIN32 MSVC
@@ -147,6 +154,92 @@ jobs:
147154
working-directory: FreeRTOS/Demo/msp430_GCC
148155
run: make -j
149156

157+
MicroBlaze-GCC:
158+
name: GCC MicroBlaze Toolchain
159+
runs-on: ubuntu-latest
160+
steps:
161+
- name: Checkout the FreeRTOS/FreeRTOS Repository
162+
uses: actions/checkout@v3
163+
with:
164+
ref: main
165+
repository: FreeRTOS/FreeRTOS
166+
fetch-depth: 1
167+
168+
- env:
169+
stepName: Fetch Community-Supported-Demos Submodule
170+
shell: bash
171+
run: |
172+
# Fetch Community-Supported-Demos Submodule
173+
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
174+
git submodule update --checkout --init --depth 1 FreeRTOS/Demo/ThirdParty/Community-Supported-Demos
175+
# This repository contains the microblaze_instructions.h header file
176+
git clone https://github.com/Xilinx/embeddedsw.git --branch xilinx_v2023.1
177+
echo "::endgroup::"
178+
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
179+
180+
# Checkout user pull request changes
181+
- name: Checkout Pull Request
182+
uses: actions/checkout@v3
183+
with:
184+
path: ./FreeRTOS/Source
185+
186+
- env:
187+
stepName: Install Dependancies
188+
shell: bash
189+
run: |
190+
# ${{ env.stepName }}
191+
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
192+
sudo apt update -y
193+
sudo apt upgrade -y
194+
sudo apt install -y build-essential m4 debhelper bison texinfo dejagnu flex
195+
sudo apt install -y autogen gawk libgmp-dev libmpc-dev libmpfr-dev
196+
sudo apt install -y patchutils sharutils zlib1g-dev autoconf2.64
197+
198+
# Download the mb-gcc toolchain from github
199+
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/binutils-microblaze_2.35-2021-0623+1_amd64.deb;
200+
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/gcc-microblaze_10.2.0-2021-0623+2_amd64.deb;
201+
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;
202+
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;
203+
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze_3.3.0-2021-0623+3_all.deb;
204+
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/newlib-source_3.3.0-2021-0623+3_all.deb;
205+
206+
# Install the packages for the toolchain
207+
sudo apt install -y ./binutils-microblaze*.deb;
208+
sudo apt install -y ./gcc-microblaze*.deb;
209+
sudo apt install -y ./libnewlib-microblaze-dev*.deb;
210+
sudo apt install -y ./libnewlib-microblaze-doc*.deb;
211+
sudo apt install -y ./libnewlib-microblaze*.deb;
212+
sudo apt install -y ./newlib-source*.deb;
213+
214+
# Validate that the toolchain is in the path and can be called
215+
which mb-gcc
216+
mb-gcc --version
217+
218+
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
219+
220+
- env:
221+
stepName: Compile Microblaze Port
222+
shell: bash
223+
run: |
224+
# ${{ env.stepName }}
225+
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
226+
# Compile MicroBlazeV9 Port files to validate they build
227+
mb-gcc -mcpu=v9.5 -c \
228+
FreeRTOS/Source/portable/GCC/MicroBlazeV9/port.c \
229+
FreeRTOS/Source/portable/GCC/MicroBlazeV9/portasm.S \
230+
FreeRTOS/Source/portable/GCC/MicroBlazeV9/port_exceptions.c \
231+
FreeRTOS/Source/tasks.c \
232+
FreeRTOS/Source/list.c \
233+
-I embeddedsw/lib/bsp/standalone/src/microblaze \
234+
-I FreeRTOS/Source/portable/GCC/MicroBlazeV9/ \
235+
-I FreeRTOS/Source/include \
236+
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src \
237+
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/standalone_v5_4/src \
238+
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/include \
239+
-I FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_5/src
240+
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
241+
242+
150243
ARM-GCC:
151244
name: GNU ARM Toolchain
152245
runs-on: ubuntu-latest
@@ -164,7 +257,7 @@ jobs:
164257
# Fetch Community-Supported-Demos Submodule
165258
echo "::group::Fetch Community-Supported-Demos Submodule"
166259
git submodule update --checkout --init --depth 1 FreeRTOS/Demo/ThirdParty/Community-Supported-Demos
167-
echo "::engdroup::"
260+
echo "::endgroup::"
168261
if [ "$?" = "0" ]; then
169262
echo -e "\033[32;3mCloned the Community-Supported-Demos\033[0m"
170263
else

portable/GCC/MicroBlazeV9/port.c

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <xintc_i.h>
4343
#include <xil_exception.h>
4444
#include <microblaze_exceptions_g.h>
45+
#include <microblaze_instructions.h>
4546

4647
/* Tasks are started with a critical section nesting of 0 - however, prior to
4748
* the scheduler being commenced interrupts should not be enabled, so the critical
@@ -58,6 +59,13 @@
5859
* given to the FSR register when the initial context is set up for a task being
5960
* created. */
6061
#define portINITIAL_FSR ( 0U )
62+
/*
63+
* Global counter used for calculation of run time statistics of tasks.
64+
* Defined only when the relevant option is turned on
65+
*/
66+
#if (configGENERATE_RUN_TIME_STATS==1)
67+
volatile uint32_t ulHighFrequencyTimerTicks;
68+
#endif
6169

6270
/*-----------------------------------------------------------*/
6371

@@ -116,10 +124,11 @@ static XIntc xInterruptControllerInstance;
116124
void * pvParameters )
117125
#endif
118126
{
119-
extern void * _SDA2_BASE_;
120-
extern void * _SDA_BASE_;
121-
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
122-
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
127+
extern void *_SDA2_BASE_;
128+
extern void *_SDA_BASE_;
129+
const UINTPTR ulR2 = ( UINTPTR ) &_SDA2_BASE_;
130+
const UINTPTR ulR13 = ( UINTPTR ) &_SDA_BASE_;
131+
123132
extern void _start1( void );
124133

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

256265
BaseType_t xPortStartScheduler( void )
257266
{
258-
extern void( vPortStartFirstTask )( void );
259-
extern uint32_t _stack[];
267+
extern void ( vPortStartFirstTask )( void );
268+
extern UINTPTR _stack[];
260269

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

272281
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
273-
pulISRStack = ( uint32_t * ) _stack;
282+
pulISRStack = ( UINTPTR * ) _stack;
274283

275284
/* Ensure there is enough space for the functions called from the interrupt
276285
* service routines to write back into the stack frame of the caller. */
@@ -304,13 +313,18 @@ void vPortYield( void )
304313
* not interrupted by the tick ISR. It is not a problem to do this as
305314
* each task maintains its own interrupt status. */
306315
portENTER_CRITICAL();
307-
{
308-
/* Jump directly to the yield function to ensure there is no
309-
* compiler generated prologue code. */
310-
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
311-
"or r0, r0, r0 \n\t" );
312-
}
313-
portEXIT_CRITICAL();
316+
{
317+
/* Jump directly to the yield function to ensure there is no
318+
* compiler generated prologue code. */
319+
#ifdef __arch64__
320+
asm volatile ( "brealid r14, VPortYieldASM \n\t" \
321+
"or r0, r0, r0 \n\t" );
322+
#else
323+
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
324+
"or r0, r0, r0 \n\t" );
325+
#endif
326+
}
327+
portEXIT_CRITICAL();
314328
}
315329
/*-----------------------------------------------------------*/
316330

@@ -434,22 +448,34 @@ void vPortTickISR( void * pvUnused )
434448
{
435449
extern void vApplicationClearTimerInterrupt( void );
436450

437-
/* Ensure the unused parameter does not generate a compiler warning. */
438-
( void ) pvUnused;
439-
440-
/* This port uses an application defined callback function to clear the tick
441-
* interrupt because the kernel will run on lots of different MicroBlaze and
442-
* FPGA configurations - not all of which will have the same timer peripherals
443-
* defined or available. An example definition of
444-
* vApplicationClearTimerInterrupt() is provided in the official demo
445-
* application that accompanies this port. */
446-
vApplicationClearTimerInterrupt();
447-
448-
/* Increment the RTOS tick - this might cause a task to unblock. */
449-
if( xTaskIncrementTick() != pdFALSE )
451+
/* Ensure the unused parameter does not generate a compiler warning. */
452+
( void ) pvUnused;
453+
454+
/* The Xilinx implementation of generating run time task stats uses the same timer used for generating
455+
* FreeRTOS ticks. In case user decides to generate run time stats the tick handler is called more
456+
* frequently (10 times faster). The timer ick handler uses logic to handle the same. It handles
457+
* the FreeRTOS tick once per 10 interrupts.
458+
* For handling generation of run time stats, it increments a pre-defined counter every time the
459+
* interrupt handler executes. */
460+
#if (configGENERATE_RUN_TIME_STATS == 1)
461+
ulHighFrequencyTimerTicks++;
462+
if (!(ulHighFrequencyTimerTicks % 10))
463+
#endif
450464
{
451-
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
452-
ulTaskSwitchRequested = 1;
465+
/* This port uses an application defined callback function to clear the tick
466+
* interrupt because the kernel will run on lots of different MicroBlaze and
467+
* FPGA configurations - not all of which will have the same timer peripherals
468+
* defined or available. An example definition of
469+
* vApplicationClearTimerInterrupt() is provided in the official demo
470+
* application that accompanies this port. */
471+
vApplicationClearTimerInterrupt();
472+
473+
/* Increment the RTOS tick - this might cause a task to unblock. */
474+
if( xTaskIncrementTick() != pdFALSE )
475+
{
476+
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
477+
ulTaskSwitchRequested = 1;
478+
}
453479
}
454480
}
455481
/*-----------------------------------------------------------*/
@@ -495,4 +521,25 @@ static int32_t prvInitialiseInterruptController( void )
495521

496522
return lStatus;
497523
}
524+
525+
#if( configGENERATE_RUN_TIME_STATS == 1 )
526+
/*
527+
* For Xilinx implementation this is a dummy function that does a redundant operation
528+
* of zeroing out the global counter.
529+
* It is called by FreeRTOS kernel.
530+
*/
531+
void xCONFIGURE_TIMER_FOR_RUN_TIME_STATS (void)
532+
{
533+
ulHighFrequencyTimerTicks = 0;
534+
}
535+
/*
536+
* For Xilinx implementation this function returns the global counter used for
537+
* run time task stats calculation.
538+
* It is called by FreeRTOS kernel task handling logic.
539+
*/
540+
uint32_t xGET_RUN_TIME_COUNTER_VALUE (void)
541+
{
542+
return ulHighFrequencyTimerTicks;
543+
}
544+
#endif
498545
/*-----------------------------------------------------------*/

portable/GCC/MicroBlazeV9/port_exceptions.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767

6868
/* This variable is set in the exception entry code, before
6969
* vPortExceptionHandler is called. */
70-
uint32_t * pulStackPointerOnFunctionEntry = NULL;
70+
UINTPTR *pulStackPointerOnFunctionEntry = NULL;
7171

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

8685
/* vApplicationExceptionRegisterDump() is a callback function that the
@@ -149,7 +148,7 @@
149148
xRegisterDump.ulR29 = mfgpr( R29 );
150149
xRegisterDump.ulR30 = mfgpr( R30 );
151150
xRegisterDump.ulR31 = mfgpr( R31 );
152-
xRegisterDump.ulR1_SP = ( ( uint32_t ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
151+
xRegisterDump.ulR1_SP = ( ( UINTPTR ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
153152
xRegisterDump.ulEAR = mfear();
154153
xRegisterDump.ulESR = mfesr();
155154
xRegisterDump.ulEDR = mfedr();

0 commit comments

Comments
 (0)