]> begriffs open source - cmsis-freertos/blob - Source/portable/GCC/NiosII/port.c
Updated pack to FreeRTOS 10.3.1
[cmsis-freertos] / Source / portable / GCC / NiosII / port.c
1 /*
2  * FreeRTOS Kernel V10.3.1
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /*-----------------------------------------------------------
29  * Implementation of functions defined in portable.h for the NIOS2 port.
30  *----------------------------------------------------------*/
31
32 /* Standard Includes. */
33 #include <string.h>
34 #include <errno.h>
35
36 /* Altera includes. */
37 #include "sys/alt_irq.h"
38 #include "altera_avalon_timer_regs.h"
39 #include "priv/alt_irq_table.h"
40
41 /* Scheduler includes. */
42 #include "FreeRTOS.h"
43 #include "task.h"
44
45 /* Interrupts are enabled. */
46 #define portINITIAL_ESTATUS     ( StackType_t ) 0x01 
47
48 /*-----------------------------------------------------------*/
49
50 /* 
51  * Setup the timer to generate the tick interrupts.
52  */
53 static void prvSetupTimerInterrupt( void );
54
55 /*
56  * Call back for the alarm function.
57  */
58 void vPortSysTickHandler( void * context, alt_u32 id );
59
60 /*-----------------------------------------------------------*/
61
62 static void prvReadGp( uint32_t *ulValue )
63 {
64         asm( "stw gp, (%0)" :: "r"(ulValue) );
65 }
66 /*-----------------------------------------------------------*/
67
68 /* 
69  * See header file for description. 
70  */
71 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
72 {    
73 StackType_t *pxFramePointer = pxTopOfStack - 1;
74 StackType_t xGlobalPointer;
75
76     prvReadGp( &xGlobalPointer ); 
77
78     /* End of stack marker. */
79     *pxTopOfStack = 0xdeadbeef;
80     pxTopOfStack--;
81     
82     *pxTopOfStack = ( StackType_t ) pxFramePointer; 
83     pxTopOfStack--;
84     
85     *pxTopOfStack = xGlobalPointer; 
86     
87     /* Space for R23 to R16. */
88     pxTopOfStack -= 9;
89
90     *pxTopOfStack = ( StackType_t ) pxCode; 
91     pxTopOfStack--;
92
93     *pxTopOfStack = portINITIAL_ESTATUS; 
94
95     /* Space for R15 to R5. */    
96     pxTopOfStack -= 12;
97     
98     *pxTopOfStack = ( StackType_t ) pvParameters; 
99
100     /* Space for R3 to R1, muldiv and RA. */
101     pxTopOfStack -= 5;
102     
103     return pxTopOfStack;
104 }
105 /*-----------------------------------------------------------*/
106
107 /* 
108  * See header file for description. 
109  */
110 BaseType_t xPortStartScheduler( void )
111 {
112         /* Start the timer that generates the tick ISR.  Interrupts are disabled
113         here already. */
114         prvSetupTimerInterrupt();
115         
116         /* Start the first task. */
117     asm volatile (  " movia r2, restore_sp_from_pxCurrentTCB        \n"
118                     " jmp r2                                          " );
119
120         /* Should not get here! */
121         return 0;
122 }
123 /*-----------------------------------------------------------*/
124
125 void vPortEndScheduler( void )
126 {
127         /* It is unlikely that the NIOS2 port will require this function as there
128         is nothing to return to.  */
129 }
130 /*-----------------------------------------------------------*/
131
132 /*
133  * Setup the systick timer to generate the tick interrupts at the required
134  * frequency.
135  */
136 void prvSetupTimerInterrupt( void )
137 {
138         /* Try to register the interrupt handler. */
139         if ( -EINVAL == alt_irq_register( SYS_CLK_IRQ, 0x0, vPortSysTickHandler ) )
140         { 
141                 /* Failed to install the Interrupt Handler. */
142                 asm( "break" );
143         }
144         else
145         {
146                 /* Configure SysTick to interrupt at the requested rate. */
147                 IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK );
148                 IOWR_ALTERA_AVALON_TIMER_PERIODL( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) & 0xFFFF );
149                 IOWR_ALTERA_AVALON_TIMER_PERIODH( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) >> 16 );
150                 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 );   
151         } 
152
153         /* Clear any already pending interrupts generated by the Timer. */
154         IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
155 }
156 /*-----------------------------------------------------------*/
157
158 void vPortSysTickHandler( void * context, alt_u32 id )
159 {
160         /* Increment the kernel tick. */
161         if( xTaskIncrementTick() != pdFALSE )
162         {
163         vTaskSwitchContext();
164         }
165                 
166         /* Clear the interrupt. */
167         IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
168 }
169 /*-----------------------------------------------------------*/
170
171 /** This function is a re-implementation of the Altera provided function.
172  * The function is re-implemented to prevent it from enabling an interrupt
173  * when it is registered. Interrupts should only be enabled after the FreeRTOS.org
174  * kernel has its scheduler started so that contexts are saved and switched 
175  * correctly.
176  */
177 int alt_irq_register( alt_u32 id, void* context, void (*handler)(void*, alt_u32) )
178 {
179         int rc = -EINVAL;  
180         alt_irq_context status;
181
182         if (id < ALT_NIRQ)
183         {
184                 /* 
185                  * interrupts are disabled while the handler tables are updated to ensure
186                  * that an interrupt doesn't occur while the tables are in an inconsistent
187                  * state.
188                  */
189         
190                 status = alt_irq_disable_all ();
191         
192                 alt_irq[id].handler = handler;
193                 alt_irq[id].context = context;
194         
195                 rc = (handler) ? alt_irq_enable (id): alt_irq_disable (id);
196         
197                 /* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */
198         }
199     
200         return rc; 
201 }
202 /*-----------------------------------------------------------*/
203