From f6b9fba68d7545b2ac9992676f3e0dc51c145520 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Thu, 6 Aug 2009 18:23:40 +0000 Subject: [PATCH] Added new Nios2 port layer. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@827 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/GCC/Nios2/port.c | 225 ++++++++++++++++++++++++++ Source/portable/GCC/Nios2/port_asm.S | 169 +++++++++++++++++++ Source/portable/GCC/Nios2/portmacro.h | 121 ++++++++++++++ 3 files changed, 515 insertions(+) create mode 100644 Source/portable/GCC/Nios2/port.c create mode 100644 Source/portable/GCC/Nios2/port_asm.S create mode 100644 Source/portable/GCC/Nios2/portmacro.h diff --git a/Source/portable/GCC/Nios2/port.c b/Source/portable/GCC/Nios2/port.c new file mode 100644 index 000000000..db64ba9d9 --- /dev/null +++ b/Source/portable/GCC/Nios2/port.c @@ -0,0 +1,225 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + 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. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + 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 along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + 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. +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the NIOS2 port. + *----------------------------------------------------------*/ + +/* Standard Includes. */ +#include +#include + +/* Altera includes. */ +#include "sys/alt_irq.h" +#include "altera_avalon_timer_regs.h" +#include "priv/alt_irq_table.h" + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Interrupts are enabled. */ +#define portINITIAL_ESTATUS ( portSTACK_TYPE ) 0x01 + +/*-----------------------------------------------------------*/ + +/* + * Setup the timer to generate the tick interrupts. + */ +static void prvSetupTimerInterrupt( void ); + +/* + * Call back for the alarm function. + */ +void vPortSysTickHandler( void * context, alt_u32 id ); + +/*-----------------------------------------------------------*/ + +void prvReadGp( unsigned portLONG *ulValue ) +{ + asm( "stw gp, (r4) " ); +}; +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ +portSTACK_TYPE *pxFramePointer = pxTopOfStack - 1; +portSTACK_TYPE xGlobalPointer; + + prvReadGp( &xGlobalPointer ); + + /* End of stack marker. */ + *pxTopOfStack = 0xdeadbeef; + pxTopOfStack--; + + *pxTopOfStack = ( portSTACK_TYPE ) pxFramePointer; + pxTopOfStack--; + + *pxTopOfStack = xGlobalPointer; + + /* Space for R23 to R16. */ + pxTopOfStack -= 9; + + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_ESTATUS; + + /* Space for R15 to R5. */ + pxTopOfStack -= 12; + + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; + + /* Space for R3 to R1, muldiv and RA. */ + pxTopOfStack -= 5; + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); + + /* Start the first task. */ + asm volatile ( " movia r2, restore_sp_from_pxCurrentTCB \n" + " jmp r2 " ); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the NIOS2 port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +void prvSetupTimerInterrupt( void ) +{ + /* Try to register the interrupt handler. */ + if ( -EINVAL == alt_irq_register( SYS_CLK_IRQ, 0x0, vPortSysTickHandler ) ) + { + /* Failed to install the Interrupt Handler. */ + asm( "break" ); + } + else + { + /* Configure SysTick to interrupt at the requested rate. */ + IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK ); + IOWR_ALTERA_AVALON_TIMER_PERIODL( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) & 0xFFFF ); + IOWR_ALTERA_AVALON_TIMER_PERIODH( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) >> 16 ); + IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK | ALTERA_AVALON_TIMER_CONTROL_ITO_MSK ); + } + + /* Clear any already pending interrupts generated by the Timer. */ + IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK ); +} +/*-----------------------------------------------------------*/ + +void vPortSysTickHandler( void * context, alt_u32 id ) +{ + /* Increment the Kernel Tick. */ + vTaskIncrementTick(); + + /* If using preemption, also force a context switch. */ + #if configUSE_PREEMPTION == 1 + vTaskSwitchContext(); + #endif + + /* Clear the interrupt. */ + IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK ); +} +/*-----------------------------------------------------------*/ + +/** This function is a re-implementation of the Altera provided function. + * The function is re-implemented to prevent it from enabling an interrupt + * when it is registered. Interrupts should only be enabled after the FreeRTOS.org + * kernel has its scheduler started so that contexts are saved and switched + * correctly. + */ +int alt_irq_register( alt_u32 id, void* context, void (*handler)(void*, alt_u32) ) +{ + int rc = -EINVAL; + alt_irq_context status; + + if (id < ALT_NIRQ) + { + /* + * interrupts are disabled while the handler tables are updated to ensure + * that an interrupt doesn't occur while the tables are in an inconsistant + * state. + */ + + status = alt_irq_disable_all (); + + alt_irq[id].handler = handler; + alt_irq[id].context = context; + + rc = (handler) ? alt_irq_enable (id): alt_irq_disable (id); + + /* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */ + } + + return rc; +} +/*-----------------------------------------------------------*/ + diff --git a/Source/portable/GCC/Nios2/port_asm.S b/Source/portable/GCC/Nios2/port_asm.S new file mode 100644 index 000000000..a47870f7f --- /dev/null +++ b/Source/portable/GCC/Nios2/port_asm.S @@ -0,0 +1,169 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + 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. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + 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 along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + 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. +*/ + +.extern vTaskSwitchContext + +.set noat + +# Exported to start the first task. +.globl restore_sp_from_pxCurrentTCB + +# Entry point for exceptions. +.section .exceptions.entry, "xa" + +# Save the entire context of a task. +save_context: + addi ea, ea, -4 # Point to the next instruction. + addi sp, sp, -116 # Create space on the stack. + stw ra, 0(sp) + # Leave a gap for muldiv 0 + stw at, 8(sp) + stw r2, 12(sp) + stw r3, 16(sp) + stw r4, 20(sp) + stw r5, 24(sp) + stw r6, 28(sp) + stw r7, 32(sp) + stw r8, 36(sp) + stw r9, 40(sp) + stw r10, 44(sp) + stw r11, 48(sp) + stw r12, 52(sp) + stw r13, 56(sp) + stw r14, 60(sp) + stw r15, 64(sp) + rdctl r5, estatus # Save the eStatus + stw r5, 68(sp) + stw ea, 72(sp) # Save the PC + stw r16, 76(sp) # Save the remaining registers + stw r17, 80(sp) + stw r18, 84(sp) + stw r19, 88(sp) + stw r20, 92(sp) + stw r21, 96(sp) + stw r22, 100(sp) + stw r23, 104(sp) + stw gp, 108(sp) + stw fp, 112(sp) + +save_sp_to_pxCurrentTCB: + movia et, pxCurrentTCB # Load the address of the pxCurrentTCB pointer + ldw et, (et) # Load the value of the pxCurrentTCB pointer + stw sp, (et) # Store the stack pointer into the top of the TCB + + .section .exceptions.irqtest, "xa" +hw_irq_test: + /* + * Test to see if the exception was a software exception or caused + * by an external interrupt, and vector accordingly. + */ + rdctl r4, ipending # Load the Pending Interrupts indication + rdctl r5, estatus # Load the eStatus (enabled interrupts). + andi r2, r5, 1 # Are interrupts enabled globally. + beq r2, zero, soft_exceptions # Interrupts are not enabled. + beq r4, zero, soft_exceptions # There are no interrupts triggered. + + .section .exceptions.irqhandler, "xa" +hw_irq_handler: + call alt_irq_handler # Call the alt_irq_handler to deliver to the registered interrupt handler. + + .section .exceptions.irqreturn, "xa" +restore_sp_from_pxCurrentTCB: + movia et, pxCurrentTCB # Load the address of the pxCurrentTCB pointer + ldw et, (et) # Load the value of the pxCurrentTCB pointer + ldw sp, (et) # Load the stack pointer with the top value of the TCB + +restore_context: + ldw ra, 0(sp) # Restore the registers. + # Leave a gap for muldiv 0. + ldw at, 8(sp) + ldw r2, 12(sp) + ldw r3, 16(sp) + ldw r4, 20(sp) + ldw r5, 24(sp) + ldw r6, 28(sp) + ldw r7, 32(sp) + ldw r8, 36(sp) + ldw r9, 40(sp) + ldw r10, 44(sp) + ldw r11, 48(sp) + ldw r12, 52(sp) + ldw r13, 56(sp) + ldw r14, 60(sp) + ldw r15, 64(sp) + ldw et, 68(sp) # Load the eStatus + wrctl estatus, et # Write the eStatus + ldw ea, 72(sp) # Load the Program Counter + ldw r16, 76(sp) + ldw r17, 80(sp) + ldw r18, 84(sp) + ldw r19, 88(sp) + ldw r20, 92(sp) + ldw r21, 96(sp) + ldw r22, 100(sp) + ldw r23, 104(sp) + ldw gp, 108(sp) + ldw fp, 112(sp) + addi sp, sp, 116 # Release stack space + + eret # Return to address ea, loading eStatus into Status. + + .section .exceptions.soft, "xa" +soft_exceptions: + ldw et, 0(ea) # Load the instruction where the interrupt occured. + movhi at, %hi(0x003B683A) # Load the registers with the trap instruction code + ori at, at, %lo(0x003B683A) + cmpne et, et, at # Compare the trap instruction code to the last excuted instruction + beq et, r0, call_scheduler # its a trap so switchcontext + break # This is an un-implemented instruction or muldiv problem. + br restore_context # its something else + +call_scheduler: + addi ea, ea, 4 # A trap was called, increment the program counter so it is not called again. + stw ea, 72(sp) # Save the new program counter to the context. + call vTaskSwitchContext # Pick the next context. + br restore_sp_from_pxCurrentTCB # Switch in the task context and restore. diff --git a/Source/portable/GCC/Nios2/portmacro.h b/Source/portable/GCC/Nios2/portmacro.h new file mode 100644 index 000000000..3661f6d0b --- /dev/null +++ b/Source/portable/GCC/Nios2/portmacro.h @@ -0,0 +1,121 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + 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. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + 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 along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + 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. +*/ + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/alt_irq.h" + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE unsigned portLONG +#define portBASE_TYPE long + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef unsigned portSHORT portTickType; + #define portMAX_DELAY ( portTickType ) 0xffff +#else + typedef unsigned portLONG portTickType; + #define portMAX_DELAY ( portTickType ) 0xffffffff +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 4 +#define portNOP() asm volatile ( "NOP" ) +#define portCRITICAL_NESTING_IN_TCB 1 +/*-----------------------------------------------------------*/ + +extern void vTaskSwitchContext( void ); +#define portYIELD() asm volatile ( "trap" ); +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext() + + +/* Include the port_asm.S file where the Context saving/restoring is defined. */ +__asm__( "\n\t.globl save_context" ); + +/*-----------------------------------------------------------*/ + +extern void vTaskEnterCritical( void ); +extern void vTaskExitCritical( void ); + +#define portDISABLE_INTERRUPTS() alt_irq_disable_all() +#define portENABLE_INTERRUPTS() alt_irq_enable_all( 0x01 ); +#define portENTER_CRITICAL() vTaskEnterCritical() +#define portEXIT_CRITICAL() vTaskExitCritical() +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + -- 2.39.2