]> begriffs open source - freertos/blob - portable/ThirdParty/xClang/XCORE200/port.c
Change XCC to xClang for XCore ports (#332)
[freertos] / portable / ThirdParty / xClang / XCORE200 / port.c
1 // Copyright (c) 2019, XMOS Ltd, All rights reserved
2
3 /* Scheduler includes. */
4 #include "FreeRTOS.h"
5 #include "task.h"
6 #include <xs1.h>
7 #include <xcore/hwtimer.h>
8 #include <xcore/triggerable.h>
9
10 static hwtimer_t xKernelTimer;
11
12 uint32_t ulPortYieldRequired[ portMAX_CORE_COUNT ] = { pdFALSE };
13
14 /*-----------------------------------------------------------*/
15
16 void vIntercoreInterruptISR( void )
17 {
18         int xCoreID;
19
20 //      debug_printf( "In KCALL: %u\n", ulData );
21         xCoreID = rtos_core_id_get();
22         ulPortYieldRequired[ xCoreID ] = pdTRUE;
23 }
24 /*-----------------------------------------------------------*/
25
26 DEFINE_RTOS_INTERRUPT_CALLBACK( pxKernelTimerISR, pvData )
27 {
28         uint32_t ulLastTrigger;
29         uint32_t ulNow;
30         int xCoreID;
31
32         xCoreID = 0;
33
34         configASSERT( xCoreID == rtos_core_id_get() );
35
36         /* Need the next interrupt to be scheduled relative to
37          * the current trigger time, rather than the current
38          * time. */
39         ulLastTrigger = hwtimer_get_trigger_time( xKernelTimer );
40
41         /* Check to see if the ISR is late. If it is, we don't
42          * want to schedule the next interrupt to be in the past. */
43         ulNow = hwtimer_get_time( xKernelTimer );
44         if( ulNow - ulLastTrigger >= configCPU_CLOCK_HZ / configTICK_RATE_HZ )
45         {
46                 ulLastTrigger = ulNow;
47         }
48
49         ulLastTrigger += configCPU_CLOCK_HZ / configTICK_RATE_HZ;
50         hwtimer_change_trigger_time( xKernelTimer, ulLastTrigger );
51
52 #if configUPDATE_RTOS_TIME_FROM_TICK_ISR == 1
53         rtos_time_increment( RTOS_TICK_PERIOD( configTICK_RATE_HZ ) );
54 #endif
55
56         if( xTaskIncrementTick() != pdFALSE )
57         {
58                 ulPortYieldRequired[ xCoreID ] = pdTRUE;
59         }
60 }
61 /*-----------------------------------------------------------*/
62
63 void vPortYieldOtherCore( int xOtherCoreID )
64 {
65         int xCoreID;
66
67         /*
68          * This function must be called from within a critical section.
69          */
70
71         xCoreID = rtos_core_id_get();
72
73 //      debug_printf("%d->%d\n", xCoreID, xOtherCoreID);
74
75 //      debug_printf("Yield core %d from %d\n", xOtherCoreID, xCoreID );
76
77         rtos_irq( xOtherCoreID, xCoreID );
78 }
79 /*-----------------------------------------------------------*/
80
81 static int prvCoreInit( void )
82 {
83         int xCoreID;
84
85         xCoreID = rtos_core_register();
86         debug_printf( "Logical Core %d initializing as FreeRTOS Core %d\n", get_logical_core_id(), xCoreID );
87
88         asm volatile (
89                         "ldap r11, kexcept\n\t"
90                         "set kep, r11\n\t"
91                         :
92                         :
93                         : "r11"
94         );
95
96         rtos_irq_enable( configNUM_CORES );
97
98         /*
99          * All threads wait here until all have enabled IRQs
100          */
101         while( rtos_irq_ready() == pdFALSE );
102
103         if( xCoreID == 0 )
104         {
105                 uint32_t ulNow;
106                 ulNow = hwtimer_get_time( xKernelTimer );
107 //              debug_printf( "The time is now (%u)\n", ulNow );
108
109                 ulNow += configCPU_CLOCK_HZ / configTICK_RATE_HZ;
110
111                 triggerable_setup_interrupt_callback( xKernelTimer, NULL, RTOS_INTERRUPT_CALLBACK( pxKernelTimerISR ) );
112                 hwtimer_set_trigger_time( xKernelTimer, ulNow );
113                 triggerable_enable_trigger( xKernelTimer );
114         }
115
116         return xCoreID;
117 }
118 /*-----------------------------------------------------------*/
119
120 DEFINE_RTOS_KERNEL_ENTRY( void, vPortStartSchedulerOnCore, void )
121 {
122         int xCoreID;
123
124         xCoreID = prvCoreInit();
125
126         debug_printf( "FreeRTOS Core %d initialized\n", xCoreID );
127
128         /*
129          * Restore the context of the first thread
130          * to run and jump into it.
131          */
132         asm volatile (
133                         "mov r6, %0\n\t" /* R6 must be the FreeRTOS core ID*/
134                         "ldaw r5, dp[pxCurrentTCBs]\n\t" /* R5 must be the TCB list which is indexed by R6 */
135                         "bu _freertos_restore_ctx\n\t"
136                         : /* no outputs */
137                         : "r"(xCoreID)
138                         : "r5", "r6"
139         );
140 }
141 /*-----------------------------------------------------------*/
142
143 /*-----------------------------------------------------------*/
144 /* Public functions required by all ports below:             */
145 /*-----------------------------------------------------------*/
146
147 /*
148  * See header file for description.
149  */
150 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
151 {
152         //debug_printf( "Top of stack was %p for task %p\n", pxTopOfStack, pxCode );
153         /*
154          * Grow the thread's stack by portTHREAD_CONTEXT_STACK_GROWTH
155          * so we can push the context onto it.
156          */
157         pxTopOfStack -= portTHREAD_CONTEXT_STACK_GROWTH;
158
159         uint32_t dp;
160         uint32_t cp;
161
162         /*
163          * We need to get the current CP and DP pointers.
164          */
165         asm volatile (
166                         "ldaw r11, cp[0]\n\t" /* get CP into R11 */
167                         "mov %0, r11\n\t" /* get R11 (CP) into cp */
168                         "ldaw r11, dp[0]\n\t" /* get DP into R11 */
169                         "mov %1, r11\n\t" /* get R11 (DP) into dp */
170                         : "=r"(cp), "=r"(dp) /* output 0 is cp, output 1 is dp */
171                         : /* there are no inputs */
172                         : "r11" /* R11 gets clobbered */
173         );
174
175         /*
176          * Push the thread context onto the stack.
177          * Saved PC will point to the new thread's
178          * entry pointer.
179          * Interrupts will default to enabled.
180          * KEDI is also set to enable dual issue mode
181          * upon kernel entry.
182          */
183         pxTopOfStack[ 1 ] = ( StackType_t ) pxCode;       /* SP[1]  := SPC */
184     pxTopOfStack[ 2 ] = XS1_SR_IEBLE_MASK
185                       | XS1_SR_KEDI_MASK;             /* SP[2]  := SSR */
186         pxTopOfStack[ 3 ] = 0x00000000;                   /* SP[3]  := SED */
187         pxTopOfStack[ 4 ] = 0x00000000;                   /* SP[4]  := ET */
188         pxTopOfStack[ 5 ] = dp;                           /* SP[5]  := DP */
189         pxTopOfStack[ 6 ] = cp;                           /* SP[6]  := CP */
190         pxTopOfStack[ 7 ] = 0x00000000;                   /* SP[7]  := LR */
191         pxTopOfStack[ 8 ] = ( StackType_t ) pvParameters; /* SP[8]  := R0 */
192         pxTopOfStack[ 9 ] = 0x01010101;                   /* SP[9]  := R1 */
193         pxTopOfStack[ 10 ] = 0x02020202;                  /* SP[10] := R2 */
194         pxTopOfStack[ 11 ] = 0x03030303;                  /* SP[11] := R3 */
195         pxTopOfStack[ 12 ] = 0x04040404;                  /* SP[12] := R4 */
196         pxTopOfStack[ 13 ] = 0x05050505;                  /* SP[13] := R5 */
197         pxTopOfStack[ 14 ] = 0x06060606;                  /* SP[14] := R6 */
198         pxTopOfStack[ 15 ] = 0x07070707;                  /* SP[15] := R7 */
199         pxTopOfStack[ 16 ] = 0x08080808;                  /* SP[16] := R8 */
200         pxTopOfStack[ 17 ] = 0x09090909;                  /* SP[17] := R9 */
201         pxTopOfStack[ 18 ] = 0x10101010;                  /* SP[18] := R10 */
202         pxTopOfStack[ 19 ] = 0x11111111;                  /* SP[19] := R11 */
203
204         //debug_printf( "Top of stack is now %p for task %p\n", pxTopOfStack, pxCode );
205
206         /*
207          * Returns the new top of the stack
208          */
209         return pxTopOfStack;
210 }
211 /*-----------------------------------------------------------*/
212
213 void vPortStartSMPScheduler( void );
214
215 /*
216  * See header file for description.
217  */
218 BaseType_t xPortStartScheduler( void )
219 {
220         if( ( configNUM_CORES > portMAX_CORE_COUNT ) || ( configNUM_CORES <= 0 ) )
221         {
222                 return pdFAIL;
223         }
224
225         rtos_locks_initialize();
226         xKernelTimer = hwtimer_alloc();
227
228         vPortStartSMPScheduler();
229
230         return pdPASS;
231 }
232 /*-----------------------------------------------------------*/
233
234 void vPortEndScheduler( void )
235 {
236         /* Do not implement. */
237 }
238 /*-----------------------------------------------------------*/