Skip to content

Commit a286632

Browse files
authored
Add first version of XCOREAI port (#63)
* xTaskIncrementTick need to be called in critical section * Rename configNUM_CORES to configNUMBER_OF_CORES * Define portENTER/EXIT_CRITICAL_FROM_ISR for SMP * portSET/CLEAR_INTERRUPT_MASK_FROM_ISR is not used in SMP
1 parent 8c067d6 commit a286632

File tree

5 files changed

+777
-0
lines changed

5 files changed

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

0 commit comments

Comments
 (0)