From ef8079daf72aa34d0cf6d77fb67684c6246debe4 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Mon, 20 Sep 2010 20:01:00 +0000 Subject: [PATCH] RX GCC port - Introduce macros that perform the interrupt entry and exit manually, then move the asm code back as naked functions within the port.c file. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1111 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/GCC/RX600/port.c | 174 +++++++++++++++++++-- Source/portable/GCC/RX600/port_asm.asm | 206 ------------------------- Source/portable/GCC/RX600/portmacro.h | 8 +- 3 files changed, 169 insertions(+), 219 deletions(-) delete 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 e38964133..a41ade7c9 100644 --- a/Source/portable/GCC/RX600/port.c +++ b/Source/portable/GCC/RX600/port.c @@ -86,20 +86,19 @@ which would require the old IPL to be read first and stored in a local variable. * Function to start the first task executing - written in asm code as direct * access to registers is required. */ -extern void prvStartFirstTask( void ); +static void prvStartFirstTask( void ) __attribute__((naked)); /* * Software interrupt handler. Performs the actual context switch (saving and * restoring of registers). Written in asm code as direct register access is * required. */ -static void prvYieldHandler( void ); +void vSoftwareInterruptISR( void ) __attribute__((naked)); /* - * The tick ISR handler. The peripheral used is configured by the application - * via a hook/callback function. + * The tick interrupt handler. */ -void vTickISR( void ) __attribute__((interrupt)); +void vTickISR( void ) __attribute__((naked)); /*-----------------------------------------------------------*/ @@ -203,10 +202,143 @@ extern void vApplicationSetupTimerInterrupt( void ); } /*-----------------------------------------------------------*/ +void vPortEndScheduler( void ) +{ + /* Not implemented as there is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +static void prvStartFirstTask( void ) +{ + __asm volatile + ( + /* 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 vSoftwareInterruptISR( void ) +{ + __asm volatile + ( + /* Re-enable interrupts. */ + "SETPSW I \n" \ + + /* 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 \n" \ + + /* Read the user stack pointer. */ + "MVFC USP, R15 \n" \ + + /* Move the address down to the data being moved. */ + "SUB #12, R15 \n" \ + "MVTC R15, USP \n" \ + + /* Copy the data across, R15, then PC, then PSW. */ + "MOV.L [ R0 ], [ R15 ] \n" \ + "MOV.L 4[ R0 ], 4[ R15 ] \n" \ + "MOV.L 8[ R0 ], 8[ R15 ] \n" \ + + /* Move the interrupt stack pointer to its new correct position. */ + "ADD #12, R0 \n" \ + + /* All the rest of the registers are saved directly to the user stack. */ + "SETPSW U \n" \ + + /* Save the rest of the general registers (R15 has been saved already). */ + "PUSHM R1-R14 \n" \ + + /* Save the FPSW and accumulator. */ + "MVFC FPSW, R15 \n" \ + "PUSH.L R15 \n" \ + "MVFACHI R15 \n" \ + "PUSH.L R15 \n" \ + + /* Middle word. */ + "MVFACMI R15 \n" \ + + /* Shifted left as it is restored to the low order word. */ + "SHLL #16, R15 \n" \ + "PUSH.L R15 \n" \ + + /* Save the stack pointer to the TCB. */ + "MOV.L #_pxCurrentTCB, R15 \n" \ + "MOV.L [ R15 ], R15 \n" \ + "MOV.L R0, [ R15 ] \n" \ + + /* Ensure the interrupt mask is set to the syscall priority while the kernel + structures are being accessed. */ + "MVTIPL %0 \n" \ + + /* Select the next task to run. */ + "BSR.A _vTaskSwitchContext \n" \ + + /* Reset the interrupt mask as no more data structure access is required. */ + "MVTIPL %1 \n" \ + + /* Load the stack pointer of the task that is now selected as the Running + state task from its TCB. */ + "MOV.L #_pxCurrentTCB,R15 \n" \ + "MOV.L [ R15 ], R15 \n" \ + "MOV.L [ R15 ], R0 \n" \ + + /* Restore the context of the new task. The PSW (Program Status Word) and + PC will be popped by the RTE instruction. */ + "POP R15 \n" \ + "MVTACLO R15 \n" \ + "POP R15 \n" \ + "MVTACHI R15 \n" \ + "POP R15 \n" \ + "MVTC R15, FPSW \n" \ + "POPM R1-R15 \n" \ + "RTE \n" \ + "NOP \n" \ + "NOP " + :: "i"(configMAX_SYSCALL_INTERRUPT_PRIORITY), "i"(configKERNEL_INTERRUPT_PRIORITY) + ); +} +/*-----------------------------------------------------------*/ + void vTickISR( void ) { - /* Re-enable interrupts. */ - __asm volatile( "SETPSW I" ); + /* This is a naked function. This macro saves registers then re-enables + interrupts. */ + portENTER_INTERRUPT(); /* Increment the tick, and perform any processing the new tick value necessitates. Ensure IPL is at the max syscall value first. */ @@ -220,14 +352,34 @@ void vTickISR( void ) #if( configUSE_PREEMPTION == 1 ) taskYIELD(); #endif + + /* Retore registers, then return. */ + portEXIT_INTERRUPT(); } /*-----------------------------------------------------------*/ -void vPortEndScheduler( void ) +unsigned long ulPortGetIPL( void ) { - /* Not implemented as there is nothing to return to. */ + __asm volatile + ( + "MVFC PSW, R1 \n" \ + "SHLR #24, R1 \n" \ + "RTS " + ); } /*-----------------------------------------------------------*/ - - +void vPortSetIPL( unsigned long ulNewIPL ) +{ + __asm volatile + ( + "PUSH R5 \n" \ + "MVFC PSW, R5 \n" \ + "SHLL #24, R1 \n" \ + "AND #-0F000001H, R5 \n" \ + "OR R1, R5 \n" \ + "MVTC R5, PSW \n" \ + "POP R5 \n" \ + "RTS " + ); +} diff --git a/Source/portable/GCC/RX600/port_asm.asm b/Source/portable/GCC/RX600/port_asm.asm deleted file mode 100644 index 8351a5971..000000000 --- a/Source/portable/GCC/RX600/port_asm.asm +++ /dev/null @@ -1,206 +0,0 @@ -/* - 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 91223530c..e20383188 100644 --- a/Source/portable/GCC/RX600/portmacro.h +++ b/Source/portable/GCC/RX600/portmacro.h @@ -117,11 +117,15 @@ extern void vTaskExitCritical( void ); #define portEXIT_CRITICAL() vTaskExitCritical(); /* As this port allows interrupt nesting... */ -unsigned long ulPortGetIPL( void ); -void vPortSetIPL( unsigned long ulNewIPL ); +unsigned long ulPortGetIPL( void ) __attribute__((naked)); +void vPortSetIPL( unsigned long ulNewIPL ) __attribute__((naked)); #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortGetIPL(); portDISABLE_INTERRUPTS() #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) vPortSetIPL( uxSavedInterruptStatus ) +#define portENTER_INTERRUPT() __asm volatile( "PUSHM R1-R15 \t\n SETPSW I" ) +#define portEXIT_INTERRUPT() __asm volatile( "POPM R1-R15 \t\n RTE" ) + + /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -- 2.39.5