feat(pthread): Pthread can now use PSRAM as stack

Closes https://github.com/espressif/esp-idf/pull/10623
Closes https://github.com/espressif/esp-idf/issues/8662

Thanks to f-hoepfinger-hr-agrartechnik for the contribution
in https://github.com/espressif/esp-idf/pull/10623
This commit is contained in:
Jakob Hasse
2023-06-30 11:21:12 +08:00
parent 261651fc19
commit be59c94917
13 changed files with 304 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,6 +15,10 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#if CONFIG_SPIRAM
#include "esp_private/freertos_idf_additions_priv.h"
#endif
#include "esp_heap_caps.h"
#include "soc/soc_memory_layout.h"
#include "pthread_internal.h"
@@ -131,6 +135,19 @@ esp_err_t esp_pthread_set_cfg(const esp_pthread_cfg_t *cfg)
return ESP_ERR_INVALID_ARG;
}
// 0 is treated as default value, hence change caps to MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL in that case
int heap_caps;
if (cfg->stack_alloc_caps == 0) {
heap_caps = MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL;
} else {
// Check that memory is 8-bit capable
if (!(cfg->stack_alloc_caps & MALLOC_CAP_8BIT)) {
return ESP_ERR_INVALID_ARG;
}
heap_caps = cfg->stack_alloc_caps;
}
/* If a value is already set, update that value */
esp_pthread_cfg_t *p = pthread_getspecific(s_pthread_cfg_key);
if (!p) {
@@ -140,6 +157,7 @@ esp_err_t esp_pthread_set_cfg(const esp_pthread_cfg_t *cfg)
}
}
*p = *cfg;
p->stack_alloc_caps = heap_caps;
pthread_setspecific(s_pthread_cfg_key, p);
return 0;
}
@@ -167,7 +185,8 @@ esp_pthread_cfg_t esp_pthread_get_default_config(void)
.prio = CONFIG_PTHREAD_TASK_PRIO_DEFAULT,
.inherit_cfg = false,
.thread_name = NULL,
.pin_to_core = get_default_pthread_core()
.pin_to_core = get_default_pthread_core(),
.stack_alloc_caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT,
};
return cfg;
@@ -201,6 +220,57 @@ static void pthread_task_func(void *arg)
ESP_LOGV(TAG, "%s EXIT", __FUNCTION__);
}
#if CONFIG_SPIRAM && CONFIG_FREERTOS_SMP
static UBaseType_t coreID_to_AffinityMask(BaseType_t core_id)
{
UBaseType_t affinity_mask = tskNO_AFFINITY;
if (core_id != tskNO_AFFINITY) {
affinity_mask = 1 << core_id;
}
return affinity_mask;
}
#endif
static BaseType_t pthread_create_freertos_task_with_caps(TaskFunction_t pxTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
BaseType_t core_id,
UBaseType_t uxStackMemoryCaps,
TaskHandle_t * const pxCreatedTask)
{
#if CONFIG_SPIRAM
#if CONFIG_FREERTOS_SMP
return prvTaskCreateDynamicAffinitySetWithCaps(pxTaskCode,
pcName,
usStackDepth,
pvParameters,
uxPriority,
coreID_to_AffinityMask(core_id),
uxStackMemoryCaps,
pxCreatedTask);
#else
return prvTaskCreateDynamicPinnedToCoreWithCaps(pxTaskCode,
pcName,
usStackDepth,
pvParameters,
uxPriority,
core_id,
uxStackMemoryCaps,
pxCreatedTask);
#endif
#else
return xTaskCreatePinnedToCore(pxTaskCode,
pcName,
usStackDepth,
pvParameters,
uxPriority,
pxCreatedTask,
core_id);
#endif
}
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg)
{
@@ -224,6 +294,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
BaseType_t prio = CONFIG_PTHREAD_TASK_PRIO_DEFAULT;
BaseType_t core_id = get_default_pthread_core();
const char *task_name = CONFIG_PTHREAD_TASK_NAME_DEFAULT;
uint32_t stack_alloc_caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
esp_pthread_cfg_t *pthread_cfg = pthread_getspecific(s_pthread_cfg_key);
if (pthread_cfg) {
@@ -252,6 +323,9 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
core_id = pthread_cfg->pin_to_core;
}
// Note: validity has been checked during esp_pthread_set_cfg()
stack_alloc_caps = pthread_cfg->stack_alloc_caps;
task_arg->cfg = *pthread_cfg;
}
@@ -269,20 +343,23 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
}
}
// stack_size is in bytes. This transformation ensures that the units are
// transformed to the units used in FreeRTOS.
// Note: float division of ceil(m / n) ==
// integer division of (m + n - 1) / n
stack_size = (stack_size + sizeof(StackType_t) - 1) / sizeof(StackType_t);
task_arg->func = start_routine;
task_arg->arg = arg;
pthread->task_arg = task_arg;
BaseType_t res = xTaskCreatePinnedToCore(&pthread_task_func,
BaseType_t res = pthread_create_freertos_task_with_caps(&pthread_task_func,
task_name,
// stack_size is in bytes. This transformation ensures that the units are
// transformed to the units used in FreeRTOS.
// Note: float division of ceil(m / n) ==
// integer division of (m + n - 1) / n
(stack_size + sizeof(StackType_t) - 1) / sizeof(StackType_t),
stack_size,
task_arg,
prio,
&xHandle,
core_id);
core_id,
stack_alloc_caps,
&xHandle);
if (res != pdPASS) {
ESP_LOGE(TAG, "Failed to create task!");