mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/esp32c3_tls' into 'master'
freertos: add thread local storage support in RISC-V port Closes IDF-2125 See merge request espressif/esp-idf!12064
This commit is contained in:
commit
cc934ea0a1
@ -192,19 +192,30 @@ int vPortSetInterruptMask(void)
|
|||||||
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
|
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
|
||||||
{
|
{
|
||||||
extern uint32_t __global_pointer$;
|
extern uint32_t __global_pointer$;
|
||||||
|
uint8_t* task_thread_local_start;
|
||||||
|
uint8_t* threadptr;
|
||||||
|
extern char _thread_local_start, _thread_local_end, _rodata_start;
|
||||||
|
|
||||||
/* Simulate the stack frame as it would be created by a context switch
|
/* Byte pointer, so that subsequent calculations don't depend on sizeof(StackType_t). */
|
||||||
interrupt. */
|
uint8_t* sp = (uint8_t*) pxTopOfStack;
|
||||||
pxTopOfStack -= RV_STK_FRMSZ;
|
|
||||||
|
|
||||||
RvExcFrame *frame = (RvExcFrame *)pxTopOfStack;
|
/* Set up TLS area */
|
||||||
|
uint32_t thread_local_sz = (uint32_t) (&_thread_local_end - &_thread_local_start);
|
||||||
|
thread_local_sz = ALIGNUP(0x10, thread_local_sz);
|
||||||
|
sp -= thread_local_sz;
|
||||||
|
task_thread_local_start = sp;
|
||||||
|
memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz);
|
||||||
|
threadptr = task_thread_local_start - (&_thread_local_start - &_rodata_start);
|
||||||
|
|
||||||
|
/* Simulate the stack frame as it would be created by a context switch interrupt. */
|
||||||
|
sp -= RV_STK_FRMSZ;
|
||||||
|
RvExcFrame *frame = (RvExcFrame *)sp;
|
||||||
|
memset(frame, 0, sizeof(*frame));
|
||||||
frame->ra = (UBaseType_t)prvTaskExitError;
|
frame->ra = (UBaseType_t)prvTaskExitError;
|
||||||
frame->mepc = (UBaseType_t)pxCode;
|
frame->mepc = (UBaseType_t)pxCode;
|
||||||
frame->a0 = (UBaseType_t)pvParameters;
|
frame->a0 = (UBaseType_t)pvParameters;
|
||||||
frame->gp = (UBaseType_t)&__global_pointer$;
|
frame->gp = (UBaseType_t)&__global_pointer$;
|
||||||
frame->a1 = 0x11111111;
|
frame->tp = (UBaseType_t)threadptr;
|
||||||
frame->a2 = 0x22222222;
|
|
||||||
frame->a3 = 0x33333333;
|
|
||||||
|
|
||||||
//TODO: IDF-2393
|
//TODO: IDF-2393
|
||||||
return (StackType_t *)frame;
|
return (StackType_t *)frame;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <esp_types.h>
|
#include <esp_types.h>
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@ -11,7 +12,12 @@
|
|||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
|
#if defined(__XTENSA__)
|
||||||
|
#define GET_THREADPTR(tp_dest) do { asm volatile ("rur.threadptr %0":"=r"(tp_dest)); } while(0)
|
||||||
|
#elif defined (__riscv)
|
||||||
|
#define GET_THREADPTR(tp_dest) do { register uint32_t _tp asm("tp"); tp_dest = _tp; } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static __thread int tl_test_var1;
|
static __thread int tl_test_var1;
|
||||||
static __thread uint8_t tl_test_var2 = 55;
|
static __thread uint8_t tl_test_var2 = 55;
|
||||||
@ -27,17 +33,19 @@ static __thread struct test_tls_var {
|
|||||||
static void task_test_tls(void *arg)
|
static void task_test_tls(void *arg)
|
||||||
{
|
{
|
||||||
bool *running = (bool *)arg;
|
bool *running = (bool *)arg;
|
||||||
uint32_t tp = (uint32_t)-1;
|
uint32_t tp = (uint32_t) -1;
|
||||||
int test_var1_old = 0;
|
int test_var1_old = 0;
|
||||||
uint8_t test_var2_old = 0;
|
uint8_t test_var2_old = 0;
|
||||||
uint16_t test_var3_old = 0;
|
uint16_t test_var3_old = 0;
|
||||||
int f32_old = 0;
|
int f32_old = 0;
|
||||||
uint8_t f8_old = 0;
|
uint8_t f8_old = 0;
|
||||||
uint16_t f16_old = 0;
|
uint16_t f16_old = 0;
|
||||||
|
srand((int) xTaskGetCurrentTaskHandle());
|
||||||
|
int step = (rand() % 10) + 1;
|
||||||
|
|
||||||
asm volatile ("rur.threadptr %0":"=r"(tp));
|
GET_THREADPTR(tp);
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
printf("Task[%x]: var = 0x%x 0x%x\n", tp, tl_test_var1, tl_test_var2);
|
printf("Task[%x]: var = 0x%x 0x%x step=%d\n", tp, tl_test_var1, tl_test_var2, step);
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
TEST_ASSERT_EQUAL(0, tl_test_var1);
|
TEST_ASSERT_EQUAL(0, tl_test_var1);
|
||||||
TEST_ASSERT_EQUAL(55, tl_test_var2);
|
TEST_ASSERT_EQUAL(55, tl_test_var2);
|
||||||
@ -52,33 +60,34 @@ static void task_test_tls(void *arg)
|
|||||||
TEST_ASSERT_EQUAL(0, tl_test_struct_var.farr[k]);
|
TEST_ASSERT_EQUAL(0, tl_test_struct_var.farr[k]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TEST_ASSERT_EQUAL(test_var1_old+1, tl_test_var1);
|
TEST_ASSERT_EQUAL(test_var1_old + step, tl_test_var1);
|
||||||
TEST_ASSERT_EQUAL(test_var2_old+1, tl_test_var2);
|
TEST_ASSERT_EQUAL(test_var2_old + step, tl_test_var2);
|
||||||
TEST_ASSERT_EQUAL(test_var3_old+1, tl_test_var3);
|
TEST_ASSERT_EQUAL(test_var3_old + step, tl_test_var3);
|
||||||
for (int k = 0; k < sizeof(tl_test_arr_var); k++) {
|
for (int k = 0; k < sizeof(tl_test_arr_var); k++) {
|
||||||
TEST_ASSERT_EQUAL(i-1, tl_test_arr_var[k]);
|
TEST_ASSERT_EQUAL((i - 1) * step, tl_test_arr_var[k]);
|
||||||
}
|
}
|
||||||
TEST_ASSERT_EQUAL(f32_old+1, tl_test_struct_var.f32);
|
TEST_ASSERT_EQUAL(f32_old + step, tl_test_struct_var.f32);
|
||||||
TEST_ASSERT_EQUAL(f8_old+1, tl_test_struct_var.f8);
|
TEST_ASSERT_EQUAL(f8_old + step, tl_test_struct_var.f8);
|
||||||
TEST_ASSERT_EQUAL(f16_old+1, tl_test_struct_var.f16);
|
TEST_ASSERT_EQUAL(f16_old + step, tl_test_struct_var.f16);
|
||||||
for (int k = 0; k < sizeof(tl_test_struct_var.farr); k++) {
|
for (int k = 0; k < sizeof(tl_test_struct_var.farr); k++) {
|
||||||
TEST_ASSERT_EQUAL(i-1, tl_test_struct_var.farr[k]);
|
TEST_ASSERT_EQUAL((i - 1) * step, tl_test_struct_var.farr[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test_var1_old = tl_test_var1;
|
test_var1_old = tl_test_var1;
|
||||||
test_var2_old = tl_test_var2;
|
test_var2_old = tl_test_var2;
|
||||||
test_var3_old = tl_test_var3;
|
test_var3_old = tl_test_var3;
|
||||||
f32_old = tl_test_struct_var.f32;
|
f32_old = tl_test_struct_var.f32;
|
||||||
f8_old = tl_test_struct_var.f8;
|
f8_old = tl_test_struct_var.f8;
|
||||||
f16_old = tl_test_struct_var.f16;
|
f16_old = tl_test_struct_var.f16;
|
||||||
tl_test_var1++;
|
tl_test_var1 += step;
|
||||||
tl_test_var2++;
|
tl_test_var2 += step;
|
||||||
tl_test_var3++;
|
tl_test_var3 += step;
|
||||||
memset(tl_test_arr_var, i, sizeof(tl_test_arr_var));
|
memset(tl_test_arr_var, i * step, sizeof(tl_test_arr_var));
|
||||||
tl_test_struct_var.f32++;
|
tl_test_struct_var.f32 += step;
|
||||||
tl_test_struct_var.f8++;
|
tl_test_struct_var.f8 += step;
|
||||||
tl_test_struct_var.f16++;
|
tl_test_struct_var.f16 += step;
|
||||||
memset(tl_test_struct_var.farr, i, sizeof(tl_test_struct_var.farr));
|
memset(tl_test_struct_var.farr, i * step, sizeof(tl_test_struct_var.farr));
|
||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,10 +112,9 @@ TEST_CASE("TLS test", "[freertos]")
|
|||||||
xTaskCreatePinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[0],
|
xTaskCreatePinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[0],
|
||||||
UNITY_FREERTOS_PRIORITY, NULL, 0);
|
UNITY_FREERTOS_PRIORITY, NULL, 0);
|
||||||
xTaskCreateStaticPinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[1],
|
xTaskCreateStaticPinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[1],
|
||||||
UNITY_FREERTOS_PRIORITY, s_stack, &s_task, other_core);
|
UNITY_FREERTOS_PRIORITY, s_stack, &s_task, other_core);
|
||||||
while (running[0] || running[1]) {
|
while (running[0] || running[1]) {
|
||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
}
|
}
|
||||||
vTaskDelay(10); /* Make sure idle task can clean up s_task, before it goes out of scope */
|
vTaskDelay(10); /* Make sure idle task can clean up s_task, before it goes out of scope */
|
||||||
}
|
}
|
||||||
#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user