FastLED 3.10.9
Loading...
Searching...
No Matches
AutoResearchLegacyAsyncFaults.cpp
Go to the documentation of this file.
1// Dedicated failure-test firmware only. Build with FL_RMT4_FAULT_TEST=1 and:
2// -Wl,--wrap=xTaskCreatePinnedToCore -Wl,--wrap=xQueueCreateMutex
3// -Wl,--wrap=rmt_driver_install
4// No wrapper or control state is present in ordinary firmware.
5
7
8#if AUTORESEARCH_LEGACY_OBSERVES_RMT4_FRAMES && FL_RMT4_ASYNC && defined(FL_RMT4_FAULT_TEST) && FL_RMT4_FAULT_TEST == 1 // ok platform specific - opt-in RMT4 SDK linker fault fixtures have no platform-neutral equivalent.
9#include "fl/stl/atomic.h"
10#include "fl/stl/cstring.h"
11
12// SDK headers stay in this translation unit, never the fixture header.
13extern "C" {
14#include "freertos/FreeRTOS.h" // ok platform specific - exact wrapper ABI comes from the SDK's declarations.
15#include "freertos/task.h" // ok platform specific - matches xTaskCreatePinnedToCore and identifies the arming task.
16#include "freertos/queue.h" // ok platform specific - matches the actual xQueueCreateMutex signature.
17#include "driver/rmt.h" // ok platform specific - matches rmt_driver_install without replacing the peripheral implementation.
18}
19
20namespace autoresearch {
21namespace legacy_async_errors {
22namespace {
23fl::atomic_int armedFault{static_cast<int>(Fault::None)};
24fl::atomic_uint failuresConsumed{0};
25fl::atomic<TaskHandle_t> armingTask{nullptr}; // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
26} // namespace
27
28void armFault(Fault fault) FL_NO_EXCEPT {
29 failuresConsumed.store(0);
30 armingTask.store(xTaskGetCurrentTaskHandle()); // ok platform specific - avoid failing unrelated tasks' mutex allocations.
31 armedFault.store(static_cast<int>(fault));
32}
33
34void disarmFault() FL_NO_EXCEPT { armedFault.store(static_cast<int>(Fault::None)); }
35unsigned consumedFaults() FL_NO_EXCEPT { return failuresConsumed.load(); }
36
37bool consumeFault(Fault fault) FL_NO_EXCEPT {
38 int expected = static_cast<int>(fault);
39 if (!armedFault.compare_exchange_strong(expected, static_cast<int>(Fault::None),
41 return false;
42 }
43 failuresConsumed.fetch_add(1);
44 return true;
45}
46
47bool isArmingTask() FL_NO_EXCEPT {
48 return xTaskGetCurrentTaskHandle() == armingTask.load(); // ok platform specific - only the local driver constructor may consume mutex failure.
49}
50
51} // namespace legacy_async_errors
52} // namespace autoresearch
53
54extern "C" {
55BaseType_t __real_xTaskCreatePinnedToCore(TaskFunction_t code, // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
56 const char *const name, const uint32_t stackBytes, void *const argument,
57 UBaseType_t priority, TaskHandle_t *const task, const BaseType_t core) FL_NO_EXCEPT; // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
58QueueHandle_t __real_xQueueCreateMutex(const uint8_t queueType) FL_NO_EXCEPT; // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
59esp_err_t __real_rmt_driver_install(rmt_channel_t channel, size_t receiveBytes, // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
60 int interruptFlags) FL_NO_EXCEPT;
61
62BaseType_t __wrap_xTaskCreatePinnedToCore(TaskFunction_t code, // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
63 const char *const name, const uint32_t stackBytes, void *const argument,
64 UBaseType_t priority, TaskHandle_t *const task, const BaseType_t core) FL_NO_EXCEPT { // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
65 using namespace autoresearch::legacy_async_errors;
66 if (name && fl::strcmp(name, "fl_rmt4") == 0 &&
67 consumeFault(Fault::TaskAllocation)) {
68 if (task) { *task = nullptr; }
69 return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; // ok platform specific - return the real SDK allocation failure from RMT4 fault linker wrappers; no neutral equivalent exists.
70 }
71 return __real_xTaskCreatePinnedToCore(code, name, stackBytes, argument, // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
72 priority, task, core);
73}
74
75QueueHandle_t __wrap_xQueueCreateMutex(const uint8_t queueType) FL_NO_EXCEPT { // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
76 using namespace autoresearch::legacy_async_errors;
77 if (isArmingTask() && consumeFault(Fault::MutexAllocation)) {
78 return nullptr;
79 }
80 return __real_xQueueCreateMutex(queueType); // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
81}
82
83esp_err_t __wrap_rmt_driver_install(rmt_channel_t channel, size_t receiveBytes, // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
84 int interruptFlags) FL_NO_EXCEPT {
85 using namespace autoresearch::legacy_async_errors;
86 if (consumeFault(Fault::DriverInstall)) { return ESP_ERR_NO_MEM; } // ok platform specific - return the real SDK allocation failure from RMT4 fault linker wrappers; no neutral equivalent exists.
87 return __real_rmt_driver_install(channel, receiveBytes, interruptFlags); // ok platform specific - RMT4 fault linker wrappers must match the exact FreeRTOS and RMT SDK ABI; no neutral wrapper exists.
88}
89}
90#endif
AtomicFake< T > atomic
Definition atomic.h:26
@ memory_order_acquire
Definition atomic.h:41
FASTLED_FORCE_INLINE int strcmp(const char *s1, const char *s2) FL_NO_EXCEPT
Definition cstring.h:60
atomic< unsigned int > atomic_uint
Definition atomic.h:31
atomic< int > atomic_int
Definition atomic.h:30
#define FL_NO_EXCEPT