From 9465667e4082ca090f75e77340b95e5f4870b07d Mon Sep 17 00:00:00 2001 From: richardbarry Date: Sun, 29 Aug 2010 07:24:30 +0000 Subject: [PATCH] Update RX GCC port - including extracting all inline asm into separate asm file. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1065 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/GCC/RX600/port.c | 179 ++------------------- Source/portable/GCC/RX600/port_asm.asm | 206 +++++++++++++++++++++++++ Source/portable/GCC/RX600/portmacro.h | 10 +- 3 files changed, 220 insertions(+), 175 deletions(-) create mode 100644 Source/portable/GCC/RX600/port_asm.asm diff --git a/Source/portable/GCC/RX600/port.c b/Source/portable/GCC/RX600/port.c index 37e624346..c5d4b69b4 100644 --- a/Source/portable/GCC/RX600/port.c +++ b/Source/portable/GCC/RX600/port.c @@ -78,7 +78,7 @@ PSW is set with U and I set, and PM and IPL clear. */ * Function to start the first task executing - written in asm code as direct * access to registers is required. */ -static void prvStartFirstTask( void ) __attribute__((naked)); +extern void prvStartFirstTask( void ); /* * Software interrupt handler. Performs the actual context switch (saving and @@ -88,19 +88,14 @@ static void prvStartFirstTask( void ) __attribute__((naked)); static void prvYieldHandler( void ); /* - * The entry point for the software interrupt handler. This is the function - * that calls the inline asm function prvYieldHandler(). It is installed in - * the vector table, but the code that installs it is in prvYieldHandler rather - * than using a #pragma. + * The tick ISR handler. The peripheral used is configured by the application + * via a hook/callback function. */ -void vSoftwareInterruptISR( void ); +void vTickISR( void ) __attribute__((interrupt)); /*-----------------------------------------------------------*/ -/* This is accessed by the inline assembler functions so is file scope for -convenience. */ extern void *pxCurrentTCB; -extern void vTaskSwitchContext( void ); /*-----------------------------------------------------------*/ @@ -190,65 +185,24 @@ extern void vApplicationSetupTimerInterrupt( void ); /* Ensure the software interrupt is set to the kernel priority. */ _IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY; - + /* Start the first task. */ prvStartFirstTask(); } - /* Just to make sure the function is not optimised away. */ - ( void ) vSoftwareInterruptISR(); - /* Should not get here. */ return pdFAIL; } /*-----------------------------------------------------------*/ -static void prvStartFirstTask( void ) -{ - __asm - ( - /* When starting the scheduler there is nothing that needs moving to the - interrupt stack because the function is not called from an interrupt. - Just ensure the current stack is the user stack. */ - "SETPSW U \n" \ - - /* Obtain the location of the stack associated with which ever task - pxCurrentTCB is currently pointing to. */ - "MOV.L #_pxCurrentTCB, R15 \n" \ - "MOV.L [R15], R15 \n" \ - "MOV.L [R15], R0 \n" \ - - /* Restore the registers from the stack of the task pointed to by - pxCurrentTCB. */ - "POP R15 \n" \ - - /* Accumulator low 32 bits. */ - "MVTACLO R15 \n" \ - "POP R15 \n" \ - - /* Accumulator high 32 bits. */ - "MVTACHI R15 \n" \ - "POP R15 \n" \ - - /* Floating point status word. */ - "MVTC R15, FPSW \n" \ - - /* R1 to R15 - R0 is not included as it is the SP. */ - "POPM R1-R15 \n" \ - - /* This pops the remaining registers. */ - "RTE \n" \ - "NOP \n" \ - "NOP \n" - ); -} -/*-----------------------------------------------------------*/ - void vTickISR( void ) { + /* Re-enable interrupts. */ + __asm volatile( "SETPSW I" ); + /* Increment the tick, and perform any processing the new tick value necessitates. */ - vTaskIncrementTick(); + vTaskIncrementTick(); /* Only select a new task if the preemptive scheduler is being used. */ #if( configUSE_PREEMPTION == 1 ) @@ -257,124 +211,9 @@ void vTickISR( void ) } /*-----------------------------------------------------------*/ -void vSoftwareInterruptISR( void ) -{ -// prvYieldHandler(); -} -/*-----------------------------------------------------------*/ - -#if 0 -#pragma inline_asm prvYieldHandler -static void prvYieldHandler( void ) -{ - /* Install as the software interrupt handler. */ - .RVECTOR _VECT( _ICU_SWINT ), _vSoftwareInterruptISR - - /* Re-enable interrupts. */ - SETPSW I - - /* Move the data that was automatically pushed onto the interrupt stack when - the interrupt occurred from the interrupt stack to the user stack. - - R15 is saved before it is clobbered. */ - PUSH.L R15 - - /* Read the user stack pointer. */ - MVFC USP, R15 - - /* Move the address down to the data being moved. */ - SUB #12, R15 - MVTC R15, USP - - /* Copy the data across. */ - MOV.L [ R0 ], [ R15 ] ; R15 - MOV.L 4[ R0 ], 4[ R15 ] ; PC - MOV.L 8[ R0 ], 8[ R15 ] ; PSW - - /* Move the interrupt stack pointer to its new correct position. */ - ADD #12, R0 - - /* All the rest of the registers are saved directly to the user stack. */ - SETPSW U - - /* Save the rest of the general registers (R15 has been saved already). */ - PUSHM R1-R14 - - /* Save the FPSW and accumulator. */ - MVFC FPSW, R15 - PUSH.L R15 - MVFACHI R15 - PUSH.L R15 - MVFACMI R15 ; Middle order word. - SHLL #16, R15 ; Shifted left as it is restored to the low order word. - PUSH.L R15 - - /* Save the stack pointer to the TCB. */ - MOV.L #_pxCurrentTCB, R15 - MOV.L [ R15 ], R15 - MOV.L R0, [ R15 ] - - /* Ensure the interrupt mask is set to the syscall priority while the kernel - structures are being accessed. */ - MVTIPL #configMAX_SYSCALL_INTERRUPT_PRIORITY - - /* Select the next task to run. */ - BSR.A _vTaskSwitchContext - - /* Reset the interrupt mask as no more data structure access is required. */ - MVTIPL #configKERNEL_INTERRUPT_PRIORITY - - /* Load the stack pointer of the task that is now selected as the Running - state task from its TCB. */ - MOV.L #_pxCurrentTCB,R15 - MOV.L [ R15 ], R15 - MOV.L [ R15 ], R0 - - /* Restore the context of the new task. The PSW (Program Status Word) and - PC will be popped by the RTE instruction. */ - POP R15 - MVTACLO R15 - POP R15 - MVTACHI R15 - POP R15 - MVTC R15,FPSW - POPM R1-R15 - RTE - NOP - NOP -} -#endif -/*-----------------------------------------------------------*/ - void vPortEndScheduler( void ) { /* Not implemented as there is nothing to return to. */ - - /* The following line is just to prevent the symbol getting optimised away. */ - ( void ) vTaskSwitchContext(); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetIPL( void ) -{ - __asm( - "MVFC PSW, R1 \n" \ - "SHLR #28, R1 \n" \ - "RTS " - ); -} -/*-----------------------------------------------------------*/ - -void vPortSetIPL( unsigned long ulNewIPL ) -{ - __asm( - "MVFC PSW, R5 \n" \ - "SHLL #28, R1 \n" \ - "AND #-0F000001H, R5 \n" \ - "OR R1, R5 \n" \ - "MVTC R5, PSW \n" \ - "RTS " - ); } /*-----------------------------------------------------------*/ diff --git a/Source/portable/GCC/RX600/port_asm.asm b/Source/portable/GCC/RX600/port_asm.asm new file mode 100644 index 000000000..8351a5971 --- /dev/null +++ b/Source/portable/GCC/RX600/port_asm.asm @@ -0,0 +1,206 @@ +/* + FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). 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 exception 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. +*/ + + .list + .section .text + .global _prvStartFirstTask + .global _vSoftwareInterruptISR + .global _ulPortGetIPL + .global _vPortSetIPL + + .extern _pxCurrentTCB + + .align 4 + +_prvStartFirstTask: + + /* When starting the scheduler there is nothing that needs moving to the + interrupt stack because the function is not called from an interrupt. + Just ensure the current stack is the user stack. */ + SETPSW U + + /* Obtain the location of the stack associated with which ever task + pxCurrentTCB is currently pointing to. */ + MOV.L #_pxCurrentTCB, R15 + MOV.L [R15], R15 + MOV.L [R15], R0 + + /* Restore the registers from the stack of the task pointed to by + pxCurrentTCB. */ + POP R15 + + /* Accumulator low 32 bits. */ + MVTACLO R15 + POP R15 + + /* Accumulator high 32 bits. */ + MVTACHI R15 + POP R15 + + /* Floating point status word. */ + MVTC R15, FPSW + + /* R1 to R15 - R0 is not included as it is the SP. */ + POPM R1-R15 + + /* This pops the remaining registers. */ + RTE + NOP + NOP + +/*-----------------------------------------------------------*/ + + .align 4 +_vSoftwareInterruptISR: + + /* Re-enable interrupts. */ + SETPSW I + + /* Move the data that was automatically pushed onto the interrupt stack when + the interrupt occurred from the interrupt stack to the user stack. + + R15 is saved before it is clobbered. */ + PUSH.L R15 + + /* Read the user stack pointer. */ + MVFC USP, R15 + + /* Move the address down to the data being moved. */ + SUB #12, R15 + MVTC R15, USP + + /* Copy the data across, R15, then PC, then PSW. */ + MOV.L [ R0 ], [ R15 ] + MOV.L 4[ R0 ], 4[ R15 ] + MOV.L 8[ R0 ], 8[ R15 ] + + /* Move the interrupt stack pointer to its new correct position. */ + ADD #12, R0 + + /* All the rest of the registers are saved directly to the user stack. */ + SETPSW U + + /* Save the rest of the general registers (R15 has been saved already). */ + PUSHM R1-R14 + + /* Save the FPSW and accumulator. */ + MVFC FPSW, R15 + PUSH.L R15 + MVFACHI R15 + PUSH.L R15 + + /* Middle word. */ + MVFACMI R15 + + /* Shifted left as it is restored to the low order word. */ + SHLL #16, R15 + PUSH.L R15 + + /* Save the stack pointer to the TCB. */ + MOV.L #_pxCurrentTCB, R15 + MOV.L [ R15 ], R15 + MOV.L R0, [ R15 ] + + /* Ensure the interrupt mask is set to the syscall priority while the kernel + structures are being accessed. */ + MVTIPL #4 + + /* Select the next task to run. */ + BSR.A _vTaskSwitchContext + + /* Reset the interrupt mask as no more data structure access is required. */ + MVTIPL #1 + + /* Load the stack pointer of the task that is now selected as the Running + state task from its TCB. */ + MOV.L #_pxCurrentTCB,R15 + MOV.L [ R15 ], R15 + MOV.L [ R15 ], R0 + + /* Restore the context of the new task. The PSW (Program Status Word) and + PC will be popped by the RTE instruction. */ + POP R15 + MVTACLO R15 + POP R15 + MVTACHI R15 + POP R15 + MVTC R15, FPSW + POPM R1-R15 + RTE + NOP + NOP + + /*:: i(configMAX_SYSCALL_INTERRUPT_PRIORITY), i(configKERNEL_INTERRUPT_PRIORITY)*/ +/*-----------------------------------------------------------*/ + + .align 4 + +_ulPortGetIPL: + + MVFC PSW, R1 + SHLR #24, R1 + RTS +/*-----------------------------------------------------------*/ + + .align 4 + +_vPortSetIPL: + + MVFC PSW, R5 + SHLL #24, R1 + AND #-0F000001H, R5 + OR R1, R5 + MVTC R5, PSW + RTS + + .end diff --git a/Source/portable/GCC/RX600/portmacro.h b/Source/portable/GCC/RX600/portmacro.h index 592cfcee9..91223530c 100644 --- a/Source/portable/GCC/RX600/portmacro.h +++ b/Source/portable/GCC/RX600/portmacro.h @@ -92,7 +92,7 @@ portSTACK_TYPE and portBASE_TYPE. */ #define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */ #define portSTACK_GROWTH -1 #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) -#define portNOP() __asm( "NOP" ) +#define portNOP() __asm volatile( "NOP" ) /* The location of the software interrupt register. Software interrupts use vector 27. */ @@ -104,8 +104,8 @@ vector 27. */ * These macros should be called directly, but through the taskENTER_CRITICAL() * and taskEXIT_CRITICAL() macros. */ -#define portENABLE_INTERRUPTS() __asm ( "MVTIPL #0" ); -#define portDISABLE_INTERRUPTS() __asm ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) ) +#define portENABLE_INTERRUPTS() __asm volatile ( "MVTIPL #0" ); +#define portDISABLE_INTERRUPTS() __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) ) /* Critical nesting counts are stored in the TCB. */ #define portCRITICAL_NESTING_IN_TCB ( 1 ) @@ -117,8 +117,8 @@ extern void vTaskExitCritical( void ); #define portEXIT_CRITICAL() vTaskExitCritical(); /* As this port allows interrupt nesting... */ -unsigned long ulPortGetIPL( void ) __attribute__((naked)); -void vPortSetIPL( unsigned long ulNewIPL ) __attribute__((naked)); +unsigned long ulPortGetIPL( void ); +void vPortSetIPL( unsigned long ulNewIPL ); #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortGetIPL(); portDISABLE_INTERRUPTS() #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) vPortSetIPL( uxSavedInterruptStatus ) -- 2.39.2