From 8bff60345135a3be4feee27eb099fe00a07047f9 Mon Sep 17 00:00:00 2001 From: Mubin Usman Sayyed Date: Mon, 30 Nov 2020 00:57:19 +0530 Subject: [PATCH] MicroblazeV9: Add support for 64 bit microblaze Updated MicroblazeV9 port, to support 64 bit version of Microblaze processor. Signed-off-by: Mubin Usman Sayyed --- portable/GCC/MicroBlazeV9/port.c | 16 +- portable/GCC/MicroBlazeV9/port_exceptions.c | 4 +- portable/GCC/MicroBlazeV9/portasm.S | 279 ++++++++++++-------- portable/GCC/MicroBlazeV9/portmacro.h | 86 +++--- 4 files changed, 237 insertions(+), 148 deletions(-) diff --git a/portable/GCC/MicroBlazeV9/port.c b/portable/GCC/MicroBlazeV9/port.c index d89aa3222..910b91f82 100644 --- a/portable/GCC/MicroBlazeV9/port.c +++ b/portable/GCC/MicroBlazeV9/port.c @@ -41,6 +41,7 @@ #include #include #include +#include /* 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 @@ -80,7 +81,7 @@ volatile UBaseType_t uxCriticalNesting = portINITIAL_NESTING_VALUE; /* This port uses a separate stack for interrupts. This prevents the stack of every task needing to be large enough to hold an entire interrupt stack on top of the task stack. */ -uint32_t *pulISRStack; +UINTPTR *pulISRStack; /* If an interrupt requests a context switch, then ulTaskSwitchRequested will get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt @@ -107,8 +108,8 @@ static XIntc xInterruptControllerInstance; StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { extern void *_SDA2_BASE_, *_SDA_BASE_; -const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_; -const uint32_t ulR13 = ( uint32_t ) &_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. @@ -237,7 +238,7 @@ extern void _start1( void ); BaseType_t xPortStartScheduler( void ) { extern void ( vPortStartFirstTask )( void ); -extern uint32_t _stack[]; +extern UINTPTR _stack[]; /* Setup the hardware to generate the tick. Interrupts are disabled when this function is called. @@ -251,7 +252,7 @@ extern uint32_t _stack[]; 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. */ @@ -288,8 +289,13 @@ extern void VPortYieldASM( void ); { /* 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(); } diff --git a/portable/GCC/MicroBlazeV9/port_exceptions.c b/portable/GCC/MicroBlazeV9/port_exceptions.c index 685a0c824..d04b89039 100644 --- a/portable/GCC/MicroBlazeV9/port_exceptions.c +++ b/portable/GCC/MicroBlazeV9/port_exceptions.c @@ -66,7 +66,7 @@ configINSTALL_EXCEPTION_HANDLERS is not set to 1. */ /* 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 @@ -148,7 +148,7 @@ extern void *pxCurrentTCB; 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(); diff --git a/portable/GCC/MicroBlazeV9/portasm.S b/portable/GCC/MicroBlazeV9/portasm.S index 00bd52356..6ce8e8a55 100644 --- a/portable/GCC/MicroBlazeV9/portasm.S +++ b/portable/GCC/MicroBlazeV9/portasm.S @@ -32,8 +32,18 @@ #include "microblaze_exceptions_g.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 @@ -41,8 +51,44 @@ back into the caller stack. */ #define portCONTEXT_SIZE 132 #define portMINUS_CONTEXT_SIZE -132 #endif +#endif /* Offsets from the stack pointer at which saved registers are placed. */ +#if defined (__arch64__) +#define portR31_OFFSET 8 +#define portR30_OFFSET 16 +#define portR29_OFFSET 24 +#define portR28_OFFSET 32 +#define portR27_OFFSET 40 +#define portR26_OFFSET 48 +#define portR25_OFFSET 56 +#define portR24_OFFSET 64 +#define portR23_OFFSET 72 +#define portR22_OFFSET 80 +#define portR21_OFFSET 88 +#define portR20_OFFSET 96 +#define portR19_OFFSET 104 +#define portR18_OFFSET 112 +#define portR17_OFFSET 120 +#define portR16_OFFSET 128 +#define portR15_OFFSET 136 +#define portR14_OFFSET 144 +#define portR13_OFFSET 152 +#define portR12_OFFSET 160 +#define portR11_OFFSET 168 +#define portR10_OFFSET 176 +#define portR9_OFFSET 184 +#define portR8_OFFSET 192 +#define portR7_OFFSET 200 +#define portR6_OFFSET 208 +#define portR5_OFFSET 216 +#define portR4_OFFSET 224 +#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 @@ -76,6 +122,7 @@ back into the caller stack. */ #define portCRITICAL_NESTING_OFFSET 124 #define portMSR_OFFSET 128 #define portFSR_OFFSET 132 +#endif .extern pxCurrentTCB .extern XIntc_DeviceInterruptHandler @@ -95,128 +142,128 @@ back into the caller stack. */ .macro portSAVE_CONTEXT /* Make room for the context on the stack. */ - addik r1, r1, portMINUS_CONTEXT_SIZE + ADDLIK r1, r1, portMINUS_CONTEXT_SIZE /* Stack general registers. */ - swi r31, r1, portR31_OFFSET - swi r30, r1, portR30_OFFSET - swi r29, r1, portR29_OFFSET - swi r28, r1, portR28_OFFSET - swi r27, r1, portR27_OFFSET - swi r26, r1, portR26_OFFSET - swi r25, r1, portR25_OFFSET - swi r24, r1, portR24_OFFSET - swi r23, r1, portR23_OFFSET - swi r22, r1, portR22_OFFSET - swi r21, r1, portR21_OFFSET - swi r20, r1, portR20_OFFSET - swi r19, r1, portR19_OFFSET - swi r18, r1, portR18_OFFSET - swi r17, r1, portR17_OFFSET - swi r16, r1, portR16_OFFSET - swi r15, r1, portR15_OFFSET + SI r31, r1, portR31_OFFSET + SI r30, r1, portR30_OFFSET + SI r29, r1, portR29_OFFSET + SI r28, r1, portR28_OFFSET + SI r27, r1, portR27_OFFSET + SI r26, r1, portR26_OFFSET + SI r25, r1, portR25_OFFSET + SI r24, r1, portR24_OFFSET + SI r23, r1, portR23_OFFSET + SI r22, r1, portR22_OFFSET + SI r21, r1, portR21_OFFSET + SI r20, r1, portR20_OFFSET + SI r19, r1, portR19_OFFSET + SI r18, r1, portR18_OFFSET + SI r17, r1, portR17_OFFSET + SI r16, r1, portR16_OFFSET + SI r15, r1, portR15_OFFSET /* R14 is saved later as it needs adjustment if a yield is performed. */ - swi r13, r1, portR13_OFFSET - swi r12, r1, portR12_OFFSET - swi r11, r1, portR11_OFFSET - swi r10, r1, portR10_OFFSET - swi r9, r1, portR9_OFFSET - swi r8, r1, portR8_OFFSET - swi r7, r1, portR7_OFFSET - swi r6, r1, portR6_OFFSET - swi r5, r1, portR5_OFFSET - swi r4, r1, portR4_OFFSET - swi r3, r1, portR3_OFFSET - swi r2, r1, portR2_OFFSET + SI r13, r1, portR13_OFFSET + SI r12, r1, portR12_OFFSET + SI r11, r1, portR11_OFFSET + SI r10, r1, portR10_OFFSET + SI r9, r1, portR9_OFFSET + SI r8, r1, portR8_OFFSET + SI r7, r1, portR7_OFFSET + SI r6, r1, portR6_OFFSET + SI r5, r1, portR5_OFFSET + SI r4, r1, portR4_OFFSET + SI r3, r1, portR3_OFFSET + SI r2, r1, portR2_OFFSET /* Stack the critical section nesting value. */ - lwi r18, r0, uxCriticalNesting - swi r18, r1, portCRITICAL_NESTING_OFFSET + LI r18, r0, uxCriticalNesting + SI r18, r1, portCRITICAL_NESTING_OFFSET /* Stack MSR. */ mfs r18, rmsr - swi r18, r1, portMSR_OFFSET + SI r18, r1, portMSR_OFFSET #if( XPAR_MICROBLAZE_USE_FPU != 0 ) /* Stack FSR. */ mfs r18, rfsr - swi r18, r1, portFSR_OFFSET + SI r18, r1, portFSR_OFFSET #endif /* Save the top of stack value to the TCB. */ - lwi r3, r0, pxCurrentTCB - sw r1, r0, r3 + LI r3, r0, pxCurrentTCB + STORE r1, r0, r3 .endm .macro portRESTORE_CONTEXT /* Load the top of stack value from the TCB. */ - lwi r18, r0, pxCurrentTCB - lw r1, r0, r18 + LI r18, r0, pxCurrentTCB + LOAD r1, r0, r18 /* Restore the general registers. */ - lwi r31, r1, portR31_OFFSET - lwi r30, r1, portR30_OFFSET - lwi r29, r1, portR29_OFFSET - lwi r28, r1, portR28_OFFSET - lwi r27, r1, portR27_OFFSET - lwi r26, r1, portR26_OFFSET - lwi r25, r1, portR25_OFFSET - lwi r24, r1, portR24_OFFSET - lwi r23, r1, portR23_OFFSET - lwi r22, r1, portR22_OFFSET - lwi r21, r1, portR21_OFFSET - lwi r20, r1, portR20_OFFSET - lwi r19, r1, portR19_OFFSET - lwi r17, r1, portR17_OFFSET - lwi r16, r1, portR16_OFFSET - lwi r15, r1, portR15_OFFSET - lwi r14, r1, portR14_OFFSET - lwi r13, r1, portR13_OFFSET - lwi r12, r1, portR12_OFFSET - lwi r11, r1, portR11_OFFSET - lwi r10, r1, portR10_OFFSET - lwi r9, r1, portR9_OFFSET - lwi r8, r1, portR8_OFFSET - lwi r7, r1, portR7_OFFSET - lwi r6, r1, portR6_OFFSET - lwi r5, r1, portR5_OFFSET - lwi r4, r1, portR4_OFFSET - lwi r3, r1, portR3_OFFSET - lwi r2, r1, portR2_OFFSET + LI r31, r1, portR31_OFFSET + LI r30, r1, portR30_OFFSET + LI r29, r1, portR29_OFFSET + LI r28, r1, portR28_OFFSET + LI r27, r1, portR27_OFFSET + LI r26, r1, portR26_OFFSET + LI r25, r1, portR25_OFFSET + LI r24, r1, portR24_OFFSET + LI r23, r1, portR23_OFFSET + LI r22, r1, portR22_OFFSET + LI r21, r1, portR21_OFFSET + LI r20, r1, portR20_OFFSET + LI r19, r1, portR19_OFFSET + LI r17, r1, portR17_OFFSET + LI r16, r1, portR16_OFFSET + LI r15, r1, portR15_OFFSET + LI r14, r1, portR14_OFFSET + LI r13, r1, portR13_OFFSET + LI r12, r1, portR12_OFFSET + LI r11, r1, portR11_OFFSET + LI r10, r1, portR10_OFFSET + LI r9, r1, portR9_OFFSET + LI r8, r1, portR8_OFFSET + LI r7, r1, portR7_OFFSET + LI r6, r1, portR6_OFFSET + LI r5, r1, portR5_OFFSET + LI r4, r1, portR4_OFFSET + LI r3, r1, portR3_OFFSET + LI r2, r1, portR2_OFFSET /* Reload the rmsr from the stack. */ - lwi r18, r1, portMSR_OFFSET + LI r18, r1, portMSR_OFFSET mts rmsr, r18 #if( XPAR_MICROBLAZE_USE_FPU != 0 ) /* Reload the FSR from the stack. */ - lwi r18, r1, portFSR_OFFSET + LI r18, r1, portFSR_OFFSET mts rfsr, r18 #endif /* Load the critical nesting value. */ - lwi r18, r1, portCRITICAL_NESTING_OFFSET - swi r18, r0, uxCriticalNesting + LI r18, r1, portCRITICAL_NESTING_OFFSET + SI r18, r0, uxCriticalNesting /* 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 last exited the running state through an interrupt. */ - xori r18, r18, 0 - bnei r18, exit_from_yield + XORI r18, r18, 0 + BNEI r18, exit_from_yield /* r18 was being used as a temporary. Now restore its true value from the stack. */ - lwi r18, r1, portR18_OFFSET + LI r18, r1, portR18_OFFSET /* 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 exited. */ rtid r14, 0 - or r0, r0, r0 + OR r0, r0, r0 .endm @@ -224,56 +271,67 @@ back into the caller stack. */ returned to last left the Running state by calling taskYIELD() (rather than being preempted by an interrupt). */ .text - .align 4 +#ifdef __arch64__ + .align 8 +#else + .align 4 +#endif + exit_from_yield: /* r18 was being used as a temporary. Now restore its true value from the stack. */ - lwi r18, r1, portR18_OFFSET + LI r18, r1, portR18_OFFSET /* Remove the stack frame. */ - addik r1, r1, portCONTEXT_SIZE + ADDLIK r1, r1, portCONTEXT_SIZE /* Return to the task. */ rtsd r14, 0 - or r0, r0, r0 + OR r0, r0, r0 .text - .align 4 + +#ifdef __arch64__ + .align 8 +#else + .align 4 +#endif + _interrupt_handler: portSAVE_CONTEXT /* Stack the return address. */ - swi r14, r1, portR14_OFFSET + SI r14, r1, portR14_OFFSET /* Switch to the ISR stack. */ - lwi r1, r0, pulISRStack + LI r1, r0, pulISRStack /* The parameter to the interrupt handler. */ - ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE + ORI r5, r0, configINTERRUPT_CONTROLLER_TO_USE /* Execute any pending interrupts. */ - bralid r15, XIntc_DeviceInterruptHandler - or r0, r0, r0 + BRALID r15, XIntc_DeviceInterruptHandler + OR r0, r0, r0 /* See if a new task should be selected to execute. */ - lwi r18, r0, ulTaskSwitchRequested - or r18, r18, r0 + LI r18, r0, ulTaskSwitchRequested + OR r18, r18, r0 /* If ulTaskSwitchRequested is already zero, then jump straight to 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 performed. */ - swi r0, r0, ulTaskSwitchRequested + SI r0, r0, ulTaskSwitchRequested /* ulTaskSwitchRequested was not 0 when tested. Select the next task to execute. */ - bralid r15, vTaskSwitchContext - or r0, r0, r0 + BRALID r15, vTaskSwitchContext + OR r0, r0, r0 task_switch_not_requested: @@ -282,28 +340,38 @@ task_switch_not_requested: .text - .align 4 +#ifdef __arch64__ + .align 8 +#else + .align 4 +#endif + VPortYieldASM: portSAVE_CONTEXT /* Modify the return address so a return is done to the instruction after the call to VPortYieldASM. */ - addi r14, r14, 8 - swi r14, r1, portR14_OFFSET + ADDI r14, r14, 8 + SI r14, r1, portR14_OFFSET /* Switch to use the ISR stack. */ - lwi r1, r0, pulISRStack + LI r1, r0, pulISRStack /* Select the next task to execute. */ - bralid r15, vTaskSwitchContext - or r0, r0, r0 + BRALID r15, vTaskSwitchContext + OR r0, r0, r0 /* Restore the context of the next task scheduled to execute. */ portRESTORE_CONTEXT .text - .align 4 +#ifdef __arch64__ + .align 8 +#else + .align 4 +#endif + vPortStartFirstTask: portRESTORE_CONTEXT @@ -313,14 +381,19 @@ vPortStartFirstTask: #if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) .text - .align 4 +#ifdef __arch64__ + .align 8 +#else + .align 4 +#endif + vPortExceptionHandlerEntry: /* Take a copy of the stack pointer before vPortExecptionHandler is called, storing its value prior to the function stack frame being created. */ - swi r1, r0, pulStackPointerOnFunctionEntry - bralid r15, vPortExceptionHandler - or r0, r0, r0 + SI r1, r0, pulStackPointerOnFunctionEntry + BRALID r15, vPortExceptionHandler + OR r0, r0, r0 #endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */ diff --git a/portable/GCC/MicroBlazeV9/portmacro.h b/portable/GCC/MicroBlazeV9/portmacro.h index 7bfd7f196..b3ddd3f8f 100644 --- a/portable/GCC/MicroBlazeV9/portmacro.h +++ b/portable/GCC/MicroBlazeV9/portmacro.h @@ -52,12 +52,18 @@ extern "C" { #define portDOUBLE double #define portLONG long #define portSHORT short +#ifdef __arch64__ +#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 unsigned long UBaseType_t; + #if( configUSE_16_BIT_TICKS == 1 ) typedef uint16_t TickType_t; @@ -145,7 +151,11 @@ extern volatile uint32_t ulTaskSwitchRequested; /*-----------------------------------------------------------*/ /* Hardware specifics. */ +#ifdef __arch64__ +#define portBYTE_ALIGNMENT 8 +#else #define portBYTE_ALIGNMENT 4 +#endif #define portSTACK_GROWTH ( -1 ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portNOP() asm volatile ( "NOP" ) @@ -163,43 +173,43 @@ typedef struct PORT_REGISTER_DUMP { /* The following structure members hold the values of the MicroBlaze registers at the time the exception was raised. */ - uint32_t ulR1_SP; - uint32_t ulR2_small_data_area; - uint32_t ulR3; - uint32_t ulR4; - uint32_t ulR5; - uint32_t ulR6; - uint32_t ulR7; - uint32_t ulR8; - uint32_t ulR9; - uint32_t ulR10; - uint32_t ulR11; - uint32_t ulR12; - uint32_t ulR13_read_write_small_data_area; - uint32_t ulR14_return_address_from_interrupt; - uint32_t ulR15_return_address_from_subroutine; - uint32_t 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. */ - uint32_t ulR18; - uint32_t ulR19; - uint32_t ulR20; - uint32_t ulR21; - uint32_t ulR22; - uint32_t ulR23; - uint32_t ulR24; - uint32_t ulR25; - uint32_t ulR26; - uint32_t ulR27; - uint32_t ulR28; - uint32_t ulR29; - uint32_t ulR30; - uint32_t ulR31; - uint32_t ulPC; - uint32_t ulESR; - uint32_t ulMSR; - uint32_t ulEAR; - uint32_t ulFSR; - uint32_t ulEDR; + UINTPTR ulR1_SP; + UINTPTR ulR2_small_data_area; + UINTPTR ulR3; + UINTPTR ulR4; + UINTPTR ulR5; + UINTPTR ulR6; + UINTPTR ulR7; + UINTPTR ulR8; + UINTPTR ulR9; + UINTPTR ulR10; + UINTPTR ulR11; + UINTPTR ulR12; + UINTPTR ulR13_read_write_small_data_area; + UINTPTR ulR14_return_address_from_interrupt; + UINTPTR ulR15_return_address_from_subroutine; + UINTPTR ulR16_return_address_from_trap; + 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. */ + UINTPTR ulR18; + UINTPTR ulR19; + UINTPTR ulR20; + UINTPTR ulR21; + UINTPTR ulR22; + UINTPTR ulR23; + UINTPTR ulR24; + UINTPTR ulR25; + UINTPTR ulR26; + UINTPTR ulR27; + UINTPTR ulR28; + UINTPTR ulR29; + UINTPTR ulR30; + UINTPTR ulR31; + UINTPTR ulPC; + UINTPTR ulESR; + UINTPTR ulMSR; + UINTPTR ulEAR; + UINTPTR ulFSR; + UINTPTR ulEDR; /* A human readable description of the exception cause. The strings used are the same as the #define constant names found in the