diff --git a/.gitignore b/.gitignore index 289dc11..317b69c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ sdkconfig.old .vscode/* /.cache +test/build/* \ No newline at end of file diff --git a/components/dataLink/CMakeLists.txt b/components/dataLink/CMakeLists.txt index 5ce31f1..60a931a 100644 --- a/components/dataLink/CMakeLists.txt +++ b/components/dataLink/CMakeLists.txt @@ -1,3 +1,4 @@ -idf_component_register(SRCS "DataLinkManager.cpp" +idf_component_register(SRCS "DataLinkManager.cpp" "DataLinkRIP.cpp" "DataLinkScheduler.cpp" "DataLinkFrames.cpp" PRIV_REQUIRES driver esp_event nvs_flash esp_netif rmt + REQUIRES esp_timer INCLUDE_DIRS "include") diff --git a/components/dataLink/DataLinkFrames.cpp b/components/dataLink/DataLinkFrames.cpp new file mode 100644 index 0000000..b2a73c0 --- /dev/null +++ b/components/dataLink/DataLinkFrames.cpp @@ -0,0 +1,377 @@ +#include "DataLinkManager.h" +#include "esp_log.h" + +ControlFrame make_control_frame_from_header(const FrameHeader& header) { + ControlFrame frame{}; + frame.preamble = header.preamble; + frame.sender_id = header.sender_id; + frame.receiver_id = header.receiver_id; + frame.seq_num = header.seq_num; + frame.type_flag = header.type_flag; + frame.data_len = header.data_len; + frame.crc_16 = header.crc_16; + return frame; +} + +GenericFrame make_generic_frame_from_header(const FrameHeader& header) { + GenericFrame frame{}; + frame.preamble = header.preamble; + frame.sender_id = header.sender_id; + frame.receiver_id = header.receiver_id; + frame.seq_num = header.seq_num; + frame.type_flag = header.type_flag; + frame.total_frag = (header.frag_info >> 16) & 0xFFFF; + frame.frag_num = (header.frag_info) & 0xFFFF; + frame.data_len = header.data_len; + frame.crc_16 = header.crc_16; + return frame; +} + +esp_err_t DataLinkManager::store_fragment(GenericFrame* fragment, uint8_t channel){ + if (fragment == nullptr){ + return ESP_ERR_INVALID_ARG; + } + + if (fragment->data_len == 0){ + return ESP_ERR_INVALID_ARG; + } + + if (fragment->receiver_id != this_board_id){ + return ESP_ERR_INVALID_ARG; + } + + if (fragment_map[fragment->receiver_id].find(fragment->seq_num) == fragment_map[fragment->receiver_id].end()){ + FragmentMetadata& metadata = fragment_map[fragment->receiver_id][fragment->seq_num]; + metadata.num_fragments_rx = 0; + + metadata.fragments.reserve(fragment->total_frag); + for (uint16_t i = 0; i < fragment->total_frag; i++){ + metadata.fragments.push_back(GenericFrame{}); + } + } + + FragmentMetadata& metadata = fragment_map[fragment->receiver_id][fragment->seq_num]; + if (fragment->frag_num >= metadata.fragments.size()){ + return ESP_ERR_INVALID_STATE; + } + + if (metadata.fragments[fragment->frag_num].data_len ==0){ + metadata.fragments[fragment->frag_num] = *fragment; + metadata.num_fragments_rx++; + } + + if (metadata.num_fragments_rx == metadata.fragments.size()){ + //all fragments received + return complete_fragment(fragment->receiver_id, fragment->seq_num, channel); + } + + return ESP_OK; +} + +/** + * @brief Removes the corresponding entry from `fragment_map` and pushes the data onto `async_receive_queue` + * + * @param board_id + * @param sequence_num + * @return esp_err_t + */ +esp_err_t DataLinkManager::complete_fragment(uint16_t board_id, uint16_t sequence_num, uint8_t channel){ + if (fragment_map[board_id].find(sequence_num) == fragment_map[board_id].end()){ + return ESP_ERR_NOT_FOUND; + } + + FragmentMetadata& metadata = fragment_map[board_id][sequence_num]; + if (metadata.num_fragments_rx != metadata.fragments.size()){ + return ESP_ERR_INVALID_STATE; + } + + Rx_Metadata rx; + uint16_t total_data_len = metadata.num_fragments_rx*MAX_CONTROL_DATA_LEN; //max data size with n fragments + uint8_t* combined_data = (uint8_t*)pvPortMalloc(total_data_len); + rx.data_len = total_data_len; + if (combined_data == nullptr){ + return ESP_ERR_NO_MEM; + } + + rx.data = combined_data; + uint16_t prev_index = 0; + for (size_t i = 0; i < metadata.num_fragments_rx; i++){ + memcpy(&combined_data[prev_index], metadata.fragments[i].data, metadata.fragments[i].data_len); + prev_index += metadata.fragments[i].data_len; + } + + rx.data_len = prev_index; + + if (async_rx_queue_mutex[channel] == nullptr){ + return ESP_FAIL; + } + + GenericFrame frame = metadata.fragments[0]; + + rx.header = { + .preamble = START_OF_FRAME, + .sender_id = frame.sender_id, + .receiver_id = frame.receiver_id, + .seq_num = frame.seq_num, + .type_flag = frame.type_flag, + .frag_info = (uint32_t)((frame.total_frag << 16) | frame.frag_num), + .data_len = prev_index, + .crc_16 = 0 + }; + + if (xSemaphoreTake(async_rx_queue_mutex[channel], pdMS_TO_TICKS(ASYNC_QUEUE_WAIT_TICKS)) != pdTRUE){ + vPortFree(combined_data); + return ESP_ERR_TIMEOUT; + } + + async_receive_queue[channel].push(rx); + + xSemaphoreGive(async_rx_queue_mutex[channel]); + + fragment_map[board_id].erase(sequence_num); + + if (fragment_map[board_id].empty()) { + fragment_map.erase(board_id); + } + + return ESP_OK; +} + +/** + * @brief Checks the channel receive queue for any received frames. If there is, return the first frame's data size + * + * @param frame_size Size of the data + * @param header Header information of the combined generic frames + * + * @return esp_err_t + */ +esp_err_t DataLinkManager::async_receive_info(uint16_t* frame_size, FrameHeader* header, uint8_t channel){ + if (frame_size == nullptr || header == nullptr){ + return ESP_ERR_INVALID_ARG; + } + + Rx_Metadata top; + if (xSemaphoreTake(async_rx_queue_mutex[channel], pdMS_TO_TICKS(ASYNC_QUEUE_WAIT_TICKS)) != pdTRUE){ + return ESP_ERR_TIMEOUT; + } + if (async_receive_queue[channel].size() == 0){ + xSemaphoreGive(async_rx_queue_mutex[channel]); + + *frame_size = 0; + + return ESP_OK; + } + top = async_receive_queue[channel].front(); + + xSemaphoreGive(async_rx_queue_mutex[channel]); + + *frame_size = top.data_len; + + *header = top.header; + + return ESP_OK; +} + +/** + * @brief Get the first frame's data + * + * @param data Char array of the actual combined data + * @param data_len Combined data length + * @param header Header information of returning frame + * + */ +esp_err_t DataLinkManager::async_receive(uint8_t* data, uint16_t data_len, FrameHeader* header, uint8_t channel){ + if (data == nullptr || header == nullptr){ + return ESP_ERR_INVALID_ARG; + } + + if (data_len == 0){ + return ESP_ERR_INVALID_ARG; + } + + Rx_Metadata top; + if (xSemaphoreTake(async_rx_queue_mutex[channel], pdMS_TO_TICKS(ASYNC_QUEUE_WAIT_TICKS)) != pdTRUE){ + return ESP_ERR_TIMEOUT; + } + + if (async_receive_queue[channel].size() == 0){ + xSemaphoreGive(async_rx_queue_mutex[channel]); + return ESP_ERR_NOT_FOUND; + } + + top = async_receive_queue[channel].front(); + async_receive_queue[channel].pop(); + + xSemaphoreGive(async_rx_queue_mutex[channel]); + + if (data_len < top.data_len){ + vPortFree(top.data); + return ESP_ERR_INVALID_ARG; + } + + *header = top.header; + + memcpy(data, top.data, top.data_len); + vPortFree(top.data); + + return ESP_OK; +} + +esp_err_t DataLinkManager::receive_rmt(uint8_t channel){ + uint16_t data_len = MAX_CONTROL_DATA_LEN+GENERIC_FRAME_OVERHEAD; //max possible data len + uint8_t data[data_len]; + memset(data, 0, data_len); + + size_t recv_len = 0; + + esp_err_t res = phys_comms->receive(data, data_len, &recv_len, channel); + + if (res != ESP_OK){ + // ESP_LOGE(DEBUG_LINK_TAG, "RMT Failed to receive - recieve_rmt"); + return ESP_ERR_TIMEOUT; + } + + if (recv_len > MAX_CONTROL_DATA_LEN + GENERIC_FRAME_OVERHEAD){ + ESP_LOGE(DEBUG_LINK_TAG, "Received frame is too large to be control or generic"); + return ESP_ERR_INVALID_RESPONSE; + } + + if (recv_len < CONTROL_FRAME_OVERHEAD) { + //Frame is too small + return ESP_ERR_INVALID_RESPONSE; + } + + uint8_t message[MAX_CONTROL_DATA_LEN]; + memset(message, 0, sizeof(message)); + size_t message_size = 0; + FrameHeader header; + + res = get_data_from_frame(data, recv_len, message, &message_size, &header); + if (res != ESP_OK){ + // print_buffer_binary(message, message_size); + return res; + } + + // print_buffer_binary(message, message_size); + + if (!IS_CONTROL_FRAME(header.type_flag)){ + //Handle generic frame fragment + GenericFrame frame = make_generic_frame_from_header(header); + if (message_size > MAX_CONTROL_DATA_LEN){ + return ESP_FAIL; + } + + memcpy(frame.data, message, message_size); + esp_err_t res = store_fragment(&frame, channel); + return res; + } + + //control frame handling: - TODO: clean up :) + memcpy(data, message, message_size); + ESP_LOGI(DEBUG_LINK_TAG, "Received frame of type 0x%X destined for board %d", GET_TYPE(header.type_flag), header.receiver_id); + + //check for a rip frame + if (static_cast(GET_TYPE(header.type_flag)) == FrameType::RIP_TABLE_CONTROL){ + // printf("Got a RIP frame\n"); + + for (size_t i = 0; i < message_size-1; i+=2){ + uint8_t board_id = message[i]; + uint8_t hops = message[i+1]; + ESP_LOGI(DEBUG_LINK_TAG, "Received: board_id %d and number of hops %d on channel %d", board_id, hops, channel); + + RIPRow* entry = nullptr; + + res = rip_find_entry(board_id, &entry, true); + if (res != ESP_OK){ + return ESP_FAIL; + } + + if (entry == nullptr){ + printf("rip pointer\n"); + return ESP_FAIL; //no room for more entries in the table + } + + if (entry->valid == RIP_NEW_ROW){ + //adding a new entry + rip_add_entry(board_id, hops + 1, channel, &entry); + } else { + //updating an entry + rip_update_entry(hops + 1, 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 + }; + + xQueueSendToBack(discovery_tables, &row_queue, (TickType_t)10); + } + + } + if (message_size == RIP_DISCOVERY_MESSAGE_SIZE){ + 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); + return res; + } + } + } + + //got frame but not destined for this board + if (header.receiver_id != this_board_id && header.receiver_id != BROADCAST_ADDR && header.seq_num > sequence_num_map[header.receiver_id]){ + // ESP_LOGI(DEBUG_LINK_TAG, "Sending message to board %d with message %s", header.receiver_id, message); + res = send(header.receiver_id, message, message_size, FrameType::DEBUG_CONTROL_TYPE, 0); + return res; + } + + //push control frame onto async_receive_queue + uint8_t* metadata_message = (uint8_t*)pvPortMalloc(message_size); + if (metadata_message == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to malloc for receive"); + return ESP_ERR_NO_MEM; + } + memcpy(metadata_message, message, message_size); + + Rx_Metadata metadata = { + .data = metadata_message, + .data_len = (uint16_t)message_size, + .header = header + }; + + if (xSemaphoreTake(async_rx_queue_mutex[channel], pdMS_TO_TICKS(ASYNC_QUEUE_WAIT_TICKS)) == pdTRUE){ + async_receive_queue[channel].push(metadata); + xSemaphoreGive(async_rx_queue_mutex[channel]); + } else { + return ESP_ERR_TIMEOUT; + } + return ESP_OK; +} + +[[noreturn]] void DataLinkManager::receive_thread_main(void* args){ + DataLinkManager* link_layer_obj = static_cast(args); + if (link_layer_obj == nullptr || link_layer_obj->manual_broadcasts == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Receive thread failed to start due to invalid pointer"); + vTaskDelete(nullptr); + } + + ESP_LOGI(DEBUG_LINK_TAG, "Starting Receive thread task"); + + esp_err_t res; + + for (uint8_t i = 0; i < link_layer_obj->num_channels; i++){ + res = link_layer_obj->start_receive_frames_rmt(i); + } + while(!link_layer_obj->stop_tasks){ + for (uint8_t i = 0; i < link_layer_obj->num_channels; i++){ + res = link_layer_obj->receive_rmt(i); + res = link_layer_obj->start_receive_frames_rmt(i); + } + + vTaskDelay(pdMS_TO_TICKS(SCHEDULER_PERIOD_MS)); + } + + vTaskDelete(nullptr); +} \ No newline at end of file diff --git a/components/dataLink/DataLinkManager.cpp b/components/dataLink/DataLinkManager.cpp index 7a687c2..e159a28 100644 --- a/components/dataLink/DataLinkManager.cpp +++ b/components/dataLink/DataLinkManager.cpp @@ -1,11 +1,12 @@ -#include "esp_log.h" #include "DataLinkManager.h" #include "RMTManager.h" +#include "esp_log.h" +#include "nvs_flash.h" /** * @brief Construct a new Data Link Manager:: Data Link Manager object * - * @param board_id Board ID of the current board. + * @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){ //init table for this board and set up link layer priority queue @@ -15,18 +16,248 @@ DataLinkManager::DataLinkManager(uint8_t board_id, uint8_t num_channels = MAX_CH return; } - this->this_board_id = board_id; + this_board_id = board_id; + set_board_id(this_board_id); + this->num_channels = num_channels; + init_scheduler(); init_rip(); } DataLinkManager::~DataLinkManager(){ - phys_comms.reset(); //not strictly necessary to do this explicitly + stop_tasks = true; + + bool dummy = true; + xQueueSend(manual_broadcasts, &dummy, 0); + + vTaskDelay(pdMS_TO_TICKS(50)); //delay to allow tasks to be killed + + if (rip_broadcast_task == NULL){ + vTaskDelete(rip_broadcast_task); + rip_broadcast_task = NULL; + } + if (rip_ttl_task == NULL){ + vTaskDelete(rip_ttl_task); + rip_ttl_task = NULL; + } + if (scheduler_task == NULL){ + vTaskDelete(scheduler_task); + scheduler_task = NULL; + } +} + +esp_err_t DataLinkManager::set_board_id(uint8_t board_id){ + if (board_id == BROADCAST_ADDR || board_id == PC_ADDR){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid board id"); + return ESP_FAIL; + } + + nvs_handle_t handle; + esp_err_t res = nvs_open("board", NVS_READWRITE, &handle); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to open NVS Handle"); + return res; + } + + res = nvs_set_u8(handle, "id", board_id); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to write ID %d to NVM", board_id); + nvs_close(handle); + return res; + } + + res = nvs_commit(handle); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to commit write"); + nvs_close(handle); + return res; + } + + this_board_id = board_id; + printf("Successfully wrote %d to NVM\n", board_id); + + nvs_close(handle); + + return ESP_OK; +} + +esp_err_t DataLinkManager::get_board_id(uint8_t& board_id){ + nvs_handle_t handle; + esp_err_t res = nvs_open("board", NVS_READWRITE, &handle); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to open NVS Handle"); + return res; + } + + res = nvs_get_u8(handle, "id", &board_id); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to get ID from NVM. Please make sure NVM is already assigned a board id!"); + nvs_close(handle); + return res; + } + + printf("Successfully got board id %d from NVM\n", board_id); + + nvs_close(handle); + + return ESP_OK; } /** - * @brief Sends a frame to another board (node to node communication) via RMT (physical layer) + * @brief Helper function to create a control frame + * + * @param dest_board + * @param data + * @param data_len + * @param type + * @param flag + * @return esp_err_t + */ +esp_err_t DataLinkManager::create_control_frame(uint8_t* data, uint16_t data_len, ControlFrame control_frame, uint8_t* send_data, size_t* send_data_len){ + if (data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Data array does not exist"); + return ESP_ERR_INVALID_ARG; + } + + if (this_board_id == PC_ADDR){ + ESP_LOGE(DEBUG_LINK_TAG, "This board is not assigned a board id"); + return ESP_ERR_INVALID_ARG; + } + + if (data_len > MAX_CONTROL_DATA_LEN){ + ESP_LOGE(DEBUG_LINK_TAG, "Data for control frame is too large. Maximum size is %d. Current data length is %d", MAX_CONTROL_DATA_LEN, data_len); + return ESP_ERR_INVALID_ARG; + } + + if (send_data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid pointer for send_data"); + return ESP_ERR_INVALID_ARG; + } + + if (send_data_len == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid pointer for send_data_len"); + return ESP_ERR_INVALID_ARG; + } + + if (*send_data_len < sizeof(ControlFrame)){ + ESP_LOGE(DEBUG_LINK_TAG, "Send data array is too small"); + return ESP_ERR_INVALID_ARG; + } + + if (!IS_CONTROL_FRAME(control_frame.type_flag)){ + ESP_LOGE(DEBUG_LINK_TAG, "Must be a control frame type"); + return ESP_ERR_INVALID_ARG; + } + + size_t offset = 0; + send_data[offset++] = control_frame.preamble; + send_data[offset++] = control_frame.sender_id; + send_data[offset++] = control_frame.receiver_id; + send_data[offset++] = control_frame.seq_num & 0xFF; + send_data[offset++] = (control_frame.seq_num >> 8) & 0xFF; + send_data[offset++] = control_frame.type_flag; + send_data[offset++] = data_len; + send_data[offset++] = (data_len >> 8) & 0xFF; + + memcpy(&send_data[offset], data, data_len); + + offset += control_frame.data_len; + + geneate_crc_16(send_data, offset, &control_frame.crc_16); + + send_data[offset++] = control_frame.crc_16 & 0xFF; + send_data[offset++] = (control_frame.crc_16 >> 8) & 0xFF; + + *send_data_len = offset; + + // printf("Sending Frame Information:\n"); + // printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n", + // "Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC"); + + // printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n", + // control_frame.preamble, control_frame.sender_id, control_frame.receiver_id, control_frame.seq_num, control_frame.type_flag, control_frame.data_len, control_frame.crc_16); + + return ESP_OK; +} + +esp_err_t DataLinkManager::create_generic_frame(uint8_t* data, uint16_t data_len, GenericFrame generic_frame, uint16_t offset, uint8_t* send_data, size_t* send_data_len){ + if (data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Data array does not exist"); + return ESP_ERR_INVALID_ARG; + } + + if (this_board_id == PC_ADDR){ + ESP_LOGE(DEBUG_LINK_TAG, "This board is not assigned a board id"); + return ESP_ERR_INVALID_ARG; + } + + if (data_len > MAX_CONTROL_DATA_LEN){ + ESP_LOGE(DEBUG_LINK_TAG, "Data for control frame is too large. Maximum size is %d. Current data length is %d", MAX_CONTROL_DATA_LEN, data_len); + return ESP_ERR_INVALID_ARG; + } + + if (send_data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid pointer for send_data"); + return ESP_ERR_INVALID_ARG; + } + + if (send_data_len == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid pointer for send_data_len"); + return ESP_ERR_INVALID_ARG; + } + + if (*send_data_len < sizeof(GenericFrame)){ + ESP_LOGE(DEBUG_LINK_TAG, "Send data array is too small"); + return ESP_ERR_INVALID_ARG; + } + + if (IS_CONTROL_FRAME(generic_frame.type_flag)){ + ESP_LOGE(DEBUG_LINK_TAG, "Must be a generic frame type"); + return ESP_ERR_INVALID_ARG; + } + + size_t send_data_offset = 0; + send_data[send_data_offset++] = generic_frame.preamble; + send_data[send_data_offset++] = generic_frame.sender_id; + send_data[send_data_offset++] = generic_frame.receiver_id; + send_data[send_data_offset++] = generic_frame.seq_num & 0xFF; + send_data[send_data_offset++] = (generic_frame.seq_num >> 8) & 0xFF; + + send_data[send_data_offset++] = generic_frame.type_flag; + + send_data[send_data_offset++] = generic_frame.total_frag & 0xFF; + send_data[send_data_offset++] = (generic_frame.total_frag >> 8) & 0xFF; + + send_data[send_data_offset++] = generic_frame.frag_num & 0xFF; + send_data[send_data_offset++] = (generic_frame.frag_num >> 8) & 0xFF; + + send_data[send_data_offset++] = data_len; + send_data[send_data_offset++] = (data_len >> 8) & 0xFF; + + memcpy(&send_data[send_data_offset], &data[offset], data_len); + + send_data_offset += data_len; + + geneate_crc_16(send_data, send_data_offset, &generic_frame.crc_16); + + send_data[send_data_offset++] = generic_frame.crc_16 & 0xFF; + send_data[send_data_offset++] = (generic_frame.crc_16 >> 8) & 0xFF; + + *send_data_len = send_data_offset; + + // printf("Sending Frame Information:\n"); + // printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n", + // "Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC"); + + // printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n", + // generic_frame.preamble, generic_frame.sender_id, generic_frame.receiver_id, generic_frame.seq_num, generic_frame.type_flag, generic_frame.data_len, generic_frame.crc_16); + + return ESP_OK; +} + +/** + * @brief Schedules a frame to be sent via RMT * * @param dest_board 8 bit ID of the destination board * @param data @@ -35,117 +266,71 @@ DataLinkManager::~DataLinkManager(){ * @return esp_err_t */ esp_err_t DataLinkManager::send(uint8_t dest_board, uint8_t* data, uint16_t data_len, FrameType type, uint8_t flag){ - if (phys_comms == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "Failed to send frame due to no RMT object"); - return ESP_FAIL; + bool isControlFrame = IS_CONTROL_FRAME((uint8_t)type); + + if (isControlFrame && data_len > MAX_CONTROL_DATA_LEN){ + //Control frames has max data size of MAX_CONTROL_DATA_LEN + return ESP_ERR_INVALID_ARG; } - if (data == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "Data array does not exist"); - return ESP_FAIL; + if (!isControlFrame && data_len > MAX_GENERIC_NUM_FRAG * MAX_CONTROL_DATA_LEN){ + //Generic frames has max MAX_GENERIC_NUM_FRAG fragments, each max size of MAX_CONTROL_DATA_LEN (data size) + return ESP_ERR_INVALID_ARG; } - - if (this_board_id == PC_ADDR){ - ESP_LOGE(DEBUG_LINK_TAG, "This board is not assigned a board id"); - return ESP_FAIL; + + //save data onto heap + uint8_t* saved_data = (uint8_t*)pvPortMalloc(data_len); + if (saved_data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to malloc in send()"); + return ESP_ERR_NO_MEM; } + memset(saved_data, 0, data_len); + memcpy(saved_data, data, data_len); //copy the contents to the heap - esp_err_t res; + //calculate number of fragments required (for generic frames only) + uint32_t frag_info = 0; + if (!isControlFrame){ + if (data_len <= MAX_CONTROL_DATA_LEN){ + frag_info = (1 << 16); //1 total fragment required + } else { + frag_info = (data_len / MAX_CONTROL_DATA_LEN + 1) << 16; - if (IS_CONTROL_FRAME(static_cast(type))){ - //control frame - if (data_len > MAX_CONTROL_DATA_LEN){ - ESP_LOGE(DEBUG_LINK_TAG, "Data for control frame is too large. Maximum size is %d. Current data length is %d", MAX_CONTROL_DATA_LEN, data_len); - return ESP_FAIL; } + } - control_frame new_frame = { + SchedulerMetadata metadata = { + .header = { .preamble = START_OF_FRAME, .sender_id = this_board_id, .receiver_id = dest_board, .seq_num = sequence_num_map[dest_board]++, .type_flag = (uint8_t)((static_cast(type) & 0xF0) | (flag & 0xF)), - .data_len = static_cast(data_len), - .crc_16 = 0, //not made yet - }; + .frag_info = frag_info, + .data_len = data_len, + .crc_16 = 0, + }, + .generic_frame_data_offset = 0, + .enqueue_time_ns = 0, + .data = saved_data, + .len = data_len, + }; - // ESP_LOGI(DEBUG_LINK_TAG, "type flag %X\n", new_frame.type_flag); - // printf("size of control frame %d\n", sizeof(control_frame)); - // printf("size of message %d\n", new_frame.data_len); - // printf("message %s\n", data); - // print_buffer_binary(data, new_frame.data_len); - - size_t frame_size = sizeof(control_frame) + new_frame.data_len - MAX_CONTROL_DATA_LEN; - - // printf("frame size %d\n", frame_size); - - uint8_t send_data[frame_size]; - size_t offset = 0; - send_data[offset++] = new_frame.preamble; - send_data[offset++] = new_frame.sender_id; - send_data[offset++] = new_frame.receiver_id; - send_data[offset++] = new_frame.seq_num & 0xFF; - send_data[offset++] = (new_frame.seq_num >> 8) & 0xFF; - send_data[offset++] = new_frame.type_flag; - send_data[offset++] = new_frame.data_len; - send_data[offset++] = (new_frame.data_len >> 8) & 0xFF; - - memcpy(&send_data[offset], data, new_frame.data_len); - - offset += new_frame.data_len; - - geneate_crc_16(send_data, offset, &new_frame.crc_16); - - send_data[offset++] = new_frame.crc_16 & 0xFF; - send_data[offset++] = (new_frame.crc_16 >> 8) & 0xFF; - - - rmt_transmit_config_t config = { - .loop_count = 0, - .flags = { - .eot_level = 0 // typically 0 or 1, depending on your output idle level - } - }; - - // ESP_LOGI(DEBUG_LINK_TAG, "Sending %d bytes", offset); - // printf("Sending Frame Information:\n"); - // printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n", - // "Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC"); + uint8_t channel = 0; + esp_err_t res = route_frame(dest_board, &channel); - // printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n", - // new_frame.preamble, new_frame.sender_id, new_frame.receiver_id, new_frame.seq_num, new_frame.type_flag, new_frame.data_len, new_frame.crc_16); - - uint8_t channel_to_route = MAX_CHANNELS; - if (new_frame.receiver_id == BROADCAST_ADDR){ - for (uint8_t i = 0; i < num_channels; i++){ - // printf("Sending on channel %d\n", i); - phys_comms->send(send_data, offset, &config, i); - } - - } else { - res = route_frame(new_frame.receiver_id, &channel_to_route); - - if (res != ESP_OK){ - // ESP_LOGE(DEBUG_LINK_TAG, "Failed to find entry for %d", new_frame.receiver_id); - return ESP_FAIL; - } - // ESP_LOGI(DEBUG_LINK_TAG, "Sending message to %d", new_frame.receiver_id); - phys_comms->send(send_data, offset, &config, channel_to_route); - } - // if (res != ESP_OK){ - // ESP_LOGE(DEBUG_LINK_TAG, "Failed to send message"); - // return ESP_FAIL; - // } else{ - // // printf("Sent message to board %d\n", dest_board); - // } - - } else { - //generic frame - printf("not implemented yet\n"); - return ESP_ERR_NOT_SUPPORTED; + if (res != ESP_OK){ + // ESP_LOGE(DEBUG_LINK_TAG, "Failed to route message to board %d", dest_board); + vPortFree(saved_data); + return res; } - return ESP_OK; + res = push_frame_to_scheduler(metadata, channel); + + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to push frame to scheduler queue"); + vPortFree(saved_data); + } + return res; } void DataLinkManager::print_binary(uint8_t byte) { @@ -163,146 +348,59 @@ void DataLinkManager::print_buffer_binary(const uint8_t* buffer, size_t length) } /** + * @deprecated This function is deprecated. This is replaced by `async_receive_info` and `async_receive`. This function returns `ESP_FAIL` + * * @brief Starts the RMT async receive job to start listening for a new frame over a given channel * * @param curr_channel * @return esp_err_t */ esp_err_t DataLinkManager::start_receive_frames(uint8_t curr_channel){ + return ESP_FAIL; +} + +/** + * @brief Starts the RMT async receive job to start listening for a new frame over a given channel + * + * @param curr_channel + * @return esp_err_t + */ +esp_err_t DataLinkManager::start_receive_frames_rmt(uint8_t curr_channel){ if (curr_channel >= num_channels){ return ESP_FAIL; } return phys_comms->start_receiving(curr_channel); } +/** + * @deprecated This function is deprecated. This is replaced by `async_receive_info` and `async_receive`. This function returns `ESP_FAIL` + * + * @brief Receive Control Frame from RMT Physical Layer + * + * @param data Byte array + * @param data_len Length of the byte array + * @param recv_len Length of the received data + * @param curr_channel Physical channel pair to look at + * @return esp_err_t + */ +esp_err_t DataLinkManager::receive(uint8_t* data, size_t data_len, size_t* recv_len, uint8_t curr_channel){ + return ESP_FAIL; +} + /** * @brief * * @param data * @param data_len - * @param recv_len - * @param curr_channel + * @param message + * @param message_size + * @param header * @return esp_err_t + * + * @deprecated + * Will be moved to private function */ -esp_err_t DataLinkManager::receive(uint8_t* data, size_t data_len, size_t* recv_len, uint8_t curr_channel){ - if (data == NULL){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid data array"); - return ESP_ERR_INVALID_ARG; - } - - if (curr_channel >= num_channels){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid channel"); - return ESP_ERR_INVALID_ARG; - } - - if (data_len < MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD){ - ESP_LOGE(DEBUG_LINK_TAG, "Receive data buffer len is too small"); - return ESP_ERR_INVALID_ARG; - } - - // uint8_t recv_buf[256]; - - esp_err_t res = phys_comms->receive(data, data_len, recv_len, curr_channel); - - if (res != ESP_OK){ - ESP_LOGW(DEBUG_LINK_TAG, "RMT Failed to receive"); - return ESP_ERR_TIMEOUT; - } - - if (*recv_len > MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid control frame"); - return ESP_ERR_INVALID_RESPONSE; - } - - if (*recv_len < CONTROL_FRAME_OVERHEAD) { - return ESP_ERR_INVALID_RESPONSE; - } - - uint8_t* message = (uint8_t*)pvPortMalloc(CONTROL_FRAME_OVERHEAD + MAX_CONTROL_DATA_LEN); - if (message == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "Failed to malloc for receive"); - return ESP_ERR_NO_MEM; - } - memset(message, 0, sizeof(message)); - size_t message_size = 0; - frame_header header; - res = get_data_from_frame(data, *recv_len, message, &message_size, &header); - if (res != ESP_OK){ - // print_buffer_binary(message, message_size); - vPortFree((void*)message); - return res; - } - *recv_len = message_size; - memcpy(data, message, message_size); - // ESP_LOGI(DEBUG_LINK_TAG, "Received frame of type 0x%X destined for board %d", GET_TYPE(header.type_flag), header.receiver_id); - - //check for a rip frame - if (static_cast(GET_TYPE(header.type_flag)) == FrameType::RIP_TABLE_CONTROL){ - // printf("Got a RIP frame\n"); - - for (size_t i = 0; i < message_size-1; i+=2){ - uint8_t board_id = message[i]; - uint8_t hops = message[i+1]; - ESP_LOGI(DEBUG_LINK_TAG, "Received: board_id %d and number of hops %d on channel %d", board_id, hops, curr_channel); - - RIPRow* entry = nullptr; - - res = rip_find_entry(board_id, &entry, true); - if (res != ESP_OK){ - vPortFree((void*)message); - return ESP_FAIL; - } - - if (entry == nullptr){ - printf("rip pointer\n"); - vPortFree((void*)message); - return ESP_FAIL; //no room for more entries in the table - } - - if (entry->valid == RIP_NEW_ROW){ - //adding a new entry - rip_add_entry(board_id, hops + 1, curr_channel, &entry); - } else { - //updating an entry - rip_update_entry(hops + 1, curr_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 - }; - - xQueueSendToBack(discovery_tables, &row_queue, (TickType_t)10); - } - - } - *recv_len = 0; - if (message_size == RIP_DISCOVERY_MESSAGE_SIZE){ - 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); - return res; - } - } - } - - //got frame but not destined for this board - if (header.receiver_id != this_board_id && header.receiver_id != BROADCAST_ADDR && header.seq_num > sequence_num_map[header.receiver_id]){ - // ESP_LOGI(DEBUG_LINK_TAG, "Sending message to board %d with message %s", header.receiver_id, message); - res = send(header.receiver_id, message, message_size, FrameType::DEBUG_CONTROL_TYPE, 0); - *recv_len = 0; - vPortFree((void*)message); - return res; - } - - vPortFree((void*)message); - return ESP_OK; -} - -esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size, frame_header* header){ +esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size, FrameHeader* header){ if (data == nullptr){ ESP_LOGE(DEBUG_LINK_TAG, "Invalid data array"); return ESP_ERR_INVALID_ARG; @@ -320,12 +418,12 @@ esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, u return ESP_ERR_INVALID_ARG; } + header->preamble = data[0]; + header->sender_id = data[1]; + header->receiver_id = data[2]; + header->seq_num = (uint16_t)data[3] | ((uint16_t)data[4] << 8); + header->type_flag = data[5]; if (IS_CONTROL_FRAME(data[5])){ - header->preamble = data[0]; - header->sender_id = data[1]; - header->receiver_id = data[2]; - header->seq_num = (uint16_t)data[3] | ((uint16_t)data[4] << 8); - header->type_flag = data[5]; header->data_len = (uint16_t)data[6] | ((uint16_t)data[7] << 8); if (header->data_len > data_len){ @@ -339,7 +437,6 @@ esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, u } *message_size = header->data_len; - memcpy(message, &data[8], header->data_len); geneate_crc_16(data, 8*sizeof(uint8_t) + header->data_len, &header->crc_16); @@ -348,21 +445,41 @@ esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, u if (crc_calc != header->crc_16){ //CRC mismatch - ESP_LOGE(DEBUG_LINK_TAG, "CRC Mismatch"); + ESP_LOGE(DEBUG_LINK_TAG, "CRC Mismatch - Control Frame"); ESP_LOGE(DEBUG_LINK_TAG, "Got 0x%04X but calculated 0x%04X\n", crc_calc, header->crc_16); return ESP_ERR_INVALID_CRC; } - // printf("Received Frame Information:\n"); - // printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n", - // "Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC"); - - // printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n", - // header->preamble, header->sender_id, header->receiver_id, header->seq_num, header->type_flag, header->data_len, header->crc_16); } else { - //not implemented yet - } + //generic frame + uint16_t total_frag = (uint16_t)data[6] | ((uint16_t)data[7] << 8); + uint16_t frag_num = (uint16_t)data[8] | ((uint16_t)data[9] << 8); + header->frag_info = (total_frag << 16) | (frag_num); + header->data_len = (uint16_t)data[10] | ((uint16_t)data[11] << 8); + *message_size = header->data_len; + memcpy(message, &data[12], header->data_len); + + geneate_crc_16(data, 12*sizeof(uint8_t) + header->data_len, &header->crc_16); + + uint16_t crc_calc = ((uint16_t)data[12 + header->data_len] | ((uint16_t)data[13 + header->data_len] << 8)); + + if (crc_calc != header->crc_16){ + //CRC mismatch + ESP_LOGE(DEBUG_LINK_TAG, "CRC Mismatch - Generic Frame"); + ESP_LOGE(DEBUG_LINK_TAG, "Got 0x%04X but calculated 0x%04X\n", crc_calc, header->crc_16); + return ESP_ERR_INVALID_CRC; + } + } + + // printf("Received Frame Information:\n"); + // printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n", + // "Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC"); + + // printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n", + // header->preamble, header->sender_id, header->receiver_id, header->seq_num, header->type_flag, header->data_len, header->crc_16); + + printf("Message received: %.*s\n", header->data_len, message); return ESP_OK; } @@ -394,464 +511,11 @@ esp_err_t DataLinkManager::geneate_crc_16(uint8_t* data, size_t data_len, uint16 return ESP_OK; } -esp_err_t DataLinkManager::print_frame_info(uint8_t* data, size_t data_len, uint8_t* message){ +esp_err_t DataLinkManager::print_frame_info(uint8_t* data, size_t data_len, uint8_t* message, size_t message_len){ // printf("Received frame of size %d:\n", data_len); - size_t message_size; - - frame_header temp; + FrameHeader temp; // print_buffer_binary(data, data_len); - return get_data_from_frame(data, data_len, message, &message_size, &temp); + return get_data_from_frame(data, data_len, message, &message_len, &temp); } - -/** - * @brief Initializes the RIP table - * - */ -void DataLinkManager::init_rip(){ - for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ - rip_table[i] = { - .info = { - .board_id = BROADCAST_ADDR, //invalid addr - .hops = RIP_MAX_HOPS + 1, //infinite - }, - .channel = MAX_CHANNELS + 1, //invalid channels - .ttl = 0, - .valid = RIP_INVALID_ROW, - .ttl_flush = 0, - .row_sem = NULL - }; - - rip_table[i].row_sem = xSemaphoreCreateMutexStatic(&rip_table[i].mutex_buf); - } - - //add the self route to the table - rip_table[0].info = { - .board_id = this_board_id, - .hops = 0, - }; - rip_table[0].channel = MAX_CHANNELS + 1; - rip_table[0].ttl = RIP_TTL_START; - rip_table[0].valid = 1; - - //temp debug - // rip_table[1].info = { - // .board_id = 2, - // .hops = 1, - // }; - // rip_table[1].channel = 0; - // rip_table[1].ttl = RIP_TTL_START; - // rip_table[1].valid = 1; - - // rip_table[2].info = { - // .board_id = 1, - // .hops = 2, - // }; - // rip_table[2].channel = 0, - // rip_table[2].ttl = RIP_TTL_START, - // rip_table[2].valid = 1; - - discovery_tables = xQueueCreate(RIP_MAX_ROUTES, sizeof(RIPRow_public)); - - start_rip_tasks(); -} - -esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t channel, RIPRow** entry){ - if (entry == nullptr){ - return ESP_FAIL; - } - - if (xSemaphoreTake((*entry)->row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ - return ESP_FAIL; - } - - (*entry)->channel = channel; - (*entry)->info = { - .board_id = board_id, - .hops = 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); - - if (uxQueueMessagesWaiting(manual_broadcasts) == 0){ - bool dummy = true; - xQueueSend(manual_broadcasts, &dummy, 0); //new row - send broadcast - } - - return ESP_OK; -} - -esp_err_t DataLinkManager::rip_reset_entry_ttl(uint8_t board_id){ - RIPRow* entry = nullptr; - - esp_err_t res; - - res = rip_find_entry(board_id, &entry, false); - if (res != ESP_OK){ - return ESP_FAIL; - } - - if (entry == nullptr){ - return ESP_FAIL; //board doesn't exist - } - - if (xSemaphoreTake(entry->row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ - return ESP_FAIL; - } - - entry->ttl = RIP_TTL_START; - - xSemaphoreGive(entry->row_sem); - - return ESP_OK; -} - -esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t channel, RIPRow** entry){ - if (entry == nullptr){ - return ESP_FAIL; //board doesn't exist - } - - if (xSemaphoreTake((*entry)->row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ - return ESP_FAIL; - } - - uint8_t old_hops = (*entry)->info.hops; - - if ((*entry)->info.hops > new_hop && (*entry)->info.hops != RIP_MAX_HOPS + 1){ //no count to infinity if path is invalid - (*entry)->info.hops = new_hop; - (*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); - } - (*entry)->ttl = RIP_TTL_START; - (*entry)->valid = 1; - - // ESP_LOGI(DEBUG_LINK_TAG, "refreshed board_id %d ttl", (*entry)->info.board_id); - - 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) - bool dummy = true; - xQueueSend(manual_broadcasts, &dummy, 0); - } - - return ESP_OK; -} - -/** - * @brief Finds the board_id in the table if it exists and stores that row in `entry` - * TODO: use an unordered map instead of an array? - * - * @param board_id - * @param entry - * @return esp_err_t - */ -esp_err_t DataLinkManager::rip_find_entry(uint8_t board_id, RIPRow** entry, bool reserve_row = false){ - RIPRow* free_slot = nullptr; - for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ - if (xSemaphoreTake(rip_table[i].row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ - return ESP_FAIL; - } - if (rip_table[i].valid == RIP_VALID_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); - return ESP_OK; - } - if (rip_table[i].valid == RIP_INVALID_ROW && free_slot == nullptr){ - free_slot = &rip_table[i]; - } - xSemaphoreGive(rip_table[i].row_sem); - } - - // ESP_LOGI(DEBUG_LINK_TAG, "Finished looking for %d in table", board_id); - - if (!reserve_row){ - return ESP_OK; - } - - if (free_slot != nullptr){ - if (xSemaphoreTake(free_slot->row_sem, RIP_MAX_SEM_WAIT) != pdTRUE) { - return ESP_FAIL; - } - - // IMPORTANT: Mark it as taken so others don't grab it - free_slot->valid = RIP_NEW_ROW; // Or some other init state - free_slot->info.board_id = board_id; - *entry = free_slot; - - xSemaphoreGive(free_slot->row_sem); - // ESP_LOGI(DEBUG_LINK_TAG, "Reserved new entry for board %d", board_id); - } - - return ESP_OK; -} - -/** - * @brief Sends RIP frame - * - * @param broadcast True - broadcasts (sends rip table to all available channels); False - sends rip table via routing based on `dest_id` - * @param dest_id Destination board (requesting board) to send the rip table to (ignored if `broadcast is true`) - * @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), ...] - - uint8_t rip_message[RIP_MAX_ROUTES*2] = {}; - size_t message_idx = 0; - - for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ - xSemaphoreTake(rip_table[i].row_sem, (TickType_t)RIP_MAX_SEM_WAIT); - if (rip_table[i].valid == RIP_INVALID_ROW){ - xSemaphoreGive(rip_table[i].row_sem); - continue; - } - - if (rip_table[i].info.hops == RIP_MAX_HOPS + 1){ - //invalid hop, decrement counter - rip_table[i].ttl_flush--; - if (rip_table[i].ttl_flush == 0){ - rip_table[i].valid = RIP_INVALID_ROW; - xSemaphoreGive(rip_table[i].row_sem); - continue; - } - } - - // //test to ensure routing works - // if (rip_table[i].info.board_id == 25){ - // rip_message[message_idx++] = 25; - // rip_message[message_idx++] = 10; - // } else { - rip_message[message_idx++] = rip_table[i].info.board_id; - rip_message[message_idx++] = rip_table[i].info.hops; - // } - - xSemaphoreGive(rip_table[i].row_sem); - } - - esp_err_t res; - if (broadcast){ - res = send(BROADCAST_ADDR, rip_message, message_idx, FrameType::RIP_TABLE_CONTROL, 0); - } else { - ESP_LOGI(DEBUG_LINK_TAG, "replying to discovery request to board %d", dest_id); - res = send(dest_id, rip_message, message_idx, FrameType::RIP_TABLE_CONTROL, FLAG_DISCOVERY); - } - if (res != ESP_OK){ - ESP_LOGE(DEBUG_LINK_TAG, "Failed to send rip frame on channel %d", 0); - } - - return ESP_OK; -} - -/** - * @brief Determines which channel to route the frame to, depending on the dest (board) id - * - * @param dest_id - * @param channel_to_send - * @return esp_err_t - */ -esp_err_t DataLinkManager::route_frame(uint8_t dest_id, uint8_t* channel_to_send){ - RIPRow* entry = nullptr; - - esp_err_t res; - - res = rip_find_entry(dest_id, &entry, false); - if (entry == nullptr){ - return ESP_FAIL; - } - - if (res != ESP_OK){ - return res; - } - - *channel_to_send = entry->channel; - - return ESP_OK; -} - -esp_err_t DataLinkManager::get_routing_table(RIPRow_public* table, size_t* table_size){ - if (table == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid table pointer"); - return ESP_FAIL; - } - - if (table_size == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid table size pointer"); - return ESP_FAIL; - } - - if (*table_size < RIP_MAX_ROUTES){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid table size (must be greater than %d)", RIP_MAX_ROUTES); - return ESP_FAIL; - } - - size_t curr_size = 0; - - for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ - if (xSemaphoreTake(rip_table[i].row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ - return ESP_FAIL; - } - if (rip_table[i].valid == RIP_VALID_ROW){ - table[i].info = rip_table[i].info; - table[i].channel = rip_table[i].channel; - curr_size++; - } - xSemaphoreGive(rip_table[i].row_sem); - } - - *table_size = curr_size; - - return ESP_OK; -} - -/** - * @brief Gets all of the routing tables of each board in the network and returns a routing matrix (entire topology of the network). - * - * RIP table will have an entry that refers to its own board id (and will always have hop value of 0 and a channel value of `MAX_CHANNELS + 1`) - * - * @warning not completely working (unable to get other board's table properly) - * - * @param matrix - * @param matrix_size size in multiples of `sizeof(RIPRow_public)` - * @return esp_err_t - */ -esp_err_t DataLinkManager::get_network_toplogy(RIPRow_public_matrix* matrix, size_t* matrix_size){ - if (matrix == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid matrix pointer"); - return ESP_FAIL; - } - - if (matrix_size == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid matrix size pointer"); - return ESP_FAIL; - } - - if (*matrix_size < RIP_MAX_ROUTES){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid matrix size (must be greater than %d)", RIP_MAX_ROUTES); - return ESP_FAIL; - } - - size_t curr_size = 0; - matrix[0].board_id = this_board_id; - if (matrix[0].table == nullptr || matrix[0].size < RIP_MAX_ROUTES){ - ESP_LOGE(DEBUG_LINK_TAG, "Invalid table size for index 0"); - return ESP_FAIL; - } - - esp_err_t res; - - res = get_routing_table(matrix[0].table, &matrix[0].size); - if (res != ESP_OK){ - return ESP_FAIL; - } - curr_size++; - - uint8_t message[RIP_DISCOVERY_MESSAGE_SIZE] = {0}; - for (size_t i = 1; i < matrix[0].size; i++){ - // ESP_LOGI(DEBUG_LINK_TAG, "Sending discovery request for board %d", matrix[0].table[i].info.board_id); - send(matrix[0].table[i].info.board_id, message, 1, FrameType::RIP_TABLE_CONTROL, FLAG_DISCOVERY); //send a discovery request to a board in this board's table index i - uint8_t table_idx = 0; - RIPRow_public temp; - while (xQueueReceive(discovery_tables, &temp, (TickType_t)1000) == pdTRUE){ //the board should have responded with rows from its routing table to insert into the matrix - // ESP_LOGI(DEBUG_LINK_TAG, "putting discovery reply into matrix"); - matrix[i].table[table_idx].info.board_id = temp.info.board_id; - matrix[i].table[table_idx].info.hops = temp.info.hops; - matrix[i].table[table_idx++].channel = temp.channel; - } - matrix[i].size = table_idx; - curr_size++; - - xQueueReset(discovery_tables); //reset the queue - } - - *matrix_size = curr_size; - - return ESP_OK; -} - -[[noreturn]] void DataLinkManager::rip_broadcast_timer_function(void* args){ - DataLinkManager* link_layer_obj = static_cast(args); - if (link_layer_obj == nullptr || link_layer_obj->manual_broadcasts == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "RIP Broadacst task failed to start due to invalid pointer"); - vTaskDelete(nullptr); - } - - ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP broadcast task"); - - esp_err_t res; - while(true){ - bool dummy; - xQueueReceive(link_layer_obj->manual_broadcasts, &dummy, pdMS_TO_TICKS(RIP_BROADCAST_INTERVAL)); //wait up to RIP_BROADCAST_INTERVAL ms - ESP_LOGI(DEBUG_LINK_TAG, "Broadcasting table..."); //debug - res = link_layer_obj->send_rip_frame(true, 0); - if (res != ESP_OK){ - ESP_LOGE(DEBUG_LINK_TAG, "Failed to broadcast rip frame"); - } - } -} - -[[noreturn]] void DataLinkManager::rip_ttl_decrement_task(void* args){ - DataLinkManager* link_layer_obj = static_cast(args); - if (link_layer_obj == nullptr || link_layer_obj->manual_broadcasts == nullptr){ - ESP_LOGE(DEBUG_LINK_TAG, "RIP Broadacst task failed to start due to invalid pointer"); - vTaskDelete(nullptr); - } - ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP ttl decrement task"); - bool broadcast = false; - bool dummy = true; - xQueueSend(link_layer_obj->manual_broadcasts, &dummy, 0); - while(true){ - vTaskDelay(pdMS_TO_TICKS(RIP_MS_TO_SEC)); //run every second - for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ - // ESP_LOGI(DEBUG_LINK_TAG, "Decrementing ttl on entry %d", i); - if (xSemaphoreTake(link_layer_obj->rip_table[i].row_sem, (TickType_t)RIP_MAX_SEM_WAIT) !=pdTRUE){ - ESP_LOGE(DEBUG_LINK_TAG, "Failed to get sem from entry %d", i); - continue; - } - if (link_layer_obj->rip_table[i].valid == RIP_INVALID_ROW){ - xSemaphoreGive(link_layer_obj->rip_table[i].row_sem); - 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; - } - } - - xSemaphoreGive(link_layer_obj->rip_table[i].row_sem); - } - - if (broadcast && uxQueueMessagesWaiting(link_layer_obj->manual_broadcasts) == 0){ - broadcast = false; - xQueueSend(link_layer_obj->manual_broadcasts, &dummy, 0); - } - } -} - -/** - * @brief This function will start the tasks required for RIP to function. - * Currently, this function will: - * - start the task to periodically broadcast the board's current copy of the RIP table to all other boards via the 4 RMT channels - * - start a task to periodically decrement the ttl values of each row in the RIP table (WIP) - this will require some sort of mutex on the table itself - */ -void DataLinkManager::start_rip_tasks(){ - manual_broadcasts = xQueueCreate(2, sizeof(bool)); - - ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP Broadcast task"); - xTaskCreate(DataLinkManager::rip_broadcast_timer_function, "RIPBroadcast", 4096, static_cast(this), 5, NULL); - ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP TTL task"); - xTaskCreate(DataLinkManager::rip_ttl_decrement_task, "RIPTTL", 4096, static_cast(this), 5, NULL); -} \ No newline at end of file diff --git a/components/dataLink/DataLinkRIP.cpp b/components/dataLink/DataLinkRIP.cpp new file mode 100644 index 0000000..51d5d5d --- /dev/null +++ b/components/dataLink/DataLinkRIP.cpp @@ -0,0 +1,456 @@ +#include "DataLinkManager.h" +#include "esp_log.h" +#include "freertos/semphr.h" + +/** + * @brief Initializes the RIP table + * + */ +void DataLinkManager::init_rip(){ + for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ + rip_table[i] = { + .info = { + .board_id = BROADCAST_ADDR, //invalid addr + .hops = RIP_MAX_HOPS + 1, //infinite + }, + .channel = MAX_CHANNELS + 1, //invalid channels + .ttl = 0, + .valid = RIP_INVALID_ROW, + .ttl_flush = 0, + .row_sem = NULL + }; + + rip_table[i].row_sem = xSemaphoreCreateMutexStatic(&rip_table[i].mutex_buf); + } + + //add the self route to the table + rip_table[0].info = { + .board_id = this_board_id, + .hops = 0, + }; + rip_table[0].channel = MAX_CHANNELS + 1; + rip_table[0].ttl = RIP_TTL_START; + rip_table[0].valid = 1; + + discovery_tables = xQueueCreate(RIP_MAX_ROUTES, sizeof(RIPRow_public)); + + start_rip_tasks(); +} + +esp_err_t DataLinkManager::rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t channel, RIPRow** entry){ + if (entry == nullptr){ + return ESP_FAIL; + } + + if (xSemaphoreTake((*entry)->row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ + return ESP_FAIL; + } + + (*entry)->channel = channel; + (*entry)->info = { + .board_id = board_id, + .hops = 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); + + if (uxQueueMessagesWaiting(manual_broadcasts) == 0){ + bool dummy = true; + xQueueSend(manual_broadcasts, &dummy, 0); //new row - send broadcast + } + + return ESP_OK; +} + +esp_err_t DataLinkManager::rip_reset_entry_ttl(uint8_t board_id){ + RIPRow* entry = nullptr; + + esp_err_t res; + + res = rip_find_entry(board_id, &entry, false); + if (res != ESP_OK){ + return ESP_FAIL; + } + + if (entry == nullptr){ + return ESP_FAIL; //board doesn't exist + } + + if (xSemaphoreTake(entry->row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ + return ESP_FAIL; + } + + entry->ttl = RIP_TTL_START; + + xSemaphoreGive(entry->row_sem); + + return ESP_OK; +} + +esp_err_t DataLinkManager::rip_update_entry(uint8_t new_hop, uint8_t channel, RIPRow** entry){ + if (entry == nullptr){ + return ESP_FAIL; //board doesn't exist + } + + if (xSemaphoreTake((*entry)->row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ + return ESP_FAIL; + } + + uint8_t old_hops = (*entry)->info.hops; + + if ((*entry)->info.hops >= new_hop && (*entry)->info.hops != RIP_MAX_HOPS + 1){ //no count to infinity if path is invalid + (*entry)->info.hops = new_hop; + (*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); + } + + (*entry)->ttl = RIP_TTL_START; + (*entry)->valid = 1; + + // ESP_LOGI(DEBUG_LINK_TAG, "refreshed board_id %d ttl", (*entry)->info.board_id); + + 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) + bool dummy = true; + xQueueSend(manual_broadcasts, &dummy, 0); + } + + return ESP_OK; +} + +/** + * @brief Finds the board_id in the table if it exists and stores that row in `entry` + * TODO: use an unordered map instead of an array? + * + * @param board_id + * @param entry + * @return esp_err_t + */ +esp_err_t DataLinkManager::rip_find_entry(uint8_t board_id, RIPRow** entry, bool reserve_row = false){ + RIPRow* free_slot = nullptr; + for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ + if (xSemaphoreTake(rip_table[i].row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ + return ESP_FAIL; + } + if (rip_table[i].valid == RIP_VALID_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); + return ESP_OK; + } + if (rip_table[i].valid == RIP_INVALID_ROW && free_slot == nullptr){ + free_slot = &rip_table[i]; + } + xSemaphoreGive(rip_table[i].row_sem); + } + + // ESP_LOGI(DEBUG_LINK_TAG, "Finished looking for %d in table", board_id); + + if (!reserve_row){ + return ESP_OK; + } + + if (free_slot != nullptr){ + if (xSemaphoreTake(free_slot->row_sem, RIP_MAX_SEM_WAIT) != pdTRUE) { + return ESP_FAIL; + } + + // IMPORTANT: Mark it as taken so others don't grab it + free_slot->valid = RIP_NEW_ROW; // Or some other init state + free_slot->info.board_id = board_id; + *entry = free_slot; + + xSemaphoreGive(free_slot->row_sem); + // ESP_LOGI(DEBUG_LINK_TAG, "Reserved new entry for board %d", board_id); + } + + return ESP_OK; +} + +/** + * @brief Returns the associated RIP Table row by row number. Information returned is read only. + * + * @param entry + * @param row_num + * @return esp_err_t + */ +esp_err_t DataLinkManager::rip_get_row(RIPRow** entry, uint8_t row_num){ + if (entry == nullptr){ + return ESP_ERR_INVALID_ARG; + } + + if (row_num >= RIP_MAX_ROUTES){ + return ESP_ERR_INVALID_ARG; + } + + if (xSemaphoreTake(rip_table[row_num].row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE) return ESP_ERR_TIMEOUT; + + if (rip_table[row_num].valid == RIP_INVALID_ROW){ + xSemaphoreGive(rip_table[row_num].row_sem); + 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; + } + } + + *entry = &rip_table[row_num]; + + xSemaphoreGive(rip_table[row_num].row_sem); + + return ESP_OK; +} + +/** + * @brief Sends RIP frame + * + * @param broadcast True - broadcasts (sends rip table to all available channels); False - sends rip table via routing based on `dest_id` + * @param dest_id Destination board (requesting board) to send the rip table to (ignored if `broadcast is true`) + * @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), ...] + + uint8_t rip_message[RIP_MAX_ROUTES*2] = {}; + uint16_t message_idx = 0; + + esp_err_t res; + + RIPRow* entry = nullptr; + + if(broadcast){ + for (size_t channel = 0; channel < num_channels; channel++){ + for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ + res = rip_get_row(&entry, i); + + if (res != ESP_OK){ + continue; + } + + if (entry == nullptr){ + 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[message_idx++] = entry->info.board_id; + rip_message[message_idx++] = RIP_MAX_HOPS + 1; + } else { + rip_message[message_idx++] = entry->info.board_id; + rip_message[message_idx++] = entry->info.hops; + } + } + + uint8_t* send_data = (uint8_t*)pvPortMalloc(message_idx); + if (send_data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to malloc when trying to send rip frame broadcast on channel %d", channel); + continue; + } + memset(send_data, 0, message_idx); + memcpy(send_data, rip_message, message_idx); + + SchedulerMetadata metadata = { + .header = { + .preamble = START_OF_FRAME, + .sender_id = this_board_id, + .receiver_id = BROADCAST_ADDR, + .seq_num = sequence_num_map[BROADCAST_ADDR]++, + .type_flag = static_cast(FrameType::RIP_TABLE_CONTROL), + .data_len = message_idx, + .crc_16 = 0, + }, + .generic_frame_data_offset = 0, + .enqueue_time_ns = 0, + .data = send_data, + .len = message_idx, + }; + + res = push_frame_to_scheduler(metadata, channel); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to schedule rip frame from send_rip_frame for channel %d", channel); + } + message_idx = 0; + memset(rip_message, 0, sizeof(rip_message)); + } + } else { + for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ + res = rip_get_row(&entry, i); + + if (res != ESP_OK){ + continue; + } + + if (entry == nullptr){ + continue; + } + rip_message[message_idx++] = entry->info.board_id; + rip_message[message_idx++] = entry->info.hops; + } + ESP_LOGI(DEBUG_LINK_TAG, "replying to discovery request to board %d", dest_id); + res = send(dest_id, rip_message, message_idx, FrameType::RIP_TABLE_CONTROL, FLAG_DISCOVERY); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to send rip frame from send_rip_frame"); + } + } + + return ESP_OK; +} + +/** + * @brief Determines which channel to route the frame to, depending on the dest (board) id + * + * @param dest_id + * @param channel_to_send + * @return esp_err_t + */ +esp_err_t DataLinkManager::route_frame(uint8_t dest_id, uint8_t* channel_to_send){ + RIPRow* entry = nullptr; + + esp_err_t res; + + res = rip_find_entry(dest_id, &entry, false); + if (entry == nullptr){ + return ESP_ERR_NOT_FOUND; + } + + if (res != ESP_OK){ + return res; + } + + *channel_to_send = entry->channel; + + return ESP_OK; +} + +esp_err_t DataLinkManager::get_routing_table(RIPRow_public* table, size_t* table_size){ + if (table == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid table pointer"); + return ESP_FAIL; + } + + if (table_size == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid table size pointer"); + return ESP_FAIL; + } + + if (*table_size < RIP_MAX_ROUTES){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid table size (must be greater than %d)", RIP_MAX_ROUTES); + return ESP_FAIL; + } + + size_t curr_size = 0; + + for (size_t i = 0; i < RIP_MAX_ROUTES; i++){ + if (xSemaphoreTake(rip_table[i].row_sem, (TickType_t)RIP_MAX_SEM_WAIT) != pdTRUE){ + return ESP_FAIL; + } + if (rip_table[i].valid == RIP_VALID_ROW){ + table[i].info = rip_table[i].info; + table[i].channel = rip_table[i].channel; + curr_size++; + } + xSemaphoreGive(rip_table[i].row_sem); + } + + *table_size = curr_size; + + return ESP_OK; +} + +[[noreturn]] void DataLinkManager::rip_broadcast_timer_function(void* args){ + DataLinkManager* link_layer_obj = static_cast(args); + if (link_layer_obj == nullptr || link_layer_obj->manual_broadcasts == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "RIP Broadacst task failed to start due to invalid pointer"); + vTaskDelete(nullptr); + } + + ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP broadcast task"); + + esp_err_t res; + while(!link_layer_obj->stop_tasks){ + bool dummy; + xQueueReceive(link_layer_obj->manual_broadcasts, &dummy, pdMS_TO_TICKS(RIP_BROADCAST_INTERVAL)); //wait up to RIP_BROADCAST_INTERVAL ms + ESP_LOGI(DEBUG_LINK_TAG, "Broadcasting table..."); //debug + res = link_layer_obj->send_rip_frame(true, 0); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to broadcast rip frame"); + } + } + vTaskDelete(nullptr); +} + +[[noreturn]] void DataLinkManager::rip_ttl_decrement_task(void* args){ + DataLinkManager* link_layer_obj = static_cast(args); + if (link_layer_obj == nullptr || link_layer_obj->manual_broadcasts == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "RIP Broadacst task failed to start due to invalid pointer"); + vTaskDelete(nullptr); + } + ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP ttl decrement task"); + bool broadcast = false; + bool dummy = true; + xQueueSend(link_layer_obj->manual_broadcasts, &dummy, 0); + while(!link_layer_obj->stop_tasks){ + vTaskDelay(pdMS_TO_TICKS(RIP_MS_TO_SEC)); //run every second + for (size_t i = 1; i < RIP_MAX_ROUTES; i++){ + // ESP_LOGI(DEBUG_LINK_TAG, "Decrementing ttl on entry %d", i); + if (xSemaphoreTake(link_layer_obj->rip_table[i].row_sem, (TickType_t)RIP_MAX_SEM_WAIT) !=pdTRUE){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to get sem from entry %d", i); + continue; + } + if (link_layer_obj->rip_table[i].valid == RIP_INVALID_ROW){ + xSemaphoreGive(link_layer_obj->rip_table[i].row_sem); + 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; + } + } + + xSemaphoreGive(link_layer_obj->rip_table[i].row_sem); + } + + if (broadcast && uxQueueMessagesWaiting(link_layer_obj->manual_broadcasts) == 0){ + broadcast = false; + xQueueSend(link_layer_obj->manual_broadcasts, &dummy, 0); + } + } + vTaskDelete(nullptr); +} + +/** + * @brief This function will start the tasks required for RIP to function. + * Currently, this function will: + * - start the task to periodically broadcast the board's current copy of the RIP table to all other boards via the 4 RMT channels + * - start a task to periodically decrement the ttl values of each row in the RIP table (WIP) - this will require some sort of mutex on the table itself + */ +void DataLinkManager::start_rip_tasks(){ + manual_broadcasts = xQueueCreate(2, sizeof(bool)); + + ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP Broadcast task"); + xTaskCreate(DataLinkManager::rip_broadcast_timer_function, "RIPBroadcast", 4096, static_cast(this), 5, &rip_broadcast_task); + ESP_LOGI(DEBUG_LINK_TAG, "Starting RIP TTL task"); + xTaskCreate(DataLinkManager::rip_ttl_decrement_task, "RIPTTL", 2048, static_cast(this), 5, &rip_ttl_task); +} \ No newline at end of file diff --git a/components/dataLink/DataLinkScheduler.cpp b/components/dataLink/DataLinkScheduler.cpp new file mode 100644 index 0000000..2f30f03 --- /dev/null +++ b/components/dataLink/DataLinkScheduler.cpp @@ -0,0 +1,223 @@ +#include "DataLinkManager.h" +#include "esp_log.h" +#include "esp_timer.h" +#include "freertos/semphr.h" + +void DataLinkManager::init_scheduler(){ + for (int i = 0; i < num_channels; i++){ + sq_handle[i] = xSemaphoreCreateMutex(); + async_rx_queue_mutex[i] = xSemaphoreCreateMutex(); + } + + ESP_LOGI(DEBUG_LINK_TAG, "Starting Frame Scheduler task"); + xTaskCreate(DataLinkManager::frame_scheduler, "Scheduler", 4096, static_cast(this), 5, &scheduler_task); + xTaskCreate(DataLinkManager::receive_thread_main, "Scheduler", 8192, static_cast(this), 5, &receive_task); +} + +[[noreturn]] void DataLinkManager::frame_scheduler(void* args){ + DataLinkManager* link_layer_obj = static_cast(args); + if (link_layer_obj == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Frame Scheduler failed to start due to invalid pointer"); + vTaskDelete(nullptr); + } + + ESP_LOGI(DEBUG_LINK_TAG, "Starting Frame Scheduler task"); + while(!link_layer_obj->stop_tasks){ + for (uint8_t i = 0; i < link_layer_obj->num_channels; i++){ + link_layer_obj->scheduler_send(i); + } + vTaskDelay(pdMS_TO_TICKS(SCHEDULER_PERIOD_MS)); + + } + vTaskDelete(nullptr); + +} + +/** + * @brief Pushes a frame to the scheduler + * + * @param frame + * @param channel + * @return esp_err_t + */ +esp_err_t DataLinkManager::push_frame_to_scheduler(SchedulerMetadata frame, uint8_t channel){ + if (frame.data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Frame data is null"); + return ESP_ERR_INVALID_ARG; + } + + if (channel >= num_channels){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid channels"); + return ESP_ERR_INVALID_ARG; + } + + if (frame.len == 0){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid Frame Length"); + + return ESP_ERR_INVALID_ARG; + } + + int64_t now = esp_timer_get_time(); + frame.enqueue_time_ns = now; + + if (sq_handle[channel] == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Invalid scheduler queue handle"); + return ESP_FAIL; + } + + if (xSemaphoreTake(sq_handle[channel], pdMS_TO_TICKS(SCHEDULER_MUTEX_WAIT)) == pdTRUE){ + frame_queue[channel].push(frame); + xSemaphoreGive(sq_handle[channel]); + } else { + //Failed to obtain mutex + ESP_LOGE(DEBUG_LINK_TAG, "Failed to get mutex"); + return ESP_ERR_TIMEOUT; + } + + // ESP_LOGI(DEBUG_LINK_TAG, "Pushed frame to queue on channel %d", channel); + + return ESP_OK; +} + +esp_err_t DataLinkManager::scheduler_send(uint8_t channel){ + if (phys_comms == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to send frame due to no RMT object"); + return ESP_ERR_INVALID_ARG; + } + + if (sq_handle[channel] == nullptr){ + return ESP_FAIL; + } + + SchedulerMetadata frame; + + if (xSemaphoreTake(sq_handle[channel], pdMS_TO_TICKS(SCHEDULER_MUTEX_WAIT)) == pdTRUE){ + if (frame_queue[channel].empty()){ + xSemaphoreGive(sq_handle[channel]); + // ESP_LOGI(DEBUG_LINK_TAG, "Scheduler queue for channel %d is empty", channel); + return ESP_OK; + } + frame = frame_queue[channel].top(); + frame_queue[channel].pop(); + xSemaphoreGive(sq_handle[channel]); + } else { + ESP_LOGE(DEBUG_LINK_TAG, "Failed to get mutex when trying to send"); + //Failed to obtain mutex + return ESP_ERR_TIMEOUT; + } + + if (frame.data == nullptr){ + ESP_LOGE(DEBUG_LINK_TAG, "Data array does not exist"); + return ESP_ERR_INVALID_ARG; + } + + if (this_board_id == PC_ADDR){ + ESP_LOGE(DEBUG_LINK_TAG, "This board is not assigned a board id"); + vPortFree(frame.data); + return ESP_ERR_INVALID_ARG; + } + + esp_err_t res; + bool isControlFrame = IS_CONTROL_FRAME(static_cast(frame.header.type_flag)); + + size_t frame_size = isControlFrame ? sizeof(ControlFrame) : sizeof(GenericFrame); + uint8_t send_data[frame_size]; + + if (isControlFrame){ + //control frame + + res = create_control_frame(frame.data, frame.len, + make_control_frame_from_header(frame.header), send_data, &frame_size); + + vPortFree(frame.data); + + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to create control frame"); + return res; + } + + // ESP_LOGI(DEBUG_LINK_TAG, "Sending %d bytes", frame_size); + } else { + //generic frame + + if (frame.len > MAX_CONTROL_DATA_LEN){ + //fragment here + uint16_t curr_offset = frame.generic_frame_data_offset; + uint16_t fragment_size = 0; + + //calculate fragment data size + if (curr_offset + MAX_CONTROL_DATA_LEN <= frame.len){ + fragment_size = curr_offset + MAX_CONTROL_DATA_LEN; + } else { + fragment_size = frame.len - curr_offset; + } + + //create fragment + res = create_generic_frame(frame.data, fragment_size, + make_generic_frame_from_header(frame.header), curr_offset, send_data, &frame_size); + + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to create generic frame fragment"); + vPortFree(frame.data); //free entire data for now - will need to implement retries/sliding window soon + return res; + } + + //need to schedule the next fragment + if (curr_offset != MAX_CONTROL_DATA_LEN){ + frame.generic_frame_data_offset += fragment_size; + frame.header.frag_info += 1; //increment frag_num + res = push_frame_to_scheduler(frame, channel); + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to schedule next generic frame fragment"); + vPortFree(frame.data); //free entire data for now - will need to implement retries/sliding window soon + return res; + } + + } else { + //Done fragmenting, can free data array + vPortFree(frame.data); + } + + } else { + res = create_generic_frame(frame.data, frame.len, + make_generic_frame_from_header(frame.header), 0, send_data, &frame_size); + vPortFree(frame.data); + } + + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to create generic frame"); + return 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 + } + }; + if (frame.header.receiver_id == BROADCAST_ADDR){ + // printf("Sending on channel %d\n", i); + phys_comms->send(send_data, frame_size, &config, channel); + + } else { + res = route_frame(frame.header.receiver_id, &channel_to_route); + + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to find entry for %d", frame.header.receiver_id); + return ESP_FAIL; + } + // ESP_LOGI(DEBUG_LINK_TAG, "Sending message to %d", frame.header.receiver_id); + phys_comms->send(send_data, frame_size, &config, channel_to_route); + } + + if (res != ESP_OK){ + ESP_LOGE(DEBUG_LINK_TAG, "Failed to send message"); + return ESP_FAIL; + } else{ + // printf("Sent message to board %d\n", frame.header.receiver_id); + } + + return ESP_OK; +} diff --git a/components/dataLink/README.md b/components/dataLink/README.md index e75270d..0da772f 100644 --- a/components/dataLink/README.md +++ b/components/dataLink/README.md @@ -1,3 +1,5 @@ +WIP + # Data Link Layer This component represents the data link layer. It will handle board to board communication (abstracting away the RMT specific details of transmitting physical raw bits over wires). @@ -8,14 +10,27 @@ See `./include/Frames.h` for frame definitions. There will be two types of frames: Control and Generic. -Control frames will contain all control information (eg. Spinning a DC motor, moving a servo to a particular angle, sensor information). These frames will have a limit of 32B of data size with a total packet size of 41B. These frames will not be fragmented. +Control frames will contain all control information (eg. Spinning a DC motor, moving a servo to a particular angle, sensor information). These frames will have a limit of 256B of data size with a total packet size of 41B. These frames will not be fragmented. -Generic frames will contain all other information. They will have a max data size of 8KiB with a total packet size of 8206B (8.013672 KiB). These frames can be fragmented. +Generic frames will contain all other information. They will have a max data size of 16MiB if fragmented (max 2**16 fragments). Each fragment will still maintain a max 256B data size. To differentiate between the two frames, the `type` field in both frames will be compared against. If the MSB is set to 1, it will be determined to be a control packet. ## Routing Information Protocol (RIP) Table -See `./include/Tables.h` for table definitions. +See `./include/Tables.h` for table definitions. See `DataLinkRIP.cpp` for function definitions. + +It handles all known (advertised) boards on the same network of ESP32-S3 boards. It will broadcast its stored routing table to its neighbours roughly every 30 seconds or upon receiving a routing table from its neighbours. All routes on a routing table will expire after 180 seconds, unless refreshed/updated/re-advertised by that respective board. The routing table itself will be used to route frames using the path with the least number of hops (known locally). + +## Frame Management + +See `DataLinkFrames.cpp` for more information. + +It handles generic frame fragmentation, user handling of receiving received frames (stored in a queue, per channel), and a thread to handle polling the available channels for receiving. + +### Send Frames Scheduler + +See `DataLinkScheduler.cpp` for more information. + +It handles all TX frames passed from the user and schedules them to be sent. The frames are stored in a priority queue (per channel), where Control frames has a higher priority than Generic frames (generally). The actual scheduler algorithm can be found in `Scheduler.h`. -WIP \ No newline at end of file diff --git a/components/dataLink/include/DataLinkManager.h b/components/dataLink/include/DataLinkManager.h index f545f41..6b7aeec 100644 --- a/components/dataLink/include/DataLinkManager.h +++ b/components/dataLink/include/DataLinkManager.h @@ -11,11 +11,14 @@ #include "Frames.h" #include "Tables.h" #include "RMTManager.h" +#include +#include "Scheduler.h" #define DEBUG_LINK_TAG "LinkLayer" #define CRC_POLYNOMIAL 0x1021 +//look up table for crc static const uint16_t crc16_table[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, @@ -33,8 +36,15 @@ static const uint16_t crc16_table[256] = { 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; //look up table for crc +}; +#define ASYNC_QUEUE_WAIT_TICKS 100 + +/** + * @brief Class to represent the Data Link Layer + * + * @author Justin Chow + */ class DataLinkManager{ public: DataLinkManager(uint8_t board_id, uint8_t num_channels); @@ -42,37 +52,36 @@ class DataLinkManager{ esp_err_t send(uint8_t dest_board, uint8_t* data, uint16_t data_len, FrameType type, uint8_t flag); esp_err_t start_receive_frames(uint8_t curr_channel); esp_err_t receive(uint8_t* data, size_t data_len, size_t* recv_len, uint8_t curr_channel); - esp_err_t print_frame_info(uint8_t* data, size_t data_len, uint8_t* message); - esp_err_t get_network_toplogy(RIPRow_public_matrix* matrix, size_t* matrix_size); + esp_err_t print_frame_info(uint8_t* data, size_t data_len, uint8_t* message, size_t message_len); esp_err_t get_routing_table(RIPRow_public* table, size_t* table_size); + esp_err_t async_receive_info(uint16_t* frame_size, FrameHeader* header, uint8_t channel); + esp_err_t async_receive(uint8_t* data, uint16_t data_len, FrameHeader* header, uint8_t channel); private: uint8_t this_board_id = 0; uint8_t num_channels = MAX_CHANNELS; - //std::priority_queue, FrameCompare> frame_queue; //create a priority queue - not in use std::unique_ptr phys_comms; std::unordered_map sequence_num_map; + + volatile bool stop_tasks = false; //used by the tasks to know when to stop (set true when DataLinkManager is destroyed) + TaskHandle_t rip_broadcast_task = NULL; + TaskHandle_t rip_ttl_task = NULL; esp_err_t set_board_id(uint8_t board_id); esp_err_t get_board_id(uint8_t& board_id); void print_binary(uint8_t byte); void print_buffer_binary(const uint8_t* buffer, size_t length); - esp_err_t get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size, frame_header* header); + esp_err_t get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size, FrameHeader* header); esp_err_t geneate_crc_16(uint8_t* data, size_t data_len, uint16_t* crc); + esp_err_t create_control_frame(uint8_t* data, uint16_t data_len, ControlFrame control_frame, uint8_t* send_data, size_t* send_data_len); + esp_err_t create_generic_frame(uint8_t* data, uint16_t data_len, GenericFrame generic_frame, uint16_t offset, uint8_t* send_data, size_t* send_data_len); //==== RIP related functions ==== - /** - * TODO for RIP: - * Periodic Routing Updates via timer (broadcast routing table every 30 seconds) - * Handle RIP table updates when a RIP table arrives (ensure there are no loops between boards of sending tables back and forth) - * TTL handling and route expiration - * TTLs in all rows should decrement at once via timer - */ - 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_reset_entry_ttl(uint8_t board_id); + esp_err_t rip_get_row(RIPRow** entry, uint8_t row_num); //this is stored locally with metadata `ttl` // std::unordered_map rip_table; //using a hash map to store the routes to other boards - will be used as we scale up @@ -87,6 +96,95 @@ class DataLinkManager{ QueueHandle_t discovery_tables; esp_err_t route_frame(uint8_t dest_id, uint8_t* channel_to_send); + + //==== Frame Scheduling related functions ==== + + /** + * @brief Priority queue for each channel to schedule when to send frames + * + */ + std::priority_queue, FrameCompare> frame_queue[MAX_CHANNELS]; + SemaphoreHandle_t sq_handle[MAX_CHANNELS]; + void init_scheduler(); + esp_err_t push_frame_to_scheduler(SchedulerMetadata frame, uint8_t channel); + TaskHandle_t scheduler_task = NULL; + /** + * @brief Schedules which frame to send + * + * Scheduler: + * - All frames will be pushed to the back onto a queue + * - When a generic frame sends a chunk, it will be pushed back to the queue for the next chunk to be sent + * + * Scheduling may change (above scheduler will lead to starvation of control frames depending on the number of generic frames/fragments to send) + */ + [[noreturn]] static void frame_scheduler(void* args); + /** + * @brief Scheduler sending the actual frame at the top of the heap on a channel + * + * @return esp_err_t + */ + esp_err_t scheduler_send(uint8_t channel); + + //Generic Frame Receive Fragments + + /** + * @brief Store a fragment that has been received + * + * @param fragment + * @param channel + * @return esp_err_t + */ + esp_err_t store_fragment(GenericFrame* fragment, uint8_t channel); + + /** + * @brief Stores generic frame fragments + * + * Mapping: + * Board ID -> Sequence number -> Array of Generic Frame Fragments, with size of the number of expected fragments + * + * TODO: + * - When receiving a fragment, insert it into the map + * - When all fragments have been received in a sequence, remove the entire entry (sequence) from the map, and push final data for async receive + * - Sliding window + ACKs + * + */ + std::unordered_map> fragment_map; + + esp_err_t complete_fragment(uint16_t board_id, uint16_t sequence_num, uint8_t channel); + + SemaphoreHandle_t async_rx_queue_mutex[MAX_CHANNELS]; + + //Async receive + /** + * @brief Queue to store complete received frame data + * + * TODO: + * - Replace the public `receive()` with the `async_receive()`. + * + */ + std::queue async_receive_queue[MAX_CHANNELS]; + + esp_err_t start_receive_frames_rmt(uint8_t curr_channel); + + /** + * @brief Receive thread entry point + * + * @param args + */ + [[noreturn]] static void receive_thread_main(void* args); + + /** + * @brief Receive bytes from Physical Layer (RMT) + * + * @note This replaces the deprecated `receive` function + * + * @param channel Physical channel pair to look at + * @return esp_err_t + */ + esp_err_t receive_rmt(uint8_t channel); + + TaskHandle_t receive_task = NULL; + }; #endif //DATA_LINK diff --git a/components/dataLink/include/Frames.h b/components/dataLink/include/Frames.h index 5790478..422aec2 100644 --- a/components/dataLink/include/Frames.h +++ b/components/dataLink/include/Frames.h @@ -1,13 +1,21 @@ #ifdef DATA_LINK +#pragma once +#include "freertos/FreeRTOS.h" +#include +#include +#include #define BROADCAST_ADDR 0xFF //used for discovery (finding the board's neighbours). this will mean the board ids will have 2^8-2 = 254 unique IDs that could be assigned #define PC_ADDR 0x0 //setting 0 to be the PC #define START_OF_FRAME 0xAB //0b1010_1011 - denotes the start of frame -#define MAX_GENERIC_DATA_LEN (1 << 16) //Max 65.5KiB #define MAX_CONTROL_DATA_LEN (1 << 8) // Max 256B +#define MAX_GENERIC_NUM_FRAG (1 << 16) // Max 2**16 Fragments can be made with a generic frame (total 2**16 *MAX_CONTROL_DATA_LEN B of data can be sent ~ 16 MiB) + +#define MAX_FRAME_QUEUE_SIZE 15 //Size of the queue for the frame scheduler (per channel) + //Flags #define FLAG_FRAG 0x8 //0b1000 //this fragmented frame is part of a larger frame #define FLAG_DISCOVERY 0x4 //0b0100 @@ -20,7 +28,7 @@ #define IS_CONTROL_FRAME(x) (((x) & 0x80) != 0) #define CONTROL_FRAME_OVERHEAD 9 -#define GENERIC_FRAME_OVERHEAD 12 +#define GENERIC_FRAME_OVERHEAD 14 #define CONTROL_FRAME_TYPE 0x80 //if the frame type MSB is set to 1, use the control frame //Types (total 2^4 = 16 different types) @@ -45,7 +53,7 @@ typedef struct _control_frame{ uint16_t data_len; //Data Length (max 256B) uint8_t data[MAX_CONTROL_DATA_LEN]; //Variable Length of Data uint16_t crc_16; //CRC-16 -} control_frame; //this will have a max size of 9 + 256B = 265B +} ControlFrame; //this will have a max size of 9 + 256B = 265B typedef struct _data_link_frame{ uint8_t preamble; //Start of Frame @@ -53,11 +61,12 @@ typedef struct _data_link_frame{ uint8_t receiver_id; //receiver board id uint16_t seq_num; //sequence number to differentiate frames being sent from sender to receiver uint8_t type_flag; //(type << 4) | flag - both are 4 bits - uint16_t frag_info; //(total_frag_num << 8) | frag_num - total_frag_num denotes the total number of fragmented frames to expect for this sequence number(?) and frag_num denotes the fragment frame num + uint16_t total_frag; //total number of fragments for this sequence + uint16_t frag_num; //current fragment number uint16_t data_len; //Data Length (max 178B) - uint8_t data[MAX_GENERIC_DATA_LEN]; //Variable Length of Data + uint8_t data[MAX_CONTROL_DATA_LEN]; //Variable Length of Data uint16_t crc_16; //CRC-16 -} data_link_frame; //this will have a max size of ~65.5KiB +} GenericFrame; //this will have a max size of 14 + 2^8 B = 270 B #pragma pack(pop) typedef struct _header{ @@ -66,8 +75,26 @@ typedef struct _header{ uint8_t receiver_id; //receiver board id uint16_t seq_num; //sequence number to differentiate frames being sent from sender to receiver uint8_t type_flag; //(type << 4) | flag - both are 4 bits - uint16_t frag_info; //(total_frag_num << 8) | frag_num - total_frag_num denotes the total number of fragmented frames to expect for this sequence number(?) and frag_num denotes the fragment frame num + uint32_t frag_info; //(total_frag_num << 16) | frag_num - total_frag_num denotes the total number of fragmented frames to expect for this sequence number(?) and frag_num denotes the fragment frame num uint16_t data_len; //Data Length (max 178B) uint16_t crc_16; //CRC-16 -} frame_header; +} FrameHeader; + +using Frame = std::variant; + +ControlFrame make_control_frame_from_header(const FrameHeader& header); + +GenericFrame make_generic_frame_from_header(const FrameHeader& header); + +typedef struct _fragment_metadata { + std::vector fragments; + uint16_t num_fragments_rx; +} FragmentMetadata; + +typedef struct _receive_metadata{ + uint8_t* data; + uint16_t data_len; + FrameHeader header; +} Rx_Metadata; + #endif //DATA_LINK \ No newline at end of file diff --git a/components/dataLink/include/Scheduler.h b/components/dataLink/include/Scheduler.h new file mode 100644 index 0000000..a05059a --- /dev/null +++ b/components/dataLink/include/Scheduler.h @@ -0,0 +1,67 @@ +#ifdef DATA_LINK +#include "Frames.h" +#include "esp_timer.h" +#include + +//TODO: need to make a private send() to accept a Frame type. +//the public send() is fine to keep but needs to be modified to simply create the Frame type based on the flags, data size, and args, and then push to the priority queue based on routing +//TODO: receive also needs to be updated, when receiving a frame not destined for that board; need to route that frame towards the actual destination (requires pushing that frame onto the priority queue) +//TODO: generic frames receive needs to be created (handle fragmenting, resend on corruption). ethe resend on corruption will be a lot of work as it requires ACK frames to be send and currently there is 0 support for ACK since we don't save any recently sent frames (can't resend) + +#define SCHEDULER_MUTEX_WAIT 10 //max time duration to wait +#define SCHEDULER_PERIOD_MS 25 + +//Metadata representing the frame to be sent but is currently scheduled +typedef struct _frame_scheduler_metadata { + FrameHeader header; //header of the frame + uint16_t generic_frame_data_offset; //For data greater than MAX_CONTROL_DATA_LEN to keep track of fragment positions + int64_t enqueue_time_ns; //when the frame has been first enqueued into the priority queue + uint8_t* data; //dyanmically allocated memory - contains the actual data + uint16_t len; // length of the actual data +} SchedulerMetadata; + +typedef struct _frame_compare { + /** + * @brief Uses aging based priority scheduling (linearly increasing priority with time) + * + * $P_f = B_f - A_f\alpha$ + * + * - $P_f$ is the effective priority value (lower comes first) + * + * - $B_f$ is the base priority + * + * - $A_f$ is the age (amount of time the frame has waited in the queue) + * + * - $\alpha$ is the aging factor (rate at which a frame increases priority) + * + * @param a + * @param b + * @return true + * @return false + */ + bool operator()(const SchedulerMetadata& a, const SchedulerMetadata& b) const { + int64_t now = esp_timer_get_time(); + double age_a = (now - a.enqueue_time_ns) / 1e6; + double age_b = (now - a.enqueue_time_ns) / 1e6; + + // Base priorities: lower is higher priority + double base_a = (IS_CONTROL_FRAME(a.header.type_flag)) ? 0.0 : 10.0; + double base_b = (IS_CONTROL_FRAME(b.header.type_flag)) ? 0.0 : 10.0; + + // Aging coefficient (tune this) + constexpr double aging_factor = 0.1; + + double effective_a = base_a - age_a * aging_factor; + double effective_b = base_b - age_b * aging_factor; + + // If effective priority equal, fall back to enqueue time (FIFO) + if (effective_a == effective_b) { + return a.enqueue_time_ns > b.enqueue_time_ns; + } + + // Return true if a has *lower* priority (so b stays on top) + return effective_a < effective_b; + } +} FrameCompare; + +#endif //DATA_LINK \ No newline at end of file diff --git a/components/dataLink/test/CMakeLists.txt b/components/dataLink/test/CMakeLists.txt new file mode 100644 index 0000000..3b66529 --- /dev/null +++ b/components/dataLink/test/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRC_DIRS "." + INCLUDE_DIRS "." + REQUIRES unity dataLink rmt esp_event) \ No newline at end of file diff --git a/components/dataLink/test/test_dataLink.cpp b/components/dataLink/test/test_dataLink.cpp new file mode 100644 index 0000000..b448729 --- /dev/null +++ b/components/dataLink/test/test_dataLink.cpp @@ -0,0 +1,29 @@ +#include "unity.h" +#include "DataLinkManager.h" +#include + +#define TEST_BOARD_ID 69 + +std::unique_ptr createObj(){ + std::unique_ptr obj = std::make_unique(TEST_BOARD_ID, 4); + TEST_ASSERT_NOT_NULL(obj.get()); + return obj; +} + +TEST_CASE("should instantiate an DataLinkManager object with 4 channels", "[dataLink]"){ + createObj(); +} + +// void board_a(){ +// std::unique_ptr obj = createObj(); +// unity_send_signal("board a"); +// unity_wait_for_signal("board b"); +// } + +// void board_b(){ +// std::unique_ptr obj = createObj(); +// unity_send_signal("board b"); +// unity_wait_for_signal("board a"); +// } + +// TEST_CASE_MULTIPLE_DEVICES("should be able to send tables to another board and receive it", "[dataLink]", board_a, board_b); \ No newline at end of file diff --git a/components/rmt/README.md b/components/rmt/README.md index 8b07f25..7c1ac4d 100644 --- a/components/rmt/README.md +++ b/components/rmt/README.md @@ -4,38 +4,28 @@ WIP The related ESP32-S3 latest documentation on RMT can be found [here](https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/rmt.html). -## Encoding -Using the Ethernet Manchester encoding method where a bit 1 is encoded as a falling edge transition (high -> low) and a bit 0 is encoded as a rising edge transition (low -> high). +# About -Specific timings are defined in `RMTSymbols.h` but it has been tested with 10us intervals (each symbol has length 20us) with 1MHz resolution. +This component is a wrapper around the ESP32-S3 RMT API and allows the operation of a physical layer between multiple ESP32-S3 microcontrollers. The goal of this component is to enable network communication encapsulation with higher and more abstract types of communication frames/packets (eg. link layer, application layer). -Physical Layer will be using Manchester encoding (see the doc/detailed_design_timeline document for more information). +## Encoding Method -### Testing with other Encoding Methods -We may test and compare with other encoding methods to see which has better performance. Currently, we are using manchester at 1MHz resolution - probably good enough for 10Mbps? (needs to be tested) +RMT uses the Ethernet Manchester encoding method, where a bit 1 is encoded as a falling edge transition and a bit 0 is encoded as a rising edge transition. -The following are some potential other encoding methods (inspired from http://units.folder101.com/cisco/sem1/Notes/ch7-technologies/encoding.htm) -- Manchester with shorter symbol durations (and with higher resolutions?) - Used by 100Mbps Ethernet -- NRZ Inverted - Used by 100BASE-FX networks -- 8b/10b with NRZ - Used by 1000BASE-X +Specific timings are defined in `RMTSymbols.h`, which includes bit timings, resolution HZ, and symbol definitions. -## Transceiver Operations -We are currently only using one channel for TX and one channel for RX. This will be changed in the future to use multiple channels at the same time (transmitting separate data however/transmitting independent of each other). +## Usage -Currently, TX is being transmitted from `RMT_TX_GPIO` and RX being received from `RMT_RX_GPIO`. +This component is not meant to be used directly by the user (should only be exclusively be used by the Link Layer, found in `components/dataLink`). -## Completed Encoding Methods -- Manchester -- NRZ-I +For specific details, see `dataLink/DataLinkManager.cpp`. -## Testing -Use `-D TIME_TEST=1` to measure the average transmission rate (over 1000 iterations) on a chosen encoding scheme. +## Channel Configurations -To change encoding schemes, use one of the following compiler flags: -- `MANCHESTER_40=1` for 40MHz resolution Manchester -- `NRZ-INVERTED=1` for Non-Return-to-Zero Inverted -- with no specified encoding schemes, the program will use Manchester at 1MHz resolution. +RMT relies on the ESP32-S3's GPIO pins. This RMT component statically sets a predefined GPIO pin to either a TX or RX for a channel. -### Notes -You may need to perform a `idf.py clean` or `idf.py fullclean` to undefine the unwanted compiler flags previously set (eg. when changing encoding schemes or not running the time test) +For TX/RX pin definitions, see `RMTManager.h`. For example, `tx_gpio[]` is a `4` length array. Each index in the array represents one half of a pair that represents the TX/RX channel on the physical layer. +## RMT Internal Async Jobs + +See the ESP32-S3 RMT documentation for more information. RMT relies on callback functions to notify the encoding/decoding on TX/RX respectively is completed, or to perform the actual encoding and decoding/char translations. \ No newline at end of file diff --git a/components/rmt/RMTManager.cpp b/components/rmt/RMTManager.cpp index e494134..3129013 100644 --- a/components/rmt/RMTManager.cpp +++ b/components/rmt/RMTManager.cpp @@ -30,6 +30,9 @@ esp_err_t RMTManager::init_tx_channel(){ esp_err_t res_tx = ESP_FAIL; memory_to_free = xQueueCreate(15, sizeof(uint8_t*)); + xTaskCreate(RMTManager::freeMemory, "RIPFreeMem", 4096, static_cast(memory_to_free), 5, NULL); + memory_to_free = xQueueCreate(15, sizeof(uint8_t*)); + xTaskCreate(RMTManager::freeMemory, "RIPFreeMem", 4096, static_cast(memory_to_free), 5, NULL); for (uint8_t i = 0; i < num_channels; i++){ @@ -104,7 +107,7 @@ esp_err_t RMTManager::init_tx_channel(){ .tx_done_sem = channels[i].tx_done_semaphore, .transmit_queue = channels[i].tx_queue, .tx_context = &channels[i].encoder_context, - .free_mem_queue = memory_to_free + .free_mem_queue = memory_to_free, }; if (channels[i].tx_done_semaphore == NULL){ @@ -150,9 +153,12 @@ bool RMTManager::rmt_tx_done_callback(rmt_channel_handle_t channel, const rmt_tx QueueHandle_t free_queue = args->free_mem_queue; TxBuffer buf = {}; + BaseType_t xTaskWokenByReceive = pdFALSE; + // xSemaphoreTakeFromISR(mutex, &xTaskWokenByReceive); xQueueReceiveFromISR(queue, static_cast(&buf), &xTaskWokenByReceive); //remove from the queue - + // xSemaphoreGiveFromISR(mutex, &xTaskWokenByReceive); + if (buf.data != nullptr){ xQueueSendFromISR(free_queue, &buf.data, &xTaskWokenByReceive); } @@ -397,10 +403,10 @@ esp_err_t RMTManager::send(uint8_t* data, size_t size, rmt_transmit_config_t* co return ESP_FAIL; } - memcpy((void*)(new_data_to_send_buf.data), data, size); + memcpy(new_data_to_send_buf.data, data, size); - if (xQueueSendToBack(channels[channel_num].tx_queue, (void*)&new_data_to_send_buf, (TickType_t) 10) != pdPASS){ - vPortFree((void*)new_data_to_send_buf.data); + if (xQueueSendToBack(channels[channel_num].tx_queue, &new_data_to_send_buf, (TickType_t) MUTEX_MAX_WAIT_TICKS) != pdPASS){ + vPortFree(new_data_to_send_buf.data); ESP_LOGE(DEBUG_TAG, "Failed to queue data"); return ESP_FAIL; } @@ -528,12 +534,12 @@ esp_err_t RMTManager::start_receiving(uint8_t channel_num){ } if (channels[channel_num].status == CHANNEL_LISTENING){ - return ESP_OK; //failed to receive earlier; no need to start the async rx job again (alreayd running) + return ESP_ERR_NOT_FINISHED; } if (channels[channel_num].status == CHANNEL_NOT_READY_STATUS){ ESP_LOGE(DEBUG_TAG, "RX Channel is not ready"); - return ESP_FAIL; + return ESP_ERR_INVALID_STATE; } if (channels[channel_num].rx_rmt_handle == NULL){ @@ -544,7 +550,6 @@ esp_err_t RMTManager::start_receiving(uint8_t channel_num){ esp_err_t res = rmt_receive(channels[channel_num].rx_rmt_handle, channels[channel_num].raw_symbols, sizeof(channels[channel_num].raw_symbols), &this->receive_config); if (res != ESP_OK){ - // printf("Failed to start receive\n"); ESP_LOGE(DEBUG_TAG, "Failed to start receive"); } @@ -556,7 +561,12 @@ esp_err_t RMTManager::start_receiving(uint8_t channel_num){ /** * @brief Function to get the received messages * - * @return int + * @param recv_buf Byte array of the received bytes + * @param size Size of the byte array + * @param output_size Pointer containing the received bytes (will be written) + * @param channel_num Physical channel pair to receive from + * + * @return esp_err_t */ esp_err_t RMTManager::receive(uint8_t* recv_buf, size_t size, size_t* output_size, uint8_t channel_num){ if (channel_num >= num_channels){ @@ -569,9 +579,9 @@ esp_err_t RMTManager::receive(uint8_t* recv_buf, size_t size, size_t* output_siz } rmt_rx_done_event_data_t rx_data; - if (xQueueReceive(channels[channel_num].rx_queue, &rx_data, pdMS_TO_TICKS(15000)) != pdTRUE){ //this will wait until a message has arrived or not + if (xQueueReceive(channels[channel_num].rx_queue, &rx_data, pdMS_TO_TICKS(150)) != pdTRUE){ //this will wait until a message has arrived or not // printf("Timeout occurred while waiting for RX event\n"); - ESP_LOGW(DEBUG_TAG, "Timeout occurred while waiting for RX event - didn't receive a message in time"); + // ESP_LOGE(DEBUG_TAG, "Timeout occurred while waiting for RX event - didn't receive a message in time"); return ESP_FAIL; } diff --git a/components/rmt/include/RMTManager.h b/components/rmt/include/RMTManager.h index d148234..172c1d9 100644 --- a/components/rmt/include/RMTManager.h +++ b/components/rmt/include/RMTManager.h @@ -22,6 +22,8 @@ #define QUEUE_SIZE 10 +#define MUTEX_MAX_WAIT_TICKS 100 + /** * @brief This struct keeps track of the current byte and bit index of the user data being transmmitted via RMT * @@ -66,7 +68,12 @@ typedef struct _rmt_channel{ uint8_t status; } rmt_channel; - +/** + * @brief Class representing the RMT/Physical Layer + * + * @author Justin Chow + * + */ class RMTManager{ public: RMTManager(uint8_t num_channels); @@ -100,26 +107,14 @@ 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 1,2,3,4 for channels 0,1,2,3 respectively for tx - // gpio_num_t tx_gpio[MAX_CHANNELS] = {GPIO_NUM_1}; //using pins 1,2,3,4 for channels 0,1,2,3 respectively for tx - - // rmt_encoder_context_t encoder_context = {0}; - - //semaphore to indicate it is done - // SemaphoreHandle_t tx_done_semaphore; - - //will be used to temporarily hold the bits that are being wait to be sent -- not working - // QueueHandle_t transmit_queue = NULL; + 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 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 12,13,14,15 for channels 0,1,2,3 respectively for rx - // gpio_num_t rx_gpio[MAX_CHANNELS] = {GPIO_NUM_12}; //using pins 12,13,14,15 for channels 0,1,2,3 respectively for rx - - // QueueHandle_t receive_queue = NULL; + 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 //rx_receive_config rmt_receive_config_t receive_config = { diff --git a/components/rmt/include/RMTSymbols.h b/components/rmt/include/RMTSymbols.h index 4d6f130..023141d 100644 --- a/components/rmt/include/RMTSymbols.h +++ b/components/rmt/include/RMTSymbols.h @@ -2,8 +2,8 @@ #include "driver/rmt_tx.h" -#define RMT_RESOLUTION_HZ 3 * 1000 * 1000 // 3MHz resolution -#define RMT_DURATION_SYMBOL 1 //0.667us +#define RMT_RESOLUTION_HZ 4 * 1000 * 1000 // 4 MHz resolution +#define RMT_DURATION_SYMBOL 2 //1 us #define RMT_DURATION_MAX (2 * RMT_DURATION_SYMBOL) diff --git a/main/README.md b/main/README.md index 428ea46..4e0756e 100644 --- a/main/README.md +++ b/main/README.md @@ -1,5 +1,3 @@ -# RMT Sample Code +# Data Link Sample Code -WIP - -Creates 2 threads per channel (there are 4 channels - 4 TX and 4 RX). Each tx thread is sending messages and the corresponding rx thread will receive the message and print its contents if it is a valid frame. \ No newline at end of file +See `main_rmt_test.cpp` for more details for Data Link Layer usage. \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp index d85d9e9..72edcf2 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,5 +1,5 @@ -#include -#include +// #include +// #include #include "freertos/FreeRTOS.h" #include "sdkconfig.h" diff --git a/main/main_rmt_test.cpp b/main/main_rmt_test.cpp index 8b1ac5e..bbee486 100644 --- a/main/main_rmt_test.cpp +++ b/main/main_rmt_test.cpp @@ -18,7 +18,10 @@ // #include "esp_log.h" // #define DATA_SIZE_TEST 270 -// #define BOARD_ID 1 +// //current board id +// #define BOARD_ID 69 +// //board id to send to +// #define RECEIVER_BOARD_ID 1 // struct TaskArgs{ // DataLinkManager* link_layer_obj; @@ -30,6 +33,7 @@ // struct ReceviedFrame{ // uint8_t buf[MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD]; //max 41B // size_t len; +// FrameHeader header; // }; // void receive_frames(void* arg){ @@ -51,41 +55,39 @@ // uint8_t recv_buf[DATA_SIZE_TEST]; // memset(recv_buf, 0, DATA_SIZE_TEST); -// size_t recv_len = 0; // ReceviedFrame recv_frame = {}; -// while(true){ -// res = obj->start_receive_frames(curr_channel); // this will be moved to a separate thread with a shared queue -// if (res != ESP_OK){ -// ESP_LOGE("thread", "Failed to start rx async job on thread %d", curr_channel); -// continue; -// } +// FrameHeader header = {}; -// res = obj->receive(recv_buf, sizeof(recv_buf), &recv_len, curr_channel); +// while(true){ +// res = obj->async_receive(recv_buf, sizeof(recv_buf), &header, curr_channel); +// vTaskDelay(pdMS_TO_TICKS(10)); // if (res != ESP_OK){ // // ESP_LOGE("thread", "Failed to receive message on thread %d", curr_channel); -// if (res != ESP_FAIL) { +// if (res != ESP_ERR_NOT_FOUND) { // recv_frame.len = 0; // if (xQueueSendToBack(shared_queue, (void*)&recv_frame, (TickType_t) 10) != pdPASS){ // ESP_LOGE("RX Job", "Failed to push received frame onto shared queue for channel %d", curr_channel); // } -// } +// } // continue; // } else { // // printf("Successfully receive message\n"); // } -// if (recv_len == 0){ +// if (header.data_len == 0){ // continue; // } -// recv_frame.len = recv_len; -// memcpy((void*)recv_frame.buf, (void*)recv_buf, recv_len); +// recv_frame.len = header.data_len; +// memcpy((void*)recv_frame.buf, (void*)recv_buf, header.data_len); +// recv_frame.header = header; // if (xQueueSendToBack(shared_queue, (void*)&recv_frame, (TickType_t) 10) != pdPASS){ // ESP_LOGE("RX Job", "Failed to push received frame onto shared queue for channel %d", curr_channel); // } + // } // } @@ -116,7 +118,7 @@ // size_t recv_len = 0; // uint8_t iteration = 0; -// esp_err_t res; +// esp_err_t res = ESP_OK; // gptimer_handle_t gptimer = NULL; // gptimer_config_t timer_config = { @@ -162,7 +164,7 @@ // // snprintf(reinterpret_cast(send_buf), sizeof(send_buf), "%s RANDOM", mej.kssage); //modifying the data while it transmits shouldn't affect the actual transmission here // if (res != ESP_OK){ -// ESP_LOGE("thread", "Failed to send message on thread %d", curr_channel); +// ESP_LOGE("thread", "Failed to send message on thread %d. Error: 0x%x", curr_channel, res); // continue; // } else { // // printf("Successfully sent message %s\n", send_buf); @@ -181,41 +183,21 @@ // //receive fail // num_incorrect++; // } else { -// res = obj->print_frame_info(recv_frame.buf, recv_frame.len, recv_buf); +// // res = obj->print_frame_info(recv_frame.buf, recv_frame.len, recv_buf, DATA_SIZE_TEST); // if (res != ESP_OK){ // num_incorrect++; // // printf("Received %ld bad frames on tx/rx round %ld for thread %d\n", num_incorrect, total_transactions, curr_channel); // } else { -// // printf("Received message %s on channel %d on round %ld. Total bad frames %ld\n", recv_buf, curr_channel, total_transactions, num_incorrect); +// // printf("Header information:\n"); +// // printf("Preamble\tTX ID\tRX ID\tSeq Num\tType/Flag\tFrag Info\tData Len\tCRC\n"); +// // printf("%X\t%d\t%d\t%d\t%X\t%ld\t%d\t%d\n",recv_frame.header.preamble, recv_frame.header.sender_id, recv_frame.header.receiver_id, recv_frame.header.seq_num, +// // recv_frame.header.type_flag, recv_frame.header.frag_info, recv_frame.header.data_len, recv_frame.header.crc_16); +// // printf("Received message '%.*s' on channel %d\n", recv_frame.len, recv_frame.buf, curr_channel); // } // } // printf("Total received packets: %ld\tTotal packets corrupted: %ld\n", total_transactions, num_incorrect); - -// // iteration++; -// // if (iteration == 10){ -// // iteration = 0; -// // // if (!receive_only){ -// // // matrix_size = RIP_MAX_ROUTES; -// // // res = obj->get_network_toplogy(matrix, &matrix_size); -// // // if (res != ESP_OK){ -// // // ESP_LOGE("multi", "Failed to get topology"); -// // // } else { -// // // for (int i = 0; i < matrix_size; i++){ -// // // printf("Table for board %d:\n", matrix[i].board_id); -// // // printf("board_id\t\tHops\t\tChannel\n"); -// // // for (int j = 0; j < matrix[i].size; j++){ -// // // printf("%d\t\t%d\t\t%d\n", matrix[i].table[j].info.board_id, matrix[i].table[j].info.hops, matrix[i].table[j].channel); -// // // } -// // // printf("=====\n"); - -// // // //reset matrix -// // // matrix[i].size = RIP_MAX_ROUTES; -// // // } -// // // } -// // // } -// // } // // vTaskDelay(1000 / portTICK_PERIOD_MS); // wait 1 second before trying to send again // //reset temp buffers @@ -282,7 +264,7 @@ // for (uint8_t i = 0; i < 1; i++){ // args[i].link_layer_obj = obj_to_send; // args[i].task_id = i; -// args[i].receiver_id = 69; +// args[i].receiver_id = RECEIVER_BOARD_ID; // args[i].receive_queue = xQueueCreate(10, sizeof(ReceviedFrame)); //queue storing up to 10 control frames // xTaskCreate(multi_transceiver, "multi_transceiver", 4096, static_cast(&args[i]), 5, NULL); // vTaskDelay(500 / portTICK_PERIOD_MS); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..4d77bf1 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.30) +set(EXTRA_COMPONENT_DIRS "../components") + +# Set the components to include the tests for. +# This can be overridden from CMake cache: +# - when invoking CMake directly: cmake -D TEST_COMPONENTS="xxxxx" .. +# - when using idf.py: idf.py -T xxxxx build +# +set(TEST_COMPONENTS "dataLink") + +set(IDF_TARGET "esp32s3") +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +idf_build_set_property(MINIMAL_BUILD ON) +project(capstone) \ No newline at end of file diff --git a/test/main/CMakeLists.txt b/test/main/CMakeLists.txt new file mode 100644 index 0000000..7e01dff --- /dev/null +++ b/test/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "main.cpp" + PRIV_REQUIRES unity nvs_flash + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/test/main/main.cpp b/test/main/main.cpp new file mode 100644 index 0000000..15d14df --- /dev/null +++ b/test/main/main.cpp @@ -0,0 +1,22 @@ +#include "unity.h" +#include "sdkconfig.h" +#include "nvs_flash.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +extern "C" [[noreturn]] void app_main(void){ + ESP_ERROR_CHECK(nvs_flash_init()); + unity_run_all_tests(); + + while(true){ + //do nothing + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + // for (int i = 5; i >= 0; i--) { + // printf("Restarting in %d seconds...\n", i); + // vTaskDelay(1000 / portTICK_PERIOD_MS); + // } + // printf("Restarting now.\n"); + // fflush(stdout); + // esp_restart(); +} \ No newline at end of file diff --git a/test/sdkconfig b/test/sdkconfig new file mode 100644 index 0000000..a82b37d --- /dev/null +++ b/test/sdkconfig @@ -0,0 +1,1938 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 5.5.1 Project Configuration +# +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +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 +CONFIG_SOC_LCDCAM_CAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y +CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_EFUSE_SUPPORTED=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_MPU_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y +CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_ADC_SHARED_POWER=y +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 +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_AHB_GDMA_VERSION=1 +CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=5 +CONFIG_SOC_AHB_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_IN_RANGE_MAX=48 +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 +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_HP_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=8 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS=y +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +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_PDM_MAX_RX_LINES=4 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_TIMER_NUM=4 +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +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 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +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_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 +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_I80_NUM_BUSES=1 +CONFIG_SOC_LCDCAM_I80_BUS_WIDTH=16 +CONFIG_SOC_LCDCAM_RGB_NUM_PANELS=1 +CONFIG_SOC_LCDCAM_RGB_DATA_WIDTH=16 +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y +CONFIG_SOC_SDM_GROUPS=1 +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +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_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +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 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_HP_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +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 +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +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 +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +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_TIMING_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y +CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y +CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_SDMMC_DELAY_PHASE_NUM=4 +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_CAM_PERIPH_NUM=1 +CONFIG_SOC_LCDCAM_CAM_DATA_WIDTH_MAX=16 +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_INIT_VERSION="5.5.1" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# + +# +# Bootloader manager +# +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 +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set + +# +# 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 +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Format +# +# 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 + +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +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_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 +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_OTG_NUM=3 +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +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 +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y +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 +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# end of Compiler options + +# +# 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 +# + +# +# Driver Configurations +# + +# +# Legacy TWAI Driver Configurations +# +# CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of Legacy TWAI Driver Configurations + +# +# Legacy ADC Driver Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration + +# +# Legacy MCPWM Driver Configurations +# +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy MCPWM Driver Configurations + +# +# Legacy Timer Group Driver Configurations +# +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations + +# +# Legacy RMT Driver Configurations +# +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations + +# +# Legacy I2S Driver Configurations +# +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations + +# +# Legacy I2C Driver Configurations +# +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + +# +# Legacy PCNT Driver Configurations +# +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy PCNT Driver Configurations + +# +# Legacy SDM Driver Configurations +# +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations + +# +# Legacy Temperature Sensor Driver Configurations +# +# 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 + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# ESP-Driver:GPIO Configurations +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +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_OBJ_CACHE_SAFE=y +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# 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 + +# +# ESP-Driver:I2S Configurations +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:LEDC Configurations +# +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:MCPWM Configurations +# +CONFIG_MCPWM_ISR_HANDLER_IN_IRAM=y +# CONFIG_MCPWM_ISR_CACHE_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 + +# +# ESP-Driver:PCNT Configurations +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations + +# +# 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 +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SPI Configurations +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Temperature Sensor Configurations +# +# 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_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 +# +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# Hardware Settings +# + +# +# Chip revision +# +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 + +# +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +# +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 + +# +# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99) +# +# end of Chip revision + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config + +# +# Sleep Config +# +# CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config + +# +# Peripheral Control +# +CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# GDMA Configurations +# +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y +CONFIG_GDMA_OBJ_DRAM_SAFE=y +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configurations + +# +# Main XTAL Config +# +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 + +# +# ESP-MM: Memory Management Configurations +# +# CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS is not set +# end of ESP-MM: Memory Management Configurations + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# 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 +CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP Ringbuf +# +# 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 +# +# end of ESP Security Specific + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160=y +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=160 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# CONFIG_ESP32S3_TRAX is not set +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 +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# 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 is not set +# CONFIG_ESP_CONSOLE_USB_CDC 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=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +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 +# CONFIG_ESP_TASK_WDT_EN is not set +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=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 +# end of IPC (Inter-Processor Call) + +# +# 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 +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=100 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port + +# +# Extra +# +# end of Extra + +CONFIG_FREERTOS_PORT=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +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 + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log +# +CONFIG_LOG_VERSION_1=y +# CONFIG_LOG_VERSION_2 is not set +CONFIG_LOG_VERSION=1 + +# +# Log Level +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 + +# +# Level Settings +# +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# CONFIG_LOG_COLORS is not set +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 + +# +# LWIP +# +CONFIG_LWIP_ENABLE=y +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=69 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 +CONFIG_LWIP_TCP_WND_DEFAULT=5760 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +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_PPP_SUPPORT is not set +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP + +# +# DNS +# +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 +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +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 +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# 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 + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y +CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set +# end of mbedTLS + +# +# LibC +# +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 + +# +# NVS +# +# CONFIG_NVS_ENCRYPTION is not set +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +# end of NVS + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# Main Flash configuration +# + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# CONFIG_SPI_FLASH_HPM_ENA is not set +CONFIG_SPI_FLASH_HPM_AUTO=y +# CONFIG_SPI_FLASH_HPM_DIS is not set +CONFIG_SPI_FLASH_HPM_ON=y +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +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 + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# 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_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y +# CONFIG_UNITY_TEST_ORDER_BY_FILE_PATH_AND_LINE is not set +# end of Unity unit testing library + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set +CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=8 + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) + +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system +# end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# 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 +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_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +# CONFIG_ESP_SYSTEM_PD_FLASH is not set +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# 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_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set +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 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_NUM=-1 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5760 +CONFIG_TCP_WND_DEFAULT=5760 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# 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 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/test/sdkconfig.defaults b/test/sdkconfig.defaults new file mode 100644 index 0000000..0d67eeb --- /dev/null +++ b/test/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_ESP_TASK_WDT_EN=n +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y \ No newline at end of file