]> begriffs open source - freertos/blob - portable/ThirdParty/GCC/ARC_v1/port.c
Add SMP in the License Header (#402)
[freertos] / portable / ThirdParty / GCC / ARC_v1 / port.c
1 /*
2  * FreeRTOS SMP Kernel V202110.00
3  * Copyright (C) 2020 Synopsys, 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  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /*
29  * Implementation of functions defined in portable.h
30  */
31
32 #include "FreeRTOS.h"
33 #include "task.h"
34 #include "FreeRTOSConfig.h"
35
36 #include "arc/arc_exception.h"
37 #include "arc/arc_timer.h"
38 #include "board.h"
39
40 #include "arc_freertos_exceptions.h"
41
42 volatile unsigned int ulCriticalNesting = 999UL;
43 volatile unsigned int context_switch_reqflg; /* task context switch request flag in exceptions and interrupts handling */
44
45 /**
46  * \var exc_nest_count
47  * \brief the counter for exc/int processing, =0 no int/exc
48  * >1 in int/exc processing
49  * @}
50  */
51 uint32_t exc_nest_count;
52 /* --------------------------------------------------------------------------*/
53
54 /**
55  * @brief kernel tick interrupt handler of freertos
56  */
57 /* ----------------------------------------------------------------------------*/
58 static void vKernelTick( void * ptr )
59 {
60     /* clear timer interrupt */
61     arc_timer_int_clear( BOARD_OS_TIMER_ID );
62     board_timer_update( configTICK_RATE_HZ );
63
64     if( xTaskIncrementTick() )
65     {
66         portYIELD_FROM_ISR(); /* need to make task switch */
67     }
68 }
69
70 /* --------------------------------------------------------------------------*/
71
72 /**
73  * @brief  setup freertos kernel tick
74  */
75 /* ----------------------------------------------------------------------------*/
76 static void prvSetupTimerInterrupt( void )
77 {
78     unsigned int cyc = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
79
80     int_disable( BOARD_OS_TIMER_INTNO ); /* disable os timer interrupt */
81     arc_timer_stop( BOARD_OS_TIMER_ID );
82     arc_timer_start( BOARD_OS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc );
83
84     int_handler_install( BOARD_OS_TIMER_INTNO, ( INT_HANDLER_T ) vKernelTick );
85     int_pri_set( BOARD_OS_TIMER_INTNO, INT_PRI_MIN );
86     int_enable( BOARD_OS_TIMER_INTNO );
87 }
88
89 /*
90  * Setup the stack of a new task so it is ready to be placed under the
91  * scheduler control.  The registers have to be placed on the stack in
92  * the order that the port expects to find them.
93  *
94  * For ARC, task context switch is implemented with the help of SWI exception
95  * It's not efficient but simple.
96  *
97  */
98 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
99                                      TaskFunction_t pxCode,
100                                      void * pvParameters )
101 {
102     /* To ensure asserts in tasks.c don't fail, although in this case the assert
103      * is not really required. */
104     pxTopOfStack--;
105
106     /* Setup the initial stack of the task.  The stack is set exactly as
107      * expected by the portRESTORE_CONTEXT() macro. */
108
109     /* When the task starts is will expect to find the function parameter in
110      * R0. */
111     *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
112
113     pxTopOfStack--;
114     *pxTopOfStack = ( StackType_t ) pxCode; /* function body */
115
116     /* PC */
117     pxTopOfStack--;
118     *pxTopOfStack = ( StackType_t ) start_r; /* dispatch return address */
119
120     pxTopOfStack--;
121     *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_NESTING;
122     return pxTopOfStack;
123 }
124
125 /* --------------------------------------------------------------------------*/
126
127 /**
128  * @brief  start the freertos scheduler, go to the first task
129  *
130  * @returns
131  */
132 /* ----------------------------------------------------------------------------*/
133 BaseType_t xPortStartScheduler( void )
134 {
135     /* Start the timer that generates the tick ISR. */
136     prvSetupTimerInterrupt();
137     start_dispatch();
138
139     /* Should not get here! */
140     return 0;
141 }
142
143 /* --------------------------------------------------------------------------*/
144
145 /**
146  * @brief
147  */
148 /* ----------------------------------------------------------------------------*/
149 void vPortEndScheduler( void )
150 {
151 }
152
153 /* --------------------------------------------------------------------------*/
154
155 /**
156  * @brief  generate a task switch request in ISR
157  */
158 /* ----------------------------------------------------------------------------*/
159 void vPortYieldFromIsr( void )
160 {
161     unsigned int status32;
162
163     status32 = cpu_lock_save();
164     context_switch_reqflg = true;
165     cpu_unlock_restore( status32 );
166 }
167
168 /* --------------------------------------------------------------------------*/
169
170 /**
171  * @brief
172  */
173 /* ----------------------------------------------------------------------------*/
174 void vPortYield( void )
175 {
176     unsigned int status32;
177
178     status32 = cpu_lock_save();
179     dispatch();
180     cpu_unlock_restore( status32 );
181 }
182
183 /* --------------------------------------------------------------------------*/
184
185 /**
186  * @brief
187  */
188 /* ----------------------------------------------------------------------------*/
189 void vPortEndTask( void )
190 {
191     #if ( INCLUDE_vTaskDelete == 1 )
192         vTaskDelete( NULL ); /* Delete task itself */
193     #endif
194
195     while( 1 ) /* Yield to other task */
196     {
197         vPortYield();
198     }
199 }
200
201 #if ARC_FEATURE_STACK_CHECK
202
203 /*
204  * !!! Note !!!
205  * This a trick!!!
206  * It's a copy from task.c. We need to konw the definition of TCB for the purpose of hardware
207  * stack check. Pls don't forget to update it when FreeRTOS is updated.
208  */
209     typedef struct tskTaskControlBlock       /* The old naming convention is used to prevent breaking kernel aware debuggers. */
210     {
211         volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
212
213         #if ( portUSING_MPU_WRAPPERS == 1 )
214             xMPU_SETTINGS xMPUSettings;     /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
215         #endif
216
217         ListItem_t xStateListItem;                  /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
218         ListItem_t xEventListItem;                  /*< Used to reference a task from an event list. */
219         UBaseType_t uxPriority;                     /*< The priority of the task.  0 is the lowest priority. */
220         StackType_t * pxStack;                      /*< Points to the start of the stack. */
221         char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
222
223         #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
224             StackType_t * pxEndOfStack;     /*< Points to the highest valid address for the stack. */
225         #endif
226
227         #if ( portCRITICAL_NESTING_IN_TCB == 1 )
228             UBaseType_t uxCriticalNesting;  /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
229         #endif
230
231         #if ( configUSE_TRACE_FACILITY == 1 )
232             UBaseType_t uxTCBNumber;        /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
233             UBaseType_t uxTaskNumber;       /*< Stores a number specifically for use by third party trace code. */
234         #endif
235
236         #if ( configUSE_MUTEXES == 1 )
237             UBaseType_t uxBasePriority;     /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
238             UBaseType_t uxMutexesHeld;
239         #endif
240
241         #if ( configUSE_APPLICATION_TASK_TAG == 1 )
242             TaskHookFunction_t pxTaskTag;
243         #endif
244
245         #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
246             void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
247         #endif
248
249         #if ( configGENERATE_RUN_TIME_STATS == 1 )
250             uint32_t ulRunTimeCounter;      /*< Stores the amount of time the task has spent in the Running state. */
251         #endif
252
253         #if ( configUSE_NEWLIB_REENTRANT == 1 )
254
255             /* Allocate a Newlib reent structure that is specific to this task.
256              * Note Newlib support has been included by popular demand, but is not
257              * used by the FreeRTOS maintainers themselves.  FreeRTOS is not
258              * responsible for resulting newlib operation.  User must be familiar with
259              * newlib and must provide system-wide implementations of the necessary
260              * stubs. Be warned that (at the time of writing) the current newlib design
261              * implements a system-wide malloc() that must be provided with locks. */
262             struct  _reent xNewLib_reent;
263         #endif
264
265         #if ( configUSE_TASK_NOTIFICATIONS == 1 )
266             volatile uint32_t ulNotifiedValue;
267             volatile uint8_t ucNotifyState;
268         #endif
269
270         /* See the comments above the definition of
271          * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
272         #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
273             uint8_t ucStaticallyAllocated;                     /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
274         #endif
275
276         #if ( INCLUDE_xTaskAbortDelay == 1 )
277             uint8_t ucDelayAborted;
278         #endif
279
280         #if ( configUSE_POSIX_ERRNO == 1 )
281             int iTaskErrno;
282         #endif
283     } tskTCB;
284
285
286     void vPortSetStackCheck( TaskHandle_t old,
287                              TaskHandle_t new )
288     {
289         if( new != NULL )
290         {
291             arc_aux_write( AUX_USTACK_BASE, ( uint32_t ) ( new->pxEndOfStack ) );
292             arc_aux_write( AUX_USTACK_TOP, ( uint32_t ) ( new->pxStack ) );
293         }
294     }
295 #endif /* if ARC_FEATURE_STACK_CHECK */