Merge branch 'feature/newlib_lock_retarget' into 'master'

newlib 3.3.0 _RETARGETABLE_LOCKING support

Closes IDF-2129

See merge request espressif/esp-idf!9141
This commit is contained in:
Angus Gratton 2020-12-30 09:11:35 +08:00
commit 1760f47681
33 changed files with 386 additions and 72 deletions

View File

@ -76,11 +76,6 @@ menu "Driver configurations"
config TWAI_ISR_IN_IRAM
bool "Place TWAI ISR function into IRAM"
default n
select FREERTOS_SUPPORT_STATIC_ALLOCATION
# We need to enable FREERTOS_SUPPORT_STATIC_ALLOCATION because the
# TWAI driver requires the use of FreeRTOS Queues and Semaphores from
# the driver ISR. These Queues and Semaphores need to be placed in
# DRAM thus FreeRTOS static allocation API is required.
help
Place the TWAI ISR in to IRAM. This will allow the ISR to avoid
cache misses, and also be able to run whilst the cache is disabled

View File

@ -64,8 +64,6 @@ typedef enum {
* buffer where this struct is of the exact size required to store a ring
* buffer's control data structure.
*
* @note The CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION option must be enabled for
* this structure to be available.
*/
#if ( configSUPPORT_STATIC_ALLOCATION == 1)
typedef struct xSTATIC_RINGBUFFER {
@ -117,9 +115,6 @@ RingbufHandle_t xRingbufferCreateNoSplit(size_t xItemSize, size_t xItemNum);
* @param[in] pxStaticRingbuffer Pointed to a struct of type StaticRingbuffer_t
* which will be used to hold the ring buffer's data structure
*
* @note The CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION option must be enabled
* for this to be available
*
* @note xBufferSize of no-split/allow-split buffers MUST be 32-bit aligned.
*
* @return A handle to the created ring buffer

View File

@ -17,3 +17,7 @@ __sf_fake_stderr = 0x3ff96458;
__sf_fake_stdin = 0x3ff96498;
__sf_fake_stdout = 0x3ff96478;
__wctomb = 0x3ff96540;
__sfp_lock = 0x3ffae0ac;
__sinit_lock = 0x3ffae0a8;
__env_lock_object = 0x3ffae0b8;
__tz_lock_object = 0x3ffae080;

View File

@ -13,3 +13,5 @@ _PathLocale = 0x3ffffd80;
__sf_fake_stderr = 0x3ffaf08c;
__sf_fake_stdin = 0x3ffaf0cc;
__sf_fake_stdout = 0x3ffaf0ac;
__sfp_recursive_mutex = 0x3ffffd88;
__sinit_recursive_mutex = 0x3ffffd84;

View File

@ -15,3 +15,5 @@ _PathLocale = 0x3fcefcd0;
__sf_fake_stderr = 0x3ff0c524;
__sf_fake_stdin = 0x3ff0c564;
__sf_fake_stdout = 0x3ff0c544;
__sinit_recursive_mutex = 0x3fcefcd4;
__sfp_recursive_mutex = 0x3fcefcd8;

View File

@ -199,6 +199,7 @@ static void do_core_init(void)
fail initializing it properly. */
heap_caps_init();
esp_setup_syscall_table();
esp_newlib_locks_init();
esp_newlib_time_init();
if (g_spiram_ok) {

View File

@ -290,7 +290,6 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub", "[deepsleep][reset=DEEPSLEE
#if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
#if CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
/* Version of prepare_wake_stub() that sets up the deep sleep call while running
from RTC memory as stack, with a high frequency timer also writing RTC FAST
@ -346,7 +345,6 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub from stack in RTC RAM", "[dee
prepare_wake_stub_from_rtc,
check_wake_stub);
#endif // CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
#endif // CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]")

View File

@ -552,6 +552,7 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st)
{
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
FIL* file = &fat_ctx->files[fd];
memset(st, 0, sizeof(*st));
st->st_size = f_size(file);
st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFREG;
st->st_mtime = 0;

View File

@ -205,36 +205,14 @@ menu "FreeRTOS"
For most uses, the default of 16 is OK.
config FREERTOS_SUPPORT_STATIC_ALLOCATION
bool "Enable FreeRTOS static allocation API"
default n
help
FreeRTOS gives the application writer the ability to instead provide the memory
themselves, allowing the following objects to optionally be created without any
memory being allocated dynamically:
- Tasks
- Software Timers (Daemon task is still dynamic. See documentation)
- Queues
- Event Groups
- Binary Semaphores
- Counting Semaphores
- Recursive Semaphores
- Mutexes
Whether it is preferable to use static or dynamic memory allocation is dependent on
the application, and the preference of the application writer. Both methods have pros
and cons, and both methods can be used within the same RTOS application.
Creating RTOS objects using statically allocated RAM has the benefit of providing the application writer
with more control: RTOS objects can be placed at specific memory locations. The maximum RAM footprint can
be determined at link time, rather than run time. The application writer does not need to concern
themselves with graceful handling of memory allocation failures. It allows the RTOS to be used in
applications that simply don't allow any dynamic memory allocation (although FreeRTOS includes allocation
schemes that can overcome most objections).
# Always enabled.
# Kconfig option preserved for compatibility with code
# which checked for CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION.
bool
default y
config FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
bool "Enable static task clean up hook"
depends on FREERTOS_SUPPORT_STATIC_ALLOCATION
default n
help
Enable this option to make FreeRTOS call the static task clean up hook when a task is deleted.

View File

@ -239,7 +239,7 @@
kept at 1. */
#define configKERNEL_INTERRUPT_PRIORITY 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configSUPPORT_STATIC_ALLOCATION CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
#define configSUPPORT_STATIC_ALLOCATION 1
#ifndef __ASSEMBLER__
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP

View File

@ -291,7 +291,7 @@ int xt_clock_freq(void) __attribute__((deprecated));
#define configUSE_NEWLIB_REENTRANT 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configSUPPORT_STATIC_ALLOCATION CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
#define configSUPPORT_STATIC_ALLOCATION 1
#ifndef __ASSEMBLER__
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP

View File

@ -1,7 +1,6 @@
# sdkconfig replacement configurations for deprecated options formatted as
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
CONFIG_SUPPORT_STATIC_ALLOCATION CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY
CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH

View File

@ -29,7 +29,6 @@
#include "unity.h"
#include "test_utils.h"
#ifdef CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
/* ---------------------Test 1: Backported Timer functions-----------------------
* Test xTimerCreateStatic(), vTimerSetTimerId(), xTimerGetPeriod(), xTimerGetExpiryTime()
*
@ -201,7 +200,6 @@ TEST_CASE("Test FreeRTOS backported eventgroup functions", "[freertos]")
//Cleanup static event
vEventGroupDelete(eg_handle);
}
#endif
/* --------Test backported thread local storage pointer and deletion cb feature----------
* vTaskSetThreadLocalStoragePointerAndDelCallback()

View File

@ -69,7 +69,6 @@ TEST_CASE("Recurring FreeRTOS timers", "[freertos]")
TEST_ASSERT( xTimerDelete(recurring, 1) );
}
#ifdef CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
TEST_CASE("Static timer creation", "[freertos]")
{
StaticTimer_t static_timer;
@ -84,4 +83,3 @@ TEST_CASE("Static timer creation", "[freertos]")
TEST_ASSERT_NOT_NULL(created_timer);
}
#endif

View File

@ -30,9 +30,8 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE c m gcc "$<TARGET_FILE:${newlib
set_source_files_properties(heap.c PROPERTIES COMPILE_FLAGS -fno-builtin)
# Forces the linker to include locks, heap, and syscalls from this component,
# Forces the linker to include heap, syscalls, and pthread from this component,
# instead of the implementations provided by newlib.
set(EXTRA_LINK_FLAGS "-u newlib_include_locks_impl")
list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_heap_impl")
list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_syscalls_impl")
list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_pthread_impl")

View File

@ -15,9 +15,8 @@ endif
COMPONENT_PRIV_INCLUDEDIRS := priv_include
COMPONENT_SRCDIRS := . port
# Forces the linker to include locks, heap, and syscalls from this component,
# Forces the linker to include heap, syscalls, and pthread from this component,
# instead of the implementations provided by newlib.
COMPONENT_ADD_LDFLAGS += -u newlib_include_locks_impl
COMPONENT_ADD_LDFLAGS += -u newlib_include_heap_impl
COMPONENT_ADD_LDFLAGS += -u newlib_include_syscalls_impl

View File

@ -21,7 +21,6 @@
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "freertos/portable.h"
#include "esp_heap_caps.h"
/* Notes on our newlib lock implementation:
*
@ -119,7 +118,6 @@ void _lock_close_recursive(_lock_t *lock) __attribute__((alias("_lock_close")));
*/
static int IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t mutex_type) {
xSemaphoreHandle h = (xSemaphoreHandle)(*lock);
if (!h) {
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
return 0; /* locking is a no-op before scheduler is up, so this "succeeds" */
@ -212,9 +210,208 @@ void IRAM_ATTR _lock_release_recursive(_lock_t *lock) {
lock_release_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX);
}
/* No-op function, used to force linking this file,
instead of the dummy locks implementation from newlib.
#ifdef _RETARGETABLE_LOCKING
/* To ease the transition to newlib 3.3.0, this part is kept under an ifdef.
* After the toolchain with newlib 3.3.0 is released and merged, the ifdefs
* can be removed.
*
* Also the retargetable locking functions still rely on the previous
* implementation. Once support for !_RETARGETABLE_LOCKING is removed,
* the code can be simplified, removing support for lazy initialization of
* locks. At the same time, IDF code which relies on _lock_acquire/_lock_release
* will have to be updated to not depend on lazy initialization.
*
* Explanation of the different lock types:
*
* Newlib 2.2.0 and 3.0.0:
* _lock_t is defined as int, stores SemaphoreHandle_t.
*
* Newlib 3.3.0:
* struct __lock is (or contains) StaticSemaphore_t
* _LOCK_T is a pointer to struct __lock, equivalent to SemaphoreHandle_t.
* It has the same meaning as _lock_t in the previous implementation.
*
*/
void newlib_include_locks_impl(void)
/* This ensures the platform-specific definition in lock.h is correct.
* We use "greater or equal" since the size of StaticSemaphore_t may
* vary by 2 words, depending on whether configUSE_TRACE_FACILITY is enabled.
*/
_Static_assert(sizeof(struct __lock) >= sizeof(StaticSemaphore_t),
"Incorrect size of struct __lock");
/* FreeRTOS configuration check */
_Static_assert(configSUPPORT_STATIC_ALLOCATION,
"FreeRTOS should be configured with static allocation support");
/* These 2 locks are used instead of 9 distinct newlib static locks,
* as most of the locks are required for lesser-used features, so
* the chance of performance degradation due to lock contention is low.
*/
static StaticSemaphore_t s_common_mutex;
static StaticSemaphore_t s_common_recursive_mutex;
#ifdef CONFIG_IDF_TARGET_ESP32C3
/* C3 ROM is built without Newlib static lock symbols exported, and
* with an extra level of _LOCK_T indirection in mind.
* The following is a workaround for this:
* - on startup, we call esp_rom_newlib_init_common_mutexes to set
* the two mutex pointers to magic values.
* - if in __retarget_lock_acquire*, we check if the argument dereferences
* to the magic value. If yes, we lock the correct mutex defined in the app,
* instead.
* Casts from &StaticSemaphore_t to _LOCK_T are okay because _LOCK_T
* (which is SemaphoreHandle_t) is a pointer to the corresponding
* StaticSemaphore_t structure. This is ensured by asserts below.
*/
#define ROM_NEEDS_MUTEX_OVERRIDE
#endif // CONFIG_IDF_TARGET_ESP32C3
#ifdef ROM_NEEDS_MUTEX_OVERRIDE
#define ROM_MUTEX_MAGIC 0xbb10c433
/* This is a macro, since we are overwriting the argument */
#define MAYBE_OVERRIDE_LOCK(_lock, _lock_to_use_instead) \
if (*(int*)_lock == ROM_MUTEX_MAGIC) { \
(_lock) = (_LOCK_T) (_lock_to_use_instead); \
}
#else // ROM_NEEDS_MUTEX_OVERRIDE
#define MAYBE_OVERRIDE_LOCK(_lock, _lock_to_use_instead)
#endif // ROM_NEEDS_MUTEX_OVERRIDE
void IRAM_ATTR __retarget_lock_init(_LOCK_T *lock)
{
*lock = NULL; /* In case lock's memory is uninitialized */
lock_init_generic(lock, queueQUEUE_TYPE_MUTEX);
}
void IRAM_ATTR __retarget_lock_init_recursive(_LOCK_T *lock)
{
*lock = NULL; /* In case lock's memory is uninitialized */
lock_init_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX);
}
void IRAM_ATTR __retarget_lock_close(_LOCK_T lock)
{
_lock_close(&lock);
}
void IRAM_ATTR __retarget_lock_close_recursive(_LOCK_T lock)
{
_lock_close_recursive(&lock);
}
/* Separate function, to prevent generating multiple assert strings */
static void IRAM_ATTR check_lock_nonzero(_LOCK_T lock)
{
assert(lock != NULL && "Uninitialized lock used");
}
void IRAM_ATTR __retarget_lock_acquire(_LOCK_T lock)
{
check_lock_nonzero(lock);
MAYBE_OVERRIDE_LOCK(lock, &s_common_mutex);
_lock_acquire(&lock);
}
void IRAM_ATTR __retarget_lock_acquire_recursive(_LOCK_T lock)
{
check_lock_nonzero(lock);
MAYBE_OVERRIDE_LOCK(lock, &s_common_recursive_mutex);
_lock_acquire_recursive(&lock);
}
int IRAM_ATTR __retarget_lock_try_acquire(_LOCK_T lock)
{
check_lock_nonzero(lock);
MAYBE_OVERRIDE_LOCK(lock, &s_common_mutex);
return _lock_try_acquire(&lock);
}
int IRAM_ATTR __retarget_lock_try_acquire_recursive(_LOCK_T lock)
{
check_lock_nonzero(lock);
MAYBE_OVERRIDE_LOCK(lock, &s_common_recursive_mutex);
return _lock_try_acquire_recursive(&lock);
}
void IRAM_ATTR __retarget_lock_release(_LOCK_T lock)
{
check_lock_nonzero(lock);
_lock_release(&lock);
}
void IRAM_ATTR __retarget_lock_release_recursive(_LOCK_T lock)
{
check_lock_nonzero(lock);
_lock_release_recursive(&lock);
}
/* When _RETARGETABLE_LOCKING is enabled, newlib expects the following locks to be provided: */
extern StaticSemaphore_t __attribute__((alias("s_common_recursive_mutex"))) __lock___sinit_recursive_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_recursive_mutex"))) __lock___malloc_recursive_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_recursive_mutex"))) __lock___env_recursive_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_recursive_mutex"))) __lock___sfp_recursive_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_recursive_mutex"))) __lock___atexit_recursive_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_mutex"))) __lock___at_quick_exit_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_mutex"))) __lock___tz_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_mutex"))) __lock___dd_hash_mutex;
extern StaticSemaphore_t __attribute__((alias("s_common_mutex"))) __lock___arc4random_mutex;
void esp_newlib_locks_init(void)
{
/* Initialize the two mutexes used for the locks above.
* Asserts below check our assumption that SemaphoreHandle_t will always
* point to the corresponding StaticSemaphore_t structure.
*/
SemaphoreHandle_t handle;
handle = xSemaphoreCreateMutexStatic(&s_common_mutex);
assert(handle == (SemaphoreHandle_t) &s_common_mutex);
handle = xSemaphoreCreateRecursiveMutexStatic(&s_common_recursive_mutex);
assert(handle == (SemaphoreHandle_t) &s_common_recursive_mutex);
(void) handle;
/* Chip ROMs are built with older versions of newlib, and rely on different lock variables.
* Initialize these locks to the same values.
*/
#ifdef CONFIG_IDF_TARGET_ESP32
/* Newlib 2.2.0 is used in ROM, the following lock symbols are defined: */
extern _lock_t __sfp_lock;
__sfp_lock = (_lock_t) &s_common_recursive_mutex;
extern _lock_t __sinit_lock;
__sinit_lock = (_lock_t) &s_common_recursive_mutex;
extern _lock_t __env_lock_object;
__env_lock_object = (_lock_t) &s_common_mutex;
extern _lock_t __tz_lock_object;
__tz_lock_object = (_lock_t) &s_common_recursive_mutex;
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
/* Newlib 3.0.0 is used in ROM, the following lock symbols are defined: */
extern _lock_t __sinit_recursive_mutex;
__sinit_recursive_mutex = (_lock_t) &s_common_recursive_mutex;
extern _lock_t __sfp_recursive_mutex;
__sfp_recursive_mutex = (_lock_t) &s_common_recursive_mutex;
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
/* Newlib 3.3.0 is used in ROM, built with _RETARGETABLE_LOCKING.
* No access to lock variables for the purpose of ECO forward compatibility,
* however we have an API to initialize lock variables used in the ROM.
*/
extern void esp_rom_newlib_init_common_mutexes(_LOCK_T, _LOCK_T);
/* See notes about ROM_NEEDS_MUTEX_OVERRIDE above */
int magic_val = ROM_MUTEX_MAGIC;
_LOCK_T magic_mutex = (_LOCK_T) &magic_val;
esp_rom_newlib_init_common_mutexes(magic_mutex, magic_mutex);
#else // other target
#error Unsupported target
#endif
}
#else // _RETARGETABLE_LOCKING
void esp_newlib_locks_init(void)
{
}
#endif // _RETARGETABLE_LOCKING

View File

@ -53,4 +53,9 @@ void esp_set_time_from_rtc(void);
*/
void esp_sync_counters_rtc_and_frc(void);
/**
* Initialize newlib static locks
*/
void esp_newlib_locks_init(void);
#endif //__ESP_NEWLIB_H__

View File

@ -0,0 +1,41 @@
#pragma once
#include_next <sys/lock.h>
#ifdef _RETARGETABLE_LOCKING
/* Actual platfrom-specific definition of struct __lock.
* The size here should be sufficient for a FreeRTOS mutex.
* This is checked by a static assertion in locks.c
*
* Note 1: this might need to be made dependent on whether FreeRTOS
* is included in the build.
*
* Note 2: the size is made sufficient for the case when
* configUSE_TRACE_FACILITY is enabled. If it is disabled,
* this definition wastes 8 bytes.
*/
struct __lock {
int reserved[23];
};
/* Compatibility definitions for the legacy ESP-specific locking implementation.
* These used to be provided by libc/sys/xtensa/sys/lock.h in newlib.
* Newer versions of newlib don't have this ESP-specific lock.h header, and are
* built with _RETARGETABLE_LOCKING enabled, instead.
*/
typedef _LOCK_T _lock_t;
void _lock_init(_lock_t *plock);
void _lock_init_recursive(_lock_t *plock);
void _lock_close(_lock_t *plock);
void _lock_close_recursive(_lock_t *plock);
void _lock_acquire(_lock_t *plock);
void _lock_acquire_recursive(_lock_t *plock);
int _lock_try_acquire(_lock_t *plock);
int _lock_try_acquire_recursive(_lock_t *plock);
void _lock_release(_lock_t *plock);
void _lock_release_recursive(_lock_t *plock);
#endif // _RETARGETABLE_LOCKING

View File

@ -0,0 +1,109 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/lock.h>
#include "unity.h"
#include "test_utils.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#if defined(_RETARGETABLE_LOCKING)
static void locking_task(void* arg)
{
_LOCK_T lock = (_LOCK_T) arg;
__lock_acquire(lock);
__lock_release(lock);
vTaskSuspend(NULL);
}
static void recursive_locking_task(void* arg)
{
_LOCK_T lock = (_LOCK_T) arg;
__lock_acquire_recursive(lock);
__lock_release_recursive(lock);
vTaskSuspend(NULL);
}
static void test_inner_normal(_LOCK_T lock)
{
/* Acquire the lock */
__lock_acquire(lock);
/* Create another task to try acquire same lock */
TaskHandle_t task_hdl;
TEST_ASSERT(xTaskCreate(&locking_task, "locking_task", 2048, lock, UNITY_FREERTOS_PRIORITY, &task_hdl));
vTaskDelay(2);
/* It should get blocked */
TEST_ASSERT_EQUAL(eBlocked, eTaskGetState(task_hdl));
/* Once we release the lock, the task should succeed and suspend itself */
__lock_release(lock);
vTaskDelay(2);
TEST_ASSERT_EQUAL(eSuspended, eTaskGetState(task_hdl));
vTaskDelete(task_hdl);
/* Can not recursively acquire the lock from same task */
TEST_ASSERT_EQUAL(0, __lock_try_acquire(lock));
TEST_ASSERT_EQUAL(-1, __lock_try_acquire(lock));
__lock_release(lock);
}
static void test_inner_recursive(_LOCK_T lock)
{
/* Acquire the lock */
__lock_acquire_recursive(lock);
/* Create another task to try acquire same lock */
TaskHandle_t task_hdl;
TEST_ASSERT(xTaskCreate(&recursive_locking_task, "locking_task", 2048, lock, UNITY_FREERTOS_PRIORITY, &task_hdl));
vTaskDelay(2);
/* It should get blocked */
TEST_ASSERT_EQUAL(eBlocked, eTaskGetState(task_hdl));
/* Once we release the lock, the task should succeed and suspend itself */
__lock_release_recursive(lock);
vTaskDelay(2);
TEST_ASSERT_EQUAL(eSuspended, eTaskGetState(task_hdl));
vTaskDelete(task_hdl);
/* Try recursively acquiring the lock */
TEST_ASSERT_EQUAL(0, __lock_try_acquire_recursive(lock));
TEST_ASSERT_EQUAL(0, __lock_try_acquire_recursive(lock));
__lock_release_recursive(lock);
__lock_release_recursive(lock);
}
TEST_CASE("Retargetable static locks", "[newlib_locks]")
{
StaticSemaphore_t semaphore;
_LOCK_T lock = (_LOCK_T) xSemaphoreCreateMutexStatic(&semaphore);
test_inner_normal(lock);
}
TEST_CASE("Retargetable static recursive locks", "[newlib_locks]")
{
StaticSemaphore_t semaphore;
_LOCK_T lock = (_LOCK_T) xSemaphoreCreateRecursiveMutexStatic(&semaphore);
test_inner_recursive(lock);
}
TEST_CASE("Retargetable dynamic locks", "[newlib_locks]")
{
_LOCK_T lock;
__lock_init(lock);
test_inner_normal(lock);
__lock_close(lock);
}
TEST_CASE("Retargetable dynamic recursive locks", "[newlib_locks]")
{
_LOCK_T lock;
__lock_init_recursive(lock);
test_inner_recursive(lock);
__lock_close_recursive(lock);
}
#endif // _RETARGETABLE_LOCKING

View File

@ -104,7 +104,6 @@ menu "SPI Flash driver"
# The bus lock on SPI1 is meaningless when the legacy implementation is used, or the SPI
# driver does not support SPI1.
depends on !SPI_FLASH_USE_LEGACY_IMPL && !IDF_TARGET_ESP32S2
select FREERTOS_SUPPORT_STATIC_ALLOCATION
help
Each SPI bus needs a lock for arbitration among devices. This allows multiple
devices on a same bus, but may reduce the speed of esp_flash driver access to the

View File

@ -536,6 +536,7 @@ static int vfs_spiffs_fstat(void* ctx, int fd, struct stat * st)
SPIFFS_clearerr(efs->fs);
return -1;
}
memset(st, 0, sizeof(*st));
st->st_size = s.size;
st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFREG;
st->st_mtime = vfs_spiffs_get_mtime(&s);
@ -558,7 +559,7 @@ static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st)
SPIFFS_clearerr(efs->fs);
return -1;
}
memset(st, 0, sizeof(*st));
st->st_size = s.size;
st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO;
st->st_mode |= (s.type == SPIFFS_TYPE_DIR)?S_IFDIR:S_IFREG;

View File

@ -4,7 +4,6 @@ menu "TinyUSB"
bool "Enable TinyUSB driver"
default n
depends on IDF_TARGET_ESP32S2
select FREERTOS_SUPPORT_STATIC_ALLOCATION
select FREERTOS_USE_AUTHENTIC_INCLUDE_PATHS
help
Adds support for TinyUSB

View File

@ -207,6 +207,7 @@ static ssize_t tusb_read(int fd, void *data, size_t size)
static int tusb_fstat(int fd, struct stat *st)
{
FD_CHECK(fd, -1);
memset(st, 0, sizeof(*st));
st->st_mode = S_IFCHR;
return 0;
}

View File

@ -96,6 +96,7 @@ static int cdcacm_open(const char *path, int flags, int mode)
static int cdcacm_fstat(int fd, struct stat *st)
{
assert(fd == 0);
memset(st, 0, sizeof(*st));
st->st_mode = S_IFCHR;
return 0;
}

View File

@ -291,7 +291,7 @@ static ssize_t uart_read(int fd, void* data, size_t size)
static int uart_fstat(int fd, struct stat * st)
{
assert(fd >=0 && fd < 3);
st->st_blksize = BUFSIZ;
memset(st, 0, sizeof(*st));
st->st_mode = S_IFCHR;
return 0;
}

View File

@ -438,9 +438,6 @@ ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>`
will be modified. For more details regarding the effects of running ESP-IDF FreeRTOS
on a single core, search for occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
:ref:`CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION` will enable the
functionality of :cpp:func:`xTaskCreateStaticPinnedToCore` in ESP-IDF FreeRTOS
:ref:`CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION` will trigger a halt in
particular functions in ESP-IDF FreeRTOS which have not been fully tested
in an SMP context.

View File

@ -412,9 +412,6 @@ The :cpp:func:`xRingbufferCreateStatic` can be used to create ring buffers with
The manner in which these blocks are allocated will depend on the users requirements (e.g. all blocks being statically declared, or dynamically allocated with specific capabilities such as external RAM).
.. note::
The :ref:`CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION` option must be enabled in `menuconfig` for statically allocated ring buffers to be available.
.. note::
When deleting a ring buffer created via :cpp:func:`xRingbufferCreateStatic`,
the function :cpp:func:`vRingbufferDelete` will not free any of the memory blocks. This must be done manually by the user after :cpp:func:`vRingbufferDelete` is called.

View File

@ -14,7 +14,6 @@ CONFIG_BLE_MESH_PB_GATT=y
CONFIG_BLE_MESH_CFG_CLI=y
CONFIG_FREERTOS_UNICORE=y
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY=y
CONFIG_BLE_MESH_MEM_ALLOC_MODE_IRAM_8BIT=y
CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC=y

View File

@ -102,9 +102,11 @@ static void IRAM_ATTR test_int_wdt_cache_disabled(void)
static void test_stack_overflow(void)
{
volatile uint8_t stuff[CONFIG_ESP_MAIN_TASK_STACK_SIZE + 1000];
for (int i = 0; i < sizeof(stuff); ++i) {
stuff[i] = rand();
register uint32_t* sp asm("sp");
uint32_t *end = sp - CONFIG_ESP_MAIN_TASK_STACK_SIZE;
// offset - 20 bytes from SP in order to not corrupt the current frame.
for (uint32_t* ptr = sp - 5; ptr != end; --ptr) {
*ptr = rand();
}
}

View File

@ -12,7 +12,6 @@ CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=n
CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE=y
CONFIG_FREERTOS_LEGACY_HOOKS=y
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=10
CONFIG_FREERTOS_USE_TRACE_FACILITY=y

View File

@ -12,7 +12,6 @@ CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=n
CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE=y
CONFIG_FREERTOS_LEGACY_HOOKS=y
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=10
CONFIG_FREERTOS_USE_TRACE_FACILITY=y

View File

@ -17,7 +17,6 @@ CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS=y
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=7
CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y
CONFIG_COMPILER_STACK_CHECK=y
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
CONFIG_ESP_TIMER_PROFILING=y
CONFIG_ADC_DISABLE_DAC=n
CONFIG_COMPILER_WARN_WRITE_STRINGS=y