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