Fix RIP bugs, add in UART

This commit is contained in:
Johnathon Slightham
2026-03-31 14:26:37 -04:00
committed by Johnathon Slightham
parent d4602012f1
commit 548e8db484
26 changed files with 704 additions and 434 deletions

View File

@@ -110,42 +110,3 @@ CLion is compatible with this project. Follow [the tutorial on Espressif's site]
- If the `Open Project Wizard` does not open, access it via `Settings > Build, Execution, Deployment > CMake`.
- When setting the `DIDF_TARGET`, ensure you specify `esp32s3`.
# me when it works
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡤⣖⣤⣶⣿⣿⣿⣿⣿⣭⡶⠶⠒⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠈⠉⠁⠒⠤⠀⡔⠄⠀⠂
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡴⢋⣥⣾⣿⣿⣿⣿⣿⣿⡿⠛⠁⢀⣠⠔⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠛⠓⢤⡀⠀⠀⢀⣀⠈⠂⠉⠀
⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠘⣿⣀⢻⡟⠉⣷⠀⠀⠀⠀⠀⠀⢀⡤⠎⠁⣀⣿⣿⣿⣿⣿⣿⣿⠟⢉⣠⣶⡾⠋⠀⠀⠀⠀⣀⣠⡤⢶⡾⠶⠀⠀⠀⠀⠀⠉⠶⣽⣾⣿⣷⣄⡀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣶⣬⣺⡟⠀⠀⠀⠀⢀⡴⠋⢀⣤⣾⣿⣿⣿⣿⣿⣿⡿⣣⣴⡿⠟⠁⠀⠀⣠⣤⣶⡿⠟⢉⣴⠋⠁⠀⠀⢀⡞⠀⠀⣦⠀⠙⢿⣿⣿⣿⣿⣦
⠀⠀⠀⠀⠀⠰⡄⠀⠀⠀⠀⠀⠀⠀⠈⠁⠀⠀⠀⢀⣴⣯⣶⣿⣿⣿⡿⣽⣿⣿⣿⣿⣿⣿⢿⠋⡀⣀⣤⣾⠿⣿⡿⢋⣴⣾⠟⠀⠀⠀⠀⣴⠋⠀⠀⠀⢹⣦⠠⢪⣻⣿⣿⣿⣿
⠀⠀⠀⠀⠀⠀⠻⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣻⢋⡞⣿⣿⣿⣿⣿⣿⣿⣷⣾⡿⠟⠉⣱⡾⣯⡶⣿⡿⠃⠀⠀⠀⢀⡼⠃⢠⣆⠀⠀⣇⣿⡆⡜⡏⢿⣿⣿⣿
⠀⠀⠀⠀⠀⠀⠀⢷⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⡟⠁⠀⠁⣰⣿⣿⣿⣿⣿⣿⡿⠛⠁⠀⢠⣾⣿⠟⢡⣾⣿⠅⠀⠀⠀⣠⡿⠁⣰⣿⢸⢸⡆⣿⣿⣿⣼⣼⡈⣿⣿⣿
⠀⠀⠀⠀⠀⠀⠀⠈⡇⠀⠀⠀⠀⠀⠀⠀⣴⣿⠟⣹⣿⡏⠀⠀⠀⢰⣿⣿⣿⣿⡿⠟⠉⠀⠀⠀⣰⣿⡿⠃⢠⣾⣿⠞⠀⠀⡴⣷⣿⠅⠀⣿⣿⢸⣾⡇⢻⣿⣿⣿⣿⣇⠸⣿⣿
⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⢰⡿⠁⣸⣿⡟⢠⢀⢠⢀⣿⣿⣿⡿⠋⠀⠀⠀⠀⠀⢰⣿⠟⠀⢠⣿⣿⡟⠀⢀⣼⣿⣿⡿⠀⢰⣿⣿⡟⣿⣇⢸⣿⣿⣿⣿⣿⠀⣿⣿
⠀⠀⠀⠀⢰⡾⢶⣀⣥⣤⡀⠀⠀⠀⢰⡟⠁⣴⣿⣿⣧⡟⣾⢋⣼⣿⡿⠋⠀⠀⠀⠀⠀⠀⢠⣿⠏⠀⠀⣼⣿⣿⠀⢀⣾⣿⣳⡿⠁⠀⡇⣿⣿⣿⣿⣿⡸⣿⣿⣿⣿⣿⡀⢻⡏
⠀⠀⠀⠀⢸⣇⠀⠻⣇⣸⡇⠀⠀⢀⡞⠀⣼⢿⣿⣿⣿⣹⡟⣾⡿⠋⠑⠦⠤⠤⣀⣀⣀⠤⣾⡿⠂⠀⢸⣿⣿⡇⢀⣾⡿⢱⡿⠁⠀⠐⠁⣿⣿⣿⣿⣿⣇⣿⣿⣿⣿⣿⡇⢸⡇
⠀⠀⠀⠀⠀⠙⢷⣴⠟⠋⠀⠀⠀⡾⠀⢰⠃⢈⣿⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⣄⡏⠀⠀⠀⢸⣿⡿⢀⣾⡿⣇⡾⠁⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⡇
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠃⢰⠇⠀⠸⢸⣿⣿⣿⢋⡀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠸⠃⠀⠀⠀⢸⣿⡇⣾⡿⠁⡸⢣⡀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⡇
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢺⣠⠏⢀⡀⠀⣸⣿⣿⡏⢀⣹⣶⣶⣶⣿⣯⡒⢆⡀⠀⠀⠀⠀⠀⠀⢸⣿⢳⡿⠀⢰⠇⠀⠙⢦⡀⢀⠀⠀⠸⣿⣿⣿⡿⣿⣿⣿⣿⣿⡃⣼⠁
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⠋⣠⠞⠀⣼⢿⣿⣿⣱⡿⠋⠁⢠⣴⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠸⣿⣿⠃⠀⠀⠀⠀⠀⠀⠙⢮⡄⠀⠀⢻⣿⣿⣿⢿⣿⣿⣿⣿⠀⣿⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡾⣁⠞⠁⢀⣾⣿⢸⣿⡿⡿⠀⠀⣰⣿⣿⣿⣿⡟⢻⡇⠀⠀⠀⠀⠀⠀⠀⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠲⣀⠈⢿⣿⣿⠈⣿⣿⣿⣿⢠⣿⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⠟⠁⢀⣴⣿⣿⣿⣾⣿⣿⠃⠀⢠⡟⠉⠙⠛⢻⣷⣿⡇⠀⠀⠀⠀⠀⠀⠀⠸⠃⠀⠀⠀⠀⢠⣤⣀⠀⡀⠀⠀⠀⠙⠚⢿⣿⣧⠸⣿⣿⣿⣾⣷⢰
⠀⠀⠀⠀⠀⠀⢀⣴⡿⢛⡥⢀⣴⣿⣿⣿⠟⠀⢹⣿⣧⠀⠀⠘⢇⠀⣀⡀⣸⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⣿⣿⣷⣿⣤⡀⠀⠀⠀⠈⢿⣿⣆⠸⣿⣿⣿⣿⣾
⠀⠀⠀⢀⣠⠾⠋⢉⣴⣫⣶⣿⣿⡿⠋⠁⠀⠀⠀⣿⣿⡄⠀⠈⢿⡀⠈⠉⢁⡼⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣷⣧⡀⠀⠈⢻⣿⣆⠹⣿⣿⣿⣿
⠀⠀⠀⠈⢱⣄⣾⣯⣿⣿⠟⠋⠀⠀⠀⠀⠀⣠⣼⠃⠙⢷⠀⠐⠚⠿⠖⠚⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⠛⠿⢿⣿⡏⢙⡏⠻⣿⣆⠀⠀⠻⣿⣷⣿⣿⣿⣿
⡀⠀⠀⣠⣿⣿⣿⠟⣹⣵⣤⣤⣤⣤⣤⣤⡼⢿⡏⠀⠀⠀⠙⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡃⠀⠀⠀⠀⢘⣿⣿⠇⠀⠹⣿⡆⠀⠀⢸⣏⣿⣿⣿⣿
⣡⣴⣾⣻⣿⠟⣩⣾⣿⣿⣿⣿⣿⣿⣿⡏⠀⣸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢉⣳⠀⢤⣀⣠⠞⢉⡿⠀⠀⠀⢹⣷⠀⢀⣾⣾⣿⣿⣿⣿
⣿⣿⢣⣿⣗⣼⣿⣿⡿⠿⢿⡟⠛⠛⠛⣷⠞⠋⠛⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣧⠀⠀⠀⠀⣠⠟⠀⠀⠀⠀⣸⠇⢀⣾⣾⣿⢿⣿⣿⣿
⣿⣿⠠⣿⠿⣿⡁⠈⠀⠀⠀⠑⣄⣠⠞⠁⠀⠀⠀⣀⡹⠶⠤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣒⠖⠋⠁⠀⠀⠀⠀⠞⠁⣰⣿⣿⠟⢡⣿⡿⠋⠀
⡋⠙⣸⠃⠀⠈⠻⣦⠀⢀⡴⣶⠟⠁⠀⠀⣀⡴⠚⠁⠀⠀⠀⠙⣆⠀⠀⠀⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⡿⢟⡥⣺⣿⠟⠀⠊⠀
⠀⠀⠃⠀⠀⠀⠀⢈⡿⠋⣰⠇⠀⠀⠐⠚⠁⠀⠀⠀⠀⣠⠴⠛⠋⠓⣆⠀⠈⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣛⣻⠵⠚⢁⡴⠟⠁⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣰⠏⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⣠⠖⠋⠀⠀⠀⠀⠀⢸⣦⠀⠈⠳⠤⠴⠖⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠊⠉⠉⠀⢀⣤⠶⠭⠄⠀⠀⠀⠀⠀⢀
⠀⠀⠀⠀⠀⡼⠁⠀⠀⠀⠘⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⠞⠉⠈⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⠋⠁⠀⠀⠀⠀⢀⣀⣀⠐⠃
⠀⠀⠀⠀⡼⠁⠀⠀⠀⠀⠀⡎⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠖⠋⠀⢀⠀⠀⢸⠀⠀⠀⡤⠤⠤⣤⡴⠒⠒⠒⢦⡖⠒⠲⠤⣄⣀⡀⠀⣀⣤⣾⡋⠉⠓⠶⠖⠚⠛⠉⠁⠀⠀⠀⢀
⠀⠀⠀⡸⠁⠀⠀⠀⠀⠀⠀⡇⠀⠈⢣⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠿⣦⡞⠀⢠⡞⠀⠀⠀⠈⡇⠀⠀⠀⢸⠇⠀⠀⠀⡇⠈⠉⠙⢿⣿⣿⣿⣆⠀⠀⠀⠀⢠⠀⠀⣠⣀⣠⣿
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡇⠀⡇⠀⢸⡓⢤⡀⠀⠀⠀⠀⠀⠀⢀⡴⢻⠉⢹⣿⠇⠀⠀⠀⠀⡇⠀⠀⠀⡸⠀⠀⠀⢰⡇⠀⠀⠀⢸⣿⣿⡿⠟⠳⠤⠖⠶⠤⣤⣴⣿⣌⢿⣿
⠀⠀⠀⠀⠀⠀⢀⠴⠋⠉⠁⡇⠀⠀⠀⠀⠇⠀⠉⠑⠶⢤⡤⠴⠞⠉⠄⣼⣠⠾⠿⠀⠀⠀⠀⠀⠃⠀⠀⠀⠃⠀⠀⠀⠸⠁⠀⠀⢰⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠦⡹
⠠⠂⠀⠀⠀⠀⢸⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣲⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡏⠘⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠁⠀⠀⠀⠀⠀⠙⠓⠤⢤⣤⣀⣀⣀⣀⣀⣠⡤⢖⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⢀⠀⠀⢀⡔⠉⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

View File

@@ -10,7 +10,7 @@
#include "flatbuffers_generated/RobotModule_generated.h"
inline std::unordered_map<int, int> MODULE_TO_NUM_CHANNELS_MAP {
{ModuleType_SPLITTER, 4},
{ModuleType_SPLITTER, 3}, // should be 4
{ModuleType_SERVO_1, 2},
{ModuleType_DC_MOTOR, 1},
{ModuleType_SERVO_2, 2},
@@ -19,7 +19,7 @@ inline std::unordered_map<int, int> MODULE_TO_NUM_CHANNELS_MAP {
{ModuleType_SPEAKER, 1},
{ModuleType_IMU, 1},
{ModuleType_DISTANCE_SENSOR, 1},
{ModuleType_SPLITTER_2, 4},
{ModuleType_SPLITTER_2, 3}, // should be 4
{ModuleType_SPLITTER_3, 3},
{ModuleType_SPLITTER_4, 3},
{ModuleType_SPLITTER_5, 3},

View File

@@ -1,4 +1,4 @@
idf_component_register(SRCS "DataLinkManager.cpp" "DataLinkRIP.cpp" "DataLinkScheduler.cpp" "DataLinkFrames.cpp"
PRIV_REQUIRES driver esp_event nvs_flash esp_netif rmt
PRIV_REQUIRES driver esp_event nvs_flash esp_netif rmt softUART
REQUIRES esp_timer ptrQueue
INCLUDE_DIRS "include")

View File

@@ -289,6 +289,15 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
return ESP_ERR_INVALID_RESPONSE;
}
// Preamble sanity check — if byte 0 is not START_OF_FRAME this buffer
// contains a merged frame, a partial capture, or line noise. Discard
// immediately rather than letting it propagate to the CRC checker.
if (data[0] != START_OF_FRAME){
ESP_LOGW(DEBUG_LINK_TAG, "Discarding frame on ch %d: bad preamble 0x%02X (expected 0x%02X)",
channel, data[0], START_OF_FRAME);
return ESP_ERR_INVALID_RESPONSE;
}
// ---- LUT fast-path for control frames ----
// Raw wire layout for control frames:
// [0] preamble
@@ -301,7 +310,8 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
// [12..] actual payload
// [-2..-1] CRC-16
bool is_control = IS_CONTROL_FRAME(data[5]);
if (is_control && recv_len >= (size_t)(CONTROL_FRAME_OVERHEAD + CONTROL_FRAME_HASH_SIZE)){
bool is_rip = (GET_TYPE(data[5]) == static_cast<uint8_t>(FrameType::RIP_TABLE_CONTROL));
if (is_control && !is_rip && recv_len >= (size_t)(CONTROL_FRAME_OVERHEAD + CONTROL_FRAME_HASH_SIZE)){
uint32_t peeked_hash = ((uint32_t)data[8] ) |
((uint32_t)data[9] << 8) |
((uint32_t)data[10] << 16) |
@@ -323,20 +333,36 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
// RIP control frames are handled internally replay them too
if (static_cast<FrameType>(GET_TYPE(cached_header.type_flag)) == FrameType::RIP_TABLE_CONTROL){
// Re-run the RIP update using the cached message
for (size_t i = 0; i < cached_message.size() - 1; i += 2){
uint8_t board_id = cached_message[i];
uint8_t hops = cached_message[i + 1];
RIPRow* entry = nullptr;
// Re-run the RIP update using the cached message (3-byte stride: board_id, hops, sum_of_hops)
for (size_t i = 0; i + 2 < cached_message.size(); i += RIP_WIRE_STRIDE){
uint8_t board_id = cached_message[i];
uint8_t hops = cached_message[i + 1];
uint8_t sum_of_hops = cached_message[i + 2];
// Skip routes about ourselves
if (board_id == this_board_id){
continue;
}
RIPRow* entry = nullptr;
if (rip_find_entry(board_id, &entry, true) != ESP_OK || entry == nullptr){
continue;
}
if (entry->valid == RIP_NEW_ROW){
rip_add_entry(board_id, hops + 1, channel, &entry);
rip_add_entry(board_id, hops + 1, sum_of_hops, channel, &entry);
} else {
rip_update_entry(hops + 1, channel, &entry);
rip_update_entry(hops + 1, sum_of_hops, channel, &entry);
}
}
// If this was a discovery request, send our routing table back
if (GET_FLAG(cached_header.type_flag) == FLAG_DISCOVERY){
esp_err_t disc_res = send_rip_frame(false, cached_header.sender_id);
if (disc_res != ESP_OK){
ESP_LOGE(DEBUG_LINK_TAG, "Failed to send back rip table to board %d (LUT path)", cached_header.sender_id);
}
}
return ESP_OK;
}
@@ -407,9 +433,8 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
return res;
}
// Control frame fully validated store in LUT for future replays
// Extract the hash that was embedded at data[8..11] (already validated in get_data_from_frame)
{
// Control frame fully validated store in LUT for future replays (skip RIP frames: their payload is dynamic)
if (!is_rip){
uint32_t validated_hash = ((uint32_t)data[8] ) |
((uint32_t)data[9] << 8) |
((uint32_t)data[10] << 16) |
@@ -424,10 +449,17 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
if (static_cast<FrameType>(GET_TYPE(header.type_flag)) == FrameType::RIP_TABLE_CONTROL){
ESP_LOGI(DEBUG_LINK_TAG, "Got a RIP frame from channel %d", channel);
for (size_t i = 0; i < message_size-1; i+=2){
uint8_t board_id = message->data()[i];
uint8_t hops = message->data()[i+1];
ESP_LOGI(DEBUG_LINK_TAG, "Received: board_id %d and number of hops %d on channel %d", board_id, hops, channel);
for (size_t i = 0; i + 2 < message_size; i += RIP_WIRE_STRIDE){
uint8_t board_id = message->data()[i];
uint8_t hops = message->data()[i + 1];
uint8_t sum_of_hops = message->data()[i + 2];
// Skip routes about ourselves - we already know we're 0 hops away from ourselves
if (board_id == this_board_id){
continue;
}
ESP_LOGI(DEBUG_LINK_TAG, "Received: board_id %d hops %d sum_of_hops %d on channel %d", board_id, hops, sum_of_hops, channel);
RIPRow* entry = nullptr;
@@ -443,15 +475,14 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
if (entry->valid == RIP_NEW_ROW){
//adding a new entry
rip_add_entry(board_id, hops + 1, channel, &entry);
rip_add_entry(board_id, hops + 1, sum_of_hops, channel, &entry);
} else {
//updating an entry
rip_update_entry(hops + 1, channel, &entry);
rip_update_entry(hops + 1, sum_of_hops, channel, &entry);
}
if (GET_FLAG(header.type_flag) == FLAG_DISCOVERY){
//discovery -> send routing table
// ESP_LOGI(DEBUG_LINK_TAG, "got discovery reply");
RIPRow_public row_queue = {
.info = entry->info,
.channel = entry->channel
@@ -461,7 +492,19 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
}
}
if (message_size == RIP_DISCOVERY_MESSAGE_SIZE){
// Print the finalized RIP table after processing all received rows
ESP_LOGI(DEBUG_LINK_TAG, "--- RIP Table (after update from channel %d) ---", channel);
for (size_t i = 0; i < RIP_MAX_ROUTES; i++){
RIPRow* row = nullptr;
if (rip_get_row(&row, i) == ESP_OK && row != nullptr){
ESP_LOGI(DEBUG_LINK_TAG, " [%d] board_id=%d hops=%d sum_of_hops=%d channel=%d ttl=%d",
i, row->info.board_id, row->info.hops, row->info.sum_of_hops, row->channel, row->ttl);
}
}
ESP_LOGI(DEBUG_LINK_TAG, "---------------------------------------------------");
if (GET_FLAG(header.type_flag) == FLAG_DISCOVERY){
res = send_rip_frame(false, header.sender_id);
if (res != ESP_OK){
ESP_LOGE(DEBUG_LINK_TAG, "Failed to send back rip table to board %d", header.sender_id);

View File

@@ -2,6 +2,7 @@
#include "BlockingQueue.h"
#include "Frames.h"
#include "RMTManager.h"
#include "SoftUARTManager.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <memory>
@@ -13,9 +14,15 @@
*
* @param board_id Board ID of the current board. Will be written to the NVM under key "board" if not already written.
*/
DataLinkManager::DataLinkManager(uint8_t board_id, uint8_t num_channels = MAX_CHANNELS){
DataLinkManager::DataLinkManager(uint8_t board_id, uint8_t num_channels, PhysicalLayerType phy_type){
//init table for this board and set up link layer priority queue
phys_comms = std::make_unique<RMTManager>(num_channels);
if (phy_type == PhysicalLayerType::SOFT_UART){
phys_comms = std::make_unique<SoftUARTManager>(num_channels);
ESP_LOGI(DEBUG_LINK_TAG, "Using SoftUART physical layer");
} else {
phys_comms = std::make_unique<RMTManager>(num_channels);
ESP_LOGI(DEBUG_LINK_TAG, "Using RMT physical layer");
}
if (phys_comms == nullptr){
ESP_LOGE(DEBUG_LINK_TAG, "RMT object was not created. Link layer communications will not function.");
return;

View File

@@ -27,6 +27,7 @@ void DataLinkManager::init_rip(){
rip_table[0].info = {
.board_id = this_board_id,
.hops = 0,
.sum_of_hops = 0,
};
rip_table[0].channel = MAX_CHANNELS + 1;
rip_table[0].ttl = RIP_TTL_START;
@@ -37,7 +38,7 @@ void DataLinkManager::init_rip(){
start_rip_tasks();
}
esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t channel, RIPRow** entry){
esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t sum_of_hops, uint8_t channel, RIPRow** entry){
if (entry == nullptr){
return ESP_FAIL;
}
@@ -49,16 +50,16 @@ esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t
(*entry)->channel = channel;
(*entry)->info = {
.board_id = board_id,
.hops = hops
.hops = hops,
.sum_of_hops = sum_of_hops,
};
(*entry)->ttl = RIP_TTL_START;
(*entry)->valid = 1;
// ESP_LOGI(DEBUG_LINK_TAG, "board_id %d now has hops %d from channel %d", (*entry)->info.board_id, (*entry)->info.hops, channel);
xSemaphoreGive((*entry)->row_sem);
rip_update_self_sum_of_hops();
if (uxQueueMessagesWaiting(manual_broadcasts) == 0){
bool dummy = true;
xQueueSend(manual_broadcasts, &dummy, 0); //new row - send broadcast
@@ -67,7 +68,32 @@ esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t
return ESP_OK;
}
/**
* @brief Recomputes and stores this board's own sum_of_hops (centrality score).
* Called whenever the routing table changes. No semaphores are held on entry.
*/
void DataLinkManager::rip_update_self_sum_of_hops(){
uint32_t total = 0;
for (size_t i = 1; i < RIP_MAX_ROUTES; i++){
if (xSemaphoreTake(rip_table[i].row_sem, pdMS_TO_TICKS(RIP_MAX_SEM_WAIT_MS)) != pdTRUE){
continue;
}
if (rip_table[i].valid == RIP_VALID_ROW && rip_table[i].info.hops <= RIP_MAX_HOPS){
total += rip_table[i].info.hops;
}
xSemaphoreGive(rip_table[i].row_sem);
}
// Clamp to uint8_t max — with RIP_MAX_ROUTES=10 and RIP_MAX_HOPS=15 the max is 9*15=135, fits fine.
if (xSemaphoreTake(rip_table[0].row_sem, pdMS_TO_TICKS(RIP_MAX_SEM_WAIT_MS)) == pdTRUE){
rip_table[0].info.sum_of_hops = (total > 255) ? 255 : static_cast<uint8_t>(total);
xSemaphoreGive(rip_table[0].row_sem);
}
}
esp_err_t DataLinkManager::rip_reset_entry_ttl(uint8_t board_id){
// ...existing code...
RIPRow* entry = nullptr;
esp_err_t res;
@@ -92,7 +118,7 @@ esp_err_t DataLinkManager::rip_reset_entry_ttl(uint8_t board_id){
return ESP_OK;
}
esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t channel, RIPRow** entry){
esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t new_sum_of_hops, uint8_t channel, RIPRow** entry){
if (entry == nullptr){
return ESP_FAIL; //board doesn't exist
}
@@ -102,22 +128,33 @@ esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t channel, RI
}
uint8_t old_hops = (*entry)->info.hops;
uint8_t old_sum_of_hops = (*entry)->info.sum_of_hops;
bool hops_improved = (new_hop < (*entry)->info.hops) || ((*entry)->info.hops == RIP_MAX_HOPS + 1);
if ((*entry)->info.hops >= new_hop && (*entry)->info.hops != RIP_MAX_HOPS + 1){ //no count to infinity if path is invalid
if (hops_improved){ //accept better paths and allow recovery from infinity
(*entry)->info.hops = new_hop;
(*entry)->info.sum_of_hops = new_sum_of_hops;
(*entry)->channel = channel;
// ESP_LOGI(DEBUG_LINK_TAG, "updated board_id %d now has hops %d from channel %d", (*entry)->info.board_id, (*entry)->info.hops, channel);
} else {
// Even if hops didn't improve, update the centrality score if it came from the same channel
if ((*entry)->channel == channel){
(*entry)->info.sum_of_hops = new_sum_of_hops;
}
}
(*entry)->ttl = RIP_TTL_START;
(*entry)->valid = 1;
// ESP_LOGI(DEBUG_LINK_TAG, "refreshed board_id %d ttl", (*entry)->info.board_id);
bool sum_of_hops_changed = (old_sum_of_hops != (*entry)->info.sum_of_hops);
xSemaphoreGive((*entry)->row_sem);
if (uxQueueMessagesWaiting(manual_broadcasts) == 0 && old_hops > new_hop && old_hops != RIP_MAX_HOPS + 1){
//if hops were changed, send broadcast (if there isn't already one manual broadcast request pending)
if (hops_improved || sum_of_hops_changed){
rip_update_self_sum_of_hops();
}
if (uxQueueMessagesWaiting(manual_broadcasts) == 0 && (old_hops > new_hop || old_hops == RIP_MAX_HOPS + 1 || sum_of_hops_changed)){
//if hops were changed (or recovered from infinity), or sum_of_hops changed, send broadcast
bool dummy = true;
xQueueSend(manual_broadcasts, &dummy, 0);
}
@@ -139,7 +176,7 @@ esp_err_t DataLinkManager::rip_find_entry(uint8_t board_id, RIPRow** entry, bool
if (xSemaphoreTake(rip_table[i].row_sem, pdMS_TO_TICKS(RIP_MAX_SEM_WAIT_MS)) != pdTRUE){
return ESP_FAIL;
}
if (rip_table[i].valid == RIP_VALID_ROW && rip_table[i].info.board_id == board_id){
if ((rip_table[i].valid == RIP_VALID_ROW || rip_table[i].valid == RIP_NEW_ROW) && rip_table[i].info.board_id == board_id){
*entry = &rip_table[i];
xSemaphoreGive(rip_table[i].row_sem);
// ESP_LOGI(DEBUG_LINK_TAG, "Found %d in table at row %d", board_id, i);
@@ -198,14 +235,11 @@ esp_err_t DataLinkManager::rip_get_row(RIPRow** entry, uint8_t row_num){
return ESP_ERR_INVALID_STATE;
}
if (rip_table[row_num].info.hops == RIP_MAX_HOPS + 1){
//invalid hop, decrement counter
rip_table[row_num].ttl_flush--;
if (rip_table[row_num].ttl_flush == 0){
rip_table[row_num].valid = RIP_INVALID_ROW;
xSemaphoreGive(rip_table[row_num].row_sem);
return ESP_FAIL;
}
if (rip_table[row_num].info.hops == RIP_MAX_HOPS + 1 && rip_table[row_num].ttl_flush == 0){
//flush countdown has expired, invalidate the row
rip_table[row_num].valid = RIP_INVALID_ROW;
xSemaphoreGive(rip_table[row_num].row_sem);
return ESP_FAIL;
}
static RIPRow row_snapshots[RIP_MAX_ROUTES];
@@ -228,8 +262,7 @@ esp_err_t DataLinkManager::rip_get_row(RIPRow** entry, uint8_t row_num){
* @return esp_err_t
*/
esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
//use the control frame for the demo (as the number of rows increase, we will need to use the generic frame)
//data will be [board_id (1), hops (1), board_id (2), hops (2), ...]
// Wire format: [board_id (1), hops (1), sum_of_hops (1), ...] (RIP_WIRE_STRIDE bytes per entry)
uint16_t message_idx = 0;
esp_err_t res;
@@ -240,7 +273,7 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
if(broadcast){
for (size_t channel = 0; channel < num_channels; channel++){
auto rip_message = std::make_unique<std::vector<uint8_t>>();
rip_message->resize(RIP_MAX_ROUTES * 2);
rip_message->resize(RIP_MAX_ROUTES * RIP_WIRE_STRIDE);
for (size_t i = 0; i < RIP_MAX_ROUTES; i++){
res = rip_get_row(&entry, i);
@@ -253,15 +286,15 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
continue;
}
// ESP_LOGI(DEBUG_LINK_TAG, "Found entry for board %d with hops %d", entry->info.board_id, entry->info.hops);
if (entry->channel == channel){
//poisoned reverse
rip_message->at(message_idx++) = entry->info.board_id;
rip_message->at(message_idx++) = RIP_MAX_HOPS + 1;
rip_message->at(message_idx++) = entry->info.sum_of_hops;
} else {
rip_message->at(message_idx++) = entry->info.board_id;
rip_message->at(message_idx++) = entry->info.hops;
rip_message->at(message_idx++) = entry->info.sum_of_hops;
}
}
@@ -299,7 +332,7 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
}
} else {
auto rip_message = std::make_unique<std::vector<uint8_t>>();
rip_message->resize(RIP_MAX_ROUTES * 2);
rip_message->resize(RIP_MAX_ROUTES * RIP_WIRE_STRIDE);
for (size_t i = 0; i < RIP_MAX_ROUTES; i++){
res = rip_get_row(&entry, i);
@@ -313,6 +346,7 @@ esp_err_t DataLinkManager::send_rip_frame(bool broadcast, uint8_t dest_id){
}
rip_message->data()[message_idx++] = entry->info.board_id;
rip_message->data()[message_idx++] = entry->info.hops;
rip_message->data()[message_idx++] = entry->info.sum_of_hops;
}
ESP_LOGI(DEBUG_LINK_TAG, "replying to discovery request to board %d", dest_id);
res = send(dest_id, std::move(rip_message), FrameType::RIP_TABLE_CONTROL, FLAG_DISCOVERY);
@@ -382,7 +416,7 @@ esp_err_t DataLinkManager::get_routing_table(RIPRow_public* table, size_t* table
return ESP_FAIL;
}
if (rip_table[i].valid == RIP_VALID_ROW){
table[i].info = rip_table[i].info;
table[i].info = rip_table[i].info; // copies board_id, hops, and sum_of_hops
table[i].channel = rip_table[i].channel;
curr_size++;
}
@@ -439,15 +473,20 @@ esp_err_t DataLinkManager::get_routing_table(RIPRow_public* table, size_t* table
continue;
}
if (link_layer_obj->rip_table[i].ttl != 0){
// link_layer_obj->rip_table[i].valid = RIP_INVALID_ROW;
// ESP_LOGI(DEBUG_LINK_TAG, "Entry %d now has ttl %d", i, link_layer_obj->rip_table[i].ttl);
// } else {
link_layer_obj->rip_table[i].ttl--;
if (link_layer_obj->rip_table[i].ttl == 0){
link_layer_obj->rip_table[i].info.hops = RIP_MAX_HOPS + 1;
link_layer_obj->rip_table[i].ttl_flush = RIP_FLUSH_COUNT;
broadcast = true;
}
} else if (link_layer_obj->rip_table[i].info.hops == RIP_MAX_HOPS + 1){
// TTL already zero and route is poisoned — count down the flush timer
if (link_layer_obj->rip_table[i].ttl_flush > 0){
link_layer_obj->rip_table[i].ttl_flush--;
}
if (link_layer_obj->rip_table[i].ttl_flush == 0){
link_layer_obj->rip_table[i].valid = RIP_INVALID_ROW;
}
}
xSemaphoreGive(link_layer_obj->rip_table[i].row_sem);

View File

@@ -275,15 +275,11 @@ esp_err_t DataLinkManager::scheduler_send(uint8_t channel){
esp_err_t DataLinkManager::scheduler_send_rmt(uint8_t channel, SchedulerMetadata frame, uint8_t* send_data, size_t frame_size, bool wait_for_tx_done){
esp_err_t res;
uint8_t channel_to_route = MAX_CHANNELS;
rmt_transmit_config_t config = {
.loop_count = 0,
.flags = {
.eot_level = 0, // typically 0 or 1, depending on your output idle level
}
};
// config is physical-layer specific; each IPhysicalLayer implementation
// uses its own internal configuration set at init time, so nullptr is fine.
if (frame.header.receiver_id == BROADCAST_ADDR){
// printf("Sending on channel %d\n", i);
res = phys_comms->send(send_data, frame_size, &config, channel);
res = phys_comms->send(send_data, frame_size, nullptr, channel);
} else {
res = route_frame(frame.header.receiver_id, &channel_to_route);
@@ -291,18 +287,12 @@ esp_err_t DataLinkManager::scheduler_send_rmt(uint8_t channel, SchedulerMetadata
ESP_LOGE(DEBUG_LINK_TAG, "Failed to find entry for %d", frame.header.receiver_id);
return ESP_FAIL;
}
// ESP_LOGI(DEBUG_LINK_TAG, "Sending frame %d on channel %d to board %d frag_info 0x%X", frame.header.seq_num, channel, frame.header.receiver_id, frame.header.frag_info);
res = phys_comms->send(send_data, frame_size, &config, channel_to_route);
// if (wait_for_tx_done){
// phys_comms->wait_until_send_complete(channel_to_route);
// }
res = phys_comms->send(send_data, frame_size, nullptr, channel_to_route);
}
if (res != ESP_OK){
ESP_LOGE(DEBUG_LINK_TAG, "Failed to send message");
return ESP_FAIL;
} else{
// ESP_LOGI(DEBUG_LINK_TAG, "Sent frame %d frag_info 0x%X", frame.header.seq_num, frame.header.frag_info);
}
return ESP_OK;

View File

@@ -10,12 +10,20 @@
#include "freertos/semphr.h"
#include "Frames.h"
#include "Tables.h"
#include "RMTManager.h"
#include "IPhysicalLayer.h"
#include "BlockingQueue.h"
#include "BlockingPriorityQueue.h"
#include <unordered_map>
#include "Scheduler.h"
/**
* @brief Selects which physical layer implementation to instantiate.
*/
enum class PhysicalLayerType : uint8_t {
RMT = 0, ///< Use the RMT-based Manchester-encoded physical layer (default)
SOFT_UART = 1, ///< Use the software-UART physical layer
};
#define DEBUG_LINK_TAG "LinkLayer"
#define CRC_POLYNOMIAL 0x1021
@@ -56,7 +64,7 @@ static const uint16_t crc16_table[256] = {
*/
class DataLinkManager{
public:
DataLinkManager(uint8_t board_id, uint8_t num_channels);
DataLinkManager(uint8_t board_id, uint8_t num_channels, PhysicalLayerType phy_type = PhysicalLayerType::SOFT_UART);
~DataLinkManager();
esp_err_t send(uint8_t dest_board, std::unique_ptr<std::vector<uint8_t>>&& buffer, FrameType type, uint8_t flag);
esp_err_t start_receive_frames(uint8_t curr_channel);
@@ -69,7 +77,7 @@ class DataLinkManager{
private:
uint8_t this_board_id = 0;
uint8_t num_channels = MAX_CHANNELS;
std::unique_ptr<RMTManager> phys_comms;
std::unique_ptr<IPhysicalLayer> phys_comms;
std::unordered_map<uint8_t, uint16_t> sequence_num_map;
SemaphoreHandle_t sequence_num_map_mutex;
@@ -93,10 +101,11 @@ class DataLinkManager{
void init_rip();
esp_err_t rip_find_entry(uint8_t board_id, RIPRow** entry, bool reserve_row);
esp_err_t rip_update_entry(uint8_t new_hop, uint8_t channel, RIPRow** entry);
esp_err_t rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t channel, RIPRow** entry);
esp_err_t rip_update_entry(uint8_t new_hop, uint8_t new_sum_of_hops, uint8_t channel, RIPRow** entry);
esp_err_t rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t sum_of_hops, uint8_t channel, RIPRow** entry);
esp_err_t rip_reset_entry_ttl(uint8_t board_id);
esp_err_t rip_get_row(RIPRow** entry, uint8_t row_num);
void rip_update_self_sum_of_hops();
//this is stored locally with metadata `ttl`
// std::unordered_map<uint8_t, RIPRow> rip_table; //using a hash map to store the routes to other boards - will be used as we scale up

View File

@@ -7,7 +7,7 @@
#define RIP_INVALID_ROW 0
#define RIP_VALID_ROW 1
#define RIP_NEW_ROW 2
#define RIP_BROADCAST_INTERVAL 30000 //broadcast every 30 seconds (30000ms)
#define RIP_BROADCAST_INTERVAL 15000 //broadcast every 30 seconds (15000ms)
// #define RIP_BROADCAST_INTERVAL 3000 //temp broadcast every 3 seconds (3000ms)
#define RIP_TTL_START 180 //seconds
#define RIP_MS_TO_SEC 1000 //1000 ms to 1 sec
@@ -15,13 +15,15 @@
#define RIP_FLUSH_COUNT 8 //flush after 8*30 seconds = 240 seconds
#define RIP_DISCOVERY_MESSAGE_SIZE 1
#define RIP_WIRE_STRIDE 3 // bytes per entry on the wire: board_id, hops, sum_of_hops
/**
* @brief Routing data to a board
* This struct will be sent to other boards
*/
typedef struct _rip_hops{
uint8_t board_id; //ID of the destination
uint8_t hops; //hop count to `board_id`
uint8_t board_id; //ID of the destination
uint8_t hops; //hop count to `board_id`
uint8_t sum_of_hops; //sum of hops from `board_id` to all other known boards (centrality score)
} RIPHop;
typedef struct _rip_row{
@@ -36,7 +38,7 @@ typedef struct _rip_row{
/**
* @brief Public facing RIP table row
*
*
*/
typedef struct _rip_public_row{
RIPHop info;

View File

@@ -353,7 +353,8 @@ void RMTManager::reset_encoder_context(rmt_encoder_context_t* ctx){
* @param config
* @return int
*/
esp_err_t RMTManager::send(uint8_t* data, size_t size, rmt_transmit_config_t* config, uint8_t channel_num){
esp_err_t RMTManager::send(uint8_t* data, size_t size, void* config_ptr, uint8_t channel_num){
rmt_transmit_config_t* config = static_cast<rmt_transmit_config_t*>(config_ptr);
if (channel_num >= num_channels){
ESP_LOGE(DEBUG_TAG, "send() error: invalid channel number");
return ESP_FAIL;

View File

@@ -0,0 +1,22 @@
#ifndef IPHYSICAL_LAYER_H
#define IPHYSICAL_LAYER_H
#include <cstddef>
#include <cstdint>
#include "esp_err.h"
#ifndef MAX_CHANNELS
#define MAX_CHANNELS 4
#endif
class IPhysicalLayer {
public:
virtual ~IPhysicalLayer() = default;
virtual esp_err_t send(uint8_t* data, size_t size, void* config, uint8_t channel_num) = 0;
virtual esp_err_t receive(uint8_t* recv_buf, size_t size, size_t* output_size, uint8_t channel_num) = 0;
virtual esp_err_t start_receiving(uint8_t channel_num) = 0;
virtual esp_err_t wait_until_send_complete(uint8_t channel_num) = 0;
};
#endif // IPHYSICAL_LAYER_H

View File

@@ -9,8 +9,11 @@
#include "driver/rmt_tx.h"
#include "driver/rmt_rx.h"
#include "soc/gpio_num.h"
#include "IPhysicalLayer.h"
#ifndef MAX_CHANNELS
#define MAX_CHANNELS 4
#endif
#define RMT_SYMBOL_BLOCK_SIZE 48
#define RECEIVE_BUFFER_SIZE 1024 //this is some value (we should probably set it to some packet size that we predetermine in some custom protocol:tm:)
@@ -74,12 +77,12 @@ typedef struct _rmt_channel{
* @author Justin Chow
*
*/
class RMTManager{
class RMTManager : public IPhysicalLayer {
public:
RMTManager(uint8_t num_channels);
~RMTManager();
esp_err_t send(uint8_t* data, size_t size, rmt_transmit_config_t* config, uint8_t channel_num); //temp function to send some string data
esp_err_t receive(uint8_t* recv_buf, size_t size, size_t* output_size, uint8_t channel_num);
~RMTManager() override;
esp_err_t send(uint8_t* data, size_t size, void* config, uint8_t channel_num) override;
esp_err_t receive(uint8_t* recv_buf, size_t size, size_t* output_size, uint8_t channel_num) override;
static size_t encoder_callback(const void* data, size_t data_size, size_t symbols_written,
size_t symbols_free, rmt_symbol_word_t* symbols, bool* done, void* arg);
@@ -87,9 +90,9 @@ class RMTManager{
static bool rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data);
static bool rmt_tx_done_callback(rmt_channel_handle_t channel, const rmt_tx_done_event_data_t *edata, void *user_data);
esp_err_t start_receiving(uint8_t channel_num);
esp_err_t start_receiving(uint8_t channel_num) override;
esp_err_t wait_until_send_complete(uint8_t channel_num);
esp_err_t wait_until_send_complete(uint8_t channel_num) override;
private:
uint8_t num_channels; //number of channels initalized
@@ -107,21 +110,21 @@ class RMTManager{
// rmt_channel_handle_t tx_chan;
const gpio_num_t tx_gpio[MAX_CHANNELS] = {GPIO_NUM_4, GPIO_NUM_5, GPIO_NUM_11, GPIO_NUM_13}; //using pins 4,5,11,13 for channels 0,1,2,3 respectively for tx
const gpio_num_t tx_gpio[MAX_CHANNELS] = {GPIO_NUM_4, GPIO_NUM_5, GPIO_NUM_11, GPIO_NUM_13};
QueueHandle_t memory_to_free;
//=====================RX=====================
rmt_channel_handle_t rx_chan;
const gpio_num_t rx_gpio[MAX_CHANNELS] = {GPIO_NUM_3, GPIO_NUM_6, GPIO_NUM_12, GPIO_NUM_14}; //using pins 3,6,12,14 for channels 0,1,2,3 respectively for rx
const gpio_num_t rx_gpio[MAX_CHANNELS] = {GPIO_NUM_3, GPIO_NUM_6, GPIO_NUM_12, GPIO_NUM_14};
//rx_receive_config
rmt_receive_config_t receive_config = {
.signal_range_min_ns = 200,
.signal_range_max_ns = 200 * 1000,
.flags = {
.en_partial_rx = true
.en_partial_rx = false // frames are max 121B = ~968 symbols, well within the 1024-symbol buffer
}
};
@@ -135,22 +138,21 @@ typedef struct _gpio_channel_pair {
static const GPIO_Channel_Pair gpio_channel_pairs[MAX_CHANNELS] = {
{
.tx_pin = GPIO_NUM_1,
.tx_pin = GPIO_NUM_4,
.rx_pin = GPIO_NUM_3
},
{
.tx_pin = GPIO_NUM_5,
.rx_pin = GPIO_NUM_6
},
{
.tx_pin = GPIO_NUM_11,
.rx_pin = GPIO_NUM_12
},
{
.tx_pin = GPIO_NUM_2,
.rx_pin = GPIO_NUM_13
},
{
.tx_pin = GPIO_NUM_3,
.rx_pin = GPIO_NUM_14
},
{
.tx_pin = GPIO_NUM_4,
.rx_pin = GPIO_NUM_15
.rx_pin = GPIO_NUM_14
}
}; //todo: use these pairs directly instead of the two arrays in the class definition above
// but ensure to update them first!!!
#endif //RMT_COMMUNICATIONS

View File

@@ -19,6 +19,7 @@
#define TAG "CommunicationRouter"
#define MAX_RX_BUFFER_SIZE 1024
#define WIRELESS_DEQUEUE_TIMEOUT_MS 3000
#define LEADER_ELECTION_PERIOD_MS 3000
CommunicationRouter::~CommunicationRouter() {
vTaskDelete(m_router_thread);
@@ -35,6 +36,16 @@ CommunicationRouter::~CommunicationRouter() {
}
}
[[noreturn]] void CommunicationRouter::leader_election_thread(void *args) {
const auto that = static_cast<CommunicationRouter *>(args);
while (true) {
that->m_last_leader_updated = std::chrono::system_clock::now();
that->update_leader();
vTaskDelay(pdMS_TO_TICKS(LEADER_ELECTION_PERIOD_MS));
}
}
[[noreturn]] void CommunicationRouter::link_layer_thread(void *args) {
const auto that = static_cast<CommunicationRouter *>(args);
@@ -61,21 +72,45 @@ void CommunicationRouter::update_leader() {
size_t table_size = RIP_MAX_ROUTES;
this->m_data_link_manager->get_routing_table(table, &table_size);
// Leader election (just get the highest id in rip)
// Compute our own sum_of_hops from our local routing table (row 0 in the
// internal table carries this, but it is also returned in the public table
// as the self-entry). We reconstruct it here directly from the peer rows.
uint32_t self_sum = 0;
std::vector<int> connected_module_ids;
uint8_t max = m_module_id;
for (int i = 0; i < table_size; i++) {
const auto id = table[i].info.board_id;
connected_module_ids.emplace_back(id);
if (id > max) { // todo: change this to be correct
max = id;
for (size_t i = 0; i < table_size; i++) {
if (table[i].info.board_id == m_module_id) continue; // skip self-row if present
connected_module_ids.emplace_back(table[i].info.board_id);
self_sum += table[i].info.hops;
}
const uint8_t self_sum_clamped = (self_sum > 255) ? 255 : static_cast<uint8_t>(self_sum);
// Leader election: elect the module with the lowest sum_of_hops (most central).
// Each module advertises its own sum_of_hops as the third byte of every RIP row,
// so every peer in the routing table carries the score that module computed
// locally from its own perspective — the true minimum total hop distance.
//
// Ties are broken by higher board_id for determinism.
uint8_t best_id = m_module_id;
uint8_t best_score = self_sum_clamped;
for (size_t i = 0; i < table_size; i++) {
const auto& row = table[i];
if (row.info.board_id == m_module_id) continue;
const uint8_t score = row.info.sum_of_hops;
if (score == 0) continue; // a remote board advertising sum_of_hops=0 is invalid — never trust it
if (score < best_score || (score == best_score && row.info.board_id > best_id)) {
best_score = score;
best_id = row.info.board_id;
}
}
const uint8_t elected = best_id;
// Leader has changed, we may need to change PC connection state
if (this->m_leader != max) {
ESP_LOGI(TAG, "Leader has changed from %d to %d", this->m_leader, max);
if (max == m_module_id) {
if (this->m_leader != elected) {
ESP_LOGI(TAG, "Leader has changed from %d to %d (sum_of_hops=%d)", this->m_leader, elected, best_score);
if (elected == m_module_id) {
m_pc_connection->connect();
m_lossless_server->startup();
m_lossy_server->startup();
@@ -86,7 +121,7 @@ void CommunicationRouter::update_leader() {
}
}
this->m_leader = max;
this->m_leader = elected;
if (this->m_leader == m_module_id) {
this->m_discovery_service->set_connected_boards(connected_module_ids);

View File

@@ -50,12 +50,15 @@ public:
xTaskCreate(router_thread, "router", 4096, this, 3, &this->m_router_thread);
xTaskCreate(link_layer_thread, "router_rmt", 4096, this, 3,
&this->m_link_layer_thread);
xTaskCreate(leader_election_thread, "router_election", 4096, this, 3,
&this->m_leader_election_thread);
}
~CommunicationRouter();
[[noreturn]] static void router_thread(void *args);
[[noreturn]] static void link_layer_thread(void *args);
[[noreturn]] static void leader_election_thread(void *args);
int send_msg(uint8_t *buffer, size_t length) const;
void update_leader();
void route(std::unique_ptr<std::vector<uint8_t>>&& buffer) const;
@@ -71,6 +74,7 @@ public:
private:
TaskHandle_t m_router_thread = nullptr;
TaskHandle_t m_link_layer_thread = nullptr;
TaskHandle_t m_leader_election_thread = nullptr;
ConfigManager &m_config_manager;
std::unique_ptr<IConnectionManager> m_pc_connection;
std::unique_ptr<IRPCServer> m_lossless_server;

View File

@@ -0,0 +1,4 @@
idf_component_register(SRCS "SoftUARTManager.cpp"
PRIV_REQUIRES driver esp_driver_uart esp_driver_gpio
REQUIRES rmt
INCLUDE_DIRS "include")

View File

@@ -0,0 +1,219 @@
#include "SoftUARTManager.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include <cstring>
#define TAG "SoftUART"
SoftUARTManager::SoftUARTManager(uint8_t num_channels) {
if (num_channels == 0 || num_channels > SUART_NUM_CHANNELS) {
ESP_LOGE(TAG, "Invalid num_channels %d (must be 1-%d)", num_channels, SUART_NUM_CHANNELS);
this->num_channels = 0;
return;
}
this->num_channels = num_channels;
memset(hw, 0, sizeof(hw));
memset(ch_status, SUART_CHANNEL_NOT_READY, sizeof(ch_status));
for (uint8_t i = 0; i < num_channels; i++) {
if (init_hw_channel(i) == ESP_OK) {
ch_status[i] = SUART_CHANNEL_READY;
} else {
ESP_LOGE(TAG, "Failed to init HW UART channel %d", i);
}
}
ESP_LOGI(TAG, "SoftUARTManager ready: %d HW UART channel(s)", num_channels);
}
SoftUARTManager::~SoftUARTManager() {
for (uint8_t i = 0; i < num_channels; i++) deinit_hw_channel(i);
}
esp_err_t SoftUARTManager::init_hw_channel(uint8_t idx) {
uart_port_t port = HW_PORT[idx];
hw[idx].port = port;
hw[idx].tx_gpio = HW_TX[idx];
hw[idx].rx_gpio = HW_RX[idx];
const uart_config_t cfg = {
.baud_rate = SUART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 0,
.source_clk = UART_SCLK_DEFAULT,
};
esp_err_t res = uart_param_config(port, &cfg);
if (res != ESP_OK) { ESP_LOGE(TAG, "HW[%d] uart_param_config: %s", idx, esp_err_to_name(res)); return res; }
res = uart_set_pin(port, (int)HW_TX[idx], (int)HW_RX[idx], UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
if (res != ESP_OK) { ESP_LOGE(TAG, "HW[%d] uart_set_pin: %s", idx, esp_err_to_name(res)); return res; }
res = uart_driver_install(port, SUART_RX_BUF_SIZE * 2, SUART_RX_BUF_SIZE * 2, 0, nullptr, 0);
if (res != ESP_OK) { ESP_LOGE(TAG, "HW[%d] uart_driver_install: %s", idx, esp_err_to_name(res)); return res; }
hw[idx].tx_done_sem = xSemaphoreCreateBinary();
if (hw[idx].tx_done_sem == nullptr) return ESP_ERR_NO_MEM;
hw[idx].status = SUART_CHANNEL_READY;
ESP_LOGI(TAG, "HW channel %d ready (UART%d TX=GPIO%d RX=GPIO%d)", idx, (int)port, (int)HW_TX[idx], (int)HW_RX[idx]);
return ESP_OK;
}
void SoftUARTManager::deinit_hw_channel(uint8_t idx) {
if (hw[idx].tx_done_sem) { vSemaphoreDelete(hw[idx].tx_done_sem); hw[idx].tx_done_sem = nullptr; }
if (hw[idx].status != SUART_CHANNEL_NOT_READY) uart_driver_delete(hw[idx].port);
hw[idx].status = SUART_CHANNEL_NOT_READY;
}
esp_err_t SoftUARTManager::send(uint8_t* data, size_t size, void* /*config*/, uint8_t channel_num) {
if (channel_num >= num_channels || data == nullptr || size == 0) return ESP_ERR_INVALID_ARG;
if (ch_status[channel_num] == SUART_CHANNEL_NOT_READY) return ESP_ERR_INVALID_STATE;
return send_hw(channel_num, data, size);
}
esp_err_t SoftUARTManager::receive(uint8_t* recv_buf, size_t size, size_t* output_size, uint8_t channel_num) {
if (channel_num >= num_channels || recv_buf == nullptr || output_size == nullptr) return ESP_FAIL;
if (ch_status[channel_num] != SUART_CHANNEL_LISTENING) return ESP_FAIL;
return receive_hw(channel_num, recv_buf, size, output_size);
}
esp_err_t SoftUARTManager::start_receiving(uint8_t channel_num) {
if (channel_num >= num_channels) return ESP_FAIL;
if (ch_status[channel_num] == SUART_CHANNEL_NOT_READY) return ESP_ERR_INVALID_STATE;
if (ch_status[channel_num] == SUART_CHANNEL_LISTENING) return ESP_OK;
uart_flush_input(hw[channel_num].port);
ch_status[channel_num] = SUART_CHANNEL_LISTENING;
return ESP_OK;
}
esp_err_t SoftUARTManager::wait_until_send_complete(uint8_t channel_num) {
if (channel_num >= num_channels) return ESP_FAIL;
SemaphoreHandle_t sem = hw[channel_num].tx_done_sem;
if (sem == nullptr) return ESP_FAIL;
if (xSemaphoreTake(sem, SUART_TX_DONE_WAIT_TICKS) != pdTRUE) {
ESP_LOGE(TAG, "wait_until_send_complete: timeout on channel %d", channel_num);
return ESP_FAIL;
}
uart_wait_tx_done(hw[channel_num].port, SUART_TX_DONE_WAIT_TICKS);
return ESP_OK;
}
esp_err_t SoftUARTManager::send_hw(uint8_t idx, uint8_t* data, size_t size) {
uart_wait_tx_done(hw[idx].port, SUART_TX_DONE_WAIT_TICKS);
int written = uart_write_bytes(hw[idx].port, reinterpret_cast<const char*>(data), size);
if (written < 0 || static_cast<size_t>(written) != size) {
ESP_LOGE(TAG, "HW[%d] uart_write_bytes returned %d", idx, written);
return ESP_FAIL;
}
xSemaphoreGive(hw[idx].tx_done_sem);
return ESP_OK;
}
esp_err_t SoftUARTManager::receive_hw(uint8_t idx, uint8_t* buf, size_t size, size_t* out) {
uart_port_t port = hw[idx].port;
// wait for at least a minimum complete frame
const size_t MIN_FRAME = 10;
size_t available = 0;
if (uart_get_buffered_data_len(port, &available) != ESP_OK || available < MIN_FRAME) {
return ESP_FAIL;
}
//scan for the preamble byte (0xAB)
uint8_t preamble = 0;
int discard_count = 0;
while (true) {
int n = uart_read_bytes(port, &preamble, 1, pdMS_TO_TICKS(2));
if (n < 1) return ESP_FAIL;
if (preamble == 0xAB) break;
discard_count++;
if (discard_count > (int)SUART_RX_BUF_SIZE) {
ESP_LOGW(TAG, "HW[%d] no preamble after %d bytes — flushing", idx, discard_count);
uart_flush_input(port);
return ESP_FAIL;
}
}
if (discard_count > 0) {
ESP_LOGD(TAG, "HW[%d] skipped %d noise byte(s) before preamble", idx, discard_count);
}
buf[0] = preamble;
// read the remaining 7 header bytes
int peeked = uart_read_bytes(port, buf + 1, 7, pdMS_TO_TICKS(20));
if (peeked < 7) {
ESP_LOGE(TAG, "HW[%d] timeout reading header (got %d of 7)", idx, peeked);
return ESP_FAIL;
}
// determine frame type and total length
bool is_control = (buf[5] & 0x80) != 0;
uint16_t len_field = (uint16_t)buf[6] | ((uint16_t)buf[7] << 8);
size_t total_frame_len;
if (is_control) {
total_frame_len = 8 + len_field + 2;
} else {
uint8_t hdr2[4];
int n2 = uart_read_bytes(port, hdr2, 4, pdMS_TO_TICKS(20));
if (n2 < 4) {
ESP_LOGE(TAG, "HW[%d] timeout reading generic header tail", idx);
return ESP_FAIL;
}
memcpy(buf + 8, hdr2, 4);
uint16_t data_len = (uint16_t)hdr2[2] | ((uint16_t)hdr2[3] << 8);
total_frame_len = 12 + data_len + 2;
}
if (total_frame_len > size || total_frame_len < 10 || total_frame_len > 256) {
ESP_LOGW(TAG, "HW[%d] unreasonable frame length %d — draining", idx, (int)total_frame_len);
// Drain remaining bytes of this bad frame so the next preamble scan
// doesn't find false 0xAB matches inside the body.
size_t hdr_consumed = is_control ? 8 : 12;
size_t to_drain = 0;
if (total_frame_len > hdr_consumed && total_frame_len <= 256) {
to_drain = total_frame_len - hdr_consumed;
} else {
size_t avail = 0;
uart_get_buffered_data_len(port, &avail);
to_drain = avail;
}
if (to_drain > 0) {
uint8_t drain_buf[128];
while (to_drain > 0) {
size_t chunk = (to_drain > sizeof(drain_buf)) ? sizeof(drain_buf) : to_drain;
int got = uart_read_bytes(port, drain_buf, chunk, pdMS_TO_TICKS(5));
if (got <= 0) break;
to_drain -= (size_t)got;
}
}
return ESP_FAIL;
}
// read the rest of the frame
size_t already_read = is_control ? 8 : 12;
size_t remaining = total_frame_len - already_read;
if (remaining > 0) {
int nr = uart_read_bytes(port, buf + already_read, remaining, pdMS_TO_TICKS(100));
if (nr < (int)remaining) {
ESP_LOGE(TAG, "HW[%d] incomplete frame: got %d of %d remaining bytes",
idx, nr, (int)remaining);
return ESP_FAIL;
}
}
*out = total_frame_len;
return ESP_OK;
}

View File

@@ -0,0 +1,59 @@
#ifndef SOFT_UART_MANAGER_H
#define SOFT_UART_MANAGER_H
#include "IPhysicalLayer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "soc/gpio_num.h"
#include <cstdint>
#include <cstddef>
#define SUART_NUM_CHANNELS 3
#define SUART_BAUD_RATE 115200
#define SUART_RX_BUF_SIZE 1024
#define SUART_TX_DONE_WAIT_TICKS pdMS_TO_TICKS(5000)
#define SUART_CHANNEL_NOT_READY 0x0
#define SUART_CHANNEL_READY 0x1
#define SUART_CHANNEL_LISTENING 0x2
typedef struct {
uart_port_t port;
gpio_num_t tx_gpio;
gpio_num_t rx_gpio;
uint8_t status;
SemaphoreHandle_t tx_done_sem;
} hw_channel_t;
class SoftUARTManager : public IPhysicalLayer {
public:
explicit SoftUARTManager(uint8_t num_channels);
~SoftUARTManager() override;
esp_err_t send(uint8_t* data, size_t size, void* config, uint8_t channel_num) override;
esp_err_t receive(uint8_t* recv_buf, size_t size, size_t* output_size, uint8_t channel_num) override;
esp_err_t start_receiving(uint8_t channel_num) override;
esp_err_t wait_until_send_complete(uint8_t channel_num) override;
private:
uint8_t num_channels;
hw_channel_t hw[SUART_NUM_CHANNELS];
uint8_t ch_status[SUART_NUM_CHANNELS];
esp_err_t init_hw_channel(uint8_t idx);
void deinit_hw_channel(uint8_t idx);
esp_err_t send_hw(uint8_t idx, uint8_t* data, size_t size);
esp_err_t receive_hw(uint8_t idx, uint8_t* buf, size_t size, size_t* out);
static constexpr gpio_num_t HW_TX[SUART_NUM_CHANNELS] = { GPIO_NUM_4, GPIO_NUM_5, GPIO_NUM_11 };
static constexpr gpio_num_t HW_RX[SUART_NUM_CHANNELS] = { GPIO_NUM_3, GPIO_NUM_6, GPIO_NUM_12 };
static constexpr uart_port_t HW_PORT[SUART_NUM_CHANNELS] = { UART_NUM_0, UART_NUM_1, UART_NUM_2 };
};
#endif // SOFT_UART_MANAGER_H

View File

@@ -12,10 +12,10 @@ dependencies:
idf:
source:
type: idf
version: 5.5.2
version: 5.4.2
direct_dependencies:
- espressif/mdns
- idf
manifest_hash: 03f5f8f0ee3b5b205949fa7dcdf902f4be49d846d055343c6b13f1a303516690
manifest_hash: d6911e14b94d3fd1a768cfd7760c9d19278efb8b4c5a517908dbc036afdfb2f3
target: esp32s3
version: 2.0.0

View File

@@ -69,7 +69,6 @@ std::string RemoteDebugging::get_coredump_summary() {
// Panic reason
char reason[200] = {};
if (esp_core_dump_get_panic_reason(reason, sizeof(reason)) == ESP_OK) {
ESP_LOGI(TAG, "Panic reason: %s", reason);
out += "Panic reason: ";
out += reason;
out += "\n";
@@ -88,8 +87,6 @@ std::string RemoteDebugging::get_coredump_summary() {
summary->ex_info.exc_vaddr);
out += line;
ESP_LOGI(TAG, "%s", line);
// Backtrace
out += "Backtrace:";
for (uint32_t i = 0; i < summary->exc_bt_info.depth && i < 16; i++) {
@@ -102,8 +99,6 @@ std::string RemoteDebugging::get_coredump_summary() {
}
out += "\n";
ESP_LOGI(TAG, "Backtrace: %s", out);
free(summary);
return out;
}

View File

@@ -6,20 +6,23 @@
#include "control/DCMotorActuator.h"
#include "driver/ledc.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include "flatbuffers_generated/SensorMessage_generated.h"
#include "util/number_utils.h"
#include "esp_log.h"
#define TAG "DCMotor"
#define LOW_DUTY 200
#define HIGH_DUTY 1000
#define FWD_CHANNEL LEDC_CHANNEL_1
#define REV_CHANNEL LEDC_CHANNEL_0
#define DEADZONE 0.05
#define KP 0.01
#define KP 0.05
#define KI 0
#define KD 0.020
#define MIN_PWM_DUTY 675
#define MAX_PWM_DUTY 1024
#define MAX_PWM_DUTY 1023
#define TICKS_PER_ROTATION 18.0
#define GEAR_RATIO 298
@@ -58,14 +61,9 @@ DCMotorActuator::DCMotorActuator() {
setup_encoder();
this->m_pid_task = nullptr;
this->m_target_angle = 0;
this->m_integral = 0;
this->m_last_error = 0;
// Pin the PID task to Core 1 so it doesn't compete with the RMT driver,
// which runs its ISR and internal tasks on Core 0.
xTaskCreatePinnedToCore(reinterpret_cast<TaskFunction_t>(pid_task), "pid_task", 3072, this, 1,
xTaskCreatePinnedToCore(reinterpret_cast<TaskFunction_t>(pid_task), "pid_task", 4096, this, 1,
&this->m_pid_task, 1);
}
@@ -73,20 +71,16 @@ DCMotorActuator::~DCMotorActuator() {
vTaskDelete(m_pid_task);
}
volatile int32_t encoder_ticks = 0;
volatile int8_t direction = 0;
static void IRAM_ATTR encoder_isr_handler(void *arg) {
auto *ticks = static_cast<volatile int32_t *>(arg);
const int a = gpio_get_level(static_cast<gpio_num_t>(DC_ENCODER_A));
const int b = gpio_get_level(static_cast<gpio_num_t>(DC_ENCODER_B));
// Determine direction
if (a == b) {
encoder_ticks++;
direction = 1;
(*ticks)++;
} else {
encoder_ticks--;
direction = -1;
(*ticks)--;
}
}
@@ -99,8 +93,12 @@ void DCMotorActuator::setup_encoder() {
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
gpio_install_isr_service(0);
gpio_isr_handler_add(static_cast<gpio_num_t>(DC_ENCODER_A), encoder_isr_handler, nullptr);
esp_err_t err = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
ESP_ERROR_CHECK(err);
}
gpio_isr_handler_add(static_cast<gpio_num_t>(DC_ENCODER_A), encoder_isr_handler,
reinterpret_cast<void *>(const_cast<int32_t *>(&m_encoder_ticks)));
}
void DCMotorActuator::actuate(uint8_t *cmd) {
@@ -108,51 +106,67 @@ void DCMotorActuator::actuate(uint8_t *cmd) {
// Will introduce latency, and means that we need to also send the size to the actuate function.
const auto *angleControlCmd =
Flatbuffers::AngleControlMessageBuilder::parse_angle_control_message(cmd);
this->m_target_angle = angleControlCmd->angle();
this->m_target_angle.store(angleControlCmd->angle(), std::memory_order_relaxed);
}
void DCMotorActuator::pid_task(char *args) {
void DCMotorActuator::pid_task(void *args) {
const auto that = reinterpret_cast<DCMotorActuator *>(args);
while (true) {
that->m_current_angle = (encoder_ticks * 360.0) / (GEAR_RATIO * TICKS_PER_ROTATION);
that->m_current_angle = (that->m_encoder_ticks * 360.0) / (GEAR_RATIO * TICKS_PER_ROTATION);
const double error = that->m_current_angle - that->m_target_angle;
const int64_t target = that->m_target_angle.load(std::memory_order_relaxed);
const double error = that->m_current_angle - target;
that->m_integral += error * KI;
const double detivative = (error - that->m_last_error) * KD;
const double derivative = (error - that->m_last_error) * KD;
that->m_last_error = error;
double control = error * KP + that->m_integral + detivative;
double control = error * KP + that->m_integral + derivative;
if (control > 1) {
control = 1;
} else if (control < -1) {
control = -1;
}
const auto pwm =
util::mapRange<double>(std::abs(control), 0, 1, MIN_PWM_DUTY, MAX_PWM_DUTY);
const uint32_t pwm = static_cast<uint32_t>(
util::mapRange<double>(std::abs(control), 0, 1, MIN_PWM_DUTY, MAX_PWM_DUTY));
if (std::abs(control) < DEADZONE) {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL, 0));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL));
esp_err_t err;
err = ledc_set_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL, 0);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_set_duty failed: %s", esp_err_to_name(err)); }
err = ledc_update_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_update_duty failed: %s", esp_err_to_name(err)); }
err = ledc_set_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL, 0);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_set_duty failed: %s", esp_err_to_name(err)); }
err = ledc_update_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_update_duty failed: %s", esp_err_to_name(err)); }
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL, 0));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL));
vTaskDelay(300 / portTICK_PERIOD_MS);
continue;
}
esp_err_t err;
if (control > 0) {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL, pwm));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL));
err = ledc_set_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL, pwm);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_set_duty failed: %s", esp_err_to_name(err)); }
err = ledc_update_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_update_duty failed: %s", esp_err_to_name(err)); }
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL, 0));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL));
err = ledc_set_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL, 0);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_set_duty failed: %s", esp_err_to_name(err)); }
err = ledc_update_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_update_duty failed: %s", esp_err_to_name(err)); }
} else {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL, pwm));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL));
err = ledc_set_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL, pwm);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_set_duty failed: %s", esp_err_to_name(err)); }
err = ledc_update_duty(LEDC_LOW_SPEED_MODE, REV_CHANNEL);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_update_duty failed: %s", esp_err_to_name(err)); }
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL, 0));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL));
err = ledc_set_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL, 0);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_set_duty failed: %s", esp_err_to_name(err)); }
err = ledc_update_duty(LEDC_LOW_SPEED_MODE, FWD_CHANNEL);
if (err != ESP_OK) { ESP_LOGE(TAG, "ledc_update_duty failed: %s", esp_err_to_name(err)); }
}
vTaskDelay(75 / portTICK_PERIOD_MS);
@@ -160,7 +174,6 @@ void DCMotorActuator::pid_task(char *args) {
}
std::vector<Flatbuffers::sensor_value> DCMotorActuator::get_sensor_data() {
// todo: this really needs to return a int32, should also return two sensor data items, one for target one for current
return {Flatbuffers::target_angle{(int16_t)m_current_angle},
Flatbuffers::current_angle{(int16_t)m_current_angle}};
}

View File

@@ -86,7 +86,7 @@ void Servo1Actuator::actuate(uint8_t *cmd) {
const auto *angleControlCmd =
Flatbuffers::AngleControlMessageBuilder::parse_angle_control_message(cmd);
m_target = static_cast<float>(angleControlCmd->angle());
// ESP_LOGI("Servo1", "new target: %d", angleControlCmd->angle());
ESP_LOGI("Servo1", "new target: %d", angleControlCmd->angle());
}
std::vector<Flatbuffers::sensor_value> Servo1Actuator::get_sensor_data() {

View File

@@ -6,6 +6,7 @@
#include "IActuator.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <atomic>
class DCMotorActuator final : public IActuator {
public:
@@ -16,14 +17,16 @@ class DCMotorActuator final : public IActuator {
private:
void setup_encoder();
static void pid_task(char *args);
static void pid_task(void *args);
double m_current_angle;
int64_t m_target_angle;
TaskHandle_t m_pid_task;
volatile int32_t m_encoder_ticks{0};
double m_integral;
double m_last_error;
double m_current_angle{0.0};
std::atomic<int64_t> m_target_angle{0};
TaskHandle_t m_pid_task{nullptr};
double m_integral{0.0};
double m_last_error{0.0};
};
#endif //SERVO1ACTUATOR_H
#endif //DCMOTORACTUATOR_H

View File

@@ -21,7 +21,6 @@ extern "C" [[noreturn]] void app_main(void) {
auto& config_manager = ConfigManager::get_instance(); // NOLINT - here for easily adding temporary config
config_manager.set_communication_method(CommunicationMethod::Wireless);
esp_log_set_vprintf(RemoteDebugging::custom_log_write);
const auto loop_manager = std::make_unique<LoopManager>();

View File

@@ -267,7 +267,7 @@ extern "C" [[noreturn]] void app_main(void) {
// uint8_t iteration = 0;
// const char* message = "THIS IS A TEXT MESSAGE";
uint8_t num_channels = 4;
uint8_t num_channels = 3;
std::unique_ptr<DataLinkManager> obj = std::make_unique<DataLinkManager>(BOARD_ID, num_channels);
if (obj->ready() != ESP_OK){

View File

@@ -4,18 +4,18 @@
| ------- | ----------------------------- |
| 1 | Servo PWM / DC Motor FWD PWM |
| 2 | DC Motor REV PWM |
| 3 | Ch. 0 RMT RX |
| 4 | Ch. 0 RMT TX |
| 5 | Ch. 1 RMT TX |
| 6 | Ch. 1 RMT RX |
| 3 | Ch. 0 UART0 RX |
| 4 | Ch. 0 UART0 TX |
| 5 | Ch. 1 UART1 TX |
| 6 | Ch. 1 UART1 RX |
| 7 | Ch. 0 90 Deg Orientation Pin |
| 8 | Ch. 0 180 Deg Orientation Pin |
| 9 | Ch. 0 270 Deg Orientation Pin |
| 10 | Ch. 0 0 Deg Orientation Pin |
| 11 | Ch. 2 RMT TX |
| 12 | Ch. 2 RMT RX |
| 13 | Ch. 3 RMT TX |
| 14 | Ch. 3 RMT RX |
| 11 | Ch. 2 UART2 TX |
| 12 | Ch. 2 UART2 RX |
| 13 | Ch. 3 SW-UART TX |
| 14 | Ch. 3 SW-UART RX |
| 15 | DC Motor Encoder A |
| 16 | DC Motor Encoder B |
| 17 | OLED SDA, Distance SDA |

307
sdkconfig
View File

@@ -1,7 +1,9 @@
#
# Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) 5.5.2 Project Configuration
# Espressif IoT Development Framework (ESP-IDF) 5.4.2 Project Configuration
#
CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000
CONFIG_SOC_MPU_REGIONS_MAX_NUM=8
CONFIG_SOC_ADC_SUPPORTED=y
CONFIG_SOC_UART_SUPPORTED=y
CONFIG_SOC_PCNT_SUPPORTED=y
@@ -9,7 +11,6 @@ CONFIG_SOC_PHY_SUPPORTED=y
CONFIG_SOC_WIFI_SUPPORTED=y
CONFIG_SOC_TWAI_SUPPORTED=y
CONFIG_SOC_GDMA_SUPPORTED=y
CONFIG_SOC_UHCI_SUPPORTED=y
CONFIG_SOC_AHB_GDMA_SUPPORTED=y
CONFIG_SOC_GPTIMER_SUPPORTED=y
CONFIG_SOC_LCDCAM_SUPPORTED=y
@@ -95,7 +96,6 @@ CONFIG_SOC_APB_BACKUP_DMA=y
CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y
CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y
CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y
CONFIG_SOC_CACHE_ACS_INVALID_STATE_ON_PANIC=y
CONFIG_SOC_CPU_CORES_NUM=2
CONFIG_SOC_CPU_INTR_NUM=32
CONFIG_SOC_CPU_HAS_FPU=y
@@ -124,6 +124,7 @@ CONFIG_SOC_GPIO_OUT_RANGE_MAX=48
CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000
CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y
CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3
CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y
CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8
CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8
CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y
@@ -146,10 +147,8 @@ CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y
CONFIG_SOC_I2S_SUPPORTS_PCM=y
CONFIG_SOC_I2S_SUPPORTS_PDM=y
CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y
CONFIG_SOC_I2S_SUPPORTS_PCM2PDM=y
CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y
CONFIG_SOC_I2S_SUPPORTS_PDM2PCM=y
CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2
CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y
CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4
CONFIG_SOC_I2S_SUPPORTS_TDM=y
CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y
@@ -171,8 +170,6 @@ CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3
CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y
CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1
CONFIG_SOC_MMU_PERIPH_NUM=1
CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000
CONFIG_SOC_MPU_REGIONS_MAX_NUM=8
CONFIG_SOC_PCNT_GROUPS=1
CONFIG_SOC_PCNT_UNITS_PER_GROUP=4
CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2
@@ -184,7 +181,7 @@ CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8
CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48
CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y
CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y
CONFIG_SOC_RMT_SUPPORT_ASYNC_STOP=y
CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y
CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y
CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y
CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y
@@ -233,7 +230,7 @@ CONFIG_SOC_SPI_SCT_SUPPORTED=y
CONFIG_SOC_SPI_SCT_REG_NUM=14
CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y
CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA
CONFIG_SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED=y
CONFIG_SOC_MEMSPI_SRC_FREQ_120M=y
CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y
CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y
CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y
@@ -256,18 +253,13 @@ CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32
CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16
CONFIG_SOC_TOUCH_SENSOR_VERSION=2
CONFIG_SOC_TOUCH_SENSOR_NUM=15
CONFIG_SOC_TOUCH_MIN_CHAN_ID=1
CONFIG_SOC_TOUCH_MAX_CHAN_ID=14
CONFIG_SOC_TOUCH_SUPPORT_BENCHMARK=y
CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y
CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y
CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y
CONFIG_SOC_TOUCH_SUPPORT_DENOISE_CHAN=y
CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3
CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y
CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1
CONFIG_SOC_TWAI_CONTROLLER_NUM=1
CONFIG_SOC_TWAI_MASK_FILTER_NUM=1
CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y
CONFIG_SOC_TWAI_BRP_MIN=2
CONFIG_SOC_TWAI_BRP_MAX=16384
@@ -281,8 +273,6 @@ CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y
CONFIG_SOC_UART_SUPPORT_APB_CLK=y
CONFIG_SOC_UART_SUPPORT_RTC_CLK=y
CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y
CONFIG_SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE=y
CONFIG_SOC_UHCI_NUM=1
CONFIG_SOC_USB_OTG_PERIPH_NUM=1
CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968
CONFIG_SOC_SHA_SUPPORT_DMA=y
@@ -325,7 +315,6 @@ CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y
CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y
CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y
CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y
CONFIG_SOC_CLK_LP_FAST_SUPPORT_XTAL_D2=y
CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y
CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y
CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y
@@ -352,7 +341,7 @@ CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y
CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y
CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y
CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y
CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE=y
CONFIG_SOC_SPI_MEM_SUPPORT_OPI_MODE=y
CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING=y
CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y
CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y
@@ -417,17 +406,6 @@ CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y
CONFIG_BOOTLOADER_PROJECT_VER=1
# end of Bootloader manager
#
# Application Rollback
#
# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set
# end of Application Rollback
#
# Recovery Bootloader and Rollback
#
# end of Recovery Bootloader and Rollback
CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set
@@ -437,8 +415,6 @@ CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
#
# Log
#
CONFIG_BOOTLOADER_LOG_VERSION_1=y
CONFIG_BOOTLOADER_LOG_VERSION=1
# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set
# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set
# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set
@@ -453,13 +429,6 @@ CONFIG_BOOTLOADER_LOG_LEVEL=3
# CONFIG_BOOTLOADER_LOG_COLORS is not set
CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y
# end of Format
#
# Settings
#
CONFIG_BOOTLOADER_LOG_MODE_TEXT_EN=y
CONFIG_BOOTLOADER_LOG_MODE_TEXT=y
# end of Settings
# end of Log
#
@@ -476,6 +445,7 @@ CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y
CONFIG_BOOTLOADER_WDT_ENABLE=y
# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set
CONFIG_BOOTLOADER_WDT_TIME_MS=9000
# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set
# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set
# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set
# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set
@@ -519,7 +489,6 @@ CONFIG_ESP_ROM_HAS_HAL_WDT=y
CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y
CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y
CONFIG_ESP_ROM_HAS_SPI_FLASH=y
CONFIG_ESP_ROM_HAS_SPI_FLASH_MMAP=y
CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y
CONFIG_ESP_ROM_HAS_NEWLIB=y
CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y
@@ -533,7 +502,6 @@ CONFIG_ESP_ROM_HAS_SW_FLOAT=y
CONFIG_ESP_ROM_HAS_VERSION=y
CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y
CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y
CONFIG_ESP_ROM_CONSOLE_OUTPUT_SECONDARY=y
#
# Boot ROM Behavior
@@ -633,18 +601,6 @@ CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y
# Component config
#
#
# !!! MINIMAL_BUILD is enabled !!!
#
#
# Only common components and those transitively required by the main component are listed
#
#
# If a component configuration is missing, please add it to the main component's requirements
#
#
# Console Library
#
@@ -656,11 +612,11 @@ CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y
#
#
# Legacy TWAI Driver Configurations
# TWAI Configuration
#
# CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK is not set
# CONFIG_TWAI_ISR_IN_IRAM is not set
CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y
# end of Legacy TWAI Driver Configurations
# end of TWAI Configuration
#
# Legacy ADC Driver Configuration
@@ -729,13 +685,6 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y
# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy Temperature Sensor Driver Configurations
#
# Legacy Touch Sensor Driver Configurations
#
# CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy Touch Sensor Driver Configurations
# end of Driver Configurations
#
@@ -771,7 +720,7 @@ CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
#
CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y
# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set
# CONFIG_GPTIMER_ISR_CACHE_SAFE is not set
# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set
CONFIG_GPTIMER_OBJ_CACHE_SAFE=y
# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:GPTimer Configurations
@@ -782,7 +731,6 @@ CONFIG_GPTIMER_OBJ_CACHE_SAFE=y
# CONFIG_I2C_ISR_IRAM_SAFE is not set
# CONFIG_I2C_ENABLE_DEBUG_LOG is not set
# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set
CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM=y
# end of ESP-Driver:I2C Configurations
#
@@ -801,10 +749,8 @@ CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM=y
#
# ESP-Driver:MCPWM Configurations
#
CONFIG_MCPWM_ISR_HANDLER_IN_IRAM=y
# CONFIG_MCPWM_ISR_CACHE_SAFE is not set
# CONFIG_MCPWM_ISR_IRAM_SAFE is not set
# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set
CONFIG_MCPWM_OBJ_CACHE_SAFE=y
# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:MCPWM Configurations
@@ -819,15 +765,9 @@ CONFIG_MCPWM_OBJ_CACHE_SAFE=y
#
# ESP-Driver:RMT Configurations
#
CONFIG_RMT_ENCODER_FUNC_IN_IRAM=y
CONFIG_RMT_TX_ISR_HANDLER_IN_IRAM=y
CONFIG_RMT_RX_ISR_HANDLER_IN_IRAM=y
# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set
# CONFIG_RMT_TX_ISR_CACHE_SAFE is not set
# CONFIG_RMT_RX_ISR_CACHE_SAFE is not set
CONFIG_RMT_OBJ_CACHE_SAFE=y
# CONFIG_RMT_ENABLE_DEBUG_LOG is not set
# CONFIG_RMT_ISR_IRAM_SAFE is not set
# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set
# CONFIG_RMT_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:RMT Configurations
#
@@ -852,29 +792,12 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:Temperature Sensor Configurations
#
# ESP-Driver:TWAI Configurations
#
# CONFIG_TWAI_ISR_IN_IRAM is not set
# CONFIG_TWAI_IO_FUNC_IN_IRAM is not set
# CONFIG_TWAI_ISR_CACHE_SAFE is not set
# CONFIG_TWAI_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:TWAI Configurations
#
# ESP-Driver:UART Configurations
#
# CONFIG_UART_ISR_IN_IRAM is not set
# end of ESP-Driver:UART Configurations
#
# ESP-Driver:UHCI Configurations
#
# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set
# CONFIG_UHCI_ISR_CACHE_SAFE is not set
# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:UHCI Configurations
#
# ESP-Driver:USB Serial/JTAG Configuration
#
@@ -957,8 +880,7 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024
#
# Peripheral Control
#
CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=y
CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=y
CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y
# end of Peripheral Control
#
@@ -978,28 +900,7 @@ CONFIG_XTAL_FREQ_40=y
CONFIG_XTAL_FREQ=40
# end of Main XTAL Config
#
# Power Supplier
#
#
# Brownout Detector
#
CONFIG_ESP_BROWNOUT_DET=y
CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set
CONFIG_ESP_BROWNOUT_DET_LVL=7
CONFIG_ESP_BROWNOUT_USE_INTR=y
# end of Brownout Detector
# end of Power Supplier
CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y
CONFIG_ESP_INTR_IN_IRAM=y
# end of Hardware Settings
#
@@ -1043,17 +944,13 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y
# CONFIG_ESP_PHY_RF_CAL_NONE is not set
# CONFIG_ESP_PHY_RF_CAL_FULL is not set
CONFIG_ESP_PHY_CALIBRATION_MODE=0
CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000
# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set
# CONFIG_ESP_PHY_RECORD_USED_TIME is not set
CONFIG_ESP_PHY_IRAM_OPT=y
# CONFIG_ESP_PHY_DEBUG is not set
# end of PHY
#
# Power Management
#
CONFIG_PM_SLEEP_FUNC_IN_IRAM=y
# CONFIG_PM_ENABLE is not set
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
@@ -1083,7 +980,6 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_SPEED_80M is not set
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM_SPEED=40
CONFIG_SPIRAM_BOOT_HW_INIT=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y
# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
@@ -1105,12 +1001,6 @@ CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set
# end of ESP Ringbuf
#
# ESP-ROM
#
CONFIG_ESP_ROM_PRINT_IN_IRAM=y
# end of ESP-ROM
#
# ESP Security Specific
#
@@ -1163,7 +1053,6 @@ CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32
CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0
# end of Trace memory
CONFIG_ESP_SYSTEM_IN_IRAM=y
# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set
CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y
# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
@@ -1186,18 +1075,15 @@ CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
CONFIG_ESP_MAIN_TASK_AFFINITY=0x0
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
# CONFIG_ESP_CONSOLE_UART_DEFAULT is not set
# CONFIG_ESP_CONSOLE_USB_CDC is not set
# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set
# CONFIG_ESP_CONSOLE_NONE is not set
# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set
CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y
CONFIG_ESP_CONSOLE_UART=y
CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
CONFIG_ESP_CONSOLE_UART_NUM=-1
CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=4
CONFIG_ESP_INT_WDT=y
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
CONFIG_ESP_INT_WDT_CHECK_CPU1=y
@@ -1211,13 +1097,28 @@ CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set
CONFIG_ESP_DEBUG_OCDAWARE=y
CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y
#
# Brownout Detector
#
CONFIG_ESP_BROWNOUT_DET=y
CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set
CONFIG_ESP_BROWNOUT_DET_LVL=7
# end of Brownout Detector
CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y
CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y
# end of ESP System Settings
#
# IPC (Inter-Processor Call)
#
CONFIG_ESP_IPC_ENABLE=y
CONFIG_ESP_IPC_TASK_STACK_SIZE=1280
CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y
CONFIG_ESP_IPC_ISR_ENABLE=y
@@ -1226,7 +1127,6 @@ CONFIG_ESP_IPC_ISR_ENABLE=y
#
# ESP Timer (High Resolution Timer)
#
CONFIG_ESP_TIMER_IN_IRAM=y
# CONFIG_ESP_TIMER_PROFILING is not set
CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y
CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y
@@ -1269,12 +1169,10 @@ CONFIG_ESP_WIFI_IRAM_OPT=y
CONFIG_ESP_WIFI_RX_IRAM_OPT=y
CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y
CONFIG_ESP_WIFI_ENABLE_SAE_PK=y
CONFIG_ESP_WIFI_ENABLE_SAE_H2E=y
CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y
CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y
# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set
CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50
# CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT is not set
CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10
CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15
# CONFIG_ESP_WIFI_FTM_ENABLE is not set
@@ -1299,10 +1197,10 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y
#
# CONFIG_ESP_WIFI_WPS_STRICT is not set
# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set
# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set
# end of WPS Configuration Options
# CONFIG_ESP_WIFI_DEBUG_PRINT is not set
# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set
CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y
# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set
# end of Wi-Fi
@@ -1401,7 +1299,6 @@ CONFIG_FREERTOS_DEBUG_OCDAWARE=y
CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
CONFIG_FREERTOS_NUMBER_OF_CORES=2
CONFIG_FREERTOS_IN_IRAM=y
# end of FreeRTOS
#
@@ -1413,6 +1310,8 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y
# CONFIG_HAL_ASSERTION_ENABLE is not set
CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2
CONFIG_HAL_WDT_USE_ROM_IMPL=y
CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y
CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y
# end of Hardware Abstraction Layer (HAL) and Low Level (LL)
#
@@ -1433,9 +1332,6 @@ CONFIG_HEAP_TRACING_OFF=y
#
# Log
#
CONFIG_LOG_VERSION_1=y
# CONFIG_LOG_VERSION_2 is not set
CONFIG_LOG_VERSION=1
#
# Log Level
@@ -1473,15 +1369,6 @@ CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31
CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y
# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set
# end of Format
#
# Settings
#
CONFIG_LOG_MODE_TEXT_EN=y
CONFIG_LOG_MODE_TEXT=y
# end of Settings
CONFIG_LOG_IN_IRAM=y
# end of Log
#
@@ -1489,6 +1376,7 @@ CONFIG_LOG_IN_IRAM=y
#
CONFIG_LWIP_ENABLE=y
CONFIG_LWIP_LOCAL_HOSTNAME="espressif"
# CONFIG_LWIP_NETIF_API is not set
CONFIG_LWIP_TCPIP_TASK_PRIO=18
# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set
# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set
@@ -1600,7 +1488,6 @@ CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5
CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5
CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3
CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10
# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set
# CONFIG_LWIP_PPP_SUPPORT is not set
# CONFIG_LWIP_SLIP_SUPPORT is not set
@@ -1635,7 +1522,6 @@ CONFIG_LWIP_DNS_MAX_HOST_IP=1
CONFIG_LWIP_DNS_MAX_SERVERS=3
# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set
# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set
# CONFIG_LWIP_USE_ESP_GETADDRINFO is not set
# end of DNS
CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7
@@ -1656,9 +1542,6 @@ CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y
CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y
# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set
# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set
CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_NONE=y
# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_DEFAULT is not set
# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_CUSTOM is not set
CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y
# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set
# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set
@@ -1693,7 +1576,6 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set
# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y
# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set
CONFIG_MBEDTLS_PKCS7_C=y
# end of mbedTLS v3.x related
@@ -1813,23 +1695,20 @@ CONFIG_MBEDTLS_FS_IO=y
# end of mbedTLS
#
# LibC
# Newlib
#
CONFIG_LIBC_NEWLIB=y
CONFIG_LIBC_MISC_IN_IRAM=y
CONFIG_LIBC_LOCKS_PLACE_IN_IRAM=y
CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF=y
# CONFIG_LIBC_STDOUT_LINE_ENDING_LF is not set
# CONFIG_LIBC_STDOUT_LINE_ENDING_CR is not set
# CONFIG_LIBC_STDIN_LINE_ENDING_CRLF is not set
# CONFIG_LIBC_STDIN_LINE_ENDING_LF is not set
CONFIG_LIBC_STDIN_LINE_ENDING_CR=y
# CONFIG_LIBC_NEWLIB_NANO_FORMAT is not set
CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y
# CONFIG_LIBC_TIME_SYSCALL_USE_RTC is not set
# CONFIG_LIBC_TIME_SYSCALL_USE_HRT is not set
# CONFIG_LIBC_TIME_SYSCALL_USE_NONE is not set
# end of LibC
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set
# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set
# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set
CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y
# CONFIG_NEWLIB_NANO_FORMAT is not set
CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y
# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set
# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set
# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set
# end of Newlib
CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y
@@ -1891,7 +1770,6 @@ CONFIG_SPI_FLASH_HPM_DC_AUTO=y
CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50
# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set
# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set
CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM=y
# end of Optional and Experimental Features (READ DOCS FIRST)
# end of Main Flash configuration
@@ -1917,13 +1795,13 @@ CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192
#
# Auto-detect flash chips
#
CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORT_ENABLED=y
CONFIG_SPI_FLASH_VENDOR_GD_SUPPORT_ENABLED=y
CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORT_ENABLED=y
CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORT_ENABLED=y
CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORT_ENABLED=y
CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORT_ENABLED=y
CONFIG_SPI_FLASH_VENDOR_TH_SUPPORT_ENABLED=y
CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED=y
CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED=y
CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED=y
CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED=y
CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED=y
CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED=y
CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED=y
CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y
CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y
CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y
@@ -2008,7 +1886,6 @@ CONFIG_MDNS_PREDEF_NETIF_AP=y
# Deprecated options for backward compatibility
# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set
# CONFIG_NO_BLOBS is not set
# CONFIG_APP_ROLLBACK_ENABLE is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
@@ -2016,6 +1893,7 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
CONFIG_LOG_BOOTLOADER_LEVEL=3
# CONFIG_APP_ROLLBACK_ENABLE is not set
# CONFIG_FLASH_ENCRYPTION_ENABLED is not set
# CONFIG_FLASHMODE_QIO is not set
# CONFIG_FLASHMODE_QOUT is not set
@@ -2039,8 +1917,7 @@ CONFIG_STACK_CHECK_NONE=y
# CONFIG_WARN_WRITE_STRINGS is not set
# CONFIG_EXTERNAL_COEX_ENABLE is not set
# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set
# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set
# CONFIG_MCPWM_ISR_IRAM_SAFE is not set
# CONFIG_MCPWM_ISR_IN_IRAM is not set
# CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
@@ -2051,26 +1928,6 @@ CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y
# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set
# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set
CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024
CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y
CONFIG_BROWNOUT_DET=y
CONFIG_ESP32S3_BROWNOUT_DET=y
CONFIG_BROWNOUT_DET_LVL_SEL_7=y
CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y
# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set
CONFIG_BROWNOUT_DET_LVL=7
CONFIG_ESP32S3_BROWNOUT_DET_LVL=7
CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y
CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set
CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
@@ -2089,13 +1946,11 @@ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=160
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_MAIN_TASK_STACK_SIZE=3584
CONFIG_CONSOLE_UART_DEFAULT=y
# CONFIG_CONSOLE_UART_DEFAULT is not set
# CONFIG_CONSOLE_UART_CUSTOM is not set
# CONFIG_CONSOLE_UART_NONE is not set
# CONFIG_ESP_CONSOLE_UART_NONE is not set
CONFIG_CONSOLE_UART=y
CONFIG_CONSOLE_UART_NUM=0
CONFIG_CONSOLE_UART_BAUDRATE=115200
CONFIG_CONSOLE_UART_NUM=-1
CONFIG_INT_WDT=y
CONFIG_INT_WDT_TIMEOUT_MS=300
CONFIG_INT_WDT_CHECK_CPU1=y
@@ -2107,6 +1962,24 @@ CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set
CONFIG_ESP32S3_DEBUG_OCDAWARE=y
CONFIG_BROWNOUT_DET=y
CONFIG_ESP32S3_BROWNOUT_DET=y
CONFIG_BROWNOUT_DET_LVL_SEL_7=y
CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y
# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set
# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set
# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set
CONFIG_BROWNOUT_DET_LVL=7
CONFIG_ESP32S3_BROWNOUT_DET_LVL=7
CONFIG_IPC_TASK_STACK_SIZE=1280
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_ESP32_WIFI_ENABLED=y
@@ -2141,6 +2014,7 @@ CONFIG_WPA_MBEDTLS_TLS_CLIENT=y
# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set
# CONFIG_WPA_WPS_STRICT is not set
# CONFIG_WPA_DEBUG_PRINT is not set
# CONFIG_WPA_TESTING_OPTIONS is not set
CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y
# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set
# CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE is not set
@@ -2179,22 +2053,11 @@ CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set
CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
# CONFIG_PPP_SUPPORT is not set
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set
# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set
# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set
CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y
# CONFIG_NEWLIB_NANO_FORMAT is not set
CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y
CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y
CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y
# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set
# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set
# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set
# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set
# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set
# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set
# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072