Compare commits
5 commits
main
...
ESP-NOW_ex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
127ac028bc | ||
|
|
9885cbc419 | ||
|
|
32a0681435 | ||
|
|
a5ac8bbdb7 | ||
|
|
b998e37c3c |
113 changed files with 2622 additions and 6771 deletions
|
|
@ -38,10 +38,10 @@ This software in turn makes use of the following open-source software libraries
|
||||||
|----------------------------|--------:|--------------------------------------------------------------------------|---------------------------------------------
|
|----------------------------|--------:|--------------------------------------------------------------------------|---------------------------------------------
|
||||||
| SystemK | 1.01 | [AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later.html) | https://git.ktag.clubk.club/Software/SystemK/
|
| SystemK | 1.01 | [AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later.html) | https://git.ktag.clubk.club/Software/SystemK/
|
||||||
| ESP-IDF | 5.5.2 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://github.com/espressif/esp-idf/
|
| ESP-IDF | 5.5.2 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://github.com/espressif/esp-idf/
|
||||||
| espressif/button | 4.1.5 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/button
|
| espressif/button | 3.5.0 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/button
|
||||||
| espressif/led_strip | 2.5.3 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/led_strip
|
| espressif/led_strip | 2.5.3 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/led_strip
|
||||||
| espressif/usb_host_msc | 1.1.4 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/usb_host_msc
|
| espressif/usb_host_msc | 1.1.4 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/usb_host_msc
|
||||||
| espressif/mdns | 1.9.1 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/mdns
|
| espressif/mdns | 1.9.1 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/espressif/mdns
|
||||||
| chmorgan/esp-audio-player | 1.1.0 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/chmorgan/esp-audio-player
|
| chmorgan/esp-audio-player | 1.0.7 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://components.espressif.com/components/chmorgan/esp-audio-player
|
||||||
| esp-libhelix-mp3 | 1.0.3 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://github.com/chmorgan/esp-libhelix-mp3
|
| esp-libhelix-mp3 | 1.0.3 | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | https://github.com/chmorgan/esp-libhelix-mp3
|
||||||
| libhelix-mp3 | f443079 | [RPSL](https://github.com/chmorgan/libhelix-mp3/blob/master/LICENSE.txt) | https://github.com/chmorgan/libhelix-mp3/
|
| libhelix-mp3 | f443079 | [RPSL](https://github.com/chmorgan/libhelix-mp3/blob/master/LICENSE.txt) | https://github.com/chmorgan/libhelix-mp3/
|
||||||
|
|
|
||||||
15
components/ESP-NOW/CMakeLists.txt
Normal file
15
components/ESP-NOW/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
idf_component_register(
|
||||||
|
SRCS
|
||||||
|
"ESP-NOW.c"
|
||||||
|
INCLUDE_DIRS
|
||||||
|
"."
|
||||||
|
REQUIRES
|
||||||
|
"SystemK"
|
||||||
|
"esp_wifi"
|
||||||
|
"nvs_flash"
|
||||||
|
"esp_netif"
|
||||||
|
"esp_event"
|
||||||
|
"esp_system"
|
||||||
|
"freertos"
|
||||||
|
"NVM"
|
||||||
|
)
|
||||||
180
components/ESP-NOW/ESP-NOW.c
Normal file
180
components/ESP-NOW/ESP-NOW.c
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of the KTag project.
|
||||||
|
*
|
||||||
|
* 🛡️ <https://ktag.clubk.club> 🃞
|
||||||
|
*
|
||||||
|
* Copyright © 2025 Joseph P. Kearney and the KTag developers.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Affero General Public License as published by the Free
|
||||||
|
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* There should be a copy of the GNU Affero General Public License in the LICENSE
|
||||||
|
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <SystemK.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_mac.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_now.h"
|
||||||
|
//
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
static const char *TAG = "ESP-NOW";
|
||||||
|
|
||||||
|
// Broadcast address (all 0xFF sends to all devices)
|
||||||
|
static uint8_t Broadcast_MAC[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
|
|
||||||
|
// Structure for the data to send
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t counter;
|
||||||
|
char message[32];
|
||||||
|
} broadcast_data_t;
|
||||||
|
|
||||||
|
// ESP-NOW receive callback
|
||||||
|
static void ESPNOW_Recv_CB(const esp_now_recv_info_t *recv_info, const uint8_t *data, int len)
|
||||||
|
{
|
||||||
|
if (recv_info == NULL || data == NULL || len <= 0)
|
||||||
|
{
|
||||||
|
KLOG_ERROR(TAG, "Receive callback error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log sender MAC address
|
||||||
|
KLOG_INFO(TAG, "Received from: " MACSTR ", RSSI: %d",
|
||||||
|
MAC2STR(recv_info->src_addr), recv_info->rx_ctrl->rssi);
|
||||||
|
|
||||||
|
// Parse received data
|
||||||
|
if (len == sizeof(broadcast_data_t))
|
||||||
|
{
|
||||||
|
broadcast_data_t *recv_data = (broadcast_data_t *)data;
|
||||||
|
KLOG_INFO(TAG, "Counter: %lu, Message: %s",
|
||||||
|
recv_data->counter, recv_data->message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KLOG_WARN(TAG, "Unexpected data length: %d", len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ESP-NOW send callback
|
||||||
|
static void ESPNOW_Send_CB(const wifi_tx_info_t *tx_info, esp_now_send_status_t status)
|
||||||
|
{
|
||||||
|
if (tx_info == NULL)
|
||||||
|
{
|
||||||
|
KLOG_ERROR(TAG, "Send callback error: tx_info is NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == ESP_NOW_SEND_SUCCESS)
|
||||||
|
{
|
||||||
|
KLOG_INFO(TAG, "Send success to " MACSTR, MAC2STR(tx_info->des_addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KLOG_WARN(TAG, "Send failed to " MACSTR, MAC2STR(tx_info->des_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t Initialize_ESPNOW(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret = esp_now_init();
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
KLOG_ERROR(TAG, "ESP-NOW init failed: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register send and receive callbacks
|
||||||
|
esp_now_register_send_cb(ESPNOW_Send_CB);
|
||||||
|
esp_now_register_recv_cb(ESPNOW_Recv_CB);
|
||||||
|
|
||||||
|
// Add broadcast peer
|
||||||
|
esp_now_peer_info_t peer_info = {};
|
||||||
|
memcpy(peer_info.peer_addr, Broadcast_MAC, ESP_NOW_ETH_ALEN);
|
||||||
|
peer_info.channel = 0; // Use current channel
|
||||||
|
peer_info.ifidx = WIFI_IF_STA;
|
||||||
|
peer_info.encrypt = false;
|
||||||
|
|
||||||
|
ret = esp_now_add_peer(&peer_info);
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
KLOG_ERROR(TAG, "Failed to add broadcast peer: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
KLOG_INFO(TAG, "ESP-NOW initialized successfully");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FreeRTOS task for periodic broadcast
|
||||||
|
static void ESPNOW_Task(void *pvParameters)
|
||||||
|
{
|
||||||
|
broadcast_data_t data = {0};
|
||||||
|
TickType_t last_wake = xTaskGetTickCount();
|
||||||
|
const TickType_t period = pdMS_TO_TICKS(2000);
|
||||||
|
|
||||||
|
KLOG_INFO(TAG, "ESP-NOW task started");
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Update data
|
||||||
|
data.counter++;
|
||||||
|
snprintf(data.message, sizeof(data.message), "Broadcast #%lu", data.counter);
|
||||||
|
|
||||||
|
// Send broadcast
|
||||||
|
esp_err_t ret = esp_now_send(Broadcast_MAC, (uint8_t *)&data, sizeof(data));
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
KLOG_ERROR(TAG, "Send error: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for next period
|
||||||
|
vTaskDelayUntil(&last_wake, period);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Initialize_WiFi(void)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
|
||||||
|
KLOG_INFO(TAG, "WiFi initialized in station mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize_ESP_NOW(void)
|
||||||
|
{
|
||||||
|
Initialize_WiFi();
|
||||||
|
|
||||||
|
// Initialize ESP-NOW
|
||||||
|
if (Initialize_ESPNOW() != ESP_OK)
|
||||||
|
{
|
||||||
|
KLOG_ERROR(TAG, "ESP-NOW initialization failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable Long Range mode
|
||||||
|
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR);
|
||||||
|
esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_LR);
|
||||||
|
|
||||||
|
// Create broadcast task
|
||||||
|
xTaskCreate(ESPNOW_Task, "ESP-NOW", 4096, NULL, 5, NULL);
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* This program source code file is part of the KTag project, a DIY laser tag
|
* This program source code file is part of the KTag project.
|
||||||
* game with customizable features and wide interoperability.
|
|
||||||
*
|
*
|
||||||
* 🛡 <https://ktag.clubk.club> 🃞
|
* 🛡️ <https://ktag.clubk.club> 🃞
|
||||||
*
|
*
|
||||||
* Copyright © 2026 Joseph P. Kearney and the KTag developers.
|
* Copyright © 2025 Joseph P. Kearney and the KTag developers.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under
|
* This program is free software: you can redistribute it and/or modify it under
|
||||||
* the terms of the GNU Affero General Public License as published by the Free
|
* the terms of the GNU Affero General Public License as published by the Free
|
||||||
|
|
@ -20,4 +19,6 @@
|
||||||
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Register_System_Command(void);
|
#pragma once
|
||||||
|
|
||||||
|
void Initialize_ESP_NOW(void);
|
||||||
|
|
@ -170,11 +170,6 @@ SystemKResult_T SETTINGS_get_uint32_t(SystemKSettingID_T id, uint32_t *value)
|
||||||
result = SYSTEMK_RESULT_SUCCESS;
|
result = SYSTEMK_RESULT_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSTEMK_SETTING_DEVICE_TYPE:
|
|
||||||
*value = BLE_DEVICE_TYPE_32ESPECIAL;
|
|
||||||
result = SYSTEMK_RESULT_SUCCESS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result = SYSTEMK_RESULT_WRONG_DATATYPE;
|
result = SYSTEMK_RESULT_WRONG_DATATYPE;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -2,35 +2,14 @@ idf_component_register(
|
||||||
SRCS
|
SRCS
|
||||||
"Console.c"
|
"Console.c"
|
||||||
"Commands/Log_Command.c"
|
"Commands/Log_Command.c"
|
||||||
"Commands/KEvent_Command.c"
|
|
||||||
"Commands/System_Command.c"
|
|
||||||
INCLUDE_DIRS
|
INCLUDE_DIRS
|
||||||
"."
|
"."
|
||||||
"./Commands"
|
"./Commands"
|
||||||
REQUIRES
|
REQUIRES
|
||||||
"SystemK"
|
"SystemK"
|
||||||
"System_Events"
|
"System_Events"
|
||||||
"app_update"
|
|
||||||
"console"
|
"console"
|
||||||
"espcoredump"
|
|
||||||
"esp_netif"
|
|
||||||
"esp_pm"
|
|
||||||
"esp_timer"
|
|
||||||
"log"
|
"log"
|
||||||
"nvs_flash"
|
"nvs_flash"
|
||||||
"spi_flash"
|
|
||||||
"vfs"
|
"vfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE HAS_SYSTEMK_GIT_VERSION)
|
|
||||||
|
|
||||||
add_custom_target(generate_git_versions ALL
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
|
||||||
-DOUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/git_versions.h
|
|
||||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/generate_git_versions.cmake
|
|
||||||
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/git_versions.h
|
|
||||||
)
|
|
||||||
|
|
||||||
add_dependencies(${COMPONENT_LIB} generate_git_versions)
|
|
||||||
target_include_directories(${COMPONENT_LIB} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
* This program source code file is part of the KTag project, a DIY laser tag
|
|
||||||
* game with customizable features and wide interoperability.
|
|
||||||
*
|
|
||||||
* 🛡 <https://ktag.clubk.club> 🃞
|
|
||||||
*
|
|
||||||
* Copyright © 2026 Joseph P. Kearney and the KTag developers.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
|
||||||
* later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* There should be a copy of the GNU Affero General Public License in the LICENSE
|
|
||||||
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include "esp_console.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "SystemK.h"
|
|
||||||
|
|
||||||
static uint32_t parse_uint32(const char *str, bool *ok)
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
errno = 0;
|
|
||||||
unsigned long val = strtoul(str, &end, 10);
|
|
||||||
|
|
||||||
if (errno != 0 || end == str || *end != '\0' || val > UINT32_MAX)
|
|
||||||
{
|
|
||||||
*ok = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ok = true;
|
|
||||||
return (uint32_t)val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_usage(void)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"Usage:\n"
|
|
||||||
" KEvent <Event ID> <Event Data>\n"
|
|
||||||
" (Note that IDs may be SystemK version-dependent.)\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_KEvent(int argc, char **argv)
|
|
||||||
{
|
|
||||||
KEvent_T event;
|
|
||||||
uint32_t data;
|
|
||||||
|
|
||||||
if (argc < 2)
|
|
||||||
{
|
|
||||||
print_usage();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Parse_KEvent_ID(argv[1], &event) == SYSTEMK_RESULT_SUCCESS)
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
data = parse_uint32(argv[2], &ok);
|
|
||||||
if (ok == true)
|
|
||||||
{
|
|
||||||
event.Data = (void *)data;
|
|
||||||
Post_KEvent(&event);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("ERROR: Couldn't parse data!");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("ERROR: Couldn't parse SystemK event!");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Register_KEvent_Command(void)
|
|
||||||
{
|
|
||||||
const esp_console_cmd_t cmd = {
|
|
||||||
.command = "KEvent",
|
|
||||||
.help = "Send arbitrary KEvents by ID",
|
|
||||||
.func = &cmd_KEvent,
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* This program source code file is part of the KTag project, a DIY laser tag
|
|
||||||
* game with customizable features and wide interoperability.
|
|
||||||
*
|
|
||||||
* 🛡 <https://ktag.clubk.club> 🃞
|
|
||||||
*
|
|
||||||
* Copyright © 2026 Joseph P. Kearney and the KTag developers.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
|
||||||
* later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* There should be a copy of the GNU Affero General Public License in the LICENSE
|
|
||||||
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Register_KEvent_Command(void);
|
|
||||||
|
|
@ -1,663 +0,0 @@
|
||||||
/*
|
|
||||||
* This program source code file is part of the KTag project, a DIY laser tag
|
|
||||||
* game with customizable features and wide interoperability.
|
|
||||||
*
|
|
||||||
* 🛡 <https://ktag.clubk.club> 🃞
|
|
||||||
*
|
|
||||||
* Copyright © 2026 Joseph P. Kearney and the KTag developers.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
|
||||||
* later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* There should be a copy of the GNU Affero General Public License in the LICENSE
|
|
||||||
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "esp_console.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "esp_chip_info.h"
|
|
||||||
#include "esp_flash.h"
|
|
||||||
#include "esp_partition.h"
|
|
||||||
#include "esp_ota_ops.h"
|
|
||||||
#include "esp_app_desc.h"
|
|
||||||
#include "esp_idf_version.h"
|
|
||||||
#include "esp_pm.h"
|
|
||||||
#include "esp_sleep.h"
|
|
||||||
#include "esp_timer.h"
|
|
||||||
#include "esp_heap_caps.h"
|
|
||||||
#include "esp_mac.h"
|
|
||||||
#include "esp_netif.h"
|
|
||||||
#include "esp_core_dump.h"
|
|
||||||
#include "nvs_flash.h"
|
|
||||||
#include "linenoise/linenoise.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "git_versions.h" // Generated during the build process.
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <SystemK.h>
|
|
||||||
|
|
||||||
static void print_usage(void)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"Usage:\n"
|
|
||||||
" system chip-info - Show chip and system information\n"
|
|
||||||
" system coredump - Check coredump status\n"
|
|
||||||
" system factory-reset - Clear NVS and restart\n"
|
|
||||||
" system flash - Show flash information\n"
|
|
||||||
" system heap-caps - Show heap by capability\n"
|
|
||||||
" system hostname [name]- Show/set hostname\n"
|
|
||||||
" system mac - Show MAC addresses\n"
|
|
||||||
" system partition - List partition table\n"
|
|
||||||
" system RAM - Display heap memory usage\n"
|
|
||||||
" system reboot - Reboot the device\n"
|
|
||||||
" system reset-reason - Show last reset reason\n"
|
|
||||||
" system stats - Combined system statistics\n"
|
|
||||||
" system tasks - List FreeRTOS tasks\n"
|
|
||||||
" system uptime - Display system uptime\n"
|
|
||||||
" system version - Show firmware version\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_chip_info(void)
|
|
||||||
{
|
|
||||||
esp_chip_info_t chip_info;
|
|
||||||
esp_chip_info(&chip_info);
|
|
||||||
|
|
||||||
printf("Chip Information:\n");
|
|
||||||
printf(" Model: %s\n", CONFIG_IDF_TARGET);
|
|
||||||
printf(" Cores: %d\n", chip_info.cores);
|
|
||||||
printf(" Revision: %d\n", chip_info.revision);
|
|
||||||
printf(" Features: %s%s%s%s\n",
|
|
||||||
(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi " : "",
|
|
||||||
(chip_info.features & CHIP_FEATURE_BT) ? "BT " : "",
|
|
||||||
(chip_info.features & CHIP_FEATURE_BLE) ? "BLE " : "",
|
|
||||||
(chip_info.features & CHIP_FEATURE_IEEE802154) ? "802.15.4 " : "");
|
|
||||||
|
|
||||||
uint32_t flash_size;
|
|
||||||
if (esp_flash_get_size(NULL, &flash_size) == ESP_OK)
|
|
||||||
{
|
|
||||||
printf(" Flash: %lu MB %s\n",
|
|
||||||
flash_size / (1024 * 1024),
|
|
||||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "(embedded)" : "(external)");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_uptime(void)
|
|
||||||
{
|
|
||||||
int64_t uptime_us = esp_timer_get_time();
|
|
||||||
int64_t uptime_s = uptime_us / 1000000;
|
|
||||||
|
|
||||||
int days = uptime_s / 86400;
|
|
||||||
int hours = (uptime_s % 86400) / 3600;
|
|
||||||
int minutes = (uptime_s % 3600) / 60;
|
|
||||||
int seconds = uptime_s % 60;
|
|
||||||
|
|
||||||
printf("Uptime: %d days, %02d:%02d:%02d\n", days, hours, minutes, seconds);
|
|
||||||
printf(" (%lld seconds)\n", uptime_s);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_tasks(void)
|
|
||||||
{
|
|
||||||
#if (configUSE_TRACE_FACILITY == 1)
|
|
||||||
uint32_t task_count = uxTaskGetNumberOfTasks();
|
|
||||||
TaskStatus_t *task_array = malloc(task_count * sizeof(TaskStatus_t));
|
|
||||||
|
|
||||||
if (task_array == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to allocate memory for task list\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t total_runtime;
|
|
||||||
task_count = uxTaskGetSystemState(task_array, task_count, &total_runtime);
|
|
||||||
|
|
||||||
printf("Tasks (%lu total):\n", task_count);
|
|
||||||
printf("%-16s %5s %6s %11s %8s", "Name", "State", "Core", "Priority", "Stack");
|
|
||||||
#if (configGENERATE_RUN_TIME_STATS == 1)
|
|
||||||
printf(" %7s", "CPU%");
|
|
||||||
#endif
|
|
||||||
printf("\n");
|
|
||||||
printf("----------------------------------------------------------------\n");
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < task_count; i++)
|
|
||||||
{
|
|
||||||
const char *state_str;
|
|
||||||
switch (task_array[i].eCurrentState)
|
|
||||||
{
|
|
||||||
case eRunning:
|
|
||||||
state_str = "RUN ";
|
|
||||||
break;
|
|
||||||
case eReady:
|
|
||||||
state_str = "READY";
|
|
||||||
break;
|
|
||||||
case eBlocked:
|
|
||||||
state_str = "BLOCK";
|
|
||||||
break;
|
|
||||||
case eSuspended:
|
|
||||||
state_str = "SUSP ";
|
|
||||||
break;
|
|
||||||
case eDeleted:
|
|
||||||
state_str = "DEL ";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
state_str = "? ";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t stack_remaining = task_array[i].usStackHighWaterMark;
|
|
||||||
|
|
||||||
BaseType_t affinity = xTaskGetCoreID(task_array[i].xHandle);
|
|
||||||
|
|
||||||
printf("%-16s %5s ", task_array[i].pcTaskName, state_str);
|
|
||||||
|
|
||||||
if (affinity == tskNO_AFFINITY)
|
|
||||||
{
|
|
||||||
printf("%6s", "ANY");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("%6d", (int)affinity);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(" %11u %8lu", task_array[i].uxCurrentPriority, stack_remaining);
|
|
||||||
|
|
||||||
#if (configGENERATE_RUN_TIME_STATS == 1)
|
|
||||||
float cpu_percent = 0.0;
|
|
||||||
if (total_runtime > 0)
|
|
||||||
{
|
|
||||||
cpu_percent = (100.0 * task_array[i].ulRunTimeCounter) / total_runtime;
|
|
||||||
}
|
|
||||||
printf(" %6.1f%%", cpu_percent);
|
|
||||||
#endif
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(task_array);
|
|
||||||
#else
|
|
||||||
printf("Task listing not available (configUSE_TRACE_FACILITY not enabled)\n");
|
|
||||||
printf("Enable in menuconfig: Component config -> FreeRTOS -> Kernel\n");
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_reset_reason(void)
|
|
||||||
{
|
|
||||||
esp_reset_reason_t reason = esp_reset_reason();
|
|
||||||
|
|
||||||
printf("Reset reason: ");
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
case ESP_RST_UNKNOWN:
|
|
||||||
printf("Unknown\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_POWERON:
|
|
||||||
printf("Power-on reset\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_EXT:
|
|
||||||
printf("External pin reset\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_SW:
|
|
||||||
printf("Software reset\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_PANIC:
|
|
||||||
printf("Exception/panic\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_INT_WDT:
|
|
||||||
printf("Interrupt watchdog\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_TASK_WDT:
|
|
||||||
printf("Task watchdog\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_WDT:
|
|
||||||
printf("Other watchdog\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_DEEPSLEEP:
|
|
||||||
printf("Deep sleep reset\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_BROWNOUT:
|
|
||||||
printf("Brownout reset\n");
|
|
||||||
break;
|
|
||||||
case ESP_RST_SDIO:
|
|
||||||
printf("SDIO reset\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Code %d\n", reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_ram(void)
|
|
||||||
{
|
|
||||||
size_t free_heap = esp_get_free_heap_size();
|
|
||||||
size_t min_free_heap = esp_get_minimum_free_heap_size();
|
|
||||||
size_t largest_block = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT);
|
|
||||||
|
|
||||||
printf("Heap Memory:\n");
|
|
||||||
printf(" Free: %u bytes (%.2f KB)\n", free_heap, free_heap / 1024.0);
|
|
||||||
printf(" Minimum free: %u bytes (%.2f KB)\n", min_free_heap, min_free_heap / 1024.0);
|
|
||||||
printf(" Largest free block: %u bytes (%.2f KB)\n", largest_block, largest_block / 1024.0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_flash(void)
|
|
||||||
{
|
|
||||||
uint32_t flash_size;
|
|
||||||
if (esp_flash_get_size(NULL, &flash_size) != ESP_OK)
|
|
||||||
{
|
|
||||||
printf("Failed to get flash size\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Flash Information:\n");
|
|
||||||
printf(" Total size: %lu bytes (%.2f MB)\n", flash_size, flash_size / (1024.0 * 1024.0));
|
|
||||||
|
|
||||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
|
||||||
if (running)
|
|
||||||
{
|
|
||||||
printf(" Running partition: %s (offset 0x%lx, size %lu KB)\n",
|
|
||||||
running->label, running->address, running->size / 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_partition(void)
|
|
||||||
{
|
|
||||||
printf("Partition Table:\n");
|
|
||||||
printf("%-16s %-10s %-10s %10s %10s\n", "Label", "Type", "SubType", "Offset", "Size");
|
|
||||||
printf("------------------------------------------------------------------------\n");
|
|
||||||
|
|
||||||
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
|
||||||
|
|
||||||
while (it != NULL)
|
|
||||||
{
|
|
||||||
const esp_partition_t *part = esp_partition_get(it);
|
|
||||||
|
|
||||||
const char *type_str = "?";
|
|
||||||
if (part->type == ESP_PARTITION_TYPE_APP)
|
|
||||||
type_str = "app";
|
|
||||||
else if (part->type == ESP_PARTITION_TYPE_DATA)
|
|
||||||
type_str = "data";
|
|
||||||
|
|
||||||
printf("%-16s %-10s 0x%-8x 0x%08lx %8lu KB\n",
|
|
||||||
part->label,
|
|
||||||
type_str,
|
|
||||||
part->subtype,
|
|
||||||
part->address,
|
|
||||||
part->size / 1024);
|
|
||||||
|
|
||||||
it = esp_partition_next(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_partition_iterator_release(it);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_heap_caps(void)
|
|
||||||
{
|
|
||||||
printf("Heap by Capability:\n");
|
|
||||||
|
|
||||||
size_t internal_free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
|
||||||
size_t internal_total = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
|
|
||||||
printf(" Internal: %u / %u bytes free (%.1f%%)\n",
|
|
||||||
internal_free, internal_total,
|
|
||||||
internal_total > 0 ? 100.0 * internal_free / internal_total : 0);
|
|
||||||
|
|
||||||
size_t spiram_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
|
||||||
size_t spiram_total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
|
|
||||||
if (spiram_total > 0)
|
|
||||||
{
|
|
||||||
printf(" SPIRAM: %u / %u bytes free (%.1f%%)\n",
|
|
||||||
spiram_free, spiram_total, 100.0 * spiram_free / spiram_total);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t dma_free = heap_caps_get_free_size(MALLOC_CAP_DMA);
|
|
||||||
size_t dma_total = heap_caps_get_total_size(MALLOC_CAP_DMA);
|
|
||||||
printf(" DMA capable: %u / %u bytes free (%.1f%%)\n",
|
|
||||||
dma_free, dma_total,
|
|
||||||
dma_total > 0 ? 100.0 * dma_free / dma_total : 0);
|
|
||||||
|
|
||||||
size_t exec_free = heap_caps_get_free_size(MALLOC_CAP_EXEC);
|
|
||||||
size_t exec_total = heap_caps_get_total_size(MALLOC_CAP_EXEC);
|
|
||||||
printf(" Executable: %u / %u bytes free (%.1f%%)\n",
|
|
||||||
exec_free, exec_total,
|
|
||||||
exec_total > 0 ? 100.0 * exec_free / exec_total : 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_stats(void)
|
|
||||||
{
|
|
||||||
printf("=== System Statistics ===\n\n");
|
|
||||||
|
|
||||||
system_cmd_uptime();
|
|
||||||
printf("\n");
|
|
||||||
system_cmd_ram();
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
uint32_t task_count = uxTaskGetNumberOfTasks();
|
|
||||||
printf("Active tasks: %lu\n\n", task_count);
|
|
||||||
|
|
||||||
system_cmd_reset_reason();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_coredump(void)
|
|
||||||
{
|
|
||||||
esp_core_dump_summary_t summary;
|
|
||||||
esp_err_t err = esp_core_dump_get_summary(&summary);
|
|
||||||
|
|
||||||
if (err == ESP_ERR_NOT_FOUND)
|
|
||||||
{
|
|
||||||
printf("No coredump found in flash\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
printf("Failed to read coredump: %s\n", esp_err_to_name(err));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Coredump found:\n");
|
|
||||||
printf(" Program counter: 0x%08lx\n", summary.exc_pc);
|
|
||||||
printf(" Exception cause: %lu\n", summary.ex_info.exc_cause);
|
|
||||||
printf(" Exception vaddr: 0x%08lx\n", summary.ex_info.exc_vaddr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_mac(void)
|
|
||||||
{
|
|
||||||
uint8_t mac[6];
|
|
||||||
|
|
||||||
printf("MAC Addresses:\n");
|
|
||||||
|
|
||||||
if (esp_read_mac(mac, ESP_MAC_WIFI_STA) == ESP_OK)
|
|
||||||
{
|
|
||||||
printf(" WiFi STA: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP) == ESP_OK)
|
|
||||||
{
|
|
||||||
printf(" WiFi AP: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_read_mac(mac, ESP_MAC_BT) == ESP_OK)
|
|
||||||
{
|
|
||||||
printf(" BT: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_read_mac(mac, ESP_MAC_ETH) == ESP_OK)
|
|
||||||
{
|
|
||||||
printf(" Ethernet: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const char **hostname_out;
|
|
||||||
bool success;
|
|
||||||
} hostname_get_ctx_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const char *hostname_in;
|
|
||||||
esp_err_t result;
|
|
||||||
} hostname_set_ctx_t;
|
|
||||||
|
|
||||||
static esp_err_t get_hostname_tcpip(void *ctx)
|
|
||||||
{
|
|
||||||
hostname_get_ctx_t *context = (hostname_get_ctx_t *)ctx;
|
|
||||||
esp_netif_t *netif = esp_netif_next_unsafe(NULL);
|
|
||||||
|
|
||||||
if (netif)
|
|
||||||
{
|
|
||||||
esp_netif_get_hostname(netif, context->hostname_out);
|
|
||||||
context->success = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context->success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t set_hostname_tcpip(void *ctx)
|
|
||||||
{
|
|
||||||
hostname_set_ctx_t *context = (hostname_set_ctx_t *)ctx;
|
|
||||||
esp_netif_t *netif = esp_netif_next_unsafe(NULL);
|
|
||||||
|
|
||||||
if (netif)
|
|
||||||
{
|
|
||||||
context->result = esp_netif_set_hostname(netif, context->hostname_in);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context->result = ESP_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_hostname(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 3)
|
|
||||||
{
|
|
||||||
const char *hostname = NULL;
|
|
||||||
hostname_get_ctx_t ctx = {
|
|
||||||
.hostname_out = &hostname,
|
|
||||||
.success = false};
|
|
||||||
|
|
||||||
esp_err_t err = esp_netif_tcpip_exec(get_hostname_tcpip, &ctx);
|
|
||||||
|
|
||||||
if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
printf("Failed to access network interface: %s\n", esp_err_to_name(err));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.success)
|
|
||||||
{
|
|
||||||
if (hostname)
|
|
||||||
{
|
|
||||||
printf("Hostname: %s\n", hostname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("No hostname set\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("No network interface available\n");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname_set_ctx_t ctx = {
|
|
||||||
.hostname_in = argv[2],
|
|
||||||
.result = ESP_FAIL};
|
|
||||||
|
|
||||||
esp_err_t err = esp_netif_tcpip_exec(set_hostname_tcpip, &ctx);
|
|
||||||
|
|
||||||
if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
printf("Failed to access network interface: %s\n", esp_err_to_name(err));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.result == ESP_ERR_NOT_FOUND)
|
|
||||||
{
|
|
||||||
printf("No network interface available\n");
|
|
||||||
}
|
|
||||||
else if (ctx.result == ESP_OK)
|
|
||||||
{
|
|
||||||
printf("Hostname set to: %s\n", argv[2]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Failed to set hostname: %s\n", esp_err_to_name(ctx.result));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_version(void)
|
|
||||||
{
|
|
||||||
const esp_app_desc_t *app_desc = esp_app_get_description();
|
|
||||||
|
|
||||||
printf("Firmware Information:\n");
|
|
||||||
printf(" Version: %s\n", app_desc->version);
|
|
||||||
printf(" Project: %s\n", app_desc->project_name);
|
|
||||||
printf(" IDF version: %s\n", app_desc->idf_ver);
|
|
||||||
printf(" SystemK version: %s (%s)\n", SYSTEMK_VERSION_STRING, SYSTEMK_GIT_COMMIT_HASH_SHORT);
|
|
||||||
printf(" Git commit: %s\n", GIT_COMMIT_HASH_LONG);
|
|
||||||
printf(" Compile time: %s %s\n", app_desc->date, app_desc->time);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_factory_reset(void)
|
|
||||||
{
|
|
||||||
printf("WARNING: This will erase all NVS data!\n");
|
|
||||||
printf("Type 'yes' to confirm: ");
|
|
||||||
|
|
||||||
char confirm[10];
|
|
||||||
if (fgets(confirm, sizeof(confirm), stdin) == NULL)
|
|
||||||
{
|
|
||||||
printf("\nCancelled\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove newline
|
|
||||||
confirm[strcspn(confirm, "\n")] = 0;
|
|
||||||
|
|
||||||
if (strcmp(confirm, "yes") != 0)
|
|
||||||
{
|
|
||||||
printf("Factory reset cancelled.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Erasing NVS...\n");
|
|
||||||
esp_err_t err = nvs_flash_erase();
|
|
||||||
if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
printf("Failed to erase NVS: %s\n", esp_err_to_name(err));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Factory reset complete. Rebooting...\n");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
esp_restart();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int system_cmd_reboot(void)
|
|
||||||
{
|
|
||||||
printf("Rebooting...\n");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
esp_restart();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_system(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 2)
|
|
||||||
{
|
|
||||||
print_usage();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(argv[1], "chip-info"))
|
|
||||||
return system_cmd_chip_info();
|
|
||||||
if (!strcmp(argv[1], "coredump"))
|
|
||||||
return system_cmd_coredump();
|
|
||||||
if (!strcmp(argv[1], "factory-reset"))
|
|
||||||
return system_cmd_factory_reset();
|
|
||||||
if (!strcmp(argv[1], "flash"))
|
|
||||||
return system_cmd_flash();
|
|
||||||
if (!strcmp(argv[1], "heap-caps"))
|
|
||||||
return system_cmd_heap_caps();
|
|
||||||
if (!strcmp(argv[1], "hostname"))
|
|
||||||
return system_cmd_hostname(argc, argv);
|
|
||||||
if (!strcmp(argv[1], "mac"))
|
|
||||||
return system_cmd_mac();
|
|
||||||
if (!strcmp(argv[1], "partition"))
|
|
||||||
return system_cmd_partition();
|
|
||||||
if (!strcmp(argv[1], "RAM"))
|
|
||||||
return system_cmd_ram();
|
|
||||||
if (!strcmp(argv[1], "reboot"))
|
|
||||||
return system_cmd_reboot();
|
|
||||||
if (!strcmp(argv[1], "reset-reason"))
|
|
||||||
return system_cmd_reset_reason();
|
|
||||||
if (!strcmp(argv[1], "stats"))
|
|
||||||
return system_cmd_stats();
|
|
||||||
if (!strcmp(argv[1], "tasks"))
|
|
||||||
return system_cmd_tasks();
|
|
||||||
if (!strcmp(argv[1], "uptime"))
|
|
||||||
return system_cmd_uptime();
|
|
||||||
if (!strcmp(argv[1], "version"))
|
|
||||||
return system_cmd_version();
|
|
||||||
|
|
||||||
printf("Unknown command\n");
|
|
||||||
print_usage();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void system_completion(const char *buf, linenoiseCompletions *lc)
|
|
||||||
{
|
|
||||||
if (!strncmp(buf, "system", 6))
|
|
||||||
{
|
|
||||||
linenoiseAddCompletion(lc, "system chip-info");
|
|
||||||
linenoiseAddCompletion(lc, "system coredump");
|
|
||||||
linenoiseAddCompletion(lc, "system factory-reset");
|
|
||||||
linenoiseAddCompletion(lc, "system flash");
|
|
||||||
linenoiseAddCompletion(lc, "system heap-caps");
|
|
||||||
linenoiseAddCompletion(lc, "system hostname");
|
|
||||||
linenoiseAddCompletion(lc, "system mac");
|
|
||||||
linenoiseAddCompletion(lc, "system partition");
|
|
||||||
linenoiseAddCompletion(lc, "system RAM");
|
|
||||||
linenoiseAddCompletion(lc, "system reboot");
|
|
||||||
linenoiseAddCompletion(lc, "system reset-reason");
|
|
||||||
linenoiseAddCompletion(lc, "system stats");
|
|
||||||
linenoiseAddCompletion(lc, "system tasks");
|
|
||||||
linenoiseAddCompletion(lc, "system uptime");
|
|
||||||
linenoiseAddCompletion(lc, "system version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Register_System_Command(void)
|
|
||||||
{
|
|
||||||
linenoiseSetCompletionCallback(system_completion);
|
|
||||||
|
|
||||||
const esp_console_cmd_t cmd = {
|
|
||||||
.command = "system",
|
|
||||||
.help = "System management and diagnostic commands",
|
|
||||||
.func = &cmd_system,
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
|
||||||
}
|
|
||||||
|
|
@ -21,15 +21,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include <KEvent_Command.h>
|
|
||||||
#include <Log_Command.h>
|
#include <Log_Command.h>
|
||||||
#include <System_Command.h>
|
|
||||||
|
|
||||||
static void register_commands()
|
static void register_commands()
|
||||||
{
|
{
|
||||||
Register_KEvent_Command();
|
|
||||||
Register_Log_Command();
|
Register_Log_Command();
|
||||||
Register_System_Command();
|
|
||||||
esp_console_register_help_command();
|
esp_console_register_help_command();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
# Main repository hashes
|
|
||||||
execute_process(
|
|
||||||
COMMAND git rev-parse --short HEAD
|
|
||||||
WORKING_DIRECTORY ${SOURCE_DIR}
|
|
||||||
OUTPUT_VARIABLE GIT_HASH_SHORT
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND git rev-parse HEAD
|
|
||||||
WORKING_DIRECTORY ${SOURCE_DIR}
|
|
||||||
OUTPUT_VARIABLE GIT_HASH_LONG
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check for uncommitted changes in main repo
|
|
||||||
execute_process(
|
|
||||||
COMMAND git diff-index --quiet HEAD --
|
|
||||||
WORKING_DIRECTORY ${SOURCE_DIR}
|
|
||||||
RESULT_VARIABLE GIT_DIRTY
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT GIT_DIRTY EQUAL 0)
|
|
||||||
set(GIT_HASH_SHORT "${GIT_HASH_SHORT}+")
|
|
||||||
set(GIT_HASH_LONG "${GIT_HASH_LONG}+")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# SystemK hashes
|
|
||||||
set(SYSTEMK_PATH "${SOURCE_DIR}/components/SystemK")
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND git rev-parse --short HEAD
|
|
||||||
WORKING_DIRECTORY ${SYSTEMK_PATH}
|
|
||||||
OUTPUT_VARIABLE SYSTEMK_HASH_SHORT
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
RESULT_VARIABLE SYSTEMK_RESULT
|
|
||||||
)
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND git rev-parse HEAD
|
|
||||||
WORKING_DIRECTORY ${SYSTEMK_PATH}
|
|
||||||
OUTPUT_VARIABLE SYSTEMK_HASH_LONG
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check for uncommitted changes in SystemK.
|
|
||||||
execute_process(
|
|
||||||
COMMAND git diff-index --quiet HEAD --
|
|
||||||
WORKING_DIRECTORY ${SYSTEMK_PATH}
|
|
||||||
RESULT_VARIABLE SYSTEMK_DIRTY
|
|
||||||
)
|
|
||||||
|
|
||||||
# Handle the case where SystemK doesn't exist or is not a git repo.
|
|
||||||
if(SYSTEMK_RESULT EQUAL 0)
|
|
||||||
if(NOT SYSTEMK_DIRTY EQUAL 0)
|
|
||||||
set(SYSTEMK_HASH_SHORT "${SYSTEMK_HASH_SHORT}+")
|
|
||||||
set(SYSTEMK_HASH_LONG "${SYSTEMK_HASH_LONG}+")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(SYSTEMK_HASH_SHORT "unknown")
|
|
||||||
set(SYSTEMK_HASH_LONG "unknown")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(WRITE ${OUTPUT_FILE}
|
|
||||||
"#ifndef GIT_VERSION_H
|
|
||||||
#define GIT_VERSION_H
|
|
||||||
#define GIT_COMMIT_HASH_SHORT \"${GIT_HASH_SHORT}\"
|
|
||||||
#define GIT_COMMIT_HASH_LONG \"${GIT_HASH_LONG}\"
|
|
||||||
#define SYSTEMK_GIT_COMMIT_HASH_SHORT \"${SYSTEMK_HASH_SHORT}\"
|
|
||||||
#define SYSTEMK_GIT_COMMIT_HASH_LONG \"${SYSTEMK_HASH_LONG}\"
|
|
||||||
#endif
|
|
||||||
")
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include <SystemK.h>
|
#include <SystemK.h>
|
||||||
#include <driver/gpio.h>
|
#include <driver/gpio.h>
|
||||||
#include <iot_button.h>
|
#include <iot_button.h>
|
||||||
#include <button_gpio.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/portmacro.h>
|
#include <freertos/portmacro.h>
|
||||||
|
|
||||||
|
|
@ -33,24 +32,28 @@ static const char *TAG = "Switches";
|
||||||
#define TRIGGER_GPIO GPIO_NUM_1
|
#define TRIGGER_GPIO GPIO_NUM_1
|
||||||
#define ACCESSORY_GPIO GPIO_NUM_4
|
#define ACCESSORY_GPIO GPIO_NUM_4
|
||||||
|
|
||||||
static const button_config_t Button_Config = {
|
static button_handle_t Trigger_Button;
|
||||||
|
static button_config_t Trigger_Button_Config = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
};
|
.gpio_button_config = {
|
||||||
|
|
||||||
static const button_gpio_config_t Trigger_GPIO_Config = {
|
|
||||||
.gpio_num = TRIGGER_GPIO,
|
.gpio_num = TRIGGER_GPIO,
|
||||||
.active_level = 0,
|
.active_level = 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const button_gpio_config_t Accessory_GPIO_Config = {
|
static button_handle_t Accessory_Button;
|
||||||
|
static button_config_t Accessory_Button_Config = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.gpio_button_config = {
|
||||||
.gpio_num = ACCESSORY_GPIO,
|
.gpio_num = ACCESSORY_GPIO,
|
||||||
.active_level = 0,
|
.active_level = 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static button_handle_t Trigger_Button;
|
|
||||||
static button_handle_t Accessory_Button;
|
|
||||||
|
|
||||||
static TickType_t TicksAtTriggerPress = 0;
|
static TickType_t TicksAtTriggerPress = 0;
|
||||||
static TickType_t TicksAtAccessoryPress = 0;
|
static TickType_t TicksAtAccessoryPress = 0;
|
||||||
static TickType_t TicksAtAccessoryRelease = 0;
|
static TickType_t TicksAtAccessoryRelease = 0;
|
||||||
|
|
@ -67,7 +70,7 @@ static void trigger_release_cb(void *arg, void *usr_data)
|
||||||
{
|
{
|
||||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||||
uint32_t triggerPressDurationInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtTriggerPress);
|
uint32_t triggerPressDurationInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtTriggerPress);
|
||||||
KEvent_T switch_event = {.ID = KEVENT_TRIGGER_SWITCH_RELEASED, .Data = (void *)triggerPressDurationInms};
|
KEvent_T switch_event = {.ID = KEVENT_TRIGGER_SWITCH_RELEASED, .Data = (void *) triggerPressDurationInms};
|
||||||
Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken);
|
Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +79,7 @@ static void accessory_press_cb(void *arg, void *usr_data)
|
||||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||||
TicksAtAccessoryPress = xTaskGetTickCountFromISR();
|
TicksAtAccessoryPress = xTaskGetTickCountFromISR();
|
||||||
uint32_t accessoryTimeReleasedInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtAccessoryRelease);
|
uint32_t accessoryTimeReleasedInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtAccessoryRelease);
|
||||||
KEvent_T switch_event = {.ID = KEVENT_ACCESSORY_SWITCH_PRESSED, .Data = (void *)accessoryTimeReleasedInms};
|
KEvent_T switch_event = {.ID = KEVENT_ACCESSORY_SWITCH_PRESSED, .Data = (void *) accessoryTimeReleasedInms};
|
||||||
Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken);
|
Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,90 +88,23 @@ static void accessory_release_cb(void *arg, void *usr_data)
|
||||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||||
TicksAtAccessoryRelease = xTaskGetTickCountFromISR();
|
TicksAtAccessoryRelease = xTaskGetTickCountFromISR();
|
||||||
uint32_t accessoryPressDurationInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtAccessoryPress);
|
uint32_t accessoryPressDurationInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtAccessoryPress);
|
||||||
KEvent_T switch_event = {.ID = KEVENT_ACCESSORY_SWITCH_RELEASED, .Data = (void *)accessoryPressDurationInms};
|
KEvent_T switch_event = {.ID = KEVENT_ACCESSORY_SWITCH_RELEASED, .Data = (void *) accessoryPressDurationInms};
|
||||||
Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken);
|
Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t Initialize_Switches(void)
|
void Initialize_Switches(void)
|
||||||
{
|
{
|
||||||
KLOG_INFO(TAG, "Initializing Switches...");
|
KLOG_INFO(TAG, "Initializing Switches...");
|
||||||
|
|
||||||
esp_err_t err;
|
Trigger_Button = iot_button_create(&Trigger_Button_Config);
|
||||||
|
assert(Trigger_Button);
|
||||||
|
|
||||||
err = iot_button_new_gpio_device(
|
Accessory_Button = iot_button_create(&Accessory_Button_Config);
|
||||||
&Button_Config,
|
assert(Accessory_Button);
|
||||||
&Trigger_GPIO_Config,
|
|
||||||
&Trigger_Button);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
iot_button_register_cb(Trigger_Button, BUTTON_PRESS_DOWN, trigger_press_cb, NULL);
|
||||||
KLOG_ERROR(TAG, "Failed to create Trigger button (%s)",
|
iot_button_register_cb(Trigger_Button, BUTTON_PRESS_UP, trigger_release_cb, NULL);
|
||||||
esp_err_to_name(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = iot_button_new_gpio_device(
|
iot_button_register_cb(Accessory_Button, BUTTON_PRESS_DOWN, accessory_press_cb, NULL);
|
||||||
&Button_Config,
|
iot_button_register_cb(Accessory_Button, BUTTON_PRESS_UP, accessory_release_cb, NULL);
|
||||||
&Accessory_GPIO_Config,
|
|
||||||
&Accessory_Button);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
KLOG_ERROR(TAG, "Failed to create Accessory button (%s)",
|
|
||||||
esp_err_to_name(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = iot_button_register_cb(
|
|
||||||
Trigger_Button,
|
|
||||||
BUTTON_PRESS_DOWN,
|
|
||||||
NULL,
|
|
||||||
trigger_press_cb,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
KLOG_ERROR(TAG, "Trigger PRESS_DOWN cb failed (%s)",
|
|
||||||
esp_err_to_name(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = iot_button_register_cb(
|
|
||||||
Trigger_Button,
|
|
||||||
BUTTON_PRESS_UP,
|
|
||||||
NULL,
|
|
||||||
trigger_release_cb,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
KLOG_ERROR(TAG, "Trigger PRESS_UP cb failed (%s)",
|
|
||||||
esp_err_to_name(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = iot_button_register_cb(
|
|
||||||
Accessory_Button,
|
|
||||||
BUTTON_PRESS_DOWN,
|
|
||||||
NULL,
|
|
||||||
accessory_press_cb,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
KLOG_ERROR(TAG, "Accessory PRESS_DOWN cb failed (%s)",
|
|
||||||
esp_err_to_name(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = iot_button_register_cb(
|
|
||||||
Accessory_Button,
|
|
||||||
BUTTON_PRESS_UP,
|
|
||||||
NULL,
|
|
||||||
accessory_release_cb,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
KLOG_ERROR(TAG, "Accessory PRESS_UP cb failed (%s)",
|
|
||||||
esp_err_to_name(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
KLOG_INFO(TAG, "Switch initialization complete");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,4 +20,4 @@
|
||||||
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
esp_err_t Initialize_Switches(void);
|
void Initialize_Switches(void);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5aeffbcbc998ab13d2a14a1a53ddc335750e6f12
|
Subproject commit 45df6f952abb82c2825a8bb16783c10a150adeba
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
chmorgan/esp-audio-player:
|
chmorgan/esp-audio-player:
|
||||||
component_hash: a19dba40c076e59baaf6383041b6feeb25135dbc5a5b8bcc6b497d8d947095c6
|
component_hash: c8ac1998e9af863bc41b57e592f88d1a5791a0f891485122336ddabbf7a65033
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: chmorgan/esp-libhelix-mp3
|
- name: chmorgan/esp-libhelix-mp3
|
||||||
registry_url: https://components.espressif.com
|
registry_url: https://components.espressif.com
|
||||||
|
|
@ -12,7 +12,7 @@ dependencies:
|
||||||
source:
|
source:
|
||||||
registry_url: https://components.espressif.com/
|
registry_url: https://components.espressif.com/
|
||||||
type: service
|
type: service
|
||||||
version: 1.1.0
|
version: 1.0.7
|
||||||
chmorgan/esp-libhelix-mp3:
|
chmorgan/esp-libhelix-mp3:
|
||||||
component_hash: cbb76089dc2c5749f7b470e2e70aedc44c9da519e04eb9a67d4c7ec275229e53
|
component_hash: cbb76089dc2c5749f7b470e2e70aedc44c9da519e04eb9a67d4c7ec275229e53
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -24,21 +24,21 @@ dependencies:
|
||||||
type: service
|
type: service
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
espressif/button:
|
espressif/button:
|
||||||
component_hash: fccb18c37f1cfe0797b74a53a44d3f400f5fd01f4993b40052dfb7f401915089
|
component_hash: 30a3f495c3862d505ce6e41adbbd218b2750e9723ab2151feff00e9fe685b326
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: espressif/cmake_utilities
|
- name: espressif/cmake_utilities
|
||||||
registry_url: https://components.espressif.com
|
registry_url: https://components.espressif.com
|
||||||
require: private
|
require: private
|
||||||
version: '*'
|
version: 0.*
|
||||||
- name: idf
|
- name: idf
|
||||||
require: private
|
require: private
|
||||||
version: '>=4.0'
|
version: '>=4.0'
|
||||||
source:
|
source:
|
||||||
registry_url: https://components.espressif.com/
|
registry_url: https://components.espressif.com/
|
||||||
type: service
|
type: service
|
||||||
version: 4.1.5
|
version: 3.5.0
|
||||||
espressif/cmake_utilities:
|
espressif/cmake_utilities:
|
||||||
component_hash: 05165f30922b422b4b90c08845e6d449329b97370fbd06309803d8cb539d79e3
|
component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: idf
|
- name: idf
|
||||||
require: private
|
require: private
|
||||||
|
|
@ -46,7 +46,7 @@ dependencies:
|
||||||
source:
|
source:
|
||||||
registry_url: https://components.espressif.com
|
registry_url: https://components.espressif.com
|
||||||
type: service
|
type: service
|
||||||
version: 1.1.1
|
version: 0.5.3
|
||||||
espressif/mdns:
|
espressif/mdns:
|
||||||
component_hash: 29e47564b1a7ee778135e17fbbf2a2773f71c97ebabfe626c8eda7c958a7ad16
|
component_hash: 29e47564b1a7ee778135e17fbbf2a2773f71c97ebabfe626c8eda7c958a7ad16
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -90,6 +90,6 @@ direct_dependencies:
|
||||||
- espressif/mdns
|
- espressif/mdns
|
||||||
- espressif/usb_host_msc
|
- espressif/usb_host_msc
|
||||||
- idf
|
- idf
|
||||||
manifest_hash: 29eed929b315679b169d30b15a00c48a5e657997ac08d9564e2b7a48396bd2c7
|
manifest_hash: 5b1cfb7b4c52ebc94cab936b2f38ddcbe41bf628b9bb3665f579c79f249e4c3b
|
||||||
target: esp32s3
|
target: esp32s3
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
#include <driver/rmt_tx.h>
|
#include <driver/rmt_tx.h>
|
||||||
#include "HW_NeoPixels.h"
|
#include "HW_NeoPixels.h"
|
||||||
|
|
||||||
#define NEOPIXELS_STACK_SIZE (10 * 1024)
|
#define NEOPIXELS_STACK_SIZE (100 * 1024)
|
||||||
#define NEOPIXELS_TASK_PRIORITY (tskIDLE_PRIORITY + 1)
|
#define NEOPIXELS_TASK_PRIORITY (tskIDLE_PRIORITY + 1)
|
||||||
static StaticTask_t xTaskBuffer;
|
static StaticTask_t xTaskBuffer;
|
||||||
StackType_t *xStack;
|
StackType_t *xStack;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
## IDF Component Manager Manifest File
|
## IDF Component Manager Manifest File
|
||||||
dependencies:
|
dependencies:
|
||||||
chmorgan/esp-libhelix-mp3: "^1.0.3"
|
chmorgan/esp-libhelix-mp3: "^1.0.3"
|
||||||
chmorgan/esp-audio-player: "^1.1.0"
|
chmorgan/esp-audio-player: "^1.0.7"
|
||||||
espressif/button: "^4.1.5"
|
espressif/button: "^3.5.0"
|
||||||
espressif/mdns: "^1.9.1"
|
espressif/mdns: "^1.9.1"
|
||||||
espressif/usb_host_msc: "^1.1.4"
|
espressif/usb_host_msc: "^1.1.4"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include <IR.h>
|
#include <IR.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <Console.h>
|
#include <Console.h>
|
||||||
|
#include <ESP-NOW.h>
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "HW_NeoPixels.h"
|
#include "HW_NeoPixels.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
|
|
@ -120,10 +121,9 @@ void app_main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the switches after SystemK, so xQueueEvents will have already been created.
|
// Initialize the switches after SystemK, so xQueueEvents will have already been created.
|
||||||
if (Initialize_Switches() != ESP_OK)
|
Initialize_Switches();
|
||||||
{
|
|
||||||
KLOG_ERROR(TAG, "Error initializing the switches!");
|
Initialize_ESP_NOW();
|
||||||
}
|
|
||||||
|
|
||||||
KLOG_INFO(TAG, "Initialization complete.");
|
KLOG_INFO(TAG, "Initialization complete.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
a19dba40c076e59baaf6383041b6feeb25135dbc5a5b8bcc6b497d8d947095c6
|
c8ac1998e9af863bc41b57e592f88d1a5791a0f891485122336ddabbf7a65033
|
||||||
|
|
@ -1,20 +1,13 @@
|
||||||
|
|
||||||
set(srcs
|
set(srcs
|
||||||
"audio_player.cpp"
|
"audio_player.cpp"
|
||||||
"audio_mixer.cpp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(includes
|
set(includes
|
||||||
"include"
|
"include"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(requires)
|
set(requires "")
|
||||||
|
|
||||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
|
|
||||||
list(APPEND requires esp_driver_i2s esp_ringbuf)
|
|
||||||
else()
|
|
||||||
list(APPEND requires driver)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CONFIG_AUDIO_PLAYER_ENABLE_MP3)
|
if(CONFIG_AUDIO_PLAYER_ENABLE_MP3)
|
||||||
list(APPEND srcs "audio_mp3.cpp")
|
list(APPEND srcs "audio_mp3.cpp")
|
||||||
|
|
@ -28,6 +21,7 @@ if(CONFIG_AUDIO_PLAYER_ENABLE_WAV)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS "${includes}"
|
|
||||||
REQUIRES "${requires}"
|
REQUIRES "${requires}"
|
||||||
|
INCLUDE_DIRS "${includes}"
|
||||||
|
REQUIRES driver
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
* MP3 decoding (via libhelix-mp3)
|
* MP3 decoding (via libhelix-mp3)
|
||||||
* Wav/wave file decoding
|
* Wav/wave file decoding
|
||||||
* Audio mixing (multiple concurrent streams)
|
|
||||||
|
|
||||||
## Who is this for?
|
## Who is this for?
|
||||||
|
|
||||||
|
|
@ -50,40 +49,6 @@ For MP3 support you'll need the [esp-libhelix-mp3](https://github.com/chmorgan/e
|
||||||
|
|
||||||
Unity tests are implemented in the [test/](../test) folder.
|
Unity tests are implemented in the [test/](../test) folder.
|
||||||
|
|
||||||
|
|
||||||
## Audio Mixer
|
|
||||||
|
|
||||||
The Audio Mixer allows for concurrent playback of multiple audio streams. It supports two types of streams:
|
|
||||||
|
|
||||||
* **Decoder Streams**: For playing MP3 or WAV files. Each stream runs its own decoding task.
|
|
||||||
* **Raw PCM Streams**: For writing raw PCM data directly to the mixer.
|
|
||||||
|
|
||||||
### Basic Mixer Usage
|
|
||||||
|
|
||||||
1. Initialize the mixer with output format and I2S write functions.
|
|
||||||
2. Create one or more streams using `audio_stream_new()`.
|
|
||||||
3. Start playback on the streams.
|
|
||||||
|
|
||||||
```c
|
|
||||||
audio_mixer_config_t mixer_cfg = {
|
|
||||||
.write_fn = bsp_i2s_write,
|
|
||||||
.clk_set_fn = bsp_i2s_reconfig_clk,
|
|
||||||
.i2s_format = {
|
|
||||||
.sample_rate = 44100,
|
|
||||||
.bits_per_sample = 16,
|
|
||||||
.channels = 2
|
|
||||||
},
|
|
||||||
// ...
|
|
||||||
};
|
|
||||||
audio_mixer_init(&mixer_cfg);
|
|
||||||
|
|
||||||
audio_stream_config_t stream_cfg = DEFAULT_AUDIO_STREAM_CONFIG("bgm");
|
|
||||||
audio_stream_handle_t bgm_stream = audio_stream_new(&stream_cfg);
|
|
||||||
|
|
||||||
FILE *f = fopen("/sdcard/music.mp3", "rb");
|
|
||||||
audio_stream_play(bgm_stream, f);
|
|
||||||
```
|
|
||||||
|
|
||||||
## States
|
## States
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "include/audio_player.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opaque handle for a player instance.
|
|
||||||
* Used for multi-instance control in mixer
|
|
||||||
*/
|
|
||||||
typedef void* audio_instance_handle_t;
|
|
||||||
|
|
||||||
#define CHECK_INSTANCE(i) \
|
|
||||||
ESP_RETURN_ON_FALSE(i != NULL, ESP_ERR_INVALID_ARG, "audio_instance", "instance is NULL")
|
|
||||||
|
|
||||||
const char* event_to_string(audio_player_callback_event_t event);
|
|
||||||
audio_player_callback_event_t state_to_event(audio_player_state_t state);
|
|
||||||
|
|
||||||
audio_player_state_t audio_instance_get_state(audio_instance_handle_t h);
|
|
||||||
esp_err_t audio_instance_callback_register(audio_instance_handle_t h, audio_player_cb_t call_back, void *user_ctx);
|
|
||||||
|
|
||||||
esp_err_t audio_instance_play(audio_instance_handle_t h, FILE *fp);
|
|
||||||
esp_err_t audio_instance_pause(audio_instance_handle_t h);
|
|
||||||
esp_err_t audio_instance_resume(audio_instance_handle_t h);
|
|
||||||
esp_err_t audio_instance_stop(audio_instance_handle_t h);
|
|
||||||
|
|
||||||
esp_err_t audio_instance_new(audio_instance_handle_t *h, audio_player_config_t *config);
|
|
||||||
esp_err_t audio_instance_delete(audio_instance_handle_t h);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,527 +0,0 @@
|
||||||
/**
|
|
||||||
* @file audio_mixer.cpp
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/queue.h>
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/ringbuf.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
#include "audio_mixer.h"
|
|
||||||
#include "audio_player.h"
|
|
||||||
#include "audio_instance.h"
|
|
||||||
#include "audio_stream.h"
|
|
||||||
|
|
||||||
static const char *TAG = "audio_mixer";
|
|
||||||
|
|
||||||
static TaskHandle_t s_mixer_task = NULL;
|
|
||||||
static audio_mixer_config_t s_cfg = {};
|
|
||||||
static volatile bool s_running = false;
|
|
||||||
static audio_mixer_cb_t s_mixer_user_cb = NULL;
|
|
||||||
|
|
||||||
typedef struct audio_stream {
|
|
||||||
audio_stream_type_t type;
|
|
||||||
char name[16];
|
|
||||||
audio_instance_handle_t instance;
|
|
||||||
QueueHandle_t file_queue;
|
|
||||||
RingbufHandle_t pcm_rb;
|
|
||||||
audio_player_state_t state; // used only for RAW stream types.
|
|
||||||
|
|
||||||
SLIST_ENTRY(audio_stream) next;
|
|
||||||
} audio_stream_t;
|
|
||||||
|
|
||||||
SLIST_HEAD(audio_stream_list, audio_stream);
|
|
||||||
static audio_stream_list s_stream_list = SLIST_HEAD_INITIALIZER(s_stream_list);
|
|
||||||
static uint32_t s_stream_name_counter = 0; // counter for unique naming (monotonic)
|
|
||||||
static uint32_t s_active_streams = 0; // counter for stream counting
|
|
||||||
static SemaphoreHandle_t s_stream_mutex = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static int16_t sat_add16(int32_t a, int32_t b) {
|
|
||||||
int32_t s = a + b;
|
|
||||||
if (s > INT16_MAX) return INT16_MAX;
|
|
||||||
if (s < INT16_MIN) return INT16_MIN;
|
|
||||||
return (int16_t)s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mixer_task(void *arg) {
|
|
||||||
const size_t frames = 512; // tune as needed
|
|
||||||
const size_t bytes = frames * s_cfg.i2s_format.channels * sizeof(int16_t);
|
|
||||||
|
|
||||||
int16_t *mix = static_cast<int16_t *>(heap_caps_malloc(bytes, MALLOC_CAP_8BIT));
|
|
||||||
ESP_ERROR_CHECK(mix == NULL);
|
|
||||||
|
|
||||||
while (s_running) {
|
|
||||||
memset(mix, 0, bytes);
|
|
||||||
|
|
||||||
audio_mixer_lock();
|
|
||||||
|
|
||||||
audio_stream_t *stream;
|
|
||||||
SLIST_FOREACH(stream, &s_stream_list, next) {
|
|
||||||
if (!stream->pcm_rb) continue;
|
|
||||||
|
|
||||||
size_t received_bytes = 0;
|
|
||||||
void *item = xRingbufferReceiveUpTo(stream->pcm_rb, &received_bytes, pdMS_TO_TICKS(5), bytes);
|
|
||||||
|
|
||||||
if (item && received_bytes > 0) {
|
|
||||||
int16_t *samples = static_cast<int16_t *>(item);
|
|
||||||
size_t count = received_bytes / sizeof(int16_t);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < count; ++k) {
|
|
||||||
mix[k] = sat_add16(mix[k], samples[k]);
|
|
||||||
}
|
|
||||||
vRingbufferReturnItem(stream->pcm_rb, item);
|
|
||||||
} else if (item) {
|
|
||||||
vRingbufferReturnItem(stream->pcm_rb, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_mixer_unlock();
|
|
||||||
|
|
||||||
size_t written = 0;
|
|
||||||
if (s_cfg.write_fn) {
|
|
||||||
s_cfg.write_fn(mix, bytes, &written, portMAX_DELAY);
|
|
||||||
if (written != bytes) {
|
|
||||||
ESP_LOGW(TAG, "mixer short write %u/%u", (unsigned)written, (unsigned)bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(mix);
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
IRAM_ATTR static esp_err_t mixer_stream_write(void *data, size_t size, size_t *bytes_written, uint32_t timeout, void *stream) {
|
|
||||||
audio_stream_t *s = static_cast<audio_stream_t *>(stream);
|
|
||||||
if (!s || !s->pcm_rb) {
|
|
||||||
if (bytes_written) *bytes_written = 0;
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* send data to the stream's ring buffer */
|
|
||||||
BaseType_t res = xRingbufferSend(s->pcm_rb, data, size, timeout);
|
|
||||||
if (res == pdTRUE) {
|
|
||||||
if (bytes_written) *bytes_written = size;
|
|
||||||
} else {
|
|
||||||
if (bytes_written) *bytes_written = 0;
|
|
||||||
ESP_LOGW(TAG, "stream ringbuf full");
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t mixer_stream_clk_set_fn(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch) {
|
|
||||||
if (rate != s_cfg.i2s_format.sample_rate) {
|
|
||||||
ESP_LOGE(TAG, "stream sample rate mismatch: %lu Hz (mixer expects %u Hz)", rate, s_cfg.i2s_format.sample_rate);
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bits_cfg != s_cfg.i2s_format.bits_per_sample) {
|
|
||||||
ESP_LOGE(TAG, "stream bit depth mismatch: %lu bits (mixer expects %lu bits)", bits_cfg, s_cfg.i2s_format.bits_per_sample);
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ch != s_cfg.i2s_format.channels) {
|
|
||||||
ESP_LOGE(TAG, "stream channels mismatch: %u (mixer expects %lu)", ch, s_cfg.i2s_format.channels);
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mixer_stream_event_handler(audio_player_cb_ctx_t *ctx) {
|
|
||||||
if (!ctx || !ctx->user_ctx) return;
|
|
||||||
|
|
||||||
audio_stream_t *s = static_cast<audio_stream_t *>(ctx->user_ctx);
|
|
||||||
|
|
||||||
// handle auto-queueing
|
|
||||||
if (ctx->audio_event == AUDIO_PLAYER_CALLBACK_EVENT_IDLE) {
|
|
||||||
if (s_stream_mutex) xSemaphoreTake(s_stream_mutex, portMAX_DELAY);
|
|
||||||
|
|
||||||
// Check if there is anything in the queue to play next
|
|
||||||
FILE *next_fp = NULL;
|
|
||||||
if (xQueueReceive(s->file_queue, &next_fp, 0) == pdTRUE) {
|
|
||||||
ESP_LOGD(TAG, "stream '%s' auto-advancing queue", s->name);
|
|
||||||
audio_instance_play(s->instance, next_fp);
|
|
||||||
}
|
|
||||||
audio_mixer_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// service callback
|
|
||||||
if (s_mixer_user_cb) {
|
|
||||||
s_mixer_user_cb(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mixer_free_stream_resources(audio_stream_t *s) {
|
|
||||||
if (s->instance) audio_instance_delete(s->instance);
|
|
||||||
if (s->pcm_rb) vRingbufferDelete(s->pcm_rb);
|
|
||||||
if (s->file_queue) {
|
|
||||||
FILE *fp = NULL;
|
|
||||||
while(xQueueReceive(s->file_queue, &fp, 0) == pdTRUE) {
|
|
||||||
if (fp) fclose(fp);
|
|
||||||
}
|
|
||||||
vQueueDelete(s->file_queue);
|
|
||||||
}
|
|
||||||
free(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
inline uint8_t audio_mixer_stream_count() {
|
|
||||||
return s_active_streams;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void audio_mixer_lock() {
|
|
||||||
if (s_stream_mutex) xSemaphoreTake(s_stream_mutex, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void audio_mixer_unlock() {
|
|
||||||
if (s_stream_mutex) xSemaphoreGive(s_stream_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_mixer_add_stream(audio_stream_handle_t h) {
|
|
||||||
audio_mixer_lock();
|
|
||||||
SLIST_INSERT_HEAD(&s_stream_list, static_cast<audio_stream_t*>(h), next);
|
|
||||||
s_active_streams++;
|
|
||||||
audio_mixer_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_mixer_remove_stream(audio_stream_handle_t h) {
|
|
||||||
audio_mixer_lock();
|
|
||||||
SLIST_REMOVE(&s_stream_list, static_cast<audio_stream_t*>(h), audio_stream, next);
|
|
||||||
if (s_active_streams > 0) s_active_streams--;
|
|
||||||
audio_mixer_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_mixer_get_output_format(uint32_t *sample_rate, uint32_t *bits_per_sample, uint32_t *channels) {
|
|
||||||
if (sample_rate) *sample_rate = s_cfg.i2s_format.sample_rate;
|
|
||||||
if (bits_per_sample) *bits_per_sample = s_cfg.i2s_format.bits_per_sample;
|
|
||||||
if (channels) *channels = s_cfg.i2s_format.channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_mixer_callback_register(audio_mixer_cb_t cb) {
|
|
||||||
s_mixer_user_cb = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_mixer_init(audio_mixer_config_t *cfg) {
|
|
||||||
if (s_running) return ESP_OK;
|
|
||||||
ESP_RETURN_ON_FALSE(cfg && cfg->write_fn && cfg->clk_set_fn, ESP_ERR_INVALID_ARG, TAG, "invalid mixer config");
|
|
||||||
s_cfg = *cfg;
|
|
||||||
|
|
||||||
i2s_slot_mode_t channel_setting = (s_cfg.i2s_format.channels == 1) ? I2S_SLOT_MODE_MONO : I2S_SLOT_MODE_STEREO;
|
|
||||||
ESP_RETURN_ON_ERROR(s_cfg.clk_set_fn(s_cfg.i2s_format.sample_rate, s_cfg.i2s_format.bits_per_sample, channel_setting), TAG, "clk set failed");
|
|
||||||
|
|
||||||
s_running = true;
|
|
||||||
if (!s_stream_mutex) s_stream_mutex = xSemaphoreCreateMutex();
|
|
||||||
|
|
||||||
SLIST_INIT(&s_stream_list);
|
|
||||||
|
|
||||||
BaseType_t ok = xTaskCreatePinnedToCore(mixer_task, "audio_mixer", 4096, NULL, s_cfg.priority, &s_mixer_task, s_cfg.coreID);
|
|
||||||
ESP_RETURN_ON_FALSE(ok == pdPASS, ESP_FAIL, TAG, "failed to start mixer");
|
|
||||||
|
|
||||||
ESP_LOGD(TAG, "mixer started");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool audio_mixer_is_initialized() {
|
|
||||||
return s_mixer_task != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_mixer_deinit() {
|
|
||||||
if (!s_running) return;
|
|
||||||
|
|
||||||
// Task will exit on next loop; no join primitive in FreeRTOS here.
|
|
||||||
s_running = false;
|
|
||||||
s_mixer_task = NULL;
|
|
||||||
|
|
||||||
// Clean up any remaining channels (safe teardown)
|
|
||||||
audio_mixer_lock();
|
|
||||||
|
|
||||||
while (!SLIST_EMPTY(&s_stream_list)) {
|
|
||||||
audio_stream_t *it = SLIST_FIRST(&s_stream_list);
|
|
||||||
SLIST_REMOVE_HEAD(&s_stream_list, next);
|
|
||||||
mixer_free_stream_resources(it);
|
|
||||||
}
|
|
||||||
s_active_streams = 0;
|
|
||||||
|
|
||||||
audio_mixer_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================= Stream (mixer channel) API ================= */
|
|
||||||
|
|
||||||
static void dispatch_callback(audio_stream_t *s, audio_player_callback_event_t event) {
|
|
||||||
ESP_LOGD(TAG, "event '%s'", event_to_string(event));
|
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
|
||||||
if (esp_ptr_executable(reinterpret_cast<void*>(s_mixer_user_cb))) {
|
|
||||||
#else
|
|
||||||
if (reinterpret_cast<void*>(s_mixer_user_cb)) {
|
|
||||||
#endif
|
|
||||||
audio_player_cb_ctx_t ctx = {
|
|
||||||
.audio_event = event,
|
|
||||||
.user_ctx = s,
|
|
||||||
};
|
|
||||||
s_mixer_user_cb(&ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stream_purge_ringbuf(audio_stream_t *s) {
|
|
||||||
if (!s || !s->pcm_rb) return;
|
|
||||||
|
|
||||||
size_t item_size;
|
|
||||||
void *item;
|
|
||||||
while ((item = xRingbufferReceive(s->pcm_rb, &item_size, 0)) != NULL) {
|
|
||||||
vRingbufferReturnItem(s->pcm_rb, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_raw_send_event(audio_stream_handle_t h, audio_player_callback_event_t event) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
|
|
||||||
if (s->type != AUDIO_STREAM_TYPE_RAW) return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
|
|
||||||
// NOTE: essentially made event_to_state()
|
|
||||||
audio_player_state_t new_state = AUDIO_PLAYER_STATE_IDLE;
|
|
||||||
switch (event) {
|
|
||||||
case AUDIO_PLAYER_CALLBACK_EVENT_IDLE:
|
|
||||||
new_state = AUDIO_PLAYER_STATE_IDLE;
|
|
||||||
break;
|
|
||||||
case AUDIO_PLAYER_CALLBACK_EVENT_PLAYING:
|
|
||||||
case AUDIO_PLAYER_CALLBACK_EVENT_COMPLETED_PLAYING_NEXT:
|
|
||||||
new_state = AUDIO_PLAYER_STATE_PLAYING;
|
|
||||||
break;
|
|
||||||
case AUDIO_PLAYER_CALLBACK_EVENT_SHUTDOWN:
|
|
||||||
new_state = AUDIO_PLAYER_STATE_SHUTDOWN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
new_state = AUDIO_PLAYER_STATE_IDLE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s->state != new_state) {
|
|
||||||
s->state = new_state;
|
|
||||||
dispatch_callback(s, event);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_player_state_t audio_stream_get_state(audio_stream_handle_t h) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
if (!s) return AUDIO_PLAYER_STATE_IDLE;
|
|
||||||
|
|
||||||
/* DECODER stream? defer to the instance state */
|
|
||||||
if (s->type == AUDIO_STREAM_TYPE_DECODER) {
|
|
||||||
return audio_instance_get_state(s->instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RAW stream? check if ringbuf has data */
|
|
||||||
if (s->type == AUDIO_STREAM_TYPE_RAW) {
|
|
||||||
// TODO: determine if checking ringbuf is valuable vs. having a stream emit its own state
|
|
||||||
// using the method audio_stream_raw_send_event().
|
|
||||||
// if (!s->pcm_rb) return AUDIO_PLAYER_STATE_IDLE;
|
|
||||||
//
|
|
||||||
// // peek for any bytes
|
|
||||||
// UBaseType_t items_waiting = 0;
|
|
||||||
// vRingbufferGetInfo(s->pcm_rb, NULL, NULL, NULL, NULL, &items_waiting);
|
|
||||||
//
|
|
||||||
// if (items_waiting > 0)
|
|
||||||
// return AUDIO_PLAYER_STATE_PLAYING;
|
|
||||||
return s->state;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AUDIO_PLAYER_STATE_IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_stream_type_t audio_stream_get_type(audio_stream_handle_t h) {
|
|
||||||
if (!h) return AUDIO_STREAM_TYPE_UNKNOWN;
|
|
||||||
return h->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_play(audio_stream_handle_t h, FILE *fp) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
|
|
||||||
if (s->type != AUDIO_STREAM_TYPE_DECODER) {
|
|
||||||
ESP_LOGE(TAG, "stream '%s' is not a decoder stream", s->name);
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop current playback?
|
|
||||||
if (audio_instance_get_state(s->instance) == AUDIO_PLAYER_STATE_PLAYING)
|
|
||||||
audio_stream_stop(s);
|
|
||||||
|
|
||||||
return audio_instance_play(s->instance, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_queue(audio_stream_handle_t h, FILE *fp, bool play_now) {
|
|
||||||
if (play_now) {
|
|
||||||
return audio_stream_play(h, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
|
|
||||||
if (s->type != AUDIO_STREAM_TYPE_DECODER) {
|
|
||||||
ESP_LOGE(TAG, "stream '%s' is not a decoder stream", s->name);
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_mixer_lock();
|
|
||||||
|
|
||||||
// add to queue
|
|
||||||
if (xQueueSend(s->file_queue, &fp, 0) != pdTRUE) {
|
|
||||||
ESP_LOGE(TAG, "stream '%s' queue full", s->name);
|
|
||||||
fclose(fp); // Take ownership and close if we can't queue
|
|
||||||
audio_mixer_unlock();
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if stream is IDLE, we need to kickstart it
|
|
||||||
if (audio_instance_get_state(s->instance) == AUDIO_PLAYER_STATE_IDLE) {
|
|
||||||
FILE *next_fp = NULL;
|
|
||||||
// pop the one we just pushed (or the one at head)
|
|
||||||
if (xQueueReceive(s->file_queue, &next_fp, 0) == pdTRUE) {
|
|
||||||
audio_instance_play(s->instance, next_fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_mixer_unlock();
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_stop(audio_stream_handle_t h) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
|
|
||||||
if (s->type == AUDIO_STREAM_TYPE_DECODER) {
|
|
||||||
// clear any pending queue items
|
|
||||||
FILE *pending = NULL;
|
|
||||||
while (xQueueReceive(s->file_queue, &pending, 0) == pdTRUE) {
|
|
||||||
if (pending) fclose(pending);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = audio_instance_stop(s->instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream_purge_ringbuf(s);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_pause(audio_stream_handle_t h) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
if (s->type != AUDIO_STREAM_TYPE_DECODER) return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
return audio_instance_pause(s->instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_resume(audio_stream_handle_t h) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
if (s->type != AUDIO_STREAM_TYPE_DECODER) return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
return audio_instance_resume(s->instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_write_pcm(audio_stream_handle_t h, void *data, size_t size, uint32_t timeout_ms) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
|
|
||||||
if (s->type != AUDIO_STREAM_TYPE_RAW) {
|
|
||||||
ESP_LOGE(TAG, "stream '%s' is not a raw stream", s->name);
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!s->pcm_rb) return ESP_ERR_INVALID_STATE;
|
|
||||||
|
|
||||||
// Send data to the ring buffer (BYTEBUF type)
|
|
||||||
BaseType_t res = xRingbufferSend(s->pcm_rb, data, size, pdMS_TO_TICKS(timeout_ms));
|
|
||||||
if (res != pdTRUE) {
|
|
||||||
ESP_LOGW(TAG, "stream '%s' overflow", s->name);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_stream_handle_t audio_stream_new(audio_stream_config_t *cfg) {
|
|
||||||
ESP_RETURN_ON_FALSE(cfg, NULL, TAG, "null config");
|
|
||||||
|
|
||||||
audio_stream_t *stream = static_cast<audio_stream_t *>(calloc(1, sizeof(audio_stream_t)));
|
|
||||||
stream->type = cfg->type;
|
|
||||||
|
|
||||||
/* use provided name? */
|
|
||||||
if (cfg->name[0] != '\0') {
|
|
||||||
strncpy(stream->name, cfg->name, sizeof(stream->name) - 1);
|
|
||||||
stream->name[sizeof(stream->name) - 1] = 0;
|
|
||||||
}
|
|
||||||
/* otherwise, generate a unique monotonic name */
|
|
||||||
else {
|
|
||||||
snprintf(stream->name, sizeof(stream->name), "stream_%lu", static_cast<unsigned long>(s_stream_name_counter++));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DECODER type stream? create a player instance and queue */
|
|
||||||
if (cfg->type == AUDIO_STREAM_TYPE_DECODER) {
|
|
||||||
// new player instance
|
|
||||||
audio_player_config_t instance_cfg;
|
|
||||||
instance_cfg.mute_fn = NULL;
|
|
||||||
instance_cfg.clk_set_fn = mixer_stream_clk_set_fn;
|
|
||||||
instance_cfg.coreID = cfg->coreID;
|
|
||||||
instance_cfg.priority = cfg->priority;
|
|
||||||
instance_cfg.force_stereo = false;
|
|
||||||
instance_cfg.write_fn2 = mixer_stream_write;
|
|
||||||
instance_cfg.write_ctx = stream;
|
|
||||||
|
|
||||||
audio_instance_handle_t h = NULL;
|
|
||||||
esp_err_t err = audio_instance_new(&h, &instance_cfg);
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
free(stream);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
stream->instance = h;
|
|
||||||
|
|
||||||
// create file queue & attach event handler
|
|
||||||
stream->file_queue = xQueueCreate(4, sizeof(FILE*));
|
|
||||||
audio_instance_callback_register(stream->instance, mixer_stream_event_handler, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* always create a ringbuffer */
|
|
||||||
stream->pcm_rb = xRingbufferCreate(16 * 1024, RINGBUF_TYPE_BYTEBUF);
|
|
||||||
|
|
||||||
if (!stream->pcm_rb || (cfg->type == AUDIO_STREAM_TYPE_DECODER && !stream->file_queue)) {
|
|
||||||
if (stream->file_queue) vQueueDelete(stream->file_queue);
|
|
||||||
if (stream->pcm_rb) vRingbufferDelete(stream->pcm_rb);
|
|
||||||
if (stream->instance) audio_instance_delete(stream->instance);
|
|
||||||
free(stream);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add to stream tracking */
|
|
||||||
audio_mixer_add_stream(stream);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Created stream '%s' (active: %u)", stream->name, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_stream_delete(audio_stream_handle_t h) {
|
|
||||||
audio_stream_t *s = h;
|
|
||||||
CHECK_STREAM(s);
|
|
||||||
|
|
||||||
/* remove from stream tracking */
|
|
||||||
audio_mixer_remove_stream(s);
|
|
||||||
|
|
||||||
/* cleanup stream */
|
|
||||||
mixer_free_stream_resources(s);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Deleted stream '%s' (active: %u)", s->name, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
@ -35,7 +35,6 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#include "audio_player.h"
|
#include "audio_player.h"
|
||||||
#include "audio_instance.h"
|
|
||||||
|
|
||||||
#include "audio_wav.h"
|
#include "audio_wav.h"
|
||||||
#include "audio_mp3.h"
|
#include "audio_mp3.h"
|
||||||
|
|
@ -95,18 +94,16 @@ typedef struct audio_instance {
|
||||||
HMP3Decoder mp3_decoder;
|
HMP3Decoder mp3_decoder;
|
||||||
mp3_instance mp3_data;
|
mp3_instance mp3_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
format i2s_format; // last configured i2s format
|
|
||||||
} audio_instance_t;
|
} audio_instance_t;
|
||||||
|
|
||||||
static audio_instance_t *g_instance = NULL; // when non-null, in legacy non-mixer mode
|
static audio_instance_t instance;
|
||||||
|
|
||||||
audio_player_state_t audio_instance_get_state(audio_instance_handle_t h) {
|
audio_player_state_t audio_player_get_state() {
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(h);
|
return instance.state;
|
||||||
return i ? i->state : AUDIO_PLAYER_STATE_IDLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t audio_instance_callback_register(audio_instance_handle_t h, audio_player_cb_t call_back, void *user_ctx) {
|
esp_err_t audio_player_callback_register(audio_player_cb_t call_back, void *user_ctx)
|
||||||
|
{
|
||||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
ESP_RETURN_ON_FALSE(esp_ptr_executable(reinterpret_cast<void*>(call_back)), ESP_ERR_INVALID_ARG,
|
ESP_RETURN_ON_FALSE(esp_ptr_executable(reinterpret_cast<void*>(call_back)), ESP_ERR_INVALID_ARG,
|
||||||
TAG, "Not a valid call back");
|
TAG, "Not a valid call back");
|
||||||
|
|
@ -114,14 +111,15 @@ esp_err_t audio_instance_callback_register(audio_instance_handle_t h, audio_play
|
||||||
ESP_RETURN_ON_FALSE(reinterpret_cast<void*>(call_back), ESP_ERR_INVALID_ARG,
|
ESP_RETURN_ON_FALSE(reinterpret_cast<void*>(call_back), ESP_ERR_INVALID_ARG,
|
||||||
TAG, "Not a valid call back");
|
TAG, "Not a valid call back");
|
||||||
#endif
|
#endif
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(h);
|
instance.s_audio_cb = call_back;
|
||||||
CHECK_INSTANCE(i);
|
instance.audio_cb_usrt_ctx = user_ctx;
|
||||||
i->s_audio_cb = call_back;
|
|
||||||
i->audio_cb_usrt_ctx = user_ctx;
|
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function is used in some optional logging functions so we don't want to
|
||||||
|
// have a cppcheck warning here
|
||||||
|
// cppcheck-suppress unusedFunction
|
||||||
const char* event_to_string(audio_player_callback_event_t event) {
|
const char* event_to_string(audio_player_callback_event_t event) {
|
||||||
switch(event) {
|
switch(event) {
|
||||||
case AUDIO_PLAYER_CALLBACK_EVENT_IDLE:
|
case AUDIO_PLAYER_CALLBACK_EVENT_IDLE:
|
||||||
|
|
@ -143,7 +141,7 @@ const char* event_to_string(audio_player_callback_event_t event) {
|
||||||
return "unknown event";
|
return "unknown event";
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_player_callback_event_t state_to_event(audio_player_state_t state) {
|
static audio_player_callback_event_t state_to_event(audio_player_state_t state) {
|
||||||
audio_player_callback_event_t event = AUDIO_PLAYER_CALLBACK_EVENT_UNKNOWN;
|
audio_player_callback_event_t event = AUDIO_PLAYER_CALLBACK_EVENT_UNKNOWN;
|
||||||
|
|
||||||
switch(state) {
|
switch(state) {
|
||||||
|
|
@ -188,15 +186,15 @@ static void set_state(audio_instance_t *i, audio_player_state_t new_state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audio_instance_init(audio_instance_t *i) {
|
static void audio_instance_init(audio_instance_t &i) {
|
||||||
i->event_queue = NULL;
|
i.event_queue = NULL;
|
||||||
i->s_audio_cb = NULL;
|
i.s_audio_cb = NULL;
|
||||||
i->audio_cb_usrt_ctx = NULL;
|
i.audio_cb_usrt_ctx = NULL;
|
||||||
i->state = AUDIO_PLAYER_STATE_IDLE;
|
i.state = AUDIO_PLAYER_STATE_IDLE;
|
||||||
memset(&i->i2s_format, 0, sizeof(i->i2s_format));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t mono_to_stereo(uint32_t output_bits_per_sample, decode_data &adata) {
|
static esp_err_t mono_to_stereo(uint32_t output_bits_per_sample, decode_data &adata)
|
||||||
|
{
|
||||||
size_t data = adata.frame_count * (output_bits_per_sample / BITS_PER_BYTE);
|
size_t data = adata.frame_count * (output_bits_per_sample / BITS_PER_BYTE);
|
||||||
data *= 2;
|
data *= 2;
|
||||||
|
|
||||||
|
|
@ -236,9 +234,13 @@ static esp_err_t mono_to_stereo(uint32_t output_bits_per_sample, decode_data &ad
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t aplay_file(audio_instance_t *i, FILE *fp) {
|
static esp_err_t aplay_file(audio_instance_t *i, FILE *fp)
|
||||||
|
{
|
||||||
LOGI_1("start to decode");
|
LOGI_1("start to decode");
|
||||||
|
|
||||||
|
format i2s_format;
|
||||||
|
memset(&i2s_format, 0, sizeof(i2s_format));
|
||||||
|
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
audio_player_event_t audio_event = { .type = AUDIO_PLAYER_REQUEST_NONE, .fp = NULL };
|
audio_player_event_t audio_event = { .type = AUDIO_PLAYER_REQUEST_NONE, .fp = NULL };
|
||||||
|
|
||||||
|
|
@ -346,9 +348,9 @@ static esp_err_t aplay_file(audio_instance_t *i, FILE *fp) {
|
||||||
// break out and exit if we aren't supposed to continue decoding
|
// break out and exit if we aren't supposed to continue decoding
|
||||||
if(decode_status == DECODE_STATUS_CONTINUE)
|
if(decode_status == DECODE_STATUS_CONTINUE)
|
||||||
{
|
{
|
||||||
// if mono and force_stereo set, convert to stereo as es8311 requires stereo input
|
// if mono, convert to stereo as es8311 requires stereo input
|
||||||
// even though it is mono output
|
// even though it is mono output
|
||||||
if(i->output.fmt.channels == 1 && i->config.force_stereo) {
|
if(i->output.fmt.channels == 1) {
|
||||||
LOGI_3("c == 1, mono -> stereo");
|
LOGI_3("c == 1, mono -> stereo");
|
||||||
ret = mono_to_stereo(i->output.fmt.bits_per_sample, i->output);
|
ret = mono_to_stereo(i->output.fmt.bits_per_sample, i->output);
|
||||||
if(ret != ESP_OK) {
|
if(ret != ESP_OK) {
|
||||||
|
|
@ -357,17 +359,17 @@ static esp_err_t aplay_file(audio_instance_t *i, FILE *fp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure I2S clock if the output format changed */
|
/* Configure I2S clock if the output format changed */
|
||||||
if ((i->i2s_format.sample_rate != i->output.fmt.sample_rate) ||
|
if ((i2s_format.sample_rate != i->output.fmt.sample_rate) ||
|
||||||
(i->i2s_format.channels != i->output.fmt.channels) ||
|
(i2s_format.channels != i->output.fmt.channels) ||
|
||||||
(i->i2s_format.bits_per_sample != i->output.fmt.bits_per_sample)) {
|
(i2s_format.bits_per_sample != i->output.fmt.bits_per_sample)) {
|
||||||
i->i2s_format = i->output.fmt;
|
i2s_format = i->output.fmt;
|
||||||
LOGI_1("format change: sr=%d, bit=%lu, ch=%lu",
|
LOGI_1("format change: sr=%d, bit=%d, ch=%d",
|
||||||
i->i2s_format.sample_rate,
|
i2s_format.sample_rate,
|
||||||
i->i2s_format.bits_per_sample,
|
i2s_format.bits_per_sample,
|
||||||
i->i2s_format.channels);
|
i2s_format.channels);
|
||||||
i2s_slot_mode_t channel_setting = (i->i2s_format.channels == 1) ? I2S_SLOT_MODE_MONO : I2S_SLOT_MODE_STEREO;
|
i2s_slot_mode_t channel_setting = (i2s_format.channels == 1) ? I2S_SLOT_MODE_MONO : I2S_SLOT_MODE_STEREO;
|
||||||
ret = i->config.clk_set_fn(i->i2s_format.sample_rate,
|
ret = i->config.clk_set_fn(i2s_format.sample_rate,
|
||||||
i->i2s_format.bits_per_sample,
|
i2s_format.bits_per_sample,
|
||||||
channel_setting);
|
channel_setting);
|
||||||
ESP_GOTO_ON_ERROR(ret, clean_up, TAG, "i2s_set_clk");
|
ESP_GOTO_ON_ERROR(ret, clean_up, TAG, "i2s_set_clk");
|
||||||
}
|
}
|
||||||
|
|
@ -378,22 +380,17 @@ static esp_err_t aplay_file(audio_instance_t *i, FILE *fp) {
|
||||||
* audio decoding to occur while the previous set of samples is finishing playback, in order
|
* audio decoding to occur while the previous set of samples is finishing playback, in order
|
||||||
* to ensure playback without interruption.
|
* to ensure playback without interruption.
|
||||||
*/
|
*/
|
||||||
size_t bytes_written = 0;
|
size_t i2s_bytes_written = 0;
|
||||||
size_t bytes_to_write = i->output.frame_count * i->output.fmt.channels * (i->i2s_format.bits_per_sample / 8);
|
size_t bytes_to_write = i->output.frame_count * i->output.fmt.channels * (i2s_format.bits_per_sample / 8);
|
||||||
LOGI_2("c %d, bps %d, bytes %d, frame_count %d",
|
LOGI_2("c %d, bps %d, bytes %d, frame_count %d",
|
||||||
i->output.fmt.channels,
|
i->output.fmt.channels,
|
||||||
i2s_format.bits_per_sample,
|
i2s_format.bits_per_sample,
|
||||||
bytes_to_write,
|
bytes_to_write,
|
||||||
i->output.frame_count);
|
i->output.frame_count);
|
||||||
|
|
||||||
// NOTE: to aid transition in api, using write_fn2 based on write_ctx assignment
|
i->config.write_fn(i->output.samples, bytes_to_write, &i2s_bytes_written, portMAX_DELAY);
|
||||||
if (i->config.write_ctx)
|
if(bytes_to_write != i2s_bytes_written) {
|
||||||
i->config.write_fn2(i->output.samples, bytes_to_write, &bytes_written, portMAX_DELAY, i->config.write_ctx);
|
ESP_LOGE(TAG, "to write %d != written %d", bytes_to_write, i2s_bytes_written);
|
||||||
else
|
|
||||||
i->config.write_fn(i->output.samples, bytes_to_write, &bytes_written, portMAX_DELAY);
|
|
||||||
|
|
||||||
if(bytes_to_write != bytes_written) {
|
|
||||||
ESP_LOGE(TAG, "to write %d != written %d", bytes_to_write, bytes_written);
|
|
||||||
}
|
}
|
||||||
} else if(decode_status == DECODE_STATUS_NO_DATA_CONTINUE)
|
} else if(decode_status == DECODE_STATUS_NO_DATA_CONTINUE)
|
||||||
{
|
{
|
||||||
|
|
@ -408,7 +405,8 @@ clean_up:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audio_task(void *pvParam) {
|
static void audio_task(void *pvParam)
|
||||||
|
{
|
||||||
audio_instance_t *i = static_cast<audio_instance_t*>(pvParam);
|
audio_instance_t *i = static_cast<audio_instance_t*>(pvParam);
|
||||||
audio_player_event_t audio_event;
|
audio_player_event_t audio_event;
|
||||||
|
|
||||||
|
|
@ -453,13 +451,13 @@ static void audio_task(void *pvParam) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->config.mute_fn) i->config.mute_fn(AUDIO_PLAYER_UNMUTE);
|
i->config.mute_fn(AUDIO_PLAYER_UNMUTE);
|
||||||
esp_err_t ret_val = aplay_file(i, audio_event.fp);
|
esp_err_t ret_val = aplay_file(i, audio_event.fp);
|
||||||
if(ret_val != ESP_OK)
|
if(ret_val != ESP_OK)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "aplay_file() %d", ret_val);
|
ESP_LOGE(TAG, "aplay_file() %d", ret_val);
|
||||||
}
|
}
|
||||||
if (i->config.mute_fn) i->config.mute_fn(AUDIO_PLAYER_MUTE);
|
i->config.mute_fn(AUDIO_PLAYER_MUTE);
|
||||||
|
|
||||||
if(audio_event.fp) fclose(audio_event.fp);
|
if(audio_event.fp) fclose(audio_event.fp);
|
||||||
}
|
}
|
||||||
|
|
@ -478,155 +476,128 @@ static esp_err_t audio_send_event(audio_instance_t *i, audio_player_event_t even
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================= New multi-instance API ================= */
|
esp_err_t audio_player_play(FILE *fp)
|
||||||
|
{
|
||||||
esp_err_t audio_instance_play(audio_instance_handle_t h, FILE *fp) {
|
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(h);
|
|
||||||
CHECK_INSTANCE(i);
|
|
||||||
|
|
||||||
LOGI_1("%s", __FUNCTION__);
|
LOGI_1("%s", __FUNCTION__);
|
||||||
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_PLAY, .fp = fp };
|
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_PLAY, .fp = fp };
|
||||||
return audio_send_event(i, event);
|
return audio_send_event(&instance, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t audio_instance_pause(audio_instance_handle_t h) {
|
esp_err_t audio_player_pause(void)
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(h);
|
{
|
||||||
CHECK_INSTANCE(i);
|
|
||||||
|
|
||||||
LOGI_1("%s", __FUNCTION__);
|
LOGI_1("%s", __FUNCTION__);
|
||||||
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_PAUSE, .fp = NULL };
|
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_PAUSE, .fp = NULL };
|
||||||
return audio_send_event(i, event);
|
return audio_send_event(&instance, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t audio_instance_resume(audio_instance_handle_t h) {
|
esp_err_t audio_player_resume(void)
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(h);
|
{
|
||||||
CHECK_INSTANCE(i);
|
|
||||||
|
|
||||||
LOGI_1("%s", __FUNCTION__);
|
LOGI_1("%s", __FUNCTION__);
|
||||||
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_RESUME, .fp = NULL };
|
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_RESUME, .fp = NULL };
|
||||||
return audio_send_event(i, event);
|
return audio_send_event(&instance, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t audio_instance_stop(audio_instance_handle_t h) {
|
esp_err_t audio_player_stop(void)
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(h);
|
{
|
||||||
CHECK_INSTANCE(i);
|
|
||||||
|
|
||||||
LOGI_1("%s", __FUNCTION__);
|
LOGI_1("%s", __FUNCTION__);
|
||||||
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_STOP, .fp = NULL };
|
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_STOP, .fp = NULL };
|
||||||
return audio_send_event(i, event);
|
return audio_send_event(&instance, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can only shut down the playback thread if the thread is not presently playing audio.
|
* Can only shut down the playback thread if the thread is not presently playing audio.
|
||||||
* Call audio_player_stop()
|
* Call audio_player_stop()
|
||||||
*/
|
*/
|
||||||
static esp_err_t _internal_audio_player_shutdown_thread(audio_instance_t *i) {
|
static esp_err_t _internal_audio_player_shutdown_thread(void)
|
||||||
CHECK_INSTANCE(i);
|
{
|
||||||
|
|
||||||
LOGI_1("%s", __FUNCTION__);
|
LOGI_1("%s", __FUNCTION__);
|
||||||
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_SHUTDOWN_THREAD, .fp = NULL };
|
audio_player_event_t event = { .type = AUDIO_PLAYER_REQUEST_SHUTDOWN_THREAD, .fp = NULL };
|
||||||
return audio_send_event(i, event);
|
return audio_send_event(&instance, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup_memory(audio_instance_t *i) {
|
static void cleanup_memory(audio_instance_t &i)
|
||||||
|
{
|
||||||
#if defined(CONFIG_AUDIO_PLAYER_ENABLE_MP3)
|
#if defined(CONFIG_AUDIO_PLAYER_ENABLE_MP3)
|
||||||
if(i->mp3_decoder) MP3FreeDecoder(i->mp3_decoder);
|
if(i.mp3_decoder) MP3FreeDecoder(i.mp3_decoder);
|
||||||
if(i->mp3_data.data_buf) free(i->mp3_data.data_buf);
|
if(i.mp3_data.data_buf) free(i.mp3_data.data_buf);
|
||||||
#endif
|
#endif
|
||||||
if(i->output.samples) free(i->output.samples);
|
if(i.output.samples) free(i.output.samples);
|
||||||
|
|
||||||
vQueueDelete(i->event_queue);
|
vQueueDelete(i.event_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t audio_instance_new(audio_instance_handle_t *h, audio_player_config_t *config) {
|
esp_err_t audio_player_new(audio_player_config_t config)
|
||||||
|
{
|
||||||
BaseType_t task_val;
|
BaseType_t task_val;
|
||||||
|
|
||||||
ESP_RETURN_ON_FALSE(h != NULL, ESP_ERR_INVALID_ARG, TAG, "handle pointer is NULL");
|
audio_instance_init(instance);
|
||||||
ESP_RETURN_ON_FALSE(*h == NULL, ESP_ERR_INVALID_ARG, TAG, "instance is not NULL");
|
|
||||||
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "null config");
|
|
||||||
|
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(calloc(1, sizeof(audio_instance_t)));
|
instance.config = config;
|
||||||
if (i == NULL) return ESP_ERR_NO_MEM;
|
|
||||||
|
|
||||||
audio_instance_init(i);
|
|
||||||
|
|
||||||
i->config = *config;
|
|
||||||
|
|
||||||
/* Audio control event queue */
|
/* Audio control event queue */
|
||||||
i->event_queue = xQueueCreate(4, sizeof(audio_player_event_t));
|
instance.event_queue = xQueueCreate(4, sizeof(audio_player_event_t));
|
||||||
ESP_RETURN_ON_FALSE(NULL != i->event_queue, -1, TAG, "xQueueCreate");
|
ESP_RETURN_ON_FALSE(NULL != instance.event_queue, -1, TAG, "xQueueCreate");
|
||||||
|
|
||||||
/** See https://github.com/ultraembedded/libhelix-mp3/blob/0a0e0673f82bc6804e5a3ddb15fb6efdcde747cd/testwrap/main.c#L74 */
|
/** See https://github.com/ultraembedded/libhelix-mp3/blob/0a0e0673f82bc6804e5a3ddb15fb6efdcde747cd/testwrap/main.c#L74 */
|
||||||
i->output.samples_capacity = MAX_NCHAN * MAX_NGRAN * MAX_NSAMP;
|
instance.output.samples_capacity = MAX_NCHAN * MAX_NGRAN * MAX_NSAMP;
|
||||||
i->output.samples_capacity_max = i->output.samples_capacity * 2;
|
instance.output.samples_capacity_max = instance.output.samples_capacity * 2;
|
||||||
i->output.samples = static_cast<uint8_t*>(malloc(i->output.samples_capacity_max));
|
instance.output.samples = static_cast<uint8_t*>(malloc(instance.output.samples_capacity_max));
|
||||||
LOGI_1("samples_capacity %d bytes", i->output.samples_capacity_max);
|
LOGI_1("samples_capacity %d bytes", instance.output.samples_capacity_max);
|
||||||
int ret = ESP_OK;
|
int ret = ESP_OK;
|
||||||
ESP_GOTO_ON_FALSE(NULL != i->output.samples, ESP_ERR_NO_MEM, cleanup,
|
ESP_GOTO_ON_FALSE(NULL != instance.output.samples, ESP_ERR_NO_MEM, cleanup,
|
||||||
TAG, "Failed allocate output buffer");
|
TAG, "Failed allocate output buffer");
|
||||||
|
|
||||||
#if defined(CONFIG_AUDIO_PLAYER_ENABLE_MP3)
|
#if defined(CONFIG_AUDIO_PLAYER_ENABLE_MP3)
|
||||||
i->mp3_data.data_buf_size = MAINBUF_SIZE * 3;
|
instance.mp3_data.data_buf_size = MAINBUF_SIZE * 3;
|
||||||
i->mp3_data.data_buf = static_cast<uint8_t*>(malloc(i->mp3_data.data_buf_size));
|
instance.mp3_data.data_buf = static_cast<uint8_t*>(malloc(instance.mp3_data.data_buf_size));
|
||||||
ESP_GOTO_ON_FALSE(NULL != i->mp3_data.data_buf, ESP_ERR_NO_MEM, cleanup,
|
ESP_GOTO_ON_FALSE(NULL != instance.mp3_data.data_buf, ESP_ERR_NO_MEM, cleanup,
|
||||||
TAG, "Failed allocate mp3 data buffer");
|
TAG, "Failed allocate mp3 data buffer");
|
||||||
|
|
||||||
i->mp3_decoder = MP3InitDecoder();
|
instance.mp3_decoder = MP3InitDecoder();
|
||||||
ESP_GOTO_ON_FALSE(NULL != i->mp3_decoder, ESP_ERR_NO_MEM, cleanup,
|
ESP_GOTO_ON_FALSE(NULL != instance.mp3_decoder, ESP_ERR_NO_MEM, cleanup,
|
||||||
TAG, "Failed create MP3 decoder");
|
TAG, "Failed create MP3 decoder");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(&i->i2s_format, 0, sizeof(i->i2s_format));
|
instance.running = true;
|
||||||
|
|
||||||
i->running = true;
|
|
||||||
task_val = xTaskCreatePinnedToCore(
|
task_val = xTaskCreatePinnedToCore(
|
||||||
(TaskFunction_t) audio_task,
|
(TaskFunction_t) audio_task,
|
||||||
"Audio Task",
|
"Audio Task",
|
||||||
4 * 1024,
|
4 * 1024,
|
||||||
i,
|
&instance,
|
||||||
(UBaseType_t) i->config.priority,
|
(UBaseType_t) instance.config.priority,
|
||||||
(TaskHandle_t *) NULL,
|
(TaskHandle_t * const) NULL,
|
||||||
(BaseType_t) i->config.coreID);
|
(BaseType_t) instance.config.coreID);
|
||||||
|
|
||||||
ESP_GOTO_ON_FALSE(pdPASS == task_val, ESP_ERR_NO_MEM, cleanup,
|
ESP_GOTO_ON_FALSE(pdPASS == task_val, ESP_ERR_NO_MEM, cleanup,
|
||||||
TAG, "Failed create audio task");
|
TAG, "Failed create audio task");
|
||||||
|
|
||||||
// start muted
|
// start muted
|
||||||
if (i->config.mute_fn)
|
instance.config.mute_fn(AUDIO_PLAYER_MUTE);
|
||||||
i->config.mute_fn(AUDIO_PLAYER_MUTE);
|
|
||||||
|
|
||||||
*h = i;
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// At the moment when we run cppcheck there is a lack of esp-idf header files this
|
// At the moment when we run cppcheck there is a lack of esp-idf header files this
|
||||||
// means cppcheck doesn't know that ESP_GOTO_ON_FALSE() etc are making use of this label
|
// means cppcheck doesn't know that ESP_GOTO_ON_FALSE() etc are making use of this label
|
||||||
// cppcheck-suppress unusedLabelConfiguration
|
// cppcheck-suppress unusedLabelConfiguration
|
||||||
cleanup:
|
cleanup:
|
||||||
cleanup_memory(i);
|
cleanup_memory(instance);
|
||||||
free(i);
|
|
||||||
i = NULL;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t audio_instance_delete(audio_instance_handle_t h) {
|
esp_err_t audio_player_delete() {
|
||||||
audio_instance_t *i = static_cast<audio_instance_t *>(h);
|
|
||||||
CHECK_INSTANCE(i);
|
|
||||||
|
|
||||||
const int MAX_RETRIES = 5;
|
const int MAX_RETRIES = 5;
|
||||||
int retries = MAX_RETRIES;
|
int retries = MAX_RETRIES;
|
||||||
while(i->running && retries) {
|
while(instance.running && retries) {
|
||||||
// stop any playback and shutdown the thread
|
// stop any playback and shutdown the thread
|
||||||
audio_instance_stop(i);
|
audio_player_stop();
|
||||||
_internal_audio_player_shutdown_thread(i);
|
_internal_audio_player_shutdown_thread();
|
||||||
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
retries--;
|
retries--;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_memory(i);
|
cleanup_memory(instance);
|
||||||
free(i);
|
|
||||||
i = NULL;
|
|
||||||
|
|
||||||
// if we ran out of retries, return fail code
|
// if we ran out of retries, return fail code
|
||||||
if(retries == 0) {
|
if(retries == 0) {
|
||||||
|
|
@ -635,46 +606,3 @@ esp_err_t audio_instance_delete(audio_instance_handle_t h) {
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================= Legacy API implemented via default instance ================= */
|
|
||||||
|
|
||||||
audio_player_state_t audio_player_get_state() {
|
|
||||||
return audio_instance_get_state(g_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_player_callback_register(audio_player_cb_t call_back, void *user_ctx) {
|
|
||||||
return audio_instance_callback_register(g_instance, call_back, user_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_player_play(FILE *fp) {
|
|
||||||
return audio_instance_play(g_instance, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_player_pause() {
|
|
||||||
return audio_instance_pause(g_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_player_resume() {
|
|
||||||
return audio_instance_resume(g_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_player_stop() {
|
|
||||||
return audio_instance_stop(g_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_player_new(audio_player_config_t config) {
|
|
||||||
if (g_instance) return ESP_OK;
|
|
||||||
config.force_stereo = true; // preserve legacy behavior
|
|
||||||
audio_instance_handle_t h = NULL;
|
|
||||||
ESP_RETURN_ON_ERROR(audio_instance_new(&h, &config), TAG, "failed to create new audio instance");
|
|
||||||
g_instance = static_cast<audio_instance_t *>(h);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t audio_player_delete() {
|
|
||||||
if (g_instance) {
|
|
||||||
audio_instance_delete(g_instance);
|
|
||||||
g_instance = NULL;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
chmorgan/esp-libhelix-mp3: '>=1.0.0,<2.0.0'
|
chmorgan/esp-libhelix-mp3:
|
||||||
|
version: '>=1.0.0,<2.0.0'
|
||||||
idf:
|
idf:
|
||||||
version: '>=5.0'
|
version: '>=5.0'
|
||||||
description: Lightweight audio decoding component for esp processors
|
description: Lightweight audio decoding component for esp processors
|
||||||
url: https://github.com/chmorgan/esp-audio-player
|
url: https://github.com/chmorgan/esp-audio-player
|
||||||
version: 1.1.0
|
version: 1.0.7
|
||||||
|
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
/**
|
|
||||||
* @file audio_mixer.h
|
|
||||||
* @brief Mixer interface for esp-audio-player. Provides a global mixer that accepts
|
|
||||||
* PCM from multiple sources via FreeRTOS ring buffers and writes mixed PCM to I2S.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
#include "audio_player.h"
|
|
||||||
#include "../audio_decode_types.h" // FIXME: leaks out
|
|
||||||
#include "audio_stream.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration structure for the audio mixer
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
audio_player_mute_fn mute_fn; /**< Function to mute/unmute audio */
|
|
||||||
audio_reconfig_std_clock clk_set_fn; /**< Function to reconfigure I2S clock */
|
|
||||||
audio_player_write_fn write_fn; /**< Function to write PCM data to I2S */
|
|
||||||
UBaseType_t priority; /**< FreeRTOS task priority for the mixer task */
|
|
||||||
BaseType_t coreID; /**< ESP32 core ID for the mixer task */
|
|
||||||
|
|
||||||
format i2s_format; /**< Fixed output format for the mixer */
|
|
||||||
} audio_mixer_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Mixer callback function type
|
|
||||||
*/
|
|
||||||
typedef audio_player_cb_t audio_mixer_cb_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the number of active streams in the mixer
|
|
||||||
*
|
|
||||||
* @return Number of active streams
|
|
||||||
*/
|
|
||||||
uint8_t audio_mixer_stream_count();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Lock the mixer's main mutex
|
|
||||||
*
|
|
||||||
* Call this before modifying stream state (busy flags, queues).
|
|
||||||
*/
|
|
||||||
void audio_mixer_lock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unlock the mixer's main mutex
|
|
||||||
*/
|
|
||||||
void audio_mixer_unlock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add a stream to the mixer's processing list
|
|
||||||
*
|
|
||||||
* This function is thread-safe.
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream to add
|
|
||||||
*/
|
|
||||||
void audio_mixer_add_stream(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove a stream from the mixer's processing list
|
|
||||||
*
|
|
||||||
* This function is thread-safe.
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream to remove
|
|
||||||
*/
|
|
||||||
void audio_mixer_remove_stream(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Query the current mixer output format
|
|
||||||
*
|
|
||||||
* Returns zeros if the mixer is not initialized.
|
|
||||||
*
|
|
||||||
* @param[out] sample_rate Pointer to store the sample rate
|
|
||||||
* @param[out] bits_per_sample Pointer to store the bits per sample
|
|
||||||
* @param[out] channels Pointer to store the number of channels
|
|
||||||
*/
|
|
||||||
void audio_mixer_get_output_format(uint32_t *sample_rate, uint32_t *bits_per_sample, uint32_t *channels);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register a global callback for mixer events
|
|
||||||
*
|
|
||||||
* @param cb Callback function to register
|
|
||||||
*/
|
|
||||||
void audio_mixer_callback_register(audio_mixer_cb_t cb);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if the mixer is initialized
|
|
||||||
*
|
|
||||||
* @return true if initialized, false otherwise
|
|
||||||
*/
|
|
||||||
bool audio_mixer_is_initialized();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize the mixer and start the mixer task
|
|
||||||
*
|
|
||||||
* @param cfg Pointer to the mixer configuration structure
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - ESP_ERR_INVALID_ARG: Invalid configuration
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_mixer_init(audio_mixer_config_t *cfg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deinitialize the mixer and stop the mixer task
|
|
||||||
*/
|
|
||||||
void audio_mixer_deinit();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -152,7 +152,6 @@ typedef enum {
|
||||||
typedef esp_err_t (*audio_player_mute_fn)(AUDIO_PLAYER_MUTE_SETTING setting);
|
typedef esp_err_t (*audio_player_mute_fn)(AUDIO_PLAYER_MUTE_SETTING setting);
|
||||||
typedef esp_err_t (*audio_reconfig_std_clock)(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch);
|
typedef esp_err_t (*audio_reconfig_std_clock)(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch);
|
||||||
typedef esp_err_t (*audio_player_write_fn)(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms);
|
typedef esp_err_t (*audio_player_write_fn)(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms);
|
||||||
typedef esp_err_t (*audio_player_write_fn2)(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms, void *ctx);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
audio_player_mute_fn mute_fn;
|
audio_player_mute_fn mute_fn;
|
||||||
|
|
@ -160,10 +159,6 @@ typedef struct {
|
||||||
audio_player_write_fn write_fn;
|
audio_player_write_fn write_fn;
|
||||||
UBaseType_t priority; /*< FreeRTOS task priority */
|
UBaseType_t priority; /*< FreeRTOS task priority */
|
||||||
BaseType_t coreID; /*< ESP32 core ID */
|
BaseType_t coreID; /*< ESP32 core ID */
|
||||||
bool force_stereo; /*< upmix mono -> stereo */
|
|
||||||
|
|
||||||
audio_player_write_fn2 write_fn2;
|
|
||||||
void *write_ctx;
|
|
||||||
} audio_player_config_t;
|
} audio_player_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
/**
|
|
||||||
* @file audio_stream.h
|
|
||||||
* @brief Stream API — create/delete logical playback streams and control them.
|
|
||||||
* These streams own their decode task and submit PCM to the mixer.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "audio_player.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct audio_stream;
|
|
||||||
/**
|
|
||||||
* @brief Audio stream handle
|
|
||||||
*/
|
|
||||||
typedef struct audio_stream* audio_stream_handle_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Macro to check if a stream handle is valid
|
|
||||||
*/
|
|
||||||
#define CHECK_STREAM(s) \
|
|
||||||
ESP_RETURN_ON_FALSE(s != NULL, ESP_ERR_INVALID_ARG, "audio_stream", "stream is NULL")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Audio stream types
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
AUDIO_STREAM_TYPE_UNKNOWN = 0, /**< Unknown stream type */
|
|
||||||
AUDIO_STREAM_TYPE_DECODER, /**< Stream that decodes audio (e.g., MP3, WAV) */
|
|
||||||
AUDIO_STREAM_TYPE_RAW /**< Stream that accepts raw PCM data */
|
|
||||||
} audio_stream_type_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration structure for an audio stream
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
audio_stream_type_t type; /**< Type of stream */
|
|
||||||
char name[16]; /**< Optional: Name of the stream (e.g. "sfx", "bgm"). Auto-generated if empty. */
|
|
||||||
UBaseType_t priority; /**< FreeRTOS task priority for the stream's decoder task (if applicable) */
|
|
||||||
BaseType_t coreID; /**< ESP32 core ID for the stream's decoder task (if applicable) */
|
|
||||||
} audio_stream_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default configuration for an audio decoder stream
|
|
||||||
*
|
|
||||||
* @param _name Name of the stream
|
|
||||||
*/
|
|
||||||
#define DEFAULT_AUDIO_STREAM_CONFIG(_name) { \
|
|
||||||
.type = AUDIO_STREAM_TYPE_DECODER, \
|
|
||||||
.name = _name, \
|
|
||||||
.priority = tskIDLE_PRIORITY + 1, \
|
|
||||||
.coreID = tskNO_AFFINITY \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the current state of a stream
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @return Current audio_player_state_t of the stream
|
|
||||||
*/
|
|
||||||
audio_player_state_t audio_stream_get_state(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the type of a stream
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @return audio_stream_type_t of the stream
|
|
||||||
*/
|
|
||||||
audio_stream_type_t audio_stream_get_type(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Play an audio file on a stream
|
|
||||||
*
|
|
||||||
* Only supported for DECODER type streams.
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @param fp File pointer to the audio file
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_play(audio_stream_handle_t h, FILE *fp);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Queue an audio file to be played on a stream
|
|
||||||
*
|
|
||||||
* Only supported for DECODER type streams.
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @param fp File pointer to the audio file
|
|
||||||
* @param play_now If true, start playing immediately (interrupting current playback)
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_queue(audio_stream_handle_t h, FILE *fp, bool play_now);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stop playback on a stream
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_stop(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Pause playback on a stream
|
|
||||||
*
|
|
||||||
* Only supported for DECODER type streams.
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_pause(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Resume playback on a stream
|
|
||||||
*
|
|
||||||
* Only supported for DECODER type streams.
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_resume(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Direct write raw PCM data to a stream
|
|
||||||
*
|
|
||||||
* Only supported for RAW type streams.
|
|
||||||
* Data format must match the mixer configuration (e.g. 44.1kHz, 16-bit, mono/stereo).
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @param data Pointer to the PCM data
|
|
||||||
* @param size Size of the data in bytes
|
|
||||||
* @param timeout_ms Timeout in milliseconds to wait for space in the stream's buffer
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a raw stream
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_write_pcm(audio_stream_handle_t h, void *data, size_t size, uint32_t timeout_ms);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Send an event to a raw stream's callback
|
|
||||||
*
|
|
||||||
* Allows manual state management for raw streams.
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream
|
|
||||||
* @param event Event to send
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a raw stream
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_raw_send_event(audio_stream_handle_t h, audio_player_callback_event_t event);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new audio stream
|
|
||||||
*
|
|
||||||
* @param cfg Pointer to the stream configuration structure
|
|
||||||
* @return Handle to the new stream, or NULL if failed
|
|
||||||
*/
|
|
||||||
audio_stream_handle_t audio_stream_new(audio_stream_config_t *cfg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete an audio stream and free its resources
|
|
||||||
*
|
|
||||||
* @param h Handle of the stream to delete
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Success
|
|
||||||
* - Others: Fail
|
|
||||||
*/
|
|
||||||
esp_err_t audio_stream_delete(audio_stream_handle_t h);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
idf_component_register(SRCS "audio_player_test.c" "audio_mixer_test.c"
|
idf_component_register(SRC_DIRS "."
|
||||||
PRIV_INCLUDE_DIRS "."
|
PRIV_INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES unity test_utils audio_player
|
PRIV_REQUIRES unity test_utils audio_player
|
||||||
EMBED_TXTFILES gs-16b-1c-44100hz.mp3)
|
EMBED_TXTFILES gs-16b-1c-44100hz.mp3)
|
||||||
|
|
|
||||||
|
|
@ -1,353 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "unity.h"
|
|
||||||
#include "audio_player.h"
|
|
||||||
#include "audio_mixer.h"
|
|
||||||
#include "audio_stream.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "test_utils.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
|
|
||||||
static const char *TAG = "AUDIO MIXER TEST";
|
|
||||||
|
|
||||||
#define CONFIG_BSP_I2S_NUM 1
|
|
||||||
|
|
||||||
/* Audio Pins (same as in audio_player_test.c) */
|
|
||||||
#define BSP_I2S_SCLK (GPIO_NUM_17)
|
|
||||||
#define BSP_I2S_MCLK (GPIO_NUM_2)
|
|
||||||
#define BSP_I2S_LCLK (GPIO_NUM_47)
|
|
||||||
#define BSP_I2S_DOUT (GPIO_NUM_15)
|
|
||||||
#define BSP_I2S_DSIN (GPIO_NUM_16)
|
|
||||||
#define BSP_POWER_AMP_IO (GPIO_NUM_46)
|
|
||||||
|
|
||||||
#define BSP_I2S_GPIO_CFG \
|
|
||||||
{ \
|
|
||||||
.mclk = BSP_I2S_MCLK, \
|
|
||||||
.bclk = BSP_I2S_SCLK, \
|
|
||||||
.ws = BSP_I2S_LCLK, \
|
|
||||||
.dout = BSP_I2S_DOUT, \
|
|
||||||
.din = BSP_I2S_DSIN, \
|
|
||||||
.invert_flags = { \
|
|
||||||
.mclk_inv = false, \
|
|
||||||
.bclk_inv = false, \
|
|
||||||
.ws_inv = false, \
|
|
||||||
}, \
|
|
||||||
}
|
|
||||||
|
|
||||||
static i2s_chan_handle_t i2s_tx_chan;
|
|
||||||
static i2s_chan_handle_t i2s_rx_chan;
|
|
||||||
|
|
||||||
static esp_err_t bsp_i2s_write(void * audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms)
|
|
||||||
{
|
|
||||||
return i2s_channel_write(i2s_tx_chan, (char *)audio_buffer, len, bytes_written, timeout_ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t bsp_i2s_reconfig_clk(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch)
|
|
||||||
{
|
|
||||||
i2s_std_config_t std_cfg = {
|
|
||||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(rate),
|
|
||||||
.slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG((i2s_data_bit_width_t)bits_cfg, (i2s_slot_mode_t)ch),
|
|
||||||
.gpio_cfg = BSP_I2S_GPIO_CFG,
|
|
||||||
};
|
|
||||||
|
|
||||||
i2s_channel_disable(i2s_tx_chan);
|
|
||||||
i2s_channel_reconfig_std_clock(i2s_tx_chan, &std_cfg.clk_cfg);
|
|
||||||
i2s_channel_reconfig_std_slot(i2s_tx_chan, &std_cfg.slot_cfg);
|
|
||||||
return i2s_channel_enable(i2s_tx_chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t bsp_audio_init(const i2s_std_config_t *i2s_config)
|
|
||||||
{
|
|
||||||
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(CONFIG_BSP_I2S_NUM, I2S_ROLE_MASTER);
|
|
||||||
chan_cfg.auto_clear = true;
|
|
||||||
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &i2s_tx_chan, &i2s_rx_chan));
|
|
||||||
ESP_ERROR_CHECK(i2s_channel_init_std_mode(i2s_tx_chan, i2s_config));
|
|
||||||
ESP_ERROR_CHECK(i2s_channel_enable(i2s_tx_chan));
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bsp_audio_deinit()
|
|
||||||
{
|
|
||||||
i2s_channel_disable(i2s_tx_chan);
|
|
||||||
i2s_del_channel(i2s_tx_chan);
|
|
||||||
i2s_del_channel(i2s_rx_chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio mixer can be initialized and deinitialized", "[audio mixer]")
|
|
||||||
{
|
|
||||||
i2s_std_config_t std_cfg = {
|
|
||||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100),
|
|
||||||
.slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
|
|
||||||
.gpio_cfg = BSP_I2S_GPIO_CFG,
|
|
||||||
};
|
|
||||||
TEST_ESP_OK(bsp_audio_init(&std_cfg));
|
|
||||||
|
|
||||||
audio_mixer_config_t mixer_cfg = {
|
|
||||||
.write_fn = bsp_i2s_write,
|
|
||||||
.clk_set_fn = bsp_i2s_reconfig_clk,
|
|
||||||
.priority = 5,
|
|
||||||
.coreID = 0,
|
|
||||||
.i2s_format = {
|
|
||||||
.sample_rate = 44100,
|
|
||||||
.bits_per_sample = 16,
|
|
||||||
.channels = 2
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_mixer_init(&mixer_cfg));
|
|
||||||
TEST_ASSERT_TRUE(audio_mixer_is_initialized());
|
|
||||||
|
|
||||||
audio_mixer_deinit();
|
|
||||||
TEST_ASSERT_FALSE(audio_mixer_is_initialized());
|
|
||||||
|
|
||||||
bsp_audio_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio streams can be created and deleted", "[audio mixer]")
|
|
||||||
{
|
|
||||||
i2s_std_config_t std_cfg = {
|
|
||||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100),
|
|
||||||
.slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
|
|
||||||
.gpio_cfg = BSP_I2S_GPIO_CFG,
|
|
||||||
};
|
|
||||||
TEST_ESP_OK(bsp_audio_init(&std_cfg));
|
|
||||||
|
|
||||||
audio_mixer_config_t mixer_cfg = {
|
|
||||||
.write_fn = bsp_i2s_write,
|
|
||||||
.clk_set_fn = bsp_i2s_reconfig_clk,
|
|
||||||
.priority = 5,
|
|
||||||
.coreID = 0,
|
|
||||||
.i2s_format = {
|
|
||||||
.sample_rate = 44100,
|
|
||||||
.bits_per_sample = 16,
|
|
||||||
.channels = 2
|
|
||||||
}
|
|
||||||
};
|
|
||||||
TEST_ESP_OK(audio_mixer_init(&mixer_cfg));
|
|
||||||
|
|
||||||
// Create a decoder stream
|
|
||||||
audio_stream_config_t stream_cfg = DEFAULT_AUDIO_STREAM_CONFIG("decoder");
|
|
||||||
audio_stream_handle_t decoder_stream = audio_stream_new(&stream_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(decoder_stream);
|
|
||||||
TEST_ASSERT_EQUAL(AUDIO_STREAM_TYPE_DECODER, audio_stream_get_type(decoder_stream));
|
|
||||||
TEST_ASSERT_EQUAL(1, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
// Create a raw stream
|
|
||||||
audio_stream_config_t raw_cfg = {
|
|
||||||
.type = AUDIO_STREAM_TYPE_RAW,
|
|
||||||
.name = "raw",
|
|
||||||
.priority = 5,
|
|
||||||
.coreID = 0
|
|
||||||
};
|
|
||||||
audio_stream_handle_t raw_stream = audio_stream_new(&raw_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(raw_stream);
|
|
||||||
TEST_ASSERT_EQUAL(AUDIO_STREAM_TYPE_RAW, audio_stream_get_type(raw_stream));
|
|
||||||
TEST_ASSERT_EQUAL(2, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
// Delete streams
|
|
||||||
TEST_ESP_OK(audio_stream_delete(decoder_stream));
|
|
||||||
TEST_ASSERT_EQUAL(1, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_delete(raw_stream));
|
|
||||||
TEST_ASSERT_EQUAL(0, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
audio_mixer_deinit();
|
|
||||||
bsp_audio_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio mixer handles multiple streams and output format", "[audio mixer]")
|
|
||||||
{
|
|
||||||
i2s_std_config_t std_cfg = {
|
|
||||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100),
|
|
||||||
.slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
|
|
||||||
.gpio_cfg = BSP_I2S_GPIO_CFG,
|
|
||||||
};
|
|
||||||
TEST_ESP_OK(bsp_audio_init(&std_cfg));
|
|
||||||
|
|
||||||
audio_mixer_config_t mixer_cfg = {
|
|
||||||
.write_fn = bsp_i2s_write,
|
|
||||||
.clk_set_fn = bsp_i2s_reconfig_clk,
|
|
||||||
.priority = 5,
|
|
||||||
.coreID = 0,
|
|
||||||
.i2s_format = {
|
|
||||||
.sample_rate = 48000,
|
|
||||||
.bits_per_sample = 16,
|
|
||||||
.channels = 2
|
|
||||||
}
|
|
||||||
};
|
|
||||||
TEST_ESP_OK(audio_mixer_init(&mixer_cfg));
|
|
||||||
|
|
||||||
uint32_t rate, bits, ch;
|
|
||||||
audio_mixer_get_output_format(&rate, &bits, &ch);
|
|
||||||
TEST_ASSERT_EQUAL(48000, rate);
|
|
||||||
TEST_ASSERT_EQUAL(16, bits);
|
|
||||||
TEST_ASSERT_EQUAL(2, ch);
|
|
||||||
|
|
||||||
audio_stream_config_t s1_cfg = DEFAULT_AUDIO_STREAM_CONFIG("s1");
|
|
||||||
audio_stream_handle_t s1 = audio_stream_new(&s1_cfg);
|
|
||||||
(void)s1;
|
|
||||||
audio_stream_config_t s2_cfg = DEFAULT_AUDIO_STREAM_CONFIG("s2");
|
|
||||||
audio_stream_handle_t s2 = audio_stream_new(&s2_cfg);
|
|
||||||
(void)s2;
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(2, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
audio_mixer_deinit(); // Should also clean up streams
|
|
||||||
TEST_ASSERT_EQUAL(0, audio_mixer_stream_count());
|
|
||||||
|
|
||||||
bsp_audio_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio stream raw can send events", "[audio mixer]")
|
|
||||||
{
|
|
||||||
audio_stream_config_t raw_cfg = {
|
|
||||||
.type = AUDIO_STREAM_TYPE_RAW,
|
|
||||||
.name = "raw_event",
|
|
||||||
.priority = 5,
|
|
||||||
.coreID = 0
|
|
||||||
};
|
|
||||||
audio_stream_handle_t raw_stream = audio_stream_new(&raw_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(raw_stream);
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(AUDIO_PLAYER_STATE_IDLE, audio_stream_get_state(raw_stream));
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_raw_send_event(raw_stream, AUDIO_PLAYER_CALLBACK_EVENT_PLAYING));
|
|
||||||
TEST_ASSERT_EQUAL(AUDIO_PLAYER_STATE_PLAYING, audio_stream_get_state(raw_stream));
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_raw_send_event(raw_stream, AUDIO_PLAYER_CALLBACK_EVENT_IDLE));
|
|
||||||
TEST_ASSERT_EQUAL(AUDIO_PLAYER_STATE_IDLE, audio_stream_get_state(raw_stream));
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_delete(raw_stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
static QueueHandle_t mixer_event_queue;
|
|
||||||
|
|
||||||
static void mixer_callback(audio_player_cb_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
if (ctx->audio_event == AUDIO_PLAYER_CALLBACK_EVENT_PLAYING ||
|
|
||||||
ctx->audio_event == AUDIO_PLAYER_CALLBACK_EVENT_IDLE) {
|
|
||||||
xQueueSend(mixer_event_queue, &(ctx->audio_event), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio mixer plays sample mp3 on multiple streams", "[audio mixer]")
|
|
||||||
{
|
|
||||||
i2s_std_config_t std_cfg = {
|
|
||||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100),
|
|
||||||
.slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
|
|
||||||
.gpio_cfg = BSP_I2S_GPIO_CFG,
|
|
||||||
};
|
|
||||||
TEST_ESP_OK(bsp_audio_init(&std_cfg));
|
|
||||||
|
|
||||||
audio_mixer_config_t mixer_cfg = {
|
|
||||||
.write_fn = bsp_i2s_write,
|
|
||||||
.clk_set_fn = bsp_i2s_reconfig_clk,
|
|
||||||
.priority = 5,
|
|
||||||
.coreID = 0,
|
|
||||||
.i2s_format = {
|
|
||||||
.sample_rate = 44100,
|
|
||||||
.bits_per_sample = 16,
|
|
||||||
.channels = 2
|
|
||||||
}
|
|
||||||
};
|
|
||||||
TEST_ESP_OK(audio_mixer_init(&mixer_cfg));
|
|
||||||
|
|
||||||
mixer_event_queue = xQueueCreate(10, sizeof(audio_player_callback_event_t));
|
|
||||||
TEST_ASSERT_NOT_NULL(mixer_event_queue);
|
|
||||||
audio_mixer_callback_register(mixer_callback);
|
|
||||||
|
|
||||||
extern const char mp3_start[] asm("_binary_gs_16b_1c_44100hz_mp3_start");
|
|
||||||
extern const char mp3_end[] asm("_binary_gs_16b_1c_44100hz_mp3_end");
|
|
||||||
size_t mp3_size = (size_t)((uintptr_t)mp3_end - (uintptr_t)mp3_start);
|
|
||||||
|
|
||||||
// Create two streams
|
|
||||||
audio_stream_config_t s1_cfg = DEFAULT_AUDIO_STREAM_CONFIG("stream1");
|
|
||||||
audio_stream_handle_t s1 = audio_stream_new(&s1_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(s1);
|
|
||||||
|
|
||||||
audio_stream_config_t s2_cfg = DEFAULT_AUDIO_STREAM_CONFIG("stream2");
|
|
||||||
audio_stream_handle_t s2 = audio_stream_new(&s2_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(s2);
|
|
||||||
|
|
||||||
// Play on stream 1
|
|
||||||
FILE *f1 = fmemopen((void*)mp3_start, mp3_size, "rb");
|
|
||||||
TEST_ASSERT_NOT_NULL(f1);
|
|
||||||
TEST_ESP_OK(audio_stream_play(s1, f1));
|
|
||||||
|
|
||||||
// Play on stream 2
|
|
||||||
FILE *f2 = fmemopen((void*)mp3_start, mp3_size, "rb");
|
|
||||||
TEST_ASSERT_NOT_NULL(f2);
|
|
||||||
TEST_ESP_OK(audio_stream_play(s2, f2));
|
|
||||||
|
|
||||||
audio_player_callback_event_t event;
|
|
||||||
// We expect two PLAYING events (one for each stream)
|
|
||||||
int playing_count = 0;
|
|
||||||
while (playing_count < 2 && xQueueReceive(mixer_event_queue, &event, pdMS_TO_TICKS(500)) == pdPASS) {
|
|
||||||
if (event == AUDIO_PLAYER_CALLBACK_EVENT_PLAYING) {
|
|
||||||
playing_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TEST_ASSERT_EQUAL(2, playing_count);
|
|
||||||
|
|
||||||
// Let it play for a few seconds
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
|
||||||
|
|
||||||
// Stop streams
|
|
||||||
TEST_ESP_OK(audio_stream_stop(s1));
|
|
||||||
TEST_ESP_OK(audio_stream_stop(s2));
|
|
||||||
|
|
||||||
audio_mixer_deinit();
|
|
||||||
vQueueDelete(mixer_event_queue);
|
|
||||||
bsp_audio_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio stream pause and resume", "[audio mixer]")
|
|
||||||
{
|
|
||||||
audio_stream_config_t stream_cfg = DEFAULT_AUDIO_STREAM_CONFIG("pause_resume");
|
|
||||||
audio_stream_handle_t s = audio_stream_new(&stream_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(s);
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_pause(s));
|
|
||||||
TEST_ASSERT_EQUAL(AUDIO_PLAYER_STATE_PAUSE, audio_stream_get_state(s));
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_resume(s));
|
|
||||||
TEST_ASSERT_EQUAL(AUDIO_PLAYER_STATE_PLAYING, audio_stream_get_state(s));
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_delete(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio stream queue", "[audio mixer]")
|
|
||||||
{
|
|
||||||
audio_stream_config_t stream_cfg = DEFAULT_AUDIO_STREAM_CONFIG("queue");
|
|
||||||
audio_stream_handle_t s = audio_stream_new(&stream_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(s);
|
|
||||||
|
|
||||||
extern const char mp3_start[] asm("_binary_gs_16b_1c_44100hz_mp3_start");
|
|
||||||
extern const char mp3_end[] asm("_binary_gs_16b_1c_44100hz_mp3_end");
|
|
||||||
size_t mp3_size = (size_t)((uintptr_t)mp3_end - (uintptr_t)mp3_start);
|
|
||||||
|
|
||||||
FILE *f1 = fmemopen((void*)mp3_start, mp3_size, "rb");
|
|
||||||
TEST_ASSERT_NOT_NULL(f1);
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_queue(s, f1, false));
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_delete(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("audio stream write pcm", "[audio mixer]")
|
|
||||||
{
|
|
||||||
audio_stream_config_t raw_cfg = {
|
|
||||||
.type = AUDIO_STREAM_TYPE_RAW,
|
|
||||||
.name = "raw_write",
|
|
||||||
.priority = 5,
|
|
||||||
.coreID = 0
|
|
||||||
};
|
|
||||||
audio_stream_handle_t s = audio_stream_new(&raw_cfg);
|
|
||||||
TEST_ASSERT_NOT_NULL(s);
|
|
||||||
|
|
||||||
int16_t dummy_pcm[128] = {0};
|
|
||||||
TEST_ESP_OK(audio_stream_write_pcm(s, dummy_pcm, sizeof(dummy_pcm), 100));
|
|
||||||
|
|
||||||
TEST_ESP_OK(audio_stream_delete(s));
|
|
||||||
}
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
fccb18c37f1cfe0797b74a53a44d3f400f5fd01f4993b40052dfb7f401915089
|
30a3f495c3862d505ce6e41adbbd218b2750e9723ab2151feff00e9fe685b326
|
||||||
|
|
@ -1,61 +1,5 @@
|
||||||
# ChangeLog
|
# ChangeLog
|
||||||
|
|
||||||
## v4.1.5 - 2025-12-3
|
|
||||||
|
|
||||||
### Fix:
|
|
||||||
|
|
||||||
* Fixed the unreasonable function name `iot_button_get_ticks_time` and renamed it to `iot_button_get_pressed_time`
|
|
||||||
|
|
||||||
## v4.1.4 - 2025-10-08
|
|
||||||
|
|
||||||
### Fix:
|
|
||||||
|
|
||||||
* Fixed requires in CMake for IDF6.
|
|
||||||
|
|
||||||
## v4.1.3 - 2025-04-11
|
|
||||||
|
|
||||||
### Fix:
|
|
||||||
|
|
||||||
* Added initialization for gpio_config. [!485](https://github.com/espressif/esp-iot-solution/pull/485)
|
|
||||||
|
|
||||||
## v4.1.2 - 2025-03-24
|
|
||||||
|
|
||||||
### Fix:
|
|
||||||
|
|
||||||
* fix incorrect long press start and release check.
|
|
||||||
|
|
||||||
## v4.1.1 - 2025-03-13
|
|
||||||
|
|
||||||
### Improve:
|
|
||||||
|
|
||||||
* include stdbool.h before using bool
|
|
||||||
|
|
||||||
## v4.1.0 - 2025-02-28
|
|
||||||
|
|
||||||
### Improve:
|
|
||||||
|
|
||||||
* Update the version of dependent cmake_utilities to *
|
|
||||||
|
|
||||||
## v4.0.0 - 2025-1-9
|
|
||||||
|
|
||||||
### Enhancements:
|
|
||||||
|
|
||||||
* Use the factory pattern to reduce the build size.
|
|
||||||
* Change the state machine to use enumerated values.
|
|
||||||
|
|
||||||
### Break change:
|
|
||||||
|
|
||||||
* Standardize the return value of the iot_button interface to esp_err_t.
|
|
||||||
* Remove support for the old ADC driver.
|
|
||||||
* Modify the callback registration interface to:
|
|
||||||
```c
|
|
||||||
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args, button_cb_t cb, void *usr_data);
|
|
||||||
```
|
|
||||||
* Modify the callback unregistration interface to:
|
|
||||||
```c
|
|
||||||
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args);
|
|
||||||
```
|
|
||||||
|
|
||||||
## v3.5.0 - 2024-12-27
|
## v3.5.0 - 2024-12-27
|
||||||
|
|
||||||
### Enhancements:
|
### Enhancements:
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
set(PRIVREQ esp_timer)
|
set(PRIVREQ esp_timer)
|
||||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
|
set(REQ driver)
|
||||||
set(REQ esp_driver_gpio)
|
|
||||||
else()
|
|
||||||
set(REQ driver)
|
|
||||||
endif()
|
|
||||||
set(SRC_FILES "button_gpio.c" "iot_button.c" "button_matrix.c")
|
set(SRC_FILES "button_gpio.c" "iot_button.c" "button_matrix.c")
|
||||||
|
|
||||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
|
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
|
||||||
|
|
@ -11,12 +7,26 @@ if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
|
||||||
if(CONFIG_SOC_ADC_SUPPORTED)
|
if(CONFIG_SOC_ADC_SUPPORTED)
|
||||||
list(APPEND SRC_FILES "button_adc.c")
|
list(APPEND SRC_FILES "button_adc.c")
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
list(APPEND REQ esp_adc_cal)
|
||||||
|
list(APPEND SRC_FILES "button_adc.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS ${SRC_FILES}
|
idf_component_register(SRCS ${SRC_FILES}
|
||||||
INCLUDE_DIRS include interface
|
INCLUDE_DIRS include
|
||||||
REQUIRES ${REQ}
|
REQUIRES ${REQ}
|
||||||
PRIV_REQUIRES ${PRIVREQ})
|
PRIV_REQUIRES ${PRIVREQ})
|
||||||
|
|
||||||
|
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_LESS "5.0")
|
||||||
|
# Add the macro CONFIG_SOC_ADC_SUPPORTED for the following chips.
|
||||||
|
if(CONFIG_IDF_TARGET STREQUAL "esp32" OR
|
||||||
|
CONFIG_IDF_TARGET STREQUAL "esp32s2" OR
|
||||||
|
CONFIG_IDF_TARGET STREQUAL "esp32s3" OR
|
||||||
|
CONFIG_IDF_TARGET STREQUAL "esp32c3" OR
|
||||||
|
CONFIG_IDF_TARGET STREQUAL "esp32h2")
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} PUBLIC CONFIG_SOC_ADC_SUPPORTED)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
include(package_manager)
|
include(package_manager)
|
||||||
cu_pkg_define_version(${CMAKE_CURRENT_LIST_DIR})
|
cu_pkg_define_version(${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,22 @@ menu "IoT Button"
|
||||||
range 500 5000
|
range 500 5000
|
||||||
default 1500
|
default 1500
|
||||||
|
|
||||||
config BUTTON_LONG_PRESS_HOLD_SERIAL_TIME_MS
|
config BUTTON_SERIAL_TIME_MS
|
||||||
int "BUTTON LONG_PRESS_HOLD SERIAL TIME (MS)"
|
int "BUTTON SERIAL TIME (MS)"
|
||||||
range 2 1000
|
range 2 1000
|
||||||
default 20
|
default 20
|
||||||
help
|
help
|
||||||
"Long press hold Serial trigger interval"
|
"Serial trigger interval"
|
||||||
|
|
||||||
|
config GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
|
bool "GPIO BUTTON SUPPORT POWER SAVE"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable GPIO button power save
|
||||||
|
|
||||||
|
The function enables the use of GPIO buttons during light sleep,
|
||||||
|
but enabling this function prevents the simultaneous use of other
|
||||||
|
types of buttons.
|
||||||
|
|
||||||
config ADC_BUTTON_MAX_CHANNEL
|
config ADC_BUTTON_MAX_CHANNEL
|
||||||
int "ADC BUTTON MAX CHANNEL"
|
int "ADC BUTTON MAX CHANNEL"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
/* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
@ -6,17 +6,28 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_idf_version.h"
|
#include "esp_idf_version.h"
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "esp_adc/adc_oneshot.h"
|
#include "esp_adc/adc_oneshot.h"
|
||||||
#include "esp_adc/adc_cali.h"
|
#include "esp_adc/adc_cali.h"
|
||||||
#include "esp_adc/adc_cali_scheme.h"
|
#include "esp_adc/adc_cali_scheme.h"
|
||||||
|
#else
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/adc.h"
|
||||||
|
#include "esp_adc_cal.h"
|
||||||
|
#endif
|
||||||
#include "button_adc.h"
|
#include "button_adc.h"
|
||||||
#include "button_interface.h"
|
|
||||||
|
|
||||||
static const char *TAG = "adc_button";
|
static const char *TAG = "adc button";
|
||||||
|
|
||||||
|
#define ADC_BTN_CHECK(a, str, ret_val) \
|
||||||
|
if (!(a)) \
|
||||||
|
{ \
|
||||||
|
ESP_LOGE(TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||||
|
return (ret_val); \
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFAULT_VREF 1100
|
#define DEFAULT_VREF 1100
|
||||||
#define NO_OF_SAMPLES CONFIG_ADC_BUTTON_SAMPLE_TIMES //Multisampling
|
#define NO_OF_SAMPLES CONFIG_ADC_BUTTON_SAMPLE_TIMES //Multisampling
|
||||||
|
|
@ -24,20 +35,19 @@ static const char *TAG = "adc_button";
|
||||||
/*!< Using atten bigger than 6db by default, it will be 11db or 12db in different target */
|
/*!< Using atten bigger than 6db by default, it will be 11db or 12db in different target */
|
||||||
#define DEFAULT_ADC_ATTEN (ADC_ATTEN_DB_6 + 1)
|
#define DEFAULT_ADC_ATTEN (ADC_ATTEN_DB_6 + 1)
|
||||||
|
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
#define ADC_BUTTON_WIDTH SOC_ADC_RTC_MAX_BITWIDTH
|
#define ADC_BUTTON_WIDTH SOC_ADC_RTC_MAX_BITWIDTH
|
||||||
#define ADC_BUTTON_CHANNEL_MAX SOC_ADC_MAX_CHANNEL_NUM
|
#define ADC1_BUTTON_CHANNEL_MAX SOC_ADC_MAX_CHANNEL_NUM
|
||||||
#define ADC_BUTTON_ATTEN DEFAULT_ADC_ATTEN
|
#define ADC_BUTTON_ATTEN DEFAULT_ADC_ATTEN
|
||||||
|
#else
|
||||||
|
#define ADC_BUTTON_WIDTH ADC_WIDTH_MAX-1
|
||||||
|
#define ADC1_BUTTON_CHANNEL_MAX ADC1_CHANNEL_MAX
|
||||||
|
#define ADC_BUTTON_ATTEN DEFAULT_ADC_ATTEN
|
||||||
|
#endif
|
||||||
|
#define ADC_BUTTON_ADC_UNIT ADC_UNIT_1
|
||||||
#define ADC_BUTTON_MAX_CHANNEL CONFIG_ADC_BUTTON_MAX_CHANNEL
|
#define ADC_BUTTON_MAX_CHANNEL CONFIG_ADC_BUTTON_MAX_CHANNEL
|
||||||
#define ADC_BUTTON_MAX_BUTTON CONFIG_ADC_BUTTON_MAX_BUTTON_PER_CHANNEL
|
#define ADC_BUTTON_MAX_BUTTON CONFIG_ADC_BUTTON_MAX_BUTTON_PER_CHANNEL
|
||||||
|
|
||||||
// ESP32C3 ADC2 it has been deprecated.
|
|
||||||
#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3
|
|
||||||
#define ADC_UNIT_NUM 2
|
|
||||||
#else
|
|
||||||
#define ADC_UNIT_NUM 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t min;
|
uint16_t min;
|
||||||
uint16_t max;
|
uint16_t max;
|
||||||
|
|
@ -50,56 +60,45 @@ typedef struct {
|
||||||
uint64_t last_time; /* the last time of adc sample */
|
uint64_t last_time; /* the last time of adc sample */
|
||||||
} btn_adc_channel_t;
|
} btn_adc_channel_t;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
ADC_NONE_INIT = 0,
|
|
||||||
ADC_INIT_BY_ADC_BUTTON,
|
|
||||||
ADC_INIT_BY_USER,
|
|
||||||
} adc_init_info_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
adc_init_info_t is_configured;
|
bool is_configured;
|
||||||
adc_cali_handle_t adc_cali_handle;
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
adc_oneshot_unit_handle_t adc_handle;
|
adc_cali_handle_t adc1_cali_handle;
|
||||||
|
adc_oneshot_unit_handle_t adc1_handle;
|
||||||
|
#else
|
||||||
|
esp_adc_cal_characteristics_t adc_chars;
|
||||||
|
#endif
|
||||||
btn_adc_channel_t ch[ADC_BUTTON_MAX_CHANNEL];
|
btn_adc_channel_t ch[ADC_BUTTON_MAX_CHANNEL];
|
||||||
uint8_t ch_num;
|
uint8_t ch_num;
|
||||||
} btn_adc_unit_t;
|
} adc_button_t;
|
||||||
|
|
||||||
typedef struct {
|
static adc_button_t g_button = {0};
|
||||||
btn_adc_unit_t unit[ADC_UNIT_NUM];
|
|
||||||
} button_adc_t;
|
|
||||||
typedef struct {
|
|
||||||
button_driver_t base;
|
|
||||||
adc_unit_t unit_id;
|
|
||||||
uint32_t ch;
|
|
||||||
uint32_t index;
|
|
||||||
} button_adc_obj;
|
|
||||||
|
|
||||||
static button_adc_t g_button = {0};
|
static int find_unused_channel(void)
|
||||||
|
|
||||||
static int find_unused_channel(adc_unit_t unit_id)
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
||||||
if (0 == g_button.unit[unit_id].ch[i].is_init) {
|
if (0 == g_button.ch[i].is_init) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_channel(adc_unit_t unit_id, uint8_t channel)
|
static int find_channel(uint8_t channel)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
||||||
if (channel == g_button.unit[unit_id].ch[i].channel) {
|
if (channel == g_button.ch[i].channel) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle)
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
static esp_err_t adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle)
|
||||||
{
|
{
|
||||||
adc_cali_handle_t handle = NULL;
|
adc_cali_handle_t handle = NULL;
|
||||||
esp_err_t ret = ESP_ERR_NOT_SUPPORTED;
|
esp_err_t ret = ESP_FAIL;
|
||||||
bool calibrated = false;
|
bool calibrated = false;
|
||||||
|
|
||||||
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
|
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
|
||||||
|
|
@ -137,191 +136,177 @@ static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_ha
|
||||||
ESP_LOGI(TAG, "Calibration Success");
|
ESP_LOGI(TAG, "Calibration Success");
|
||||||
} else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
|
} else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
|
||||||
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
|
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
|
||||||
} else if (ret == ESP_ERR_NOT_SUPPORTED) {
|
|
||||||
ESP_LOGW(TAG, "Calibration not supported");
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Invalid arg or no memory");
|
ESP_LOGE(TAG, "Invalid arg or no memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
return calibrated;
|
return calibrated ? ESP_OK : ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool adc_calibration_deinit(adc_cali_handle_t handle)
|
|
||||||
{
|
|
||||||
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
|
|
||||||
if (adc_cali_delete_scheme_curve_fitting(handle) == ESP_OK) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
|
esp_err_t button_adc_init(const button_adc_config_t *config)
|
||||||
if (adc_cali_delete_scheme_line_fitting(handle) == ESP_OK) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t button_adc_del(button_driver_t *button_driver)
|
|
||||||
{
|
{
|
||||||
button_adc_obj *adc_btn = __containerof(button_driver, button_adc_obj, base);
|
ADC_BTN_CHECK(NULL != config, "Pointer of config is invalid", ESP_ERR_INVALID_ARG);
|
||||||
ESP_RETURN_ON_FALSE(adc_btn->ch < ADC_BUTTON_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "channel out of range");
|
ADC_BTN_CHECK(config->adc_channel < ADC1_BUTTON_CHANNEL_MAX, "channel out of range", ESP_ERR_NOT_SUPPORTED);
|
||||||
ESP_RETURN_ON_FALSE(adc_btn->index < ADC_BUTTON_MAX_BUTTON, ESP_ERR_INVALID_ARG, TAG, "button_index out of range");
|
ADC_BTN_CHECK(config->button_index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", ESP_ERR_NOT_SUPPORTED);
|
||||||
|
ADC_BTN_CHECK(config->max > 0, "key max voltage invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
int ch_index = find_channel(adc_btn->unit_id, adc_btn->ch);
|
int ch_index = find_channel(config->adc_channel);
|
||||||
ESP_RETURN_ON_FALSE(ch_index >= 0, ESP_ERR_INVALID_ARG, TAG, "can't find the channel");
|
|
||||||
|
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].btns[adc_btn->index].max = 0;
|
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].btns[adc_btn->index].min = 0;
|
|
||||||
|
|
||||||
/** check button usage on the channel*/
|
|
||||||
uint8_t unused_button = 0;
|
|
||||||
for (size_t i = 0; i < ADC_BUTTON_MAX_BUTTON; i++) {
|
|
||||||
if (0 == g_button.unit[adc_btn->unit_id].ch[ch_index].btns[i].max) {
|
|
||||||
unused_button++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unused_button == ADC_BUTTON_MAX_BUTTON && g_button.unit[adc_btn->unit_id].ch[ch_index].is_init) { /**< if all button is unused, deinit the channel */
|
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].is_init = 0;
|
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].channel = ADC_BUTTON_CHANNEL_MAX;
|
|
||||||
ESP_LOGD(TAG, "all button is unused on channel%d, deinit the channel", g_button.unit[adc_btn->unit_id].ch[ch_index].channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** check channel usage on the adc*/
|
|
||||||
uint8_t unused_ch = 0;
|
|
||||||
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
|
||||||
if (0 == g_button.unit[adc_btn->unit_id].ch[i].is_init) {
|
|
||||||
unused_ch++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unused_ch == ADC_BUTTON_MAX_CHANNEL && g_button.unit[adc_btn->unit_id].is_configured) { /**< if all channel is unused, deinit the adc */
|
|
||||||
if (g_button.unit[adc_btn->unit_id].is_configured == ADC_INIT_BY_ADC_BUTTON) {
|
|
||||||
esp_err_t ret = adc_oneshot_del_unit(g_button.unit[adc_btn->unit_id].adc_handle);
|
|
||||||
ESP_RETURN_ON_FALSE(ret == ESP_OK, ret, TAG, "adc oneshot del unit fail");
|
|
||||||
adc_calibration_deinit(g_button.unit[adc_btn->unit_id].adc_cali_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_button.unit[adc_btn->unit_id].is_configured = ADC_NONE_INIT;
|
|
||||||
memset(&g_button.unit[adc_btn->unit_id], 0, sizeof(btn_adc_unit_t));
|
|
||||||
ESP_LOGD(TAG, "all channel is unused, , deinit adc");
|
|
||||||
}
|
|
||||||
free(adc_btn);
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t get_adc_voltage(adc_unit_t unit_id, uint8_t channel)
|
|
||||||
{
|
|
||||||
uint32_t adc_reading = 0;
|
|
||||||
int adc_raw = 0;
|
|
||||||
for (int i = 0; i < NO_OF_SAMPLES; i++) {
|
|
||||||
adc_oneshot_read(g_button.unit[unit_id].adc_handle, channel, &adc_raw);
|
|
||||||
adc_reading += adc_raw;
|
|
||||||
}
|
|
||||||
adc_reading /= NO_OF_SAMPLES;
|
|
||||||
//Convert adc_reading to voltage in mV
|
|
||||||
int voltage = 0;
|
|
||||||
adc_cali_raw_to_voltage(g_button.unit[unit_id].adc_cali_handle, adc_reading, &voltage);
|
|
||||||
ESP_LOGV(TAG, "Raw: %"PRIu32"\tVoltage: %dmV", adc_reading, voltage);
|
|
||||||
return voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t button_adc_get_key_level(button_driver_t *button_driver)
|
|
||||||
{
|
|
||||||
button_adc_obj *adc_btn = __containerof(button_driver, button_adc_obj, base);
|
|
||||||
static uint16_t vol = 0;
|
|
||||||
uint32_t ch = adc_btn->ch;
|
|
||||||
uint32_t index = adc_btn->index;
|
|
||||||
ESP_RETURN_ON_FALSE(ch < ADC_BUTTON_CHANNEL_MAX, 0, TAG, "channel out of range");
|
|
||||||
ESP_RETURN_ON_FALSE(index < ADC_BUTTON_MAX_BUTTON, 0, TAG, "button_index out of range");
|
|
||||||
|
|
||||||
int ch_index = find_channel(adc_btn->unit_id, ch);
|
|
||||||
ESP_RETURN_ON_FALSE(ch_index >= 0, 0, TAG, "The button_index is not init");
|
|
||||||
|
|
||||||
/** It starts only when the elapsed time is more than 1ms */
|
|
||||||
if ((esp_timer_get_time() - g_button.unit[adc_btn->unit_id].ch[ch_index].last_time) > 1000) {
|
|
||||||
vol = get_adc_voltage(adc_btn->unit_id, ch);
|
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].last_time = esp_timer_get_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vol <= g_button.unit[adc_btn->unit_id].ch[ch_index].btns[index].max &&
|
|
||||||
vol >= g_button.unit[adc_btn->unit_id].ch[ch_index].btns[index].min) {
|
|
||||||
return BUTTON_ACTIVE;
|
|
||||||
}
|
|
||||||
return BUTTON_INACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t iot_button_new_adc_device(const button_config_t *button_config, const button_adc_config_t *adc_config, button_handle_t *ret_button)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_RETURN_ON_FALSE(button_config && adc_config && ret_button, ESP_ERR_INVALID_ARG, TAG, "Invalid argument");
|
|
||||||
ESP_RETURN_ON_FALSE(adc_config->unit_id < ADC_UNIT_NUM, ESP_ERR_INVALID_ARG, TAG, "adc_handle out of range");
|
|
||||||
ESP_RETURN_ON_FALSE(adc_config->adc_channel < ADC_BUTTON_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "channel out of range");
|
|
||||||
ESP_RETURN_ON_FALSE(adc_config->button_index < ADC_BUTTON_MAX_BUTTON, ESP_ERR_INVALID_ARG, TAG, "button_index out of range");
|
|
||||||
ESP_RETURN_ON_FALSE(adc_config->max > 0, ESP_ERR_INVALID_ARG, TAG, "key max voltage invalid");
|
|
||||||
button_adc_obj *adc_btn = calloc(1, sizeof(button_adc_obj));
|
|
||||||
ESP_RETURN_ON_FALSE(adc_btn, ESP_ERR_NO_MEM, TAG, "calloc fail");
|
|
||||||
adc_btn->unit_id = adc_config->unit_id;
|
|
||||||
|
|
||||||
int ch_index = find_channel(adc_btn->unit_id, adc_config->adc_channel);
|
|
||||||
if (ch_index >= 0) { /**< the channel has been initialized */
|
if (ch_index >= 0) { /**< the channel has been initialized */
|
||||||
ESP_GOTO_ON_FALSE(g_button.unit[adc_btn->unit_id].ch[ch_index].btns[adc_config->button_index].max == 0, ESP_ERR_INVALID_STATE, err, TAG, "The button_index has been used");
|
ADC_BTN_CHECK(g_button.ch[ch_index].btns[config->button_index].max == 0, "The button_index has been used", ESP_ERR_INVALID_STATE);
|
||||||
} else { /**< this is a new channel */
|
} else { /**< this is a new channel */
|
||||||
int unused_ch_index = find_unused_channel(adc_config->unit_id);
|
int unused_ch_index = find_unused_channel();
|
||||||
ESP_GOTO_ON_FALSE(unused_ch_index >= 0, ESP_ERR_INVALID_STATE, err, TAG, "exceed max channel number, can't create a new channel");
|
ADC_BTN_CHECK(unused_ch_index >= 0, "exceed max channel number, can't create a new channel", ESP_ERR_INVALID_STATE);
|
||||||
ch_index = unused_ch_index;
|
ch_index = unused_ch_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** initialize adc */
|
/** initialize adc */
|
||||||
if (0 == g_button.unit[adc_btn->unit_id].is_configured) {
|
if (0 == g_button.is_configured) {
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
if (NULL == adc_config->adc_handle) {
|
if (NULL == config->adc_handle) {
|
||||||
//ADC1 Init
|
//ADC1 Init
|
||||||
adc_oneshot_unit_init_cfg_t init_config = {
|
adc_oneshot_unit_init_cfg_t init_config = {
|
||||||
.unit_id = adc_btn->unit_id,
|
.unit_id = ADC_UNIT_1,
|
||||||
};
|
};
|
||||||
ret = adc_oneshot_new_unit(&init_config, &g_button.unit[adc_btn->unit_id].adc_handle);
|
ret = adc_oneshot_new_unit(&init_config, &g_button.adc1_handle);
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "adc oneshot new unit fail!");
|
ADC_BTN_CHECK(ret == ESP_OK, "adc oneshot new unit fail!", ESP_FAIL);
|
||||||
g_button.unit[adc_btn->unit_id].is_configured = ADC_INIT_BY_ADC_BUTTON;
|
|
||||||
} else {
|
} else {
|
||||||
g_button.unit[adc_btn->unit_id].adc_handle = *adc_config->adc_handle;
|
g_button.adc1_handle = *config->adc_handle ;
|
||||||
ESP_LOGI(TAG, "ADC1 has been initialized");
|
ESP_LOGI(TAG, "ADC1 has been initialized");
|
||||||
g_button.unit[adc_btn->unit_id].is_configured = ADC_INIT_BY_USER;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
//Configure ADC
|
||||||
|
adc1_config_width(ADC_BUTTON_WIDTH);
|
||||||
|
//Characterize ADC
|
||||||
|
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_BUTTON_ADC_UNIT, ADC_BUTTON_ATTEN, ADC_BUTTON_WIDTH, DEFAULT_VREF, &g_button.adc_chars);
|
||||||
|
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
|
||||||
|
ESP_LOGI(TAG, "Characterized using Two Point Value");
|
||||||
|
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
|
||||||
|
ESP_LOGI(TAG, "Characterized using eFuse Vref");
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "Characterized using Default Vref");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
g_button.is_configured = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** initialize adc channel */
|
/** initialize adc channel */
|
||||||
if (0 == g_button.unit[adc_btn->unit_id].ch[ch_index].is_init) {
|
if (0 == g_button.ch[ch_index].is_init) {
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
//ADC1 Config
|
//ADC1 Config
|
||||||
adc_oneshot_chan_cfg_t oneshot_config = {
|
adc_oneshot_chan_cfg_t oneshot_config = {
|
||||||
.bitwidth = ADC_BUTTON_WIDTH,
|
.bitwidth = ADC_BUTTON_WIDTH,
|
||||||
.atten = ADC_BUTTON_ATTEN,
|
.atten = ADC_BUTTON_ATTEN,
|
||||||
};
|
};
|
||||||
esp_err_t ret = adc_oneshot_config_channel(g_button.unit[adc_btn->unit_id].adc_handle, adc_config->adc_channel, &oneshot_config);
|
esp_err_t ret = adc_oneshot_config_channel(g_button.adc1_handle, config->adc_channel, &oneshot_config);
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "adc oneshot config channel fail!");
|
ADC_BTN_CHECK(ret == ESP_OK, "adc oneshot config channel fail!", ESP_FAIL);
|
||||||
//-------------ADC1 Calibration Init---------------//
|
//-------------ADC1 Calibration Init---------------//
|
||||||
adc_calibration_init(adc_btn->unit_id, ADC_BUTTON_ATTEN, &g_button.unit[adc_btn->unit_id].adc_cali_handle);
|
ret = adc_calibration_init(ADC_BUTTON_ADC_UNIT, ADC_BUTTON_ATTEN, &g_button.adc1_cali_handle);
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].channel = adc_config->adc_channel;
|
ADC_BTN_CHECK(ret == ESP_OK, "ADC1 Calibration Init False", 0);
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].is_init = 1;
|
#else
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].last_time = 0;
|
adc1_config_channel_atten(config->adc_channel, ADC_BUTTON_ATTEN);
|
||||||
|
#endif
|
||||||
|
g_button.ch[ch_index].channel = config->adc_channel;
|
||||||
|
g_button.ch[ch_index].is_init = 1;
|
||||||
|
g_button.ch[ch_index].last_time = 0;
|
||||||
}
|
}
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].btns[adc_config->button_index].max = adc_config->max;
|
g_button.ch[ch_index].btns[config->button_index].max = config->max;
|
||||||
g_button.unit[adc_btn->unit_id].ch[ch_index].btns[adc_config->button_index].min = adc_config->min;
|
g_button.ch[ch_index].btns[config->button_index].min = config->min;
|
||||||
g_button.unit[adc_btn->unit_id].ch_num++;
|
g_button.ch_num++;
|
||||||
|
|
||||||
adc_btn->ch = adc_config->adc_channel;
|
|
||||||
adc_btn->index = adc_config->button_index;
|
|
||||||
adc_btn->base.get_key_level = button_adc_get_key_level;
|
|
||||||
adc_btn->base.del = button_adc_del;
|
|
||||||
ret = iot_button_create(button_config, &adc_btn->base, ret_button);
|
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "Create button failed");
|
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
err:
|
}
|
||||||
if (adc_btn) {
|
|
||||||
free(adc_btn);
|
esp_err_t button_adc_deinit(uint8_t channel, int button_index)
|
||||||
}
|
{
|
||||||
return ret;
|
ADC_BTN_CHECK(channel < ADC1_BUTTON_CHANNEL_MAX, "channel out of range", ESP_ERR_INVALID_ARG);
|
||||||
|
ADC_BTN_CHECK(button_index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
int ch_index = find_channel(channel);
|
||||||
|
ADC_BTN_CHECK(ch_index >= 0, "can't find the channel", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
g_button.ch[ch_index].btns[button_index].max = 0;
|
||||||
|
g_button.ch[ch_index].btns[button_index].min = 0;
|
||||||
|
|
||||||
|
/** check button usage on the channel*/
|
||||||
|
uint8_t unused_button = 0;
|
||||||
|
for (size_t i = 0; i < ADC_BUTTON_MAX_BUTTON; i++) {
|
||||||
|
if (0 == g_button.ch[ch_index].btns[i].max) {
|
||||||
|
unused_button++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unused_button == ADC_BUTTON_MAX_BUTTON && g_button.ch[ch_index].is_init) { /**< if all button is unused, deinit the channel */
|
||||||
|
g_button.ch[ch_index].is_init = 0;
|
||||||
|
g_button.ch[ch_index].channel = ADC1_BUTTON_CHANNEL_MAX;
|
||||||
|
ESP_LOGD(TAG, "all button is unused on channel%d, deinit the channel", g_button.ch[ch_index].channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** check channel usage on the adc*/
|
||||||
|
uint8_t unused_ch = 0;
|
||||||
|
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
||||||
|
if (0 == g_button.ch[i].is_init) {
|
||||||
|
unused_ch++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unused_ch == ADC_BUTTON_MAX_CHANNEL && g_button.is_configured) { /**< if all channel is unused, deinit the adc */
|
||||||
|
g_button.is_configured = false;
|
||||||
|
memset(&g_button, 0, sizeof(adc_button_t));
|
||||||
|
ESP_LOGD(TAG, "all channel is unused, , deinit adc");
|
||||||
|
}
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
esp_err_t ret = adc_oneshot_del_unit(g_button.adc1_handle);
|
||||||
|
ADC_BTN_CHECK(ret == ESP_OK, "adc oneshot deinit fail", ESP_FAIL);
|
||||||
|
#endif
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_adc_volatge(uint8_t channel)
|
||||||
|
{
|
||||||
|
uint32_t adc_reading = 0;
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
int adc_raw = 0;
|
||||||
|
for (int i = 0; i < NO_OF_SAMPLES; i++) {
|
||||||
|
adc_oneshot_read(g_button.adc1_handle, channel, &adc_raw);
|
||||||
|
adc_reading += adc_raw;
|
||||||
|
}
|
||||||
|
adc_reading /= NO_OF_SAMPLES;
|
||||||
|
//Convert adc_reading to voltage in mV
|
||||||
|
int voltage = 0;
|
||||||
|
adc_cali_raw_to_voltage(g_button.adc1_cali_handle, adc_reading, &voltage);
|
||||||
|
ESP_LOGV(TAG, "Raw: %"PRIu32"\tVoltage: %dmV", adc_reading, voltage);
|
||||||
|
#else
|
||||||
|
//Multisampling
|
||||||
|
for (int i = 0; i < NO_OF_SAMPLES; i++) {
|
||||||
|
adc_reading += adc1_get_raw(channel);
|
||||||
|
}
|
||||||
|
adc_reading /= NO_OF_SAMPLES;
|
||||||
|
//Convert adc_reading to voltage in mV
|
||||||
|
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, &g_button.adc_chars);
|
||||||
|
ESP_LOGV(TAG, "Raw: %"PRIu32"\tVoltage: %"PRIu32"mV", adc_reading, voltage);
|
||||||
|
#endif
|
||||||
|
return voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t button_adc_get_key_level(void *button_index)
|
||||||
|
{
|
||||||
|
static uint16_t vol = 0;
|
||||||
|
uint32_t ch = ADC_BUTTON_SPLIT_CHANNEL(button_index);
|
||||||
|
uint32_t index = ADC_BUTTON_SPLIT_INDEX(button_index);
|
||||||
|
ADC_BTN_CHECK(ch < ADC1_BUTTON_CHANNEL_MAX, "channel out of range", 0);
|
||||||
|
ADC_BTN_CHECK(index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", 0);
|
||||||
|
int ch_index = find_channel(ch);
|
||||||
|
ADC_BTN_CHECK(ch_index >= 0, "The button_index is not init", 0);
|
||||||
|
|
||||||
|
/** It starts only when the elapsed time is more than 1ms */
|
||||||
|
if ((esp_timer_get_time() - g_button.ch[ch_index].last_time) > 1000) {
|
||||||
|
vol = get_adc_volatge(ch);
|
||||||
|
g_button.ch[ch_index].last_time = esp_timer_get_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vol <= g_button.ch[ch_index].btns[index].max &&
|
||||||
|
vol >= g_button.ch[ch_index].btns[index].min) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,96 +4,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "button_gpio.h"
|
#include "button_gpio.h"
|
||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
#include "button_interface.h"
|
|
||||||
#include "iot_button.h"
|
|
||||||
|
|
||||||
static const char *TAG = "gpio_button";
|
static const char *TAG = "gpio button";
|
||||||
|
|
||||||
typedef struct {
|
#define GPIO_BTN_CHECK(a, str, ret_val) \
|
||||||
button_driver_t base; /**< button driver */
|
if (!(a)) \
|
||||||
int32_t gpio_num; /**< num of gpio */
|
{ \
|
||||||
uint8_t active_level; /**< gpio level when press down */
|
ESP_LOGE(TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||||
bool enable_power_save; /**< enable power save */
|
return (ret_val); \
|
||||||
} button_gpio_obj;
|
|
||||||
|
|
||||||
static esp_err_t button_gpio_del(button_driver_t *button_driver)
|
|
||||||
{
|
|
||||||
button_gpio_obj *gpio_btn = __containerof(button_driver, button_gpio_obj, base);
|
|
||||||
esp_err_t ret = gpio_reset_pin(gpio_btn->gpio_num);
|
|
||||||
free(gpio_btn);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t button_gpio_get_key_level(button_driver_t *button_driver)
|
|
||||||
{
|
|
||||||
button_gpio_obj *gpio_btn = __containerof(button_driver, button_gpio_obj, base);
|
|
||||||
int level = gpio_get_level(gpio_btn->gpio_num);
|
|
||||||
return level == gpio_btn->active_level ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t button_gpio_enable_gpio_wakeup(uint32_t gpio_num, uint8_t active_level, bool enable)
|
|
||||||
{
|
|
||||||
esp_err_t ret;
|
|
||||||
if (enable) {
|
|
||||||
gpio_intr_enable(gpio_num);
|
|
||||||
ret = gpio_wakeup_enable(gpio_num, active_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
|
||||||
} else {
|
|
||||||
gpio_intr_disable(gpio_num);
|
|
||||||
ret = gpio_wakeup_disable(gpio_num);
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t button_gpio_set_intr(int gpio_num, gpio_int_type_t intr_type, gpio_isr_t isr_handler)
|
esp_err_t button_gpio_init(const button_gpio_config_t *config)
|
||||||
{
|
{
|
||||||
static bool isr_service_installed = false;
|
GPIO_BTN_CHECK(NULL != config, "Pointer of config is invalid", ESP_ERR_INVALID_ARG);
|
||||||
gpio_set_intr_type(gpio_num, intr_type);
|
GPIO_BTN_CHECK(GPIO_IS_VALID_GPIO(config->gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||||
if (!isr_service_installed) {
|
|
||||||
gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
|
|
||||||
isr_service_installed = true;
|
|
||||||
}
|
|
||||||
gpio_isr_handler_add(gpio_num, isr_handler, (void *)gpio_num);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void button_power_save_isr_handler(void* arg)
|
gpio_config_t gpio_conf;
|
||||||
{
|
|
||||||
/*!< resume the button */
|
|
||||||
iot_button_resume();
|
|
||||||
/*!< disable gpio wakeup not need active level*/
|
|
||||||
button_gpio_enable_gpio_wakeup((uint32_t)arg, 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t button_enter_power_save(button_driver_t *button_driver)
|
|
||||||
{
|
|
||||||
button_gpio_obj *gpio_btn = __containerof(button_driver, button_gpio_obj, base);
|
|
||||||
return button_gpio_enable_gpio_wakeup(gpio_btn->gpio_num, gpio_btn->active_level, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t iot_button_new_gpio_device(const button_config_t *button_config, const button_gpio_config_t *gpio_cfg, button_handle_t *ret_button)
|
|
||||||
{
|
|
||||||
button_gpio_obj *gpio_btn = NULL;
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_GOTO_ON_FALSE(button_config && gpio_cfg && ret_button, ESP_ERR_INVALID_ARG, err, TAG, "Invalid argument");
|
|
||||||
ESP_GOTO_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_cfg->gpio_num), ESP_ERR_INVALID_ARG, err, TAG, "GPIO number error");
|
|
||||||
|
|
||||||
gpio_btn = (button_gpio_obj *)calloc(1, sizeof(button_gpio_obj));
|
|
||||||
ESP_GOTO_ON_FALSE(gpio_btn, ESP_ERR_NO_MEM, err, TAG, "No memory for gpio button");
|
|
||||||
gpio_btn->gpio_num = gpio_cfg->gpio_num;
|
|
||||||
gpio_btn->active_level = gpio_cfg->active_level;
|
|
||||||
gpio_btn->enable_power_save = gpio_cfg->enable_power_save;
|
|
||||||
|
|
||||||
gpio_config_t gpio_conf = {0};
|
|
||||||
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
||||||
gpio_conf.mode = GPIO_MODE_INPUT;
|
gpio_conf.mode = GPIO_MODE_INPUT;
|
||||||
gpio_conf.pin_bit_mask = (1ULL << gpio_cfg->gpio_num);
|
gpio_conf.pin_bit_mask = (1ULL << config->gpio_num);
|
||||||
if (!gpio_cfg->disable_pull) {
|
if (config->disable_pull) {
|
||||||
if (gpio_cfg->active_level) {
|
gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||||
|
gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||||
|
} else {
|
||||||
|
if (config->active_level) {
|
||||||
gpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
gpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||||
gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -103,47 +40,75 @@ esp_err_t iot_button_new_gpio_device(const button_config_t *button_config, const
|
||||||
}
|
}
|
||||||
gpio_config(&gpio_conf);
|
gpio_config(&gpio_conf);
|
||||||
|
|
||||||
if (gpio_cfg->enable_power_save) {
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
|
if (config->enable_power_save) {
|
||||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
if (!esp_sleep_is_valid_wakeup_gpio(gpio_cfg->gpio_num)) {
|
if (!esp_sleep_is_valid_wakeup_gpio(config->gpio_num)) {
|
||||||
ESP_LOGE(TAG, "GPIO %ld is not a valid wakeup source under CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE", gpio_cfg->gpio_num);
|
ESP_LOGE(TAG, "GPIO %ld is not a valid wakeup source under CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE", config->gpio_num);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
gpio_hold_en(gpio_cfg->gpio_num);
|
gpio_hold_en(config->gpio_num);
|
||||||
#endif
|
#endif
|
||||||
/* Enable wake up from GPIO */
|
/* Enable wake up from GPIO */
|
||||||
esp_err_t ret = gpio_wakeup_enable(gpio_cfg->gpio_num, gpio_cfg->active_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
esp_err_t ret = gpio_wakeup_enable(config->gpio_num, config->active_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_ERR_INVALID_STATE, err, TAG, "Enable gpio wakeup failed");
|
GPIO_BTN_CHECK(ret == ESP_OK, "Enable gpio wakeup failed", ESP_FAIL);
|
||||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
||||||
ret = esp_sleep_enable_ext1_wakeup_io((1ULL << gpio_cfg->gpio_num), gpio_cfg->active_level == 0 ? ESP_EXT1_WAKEUP_ANY_LOW : ESP_EXT1_WAKEUP_ANY_HIGH);
|
ret = esp_sleep_enable_ext1_wakeup_io((1ULL << config->gpio_num), config->active_level == 0 ? ESP_EXT1_WAKEUP_ANY_LOW : ESP_EXT1_WAKEUP_ANY_HIGH);
|
||||||
#else
|
#else
|
||||||
/*!< Not support etc: esp32c2, esp32c3. Target must support ext1 wakeup */
|
/*!< Not support etc: esp32c2, esp32c3. Target must support ext1 wakeup */
|
||||||
ret = ESP_FAIL;
|
ret = ESP_FAIL;
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "Target must support ext1 wakeup");
|
GPIO_BTN_CHECK(ret == ESP_OK, "Target must support ext1 wakeup", ESP_FAIL);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
ret = esp_sleep_enable_gpio_wakeup();
|
ret = esp_sleep_enable_gpio_wakeup();
|
||||||
#endif
|
#endif
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "Configure gpio as wakeup source failed");
|
GPIO_BTN_CHECK(ret == ESP_OK, "Configure gpio as wakeup source failed", ESP_FAIL);
|
||||||
|
|
||||||
ret = button_gpio_set_intr(gpio_btn->gpio_num, gpio_cfg->active_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL, button_power_save_isr_handler);
|
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "Set gpio interrupt failed");
|
|
||||||
|
|
||||||
gpio_btn->base.enable_power_save = true;
|
|
||||||
gpio_btn->base.enter_power_save = button_enter_power_save;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
gpio_btn->base.get_key_level = button_gpio_get_key_level;
|
|
||||||
gpio_btn->base.del = button_gpio_del;
|
|
||||||
|
|
||||||
ret = iot_button_create(button_config, &gpio_btn->base, ret_button);
|
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "Create button failed");
|
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
err:
|
}
|
||||||
if (gpio_btn) {
|
|
||||||
free(gpio_btn);
|
esp_err_t button_gpio_deinit(int gpio_num)
|
||||||
|
{
|
||||||
|
return gpio_reset_pin(gpio_num);;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t button_gpio_get_key_level(void *gpio_num)
|
||||||
|
{
|
||||||
|
return (uint8_t)gpio_get_level((uint32_t)gpio_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t button_gpio_set_intr(int gpio_num, gpio_int_type_t intr_type, gpio_isr_t isr_handler, void *args)
|
||||||
|
{
|
||||||
|
static bool isr_service_installed = false;
|
||||||
|
gpio_set_intr_type(gpio_num, intr_type);
|
||||||
|
if (!isr_service_installed) {
|
||||||
|
gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
|
||||||
|
isr_service_installed = true;
|
||||||
|
}
|
||||||
|
gpio_isr_handler_add(gpio_num, isr_handler, args);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t button_gpio_intr_control(int gpio_num, bool enable)
|
||||||
|
{
|
||||||
|
if (enable) {
|
||||||
|
gpio_intr_enable(gpio_num);
|
||||||
|
} else {
|
||||||
|
gpio_intr_disable(gpio_num);
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t button_gpio_enable_gpio_wakeup(uint32_t gpio_num, uint8_t active_level, bool enable)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
if (enable) {
|
||||||
|
ret = gpio_wakeup_enable(gpio_num, active_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
||||||
|
} else {
|
||||||
|
ret = gpio_wakeup_disable(gpio_num);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,88 +1,59 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_check.h"
|
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "button_matrix.h"
|
#include "button_matrix.h"
|
||||||
#include "button_interface.h"
|
|
||||||
|
|
||||||
static const char *TAG = "matrix_button";
|
static const char *TAG = "matrix button";
|
||||||
|
|
||||||
typedef struct {
|
#define MATRIX_BTN_CHECK(a, str, ret_val) \
|
||||||
button_driver_t base; /**< base button driver */
|
if (!(a)) \
|
||||||
int32_t row_gpio_num; /**< row gpio */
|
{ \
|
||||||
int32_t col_gpio_num; /**< col gpio */
|
ESP_LOGE(TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||||
} button_matrix_obj;
|
return (ret_val); \
|
||||||
|
}
|
||||||
|
|
||||||
static esp_err_t button_matrix_gpio_init(int32_t gpio_num, gpio_mode_t mode)
|
esp_err_t button_matrix_init(const button_matrix_config_t *config)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio_num error");
|
MATRIX_BTN_CHECK(NULL != config, "Pointer of config is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
MATRIX_BTN_CHECK(GPIO_IS_VALID_GPIO(config->row_gpio_num), "row GPIO number error", ESP_ERR_INVALID_ARG);
|
||||||
|
MATRIX_BTN_CHECK(GPIO_IS_VALID_GPIO(config->col_gpio_num), "col GPIO number error", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
// set row gpio as output
|
||||||
gpio_config_t gpio_conf = {0};
|
gpio_config_t gpio_conf = {0};
|
||||||
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
||||||
|
gpio_conf.mode = GPIO_MODE_OUTPUT;
|
||||||
gpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
gpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||||
gpio_conf.pin_bit_mask = (1ULL << gpio_num);
|
gpio_conf.pin_bit_mask = (1ULL << config->row_gpio_num);
|
||||||
gpio_conf.mode = mode;
|
|
||||||
gpio_config(&gpio_conf);
|
gpio_config(&gpio_conf);
|
||||||
|
|
||||||
|
// set col gpio as input
|
||||||
|
gpio_conf.mode = GPIO_MODE_INPUT;
|
||||||
|
gpio_conf.pin_bit_mask = (1ULL << config->col_gpio_num);
|
||||||
|
gpio_config(&gpio_conf);
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t button_matrix_del(button_driver_t *button_driver)
|
esp_err_t button_matrix_deinit(int row_gpio_num, int col_gpio_num)
|
||||||
{
|
{
|
||||||
button_matrix_obj *matrix_btn = __containerof(button_driver, button_matrix_obj, base);
|
|
||||||
//Reset an gpio to default state (select gpio function, enable pullup and disable input and output).
|
//Reset an gpio to default state (select gpio function, enable pullup and disable input and output).
|
||||||
gpio_reset_pin(matrix_btn->row_gpio_num);
|
gpio_reset_pin(row_gpio_num);
|
||||||
gpio_reset_pin(matrix_btn->col_gpio_num);
|
gpio_reset_pin(col_gpio_num);
|
||||||
free(matrix_btn);
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t button_matrix_get_key_level(button_driver_t *button_driver)
|
uint8_t button_matrix_get_key_level(void *hardware_data)
|
||||||
{
|
{
|
||||||
button_matrix_obj *matrix_btn = __containerof(button_driver, button_matrix_obj, base);
|
uint32_t row = MATRIX_BUTTON_SPLIT_ROW(hardware_data);
|
||||||
gpio_set_level(matrix_btn->row_gpio_num, 1);
|
uint32_t col = MATRIX_BUTTON_SPLIT_COL(hardware_data);
|
||||||
uint8_t level = gpio_get_level(matrix_btn->col_gpio_num);
|
gpio_set_level(row, 1);
|
||||||
gpio_set_level(matrix_btn->row_gpio_num, 0);
|
uint8_t level = gpio_get_level(col);
|
||||||
|
gpio_set_level(row, 0);
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t iot_button_new_matrix_device(const button_config_t *button_config, const button_matrix_config_t *matrix_config, button_handle_t *ret_button, size_t *size)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_RETURN_ON_FALSE(button_config && matrix_config && ret_button, ESP_ERR_INVALID_ARG, TAG, "Invalid argument");
|
|
||||||
ESP_RETURN_ON_FALSE(matrix_config->col_gpios && matrix_config->row_gpios, ESP_ERR_INVALID_ARG, TAG, "Invalid matrix config");
|
|
||||||
ESP_RETURN_ON_FALSE(matrix_config->col_gpio_num > 0 && matrix_config->row_gpio_num > 0, ESP_ERR_INVALID_ARG, TAG, "Invalid matrix config");
|
|
||||||
ESP_RETURN_ON_FALSE(*size == matrix_config->row_gpio_num * matrix_config->col_gpio_num, ESP_ERR_INVALID_ARG, TAG, "Invalid size");
|
|
||||||
|
|
||||||
button_matrix_obj *matrix_btn = calloc(*size, sizeof(button_matrix_obj));
|
|
||||||
for (int i = 0; i < matrix_config->row_gpio_num; i++) {
|
|
||||||
button_matrix_gpio_init(matrix_config->row_gpios[i], GPIO_MODE_OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < matrix_config->col_gpio_num; i++) {
|
|
||||||
button_matrix_gpio_init(matrix_config->col_gpios[i], GPIO_MODE_INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < *size; i++) {
|
|
||||||
matrix_btn[i].base.get_key_level = button_matrix_get_key_level;
|
|
||||||
matrix_btn[i].base.del = button_matrix_del;
|
|
||||||
matrix_btn[i].row_gpio_num = matrix_config->row_gpios[i / matrix_config->col_gpio_num];
|
|
||||||
matrix_btn[i].col_gpio_num = matrix_config->col_gpios[i % matrix_config->col_gpio_num];
|
|
||||||
ESP_LOGD(TAG, "row_gpio_num: %"PRId32", col_gpio_num: %"PRId32"", matrix_btn[i].row_gpio_num, matrix_btn[i].col_gpio_num);
|
|
||||||
ret = iot_button_create(button_config, &matrix_btn[i].base, &ret_button[i]);
|
|
||||||
ESP_GOTO_ON_FALSE(ret == ESP_OK, ESP_FAIL, err, TAG, "Create button failed");
|
|
||||||
}
|
|
||||||
*size = matrix_config->row_gpio_num * matrix_config->col_gpio_num;
|
|
||||||
return ESP_OK;
|
|
||||||
|
|
||||||
err:
|
|
||||||
if (matrix_btn) {
|
|
||||||
free(matrix_btn);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
# The following five lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(button_power_save)
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
## Button Power Save Example
|
||||||
|
|
||||||
|
This example demonstrates how to utilize the `button` component in conjunction with the light sleep low-power mode.
|
||||||
|
|
||||||
|
* `button` [Component Introduction](https://docs.espressif.com/projects/esp-iot-solution/en/latest/input_device/button.html)
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
* Any GPIO on any development board can be used in this example.
|
||||||
|
|
||||||
|
## Build and Flash
|
||||||
|
|
||||||
|
Build the project and flash it to the board, then run the monitor tool to view the serial output:
|
||||||
|
|
||||||
|
* Run `. ./export.sh` to set IDF environment
|
||||||
|
* Run `idf.py set-target esp32xx` to set target chip
|
||||||
|
* Run `idf.py -p PORT flash monitor` to build, flash and monitor the project
|
||||||
|
|
||||||
|
(To exit the serial monitor, type `Ctrl-]`.)
|
||||||
|
|
||||||
|
See the Getting Started Guide for all the steps to configure and use the ESP-IDF to build projects.
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
```
|
||||||
|
I (1139) pm: Frequency switching config: CPU_MAX: 160, APB_MAX: 80, APB_MIN: 80, Light sleep: ENABLED
|
||||||
|
I (1149) sleep: Code start at 42000020, total 119.03 KiB, data start at 3c000000, total 49152.00 KiB
|
||||||
|
I (1159) button: IoT Button Version: 3.2.0
|
||||||
|
I (1163) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||||
|
I (2922) button_power_save: Button event BUTTON_PRESS_DOWN
|
||||||
|
I (3017) button_power_save: Button event BUTTON_PRESS_UP
|
||||||
|
I (3017) button_power_save: Wake up from light sleep, reason 4
|
||||||
|
I (3200) button_power_save: Button event BUTTON_SINGLE_CLICK
|
||||||
|
I (3200) button_power_save: Wake up from light sleep, reason 4
|
||||||
|
I (3202) button_power_save: Button event BUTTON_PRESS_REPEAT_DONE
|
||||||
|
I (3208) button_power_save: Wake up from light sleep, reason 4
|
||||||
|
I (3627) button_power_save: Button event BUTTON_PRESS_DOWN
|
||||||
|
I (3702) button_power_save: Button event BUTTON_PRESS_UP
|
||||||
|
I (3702) button_power_save: Wake up from light sleep, reason 4
|
||||||
|
I (3887) button_power_save: Button event BUTTON_SINGLE_CLICK
|
||||||
|
I (3887) button_power_save: Wake up from light sleep, reason 4
|
||||||
|
I (3889) button_power_save: Button event BUTTON_PRESS_REPEAT_DONE
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
idf_component_register(SRCS "main.c"
|
||||||
|
INCLUDE_DIRS ".")
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
menu "Example Configuration"
|
||||||
|
|
||||||
|
choice ENTER_LIGHT_SLEEP_MODE
|
||||||
|
prompt "Enter light sleep mode"
|
||||||
|
default ENTER_LIGHT_SLEEP_AUTO
|
||||||
|
depends on PM_ENABLE
|
||||||
|
help
|
||||||
|
Enable light sleep mode to save power.
|
||||||
|
|
||||||
|
config ENTER_LIGHT_SLEEP_AUTO
|
||||||
|
bool "Auto enter Light Sleep"
|
||||||
|
config ENTER_LIGHT_SLEEP_MODE_MANUALLY
|
||||||
|
bool "Manually enter Light Sleep"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice EXAMPLE_MAX_CPU_FREQ
|
||||||
|
prompt "Maximum CPU frequency"
|
||||||
|
default EXAMPLE_MAX_CPU_FREQ_80 if !IDF_TARGET_ESP32H2
|
||||||
|
default EXAMPLE_MAX_CPU_FREQ_96 if IDF_TARGET_ESP32H2
|
||||||
|
depends on PM_ENABLE
|
||||||
|
help
|
||||||
|
Maximum CPU frequency to use for dynamic frequency scaling.
|
||||||
|
|
||||||
|
config EXAMPLE_MAX_CPU_FREQ_80
|
||||||
|
bool "80 MHz"
|
||||||
|
config EXAMPLE_MAX_CPU_FREQ_96
|
||||||
|
bool "96 MHz"
|
||||||
|
depends on IDF_TARGET_ESP32H2
|
||||||
|
config EXAMPLE_MAX_CPU_FREQ_120
|
||||||
|
bool "120 MHz"
|
||||||
|
depends on IDF_TARGET_ESP32C2
|
||||||
|
config EXAMPLE_MAX_CPU_FREQ_160
|
||||||
|
bool "160 MHz"
|
||||||
|
depends on !IDF_TARGET_ESP32C2
|
||||||
|
config EXAMPLE_MAX_CPU_FREQ_240
|
||||||
|
bool "240 MHz"
|
||||||
|
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config EXAMPLE_MAX_CPU_FREQ_MHZ
|
||||||
|
int
|
||||||
|
default 80 if EXAMPLE_MAX_CPU_FREQ_80
|
||||||
|
default 96 if EXAMPLE_MAX_CPU_FREQ_96
|
||||||
|
default 120 if EXAMPLE_MAX_CPU_FREQ_120
|
||||||
|
default 160 if EXAMPLE_MAX_CPU_FREQ_160
|
||||||
|
default 240 if EXAMPLE_MAX_CPU_FREQ_240
|
||||||
|
|
||||||
|
choice EXAMPLE_MIN_CPU_FREQ
|
||||||
|
prompt "Minimum CPU frequency"
|
||||||
|
default EXAMPLE_MIN_CPU_FREQ_10M if !IDF_TARGET_ESP32H2
|
||||||
|
default EXAMPLE_MIN_CPU_FREQ_32M if IDF_TARGET_ESP32H2
|
||||||
|
depends on PM_ENABLE
|
||||||
|
help
|
||||||
|
Minimum CPU frequency to use for dynamic frequency scaling.
|
||||||
|
Should be set to XTAL frequency or XTAL frequency divided by integer.
|
||||||
|
|
||||||
|
config EXAMPLE_MIN_CPU_FREQ_40M
|
||||||
|
bool "40 MHz (use with 40MHz XTAL)"
|
||||||
|
depends on XTAL_FREQ_40 || XTAL_FREQ_AUTO || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO || !IDF_TARGET_ESP32
|
||||||
|
config EXAMPLE_MIN_CPU_FREQ_20M
|
||||||
|
bool "20 MHz (use with 40MHz XTAL)"
|
||||||
|
depends on XTAL_FREQ_40 || XTAL_FREQ_AUTO || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO || !IDF_TARGET_ESP32
|
||||||
|
config EXAMPLE_MIN_CPU_FREQ_10M
|
||||||
|
bool "10 MHz (use with 40MHz XTAL)"
|
||||||
|
depends on XTAL_FREQ_40 || XTAL_FREQ_AUTO || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO || !IDF_TARGET_ESP32
|
||||||
|
config EXAMPLE_MIN_CPU_FREQ_26M
|
||||||
|
bool "26 MHz (use with 26MHz XTAL)"
|
||||||
|
depends on XTAL_FREQ_26 || XTAL_FREQ_AUTO || ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO
|
||||||
|
config EXAMPLE_MIN_CPU_FREQ_13M
|
||||||
|
bool "13 MHz (use with 26MHz XTAL)"
|
||||||
|
depends on XTAL_FREQ_26 || XTAL_FREQ_AUTO || ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO
|
||||||
|
config EXAMPLE_MIN_CPU_FREQ_32M
|
||||||
|
bool "32 MHz (use with 32MHz XTAL)"
|
||||||
|
depends on IDF_TARGET_ESP32H2
|
||||||
|
depends on XTAL_FREQ_32 || XTAL_FREQ_AUTO
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config EXAMPLE_MIN_CPU_FREQ_MHZ
|
||||||
|
int
|
||||||
|
default 40 if EXAMPLE_MIN_CPU_FREQ_40M
|
||||||
|
default 20 if EXAMPLE_MIN_CPU_FREQ_20M
|
||||||
|
default 10 if EXAMPLE_MIN_CPU_FREQ_10M
|
||||||
|
default 26 if EXAMPLE_MIN_CPU_FREQ_26M
|
||||||
|
default 13 if EXAMPLE_MIN_CPU_FREQ_13M
|
||||||
|
default 32 if EXAMPLE_MIN_CPU_FREQ_32M
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
version: "0.1.0"
|
||||||
|
dependencies:
|
||||||
|
idf: ">=4.4"
|
||||||
|
button:
|
||||||
|
version: "*"
|
||||||
|
override_path: "../../../../components/button"
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_pm.h"
|
||||||
|
#include "iot_button.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "esp_idf_version.h"
|
||||||
|
|
||||||
|
/* Most development boards have "boot" button attached to GPIO0.
|
||||||
|
* You can also change this to another pin.
|
||||||
|
*/
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
#define BOOT_BUTTON_NUM 9
|
||||||
|
#else
|
||||||
|
#define BOOT_BUTTON_NUM 0
|
||||||
|
#endif
|
||||||
|
#define BUTTON_ACTIVE_LEVEL 0
|
||||||
|
|
||||||
|
static const char *TAG = "button_power_save";
|
||||||
|
|
||||||
|
static void button_event_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
iot_button_print_event((button_handle_t)arg);
|
||||||
|
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||||
|
if (cause != ESP_SLEEP_WAKEUP_UNDEFINED) {
|
||||||
|
ESP_LOGI(TAG, "Wake up from light sleep, reason %d", cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ENTER_LIGHT_SLEEP_MODE_MANUALLY
|
||||||
|
void button_enter_power_save(void *usr_data)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Can enter power save now");
|
||||||
|
esp_light_sleep_start();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void button_init(uint32_t button_num)
|
||||||
|
{
|
||||||
|
button_config_t btn_cfg = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
|
.gpio_button_config = {
|
||||||
|
.gpio_num = button_num,
|
||||||
|
.active_level = BUTTON_ACTIVE_LEVEL,
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
|
.enable_power_save = true,
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
};
|
||||||
|
button_handle_t btn = iot_button_create(&btn_cfg);
|
||||||
|
assert(btn);
|
||||||
|
esp_err_t err = iot_button_register_cb(btn, BUTTON_PRESS_DOWN, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_PRESS_UP, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_PRESS_REPEAT, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_PRESS_REPEAT_DONE, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_SINGLE_CLICK, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_DOUBLE_CLICK, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_LONG_PRESS_START, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_LONG_PRESS_HOLD, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, button_event_cb, NULL);
|
||||||
|
err |= iot_button_register_cb(btn, BUTTON_PRESS_END, button_event_cb, NULL);
|
||||||
|
|
||||||
|
#if CONFIG_ENTER_LIGHT_SLEEP_MODE_MANUALLY
|
||||||
|
/*!< For enter Power Save */
|
||||||
|
button_power_save_config_t config = {
|
||||||
|
.enter_power_save_cb = button_enter_power_save,
|
||||||
|
};
|
||||||
|
err |= iot_button_register_power_save_cb(&config);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
|
||||||
|
void power_save_init(void)
|
||||||
|
{
|
||||||
|
esp_pm_config_t pm_config = {
|
||||||
|
.max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ,
|
||||||
|
.min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ,
|
||||||
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||||
|
.light_sleep_enable = true
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void power_save_init(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
esp_pm_config_esp32_t pm_config = {
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
esp_pm_config_esp32s2_t pm_config = {
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
esp_pm_config_esp32c3_t pm_config = {
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
esp_pm_config_esp32s3_t pm_config = {
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||||
|
esp_pm_config_esp32c2_t pm_config = {
|
||||||
|
#endif
|
||||||
|
.max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ,
|
||||||
|
.min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ,
|
||||||
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||||
|
.light_sleep_enable = true
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
button_init(BOOT_BUTTON_NUM);
|
||||||
|
#if CONFIG_ENTER_LIGHT_SLEEP_AUTO
|
||||||
|
power_save_init();
|
||||||
|
#else
|
||||||
|
esp_light_sleep_start();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_ENTER_LIGHT_SLEEP_MODE_MANUALLY=y\
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Enable support for power management
|
||||||
|
CONFIG_PM_ENABLE=y
|
||||||
|
# Enable tickless idle mode
|
||||||
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
|
# Put related source code in IRAM
|
||||||
|
CONFIG_PM_SLP_IRAM_OPT=y
|
||||||
|
CONFIG_PM_RTOS_IDLE_OPT=y
|
||||||
|
# Use 1000Hz freertos tick to lower sleep time threshold
|
||||||
|
CONFIG_FREERTOS_HZ=1000
|
||||||
|
# For button power save
|
||||||
|
CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE=y
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
cmake_utilities: '*'
|
cmake_utilities: 0.*
|
||||||
idf: '>=4.0'
|
idf: '>=4.0'
|
||||||
description: GPIO and ADC and Matrix button driver
|
description: GPIO and ADC button driver
|
||||||
documentation: https://docs.espressif.com/projects/esp-iot-solution/en/latest/input_device/button.html
|
documentation: https://docs.espressif.com/projects/esp-iot-solution/en/latest/input_device/button.html
|
||||||
issues: https://github.com/espressif/esp-iot-solution/issues
|
issues: https://github.com/espressif/esp-iot-solution/issues
|
||||||
repository: git://github.com/espressif/esp-iot-solution.git
|
repository: git://github.com/espressif/esp-iot-solution.git
|
||||||
repository_info:
|
repository_info:
|
||||||
commit_sha: 91aeb7fb41e8a3e76aeb21371f9f83711c74cf3f
|
commit_sha: ef19f4a5524a0ea147c9eccde0438123b41aeeb1
|
||||||
path: components/button
|
path: components/button
|
||||||
url: https://github.com/espressif/esp-iot-solution/tree/master/components/button
|
url: https://github.com/espressif/esp-iot-solution/tree/master/components/button
|
||||||
version: 4.1.5
|
version: 3.5.0
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,75 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
/* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "esp_idf_version.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
#include "esp_adc/adc_oneshot.h"
|
#include "esp_adc/adc_oneshot.h"
|
||||||
#include "button_types.h"
|
#else
|
||||||
|
#include "driver/adc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ADC_BUTTON_COMBINE(channel, index) ((channel)<<8 | (index))
|
||||||
|
#define ADC_BUTTON_SPLIT_INDEX(data) ((uint32_t)(data)&0xff)
|
||||||
|
#define ADC_BUTTON_SPLIT_CHANNEL(data) (((uint32_t)(data) >> 8) & 0xff)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief adc button configuration
|
* @brief adc button configuration
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
adc_oneshot_unit_handle_t *adc_handle; /**< handle of adc unit, if NULL will create new one internal, else will use the handle */
|
|
||||||
adc_unit_t unit_id; /**< ADC unit */
|
|
||||||
uint8_t adc_channel; /**< Channel of ADC */
|
uint8_t adc_channel; /**< Channel of ADC */
|
||||||
uint8_t button_index; /**< button index on the channel */
|
uint8_t button_index; /**< button index on the channel */
|
||||||
uint16_t min; /**< min voltage in mv corresponding to the button */
|
uint16_t min; /**< min voltage in mv corresponding to the button */
|
||||||
uint16_t max; /**< max voltage in mv corresponding to the button */
|
uint16_t max; /**< max voltage in mv corresponding to the button */
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
adc_oneshot_unit_handle_t *adc_handle; /**< handle of adc unit, if NULL will create new one internal, else will use the handle */
|
||||||
|
#endif
|
||||||
} button_adc_config_t;
|
} button_adc_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new ADC button device
|
* @brief Initialize gpio button
|
||||||
*
|
*
|
||||||
* This function initializes and configures a new ADC button device using the given configuration parameters.
|
* @param config pointer of configuration struct
|
||||||
* It manages the ADC unit, channels, and button-specific parameters, and ensures proper resource allocation
|
|
||||||
* for the ADC button object.
|
|
||||||
*
|
|
||||||
* @param[in] button_config Configuration for the button device, including callbacks and debounce parameters.
|
|
||||||
* @param[in] adc_config Configuration for the ADC channel and button, including the ADC unit, channel,
|
|
||||||
* button index, and voltage range (min and max).
|
|
||||||
* @param[out] ret_button Handle to the newly created button device.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK: Successfully created the ADC button device.
|
* - ESP_OK on success
|
||||||
* - ESP_ERR_INVALID_ARG: Invalid argument provided.
|
* - ESP_ERR_INVALID_ARG Arguments is NULL.
|
||||||
* - ESP_ERR_NO_MEM: Memory allocation failed.
|
* - ESP_ERR_NOT_SUPPORTED Arguments out of range.
|
||||||
* - ESP_ERR_INVALID_STATE: The requested button index or channel is already in use, or no channels are available.
|
* - ESP_ERR_INVALID_STATE State is error.
|
||||||
* - ESP_FAIL: Failed to initialize or configure the ADC or button device.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* - If the ADC unit is not already configured, it will be initialized with the provided or default settings.
|
|
||||||
* - If the ADC channel is not initialized, it will be configured for the specified unit and calibrated.
|
|
||||||
* - This function ensures that ADC resources are reused whenever possible to optimize resource allocation.
|
|
||||||
*/
|
*/
|
||||||
esp_err_t iot_button_new_adc_device(const button_config_t *button_config, const button_adc_config_t *adc_config, button_handle_t *ret_button);
|
esp_err_t button_adc_init(const button_adc_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize gpio button
|
||||||
|
*
|
||||||
|
* @param channel ADC channel
|
||||||
|
* @param button_index Button index on the channel
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
||||||
|
*/
|
||||||
|
esp_err_t button_adc_deinit(uint8_t channel, int button_index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the adc button level
|
||||||
|
*
|
||||||
|
* @param button_index It is compressed by ADC channel and button index, use the macro ADC_BUTTON_COMBINE to generate. It will be treated as a uint32_t variable.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - 0 Not pressed
|
||||||
|
* - 1 Pressed
|
||||||
|
*/
|
||||||
|
uint8_t button_adc_get_key_level(void *button_index);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esp_err.h"
|
#include "driver/gpio.h"
|
||||||
#include "button_types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -19,34 +18,74 @@ extern "C" {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t gpio_num; /**< num of gpio */
|
int32_t gpio_num; /**< num of gpio */
|
||||||
uint8_t active_level; /**< gpio level when press down */
|
uint8_t active_level; /**< gpio level when press down */
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
bool enable_power_save; /**< enable power save mode */
|
bool enable_power_save; /**< enable power save mode */
|
||||||
bool disable_pull; /**< disable internal pull up or down */
|
#endif
|
||||||
|
bool disable_pull; /**< disable internal pull or not */
|
||||||
} button_gpio_config_t;
|
} button_gpio_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new GPIO button device
|
* @brief Initialize gpio button
|
||||||
*
|
*
|
||||||
* This function initializes and configures a GPIO-based button device using the given configuration parameters.
|
* @param config pointer of configuration struct
|
||||||
* It sets up the GPIO pin, configures its input mode, and optionally enables power-saving features or wake-up functionality.
|
|
||||||
*
|
|
||||||
* @param[in] button_config Configuration for the button device, including callbacks and debounce parameters.
|
|
||||||
* @param[in] gpio_cfg Configuration for the GPIO, including the pin number, active level, and power-save options.
|
|
||||||
* @param[out] ret_button Handle to the newly created GPIO button device.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK: Successfully created the GPIO button device.
|
* - ESP_OK on success
|
||||||
* - ESP_ERR_INVALID_ARG: Invalid argument provided, such as an invalid GPIO number.
|
* - ESP_ERR_INVALID_ARG Arguments is NULL.
|
||||||
* - ESP_ERR_NO_MEM: Memory allocation failed.
|
|
||||||
* - ESP_ERR_INVALID_STATE: Failed to configure GPIO wake-up or interrupt settings.
|
|
||||||
* - ESP_FAIL: General failure, such as unsupported wake-up configuration on the target.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* - If power-saving is enabled, the GPIO will be configured as a wake-up source for light sleep.
|
|
||||||
* - Pull-up or pull-down resistors are configured based on the `active_level` and the `disable_pull` flag.
|
|
||||||
* - This function checks for the validity of the GPIO as a wake-up source when power-saving is enabled.
|
|
||||||
* - If power-saving is not supported by the hardware or configuration, the function will return an error.
|
|
||||||
*/
|
*/
|
||||||
esp_err_t iot_button_new_gpio_device(const button_config_t *button_config, const button_gpio_config_t *gpio_config, button_handle_t *ret_button);
|
esp_err_t button_gpio_init(const button_gpio_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize gpio button
|
||||||
|
*
|
||||||
|
* @param gpio_num gpio number of button
|
||||||
|
*
|
||||||
|
* @return Always return ESP_OK
|
||||||
|
*/
|
||||||
|
esp_err_t button_gpio_deinit(int gpio_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get current level on button gpio
|
||||||
|
*
|
||||||
|
* @param gpio_num gpio number of button, it will be treated as a uint32_t variable.
|
||||||
|
*
|
||||||
|
* @return Level on gpio
|
||||||
|
*/
|
||||||
|
uint8_t button_gpio_get_key_level(void *gpio_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets up interrupt for GPIO button.
|
||||||
|
*
|
||||||
|
* @param gpio_num gpio number of button
|
||||||
|
* @param intr_type The type of GPIO interrupt.
|
||||||
|
* @param isr_handler The ISR (Interrupt Service Routine) handler function.
|
||||||
|
* @param args Arguments to be passed to the ISR handler function.
|
||||||
|
* @return Always return ESP_OK
|
||||||
|
*/
|
||||||
|
esp_err_t button_gpio_set_intr(int gpio_num, gpio_int_type_t intr_type, gpio_isr_t isr_handler, void *args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable or disable interrupt for GPIO button.
|
||||||
|
*
|
||||||
|
* @param gpio_num gpio number of button
|
||||||
|
* @param enable enable or disable
|
||||||
|
* @return Always return ESP_OK
|
||||||
|
*/
|
||||||
|
esp_err_t button_gpio_intr_control(int gpio_num, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable or disable GPIO wakeup functionality.
|
||||||
|
*
|
||||||
|
* This function allows enabling or disabling GPIO wakeup feature.
|
||||||
|
*
|
||||||
|
* @param gpio_num GPIO number for wakeup functionality.
|
||||||
|
* @param active_level Active level of the GPIO when triggered.
|
||||||
|
* @param enable Enable or disable the GPIO wakeup.
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_STATE if trigger was not active or in conflict.
|
||||||
|
*/
|
||||||
|
esp_err_t button_gpio_enable_gpio_wakeup(uint32_t gpio_num, uint8_t active_level, bool enable);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "button_types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MATRIX_BUTTON_COMBINE(row_gpio, col_gpio) ((row_gpio)<<8 | (col_gpio))
|
||||||
|
#define MATRIX_BUTTON_SPLIT_COL(data) ((uint32_t)(data)&0xff)
|
||||||
|
#define MATRIX_BUTTON_SPLIT_ROW(data) (((uint32_t)(data) >> 8) & 0xff)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Button matrix key configuration.
|
* @brief Button matrix key configuration.
|
||||||
* Just need to configure the GPIO associated with this GPIO in the matrix keyboard.
|
* Just need to configure the GPIO associated with this GPIO in the matrix keyboard.
|
||||||
|
|
@ -33,37 +34,46 @@ extern "C" {
|
||||||
* but buttons within the same row can be detected without conflicts.
|
* but buttons within the same row can be detected without conflicts.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t *row_gpios; /**< GPIO number list for the row */
|
int32_t row_gpio_num; /**< GPIO number associated with the row */
|
||||||
int32_t *col_gpios; /**< GPIO number list for the column */
|
int32_t col_gpio_num; /**< GPIO number associated with the column */
|
||||||
uint32_t row_gpio_num; /**< Number of GPIOs associated with the row */
|
|
||||||
uint32_t col_gpio_num; /**< Number of GPIOs associated with the column */
|
|
||||||
} button_matrix_config_t;
|
} button_matrix_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new button matrix device
|
* @brief Initialize a button matrix keyboard.
|
||||||
*
|
|
||||||
* This function initializes and configures a button matrix device using the specified row and column GPIOs.
|
|
||||||
* Each button in the matrix is represented as an independent button object, and its handle is returned in the `ret_button` array.
|
|
||||||
*
|
|
||||||
* @param[in] button_config Configuration for the button device, including callbacks and debounce parameters.
|
|
||||||
* @param[in] matrix_config Configuration for the matrix, including row and column GPIOs and their counts.
|
|
||||||
* @param[out] ret_button Array of handles for the buttons in the matrix.
|
|
||||||
* @param[inout] size Pointer to the total number of buttons in the matrix. Must match the product of row and column GPIO counts.
|
|
||||||
* On success, this value is updated to reflect the size of the button matrix.
|
|
||||||
*
|
*
|
||||||
|
* @param config Pointer to the button matrix key configuration.
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK: Successfully created the button matrix device.
|
* - ESP_OK on success
|
||||||
* - ESP_ERR_INVALID_ARG: Invalid argument provided, such as null pointers or mismatched matrix dimensions.
|
* - ESP_ERR_INVALID_ARG if the argument is NULL.
|
||||||
* - ESP_ERR_NO_MEM: Memory allocation failed.
|
|
||||||
* - ESP_FAIL: General failure, such as button creation failure for one or more buttons.
|
|
||||||
*
|
*
|
||||||
* @note
|
* @note When initializing the button matrix keyboard, the row GPIO pins will be set as outputs,
|
||||||
* - Each row GPIO is configured as an output, while each column GPIO is configured as an input.
|
* and the column GPIO pins will be set as inputs, both with pull-down resistors enabled.
|
||||||
* - The total number of buttons in the matrix must equal the product of the row and column GPIO counts.
|
|
||||||
* - The `ret_button` array must be large enough to store handles for all buttons in the matrix.
|
|
||||||
* - If any button creation fails, the function will free all allocated resources and return an error.
|
|
||||||
*/
|
*/
|
||||||
esp_err_t iot_button_new_matrix_device(const button_config_t *button_config, const button_matrix_config_t *matrix_config, button_handle_t *ret_button, size_t *size);
|
esp_err_t button_matrix_init(const button_matrix_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize a button in the matrix keyboard.
|
||||||
|
*
|
||||||
|
* @param row_gpio_num GPIO number of the row where the button is located.
|
||||||
|
* @param col_gpio_num GPIO number of the column where the button is located.
|
||||||
|
* @return
|
||||||
|
* - ESP_OK if the button is successfully deinitialized
|
||||||
|
*
|
||||||
|
* @note When deinitializing a button, please exercise caution and avoid deinitializing a button individually, as it may affect the proper functioning of other buttons in the same row or column.
|
||||||
|
*/
|
||||||
|
esp_err_t button_matrix_deinit(int row_gpio_num, int col_gpio_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the key level from the button matrix hardware.
|
||||||
|
*
|
||||||
|
* @param hardware_data Pointer to hardware-specific data containing information about row GPIO and column GPIO.
|
||||||
|
* @return uint8_t[out] The key level read from the hardware.
|
||||||
|
*
|
||||||
|
* @note This function retrieves the key level from the button matrix hardware.
|
||||||
|
* The `hardware_data` parameter should contain information about the row and column GPIO pins,
|
||||||
|
* and you can access this information using the `MATRIX_BUTTON_SPLIT_COL` and `MATRIX_BUTTON_SPLIT_ROW` macros.
|
||||||
|
*/
|
||||||
|
uint8_t button_matrix_get_key_level(void *hardware_data);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "button_interface.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum {
|
|
||||||
BUTTON_INACTIVE = 0,
|
|
||||||
BUTTON_ACTIVE,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct button_dev_t *button_handle_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Button configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
uint16_t long_press_time; /**< Trigger time(ms) for long press, if 0 default to BUTTON_LONG_PRESS_TIME_MS */
|
|
||||||
uint16_t short_press_time; /**< Trigger time(ms) for short press, if 0 default to BUTTON_SHORT_PRESS_TIME_MS */
|
|
||||||
} button_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new IoT button instance
|
|
||||||
*
|
|
||||||
* This function initializes a new button instance with the specified configuration
|
|
||||||
* and driver. It also sets up internal resources such as the button timer if not
|
|
||||||
* already initialized.
|
|
||||||
*
|
|
||||||
* @param[in] config Pointer to the button configuration structure
|
|
||||||
* @param[in] driver Pointer to the button driver structure
|
|
||||||
* @param[out] ret_button Pointer to where the handle of the created button will be stored
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK: Successfully created the button
|
|
||||||
* - ESP_ERR_INVALID_ARG: Invalid arguments passed to the function
|
|
||||||
* - ESP_ERR_NO_MEM: Memory allocation failed
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* - The first call to this function logs the IoT Button version.
|
|
||||||
* - The function initializes a global button timer if it is not already running.
|
|
||||||
* - Timer is started only if the driver does not enable power-saving mode.
|
|
||||||
*/
|
|
||||||
esp_err_t iot_button_create(const button_config_t *config, const button_driver_t *driver, button_handle_t *ret_button);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
@ -6,8 +6,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#if CONFIG_SOC_ADC_SUPPORTED
|
||||||
|
#include "button_adc.h"
|
||||||
|
#endif
|
||||||
|
#include "button_gpio.h"
|
||||||
|
#include "button_matrix.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "button_types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -15,6 +19,7 @@ extern "C" {
|
||||||
|
|
||||||
typedef void (* button_cb_t)(void *button_handle, void *usr_data);
|
typedef void (* button_cb_t)(void *button_handle, void *usr_data);
|
||||||
|
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
typedef void (* button_power_save_cb_t)(void *usr_data);
|
typedef void (* button_power_save_cb_t)(void *usr_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -22,9 +27,12 @@ typedef void (* button_power_save_cb_t)(void *usr_data);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
button_power_save_cb_t enter_power_save_cb; /**< Callback function when entering power save mode */
|
button_power_save_cb_t enter_power_save_cb;
|
||||||
void *usr_data; /**< User data for the callback */
|
void *usr_data;
|
||||||
} button_power_save_config_t;
|
} button_power_save_config_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void *button_handle_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Button events
|
* @brief Button events
|
||||||
|
|
@ -47,7 +55,7 @@ typedef enum {
|
||||||
} button_event_t;
|
} button_event_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Button events arg
|
* @brief Button events data
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|
@ -66,7 +74,27 @@ typedef union {
|
||||||
struct multiple_clicks_t {
|
struct multiple_clicks_t {
|
||||||
uint16_t clicks; /**< number of clicks, to trigger the callback */
|
uint16_t clicks; /**< number of clicks, to trigger the callback */
|
||||||
} multiple_clicks; /**< multiple clicks struct, for event BUTTON_MULTIPLE_CLICK */
|
} multiple_clicks; /**< multiple clicks struct, for event BUTTON_MULTIPLE_CLICK */
|
||||||
} button_event_args_t;
|
} button_event_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Button events configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
button_event_t event; /**< button event type */
|
||||||
|
button_event_data_t event_data; /**< event data corresponding to the event */
|
||||||
|
} button_event_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Supported button type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
BUTTON_TYPE_GPIO,
|
||||||
|
BUTTON_TYPE_ADC,
|
||||||
|
BUTTON_TYPE_MATRIX,
|
||||||
|
BUTTON_TYPE_CUSTOM
|
||||||
|
} button_type_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Button parameter
|
* @brief Button parameter
|
||||||
|
|
@ -78,6 +106,45 @@ typedef enum {
|
||||||
BUTTON_PARAM_MAX,
|
BUTTON_PARAM_MAX,
|
||||||
} button_param_t;
|
} button_param_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief custom button configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t active_level; /**< active level when press down */
|
||||||
|
esp_err_t (*button_custom_init)(void *param); /**< user defined button init */
|
||||||
|
uint8_t (*button_custom_get_key_value)(void *param); /**< user defined button get key value */
|
||||||
|
esp_err_t (*button_custom_deinit)(void *param); /**< user defined button deinit */
|
||||||
|
void *priv; /**< private data used for custom button, MUST be allocated dynamically and will be auto freed in iot_button_delete*/
|
||||||
|
} button_custom_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Button configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
button_type_t type; /**< button type, The corresponding button configuration must be filled */
|
||||||
|
uint16_t long_press_time; /**< Trigger time(ms) for long press, if 0 default to BUTTON_LONG_PRESS_TIME_MS */
|
||||||
|
uint16_t short_press_time; /**< Trigger time(ms) for short press, if 0 default to BUTTON_SHORT_PRESS_TIME_MS */
|
||||||
|
union {
|
||||||
|
button_gpio_config_t gpio_button_config; /**< gpio button configuration */
|
||||||
|
#if CONFIG_SOC_ADC_SUPPORTED
|
||||||
|
button_adc_config_t adc_button_config; /**< adc button configuration */
|
||||||
|
#endif
|
||||||
|
button_matrix_config_t matrix_button_config; /**< matrix key button configuration */
|
||||||
|
button_custom_config_t custom_button_config; /**< custom button configuration */
|
||||||
|
}; /**< button configuration */
|
||||||
|
} button_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a button
|
||||||
|
*
|
||||||
|
* @param config pointer of button configuration, must corresponding the button type
|
||||||
|
*
|
||||||
|
* @return A handle to the created button, or NULL in case of error.
|
||||||
|
*/
|
||||||
|
button_handle_t iot_button_create(const button_config_t *config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delete a button
|
* @brief Delete a button
|
||||||
*
|
*
|
||||||
|
|
@ -94,7 +161,6 @@ esp_err_t iot_button_delete(button_handle_t btn_handle);
|
||||||
*
|
*
|
||||||
* @param btn_handle A button handle to register
|
* @param btn_handle A button handle to register
|
||||||
* @param event Button event
|
* @param event Button event
|
||||||
* @param event_args Button event arguments
|
|
||||||
* @param cb Callback function.
|
* @param cb Callback function.
|
||||||
* @param usr_data user data
|
* @param usr_data user data
|
||||||
*
|
*
|
||||||
|
|
@ -104,21 +170,51 @@ esp_err_t iot_button_delete(button_handle_t btn_handle);
|
||||||
* - ESP_ERR_INVALID_STATE The Callback is already registered. No free Space for another Callback.
|
* - ESP_ERR_INVALID_STATE The Callback is already registered. No free Space for another Callback.
|
||||||
* - ESP_ERR_NO_MEM No more memory allocation for the event
|
* - ESP_ERR_NO_MEM No more memory allocation for the event
|
||||||
*/
|
*/
|
||||||
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args, button_cb_t cb, void *usr_data);
|
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb, void *usr_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register the button event callback function.
|
||||||
|
*
|
||||||
|
* @param btn_handle A button handle to register
|
||||||
|
* @param event_cfg Button event configuration
|
||||||
|
* @param cb Callback function.
|
||||||
|
* @param usr_data user data
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
||||||
|
* - ESP_ERR_INVALID_STATE The Callback is already registered. No free Space for another Callback.
|
||||||
|
* - ESP_ERR_NO_MEM No more memory allocation for the event
|
||||||
|
*/
|
||||||
|
esp_err_t iot_button_register_event_cb(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb, void *usr_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregister the button event callback function.
|
||||||
|
* In case event_data is also passed it will unregister function for that particular event_data only.
|
||||||
|
*
|
||||||
|
* @param btn_handle A button handle to unregister
|
||||||
|
* @param event_cfg Button event
|
||||||
|
* @param cb callback to unregister
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
||||||
|
* - ESP_ERR_INVALID_STATE The Callback was never registered with the event
|
||||||
|
*/
|
||||||
|
esp_err_t iot_button_unregister_event(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Unregister all the callbacks associated with the event.
|
* @brief Unregister all the callbacks associated with the event.
|
||||||
*
|
*
|
||||||
* @param btn_handle A button handle to unregister
|
* @param btn_handle A button handle to unregister
|
||||||
* @param event Button event
|
* @param event Button event
|
||||||
* @param event_args Used for unregistering a specific callback.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK on success
|
* - ESP_OK on success
|
||||||
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
||||||
* - ESP_ERR_INVALID_STATE No callbacks registered for the event
|
* - ESP_ERR_INVALID_STATE No callbacks registered for the event
|
||||||
*/
|
*/
|
||||||
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args);
|
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief counts total callbacks registered
|
* @brief counts total callbacks registered
|
||||||
|
|
@ -142,7 +238,7 @@ size_t iot_button_count_cb(button_handle_t btn_handle);
|
||||||
* - 0 if no callbacks registered, or 1 .. (BUTTON_EVENT_MAX-1) for the number of Registered Buttons.
|
* - 0 if no callbacks registered, or 1 .. (BUTTON_EVENT_MAX-1) for the number of Registered Buttons.
|
||||||
* - ESP_ERR_INVALID_ARG if btn_handle is invalid
|
* - ESP_ERR_INVALID_ARG if btn_handle is invalid
|
||||||
*/
|
*/
|
||||||
size_t iot_button_count_event_cb(button_handle_t btn_handle, button_event_t event);
|
size_t iot_button_count_event(button_handle_t btn_handle, button_event_t event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get button event
|
* @brief Get button event
|
||||||
|
|
@ -189,26 +285,13 @@ esp_err_t iot_button_print_event(button_handle_t btn_handle);
|
||||||
*/
|
*/
|
||||||
uint8_t iot_button_get_repeat(button_handle_t btn_handle);
|
uint8_t iot_button_get_repeat(button_handle_t btn_handle);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get button pressed time
|
|
||||||
*
|
|
||||||
* @param btn_handle Button handle
|
|
||||||
*
|
|
||||||
* @return Actual time from press down to up (ms).
|
|
||||||
*/
|
|
||||||
uint32_t iot_button_get_pressed_time(button_handle_t btn_handle);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get button ticks time
|
* @brief Get button ticks time
|
||||||
*
|
*
|
||||||
* @deprecated This function is deprecated and will be removed in a future release.
|
|
||||||
* Please use iot_button_get_pressed_time() instead.
|
|
||||||
*
|
|
||||||
* @param btn_handle Button handle
|
* @param btn_handle Button handle
|
||||||
*
|
*
|
||||||
* @return Actual time from press down to up (ms).
|
* @return Actual time from press down to up (ms).
|
||||||
*/
|
*/
|
||||||
__attribute__((deprecated("Use iot_button_get_pressed_time() instead")))
|
|
||||||
uint32_t iot_button_get_ticks_time(button_handle_t btn_handle);
|
uint32_t iot_button_get_ticks_time(button_handle_t btn_handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -260,6 +343,7 @@ esp_err_t iot_button_resume(void);
|
||||||
*/
|
*/
|
||||||
esp_err_t iot_button_stop(void);
|
esp_err_t iot_button_stop(void);
|
||||||
|
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
/**
|
/**
|
||||||
* @brief Register a callback function for power saving.
|
* @brief Register a callback function for power saving.
|
||||||
* The config->enter_power_save_cb function will be called when all keys stop working.
|
* The config->enter_power_save_cb function will be called when all keys stop working.
|
||||||
|
|
@ -272,6 +356,7 @@ esp_err_t iot_button_stop(void);
|
||||||
* - ESP_ERR_NO_MEM Not enough memory
|
* - ESP_ERR_NO_MEM Not enough memory
|
||||||
*/
|
*/
|
||||||
esp_err_t iot_button_register_power_save_cb(const button_power_save_config_t *config);
|
esp_err_t iot_button_register_power_save_cb(const button_power_save_config_t *config);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct button_driver_t button_driver_t; /*!< Type of button object */
|
|
||||||
|
|
||||||
struct button_driver_t {
|
|
||||||
/*!< (optional) Need Support Power Save */
|
|
||||||
bool enable_power_save;
|
|
||||||
|
|
||||||
/*!< (necessary) Get key level */
|
|
||||||
uint8_t (*get_key_level)(button_driver_t *button_driver);
|
|
||||||
|
|
||||||
/*!< (optional) Enter Power Save cb */
|
|
||||||
esp_err_t (*enter_power_save)(button_driver_t *button_driver);
|
|
||||||
|
|
||||||
/*!< (optional) Del the hardware driver and cleanup */
|
|
||||||
esp_err_t (*del)(button_driver_t *button_driver);
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
@ -12,10 +12,11 @@
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_check.h"
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
|
#include "esp_pm.h"
|
||||||
|
#endif
|
||||||
#include "iot_button.h"
|
#include "iot_button.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "button_interface.h"
|
|
||||||
|
|
||||||
static const char *TAG = "button";
|
static const char *TAG = "button";
|
||||||
static portMUX_TYPE s_button_lock = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE s_button_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
@ -44,14 +45,6 @@ static const char *button_event_str[] = {
|
||||||
"BUTTON_NONE_PRESS",
|
"BUTTON_NONE_PRESS",
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
PRESS_DOWN_CHECK = 0,
|
|
||||||
PRESS_UP_CHECK,
|
|
||||||
PRESS_REPEAT_DOWN_CHECK,
|
|
||||||
PRESS_REPEAT_UP_CHECK,
|
|
||||||
PRESS_LONG_PRESS_UP_CHECK,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structs to store callback info
|
* @brief Structs to store callback info
|
||||||
*
|
*
|
||||||
|
|
@ -59,41 +52,48 @@ enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
button_cb_t cb;
|
button_cb_t cb;
|
||||||
void *usr_data;
|
void *usr_data;
|
||||||
button_event_args_t event_args;
|
button_event_data_t event_data;
|
||||||
} button_cb_info_t;
|
} button_cb_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structs to record individual key parameters
|
* @brief Structs to record individual key parameters
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct button_dev_t {
|
typedef struct Button {
|
||||||
uint32_t ticks; /*!< Count for the current button state. */
|
uint32_t ticks; /*!< Count for the current button state. */
|
||||||
uint32_t long_press_ticks; /*!< Trigger ticks for long press, */
|
uint32_t long_press_ticks; /*!< Trigger ticks for long press, */
|
||||||
uint32_t short_press_ticks; /*!< Trigger ticks for repeat press */
|
uint32_t short_press_ticks; /*!< Trigger ticks for repeat press */
|
||||||
uint32_t long_press_hold_cnt; /*!< Record long press hold count */
|
uint32_t long_press_hold_cnt; /*!< Record long press hold count */
|
||||||
uint8_t repeat;
|
uint8_t repeat;
|
||||||
uint8_t state: 3;
|
uint8_t state: 3;
|
||||||
uint8_t debounce_cnt: 4; /*!< Max 15 */
|
uint8_t debounce_cnt: 3;
|
||||||
|
uint8_t active_level: 1;
|
||||||
uint8_t button_level: 1;
|
uint8_t button_level: 1;
|
||||||
|
uint8_t enable_power_save: 1;
|
||||||
button_event_t event;
|
button_event_t event;
|
||||||
button_driver_t *driver;
|
uint8_t (*hal_button_Level)(void *hardware_data);
|
||||||
|
esp_err_t (*hal_button_deinit)(void *hardware_data);
|
||||||
|
void *hardware_data;
|
||||||
|
button_type_t type;
|
||||||
button_cb_info_t *cb_info[BUTTON_EVENT_MAX];
|
button_cb_info_t *cb_info[BUTTON_EVENT_MAX];
|
||||||
size_t size[BUTTON_EVENT_MAX];
|
size_t size[BUTTON_EVENT_MAX];
|
||||||
int count[2];
|
int count[2];
|
||||||
struct button_dev_t *next;
|
struct Button *next;
|
||||||
} button_dev_t;
|
} button_dev_t;
|
||||||
|
|
||||||
//button handle list head.
|
//button handle list head.
|
||||||
static button_dev_t *g_head_handle = NULL;
|
static button_dev_t *g_head_handle = NULL;
|
||||||
static esp_timer_handle_t g_button_timer_handle = NULL;
|
static esp_timer_handle_t g_button_timer_handle = NULL;
|
||||||
static bool g_is_timer_running = false;
|
static bool g_is_timer_running = false;
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
static button_power_save_config_t power_save_usr_cfg = {0};
|
static button_power_save_config_t power_save_usr_cfg = {0};
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TICKS_INTERVAL CONFIG_BUTTON_PERIOD_TIME_MS
|
#define TICKS_INTERVAL CONFIG_BUTTON_PERIOD_TIME_MS
|
||||||
#define DEBOUNCE_TICKS CONFIG_BUTTON_DEBOUNCE_TICKS //MAX 8
|
#define DEBOUNCE_TICKS CONFIG_BUTTON_DEBOUNCE_TICKS //MAX 8
|
||||||
#define SHORT_TICKS (CONFIG_BUTTON_SHORT_PRESS_TIME_MS /TICKS_INTERVAL)
|
#define SHORT_TICKS (CONFIG_BUTTON_SHORT_PRESS_TIME_MS /TICKS_INTERVAL)
|
||||||
#define LONG_TICKS (CONFIG_BUTTON_LONG_PRESS_TIME_MS /TICKS_INTERVAL)
|
#define LONG_TICKS (CONFIG_BUTTON_LONG_PRESS_TIME_MS /TICKS_INTERVAL)
|
||||||
#define SERIAL_TICKS (CONFIG_BUTTON_LONG_PRESS_HOLD_SERIAL_TIME_MS /TICKS_INTERVAL)
|
#define SERIAL_TICKS (CONFIG_BUTTON_SERIAL_TIME_MS /TICKS_INTERVAL)
|
||||||
#define TOLERANCE (CONFIG_BUTTON_PERIOD_TIME_MS*4)
|
#define TOLERANCE (CONFIG_BUTTON_PERIOD_TIME_MS*4)
|
||||||
|
|
||||||
#define CALL_EVENT_CB(ev) \
|
#define CALL_EVENT_CB(ev) \
|
||||||
|
|
@ -110,7 +110,7 @@ static button_power_save_config_t power_save_usr_cfg = {0};
|
||||||
*/
|
*/
|
||||||
static void button_handler(button_dev_t *btn)
|
static void button_handler(button_dev_t *btn)
|
||||||
{
|
{
|
||||||
uint8_t read_gpio_level = btn->driver->get_key_level(btn->driver);
|
uint8_t read_gpio_level = btn->hal_button_Level(btn->hardware_data);
|
||||||
|
|
||||||
/** ticks counter working.. */
|
/** ticks counter working.. */
|
||||||
if ((btn->state) > 0) {
|
if ((btn->state) > 0) {
|
||||||
|
|
@ -129,54 +129,54 @@ static void button_handler(button_dev_t *btn)
|
||||||
|
|
||||||
/** State machine */
|
/** State machine */
|
||||||
switch (btn->state) {
|
switch (btn->state) {
|
||||||
case PRESS_DOWN_CHECK:
|
case 0:
|
||||||
if (btn->button_level == BUTTON_ACTIVE) {
|
if (btn->button_level == btn->active_level) {
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
||||||
btn->ticks = 0;
|
btn->ticks = 0;
|
||||||
btn->repeat = 1;
|
btn->repeat = 1;
|
||||||
btn->state = PRESS_UP_CHECK;
|
btn->state = 1;
|
||||||
} else {
|
} else {
|
||||||
btn->event = (uint8_t)BUTTON_NONE_PRESS;
|
btn->event = (uint8_t)BUTTON_NONE_PRESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRESS_UP_CHECK:
|
case 1:
|
||||||
if (btn->button_level != BUTTON_ACTIVE) {
|
if (btn->button_level != btn->active_level) {
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||||
btn->ticks = 0;
|
btn->ticks = 0;
|
||||||
btn->state = PRESS_REPEAT_DOWN_CHECK;
|
btn->state = 2;
|
||||||
|
|
||||||
} else if (btn->ticks >= btn->long_press_ticks) {
|
} else if (btn->ticks >= btn->long_press_ticks) {
|
||||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
||||||
btn->state = PRESS_LONG_PRESS_UP_CHECK;
|
btn->state = 4;
|
||||||
/** Calling callbacks for BUTTON_LONG_PRESS_START */
|
/** Calling callbacks for BUTTON_LONG_PRESS_START */
|
||||||
uint32_t pressed_time = iot_button_get_pressed_time(btn);
|
uint32_t ticks_time = iot_button_get_ticks_time(btn);
|
||||||
int32_t diff = pressed_time - btn->long_press_ticks * TICKS_INTERVAL;
|
int32_t diff = ticks_time - btn->long_press_ticks * TICKS_INTERVAL;
|
||||||
if (btn->cb_info[btn->event] && btn->count[0] == 0) {
|
if (btn->cb_info[btn->event] && btn->count[0] == 0) {
|
||||||
if (abs(diff) <= TOLERANCE && btn->cb_info[btn->event][btn->count[0]].event_args.long_press.press_time == (btn->long_press_ticks * TICKS_INTERVAL)) {
|
if (abs(diff) <= TOLERANCE && btn->cb_info[btn->event][btn->count[0]].event_data.long_press.press_time == (btn->long_press_ticks * TICKS_INTERVAL)) {
|
||||||
do {
|
do {
|
||||||
btn->cb_info[btn->event][btn->count[0]].cb(btn, btn->cb_info[btn->event][btn->count[0]].usr_data);
|
btn->cb_info[btn->event][btn->count[0]].cb(btn, btn->cb_info[btn->event][btn->count[0]].usr_data);
|
||||||
btn->count[0]++;
|
btn->count[0]++;
|
||||||
if (btn->count[0] >= btn->size[btn->event]) {
|
if (btn->count[0] >= btn->size[btn->event]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (btn->cb_info[btn->event][btn->count[0]].event_args.long_press.press_time == btn->long_press_ticks * TICKS_INTERVAL);
|
} while (btn->cb_info[btn->event][btn->count[0]].event_data.long_press.press_time == btn->long_press_ticks * TICKS_INTERVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRESS_REPEAT_DOWN_CHECK:
|
case 2:
|
||||||
if (btn->button_level == BUTTON_ACTIVE) {
|
if (btn->button_level == btn->active_level) {
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_REPEAT;
|
btn->event = (uint8_t)BUTTON_PRESS_REPEAT;
|
||||||
btn->repeat++;
|
btn->repeat++;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_REPEAT); // repeat hit
|
CALL_EVENT_CB(BUTTON_PRESS_REPEAT); // repeat hit
|
||||||
btn->ticks = 0;
|
btn->ticks = 0;
|
||||||
btn->state = PRESS_REPEAT_UP_CHECK;
|
btn->state = 3;
|
||||||
} else if (btn->ticks > btn->short_press_ticks) {
|
} else if (btn->ticks > btn->short_press_ticks) {
|
||||||
if (btn->repeat == 1) {
|
if (btn->repeat == 1) {
|
||||||
btn->event = (uint8_t)BUTTON_SINGLE_CLICK;
|
btn->event = (uint8_t)BUTTON_SINGLE_CLICK;
|
||||||
|
|
@ -190,8 +190,14 @@ static void button_handler(button_dev_t *btn)
|
||||||
|
|
||||||
/** Calling the callbacks for MULTIPLE BUTTON CLICKS */
|
/** Calling the callbacks for MULTIPLE BUTTON CLICKS */
|
||||||
for (int i = 0; i < btn->size[btn->event]; i++) {
|
for (int i = 0; i < btn->size[btn->event]; i++) {
|
||||||
if (btn->repeat == btn->cb_info[btn->event][i].event_args.multiple_clicks.clicks) {
|
if (btn->repeat == btn->cb_info[btn->event][i].event_data.multiple_clicks.clicks) {
|
||||||
|
do {
|
||||||
btn->cb_info[btn->event][i].cb(btn, btn->cb_info[btn->event][i].usr_data);
|
btn->cb_info[btn->event][i].cb(btn, btn->cb_info[btn->event][i].usr_data);
|
||||||
|
i++;
|
||||||
|
if (i >= btn->size[btn->event]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (btn->cb_info[btn->event][i].event_data.multiple_clicks.clicks == btn->repeat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,44 +211,43 @@ static void button_handler(button_dev_t *btn)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
if (btn->button_level != BUTTON_ACTIVE) {
|
if (btn->button_level != btn->active_level) {
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||||
if (btn->ticks < btn->short_press_ticks) {
|
if (btn->ticks < btn->short_press_ticks) {
|
||||||
btn->ticks = 0;
|
btn->ticks = 0;
|
||||||
btn->state = PRESS_REPEAT_DOWN_CHECK; //repeat press
|
btn->state = 2; //repeat press
|
||||||
} else {
|
} else {
|
||||||
btn->state = PRESS_DOWN_CHECK;
|
btn->state = 0;
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_END;
|
btn->event = (uint8_t)BUTTON_PRESS_END;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_END);
|
CALL_EVENT_CB(BUTTON_PRESS_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRESS_LONG_PRESS_UP_CHECK:
|
case 4:
|
||||||
if (btn->button_level == BUTTON_ACTIVE) {
|
if (btn->button_level == btn->active_level) {
|
||||||
//continue hold trigger
|
//continue hold trigger
|
||||||
if (btn->ticks >= (btn->long_press_hold_cnt + 1) * SERIAL_TICKS + btn->long_press_ticks) {
|
if (btn->ticks >= (btn->long_press_hold_cnt + 1) * SERIAL_TICKS + btn->long_press_ticks) {
|
||||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_HOLD;
|
btn->event = (uint8_t)BUTTON_LONG_PRESS_HOLD;
|
||||||
btn->long_press_hold_cnt++;
|
btn->long_press_hold_cnt++;
|
||||||
CALL_EVENT_CB(BUTTON_LONG_PRESS_HOLD);
|
CALL_EVENT_CB(BUTTON_LONG_PRESS_HOLD);
|
||||||
}
|
|
||||||
|
|
||||||
/** Calling callbacks for BUTTON_LONG_PRESS_START based on press_time */
|
/** Calling callbacks for BUTTON_LONG_PRESS_START based on press_time */
|
||||||
uint32_t pressed_time = iot_button_get_pressed_time(btn);
|
uint32_t ticks_time = iot_button_get_ticks_time(btn);
|
||||||
if (btn->cb_info[BUTTON_LONG_PRESS_START]) {
|
if (btn->cb_info[BUTTON_LONG_PRESS_START]) {
|
||||||
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_START];
|
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_START];
|
||||||
uint16_t time = cb_info[btn->count[0]].event_args.long_press.press_time;
|
uint16_t time = cb_info[btn->count[0]].event_data.long_press.press_time;
|
||||||
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
||||||
for (int i = btn->count[0] + 1; i < btn->size[BUTTON_LONG_PRESS_START]; i++) {
|
for (int i = btn->count[0] + 1; i < btn->size[BUTTON_LONG_PRESS_START]; i++) {
|
||||||
time = cb_info[i].event_args.long_press.press_time;
|
time = cb_info[i].event_data.long_press.press_time;
|
||||||
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
||||||
btn->count[0] = i;
|
btn->count[0] = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (btn->count[0] < btn->size[BUTTON_LONG_PRESS_START] && abs((int)pressed_time - (int)time) <= TOLERANCE) {
|
if (btn->count[0] < btn->size[BUTTON_LONG_PRESS_START] && abs((int)ticks_time - (int)time) <= TOLERANCE) {
|
||||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
||||||
do {
|
do {
|
||||||
cb_info[btn->count[0]].cb(btn, cb_info[btn->count[0]].usr_data);
|
cb_info[btn->count[0]].cb(btn, cb_info[btn->count[0]].usr_data);
|
||||||
|
|
@ -250,30 +255,31 @@ static void button_handler(button_dev_t *btn)
|
||||||
if (btn->count[0] >= btn->size[BUTTON_LONG_PRESS_START]) {
|
if (btn->count[0] >= btn->size[BUTTON_LONG_PRESS_START]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (time == cb_info[btn->count[0]].event_args.long_press.press_time);
|
} while (time == cb_info[btn->count[0]].event_data.long_press.press_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updating counter for BUTTON_LONG_PRESS_UP press_time */
|
/** Updating counter for BUTTON_LONG_PRESS_UP press_time */
|
||||||
if (btn->cb_info[BUTTON_LONG_PRESS_UP]) {
|
if (btn->cb_info[BUTTON_LONG_PRESS_UP]) {
|
||||||
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_UP];
|
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_UP];
|
||||||
uint16_t time = cb_info[btn->count[1] + 1].event_args.long_press.press_time;
|
uint16_t time = cb_info[btn->count[1] + 1].event_data.long_press.press_time;
|
||||||
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
||||||
for (int i = btn->count[1] + 1; i < btn->size[BUTTON_LONG_PRESS_UP]; i++) {
|
for (int i = btn->count[1] + 1; i < btn->size[BUTTON_LONG_PRESS_UP]; i++) {
|
||||||
time = cb_info[i].event_args.long_press.press_time;
|
time = cb_info[i].event_data.long_press.press_time;
|
||||||
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
||||||
btn->count[1] = i;
|
btn->count[1] = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (btn->count[1] + 1 < btn->size[BUTTON_LONG_PRESS_UP] && abs((int)pressed_time - (int)time) <= TOLERANCE) {
|
if (btn->count[1] + 1 < btn->size[BUTTON_LONG_PRESS_UP] && abs((int)ticks_time - (int)time) <= TOLERANCE) {
|
||||||
do {
|
do {
|
||||||
btn->count[1]++;
|
btn->count[1]++;
|
||||||
if (btn->count[1] + 1 >= btn->size[BUTTON_LONG_PRESS_UP]) {
|
if (btn->count[1] + 1 >= btn->size[BUTTON_LONG_PRESS_UP]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (time == cb_info[btn->count[1] + 1].event_args.long_press.press_time);
|
} while (time == cb_info[btn->count[1] + 1].event_data.long_press.press_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { //releasd
|
} else { //releasd
|
||||||
|
|
@ -289,7 +295,7 @@ static void button_handler(button_dev_t *btn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
btn->count[1]--;
|
btn->count[1]--;
|
||||||
} while (cb_info[btn->count[1]].event_args.long_press.press_time == cb_info[btn->count[1] + 1].event_args.long_press.press_time);
|
} while (cb_info[btn->count[1]].event_data.long_press.press_time == cb_info[btn->count[1] + 1].event_data.long_press.press_time);
|
||||||
|
|
||||||
/** Reset the counter */
|
/** Reset the counter */
|
||||||
btn->count[1] = -1;
|
btn->count[1] = -1;
|
||||||
|
|
@ -301,7 +307,7 @@ static void button_handler(button_dev_t *btn)
|
||||||
|
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||||
btn->state = PRESS_DOWN_CHECK; //reset
|
btn->state = 0; //reset
|
||||||
btn->long_press_hold_cnt = 0;
|
btn->long_press_hold_cnt = 0;
|
||||||
btn->event = (uint8_t)BUTTON_PRESS_END;
|
btn->event = (uint8_t)BUTTON_PRESS_END;
|
||||||
CALL_EVENT_CB(BUTTON_PRESS_END);
|
CALL_EVENT_CB(BUTTON_PRESS_END);
|
||||||
|
|
@ -314,13 +320,18 @@ static void button_cb(void *args)
|
||||||
{
|
{
|
||||||
button_dev_t *target;
|
button_dev_t *target;
|
||||||
/*!< When all buttons enter the BUTTON_NONE_PRESS state, the system enters low-power mode */
|
/*!< When all buttons enter the BUTTON_NONE_PRESS state, the system enters low-power mode */
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
bool enter_power_save_flag = true;
|
bool enter_power_save_flag = true;
|
||||||
|
#endif
|
||||||
for (target = g_head_handle; target; target = target->next) {
|
for (target = g_head_handle; target; target = target->next) {
|
||||||
button_handler(target);
|
button_handler(target);
|
||||||
if (!(target->driver->enable_power_save && target->debounce_cnt == 0 && target->event == BUTTON_NONE_PRESS)) {
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
|
if (!(target->enable_power_save && target->debounce_cnt == 0 && target->event == BUTTON_NONE_PRESS)) {
|
||||||
enter_power_save_flag = false;
|
enter_power_save_flag = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
if (enter_power_save_flag) {
|
if (enter_power_save_flag) {
|
||||||
/*!< Stop esp timer for power save */
|
/*!< Stop esp timer for power save */
|
||||||
if (g_is_timer_running) {
|
if (g_is_timer_running) {
|
||||||
|
|
@ -328,8 +339,9 @@ static void button_cb(void *args)
|
||||||
g_is_timer_running = false;
|
g_is_timer_running = false;
|
||||||
}
|
}
|
||||||
for (target = g_head_handle; target; target = target->next) {
|
for (target = g_head_handle; target; target = target->next) {
|
||||||
if (target->driver->enable_power_save && target->driver->enter_power_save) {
|
if (target->type == BUTTON_TYPE_GPIO && target->enable_power_save) {
|
||||||
target->driver->enter_power_save(target->driver);
|
button_gpio_intr_control((int)(target->hardware_data), true);
|
||||||
|
button_gpio_enable_gpio_wakeup((uint32_t)(target->hardware_data), target->active_level, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*!< Notify the user that the Button has entered power save mode by calling this callback function. */
|
/*!< Notify the user that the Button has entered power save mode by calling this callback function. */
|
||||||
|
|
@ -337,20 +349,211 @@ static void button_cb(void *args)
|
||||||
power_save_usr_cfg.enter_power_save_cb(power_save_usr_cfg.usr_data);
|
power_save_usr_cfg.enter_power_save_cb(power_save_usr_cfg.usr_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args, button_cb_t cb, void *usr_data)
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
|
static void IRAM_ATTR button_power_save_isr_handler(void* arg)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(NULL != btn_handle, ESP_ERR_INVALID_ARG, TAG, "Pointer of handle is invalid");
|
if (!g_is_timer_running) {
|
||||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||||
ESP_RETURN_ON_FALSE(event < BUTTON_EVENT_MAX, ESP_ERR_INVALID_ARG, TAG, "event is invalid");
|
g_is_timer_running = true;
|
||||||
ESP_RETURN_ON_FALSE(NULL != cb, ESP_ERR_INVALID_ARG, TAG, "Pointer of cb is invalid");
|
|
||||||
ESP_RETURN_ON_FALSE(event != BUTTON_MULTIPLE_CLICK || event_args, ESP_ERR_INVALID_ARG, TAG, "event is invalid");
|
|
||||||
|
|
||||||
if (event_args) {
|
|
||||||
ESP_RETURN_ON_FALSE(!(event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) || event_args->long_press.press_time > btn->short_press_ticks * TICKS_INTERVAL, ESP_ERR_INVALID_ARG, TAG, "event_args is invalid");
|
|
||||||
ESP_RETURN_ON_FALSE(event != BUTTON_MULTIPLE_CLICK || event_args->multiple_clicks.clicks, ESP_ERR_INVALID_ARG, TAG, "event_args is invalid");
|
|
||||||
}
|
}
|
||||||
|
button_gpio_intr_control((int)arg, false);
|
||||||
|
/*!< disable gpio wakeup not need active level*/
|
||||||
|
button_gpio_enable_gpio_wakeup((uint32_t)arg, 0, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static button_dev_t *button_create_com(uint8_t active_level, uint8_t (*hal_get_key_state)(void *hardware_data), void *hardware_data, uint16_t long_press_ticks, uint16_t short_press_ticks)
|
||||||
|
{
|
||||||
|
BTN_CHECK(NULL != hal_get_key_state, "Function pointer is invalid", NULL);
|
||||||
|
|
||||||
|
button_dev_t *btn = (button_dev_t *) calloc(1, sizeof(button_dev_t));
|
||||||
|
BTN_CHECK(NULL != btn, "Button memory alloc failed", NULL);
|
||||||
|
btn->hardware_data = hardware_data;
|
||||||
|
btn->event = BUTTON_NONE_PRESS;
|
||||||
|
btn->active_level = active_level;
|
||||||
|
btn->hal_button_Level = hal_get_key_state;
|
||||||
|
btn->button_level = !active_level;
|
||||||
|
btn->long_press_ticks = long_press_ticks;
|
||||||
|
btn->short_press_ticks = short_press_ticks;
|
||||||
|
|
||||||
|
/** Add handle to list */
|
||||||
|
btn->next = g_head_handle;
|
||||||
|
g_head_handle = btn;
|
||||||
|
|
||||||
|
if (!g_button_timer_handle) {
|
||||||
|
esp_timer_create_args_t button_timer = {0};
|
||||||
|
button_timer.arg = NULL;
|
||||||
|
button_timer.callback = button_cb;
|
||||||
|
button_timer.dispatch_method = ESP_TIMER_TASK;
|
||||||
|
button_timer.name = "button_timer";
|
||||||
|
esp_timer_create(&button_timer, &g_button_timer_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t button_delete_com(button_dev_t *btn)
|
||||||
|
{
|
||||||
|
BTN_CHECK(NULL != btn, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
button_dev_t **curr;
|
||||||
|
for (curr = &g_head_handle; *curr;) {
|
||||||
|
button_dev_t *entry = *curr;
|
||||||
|
if (entry == btn) {
|
||||||
|
*curr = entry->next;
|
||||||
|
free(entry);
|
||||||
|
} else {
|
||||||
|
curr = &entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* count button number */
|
||||||
|
uint16_t number = 0;
|
||||||
|
button_dev_t *target = g_head_handle;
|
||||||
|
while (target) {
|
||||||
|
target = target->next;
|
||||||
|
number++;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "remain btn number=%d", number);
|
||||||
|
|
||||||
|
if (0 == number && g_is_timer_running) { /**< if all button is deleted, stop the timer */
|
||||||
|
esp_timer_stop(g_button_timer_handle);
|
||||||
|
esp_timer_delete(g_button_timer_handle);
|
||||||
|
g_button_timer_handle = NULL;
|
||||||
|
g_is_timer_running = false;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
button_handle_t iot_button_create(const button_config_t *config)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "IoT Button Version: %d.%d.%d", BUTTON_VER_MAJOR, BUTTON_VER_MINOR, BUTTON_VER_PATCH);
|
||||||
|
BTN_CHECK(config, "Invalid button config", NULL);
|
||||||
|
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
button_dev_t *btn = NULL;
|
||||||
|
uint16_t long_press_time = 0;
|
||||||
|
uint16_t short_press_time = 0;
|
||||||
|
long_press_time = TIME_TO_TICKS(config->long_press_time, LONG_TICKS);
|
||||||
|
short_press_time = TIME_TO_TICKS(config->short_press_time, SHORT_TICKS);
|
||||||
|
switch (config->type) {
|
||||||
|
case BUTTON_TYPE_GPIO: {
|
||||||
|
const button_gpio_config_t *cfg = &(config->gpio_button_config);
|
||||||
|
ret = button_gpio_init(cfg);
|
||||||
|
BTN_CHECK(ESP_OK == ret, "gpio button init failed", NULL);
|
||||||
|
btn = button_create_com(cfg->active_level, button_gpio_get_key_level, (void *)cfg->gpio_num, long_press_time, short_press_time);
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
|
if (cfg->enable_power_save) {
|
||||||
|
btn->enable_power_save = cfg->enable_power_save;
|
||||||
|
button_gpio_set_intr(cfg->gpio_num, cfg->active_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL, button_power_save_isr_handler, (void *)cfg->gpio_num);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
|
#if CONFIG_SOC_ADC_SUPPORTED
|
||||||
|
case BUTTON_TYPE_ADC: {
|
||||||
|
const button_adc_config_t *cfg = &(config->adc_button_config);
|
||||||
|
ret = button_adc_init(cfg);
|
||||||
|
BTN_CHECK(ESP_OK == ret, "adc button init failed", NULL);
|
||||||
|
btn = button_create_com(1, button_adc_get_key_level, (void *)ADC_BUTTON_COMBINE(cfg->adc_channel, cfg->button_index), long_press_time, short_press_time);
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
|
case BUTTON_TYPE_MATRIX: {
|
||||||
|
const button_matrix_config_t *cfg = &(config->matrix_button_config);
|
||||||
|
ret = button_matrix_init(cfg);
|
||||||
|
BTN_CHECK(ESP_OK == ret, "matrix button init failed", NULL);
|
||||||
|
btn = button_create_com(1, button_matrix_get_key_level, (void *)MATRIX_BUTTON_COMBINE(cfg->row_gpio_num, cfg->col_gpio_num), long_press_time, short_press_time);
|
||||||
|
} break;
|
||||||
|
case BUTTON_TYPE_CUSTOM: {
|
||||||
|
if (config->custom_button_config.button_custom_init) {
|
||||||
|
ret = config->custom_button_config.button_custom_init(config->custom_button_config.priv);
|
||||||
|
BTN_CHECK(ESP_OK == ret, "custom button init failed", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
btn = button_create_com(config->custom_button_config.active_level,
|
||||||
|
config->custom_button_config.button_custom_get_key_value,
|
||||||
|
config->custom_button_config.priv,
|
||||||
|
long_press_time, short_press_time);
|
||||||
|
if (btn) {
|
||||||
|
btn->hal_button_deinit = config->custom_button_config.button_custom_deinit;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unsupported button type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BTN_CHECK(NULL != btn, "button create failed", NULL);
|
||||||
|
btn->type = config->type;
|
||||||
|
if (!btn->enable_power_save && !g_is_timer_running) {
|
||||||
|
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||||
|
g_is_timer_running = true;
|
||||||
|
}
|
||||||
|
return (button_handle_t)btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t iot_button_delete(button_handle_t btn_handle)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
button_dev_t *btn = (button_dev_t *)btn_handle;
|
||||||
|
switch (btn->type) {
|
||||||
|
case BUTTON_TYPE_GPIO:
|
||||||
|
ret = button_gpio_deinit((int)(btn->hardware_data));
|
||||||
|
break;
|
||||||
|
#if CONFIG_SOC_ADC_SUPPORTED
|
||||||
|
case BUTTON_TYPE_ADC:
|
||||||
|
ret = button_adc_deinit(ADC_BUTTON_SPLIT_CHANNEL(btn->hardware_data), ADC_BUTTON_SPLIT_INDEX(btn->hardware_data));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case BUTTON_TYPE_MATRIX:
|
||||||
|
ret = button_matrix_deinit(MATRIX_BUTTON_SPLIT_ROW(btn->hardware_data), MATRIX_BUTTON_SPLIT_COL(btn->hardware_data));
|
||||||
|
break;
|
||||||
|
case BUTTON_TYPE_CUSTOM:
|
||||||
|
if (btn->hal_button_deinit) {
|
||||||
|
ret = btn->hal_button_deinit(btn->hardware_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BTN_CHECK(ESP_OK == ret, "button deinit failed", ESP_FAIL);
|
||||||
|
for (int i = 0; i < BUTTON_EVENT_MAX; i++) {
|
||||||
|
if (btn->cb_info[i]) {
|
||||||
|
free(btn->cb_info[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button_delete_com(btn);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb, void *usr_data)
|
||||||
|
{
|
||||||
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||||
|
BTN_CHECK(event != BUTTON_MULTIPLE_CLICK, "event argument is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
button_event_config_t event_cfg = {
|
||||||
|
.event = event,
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && !event_cfg.event_data.long_press.press_time) {
|
||||||
|
event_cfg.event_data.long_press.press_time = btn->long_press_ticks * TICKS_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iot_button_register_event_cb(btn_handle, event_cfg, cb, usr_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t iot_button_register_event_cb(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb, void *usr_data)
|
||||||
|
{
|
||||||
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||||
|
button_event_t event = event_cfg.event;
|
||||||
|
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
BTN_CHECK(!(event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) || event_cfg.event_data.long_press.press_time > btn->short_press_ticks * TICKS_INTERVAL, "event_data is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
BTN_CHECK(event != BUTTON_MULTIPLE_CLICK || event_cfg.event_data.multiple_clicks.clicks, "event_data is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
if (!btn->cb_info[event]) {
|
if (!btn->cb_info[event]) {
|
||||||
btn->cb_info[event] = calloc(1, sizeof(button_cb_info_t));
|
btn->cb_info[event] = calloc(1, sizeof(button_cb_info_t));
|
||||||
|
|
@ -370,30 +573,27 @@ esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t even
|
||||||
btn->cb_info[event][btn->size[event]].usr_data = usr_data;
|
btn->cb_info[event][btn->size[event]].usr_data = usr_data;
|
||||||
btn->size[event]++;
|
btn->size[event]++;
|
||||||
|
|
||||||
/** Inserting the event_args in sorted manner */
|
/** Inserting the event_data in sorted manner */
|
||||||
if (event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) {
|
if (event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) {
|
||||||
uint16_t press_time = btn->long_press_ticks * TICKS_INTERVAL;
|
uint16_t press_time = event_cfg.event_data.long_press.press_time;
|
||||||
if (event_args) {
|
BTN_CHECK(press_time / TICKS_INTERVAL > btn->short_press_ticks, "press_time event_data is less than short_press_ticks", ESP_ERR_INVALID_ARG);
|
||||||
press_time = event_args->long_press.press_time;
|
|
||||||
}
|
|
||||||
BTN_CHECK(press_time / TICKS_INTERVAL > btn->short_press_ticks, "press_time event_args is less than short_press_ticks", ESP_ERR_INVALID_ARG);
|
|
||||||
if (btn->size[event] >= 2) {
|
if (btn->size[event] >= 2) {
|
||||||
for (int i = btn->size[event] - 2; i >= 0; i--) {
|
for (int i = btn->size[event] - 2; i >= 0; i--) {
|
||||||
if (btn->cb_info[event][i].event_args.long_press.press_time > press_time) {
|
if (btn->cb_info[event][i].event_data.long_press.press_time > press_time) {
|
||||||
btn->cb_info[event][i + 1] = btn->cb_info[event][i];
|
btn->cb_info[event][i + 1] = btn->cb_info[event][i];
|
||||||
|
|
||||||
btn->cb_info[event][i].event_args.long_press.press_time = press_time;
|
btn->cb_info[event][i].event_data.long_press.press_time = press_time;
|
||||||
btn->cb_info[event][i].cb = cb;
|
btn->cb_info[event][i].cb = cb;
|
||||||
btn->cb_info[event][i].usr_data = usr_data;
|
btn->cb_info[event][i].usr_data = usr_data;
|
||||||
} else {
|
} else {
|
||||||
btn->cb_info[event][i + 1].event_args.long_press.press_time = press_time;
|
btn->cb_info[event][i + 1].event_data.long_press.press_time = press_time;
|
||||||
btn->cb_info[event][i + 1].cb = cb;
|
btn->cb_info[event][i + 1].cb = cb;
|
||||||
btn->cb_info[event][i + 1].usr_data = usr_data;
|
btn->cb_info[event][i + 1].usr_data = usr_data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
btn->cb_info[event][btn->size[event] - 1].event_args.long_press.press_time = press_time;
|
btn->cb_info[event][btn->size[event] - 1].event_data.long_press.press_time = press_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t press_ticks = press_time / TICKS_INTERVAL;
|
int32_t press_ticks = press_time / TICKS_INTERVAL;
|
||||||
|
|
@ -403,52 +603,35 @@ esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t even
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == BUTTON_MULTIPLE_CLICK) {
|
if (event == BUTTON_MULTIPLE_CLICK) {
|
||||||
uint16_t clicks = btn->long_press_ticks * TICKS_INTERVAL;
|
|
||||||
if (event_args) {
|
|
||||||
clicks = event_args->multiple_clicks.clicks;
|
|
||||||
}
|
|
||||||
if (btn->size[event] >= 2) {
|
if (btn->size[event] >= 2) {
|
||||||
for (int i = btn->size[event] - 2; i >= 0; i--) {
|
for (int i = btn->size[event] - 2; i >= 0; i--) {
|
||||||
if (btn->cb_info[event][i].event_args.multiple_clicks.clicks > clicks) {
|
if (btn->cb_info[event][i].event_data.multiple_clicks.clicks > event_cfg.event_data.multiple_clicks.clicks) {
|
||||||
btn->cb_info[event][i + 1] = btn->cb_info[event][i];
|
btn->cb_info[event][i + 1] = btn->cb_info[event][i];
|
||||||
|
|
||||||
btn->cb_info[event][i].event_args.multiple_clicks.clicks = clicks;
|
btn->cb_info[event][i].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
|
||||||
btn->cb_info[event][i].cb = cb;
|
btn->cb_info[event][i].cb = cb;
|
||||||
btn->cb_info[event][i].usr_data = usr_data;
|
btn->cb_info[event][i].usr_data = usr_data;
|
||||||
} else {
|
} else {
|
||||||
btn->cb_info[event][i + 1].event_args.multiple_clicks.clicks = clicks;
|
btn->cb_info[event][i + 1].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
|
||||||
btn->cb_info[event][i + 1].cb = cb;
|
btn->cb_info[event][i + 1].cb = cb;
|
||||||
btn->cb_info[event][i + 1].usr_data = usr_data;
|
btn->cb_info[event][i + 1].usr_data = usr_data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
btn->cb_info[event][btn->size[event] - 1].event_args.multiple_clicks.clicks = clicks;
|
btn->cb_info[event][btn->size[event] - 1].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args)
|
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(NULL != btn_handle, ESP_ERR_INVALID_ARG, TAG, "Pointer of handle is invalid");
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||||
ESP_RETURN_ON_FALSE(event < BUTTON_EVENT_MAX, ESP_ERR_INVALID_ARG, TAG, "event is invalid");
|
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||||
ESP_RETURN_ON_FALSE(btn->cb_info[event], ESP_ERR_INVALID_STATE, TAG, "No callbacks registered for the event");
|
BTN_CHECK(NULL != btn->cb_info[event], "No callbacks registered for the event", ESP_ERR_INVALID_STATE);
|
||||||
|
|
||||||
int check = -1;
|
|
||||||
|
|
||||||
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && event_args) {
|
|
||||||
if (event_args->long_press.press_time != 0) {
|
|
||||||
goto unregister_event;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == BUTTON_MULTIPLE_CLICK && event_args) {
|
|
||||||
if (event_args->multiple_clicks.clicks != 0) {
|
|
||||||
goto unregister_event;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (btn->cb_info[event]) {
|
if (btn->cb_info[event]) {
|
||||||
free(btn->cb_info[event]);
|
free(btn->cb_info[event]);
|
||||||
|
|
@ -465,18 +648,28 @@ esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t ev
|
||||||
btn->cb_info[event] = NULL;
|
btn->cb_info[event] = NULL;
|
||||||
btn->size[event] = 0;
|
btn->size[event] = 0;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
unregister_event:
|
esp_err_t iot_button_unregister_event(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb)
|
||||||
|
{
|
||||||
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
button_event_t event = event_cfg.event;
|
||||||
|
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
BTN_CHECK(NULL != cb, "Pointer to function callback is invalid", ESP_ERR_INVALID_ARG);
|
||||||
|
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||||
|
|
||||||
|
int check = -1;
|
||||||
|
|
||||||
for (int i = 0; i < btn->size[event]; i++) {
|
for (int i = 0; i < btn->size[event]; i++) {
|
||||||
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && event_args->long_press.press_time) {
|
if (cb == btn->cb_info[event][i].cb) {
|
||||||
if (event_args->long_press.press_time != btn->cb_info[event][i].event_args.long_press.press_time) {
|
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && event_cfg.event_data.long_press.press_time) {
|
||||||
|
if (event_cfg.event_data.long_press.press_time != btn->cb_info[event][i].event_data.long_press.press_time) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == BUTTON_MULTIPLE_CLICK && event_args->multiple_clicks.clicks) {
|
if (event == BUTTON_MULTIPLE_CLICK && event_cfg.event_data.multiple_clicks.clicks) {
|
||||||
if (event_args->multiple_clicks.clicks != btn->cb_info[event][i].event_args.multiple_clicks.clicks) {
|
if (event_cfg.event_data.multiple_clicks.clicks != btn->cb_info[event][i].event_data.multiple_clicks.clicks) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -497,8 +690,10 @@ unregister_event:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BTN_CHECK(check != -1, "No such callback registered for the event", ESP_ERR_INVALID_STATE);
|
||||||
|
|
||||||
ESP_RETURN_ON_FALSE(check != -1, ESP_ERR_NOT_FOUND, TAG, "No such callback registered for the event");
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -515,7 +710,7 @@ size_t iot_button_count_cb(button_handle_t btn_handle)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t iot_button_count_event_cb(button_handle_t btn_handle, button_event_t event)
|
size_t iot_button_count_event(button_handle_t btn_handle, button_event_t event)
|
||||||
{
|
{
|
||||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||||
|
|
@ -550,18 +745,13 @@ uint8_t iot_button_get_repeat(button_handle_t btn_handle)
|
||||||
return btn->repeat;
|
return btn->repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t iot_button_get_pressed_time(button_handle_t btn_handle)
|
uint32_t iot_button_get_ticks_time(button_handle_t btn_handle)
|
||||||
{
|
{
|
||||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
||||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||||
return (btn->ticks * TICKS_INTERVAL);
|
return (btn->ticks * TICKS_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t iot_button_get_ticks_time(button_handle_t btn_handle)
|
|
||||||
{
|
|
||||||
return iot_button_get_pressed_time(btn_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t iot_button_get_long_press_hold_cnt(button_handle_t btn_handle)
|
uint16_t iot_button_get_long_press_hold_cnt(button_handle_t btn_handle)
|
||||||
{
|
{
|
||||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
||||||
|
|
@ -592,19 +782,18 @@ uint8_t iot_button_get_key_level(button_handle_t btn_handle)
|
||||||
{
|
{
|
||||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
||||||
button_dev_t *btn = (button_dev_t *)btn_handle;
|
button_dev_t *btn = (button_dev_t *)btn_handle;
|
||||||
uint8_t level = btn->driver->get_key_level(btn->driver);
|
uint8_t level = btn->hal_button_Level(btn->hardware_data);
|
||||||
return level;
|
return (level == btn->active_level) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t iot_button_resume(void)
|
esp_err_t iot_button_resume(void)
|
||||||
{
|
{
|
||||||
if (!g_button_timer_handle) {
|
BTN_CHECK(g_button_timer_handle, "Button timer handle is invalid", ESP_ERR_INVALID_STATE);
|
||||||
return ESP_ERR_INVALID_STATE;
|
BTN_CHECK(!g_is_timer_running, "Button timer is already running", ESP_ERR_INVALID_STATE);
|
||||||
}
|
|
||||||
if (!g_is_timer_running) {
|
esp_err_t err = esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||||
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
BTN_CHECK(ESP_OK == err, "Button timer start failed", ESP_FAIL);
|
||||||
g_is_timer_running = true;
|
g_is_timer_running = true;
|
||||||
}
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -619,6 +808,7 @@ esp_err_t iot_button_stop(void)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||||
esp_err_t iot_button_register_power_save_cb(const button_power_save_config_t *config)
|
esp_err_t iot_button_register_power_save_cb(const button_power_save_config_t *config)
|
||||||
{
|
{
|
||||||
BTN_CHECK(g_head_handle, "No button registered", ESP_ERR_INVALID_STATE);
|
BTN_CHECK(g_head_handle, "No button registered", ESP_ERR_INVALID_STATE);
|
||||||
|
|
@ -628,83 +818,4 @@ esp_err_t iot_button_register_power_save_cb(const button_power_save_config_t *co
|
||||||
power_save_usr_cfg.usr_data = config->usr_data;
|
power_save_usr_cfg.usr_data = config->usr_data;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
esp_err_t iot_button_create(const button_config_t *config, const button_driver_t *driver, button_handle_t *ret_button)
|
|
||||||
{
|
|
||||||
if (!g_head_handle) {
|
|
||||||
ESP_LOGI(TAG, "IoT Button Version: %d.%d.%d", BUTTON_VER_MAJOR, BUTTON_VER_MINOR, BUTTON_VER_PATCH);
|
|
||||||
}
|
|
||||||
ESP_RETURN_ON_FALSE(driver && config && ret_button, ESP_ERR_INVALID_ARG, TAG, "Invalid argument");
|
|
||||||
button_dev_t *btn = (button_dev_t *) calloc(1, sizeof(button_dev_t));
|
|
||||||
ESP_RETURN_ON_FALSE(btn, ESP_ERR_NO_MEM, TAG, "Button memory alloc failed");
|
|
||||||
|
|
||||||
btn->driver = (button_driver_t *)driver;
|
|
||||||
btn->long_press_ticks = TIME_TO_TICKS(config->long_press_time, LONG_TICKS);
|
|
||||||
btn->short_press_ticks = TIME_TO_TICKS(config->short_press_time, SHORT_TICKS);
|
|
||||||
btn->event = BUTTON_NONE_PRESS;
|
|
||||||
btn->button_level = BUTTON_INACTIVE;
|
|
||||||
|
|
||||||
btn->next = g_head_handle;
|
|
||||||
g_head_handle = btn;
|
|
||||||
|
|
||||||
if (!g_button_timer_handle) {
|
|
||||||
esp_timer_create_args_t button_timer = {0};
|
|
||||||
button_timer.arg = NULL;
|
|
||||||
button_timer.callback = button_cb;
|
|
||||||
button_timer.dispatch_method = ESP_TIMER_TASK;
|
|
||||||
button_timer.name = "button_timer";
|
|
||||||
esp_timer_create(&button_timer, &g_button_timer_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!driver->enable_power_save && !g_is_timer_running) {
|
|
||||||
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
|
||||||
g_is_timer_running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ret_button = (button_handle_t)btn;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t iot_button_delete(button_handle_t btn_handle)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_RETURN_ON_FALSE(NULL != btn_handle, ESP_ERR_INVALID_ARG, TAG, "Pointer of handle is invalid");
|
|
||||||
button_dev_t *btn = (button_dev_t *)btn_handle;
|
|
||||||
|
|
||||||
for (int i = 0; i < BUTTON_EVENT_MAX; i++) {
|
|
||||||
if (btn->cb_info[i]) {
|
|
||||||
free(btn->cb_info[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = btn->driver->del(btn->driver);
|
|
||||||
ESP_RETURN_ON_FALSE(ESP_OK == ret, ret, TAG, "Failed to delete button driver");
|
|
||||||
|
|
||||||
button_dev_t **curr;
|
|
||||||
for (curr = &g_head_handle; *curr;) {
|
|
||||||
button_dev_t *entry = *curr;
|
|
||||||
if (entry == btn) {
|
|
||||||
*curr = entry->next;
|
|
||||||
free(entry);
|
|
||||||
} else {
|
|
||||||
curr = &entry->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* count button number */
|
|
||||||
uint16_t number = 0;
|
|
||||||
button_dev_t *target = g_head_handle;
|
|
||||||
while (target) {
|
|
||||||
target = target->next;
|
|
||||||
number++;
|
|
||||||
}
|
|
||||||
ESP_LOGD(TAG, "remain btn number=%d", number);
|
|
||||||
|
|
||||||
if (0 == number && g_is_timer_running) { /**< if all button is deleted, stop the timer */
|
|
||||||
esp_timer_stop(g_button_timer_handle);
|
|
||||||
esp_timer_delete(g_button_timer_handle);
|
|
||||||
g_button_timer_handle = NULL;
|
|
||||||
g_is_timer_running = false;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
|
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
|
||||||
list(APPEND PRIVREQ esp_adc)
|
list(APPEND PRIVREQ esp_adc)
|
||||||
|
else()
|
||||||
|
list(APPEND PRIVREQ esp_adc_cal)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRC_DIRS "."
|
idf_component_register(SRC_DIRS "."
|
||||||
PRIV_INCLUDE_DIRS "."
|
PRIV_INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES esp_event unity test_utils button ${PRIVREQ}
|
PRIV_REQUIRES unity test_utils button ${PRIVREQ})
|
||||||
WHOLE_ARCHIVE)
|
|
||||||
|
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/queue.h"
|
|
||||||
#include "freertos/timers.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "esp_idf_version.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "unity.h"
|
|
||||||
#include "iot_button.h"
|
|
||||||
#include "button_adc.h"
|
|
||||||
|
|
||||||
static const char *TAG = "ADC BUTTON TEST";
|
|
||||||
|
|
||||||
static void button_event_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
button_event_t event = iot_button_get_event(arg);
|
|
||||||
ESP_LOGI(TAG, "BTN[%d] %s", (int)data, iot_button_get_event_str(event));
|
|
||||||
if (BUTTON_PRESS_REPEAT == event || BUTTON_PRESS_REPEAT_DONE == event) {
|
|
||||||
ESP_LOGI(TAG, "\tREPEAT[%d]", iot_button_get_repeat(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_PRESS_UP == event || BUTTON_LONG_PRESS_HOLD == event || BUTTON_LONG_PRESS_UP == event) {
|
|
||||||
ESP_LOGI(TAG, "\tPressed Time[%"PRIu32"]", iot_button_get_pressed_time(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_MULTIPLE_CLICK == event) {
|
|
||||||
ESP_LOGI(TAG, "\tMULTIPLE[%d]", (int)data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("adc button test", "[button][adc]")
|
|
||||||
{
|
|
||||||
/** ESP32-S3-Korvo2 board */
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
button_adc_config_t btn_adc_cfg = {
|
|
||||||
.unit_id = ADC_UNIT_1,
|
|
||||||
.adc_channel = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btns[6] = {NULL};
|
|
||||||
|
|
||||||
const uint16_t vol[6] = {380, 820, 1180, 1570, 1980, 2410};
|
|
||||||
for (size_t i = 0; i < 6; i++) {
|
|
||||||
btn_adc_cfg.button_index = i;
|
|
||||||
if (i == 0) {
|
|
||||||
btn_adc_cfg.min = (0 + vol[i]) / 2;
|
|
||||||
} else {
|
|
||||||
btn_adc_cfg.min = (vol[i - 1] + vol[i]) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 5) {
|
|
||||||
btn_adc_cfg.max = (vol[i] + 3000) / 2;
|
|
||||||
} else {
|
|
||||||
btn_adc_cfg.max = (vol[i] + vol[i + 1]) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t ret = iot_button_new_adc_device(&btn_cfg, &btn_adc_cfg, &btns[i]);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
TEST_ASSERT_NOT_NULL(btns[i]);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_DOWN, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_UP, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_REPEAT, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_REPEAT_DONE, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_SINGLE_CLICK, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_DOUBLE_CLICK, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_LONG_PRESS_START, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_LONG_PRESS_HOLD, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_LONG_PRESS_UP, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_END, NULL, button_event_cb, (void *)i);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 6; i++) {
|
|
||||||
iot_button_delete(btns[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("adc button test memory leak", "[button][adc][memory leak]")
|
|
||||||
{
|
|
||||||
/** ESP32-S3-Korvo2 board */
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
button_adc_config_t btn_adc_cfg = {
|
|
||||||
.unit_id = ADC_UNIT_1,
|
|
||||||
.adc_channel = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btns[6] = {NULL};
|
|
||||||
|
|
||||||
const uint16_t vol[6] = {380, 820, 1180, 1570, 1980, 2410};
|
|
||||||
for (size_t i = 0; i < 6; i++) {
|
|
||||||
btn_adc_cfg.button_index = i;
|
|
||||||
if (i == 0) {
|
|
||||||
btn_adc_cfg.min = (0 + vol[i]) / 2;
|
|
||||||
} else {
|
|
||||||
btn_adc_cfg.min = (vol[i - 1] + vol[i]) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 5) {
|
|
||||||
btn_adc_cfg.max = (vol[i] + 3000) / 2;
|
|
||||||
} else {
|
|
||||||
btn_adc_cfg.max = (vol[i] + vol[i + 1]) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t ret = iot_button_new_adc_device(&btn_cfg, &btn_adc_cfg, &btns[i]);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
|
|
||||||
TEST_ASSERT_NOT_NULL(btns[i]);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_DOWN, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_UP, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_REPEAT, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_REPEAT_DONE, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_SINGLE_CLICK, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_DOUBLE_CLICK, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_LONG_PRESS_START, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_LONG_PRESS_HOLD, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_LONG_PRESS_UP, NULL, button_event_cb, (void *)i);
|
|
||||||
iot_button_register_cb(btns[i], BUTTON_PRESS_END, NULL, button_event_cb, (void *)i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 6; i++) {
|
|
||||||
iot_button_delete(btns[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,288 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "unity.h"
|
|
||||||
#include "iot_button.h"
|
|
||||||
#include "button_gpio.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
|
|
||||||
static const char *TAG = "BUTTON AUTO TEST";
|
|
||||||
|
|
||||||
#define GPIO_OUTPUT_IO_45 45
|
|
||||||
#define BUTTON_IO_NUM 0
|
|
||||||
#define BUTTON_ACTIVE_LEVEL 0
|
|
||||||
|
|
||||||
static EventGroupHandle_t g_check = NULL;
|
|
||||||
static SemaphoreHandle_t g_auto_check_pass = NULL;
|
|
||||||
|
|
||||||
static button_event_t state = BUTTON_PRESS_DOWN;
|
|
||||||
|
|
||||||
static void button_auto_press_test_task(void *arg)
|
|
||||||
{
|
|
||||||
// test BUTTON_PRESS_DOWN
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
|
|
||||||
// // test BUTTON_PRESS_UP
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(200));
|
|
||||||
|
|
||||||
// test BUTTON_PRESS_REPEAT
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
|
|
||||||
// test BUTTON_PRESS_REPEAT_DONE
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(200));
|
|
||||||
|
|
||||||
// test BUTTON_SINGLE_CLICK
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(200));
|
|
||||||
|
|
||||||
// test BUTTON_DOUBLE_CLICK
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(200));
|
|
||||||
|
|
||||||
// test BUTTON_MULTIPLE_CLICK
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
|
|
||||||
// test BUTTON_LONG_PRESS_START
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1600));
|
|
||||||
|
|
||||||
// test BUTTON_LONG_PRESS_HOLD and BUTTON_LONG_PRESS_UP
|
|
||||||
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Auto Press Success!");
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
static void button_auto_check_cb_1(void *arg, void *data)
|
|
||||||
{
|
|
||||||
if (iot_button_get_event(arg) == state) {
|
|
||||||
xEventGroupSetBits(g_check, BIT(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void button_auto_check_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
if (iot_button_get_event(arg) == state) {
|
|
||||||
ESP_LOGI(TAG, "Auto check: button event %s pass", iot_button_get_event_str(state));
|
|
||||||
xEventGroupSetBits(g_check, BIT(0));
|
|
||||||
if (++state >= BUTTON_EVENT_MAX) {
|
|
||||||
xSemaphoreGive(g_auto_check_pass);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("gpio button auto-test", "[button][iot][auto]")
|
|
||||||
{
|
|
||||||
state = BUTTON_PRESS_DOWN;
|
|
||||||
g_check = xEventGroupCreate();
|
|
||||||
g_auto_check_pass = xSemaphoreCreateBinary();
|
|
||||||
xEventGroupSetBits(g_check, BIT(0) | BIT(1));
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
const button_gpio_config_t btn_gpio_cfg = {
|
|
||||||
.gpio_num = BUTTON_IO_NUM,
|
|
||||||
.active_level = BUTTON_ACTIVE_LEVEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btn = NULL;
|
|
||||||
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &btn);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
TEST_ASSERT_NOT_NULL(btn);
|
|
||||||
|
|
||||||
/* register iot_button callback for all the button_event */
|
|
||||||
for (uint8_t i = 0; i < BUTTON_EVENT_MAX; i++) {
|
|
||||||
if (i == BUTTON_MULTIPLE_CLICK) {
|
|
||||||
button_event_args_t args = {
|
|
||||||
.multiple_clicks.clicks = 4,
|
|
||||||
};
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_auto_check_cb_1, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_auto_check_cb, NULL);
|
|
||||||
} else {
|
|
||||||
iot_button_register_cb(btn, i, NULL, button_auto_check_cb_1, NULL);
|
|
||||||
iot_button_register_cb(btn, i, NULL, button_auto_check_cb, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, iot_button_set_param(btn, BUTTON_LONG_PRESS_TIME_MS, (void *)1500));
|
|
||||||
|
|
||||||
gpio_config_t io_conf = {
|
|
||||||
.intr_type = GPIO_INTR_DISABLE,
|
|
||||||
.mode = GPIO_MODE_OUTPUT,
|
|
||||||
.pin_bit_mask = (1ULL << GPIO_OUTPUT_IO_45),
|
|
||||||
.pull_down_en = 0,
|
|
||||||
.pull_up_en = 0,
|
|
||||||
};
|
|
||||||
gpio_config(&io_conf);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
|
|
||||||
xTaskCreate(button_auto_press_test_task, "button_auto_press_test_task", 1024 * 4, NULL, 10, NULL);
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(g_auto_check_pass, pdMS_TO_TICKS(6000)));
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < BUTTON_EVENT_MAX; i++) {
|
|
||||||
button_event_args_t args;
|
|
||||||
|
|
||||||
if (i == BUTTON_MULTIPLE_CLICK) {
|
|
||||||
args.multiple_clicks.clicks = 4;
|
|
||||||
iot_button_unregister_cb(btn, i, &args);
|
|
||||||
} else if (i == BUTTON_LONG_PRESS_UP || i == BUTTON_LONG_PRESS_START) {
|
|
||||||
args.long_press.press_time = 1500;
|
|
||||||
iot_button_unregister_cb(btn, i, &args);
|
|
||||||
} else {
|
|
||||||
iot_button_unregister_cb(btn, i, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, iot_button_delete(btn));
|
|
||||||
vEventGroupDelete(g_check);
|
|
||||||
vSemaphoreDelete(g_auto_check_pass);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TOLERANCE (CONFIG_BUTTON_PERIOD_TIME_MS * 4)
|
|
||||||
|
|
||||||
uint16_t long_press_time[5] = {2000, 2500, 3000, 3500, 4000};
|
|
||||||
static SemaphoreHandle_t long_press_check = NULL;
|
|
||||||
static SemaphoreHandle_t long_press_auto_check_pass = NULL;
|
|
||||||
unsigned int status = 0;
|
|
||||||
|
|
||||||
static void button_auto_long_press_test_task(void *arg)
|
|
||||||
{
|
|
||||||
// Test for BUTTON_LONG_PRESS_START
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
xSemaphoreTake(long_press_check, portMAX_DELAY);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
status = (BUTTON_LONG_PRESS_START << 16) | long_press_time[i];
|
|
||||||
if (i > 0) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(long_press_time[i] - long_press_time[i - 1]));
|
|
||||||
} else {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(long_press_time[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
xSemaphoreGive(long_press_auto_check_pass);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
// Test for BUTTON_LONG_PRESS_UP
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
xSemaphoreTake(long_press_check, portMAX_DELAY);
|
|
||||||
status = (BUTTON_LONG_PRESS_UP << 16) | long_press_time[i];
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(long_press_time[i] + 10));
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Auto Long Press Success!");
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void button_long_press_auto_check_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
uint32_t value = (uint32_t)data;
|
|
||||||
uint16_t event = (0xffff0000 & value) >> 16;
|
|
||||||
uint16_t time = 0xffff & value;
|
|
||||||
uint32_t pressed_time = iot_button_get_pressed_time(arg);
|
|
||||||
int32_t diff = pressed_time - time;
|
|
||||||
if (status == value && abs(diff) <= TOLERANCE) {
|
|
||||||
ESP_LOGI(TAG, "Auto check: button event: %s and time: %d pass", iot_button_get_event_str(event), time);
|
|
||||||
|
|
||||||
if (event == BUTTON_LONG_PRESS_UP && time == long_press_time[4]) {
|
|
||||||
xSemaphoreGive(long_press_auto_check_pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
xSemaphoreGive(long_press_check);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("gpio button long_press auto-test", "[button][long_press][auto]")
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Starting the test");
|
|
||||||
long_press_check = xSemaphoreCreateBinary();
|
|
||||||
long_press_auto_check_pass = xSemaphoreCreateBinary();
|
|
||||||
xSemaphoreGive(long_press_check);
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
const button_gpio_config_t btn_gpio_cfg = {
|
|
||||||
.gpio_num = BUTTON_IO_NUM,
|
|
||||||
.active_level = BUTTON_ACTIVE_LEVEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btn = NULL;
|
|
||||||
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &btn);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
TEST_ASSERT_NOT_NULL(btn);
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
button_event_args_t args = {
|
|
||||||
.long_press.press_time = long_press_time[i],
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t data = (BUTTON_LONG_PRESS_START << 16) | long_press_time[i];
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_START, &args, button_long_press_auto_check_cb, (void*)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_config_t io_conf = {
|
|
||||||
.intr_type = GPIO_INTR_DISABLE,
|
|
||||||
.mode = GPIO_MODE_OUTPUT,
|
|
||||||
.pin_bit_mask = (1ULL << GPIO_OUTPUT_IO_45),
|
|
||||||
.pull_down_en = 0,
|
|
||||||
.pull_up_en = 0,
|
|
||||||
};
|
|
||||||
gpio_config(&io_conf);
|
|
||||||
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
|
||||||
xTaskCreate(button_auto_long_press_test_task, "button_auto_long_press_test_task", 1024 * 4, NULL, 10, NULL);
|
|
||||||
|
|
||||||
xSemaphoreTake(long_press_auto_check_pass, portMAX_DELAY);
|
|
||||||
iot_button_unregister_cb(btn, BUTTON_LONG_PRESS_START, NULL);
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
button_event_args_t args = {
|
|
||||||
.long_press.press_time = long_press_time[i]
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t data = (BUTTON_LONG_PRESS_UP << 16) | long_press_time[i];
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, &args, button_long_press_auto_check_cb, (void*)data);
|
|
||||||
}
|
|
||||||
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(long_press_auto_check_pass, pdMS_TO_TICKS(17000)));
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, iot_button_delete(btn));
|
|
||||||
vSemaphoreDelete(long_press_check);
|
|
||||||
vSemaphoreDelete(long_press_auto_check_pass);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,743 @@
|
||||||
|
/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "freertos/timers.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "esp_idf_version.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "iot_button.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
static const char *TAG = "BUTTON TEST";
|
||||||
|
|
||||||
|
#define TEST_MEMORY_LEAK_THRESHOLD (-400)
|
||||||
|
#define BUTTON_IO_NUM 0
|
||||||
|
#define BUTTON_ACTIVE_LEVEL 0
|
||||||
|
#define BUTTON_NUM 16
|
||||||
|
|
||||||
|
static size_t before_free_8bit;
|
||||||
|
static size_t before_free_32bit;
|
||||||
|
static button_handle_t g_btns[BUTTON_NUM] = {0};
|
||||||
|
|
||||||
|
static int get_btn_index(button_handle_t btn)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < BUTTON_NUM; i++) {
|
||||||
|
if (btn == g_btns[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_press_down_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_HEX(BUTTON_PRESS_DOWN, iot_button_get_event(arg));
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_PRESS_DOWN", get_btn_index((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_press_up_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_HEX(BUTTON_PRESS_UP, iot_button_get_event(arg));
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_PRESS_UP[%"PRIu32"]", get_btn_index((button_handle_t)arg), iot_button_get_ticks_time((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_press_repeat_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_PRESS_REPEAT[%d]", get_btn_index((button_handle_t)arg), iot_button_get_repeat((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_single_click_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_HEX(BUTTON_SINGLE_CLICK, iot_button_get_event(arg));
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_SINGLE_CLICK", get_btn_index((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_double_click_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_HEX(BUTTON_DOUBLE_CLICK, iot_button_get_event(arg));
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_DOUBLE_CLICK", get_btn_index((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_long_press_start_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_HEX(BUTTON_LONG_PRESS_START, iot_button_get_event(arg));
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_LONG_PRESS_START", get_btn_index((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_long_press_hold_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_HEX(BUTTON_LONG_PRESS_HOLD, iot_button_get_event(arg));
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_LONG_PRESS_HOLD[%"PRIu32"],count is [%d]", get_btn_index((button_handle_t)arg), iot_button_get_ticks_time((button_handle_t)arg), iot_button_get_long_press_hold_cnt((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_press_repeat_done_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_HEX(BUTTON_PRESS_REPEAT_DONE, iot_button_get_event(arg));
|
||||||
|
ESP_LOGI(TAG, "BTN%d: BUTTON_PRESS_REPEAT_DONE[%d]", get_btn_index((button_handle_t)arg), iot_button_get_repeat((button_handle_t)arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t custom_button_gpio_init(void *param)
|
||||||
|
{
|
||||||
|
button_gpio_config_t *cfg = (button_gpio_config_t *)param;
|
||||||
|
|
||||||
|
return button_gpio_init(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t custom_button_gpio_get_key_value(void *param)
|
||||||
|
{
|
||||||
|
button_gpio_config_t *cfg = (button_gpio_config_t *)param;
|
||||||
|
|
||||||
|
return button_gpio_get_key_level((void *)cfg->gpio_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t custom_button_gpio_deinit(void *param)
|
||||||
|
{
|
||||||
|
button_gpio_config_t *cfg = (button_gpio_config_t *)param;
|
||||||
|
|
||||||
|
return button_gpio_deinit(cfg->gpio_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("custom button test", "[button][iot]")
|
||||||
|
{
|
||||||
|
button_gpio_config_t *gpio_cfg = calloc(1, sizeof(button_gpio_config_t));
|
||||||
|
gpio_cfg->active_level = 0;
|
||||||
|
gpio_cfg->gpio_num = 0;
|
||||||
|
|
||||||
|
button_config_t cfg = {
|
||||||
|
.type = BUTTON_TYPE_CUSTOM,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.custom_button_config = {
|
||||||
|
.button_custom_init = custom_button_gpio_init,
|
||||||
|
.button_custom_deinit = custom_button_gpio_deinit,
|
||||||
|
.button_custom_get_key_value = custom_button_gpio_get_key_value,
|
||||||
|
.active_level = 0,
|
||||||
|
.priv = gpio_cfg,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
g_btns[0] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[0]);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_DOWN, button_press_down_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_UP, button_press_up_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_REPEAT, button_press_repeat_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_SINGLE_CLICK, button_single_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_DOUBLE_CLICK, button_double_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_START, button_long_press_start_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_REPEAT_DONE, button_press_repeat_done_cb, NULL);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
iot_button_delete(g_btns[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("gpio button test", "[button][iot]")
|
||||||
|
{
|
||||||
|
button_config_t cfg = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.gpio_button_config = {
|
||||||
|
.gpio_num = 0,
|
||||||
|
.active_level = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
g_btns[0] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[0]);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_DOWN, button_press_down_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_UP, button_press_up_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_REPEAT, button_press_repeat_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_SINGLE_CLICK, button_single_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_DOUBLE_CLICK, button_double_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_START, button_long_press_start_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_REPEAT_DONE, button_press_repeat_done_cb, NULL);
|
||||||
|
|
||||||
|
uint8_t level = 0;
|
||||||
|
level = iot_button_get_key_level(g_btns[0]);
|
||||||
|
ESP_LOGI(TAG, "button level is %d", level);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
iot_button_delete(g_btns[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("gpio button get event test", "[button][iot]")
|
||||||
|
{
|
||||||
|
button_config_t cfg = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.gpio_button_config = {
|
||||||
|
.gpio_num = 0,
|
||||||
|
.active_level = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
g_btns[0] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[0]);
|
||||||
|
|
||||||
|
uint8_t level = 0;
|
||||||
|
level = iot_button_get_key_level(g_btns[0]);
|
||||||
|
ESP_LOGI(TAG, "button level is %d", level);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
button_event_t event = iot_button_get_event(g_btns[0]);
|
||||||
|
if (event != BUTTON_NONE_PRESS) {
|
||||||
|
ESP_LOGI(TAG, "event is %s", iot_button_get_event_str(event));
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
iot_button_delete(g_btns[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("gpio button test power save", "[button][iot][power save]")
|
||||||
|
{
|
||||||
|
button_config_t cfg = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.gpio_button_config = {
|
||||||
|
.gpio_num = 0,
|
||||||
|
.active_level = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
g_btns[0] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[0]);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_DOWN, button_press_down_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_UP, button_press_up_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_REPEAT, button_press_repeat_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_SINGLE_CLICK, button_single_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_DOUBLE_CLICK, button_double_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_START, button_long_press_start_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], BUTTON_PRESS_REPEAT_DONE, button_press_repeat_done_cb, NULL);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, iot_button_stop());
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, iot_button_resume());
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
iot_button_delete(g_btns[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("matrix keyboard button test", "[button][matrix key]")
|
||||||
|
{
|
||||||
|
int32_t row_gpio[4] = {4, 5, 6, 7};
|
||||||
|
int32_t col_gpio[4] = {3, 8, 16, 15};
|
||||||
|
button_config_t cfg = {
|
||||||
|
.type = BUTTON_TYPE_MATRIX,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.matrix_button_config = {
|
||||||
|
.row_gpio_num = 0,
|
||||||
|
.col_gpio_num = 0,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
cfg.matrix_button_config.row_gpio_num = row_gpio[i];
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
cfg.matrix_button_config.col_gpio_num = col_gpio[j];
|
||||||
|
g_btns[i * 4 + j] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[i * 4 + j]);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_PRESS_DOWN, button_press_down_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_PRESS_UP, button_press_up_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_PRESS_REPEAT, button_press_repeat_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_SINGLE_CLICK, button_single_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_DOUBLE_CLICK, button_double_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_LONG_PRESS_START, button_long_press_start_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i * 4 + j], BUTTON_PRESS_REPEAT_DONE, button_press_repeat_done_cb, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
iot_button_delete(g_btns[i * 4 + j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_SOC_ADC_SUPPORTED
|
||||||
|
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
TEST_CASE("adc button test", "[button][iot]")
|
||||||
|
{
|
||||||
|
/** ESP32-S3-Korvo board */
|
||||||
|
const uint16_t vol[6] = {380, 820, 1180, 1570, 1980, 2410};
|
||||||
|
button_config_t cfg = {0};
|
||||||
|
cfg.type = BUTTON_TYPE_ADC;
|
||||||
|
cfg.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS;
|
||||||
|
cfg.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS;
|
||||||
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
cfg.adc_button_config.adc_channel = 7,
|
||||||
|
cfg.adc_button_config.button_index = i;
|
||||||
|
if (i == 0) {
|
||||||
|
cfg.adc_button_config.min = (0 + vol[i]) / 2;
|
||||||
|
} else {
|
||||||
|
cfg.adc_button_config.min = (vol[i - 1] + vol[i]) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 5) {
|
||||||
|
cfg.adc_button_config.max = (vol[i] + 3000) / 2;
|
||||||
|
} else {
|
||||||
|
cfg.adc_button_config.max = (vol[i] + vol[i + 1]) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_btns[i] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[i]);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_DOWN, button_press_down_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_UP, button_press_up_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_REPEAT, button_press_repeat_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_SINGLE_CLICK, button_single_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_DOUBLE_CLICK, button_double_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_START, button_long_press_start_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_REPEAT_DONE, button_press_repeat_done_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
iot_button_delete(g_btns[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "esp_adc/adc_cali.h"
|
||||||
|
|
||||||
|
static esp_err_t adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
#define ADC_BUTTON_WIDTH SOC_ADC_RTC_MAX_BITWIDTH
|
||||||
|
#else
|
||||||
|
#define ADC_BUTTON_WIDTH ADC_WIDTH_MAX - 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
adc_cali_handle_t handle = NULL;
|
||||||
|
esp_err_t ret = ESP_FAIL;
|
||||||
|
bool calibrated = false;
|
||||||
|
|
||||||
|
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
|
||||||
|
if (!calibrated) {
|
||||||
|
ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
|
||||||
|
adc_cali_curve_fitting_config_t cali_config = {
|
||||||
|
.unit_id = unit,
|
||||||
|
.atten = atten,
|
||||||
|
.bitwidth = ADC_BUTTON_WIDTH,
|
||||||
|
};
|
||||||
|
ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
calibrated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
|
||||||
|
if (!calibrated) {
|
||||||
|
ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
|
||||||
|
adc_cali_line_fitting_config_t cali_config = {
|
||||||
|
.unit_id = unit,
|
||||||
|
.atten = atten,
|
||||||
|
.bitwidth = ADC_BUTTON_WIDTH,
|
||||||
|
};
|
||||||
|
ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
calibrated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*out_handle = handle;
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "Calibration Success");
|
||||||
|
} else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
|
||||||
|
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Invalid arg or no memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
return calibrated ? ESP_OK : ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("adc button idf5 drive test", "[button][iot]")
|
||||||
|
{
|
||||||
|
adc_oneshot_unit_handle_t adc1_handle;
|
||||||
|
adc_cali_handle_t adc1_cali_handle;
|
||||||
|
adc_oneshot_unit_init_cfg_t init_config = {
|
||||||
|
.unit_id = ADC_UNIT_1,
|
||||||
|
};
|
||||||
|
esp_err_t ret = adc_oneshot_new_unit(&init_config, &adc1_handle);
|
||||||
|
TEST_ASSERT_TRUE(ret == ESP_OK);
|
||||||
|
/*!< use atten 11db or 12db */
|
||||||
|
adc_calibration_init(ADC_UNIT_1, 3, &adc1_cali_handle);
|
||||||
|
|
||||||
|
/** ESP32-S3-Korvo board */
|
||||||
|
const uint16_t vol[6] = {380, 820, 1180, 1570, 1980, 2410};
|
||||||
|
button_config_t cfg = {0};
|
||||||
|
cfg.type = BUTTON_TYPE_ADC;
|
||||||
|
cfg.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS;
|
||||||
|
cfg.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS;
|
||||||
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
cfg.adc_button_config.adc_handle = &adc1_handle;
|
||||||
|
cfg.adc_button_config.adc_channel = 7,
|
||||||
|
cfg.adc_button_config.button_index = i;
|
||||||
|
if (i == 0) {
|
||||||
|
cfg.adc_button_config.min = (0 + vol[i]) / 2;
|
||||||
|
} else {
|
||||||
|
cfg.adc_button_config.min = (vol[i - 1] + vol[i]) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 5) {
|
||||||
|
cfg.adc_button_config.max = (vol[i] + 3000) / 2;
|
||||||
|
} else {
|
||||||
|
cfg.adc_button_config.max = (vol[i] + vol[i + 1]) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_btns[i] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[i]);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_DOWN, button_press_down_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_UP, button_press_up_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_REPEAT, button_press_repeat_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_SINGLE_CLICK, button_single_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_DOUBLE_CLICK, button_double_click_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_START, button_long_press_start_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb, NULL);
|
||||||
|
iot_button_register_cb(g_btns[i], BUTTON_PRESS_REPEAT_DONE, button_press_repeat_done_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
iot_button_delete(g_btns[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // CONFIG_SOC_ADC_SUPPORTED
|
||||||
|
|
||||||
|
#define GPIO_OUTPUT_IO_45 45
|
||||||
|
static EventGroupHandle_t g_check = NULL;
|
||||||
|
static SemaphoreHandle_t g_auto_check_pass = NULL;
|
||||||
|
|
||||||
|
static button_event_t state = BUTTON_PRESS_DOWN;
|
||||||
|
|
||||||
|
static void button_auto_press_test_task(void *arg)
|
||||||
|
{
|
||||||
|
// test BUTTON_PRESS_DOWN
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
|
||||||
|
// // test BUTTON_PRESS_UP
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(200));
|
||||||
|
|
||||||
|
// test BUTTON_PRESS_REPEAT
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
|
||||||
|
// test BUTTON_PRESS_REPEAT_DONE
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(200));
|
||||||
|
|
||||||
|
// test BUTTON_SINGLE_CLICK
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(200));
|
||||||
|
|
||||||
|
// test BUTTON_DOUBLE_CLICK
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(200));
|
||||||
|
|
||||||
|
// test BUTTON_MULTIPLE_CLICK
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
|
||||||
|
// test BUTTON_LONG_PRESS_START
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1600));
|
||||||
|
|
||||||
|
// test BUTTON_LONG_PRESS_HOLD and BUTTON_LONG_PRESS_UP
|
||||||
|
xEventGroupWaitBits(g_check, BIT(0) | BIT(1), pdTRUE, pdTRUE, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Auto Press Success!");
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
static void button_auto_check_cb_1(void *arg, void *data)
|
||||||
|
{
|
||||||
|
if (iot_button_get_event(g_btns[0]) == state) {
|
||||||
|
xEventGroupSetBits(g_check, BIT(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void button_auto_check_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
if (iot_button_get_event(g_btns[0]) == state) {
|
||||||
|
ESP_LOGI(TAG, "Auto check: button event %s pass", iot_button_get_event_str(state));
|
||||||
|
xEventGroupSetBits(g_check, BIT(0));
|
||||||
|
if (++state >= BUTTON_EVENT_MAX) {
|
||||||
|
xSemaphoreGive(g_auto_check_pass);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("gpio button auto-test", "[button][iot][auto]")
|
||||||
|
{
|
||||||
|
state = BUTTON_PRESS_DOWN;
|
||||||
|
g_check = xEventGroupCreate();
|
||||||
|
g_auto_check_pass = xSemaphoreCreateBinary();
|
||||||
|
xEventGroupSetBits(g_check, BIT(0) | BIT(1));
|
||||||
|
button_config_t cfg = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.gpio_button_config = {
|
||||||
|
.gpio_num = 0,
|
||||||
|
.active_level = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
g_btns[0] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[0]);
|
||||||
|
|
||||||
|
/* register iot_button callback for all the button_event */
|
||||||
|
for (uint8_t i = 0; i < BUTTON_EVENT_MAX; i++) {
|
||||||
|
if (i == BUTTON_MULTIPLE_CLICK) {
|
||||||
|
button_event_config_t btn_cfg;
|
||||||
|
btn_cfg.event = i;
|
||||||
|
btn_cfg.event_data.multiple_clicks.clicks = 4;
|
||||||
|
iot_button_register_event_cb(g_btns[0], btn_cfg, button_auto_check_cb_1, NULL);
|
||||||
|
iot_button_register_event_cb(g_btns[0], btn_cfg, button_auto_check_cb, NULL);
|
||||||
|
} else {
|
||||||
|
iot_button_register_cb(g_btns[0], i, button_auto_check_cb_1, NULL);
|
||||||
|
iot_button_register_cb(g_btns[0], i, button_auto_check_cb, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, iot_button_set_param(g_btns[0], BUTTON_LONG_PRESS_TIME_MS, (void *)1500));
|
||||||
|
|
||||||
|
gpio_config_t io_conf = {
|
||||||
|
.intr_type = GPIO_INTR_DISABLE,
|
||||||
|
.mode = GPIO_MODE_OUTPUT,
|
||||||
|
.pin_bit_mask = (1ULL << GPIO_OUTPUT_IO_45),
|
||||||
|
.pull_down_en = 0,
|
||||||
|
.pull_up_en = 0,
|
||||||
|
};
|
||||||
|
gpio_config(&io_conf);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
|
||||||
|
xTaskCreate(button_auto_press_test_task, "button_auto_press_test_task", 1024 * 4, NULL, 10, NULL);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(g_auto_check_pass, pdMS_TO_TICKS(6000)));
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < BUTTON_EVENT_MAX; i++) {
|
||||||
|
button_event_config_t btn_cfg;
|
||||||
|
btn_cfg.event = i;
|
||||||
|
if (i == BUTTON_MULTIPLE_CLICK) {
|
||||||
|
btn_cfg.event_data.multiple_clicks.clicks = 4;
|
||||||
|
} else if (i == BUTTON_LONG_PRESS_UP || i == BUTTON_LONG_PRESS_START) {
|
||||||
|
btn_cfg.event_data.long_press.press_time = 1500;
|
||||||
|
}
|
||||||
|
iot_button_unregister_event(g_btns[0], btn_cfg, button_auto_check_cb);
|
||||||
|
iot_button_unregister_event(g_btns[0], btn_cfg, button_auto_check_cb_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, iot_button_delete(g_btns[0]));
|
||||||
|
vEventGroupDelete(g_check);
|
||||||
|
vSemaphoreDelete(g_auto_check_pass);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TOLERANCE (CONFIG_BUTTON_PERIOD_TIME_MS * 4)
|
||||||
|
|
||||||
|
uint16_t long_press_time[5] = {2000, 2500, 3000, 3500, 4000};
|
||||||
|
static SemaphoreHandle_t long_press_check = NULL;
|
||||||
|
static SemaphoreHandle_t long_press_auto_check_pass = NULL;
|
||||||
|
unsigned int status = 0;
|
||||||
|
|
||||||
|
static void button_auto_long_press_test_task(void *arg)
|
||||||
|
{
|
||||||
|
// Test for BUTTON_LONG_PRESS_START
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
xSemaphoreTake(long_press_check, portMAX_DELAY);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
status = (BUTTON_LONG_PRESS_START << 16) | long_press_time[i];
|
||||||
|
if (i > 0) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(long_press_time[i] - long_press_time[i - 1]));
|
||||||
|
} else {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(long_press_time[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
xSemaphoreGive(long_press_auto_check_pass);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
// Test for BUTTON_LONG_PRESS_UP
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
xSemaphoreTake(long_press_check, portMAX_DELAY);
|
||||||
|
status = (BUTTON_LONG_PRESS_UP << 16) | long_press_time[i];
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(long_press_time[i] + 10));
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Auto Long Press Success!");
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_long_press_auto_check_cb(void *arg, void *data)
|
||||||
|
{
|
||||||
|
uint32_t value = (uint32_t)data;
|
||||||
|
uint16_t event = (0xffff0000 & value) >> 16;
|
||||||
|
uint16_t time = 0xffff & value;
|
||||||
|
uint32_t ticks_time = iot_button_get_ticks_time(g_btns[0]);
|
||||||
|
int32_t diff = ticks_time - time;
|
||||||
|
if (status == value && abs(diff) <= TOLERANCE) {
|
||||||
|
ESP_LOGI(TAG, "Auto check: button event: %s and time: %d pass", iot_button_get_event_str(state), time);
|
||||||
|
|
||||||
|
if (event == BUTTON_LONG_PRESS_UP && time == long_press_time[4]) {
|
||||||
|
xSemaphoreGive(long_press_auto_check_pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(long_press_check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("gpio button long_press auto-test", "[button][long_press][auto]")
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Starting the test");
|
||||||
|
long_press_check = xSemaphoreCreateBinary();
|
||||||
|
long_press_auto_check_pass = xSemaphoreCreateBinary();
|
||||||
|
xSemaphoreGive(long_press_check);
|
||||||
|
button_config_t cfg = {
|
||||||
|
.type = BUTTON_TYPE_GPIO,
|
||||||
|
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
|
||||||
|
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
|
||||||
|
.gpio_button_config = {
|
||||||
|
.gpio_num = 0,
|
||||||
|
.active_level = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
g_btns[0] = iot_button_create(&cfg);
|
||||||
|
TEST_ASSERT_NOT_NULL(g_btns[0]);
|
||||||
|
|
||||||
|
button_event_config_t btn_cfg;
|
||||||
|
btn_cfg.event = BUTTON_LONG_PRESS_START;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
btn_cfg.event_data.long_press.press_time = long_press_time[i];
|
||||||
|
uint32_t data = (btn_cfg.event << 16) | long_press_time[i];
|
||||||
|
iot_button_register_event_cb(g_btns[0], btn_cfg, button_long_press_auto_check_cb, (void*)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_config_t io_conf = {
|
||||||
|
.intr_type = GPIO_INTR_DISABLE,
|
||||||
|
.mode = GPIO_MODE_OUTPUT,
|
||||||
|
.pin_bit_mask = (1ULL << GPIO_OUTPUT_IO_45),
|
||||||
|
.pull_down_en = 0,
|
||||||
|
.pull_up_en = 0,
|
||||||
|
};
|
||||||
|
gpio_config(&io_conf);
|
||||||
|
gpio_set_level(GPIO_OUTPUT_IO_45, 1);
|
||||||
|
xTaskCreate(button_auto_long_press_test_task, "button_auto_long_press_test_task", 1024 * 4, NULL, 10, NULL);
|
||||||
|
|
||||||
|
xSemaphoreTake(long_press_auto_check_pass, portMAX_DELAY);
|
||||||
|
iot_button_unregister_cb(g_btns[0], BUTTON_LONG_PRESS_START);
|
||||||
|
btn_cfg.event = BUTTON_LONG_PRESS_UP;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
btn_cfg.event_data.long_press.press_time = long_press_time[i];
|
||||||
|
uint32_t data = (btn_cfg.event << 16) | long_press_time[i];
|
||||||
|
iot_button_register_event_cb(g_btns[0], btn_cfg, button_long_press_auto_check_cb, (void*)data);
|
||||||
|
}
|
||||||
|
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(long_press_auto_check_pass, pdMS_TO_TICKS(17000)));
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, iot_button_delete(g_btns[0]));
|
||||||
|
vSemaphoreDelete(long_press_check);
|
||||||
|
vSemaphoreDelete(long_press_auto_check_pass);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
||||||
|
{
|
||||||
|
ssize_t delta = after_free - before_free;
|
||||||
|
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
|
||||||
|
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp(void)
|
||||||
|
{
|
||||||
|
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||||
|
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void)
|
||||||
|
{
|
||||||
|
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||||
|
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||||
|
check_leak(before_free_8bit, after_free_8bit, "8BIT");
|
||||||
|
check_leak(before_free_32bit, after_free_32bit, "32BIT");
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* ____ _ _ _______ _
|
||||||
|
*| _ \ | | | | |__ __| | |
|
||||||
|
*| |_) | _ _ | |_ | |_ ___ _ __ | | ___ ___ | |_
|
||||||
|
*| _ < | | | || __|| __|/ _ \ | '_ \ | | / _ \/ __|| __|
|
||||||
|
*| |_) || |_| || |_ | |_| (_) || | | | | || __/\__ \| |_
|
||||||
|
*|____/ \__,_| \__| \__|\___/ |_| |_| |_| \___||___/ \__|
|
||||||
|
*/
|
||||||
|
printf(" ____ _ _ _______ _ \n");
|
||||||
|
printf(" | _ \\ | | | | |__ __| | | \n");
|
||||||
|
printf(" | |_) | _ _ | |_ | |_ ___ _ __ | | ___ ___ | |_ \n");
|
||||||
|
printf(" | _ < | | | || __|| __|/ _ \\ | '_ \\ | | / _ \\/ __|| __|\n");
|
||||||
|
printf(" | |_) || |_| || |_ | |_| (_) || | | | | || __/\\__ \\| |_ \n");
|
||||||
|
printf(" |____/ \\__,_| \\__| \\__|\\___/ |_| |_| |_| \\___||___/ \\__|\n");
|
||||||
|
unity_run_menu();
|
||||||
|
}
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "unity.h"
|
|
||||||
#include "unity_test_runner.h"
|
|
||||||
#include "unity_test_utils_memory.h"
|
|
||||||
#include "esp_heap_caps.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
#define LEAKS (400)
|
|
||||||
|
|
||||||
void setUp(void)
|
|
||||||
{
|
|
||||||
unity_utils_record_free_mem();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tearDown(void)
|
|
||||||
{
|
|
||||||
unity_utils_evaluate_leaks_direct(LEAKS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* ____ _ _ _______ _
|
|
||||||
*| _ \ | | | | |__ __| | |
|
|
||||||
*| |_) | _ _ | |_ | |_ ___ _ __ | | ___ ___ | |_
|
|
||||||
*| _ < | | | || __|| __|/ _ \ | '_ \ | | / _ \/ __|| __|
|
|
||||||
*| |_) || |_| || |_ | |_| (_) || | | | | || __/\__ \| |_
|
|
||||||
*|____/ \__,_| \__| \__|\___/ |_| |_| |_| \___||___/ \__|
|
|
||||||
*/
|
|
||||||
printf(" ____ _ _ _______ _ \n");
|
|
||||||
printf(" | _ \\ | | | | |__ __| | | \n");
|
|
||||||
printf(" | |_) | _ _ | |_ | |_ ___ _ __ | | ___ ___ | |_ \n");
|
|
||||||
printf(" | _ < | | | || __|| __|/ _ \\ | '_ \\ | | / _ \\/ __|| __|\n");
|
|
||||||
printf(" | |_) || |_| || |_ | |_| (_) || | | | | || __/\\__ \\| |_ \n");
|
|
||||||
printf(" |____/ \\__,_| \\__| \\__|\\___/ |_| |_| |_| \\___||___/ \\__|\n");
|
|
||||||
unity_run_menu();
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "unity.h"
|
|
||||||
#include "iot_button.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
|
|
||||||
static const char *TAG = "CUSTOM BUTTON TEST";
|
|
||||||
|
|
||||||
#define BUTTON_IO_NUM 0
|
|
||||||
#define BUTTON_ACTIVE_LEVEL 0
|
|
||||||
|
|
||||||
static void button_event_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
button_event_t event = iot_button_get_event(arg);
|
|
||||||
ESP_LOGI(TAG, "%s", iot_button_get_event_str(event));
|
|
||||||
if (BUTTON_PRESS_REPEAT == event || BUTTON_PRESS_REPEAT_DONE == event) {
|
|
||||||
ESP_LOGI(TAG, "\tREPEAT[%d]", iot_button_get_repeat(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_PRESS_UP == event || BUTTON_LONG_PRESS_HOLD == event || BUTTON_LONG_PRESS_UP == event) {
|
|
||||||
ESP_LOGI(TAG, "\tPressed Time[%"PRIu32"]", iot_button_get_pressed_time(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_MULTIPLE_CLICK == event) {
|
|
||||||
ESP_LOGI(TAG, "\tMULTIPLE[%d]", (int)data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
button_driver_t base;
|
|
||||||
int32_t gpio_num; /**< num of gpio */
|
|
||||||
uint8_t active_level; /**< gpio level when press down */
|
|
||||||
} custom_gpio_obj;
|
|
||||||
|
|
||||||
static uint8_t button_get_key_level(button_driver_t *button_driver)
|
|
||||||
{
|
|
||||||
custom_gpio_obj *custom_btn = __containerof(button_driver, custom_gpio_obj, base);
|
|
||||||
int level = gpio_get_level(custom_btn->gpio_num);
|
|
||||||
return level == custom_btn->active_level ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t button_del(button_driver_t *button_driver)
|
|
||||||
{
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("custom button test", "[button][custom]")
|
|
||||||
{
|
|
||||||
gpio_config_t gpio_conf = {
|
|
||||||
.pin_bit_mask = 1ULL << BUTTON_IO_NUM,
|
|
||||||
.mode = GPIO_MODE_INPUT,
|
|
||||||
.pull_up_en = 1,
|
|
||||||
.pull_down_en = 0,
|
|
||||||
.intr_type = GPIO_INTR_DISABLE,
|
|
||||||
};
|
|
||||||
gpio_config(&gpio_conf);
|
|
||||||
|
|
||||||
custom_gpio_obj *custom_btn = (custom_gpio_obj *)calloc(1, sizeof(custom_gpio_obj));
|
|
||||||
TEST_ASSERT_NOT_NULL(custom_btn);
|
|
||||||
custom_btn->active_level = BUTTON_ACTIVE_LEVEL;
|
|
||||||
custom_btn->gpio_num = BUTTON_IO_NUM;
|
|
||||||
|
|
||||||
button_handle_t btn = NULL;
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
custom_btn->base.get_key_level = button_get_key_level;
|
|
||||||
custom_btn->base.del = button_del;
|
|
||||||
esp_err_t ret = iot_button_create(&btn_cfg, &custom_btn->base, &btn);
|
|
||||||
TEST_ASSERT(ESP_OK == ret);
|
|
||||||
TEST_ASSERT_NOT_NULL(btn);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_DOWN, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT_DONE, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_SINGLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_DOUBLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
/*!< Multiple Click must provide button_event_args_t */
|
|
||||||
/*!< Double Click */
|
|
||||||
button_event_args_t args = {
|
|
||||||
.multiple_clicks.clicks = 2,
|
|
||||||
};
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)2);
|
|
||||||
/*!< Triple Click */
|
|
||||||
args.multiple_clicks.clicks = 3;
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)3);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_START, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_HOLD, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_END, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
iot_button_delete(btn);
|
|
||||||
}
|
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "unity.h"
|
|
||||||
#include "iot_button.h"
|
|
||||||
#include "button_gpio.h"
|
|
||||||
|
|
||||||
static const char *TAG = "GPIO BUTTON TEST";
|
|
||||||
|
|
||||||
#define BUTTON_IO_NUM 0
|
|
||||||
#define BUTTON_ACTIVE_LEVEL 0
|
|
||||||
|
|
||||||
static void button_event_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
button_event_t event = iot_button_get_event(arg);
|
|
||||||
ESP_LOGI(TAG, "%s", iot_button_get_event_str(event));
|
|
||||||
if (BUTTON_PRESS_REPEAT == event || BUTTON_PRESS_REPEAT_DONE == event) {
|
|
||||||
ESP_LOGI(TAG, "\tREPEAT[%d]", iot_button_get_repeat(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_PRESS_UP == event || BUTTON_LONG_PRESS_HOLD == event || BUTTON_LONG_PRESS_UP == event) {
|
|
||||||
ESP_LOGI(TAG, "\tPressed Time[%"PRIu32"]", iot_button_get_pressed_time(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_MULTIPLE_CLICK == event) {
|
|
||||||
ESP_LOGI(TAG, "\tMULTIPLE[%d]", (int)data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("gpio button test", "[button][gpio]")
|
|
||||||
{
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
const button_gpio_config_t btn_gpio_cfg = {
|
|
||||||
.gpio_num = BUTTON_IO_NUM,
|
|
||||||
.active_level = BUTTON_ACTIVE_LEVEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btn = NULL;
|
|
||||||
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &btn);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
TEST_ASSERT_NOT_NULL(btn);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_DOWN, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT_DONE, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_SINGLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_DOUBLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
/*!< Multiple Click must provide button_event_args_t */
|
|
||||||
/*!< Double Click */
|
|
||||||
button_event_args_t args = {
|
|
||||||
.multiple_clicks.clicks = 2,
|
|
||||||
};
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)2);
|
|
||||||
/*!< Triple Click */
|
|
||||||
args.multiple_clicks.clicks = 3;
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)3);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_START, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_HOLD, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_END, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
uint8_t level = 0;
|
|
||||||
level = iot_button_get_key_level(btn);
|
|
||||||
ESP_LOGI(TAG, "button level is %d", level);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
iot_button_delete(btn);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("gpio button get event test", "[button][gpio][event test]")
|
|
||||||
{
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
const button_gpio_config_t btn_gpio_cfg = {
|
|
||||||
.gpio_num = BUTTON_IO_NUM,
|
|
||||||
.active_level = BUTTON_ACTIVE_LEVEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btn = NULL;
|
|
||||||
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &btn);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
TEST_ASSERT_NOT_NULL(btn);
|
|
||||||
|
|
||||||
uint8_t level = 0;
|
|
||||||
level = iot_button_get_key_level(btn);
|
|
||||||
ESP_LOGI(TAG, "button level is %d", level);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
button_event_t event = iot_button_get_event(btn);
|
|
||||||
if (event != BUTTON_NONE_PRESS) {
|
|
||||||
ESP_LOGI(TAG, "event is %s", iot_button_get_event_str(event));
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
iot_button_delete(btn);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("gpio button test power save", "[button][gpio][power save]")
|
|
||||||
{
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
const button_gpio_config_t btn_gpio_cfg = {
|
|
||||||
.gpio_num = BUTTON_IO_NUM,
|
|
||||||
.active_level = BUTTON_ACTIVE_LEVEL,
|
|
||||||
.enable_power_save = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btn = NULL;
|
|
||||||
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &btn);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
TEST_ASSERT_NOT_NULL(btn);
|
|
||||||
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_DOWN, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT_DONE, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_SINGLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_DOUBLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
/*!< Multiple Click must provide button_event_args_t */
|
|
||||||
/*!< Double Click */
|
|
||||||
button_event_args_t args = {
|
|
||||||
.multiple_clicks.clicks = 2,
|
|
||||||
};
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)2);
|
|
||||||
/*!< Triple Click */
|
|
||||||
args.multiple_clicks.clicks = 3;
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)3);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_START, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_HOLD, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_END, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
iot_button_delete(btn);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("gpio button test memory leak", "[button][gpio][memory leak]")
|
|
||||||
{
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
const button_gpio_config_t btn_gpio_cfg = {
|
|
||||||
.gpio_num = BUTTON_IO_NUM,
|
|
||||||
.active_level = BUTTON_ACTIVE_LEVEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btn = NULL;
|
|
||||||
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &btn);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
TEST_ASSERT_NOT_NULL(btn);
|
|
||||||
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_DOWN, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_REPEAT_DONE, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_SINGLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_DOUBLE_CLICK, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
/*!< Multiple Click must provide button_event_args_t */
|
|
||||||
/*!< Double Click */
|
|
||||||
button_event_args_t args = {
|
|
||||||
.multiple_clicks.clicks = 2,
|
|
||||||
};
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)2);
|
|
||||||
/*!< Triple Click */
|
|
||||||
args.multiple_clicks.clicks = 3;
|
|
||||||
iot_button_register_cb(btn, BUTTON_MULTIPLE_CLICK, &args, button_event_cb, (void *)3);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_START, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_HOLD, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, NULL, button_event_cb, NULL);
|
|
||||||
iot_button_register_cb(btn, BUTTON_PRESS_END, NULL, button_event_cb, NULL);
|
|
||||||
|
|
||||||
iot_button_delete(btn);
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "unity.h"
|
|
||||||
#include "iot_button.h"
|
|
||||||
#include "button_matrix.h"
|
|
||||||
|
|
||||||
static const char *TAG = "MATRIX BUTTON TEST";
|
|
||||||
|
|
||||||
static void button_event_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
button_event_t event = iot_button_get_event(arg);
|
|
||||||
ESP_LOGI(TAG, "BUTTON[%d] %s", (int)data, iot_button_get_event_str(event));
|
|
||||||
if (BUTTON_PRESS_REPEAT == event || BUTTON_PRESS_REPEAT_DONE == event) {
|
|
||||||
ESP_LOGI(TAG, "\tREPEAT[%d]", iot_button_get_repeat(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_PRESS_UP == event || BUTTON_LONG_PRESS_HOLD == event || BUTTON_LONG_PRESS_UP == event) {
|
|
||||||
ESP_LOGI(TAG, "\tPressed Time[%"PRIu32"]", iot_button_get_pressed_time(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUTTON_MULTIPLE_CLICK == event) {
|
|
||||||
ESP_LOGI(TAG, "\tMULTIPLE[%d]", (int)data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("matrix keyboard button test", "[button][matrix key]")
|
|
||||||
{
|
|
||||||
const button_config_t btn_cfg = {0};
|
|
||||||
const button_matrix_config_t matrix_cfg = {
|
|
||||||
.row_gpios = (int32_t[]){4, 5, 6, 7},
|
|
||||||
.col_gpios = (int32_t[]){3, 8, 16, 15},
|
|
||||||
.row_gpio_num = 4,
|
|
||||||
.col_gpio_num = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
button_handle_t btns[16] = {0};
|
|
||||||
size_t btn_num = 16;
|
|
||||||
esp_err_t ret = iot_button_new_matrix_device(&btn_cfg, &matrix_cfg, btns, &btn_num);
|
|
||||||
TEST_ASSERT(ret == ESP_OK);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
int index = i * 4 + j;
|
|
||||||
TEST_ASSERT_NOT_NULL(btns[index]);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_PRESS_DOWN, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_PRESS_UP, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_PRESS_REPEAT, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_PRESS_REPEAT_DONE, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_SINGLE_CLICK, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_DOUBLE_CLICK, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_LONG_PRESS_START, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_LONG_PRESS_HOLD, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_LONG_PRESS_UP, NULL, button_event_cb, (void *)index);
|
|
||||||
iot_button_register_cb(btns[index], BUTTON_PRESS_END, NULL, button_event_cb, (void *)index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
iot_button_delete(btns[i * 4 + j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE=y
|
||||||
|
|
@ -1 +1 @@
|
||||||
05165f30922b422b4b90c08845e6d449329b97370fbd06309803d8cb539d79e3
|
351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
|
||||||
|
|
@ -1,15 +1,3 @@
|
||||||
## v1.1.1 - 2025-02-25
|
|
||||||
|
|
||||||
* relinker: some typo
|
|
||||||
* relinker: add CI for relinker func
|
|
||||||
* relinker: relinker.py:76: SyntaxWarning: invalid escape sequence '('
|
|
||||||
* relinker: incorrect IDF_VERSION for IDF 5.0
|
|
||||||
|
|
||||||
## v1.1.0 - 2025-01-16
|
|
||||||
|
|
||||||
* relinker: support ESP32-C3 and SRAM optimization for flash-suspend
|
|
||||||
* relinker: add IDF v5.3.x support
|
|
||||||
|
|
||||||
## v0.5.3 - 2023-09-15
|
## v0.5.3 - 2023-09-15
|
||||||
|
|
||||||
* fix `add_dependencies called with incorrect number of arguments` in `relinker.cmake`
|
* fix `add_dependencies called with incorrect number of arguments` in `relinker.cmake`
|
||||||
|
|
@ -27,10 +15,6 @@
|
||||||
|
|
||||||
* Add GCC LTO support
|
* Add GCC LTO support
|
||||||
|
|
||||||
## v0.4.9 - 2023-7-26
|
|
||||||
|
|
||||||
* gen_compressed_ota: Update the document to use the default V3 version compression format.
|
|
||||||
|
|
||||||
## v0.4.8 - 2023-05-24
|
## v0.4.8 - 2023-05-24
|
||||||
|
|
||||||
* Add unit test app
|
* Add unit test app
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,6 @@ menu "CMake Utilities"
|
||||||
"Enable this option to print error information instead of
|
"Enable this option to print error information instead of
|
||||||
throwing exception when missing function"
|
throwing exception when missing function"
|
||||||
|
|
||||||
config CU_RELINKER_LINK_SPECIFIC_FUNCTIONS_TO_IRAM
|
|
||||||
bool "Link specific functions to IRAM regardless of ESP-IDF's behavior"
|
|
||||||
default n
|
|
||||||
depends on SPI_FLASH_AUTO_SUSPEND
|
|
||||||
help
|
|
||||||
"Enable this option, although functions' attribution
|
|
||||||
are IRAM_ATTR, or configured to be noflash by link.lf, they will
|
|
||||||
not be linked into IRAM. Only functions specified by relinker
|
|
||||||
configuration file will be linked into IRAM."
|
|
||||||
|
|
||||||
|
|
||||||
config CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES
|
config CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES
|
||||||
bool "Enable customized relinker configuration files"
|
bool "Enable customized relinker configuration files"
|
||||||
default n
|
default n
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,28 @@
|
||||||
|
|
||||||
This component is aiming to provide some useful CMake utilities outside of ESP-IDF.
|
This component is aiming to provide some useful CMake utilities outside of ESP-IDF.
|
||||||
|
|
||||||
**Supported features:**
|
## Use
|
||||||
|
|
||||||
- `project_include.cmake`: add additional features like `DIAGNOSTICS_COLOR` to the project. The file will be automatically parsed, for details, please refer [project-include-cmake](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/build-system.html#project-include-cmake>).
|
1. Add dependency of this component in your component or project's idf_component.yml.
|
||||||
- `package_manager.cmake`: provides functions to manager components' versions, etc.
|
|
||||||
- `gcc.cmake`: manager the GCC compiler options like `LTO` through menuconfig.
|
|
||||||
- `relinker.cmake` provides a way to move IRAM functions to flash to save RAM space.
|
|
||||||
- `gen_compressed_ota.cmake`: add new command `idf.py gen_compressed_ota` to generate `xz` compressed OTA binary. please refer [xz](https://github.com/espressif/esp-iot-solution/tree/master/components/utilities/xz).
|
|
||||||
- `gen_single_bin.cmake`: add new command `idf.py gen_single_bin` to generate single combined bin file (combine app, bootloader, partition table, etc).
|
|
||||||
|
|
||||||
## User Guide
|
```yml
|
||||||
|
dependencies:
|
||||||
|
espressif/cmake_utilities: "0.*"
|
||||||
|
```
|
||||||
|
|
||||||
[cmake_utilities user guide](https://docs.espressif.com/projects/esp-iot-solution/zh_CN/latest/basic/cmake_utilities.html)
|
2. Include the CMake file you need in your component's CMakeLists.txt after `idf_component_register`, or in your project's CMakeLists.txt
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
// Note: should remove .cmake postfix when using include(), otherwise the requested file will not found
|
||||||
|
// Note: should place this line after `idf_component_register` function
|
||||||
|
// only include the one you needed.
|
||||||
|
include(package_manager)
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Then you can use the corresponding CMake function which is provided by the CMake file.
|
||||||
|
|
||||||
|
## Supported features
|
||||||
|
|
||||||
|
1. [relinker](https://github.com/espressif/esp-iot-solution/blob/master/tools/cmake_utilities/docs/relinker.md)
|
||||||
|
2. [gen_compressed_ota](https://github.com/espressif/esp-iot-solution/blob/master/tools/cmake_utilities/docs/gen_compressed_ota.md)
|
||||||
|
3. [GCC Optimization](https://github.com/espressif/esp-iot-solution/blob/master/tools/cmake_utilities/docs/gcc.md)
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,6 @@ simple_ota.bin.xz.packed.signed
|
||||||
|
|
||||||
you can also use the script [gen_custom_ota.py](https://github.com/espressif/esp-iot-solution/tree/master/tools/cmake_utilities/scripts/gen_custom_ota.py) to compress the specified app:
|
you can also use the script [gen_custom_ota.py](https://github.com/espressif/esp-iot-solution/tree/master/tools/cmake_utilities/scripts/gen_custom_ota.py) to compress the specified app:
|
||||||
|
|
||||||
```plaintext
|
|
||||||
python3 gen_custom_ota.py -hv v3 -i simple_ota.bin --add_app_header
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
1. Command tool [gen_custom_ota.py](https://github.com/espressif/esp-iot-solution/tree/master/tools/cmake_utilities/scripts/gen_custom_ota.py) can also be used to generate the compressed firmware required by [esp bootloader plus](https://github.com/espressif/esp-bootloader-plus):
|
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
python3 gen_custom_ota.py -i simple_ota.bin
|
python3 gen_custom_ota.py -i simple_ota.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `python3 gen_custom_ota.py -h` to see a summary of all available command line options.
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
In ESP-IDF, some functions are put in SRAM when link stage, the reason is that some functions are critical, we need to put them in SRAM to speed up the program, or the functions will be executed when the cache is disabled. But actually, some functions can be put into Flash, here, we provide a script to let the user set the functions which are located in SRAM by default to put them into Flash, in order to save more SRAM which can be used as heap region later. This happens in the linker stage, so we call it as relinker.
|
In ESP-IDF, some functions are put in SRAM when link stage, the reason is that some functions are critical, we need to put them in SRAM to speed up the program, or the functions will be executed when the cache is disabled. But actually, some functions can be put into Flash, here, we provide a script to let the user set the functions which are located in SRAM by default to put them into Flash, in order to save more SRAM which can be used as heap region later. This happens in the linker stage, so we call it as relinker.
|
||||||
|
|
||||||
Some SoCs(ESP32-C2 and ESP32-C3) support hardware auto flash-suspend, meaning when reading, writing, or erasing the flash stage, the CPU hardware can switch to run code laying in the flash automatically without any software assist, so that we can link more functions from IRAM to flash.
|
|
||||||
|
|
||||||
## Use
|
## Use
|
||||||
|
|
||||||
In order to use this feature, you need to include the needed CMake file in your project's CMakeLists.txt after `project(XXXX)`.
|
In order to use this feature, you need to include the needed CMake file in your project's CMakeLists.txt after `project(XXXX)`.
|
||||||
|
|
@ -16,52 +14,28 @@ include(relinker)
|
||||||
|
|
||||||
The relinker feature is disabled by default, in order to use it, you need to enable the option `CU_RELINKER_ENABLE` in menuconfig.
|
The relinker feature is disabled by default, in order to use it, you need to enable the option `CU_RELINKER_ENABLE` in menuconfig.
|
||||||
|
|
||||||
Here are the default configuration files in the folder `cmake_utilities/scripts/relinker/examples/flash_suspend/XXX (XXX=esp32c2, esp32c3...)` for specific SoC platform when flash_suspend and relinker feature are enabled, please note that the configuration files may be slightly different for different ESP-IDF versions, it's just used as a reference. If you would like to use your own configuration files, please enable option `CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES` and set the path of your configuration files as following, this path is evaluated relative to the project root directory:
|
Here are the default configuration files in the folder `cmake_utilities/scripts/relinker/examples/esp32c2`, it's just used as a reference. If you would like to use your own configuration files, please enable option `CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES` and set the path of your configuration files as following, this path is evaluated relative to the project root directory:
|
||||||
|
|
||||||
```
|
```
|
||||||
[*] Enable customized relinker configuration files
|
[*] Enable customized relinker configuration files
|
||||||
(path of your configuration files) Customized relinker configuration files path
|
(path of your configuration files) Customized relinker configuration files path
|
||||||
```
|
```
|
||||||
|
|
||||||
If you would like to save more RAM, you can try flash-suspend feature, enable options as following:
|
> Note: Currently only esp32c2 is supported.
|
||||||
|
|
||||||
```
|
|
||||||
Component config --->
|
|
||||||
SPI Flash driver --->
|
|
||||||
[ ] Use esp_flash implementation in ROM
|
|
||||||
[*] Auto suspend long erase/write operations (READ DOCS FIRST)
|
|
||||||
|
|
||||||
CMake Utilities --->
|
|
||||||
[*] Enable relinker
|
|
||||||
[*] Link specific functions to IRAM regardless of ESP-IDF's behavior
|
|
||||||
```
|
|
||||||
|
|
||||||
> Note: Currently supported platform: esp32c2 and esp32c3.
|
|
||||||
> Note: Before enable flash-suspend, please check if ESP-IDF supports this flash's flash-suspend feature.
|
|
||||||
|
|
||||||
## Configuration Files
|
## Configuration Files
|
||||||
|
|
||||||
You can refer to the files in the directory of `cmake_utilities/scripts/relinker/examples/$ACTION/XXX ($ACTION=iram_strip, flash_suspend) (XXX=esp32c2, esp32c3...)`:
|
You can refer to the files in the directory of `cmake_utilities/scripts/relinker/examples/esp32c2`:
|
||||||
|
|
||||||
- library.csv
|
- library.csv
|
||||||
- object.csv
|
- object.csv
|
||||||
- function.csv
|
- function.csv
|
||||||
|
|
||||||
1. iram_strip
|
For example, if you want to link function `__getreent` from SRAM to Flash, firstly you should add it to `function.csv` file as following:
|
||||||
|
|
||||||
For `example/iram_strip`, it includes the functions which you want to relink into Flash after enable the option `CU_RELINKER_ENABLE` and disable the option `CU_RELINKER_LINK_SPECIFIC_FUNCTIONS_TO_IRAM` in menuconfig. If you want to link function `__getreent` from SRAM to Flash, firstly you should add it to `function.csv` file as following:
|
```
|
||||||
|
libfreertos.a,tasks.c.obj,__getreent,
|
||||||
```
|
```
|
||||||
libfreertos.a,tasks.c.obj,__getreent,
|
|
||||||
```
|
|
||||||
|
|
||||||
2. flash_suspend
|
|
||||||
|
|
||||||
For `example/flash_suspend`, it includes the functions which you want to relink into SRAM after enable the options: `SPI_FLASH_AUTO_SUSPEND`, `CU_RELINKER_ENABLE`, `CU_RELINKER_LINK_SPECIFIC_FUNCTIONS_TO_IRAM` in menuconfig. If you want to link function `__getreent` into SRAM no matter its original locations, firstly you should add it to `function.csv` file as following:
|
|
||||||
|
|
||||||
```
|
|
||||||
libfreertos.a,tasks.c.obj,__getreent,
|
|
||||||
```
|
|
||||||
|
|
||||||
This means function `__getreent` is in object file `tasks.c.obj`, and object file `tasks.c.obj` is in library `libfreertos.a`.
|
This means function `__getreent` is in object file `tasks.c.obj`, and object file `tasks.c.obj` is in library `libfreertos.a`.
|
||||||
|
|
||||||
|
|
@ -90,13 +64,3 @@ libfreertos.a,./esp-idf/freertos/libfreertos.a
|
||||||
This means library `libfreertos.a`'s location is `./esp-idf/freertos/libfreertos.a` relative to `build`.
|
This means library `libfreertos.a`'s location is `./esp-idf/freertos/libfreertos.a` relative to `build`.
|
||||||
|
|
||||||
If above related data has exists in corresponding files, please don't add this repeatedly.
|
If above related data has exists in corresponding files, please don't add this repeatedly.
|
||||||
|
|
||||||
## Test Results Reference
|
|
||||||
|
|
||||||
| Chip | example | | SRAM used (Bytes) | |
|
|
||||||
| -------- | --------------- | ----------------- | ----------------- | --------------------------------- |
|
|
||||||
| | | Default options | Enable relinker | Enable relinker and flash-suspend |
|
|
||||||
| ESP32-C2 | power_save | 101408 | 91728 | 51360 |
|
|
||||||
| ESP32-C3 | power_save | 118728 | 99864 | 58312 |
|
|
||||||
|
|
||||||
All of the above examples are compiled on ESP-IDF Tag/v5.3.2 and version v1.1.0 of `cmake_utilities` component, you can view the memory type usage summary by using `idf.py size`, the above data is for reference only.
|
|
||||||
|
|
@ -12,7 +12,7 @@ if (NOT TARGET gen_compressed_ota)
|
||||||
add_custom_command(TARGET gen_compressed_ota
|
add_custom_command(TARGET gen_compressed_ota
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND ${PYTHON} ${GEN_COMPRESSED_BIN_CMD}
|
COMMAND ${PYTHON} ${GEN_COMPRESSED_BIN_CMD}
|
||||||
COMMENT "The gen compressed bin cmd is: ${GEN_COMPRESSED_BIN_CMD}"
|
COMMENT "The gen compresssed bin cmd is: ${GEN_COMPRESSED_BIN_CMD}"
|
||||||
)
|
)
|
||||||
add_dependencies(gen_compressed_ota gen_project_binary)
|
add_dependencies(gen_compressed_ota gen_project_binary)
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
idf: '>=4.1'
|
idf:
|
||||||
|
version: '>=4.1'
|
||||||
description: A collection of useful cmake utilities
|
description: A collection of useful cmake utilities
|
||||||
documentation: https://docs.espressif.com/projects/esp-iot-solution/zh_CN/latest/basic/cmake_utilities.html
|
|
||||||
issues: https://github.com/espressif/esp-iot-solution/issues
|
issues: https://github.com/espressif/esp-iot-solution/issues
|
||||||
repository: git://github.com/espressif/esp-iot-solution.git
|
|
||||||
repository_info:
|
|
||||||
commit_sha: 05f51bd7044e9f95bc978093fc78656e4d81cd37
|
|
||||||
path: tools/cmake_utilities
|
|
||||||
url: https://github.com/espressif/esp-iot-solution/tree/master/tools/cmake_utilities
|
url: https://github.com/espressif/esp-iot-solution/tree/master/tools/cmake_utilities
|
||||||
version: 1.1.1
|
version: 0.5.3
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,10 @@ if(CONFIG_CU_RELINKER_ENABLE)
|
||||||
message(STATUS "Relinker is enabled.")
|
message(STATUS "Relinker is enabled.")
|
||||||
if(CONFIG_IDF_TARGET_ESP32C2)
|
if(CONFIG_IDF_TARGET_ESP32C2)
|
||||||
set(target "esp32c2")
|
set(target "esp32c2")
|
||||||
elseif(CONFIG_IDF_TARGET_ESP32C3)
|
|
||||||
set(target "esp32c3")
|
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Other targets are not supported.")
|
message(FATAL_ERROR "Other targets are not supported.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(idf_version "$ENV{IDF_VERSION}")
|
|
||||||
string(REGEX MATCH "^([0-9]+\\.[0-9]+)" version_prefix "${idf_version}")
|
|
||||||
|
|
||||||
if(CONFIG_CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES)
|
if(CONFIG_CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES)
|
||||||
idf_build_get_property(project_dir PROJECT_DIR)
|
idf_build_get_property(project_dir PROJECT_DIR)
|
||||||
get_filename_component(cfg_file_path "${CONFIG_CU_RELINKER_CUSTOMIZED_CONFIGURATION_FILES_PATH}"
|
get_filename_component(cfg_file_path "${CONFIG_CU_RELINKER_CUSTOMIZED_CONFIGURATION_FILES_PATH}"
|
||||||
|
|
@ -25,15 +20,7 @@ if(CONFIG_CU_RELINKER_ENABLE)
|
||||||
else()
|
else()
|
||||||
set(cfg_file_path ${PROJECT_DIR}/relinker/${target})
|
set(cfg_file_path ${PROJECT_DIR}/relinker/${target})
|
||||||
if(NOT EXISTS ${cfg_file_path})
|
if(NOT EXISTS ${cfg_file_path})
|
||||||
if(version_prefix STREQUAL "5.0" OR version_prefix STREQUAL "5.3")
|
set(cfg_file_path ${CMAKE_CURRENT_LIST_DIR}/scripts/relinker/examples/${target})
|
||||||
if(CONFIG_CU_RELINKER_LINK_SPECIFIC_FUNCTIONS_TO_IRAM)
|
|
||||||
set(cfg_file_path ${CMAKE_CURRENT_LIST_DIR}/scripts/relinker/examples/flash_suspend/${target}/${version_prefix})
|
|
||||||
else()
|
|
||||||
set(cfg_file_path ${CMAKE_CURRENT_LIST_DIR}/scripts/relinker/examples/iram_strip/${target}/${version_prefix})
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "There is no configuration file corresponding to esp-idf/v${version_prefix}, please make a request in github issue")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
@ -55,16 +42,10 @@ if(CONFIG_CU_RELINKER_ENABLE)
|
||||||
--object ${object_file}
|
--object ${object_file}
|
||||||
--function ${function_file}
|
--function ${function_file}
|
||||||
--sdkconfig ${sdkconfig}
|
--sdkconfig ${sdkconfig}
|
||||||
--target ${target}
|
|
||||||
--version ${version_prefix}
|
|
||||||
--objdump ${cmake_objdump})
|
--objdump ${cmake_objdump})
|
||||||
|
|
||||||
if(CONFIG_CU_RELINKER_ENABLE_PRINT_ERROR_INFO_WHEN_MISSING_FUNCTION)
|
if(CONFIG_CU_RELINKER_ENABLE_PRINT_ERROR_INFO_WHEN_MISSING_FUNCTION)
|
||||||
list(APPEND relinker_opts --missing_function_info)
|
list(APPEND relinker_opts --missing_function_info True)
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CONFIG_CU_RELINKER_LINK_SPECIFIC_FUNCTIONS_TO_IRAM)
|
|
||||||
list(APPEND relinker_opts --link_to_iram)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_build_get_property(link_depends __LINK_DEPENDS)
|
idf_build_get_property(link_depends __LINK_DEPENDS)
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ def xz_compress(store_directory, in_file):
|
||||||
os.remove(compressed_file)
|
os.remove(compressed_file)
|
||||||
|
|
||||||
xz_compressor_filter = [
|
xz_compressor_filter = [
|
||||||
{'id': lzma.FILTER_LZMA2, 'preset': 6, 'dict_size': 64*1024},
|
{"id": lzma.FILTER_LZMA2, "preset": 6, "dict_size": 64*1024},
|
||||||
]
|
]
|
||||||
with open(in_file, 'rb') as src_f:
|
with open(in_file, 'rb') as src_f:
|
||||||
data = src_f.read()
|
data = src_f.read()
|
||||||
with lzma.open(compressed_file, 'wb', format=lzma.FORMAT_XZ, check=lzma.CHECK_CRC32, filters=xz_compressor_filter) as f:
|
with lzma.open(compressed_file, "wb", format=lzma.FORMAT_XZ, check=lzma.CHECK_CRC32, filters=xz_compressor_filter) as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@ def main():
|
||||||
default='', help='the sign key used for secure boot')
|
default='', help='the sign key used for secure boot')
|
||||||
parser.add_argument('-fv', '--fw_ver', nargs='?',
|
parser.add_argument('-fv', '--fw_ver', nargs='?',
|
||||||
default='', help='the version of the compressed data(this field is deprecated in v3)')
|
default='', help='the version of the compressed data(this field is deprecated in v3)')
|
||||||
parser.add_argument('--add_app_header', action='store_true', help='add app header to use native esp_ota_* & esp_https_ota_* APIs')
|
parser.add_argument('--add_app_header', action="store_true", help='add app header to use native esp_ota_* & esp_https_ota_* APIs')
|
||||||
parser.add_argument('-v', '--version', action='version', version=get_script_version(), help='the version of the script')
|
parser.add_argument('-v', '--version', action='version', version=get_script_version(), help='the version of the script')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
@ -146,7 +146,7 @@ def main():
|
||||||
|
|
||||||
print('src file is: {}'.format(src_file))
|
print('src file is: {}'.format(src_file))
|
||||||
|
|
||||||
# rebuild the cpmpressed_app directory
|
# rebuild the cpmpressed_app directroy
|
||||||
cpmoressed_app_directory = 'custom_ota_binaries'
|
cpmoressed_app_directory = 'custom_ota_binaries'
|
||||||
if os.path.exists(cpmoressed_app_directory):
|
if os.path.exists(cpmoressed_app_directory):
|
||||||
shutil.rmtree(cpmoressed_app_directory)
|
shutil.rmtree(cpmoressed_app_directory)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
|
|
@ -18,18 +19,17 @@ espidf_missing_function_info = True
|
||||||
|
|
||||||
class sdkconfig_c:
|
class sdkconfig_c:
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
with open(path) as f:
|
lines = open(path).read().splitlines()
|
||||||
lines = f.read().splitlines()
|
config = dict()
|
||||||
config = {}
|
|
||||||
for l in lines:
|
for l in lines:
|
||||||
if len(l) > OPT_MIN_LEN and l[0] != '#':
|
if len(l) > OPT_MIN_LEN and l[0] != '#':
|
||||||
mo = re.match(r'(.*)=(.*)', l, re.M | re.I)
|
mo = re.match( r'(.*)=(.*)', l, re.M|re.I)
|
||||||
if mo:
|
if mo:
|
||||||
config[mo.group(1)] = mo.group(2).replace('"', '')
|
config[mo.group(1)]=mo.group(2).replace('"', '')
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
def index(self, key):
|
def index(self, i):
|
||||||
return self.config[key]
|
return self.config[i]
|
||||||
|
|
||||||
def check(self, options):
|
def check(self, options):
|
||||||
options = options.replace(' ', '')
|
options = options.replace(' ', '')
|
||||||
|
|
@ -54,69 +54,52 @@ class sdkconfig_c:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class object_c:
|
class object_c:
|
||||||
def read_dump_info(self, paths):
|
def read_dump_info(self, pathes):
|
||||||
new_env = os.environ.copy()
|
new_env = os.environ.copy()
|
||||||
new_env['LC_ALL'] = 'C'
|
new_env['LC_ALL'] = 'C'
|
||||||
dumps = []
|
dumps = list()
|
||||||
print('paths:', paths)
|
print('pathes:', pathes)
|
||||||
for path in paths:
|
for path in pathes:
|
||||||
try:
|
try:
|
||||||
dump_output = subprocess.check_output([espidf_objdump, '-t', path], env=new_env).decode()
|
dump = StringIO(subprocess.check_output([espidf_objdump, '-t', path], env=new_env).decode())
|
||||||
dumps.append(StringIO(dump_output).readlines())
|
dumps.append(dump.readlines())
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
raise RuntimeError(f"Command '{e.cmd}' failed with exit code {e.returncode}")
|
raise RuntimeError('cmd:%s result:%s'%(e.cmd, e.returncode))
|
||||||
return dumps
|
return dumps
|
||||||
|
|
||||||
def get_func_section(self, dumps, func):
|
def get_func_section(self, dumps, func):
|
||||||
for dump in dumps:
|
for dump in dumps:
|
||||||
for line in dump:
|
for l in dump:
|
||||||
if f' {func}' in line and '*UND*' not in line:
|
if ' %s'%(func) in l and '*UND*' not in l:
|
||||||
m = re.match(r'(\S*)\s*([glw])\s*([F|O])\s*(\S*)\s*(\S*)\s*(\S*)\s*', line, re.M | re.I)
|
m = re.match(r'(\S*)\s*([glw])\s*([F|O])\s*(\S*)\s*(\S*)\s*(\S*)\s*', l, re.M|re.I)
|
||||||
if m and m[6] == func:
|
if m and m[6] == func:
|
||||||
return m.group(4).replace('.text.', '')
|
return m[4].replace('.text.', '')
|
||||||
if espidf_missing_function_info:
|
if espidf_missing_function_info:
|
||||||
print(f'{func} failed to find section')
|
print('%s failed to find section'%(func))
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f'{func} failed to find section')
|
raise RuntimeError('%s failed to find section'%(func))
|
||||||
|
|
||||||
def __init__(self, name, paths, library):
|
def __init__(self, name, pathes, libray):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.library = library
|
self.libray = libray
|
||||||
self.funcs = {}
|
self.funcs = dict()
|
||||||
self.paths = paths
|
self.pathes = pathes
|
||||||
self.dumps = self.read_dump_info(paths)
|
self.dumps = self.read_dump_info(pathes)
|
||||||
self.section_all = False
|
|
||||||
|
|
||||||
def append(self, func):
|
def append(self, func):
|
||||||
section = None
|
|
||||||
|
|
||||||
if func == '.text.*':
|
|
||||||
section = '.literal .literal.* .text .text.*'
|
|
||||||
self.section_all = True
|
|
||||||
elif func == '.iram1.*':
|
|
||||||
section = '.iram1 .iram1.*'
|
|
||||||
self.section_all = True
|
|
||||||
elif func == '.wifi0iram.*':
|
|
||||||
section = '.wifi0iram .wifi0iram.*'
|
|
||||||
self.section_all = True
|
|
||||||
elif func == '.wifirxiram.*':
|
|
||||||
section = '.wifirxiram .wifirxiram.*'
|
|
||||||
self.section_all = True
|
|
||||||
else:
|
|
||||||
section = self.get_func_section(self.dumps, func)
|
section = self.get_func_section(self.dumps, func)
|
||||||
|
if section != None:
|
||||||
if section is not None:
|
|
||||||
self.funcs[func] = section
|
self.funcs[func] = section
|
||||||
|
|
||||||
def functions(self):
|
def functions(self):
|
||||||
nlist = []
|
nlist = list()
|
||||||
for i in self.funcs:
|
for i in self.funcs:
|
||||||
nlist.append(i)
|
nlist.append(i)
|
||||||
return nlist
|
return nlist
|
||||||
|
|
||||||
def sections(self):
|
def sections(self):
|
||||||
nlist = []
|
nlist = list()
|
||||||
for i in self.funcs:
|
for i in self.funcs:
|
||||||
nlist.append(self.funcs[i])
|
nlist.append(self.funcs[i])
|
||||||
return nlist
|
return nlist
|
||||||
|
|
@ -125,7 +108,7 @@ class library_c:
|
||||||
def __init__(self, name, path):
|
def __init__(self, name, path):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.path = path
|
self.path = path
|
||||||
self.objs = {}
|
self.objs = dict()
|
||||||
|
|
||||||
def append(self, obj, path, func):
|
def append(self, obj, path, func):
|
||||||
if obj not in self.objs:
|
if obj not in self.objs:
|
||||||
|
|
@ -134,7 +117,7 @@ class library_c:
|
||||||
|
|
||||||
class libraries_c:
|
class libraries_c:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.libs = {}
|
self.libs = dict()
|
||||||
|
|
||||||
def append(self, lib, lib_path, obj, obj_path, func):
|
def append(self, lib, lib_path, obj, obj_path, func):
|
||||||
if lib not in self.libs:
|
if lib not in self.libs:
|
||||||
|
|
@ -146,20 +129,20 @@ class libraries_c:
|
||||||
lib = self.libs[libname]
|
lib = self.libs[libname]
|
||||||
for objname in lib.objs:
|
for objname in lib.objs:
|
||||||
obj = lib.objs[objname]
|
obj = lib.objs[objname]
|
||||||
print(f'{libname}, {objname}, {obj.path}, {obj.funcs}')
|
print('%s, %s, %s, %s'%(libname, objname, obj.path, obj.funcs))
|
||||||
|
|
||||||
class paths_c:
|
class paths_c:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.paths = {}
|
self.paths = dict()
|
||||||
|
|
||||||
def append(self, lib, obj, path):
|
def append(self, lib, obj, path):
|
||||||
if '$IDF_PATH' in path:
|
if '$IDF_PATH' in path:
|
||||||
path = path.replace('$IDF_PATH', os.environ['IDF_PATH'])
|
path = path.replace('$IDF_PATH', os.environ['IDF_PATH'])
|
||||||
|
|
||||||
if lib not in self.paths:
|
if lib not in self.paths:
|
||||||
self.paths[lib] = {}
|
self.paths[lib] = dict()
|
||||||
if obj not in self.paths[lib]:
|
if obj not in self.paths[lib]:
|
||||||
self.paths[lib][obj] = []
|
self.paths[lib][obj] = list()
|
||||||
self.paths[lib][obj].append(path)
|
self.paths[lib][obj].append(path)
|
||||||
|
|
||||||
def index(self, lib, obj):
|
def index(self, lib, obj):
|
||||||
|
|
@ -167,7 +150,7 @@ class paths_c:
|
||||||
return None
|
return None
|
||||||
if '*' in self.paths[lib]:
|
if '*' in self.paths[lib]:
|
||||||
obj = '*'
|
obj = '*'
|
||||||
return self.paths[lib].get(obj)
|
return self.paths[lib][obj]
|
||||||
|
|
||||||
def generator(library_file, object_file, function_file, sdkconfig_file, missing_function_info, objdump='riscv32-esp-elf-objdump'):
|
def generator(library_file, object_file, function_file, sdkconfig_file, missing_function_info, objdump='riscv32-esp-elf-objdump'):
|
||||||
global espidf_objdump, espidf_missing_function_info
|
global espidf_objdump, espidf_missing_function_info
|
||||||
|
|
@ -177,29 +160,23 @@ def generator(library_file, object_file, function_file, sdkconfig_file, missing_
|
||||||
sdkconfig = sdkconfig_c(sdkconfig_file)
|
sdkconfig = sdkconfig_c(sdkconfig_file)
|
||||||
|
|
||||||
lib_paths = paths_c()
|
lib_paths = paths_c()
|
||||||
with open(library_file, newline='') as csvfile:
|
for p in csv.DictReader(open(library_file, 'r')):
|
||||||
reader = csv.DictReader(csvfile)
|
lib_paths.append(p['library'], '*', p['path'])
|
||||||
for row in reader:
|
|
||||||
lib_paths.append(row['library'], '*', row['path'])
|
|
||||||
|
|
||||||
obj_paths = paths_c()
|
obj_paths = paths_c()
|
||||||
with open(object_file, newline='') as csvfile:
|
for p in csv.DictReader(open(object_file, 'r')):
|
||||||
reader = csv.DictReader(csvfile)
|
obj_paths.append(p['library'], p['object'], p['path'])
|
||||||
for row in reader:
|
|
||||||
obj_paths.append(row['library'], row['object'], row['path'])
|
|
||||||
|
|
||||||
libraries = libraries_c()
|
libraries = libraries_c()
|
||||||
with open(function_file, newline='') as csvfile:
|
for d in csv.DictReader(open(function_file, 'r')):
|
||||||
reader = csv.DictReader(csvfile)
|
if d['option'] and sdkconfig.check(d['option']) == False:
|
||||||
for row in reader:
|
print('skip %s(%s)'%(d['function'], d['option']))
|
||||||
if row['option'] and not sdkconfig.check(row['option']):
|
|
||||||
print(f'skip {row["function"]}({row["option"]})')
|
|
||||||
continue
|
continue
|
||||||
lib_path = lib_paths.index(row['library'], '*')
|
lib_path = lib_paths.index(d['library'], '*')
|
||||||
obj_path = obj_paths.index(row['library'], row['object'])
|
obj_path = obj_paths.index(d['library'], d['object'])
|
||||||
if not obj_path:
|
if not obj_path:
|
||||||
obj_path = lib_path
|
obj_path = lib_path
|
||||||
libraries.append(row['library'], lib_path[0], row['object'], obj_path, row['function'])
|
libraries.append(d['library'], lib_path[0], d['object'], obj_path, d['function'])
|
||||||
return libraries
|
return libraries
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -208,30 +185,26 @@ def main():
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--library', '-l',
|
'--library', '-l',
|
||||||
help='Library description file',
|
help='Library description file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--object', '-b',
|
'--object', '-b',
|
||||||
help='Object description file',
|
help='Object description file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--function', '-f',
|
'--function', '-f',
|
||||||
help='Function description file',
|
help='Function description file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--sdkconfig', '-s',
|
'--sdkconfig', '-s',
|
||||||
help='sdkconfig file',
|
help='sdkconfig file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
args = argparser.parse_args()
|
args = argparser.parse_args()
|
||||||
|
|
||||||
libraries = generator(args.library, args.object, args.function, args.sdkconfig, espidf_missing_function_info)
|
libraries = generator(args.library, args.object, args.function, args.sdkconfig)
|
||||||
# libraries.dump()
|
# libraries.dump()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ libesp_timer.a,system_time.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.di
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c2/esp_adapter.c.obj
|
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c2/esp_adapter.c.obj
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj
|
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_common.c.obj
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_systick.c.obj
|
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_systick.c.obj
|
||||||
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
library,object,function,option
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr,FALSE
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp_sleep_enable_timer_wakeup,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_enable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_disable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,periph_module_reset,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp_ptr_byte_accessible
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_wait_for_intr
|
|
||||||
libesp_system.a,cpu_start.c.obj,call_start_cpu0,FALSE
|
|
||||||
libesp_system.a,panic_handler.c.obj,xt_unhandled_exception
|
|
||||||
libesp_system.a,panic_handler.c.obj,panicHandler
|
|
||||||
libesp_system.a,system_internal.c.obj,esp_restart_noos
|
|
||||||
libesp_system.a,system_internal.c.obj,esp_system_reset_modules_on_exit
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_isr,FALSE
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send_yield
|
|
||||||
libesp_system.a,panic_handler.c.obj,panic_enable_cache
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationIdleHook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationTickHook
|
|
||||||
libesp_system.a,int_wdt.c.obj,tick_hook,CONFIG_ESP_INT_WDT
|
|
||||||
libesp_system.a,task_wdt.c.obj,idle_hook_cb,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset_user,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,task_wdt_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_from_task_handle_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt_impl_esp_timer.c.obj,esp_task_wdt_impl_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,timer_alarm_isr,FALSE
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_get_time
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_next_alarm_for_wake_up,CONFIG_PM_ENABLE
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_unlock
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_lock
|
|
||||||
libfreertos.a,port_systick.c.obj,SysTickIsrHandler
|
|
||||||
libfreertos.a,port_systick.c.obj,xPortSysTickHandler
|
|
||||||
libfreertos.a,port.c.obj,vPortEnterCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortExitCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortYieldFromISR
|
|
||||||
libfreertos.a,port.c.obj,vPortSetInterruptMask
|
|
||||||
libfreertos.a,port.c.obj,xPortInIsrContext
|
|
||||||
libfreertos.a,port.c.obj,vPortYield
|
|
||||||
libfreertos.a,port.c.obj,vPortClearInterruptMask
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetCurrentTaskHandle
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetSchedulerState
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskIncrementTick
|
|
||||||
libfreertos.a,tasks.c.obj,prvResetNextTaskUnblockTime
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskStepTick,CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
||||||
libfreertos.a,tasks.c.obj,taskSelectHighestPriorityTaskSMP
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskSwitchContext
|
|
||||||
libfreertos.a,port_common.c.obj,xPortCheckValidTCBMem
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_program_page
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_sector
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_block
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_block
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_read
|
|
||||||
libhal.a,spi_flash_hal_gpspi.c.obj,spi_flash_hal_gpspi_poll_cmd_done
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_cache_enabled
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_restore_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,.iram1.*
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_isr_hook,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,vApplicationSleep,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,leave_idle,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_idle_hook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_waiti,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_release_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_request_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_reset_mac_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_disable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_enable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_request,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,assert.c.obj,__assert_func
|
|
||||||
libriscv.a,interrupt.c.obj,.text.*
|
|
||||||
libriscv.a,vectors.S.obj,.text.*
|
|
||||||
libfreertos.a,portasm.S.obj,.text.*
|
|
||||||
libfreertos.a,list.c.obj,.text.*
|
|
||||||
libpp.a,*,.iram1.*
|
|
||||||
libpp.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libpp.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
library,path
|
|
||||||
libesp_hw_support.a,./esp-idf/esp_hw_support/libesp_hw_support.a
|
|
||||||
libesp_pm.a,./esp-idf/esp_pm/libesp_pm.a
|
|
||||||
libesp_phy.a,./esp-idf/esp_phy/libesp_phy.a
|
|
||||||
libesp_system.a,./esp-idf/esp_system/libesp_system.a
|
|
||||||
libesp_timer.a,./esp-idf/esp_timer/libesp_timer.a
|
|
||||||
libesp_wifi.a,./esp-idf/esp_wifi/libesp_wifi.a
|
|
||||||
libfreertos.a,./esp-idf/freertos/libfreertos.a
|
|
||||||
libhal.a,./esp-idf/hal/libhal.a
|
|
||||||
libnet80211.a,$IDF_PATH/components/esp_wifi/lib/esp32c2/libnet80211.a
|
|
||||||
libnewlib.a,./esp-idf/newlib/libnewlib.a
|
|
||||||
libpp.a,$IDF_PATH/components/esp_wifi/lib/esp32c2/libpp.a
|
|
||||||
libriscv.a,./esp-idf/riscv/libriscv.a
|
|
||||||
libspi_flash.a,./esp-idf/spi_flash/libspi_flash.a
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
library,object,path
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj
|
|
||||||
libesp_system.a,cpu_start.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj
|
|
||||||
libesp_system.a,panic_handler.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj
|
|
||||||
libesp_system.a,int_wdt.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/int_wdt.c.obj
|
|
||||||
libesp_system.a,system_internal.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c2/system_internal.c.obj
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj
|
|
||||||
libesp_system.a,task_wdt_impl_esp_timer.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_esp_timer.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c2/esp_adapter.c.obj
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj
|
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_systick.c.obj
|
|
||||||
libfreertos.a,portasm.S.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/portasm.S.obj
|
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_common.c.obj
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj
|
|
||||||
libhal.a,spi_flash_hal_gpspi.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj
|
|
||||||
libnewlib.a,locks.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/locks.c.obj
|
|
||||||
libnewlib.a,assert.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/assert.c.obj
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj
|
|
||||||
libspi_flash.a,cache_utils.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj
|
|
||||||
libriscv.a.a,interrupt.c.obj,esp-idf/riscv/CMakeFiles/__idf_riscv.dir/interrupt.c.obj
|
|
||||||
libriscv.a.a,vectors.S.obj,esp-idf/riscv/CMakeFiles/__idf_riscv.dir/vectors.S.obj
|
|
||||||
libfreertos.a,portasm.S.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/portasm.S.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
|
|
|
@ -1,150 +0,0 @@
|
||||||
library,object,function,option
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr_noniram_disable
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr_noniram_enable
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,suspend_cache
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,resume_cache
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_start
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_pu
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_finish
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_get_default_config
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_init
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_low_init
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_clk_cal
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_clk_cal_internal
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_get
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_us_to_slowclk
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_slowclk_to_us
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp_sleep_enable_timer_wakeup,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_enable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_disable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,periph_module_reset,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp_ptr_byte_accessible
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_wait_for_intr
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_set_to_default_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_32k_enable_external
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_fast_src_set
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_freq_get_hz
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_src_get
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_src_set
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_dig_clk8m_disable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_config_fast
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_8m_enable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_8md256_enabled
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_configure
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_enable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_get_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_mhz_to_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_8m
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_pll_mhz
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_xtal
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_xtal_freq_get
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_xtal
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_disable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_apb_freq_update
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,clk_ll_rtc_slow_get_src
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,.iram1.*
|
|
||||||
libesp_system.a,cpu_start.c.obj,call_start_cpu0,FALSE
|
|
||||||
libesp_system.a,panic_handler.c.obj,xt_unhandled_exception
|
|
||||||
libesp_system.a,panic_handler.c.obj,panicHandler
|
|
||||||
libesp_system.a,system_internal.c.obj,esp_restart_noos
|
|
||||||
libesp_system.a,system_internal.c.obj,esp_system_reset_modules_on_exit
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_isr,FALSE
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send_yield
|
|
||||||
libesp_system.a,panic_handler.c.obj,panic_enable_cache
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationIdleHook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationTickHook
|
|
||||||
libesp_system.a,int_wdt.c.obj,tick_hook,CONFIG_ESP_INT_WDT
|
|
||||||
libesp_system.a,task_wdt.c.obj,idle_hook_cb,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset_user,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,task_wdt_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_from_task_handle_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt_impl_esp_timer.c.obj,esp_task_wdt_impl_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,timer_alarm_isr,FALSE
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_get_time
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_next_alarm_for_wake_up,CONFIG_PM_ENABLE
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_unlock
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_lock
|
|
||||||
libfreertos.a,port_systick.c.obj,SysTickIsrHandler
|
|
||||||
libfreertos.a,port_systick.c.obj,xPortSysTickHandler
|
|
||||||
libfreertos.a,port.c.obj,vPortEnterCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortExitCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortYieldFromISR
|
|
||||||
libfreertos.a,port.c.obj,vPortSetInterruptMask
|
|
||||||
libfreertos.a,port.c.obj,xPortInIsrContext
|
|
||||||
libfreertos.a,port.c.obj,vPortYield
|
|
||||||
libfreertos.a,port.c.obj,vPortClearInterruptMask
|
|
||||||
libfreertos.a,port.c.obj,xPortSetInterruptMaskFromISR
|
|
||||||
libfreertos.a,port.c.obj,vPortClearInterruptMaskFromISR
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetCurrentTaskHandle
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetSchedulerState
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskIncrementTick
|
|
||||||
libfreertos.a,tasks.c.obj,prvResetNextTaskUnblockTime
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskStepTick,CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
||||||
libfreertos.a,tasks.c.obj,taskSelectHighestPriorityTaskSMP
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskSwitchContext
|
|
||||||
libfreertos.a,port_common.c.obj,xPortCheckValidTCBMem
|
|
||||||
libfreertos.a,portasm.S.obj,.text.*
|
|
||||||
libfreertos.a,list.c.obj,.text.*,FALSE
|
|
||||||
libfreertos.a,queue.c.obj,.text.*,FALSE
|
|
||||||
libfreertos.a,queue.c.obj,.iram1.*,FALSE
|
|
||||||
libhal.a,cache_hal.c.obj,.iram1.*
|
|
||||||
libhal.a,cache_hal.c.obj,.text.*
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_program_page
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_sector
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_block
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_block
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_read
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_common_command
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_resume
|
|
||||||
libhal.a,spi_flash_hal_gpspi.c.obj,spi_flash_hal_gpspi_poll_cmd_done
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_cache_enabled
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_restore_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,.iram1.*
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_isr_hook,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,vApplicationSleep,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,leave_idle,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_idle_hook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_waiti,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_release_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_request_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_reset_mac_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_disable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_enable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_request,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,.text.*
|
|
||||||
libnewlib.a,locks.c.obj,.iram1.*
|
|
||||||
libriscv.a,interrupt.c.obj,.text.*
|
|
||||||
libriscv.a,vectors.S.obj,.text.*
|
|
||||||
libpp.a,*,.iram1.*,FALSE
|
|
||||||
libpp.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libpp.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,.iram1.*
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,.text.*,FALSE
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,s_do_cache_invalidate,
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,s_do_mapping,
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,s_do_unmapping,
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,esp_mmu_vaddr_to_paddr,
|
|
||||||
libhal.a,mmu_hal.c.obj,.iram1.*
|
|
||||||
libhal.a,mmu_hal.c.obj,.text.*
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
library,path
|
|
||||||
libesp_hw_support.a,./esp-idf/esp_hw_support/libesp_hw_support.a
|
|
||||||
libesp_pm.a,./esp-idf/esp_pm/libesp_pm.a
|
|
||||||
libesp_phy.a,./esp-idf/esp_phy/libesp_phy.a
|
|
||||||
libesp_system.a,./esp-idf/esp_system/libesp_system.a
|
|
||||||
libesp_timer.a,./esp-idf/esp_timer/libesp_timer.a
|
|
||||||
libesp_wifi.a,./esp-idf/esp_wifi/libesp_wifi.a
|
|
||||||
libfreertos.a,./esp-idf/freertos/libfreertos.a
|
|
||||||
libhal.a,./esp-idf/hal/libhal.a
|
|
||||||
libnet80211.a,$IDF_PATH/components/esp_wifi/lib/esp32c2/libnet80211.a
|
|
||||||
libnewlib.a,./esp-idf/newlib/libnewlib.a
|
|
||||||
libpp.a,$IDF_PATH/components/esp_wifi/lib/esp32c2/libpp.a
|
|
||||||
libriscv.a,./esp-idf/riscv/libriscv.a
|
|
||||||
libspi_flash.a,./esp-idf/spi_flash/libspi_flash.a
|
|
||||||
libesp_mm.a,./esp-idf/esp_mm/libesp_mm.a
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
library,object,path
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c2/rtc_sleep.c.obj
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c2/rtc_clk.c.obj
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c2/rtc_time.c.obj
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj
|
|
||||||
libesp_system.a,cpu_start.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj
|
|
||||||
libesp_system.a,panic_handler.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj
|
|
||||||
libesp_system.a,int_wdt.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/int_wdt.c.obj
|
|
||||||
libesp_system.a,system_internal.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c2/system_internal.c.obj
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj
|
|
||||||
libesp_system.a,task_wdt_impl_esp_timer.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_esp_timer.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c2/esp_adapter.c.obj
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj
|
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj
|
|
||||||
libfreertos.a,portasm.S.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/portasm.S.obj
|
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj
|
|
||||||
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj
|
|
||||||
libhal.a,cache_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj
|
|
||||||
libhal.a,spi_flash_hal_gpspi.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj
|
|
||||||
libnewlib.a,locks.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/locks.c.obj
|
|
||||||
libnewlib.a,assert.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/assert.c.obj
|
|
||||||
libriscv.a.a,interrupt.c.obj,esp-idf/riscv/CMakeFiles/__idf_riscv.dir/interrupt.c.obj
|
|
||||||
libriscv.a.a,vectors.S.obj,esp-idf/riscv/CMakeFiles/__idf_riscv.dir/vectors.S.obj
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_mmu_map.c.obj
|
|
||||||
libhal.a,mmu_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj
|
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
library,object,function,option
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr,FALSE
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp_sleep_enable_timer_wakeup,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_enable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_disable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,periph_module_reset,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp_ptr_byte_accessible
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_wait_for_intr
|
|
||||||
libesp_system.a,cpu_start.c.obj,call_start_cpu0,FALSE
|
|
||||||
libesp_system.a,panic_handler.c.obj,xt_unhandled_exception
|
|
||||||
libesp_system.a,panic_handler.c.obj,panicHandler
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_isr,FALSE
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send_yield
|
|
||||||
libesp_system.a,panic_handler.c.obj,panic_enable_cache
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationIdleHook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationTickHook
|
|
||||||
libesp_system.a,task_wdt.c.obj,idle_hook_cb,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset_user,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,task_wdt_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_from_task_handle_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt_impl_timergroup.c.obj,esp_task_wdt_impl_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,timer_alarm_isr,FALSE
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_get_time
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_next_alarm_for_wake_up,CONFIG_PM_ENABLE
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_unlock
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_lock
|
|
||||||
libfreertos.a,port_systick.c.obj,SysTickIsrHandler
|
|
||||||
libfreertos.a,port_systick.c.obj,xPortSysTickHandler
|
|
||||||
libfreertos.a,portasm.S.obj,rtos_int_enter
|
|
||||||
libfreertos.a,port.c.obj,vPortEnterCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortExitCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortYieldFromISR
|
|
||||||
libfreertos.a,port.c.obj,vPortSetInterruptMask
|
|
||||||
libfreertos.a,port.c.obj,xPortInIsrContext
|
|
||||||
libfreertos.a,port.c.obj,vPortYield
|
|
||||||
libfreertos.a,port.c.obj,vPortClearInterruptMask
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetCurrentTaskHandle
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetSchedulerState
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskIncrementTick
|
|
||||||
libfreertos.a,tasks.c.obj,prvResetNextTaskUnblockTime
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskStepTick,CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
||||||
libfreertos.a,port_common.c.obj,xPortCheckValidTCBMem
|
|
||||||
libfreertos.a,queue.c.obj,xQueueSemaphoreTake
|
|
||||||
libfreertos.a,queue.c.obj,xQueueGenericSend
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceive
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_program_page
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_cache_enabled
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_restore_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_mmap_pages
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_mmap_init
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,get_mmu_region
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_munmap
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_protected_read_mmu_entry
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_mmap_get_free_pages
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_isr_hook,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,vApplicationSleep,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_idle_hook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_waiti,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_enable,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,assert.c.obj,__assert_func
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_release_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_request_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_reset_mac_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_disable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_enable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_request,CONFIG_PM_ENABLE
|
|
||||||
libesp_netif.a,ethernetif.c.obj,ethernet_low_level_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,ethernetif.c.obj,ethernetif_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,wlanif.c.obj,low_level_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,wlanif.c.obj,wlanif_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp_netif_transmit_wrap,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp_netif_free_rx_buffer,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp_netif_receive,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_pbuf_ref.c.obj,esp_pbuf_allocate,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_pbuf_ref.c.obj,esp_pbuf_free,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,api_msg.c.obj,lwip_netconn_do_send,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,api_msg.c.obj,lwip_netconn_do_write,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,netbuf.c.obj,netbuf_alloc,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,netbuf.c.obj,netbuf_free,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_thread,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_thread_handle_msg,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_inpkt,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_callback,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_try_callback,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_send_msg_wait_sem,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,inet_chksum.c.obj,inet_cksum_pseudo_base,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,inet_chksum.c.obj,inet_chksum_pseudo,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,etharp.c.obj,etharp_output_to_arp_index,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,etharp.c.obj,etharp_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4_addr.c.obj,ip4_addr_isbroadcast_u32,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_route_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_route,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if_opt,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if_opt_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_alloc,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_add_header_impl,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_add_header,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_remove_header,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_header_impl,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_header,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_free,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_alloced_custom,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_init_alloced_pbuf,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_input_local_match,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_send,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_sendto,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_sendto_if,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_sendto_if_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ethernet.c.obj,ethernet_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ethernet.c.obj,ethernet_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mutex_lock,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mutex_unlock,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_sem_signal,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_arch_sem_wait,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mbox_post,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mbox_trypost,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_arch_mbox_fetch,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,lwip_default_hooks.c.obj,ip4_route_src_hook,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libriscv.a,interrupt.c.obj,.text.*
|
|
||||||
libriscv.a,vectors.S.obj,.text.*
|
|
||||||
libfreertos.a,portasm.S.obj,.text.*
|
|
||||||
libfreertos.a,list.c.obj,.text.*
|
|
||||||
libhal.a,systimer_hal.c.obj,.text.*
|
|
||||||
libpp.a,*,.iram1.*
|
|
||||||
libpp.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libpp.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
library,path
|
|
||||||
libesp_hw_support.a,./esp-idf/esp_hw_support/libesp_hw_support.a
|
|
||||||
libesp_system.a,./esp-idf/esp_system/libesp_system.a
|
|
||||||
libesp_timer.a,./esp-idf/esp_timer/libesp_timer.a
|
|
||||||
libfreertos.a,./esp-idf/freertos/libfreertos.a
|
|
||||||
libhal.a,./esp-idf/hal/libhal.a
|
|
||||||
libriscv.a,./esp-idf/riscv/libriscv.a
|
|
||||||
libspi_flash.a,./esp-idf/spi_flash/libspi_flash.a
|
|
||||||
libesp_pm.a,./esp-idf/esp_pm/libesp_pm.a
|
|
||||||
libesp_phy.a,./esp-idf/esp_phy/libesp_phy.a
|
|
||||||
libnewlib.a,./esp-idf/newlib/libnewlib.a
|
|
||||||
libesp_wifi.a,./esp-idf/esp_wifi/libesp_wifi.a
|
|
||||||
libesp_netif.a,./esp-idf/esp_netif/libesp_netif.a
|
|
||||||
liblwip.a,./esp-idf/lwip/liblwip.a
|
|
||||||
libpp.a,$IDF_PATH/components/esp_wifi/lib/esp32c3/libpp.a
|
|
||||||
libnet80211.a,$IDF_PATH/components/esp_wifi/lib/esp32c3/libnet80211.a
|
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
library,object,path
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj
|
|
||||||
libesp_system.a,cpu_start.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj
|
|
||||||
libesp_system.a,panic_handler.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj
|
|
||||||
libesp_system.a,task_wdt_impl_timergroup.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_timergroup.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj
|
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_systick.c.obj
|
|
||||||
libfreertos.a,portasm.S.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/portasm.S.obj
|
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_common.c.obj
|
|
||||||
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj
|
|
||||||
libhal.a,systimer_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/systimer_hal.c.obj
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj
|
|
||||||
libspi_flash.a,cache_utils.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj
|
|
||||||
libnewlib.a,locks.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/locks.c.obj
|
|
||||||
libnewlib.a,assert.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/assert.c.obj
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c3/esp_adapter.c.obj
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj
|
|
||||||
libesp_netif.a,ethernetif.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/ethernetif.c.obj
|
|
||||||
libesp_netif.a,wlanif.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/wlanif.c.obj
|
|
||||||
libesp_netif.a,esp_pbuf_ref.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/esp_pbuf_ref.c.obj
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip.c.obj
|
|
||||||
liblwip.a,sockets.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/sockets.c.obj
|
|
||||||
liblwip.a,api_lib.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_lib.c.obj
|
|
||||||
liblwip.a,api_msg.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_msg.c.obj
|
|
||||||
liblwip.a,netbuf.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netbuf.c.obj
|
|
||||||
liblwip.a,tcpip.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/tcpip.c.obj
|
|
||||||
liblwip.a,inet_chksum.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/inet_chksum.c.obj
|
|
||||||
liblwip.a,etharp.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/etharp.c.obj
|
|
||||||
liblwip.a,ip4_addr.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_addr.c.obj
|
|
||||||
liblwip.a,ip4.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4.c.obj
|
|
||||||
liblwip.a,pbuf.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/pbuf.c.obj
|
|
||||||
liblwip.a,udp.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/udp.c.obj
|
|
||||||
liblwip.a,ethernet.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ethernet.c.obj
|
|
||||||
liblwip.a,sys_arch.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/esp32/freertos/sys_arch.c.obj
|
|
||||||
liblwip.a,lwip_default_hooks.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/esp32/hooks/lwip_default_hooks.c.obj
|
|
||||||
|
|
|
@ -1,217 +0,0 @@
|
||||||
library,object,function,option
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr_noniram_disable
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr_noniram_enable
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,suspend_cache
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,resume_cache
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_start
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_pu
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_finish
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_get_default_config
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_init
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_low_init
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_clk_cal
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_clk_cal_internal
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_get
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_us_to_slowclk
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_slowclk_to_us
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp_sleep_enable_timer_wakeup,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_enable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_module_disable,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,periph_module_reset,CONFIG_PERIPH_CTRL_FUNC_IN_IRAM
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp_ptr_byte_accessible
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_wait_for_intr
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_set_to_default_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_32k_enable_external
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_fast_src_set
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_freq_get_hz
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_src_get
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_src_set
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_dig_clk8m_disable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_config_fast
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_8m_enable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_8md256_enabled
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_configure
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_enable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_get_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_mhz_to_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_config
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_8m
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_pll_mhz
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_xtal
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_xtal_freq_get
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_xtal
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_disable
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_apb_freq_update
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,clk_ll_rtc_slow_get_src
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,.iram1.*
|
|
||||||
libesp_system.a,cpu_start.c.obj,call_start_cpu0,FALSE
|
|
||||||
libesp_system.a,panic_handler.c.obj,xt_unhandled_exception
|
|
||||||
libesp_system.a,panic_handler.c.obj,panicHandler
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_isr,FALSE
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send_yield
|
|
||||||
libesp_system.a,panic_handler.c.obj,panic_enable_cache
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationIdleHook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp_vApplicationTickHook
|
|
||||||
libesp_system.a,task_wdt.c.obj,idle_hook_cb,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp_task_wdt_reset_user,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,task_wdt_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt.c.obj,find_entry_from_task_handle_and_check_all_reset,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_system.a,task_wdt_impl_timergroup.c.obj,esp_task_wdt_impl_timer_feed,CONFIG_PM_SLP_IRAM_OPT
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,timer_alarm_isr,FALSE
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_get_time
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_next_alarm_for_wake_up,CONFIG_PM_ENABLE
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_unlock
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_lock
|
|
||||||
libfreertos.a,port_systick.c.obj,SysTickIsrHandler
|
|
||||||
libfreertos.a,port_systick.c.obj,xPortSysTickHandler
|
|
||||||
libfreertos.a,portasm.S.obj,rtos_int_enter
|
|
||||||
libfreertos.a,port.c.obj,vPortEnterCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortExitCritical
|
|
||||||
libfreertos.a,port.c.obj,vPortYieldFromISR
|
|
||||||
libfreertos.a,port.c.obj,vPortSetInterruptMask
|
|
||||||
libfreertos.a,port.c.obj,xPortInIsrContext
|
|
||||||
libfreertos.a,port.c.obj,vPortYield
|
|
||||||
libfreertos.a,port.c.obj,vPortClearInterruptMask
|
|
||||||
libfreertos.a,port.c.obj,xPortSetInterruptMaskFromISR
|
|
||||||
libfreertos.a,port.c.obj,vPortClearInterruptMaskFromISR
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetCurrentTaskHandle
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetSchedulerState
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskIncrementTick
|
|
||||||
libfreertos.a,tasks.c.obj,prvResetNextTaskUnblockTime
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskStepTick,CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
||||||
libfreertos.a,port_common.c.obj,xPortCheckValidTCBMem
|
|
||||||
libfreertos.a,queue.c.obj,xQueueSemaphoreTake
|
|
||||||
libfreertos.a,queue.c.obj,xQueueGenericSend
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceive
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_program_page
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_sector
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_block
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_erase_block
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_read
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_common_command
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,spi_flash_hal_resume
|
|
||||||
libhal.a,spi_flash_hal_gpspi.c.obj,spi_flash_hal_gpspi_poll_cmd_done
|
|
||||||
libhal.a,systimer_hal.c.obj,.text.*
|
|
||||||
libhal.a,mmu_hal.c.obj,.iram1.*
|
|
||||||
libhal.a,mmu_hal.c.obj,.text.*
|
|
||||||
libfreertos.a,portasm.S.obj,.text.*
|
|
||||||
libfreertos.a,list.c.obj,.text.*,FALSE
|
|
||||||
libfreertos.a,queue.c.obj,.text.*,FALSE
|
|
||||||
libfreertos.a,queue.c.obj,.iram1.*,FALSE
|
|
||||||
libhal.a,cache_hal.c.obj,.iram1.*
|
|
||||||
libhal.a,cache_hal.c.obj,.text.*
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_cache_enabled
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_restore_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_cache
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_disable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,cache_utils.c.obj,spi_flash_enable_interrupts_caches_and_other_cpu
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_mmap_pages
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_mmap_init
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,get_mmu_region
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_munmap
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_protected_read_mmu_entry
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,spi_flash_mmap_get_free_pages
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_isr_hook,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,vApplicationSleep,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_idle_hook,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_waiti,CONFIG_PM_RTOS_IDLE_OPT
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_enable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_disable,CONFIG_PM_ENABLE
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_enable,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release,CONFIG_PM_ENABLE
|
|
||||||
libnewlib.a,locks.c.obj,.text.*
|
|
||||||
libnewlib.a,locks.c.obj,.iram1.*
|
|
||||||
libnewlib.a,assert.c.obj,__assert_func
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_release_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_request_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_reset_mac_wrapper,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_disable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_clock_enable_wrapper,CONFIG_ESP_WIFI_SLP_IRAM_OPT
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_release,CONFIG_PM_ENABLE
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,wifi_apb80m_request,CONFIG_PM_ENABLE
|
|
||||||
libesp_netif.a,ethernetif.c.obj,ethernet_low_level_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,ethernetif.c.obj,ethernetif_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,wlanif.c.obj,low_level_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,wlanif.c.obj,wlanif_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp_netif_transmit_wrap,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp_netif_free_rx_buffer,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp_netif_receive,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_pbuf_ref.c.obj,esp_pbuf_allocate,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libesp_netif.a,esp_pbuf_ref.c.obj,esp_pbuf_free,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,api_msg.c.obj,lwip_netconn_do_send,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,api_msg.c.obj,lwip_netconn_do_write,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,netbuf.c.obj,netbuf_alloc,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,netbuf.c.obj,netbuf_free,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_thread,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_thread_handle_msg,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_inpkt,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_callback,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_try_callback,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,tcpip.c.obj,tcpip_send_msg_wait_sem,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,inet_chksum.c.obj,inet_cksum_pseudo_base,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,inet_chksum.c.obj,inet_chksum_pseudo,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,etharp.c.obj,etharp_output_to_arp_index,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,etharp.c.obj,etharp_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4_addr.c.obj,ip4_addr_isbroadcast_u32,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_route_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_route,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if_opt,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output_if_opt_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ip4.c.obj,ip4_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_alloc,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_add_header_impl,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_add_header,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_remove_header,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_header_impl,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_header,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_free,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_alloced_custom,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,pbuf.c.obj,pbuf_init_alloced_pbuf,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_input_local_match,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_send,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_sendto,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_sendto_if,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,udp.c.obj,udp_sendto_if_src,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ethernet.c.obj,ethernet_input,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,ethernet.c.obj,ethernet_output,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mutex_lock,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mutex_unlock,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_sem_signal,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_arch_sem_wait,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mbox_post,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_mbox_trypost,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,sys_arch.c.obj,sys_arch_mbox_fetch,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
liblwip.a,lwip_default_hooks.c.obj,ip4_route_src_hook,CONFIG_LWIP_IRAM_OPTIMIZATION
|
|
||||||
libriscv.a,interrupt.c.obj,.text.*
|
|
||||||
libriscv.a,vectors.S.obj,.text.*
|
|
||||||
libfreertos.a,portasm.S.obj,.text.*
|
|
||||||
libfreertos.a,list.c.obj,.text.*
|
|
||||||
libpp.a,*,.iram1.*
|
|
||||||
libpp.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libpp.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifi0iram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libnet80211.a,*,.wifirxiram.*,CONFIG_ESP32_WIFI_IRAM_OPT
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,.iram1.*
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,.text.*,FALSE
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,s_do_cache_invalidate,
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,s_do_mapping,
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,s_do_unmapping,
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,esp_mmu_vaddr_to_paddr,
|
|
||||||
libhal.a,mmu_hal.c.obj,.iram1.*
|
|
||||||
libhal.a,mmu_hal.c.obj,.text.*
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
library,path
|
|
||||||
libesp_hw_support.a,./esp-idf/esp_hw_support/libesp_hw_support.a
|
|
||||||
libesp_system.a,./esp-idf/esp_system/libesp_system.a
|
|
||||||
libesp_timer.a,./esp-idf/esp_timer/libesp_timer.a
|
|
||||||
libfreertos.a,./esp-idf/freertos/libfreertos.a
|
|
||||||
libhal.a,./esp-idf/hal/libhal.a
|
|
||||||
libriscv.a,./esp-idf/riscv/libriscv.a
|
|
||||||
libspi_flash.a,./esp-idf/spi_flash/libspi_flash.a
|
|
||||||
libesp_pm.a,./esp-idf/esp_pm/libesp_pm.a
|
|
||||||
libesp_phy.a,./esp-idf/esp_phy/libesp_phy.a
|
|
||||||
libnewlib.a,./esp-idf/newlib/libnewlib.a
|
|
||||||
libesp_wifi.a,./esp-idf/esp_wifi/libesp_wifi.a
|
|
||||||
libesp_netif.a,./esp-idf/esp_netif/libesp_netif.a
|
|
||||||
liblwip.a,./esp-idf/lwip/liblwip.a
|
|
||||||
libpp.a,$IDF_PATH/components/esp_wifi/lib/esp32c3/libpp.a
|
|
||||||
libnet80211.a,$IDF_PATH/components/esp_wifi/lib/esp32c3/libnet80211.a
|
|
||||||
libesp_mm.a,./esp-idf/esp_mm/libesp_mm.a
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
library,object,path
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_sleep.c.obj
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_clk.c.obj
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_time.c.obj
|
|
||||||
libesp_system.a,cpu_start.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj
|
|
||||||
libesp_system.a,panic_handler.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj
|
|
||||||
libesp_system.a,freertos_hooks.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj
|
|
||||||
libesp_system.a,task_wdt.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj
|
|
||||||
libesp_system.a,task_wdt_impl_timergroup.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_timergroup.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj
|
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj
|
|
||||||
libfreertos.a,portasm.S.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/portasm.S.obj
|
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj
|
|
||||||
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libhal.a,spi_flash_hal_iram.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj
|
|
||||||
libhal.a,cache_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj
|
|
||||||
libhal.a,systimer_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/systimer_hal.c.obj
|
|
||||||
libhal.a,mmu_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj
|
|
||||||
libhal.a,spi_flash_hal_gpspi.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj
|
|
||||||
libspi_flash.a,flash_mmap.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj
|
|
||||||
libspi_flash.a,cache_utils.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj
|
|
||||||
libnewlib.a,locks.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/locks.c.obj
|
|
||||||
libnewlib.a,assert.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/assert.c.obj
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c3/esp_adapter.c.obj
|
|
||||||
libesp_wifi.a,wifi_init.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj
|
|
||||||
libesp_netif.a,ethernetif.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/ethernetif.c.obj
|
|
||||||
libesp_netif.a,wlanif.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/wlanif.c.obj
|
|
||||||
libesp_netif.a,esp_pbuf_ref.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/esp_pbuf_ref.c.obj
|
|
||||||
libesp_netif.a,esp_netif_lwip.c.obj,esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip.c.obj
|
|
||||||
liblwip.a,sockets.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/sockets.c.obj
|
|
||||||
liblwip.a,api_lib.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_lib.c.obj
|
|
||||||
liblwip.a,api_msg.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_msg.c.obj
|
|
||||||
liblwip.a,netbuf.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netbuf.c.obj
|
|
||||||
liblwip.a,tcpip.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/tcpip.c.obj
|
|
||||||
liblwip.a,inet_chksum.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/inet_chksum.c.obj
|
|
||||||
liblwip.a,etharp.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/etharp.c.obj
|
|
||||||
liblwip.a,ip4_addr.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_addr.c.obj
|
|
||||||
liblwip.a,ip4.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4.c.obj
|
|
||||||
liblwip.a,pbuf.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/pbuf.c.obj
|
|
||||||
liblwip.a,udp.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/udp.c.obj
|
|
||||||
liblwip.a,ethernet.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ethernet.c.obj
|
|
||||||
liblwip.a,sys_arch.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/freertos/sys_arch.c.obj
|
|
||||||
liblwip.a,lwip_default_hooks.c.obj,esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/lwip_default_hooks.c.obj
|
|
||||||
libesp_mm.a,esp_mmu_map.c.obj,esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_mmu_map.c.obj
|
|
||||||
|
|
|
@ -1,327 +0,0 @@
|
||||||
library,object,function,option
|
|
||||||
libble_app.a,ble_hw.c.o,r_ble_hw_resolv_list_get_cur_entry,
|
|
||||||
libble_app.a,ble_ll_adv.c.o,r_ble_ll_adv_set_sched,
|
|
||||||
libble_app.a,ble_ll_adv.c.o,r_ble_ll_adv_sync_pdu_make,
|
|
||||||
libble_app.a,ble_ll_adv.c.o,r_ble_ll_adv_sync_calculate,
|
|
||||||
libble_app.a,ble_ll_conn.c.o,r_ble_ll_conn_is_dev_connected,
|
|
||||||
libble_app.a,ble_ll_ctrl.c.o,r_ble_ll_ctrl_tx_done,
|
|
||||||
libble_app.a,ble_lll_adv.c.o,r_ble_lll_adv_aux_scannable_pdu_payload_len,
|
|
||||||
libble_app.a,ble_lll_adv.c.o,r_ble_lll_adv_halt,
|
|
||||||
libble_app.a,ble_lll_adv.c.o,r_ble_lll_adv_periodic_schedule_next,
|
|
||||||
libble_app.a,ble_lll_conn.c.o,r_ble_lll_conn_cth_flow_free_credit,
|
|
||||||
libble_app.a,ble_lll_conn.c.o,r_ble_lll_conn_update_encryption,
|
|
||||||
libble_app.a,ble_lll_conn.c.o,r_ble_lll_conn_set_slave_flow_control,
|
|
||||||
libble_app.a,ble_lll_conn.c.o,r_ble_lll_init_rx_pkt_isr,
|
|
||||||
libble_app.a,ble_lll_conn.c.o,r_ble_lll_conn_get_rx_mbuf,
|
|
||||||
libble_app.a,ble_lll_rfmgmt.c.o,r_ble_lll_rfmgmt_enable,
|
|
||||||
libble_app.a,ble_lll_rfmgmt.c.o,r_ble_lll_rfmgmt_timer_reschedule,
|
|
||||||
libble_app.a,ble_lll_rfmgmt.c.o,r_ble_lll_rfmgmt_timer_exp,
|
|
||||||
libble_app.a,ble_lll_scan.c.o,r_ble_lll_scan_targeta_is_matched,
|
|
||||||
libble_app.a,ble_lll_scan.c.o,r_ble_lll_scan_rx_isr_on_legacy,
|
|
||||||
libble_app.a,ble_lll_scan.c.o,r_ble_lll_scan_rx_isr_on_aux,
|
|
||||||
libble_app.a,ble_lll_scan.c.o,r_ble_lll_scan_process_rsp_in_isr,
|
|
||||||
libble_app.a,ble_lll_scan.c.o,r_ble_lll_scan_rx_pkt_isr,
|
|
||||||
libble_app.a,ble_lll_sched.c.o,r_ble_lll_sched_execute_check,
|
|
||||||
libble_app.a,ble_lll_sync.c.o,r_ble_lll_sync_event_start_cb,
|
|
||||||
libble_app.a,ble_phy.c.o,r_ble_phy_set_rxhdr,
|
|
||||||
libble_app.a,ble_phy.c.o,r_ble_phy_update_conn_sequence,
|
|
||||||
libble_app.a,ble_phy.c.o,r_ble_phy_set_sequence_mode,
|
|
||||||
libble_app.a,ble_phy.c.o,r_ble_phy_txpower_round,
|
|
||||||
libble_app.a,os_mempool.c.obj,r_os_memblock_put,
|
|
||||||
libbootloader_support.a,bootloader_flash.c.obj,bootloader_read_flash_id,
|
|
||||||
libbootloader_support.a,flash_encrypt.c.obj,esp_flash_encryption_enabled,
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_calloc,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_malloc,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_malloc_internal,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_free,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,esp_reset_rpa_moudle,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,osi_assert_wrapper,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,osi_random_wrapper,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,nimble_port.c.obj,nimble_port_run,CONFIG_BT_NIMBLE_ENABLED
|
|
||||||
libbt.a,nimble_port.c.obj,nimble_port_get_dflt_eventq,CONFIG_BT_NIMBLE_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,os_callout_timer_cb,CONFIG_BT_ENABLED && !CONFIG_BT_NIMBLE_USE_ESP_TIMER
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_event_run,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_stop,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_time_get,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_reset,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_is_active,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_get_ticks,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_remaining_ticks,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_time_delay,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_eventq_is_empty,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_mutex_pend,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_mutex_release,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_sem_init,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_sem_pend,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_sem_release,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_init,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_deinit,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_event_is_queued,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_event_get_arg,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_time_ms_to_ticks32,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_time_ticks_to_ms32,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_hw_is_in_critical,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_get_time_forever,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_os_started,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_get_current_task_id,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_event_reset,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_mem_reset,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_event_init,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_sem_get_count,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_eventq_remove,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_hw_exit_critical,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_mutex_init,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_hw_enter_critical,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_eventq_put,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_eventq_get,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_sem_deinit,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_mutex_deinit,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_eventq_deinit,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_eventq_init,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_event_deinit,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_time_ticks_to_ms,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_time_ms_to_ticks,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_callout_set_arg,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,npl_os_freertos.c.obj,npl_freertos_event_set_arg,CONFIG_BT_ENABLED
|
|
||||||
libesp_driver_gpio.a,gpio.c.obj,gpio_intr_service,
|
|
||||||
libesp_app_format.a,esp_app_desc.c.obj,esp_app_get_elf_sha256,
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_wait_for_intr,
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_reset,
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_cpu_freq,
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_apb_freq,
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_xtal_freq,
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp_ptr_byte_accessible,
|
|
||||||
libesp_hw_support.a,hw_random.c.obj,esp_random,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,shared_intr_isr,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_noniram_disable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_noniram_enable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_enable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_disable,
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_enable,
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_disable,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_read_reg,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_read_reg_mask,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_write_reg,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_write_reg_mask,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_enter_critical,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_exit_critical,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_analog_cali_reg_read,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_analog_cali_reg_write,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_enable,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_disable,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_wifi_bt_power_domain_on,
|
|
||||||
libesp_phy.a,phy_override.c.obj,phy_i2c_enter_critical,
|
|
||||||
libesp_phy.a,phy_override.c.obj,phy_i2c_exit_critical,
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_acquire,
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_release,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,get_lowest_allowed_mode,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_switch_mode,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,on_freq_update,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,vApplicationSleep,CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,do_switch,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvCheckItemAvail,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvGetFreeSize,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvReceiveGenericFromISR,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,xRingbufferGetMaxItemSize,
|
|
||||||
libesp_system.a,brownout.c.obj,rtc_brownout_isr_handler,
|
|
||||||
libesp_system.a,cache_err_int.c.obj,esp_cache_err_get_cpuid,
|
|
||||||
libesp_system.a,cpu_start.c.obj,call_start_cpu0,
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send,
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send_yield,
|
|
||||||
libesp_system.a,esp_system.c.obj,esp_restart,
|
|
||||||
libesp_system.a,esp_system_chip.c.obj,esp_system_abort,
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp_reset_reason_set_hint,
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp_reset_reason_get_hint,
|
|
||||||
libesp_system.a,ubsan.c.obj,__ubsan_include,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_next_alarm_for_wake_up,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_unlock,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_lock,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_armed,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_remove,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_insert,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_start_once,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_start_periodic,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_stop,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_expiry_time,
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_get_time,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_set_alarm_id,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_update_apb_freq,
|
|
||||||
libesp_timer.a,esp_timer_impl_common.c.obj,esp_timer_impl_get_min_period_us,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,timer_initialized,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_arm_us,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_arm,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_disarm,
|
|
||||||
libesp_timer.a,system_time.c.obj,esp_system_get_time,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,semphr_take_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_realloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_event_duration_get_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_schm_interval_set_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp_empty_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_calloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_zalloc_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,env_is_chip_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,is_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,semphr_give_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,mutex_lock_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,mutex_unlock_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,task_ms_to_tick_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_request_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_release_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_arm_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_malloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_disarm_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_arm_us_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_rtc_enable_iso_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_rtc_disable_iso_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,malloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,realloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,calloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,zalloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_status_get_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_wifi_release_wrapper,
|
|
||||||
libfreertos.a,list.c.obj,uxListRemove,FALSE
|
|
||||||
libfreertos.a,list.c.obj,vListInitialise,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInitialiseItem,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInsert,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInsertEnd,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vApplicationStackOverflowHook,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vPortYieldOtherCore,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vPortYield,
|
|
||||||
libfreertos.a,port_common.c.obj,xPortcheckValidStackMem,
|
|
||||||
libfreertos.a,port_common.c.obj,vApplicationGetTimerTaskMemory,
|
|
||||||
libfreertos.a,port_common.c.obj,esp_startup_start_app_common,
|
|
||||||
libfreertos.a,heap_idf.c.obj,xPortCheckValidTCBMem,
|
|
||||||
libfreertos.a,port_common.c.obj,vApplicationGetIdleTaskMemory,
|
|
||||||
libfreertos.a,port_systick.c.obj,vPortSetupTimer,
|
|
||||||
libfreertos.a,port_systick.c.obj,xPortSysTickHandler,FALSE
|
|
||||||
libfreertos.a,queue.c.obj,prvCopyDataFromQueue,
|
|
||||||
libfreertos.a,queue.c.obj,prvGetDisinheritPriorityAfterTimeout,
|
|
||||||
libfreertos.a,queue.c.obj,prvIsQueueEmpty,
|
|
||||||
libfreertos.a,queue.c.obj,prvNotifyQueueSetContainer,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceive,
|
|
||||||
libfreertos.a,queue.c.obj,prvUnlockQueue,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueSemaphoreTake,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceiveFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,uxQueueMessagesWaitingFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueIsQueueEmptyFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueGiveFromISR,
|
|
||||||
libfreertos.a,tasks.c.obj,__getreent,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,pcTaskGetName,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvAddCurrentTaskToDelayedList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvDeleteTLS,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,pvTaskIncrementMutexHeldCount,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,taskSelectHighestPriorityTaskSMP,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,taskYIELD_OTHER_CORE,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskGetSnapshot,CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskInternalSetTimeOutState,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnEventList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnEventListRestricted,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnUnorderedEventList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPriorityDisinheritAfterTimeout,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskReleaseEventListLock,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskTakeEventListLock,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskCheckForTimeOut,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetCurrentTaskHandle,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetSchedulerState,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetTickCount,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskPriorityDisinherit,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskPriorityInherit,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvGetExpectedIdleTime,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskStepTick,FALSE
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_chip_revision,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_major_chip_version,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_minor_chip_version,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_blk_version,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_disable_wafer_version_major,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_disable_blk_version_major,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_flash_encryption_enabled,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_free,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_aligned_alloc_base,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_malloc_base,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_realloc_base,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_calloc_base,
|
|
||||||
libheap.a,heap_caps.c.obj,hex_to_str,CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
|
|
||||||
libheap.a,heap_caps.c.obj,fmt_abort_str,CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_alloc_failed,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc_prefer,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc_prefer,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_calloc_prefer,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_calloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_aligned_alloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_aligned_alloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_aligned_free,
|
|
||||||
libheap.a,multi_heap.c.obj,_multi_heap_lock,
|
|
||||||
libheap.a,multi_heap.c.obj,multi_heap_in_rom_init,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_timestamp,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_lock,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_unlock,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_lock_timeout,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_early_timestamp,
|
|
||||||
liblog.a,log.c.obj,esp_log_write,
|
|
||||||
liblog.a,log.c.obj,esp_log_writev,
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp_mbedtls_mem_calloc,!CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp_mbedtls_mem_free,!CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC
|
|
||||||
libnewlib.a,assert.c.obj,__assert_func,
|
|
||||||
libnewlib.a,assert.c.obj,newlib_include_assert_impl,
|
|
||||||
libnewlib.a,heap.c.obj,_calloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,_free_r,
|
|
||||||
libnewlib.a,heap.c.obj,_malloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,_realloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,calloc,
|
|
||||||
libnewlib.a,heap.c.obj,cfree,
|
|
||||||
libnewlib.a,heap.c.obj,free,
|
|
||||||
libnewlib.a,heap.c.obj,malloc,
|
|
||||||
libnewlib.a,heap.c.obj,newlib_include_heap_impl,
|
|
||||||
libnewlib.a,heap.c.obj,realloc,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_try_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,lock_release_generic,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_init,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_init_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_close,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_close_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,check_lock_nonzero,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,lock_init_generic,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_try_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_try_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_release,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_release_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_close,
|
|
||||||
libnewlib.a,locks.c.obj,lock_acquire_generic,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_try_acquire,
|
|
||||||
libnewlib.a,reent_init.c.obj,esp_reent_init,
|
|
||||||
libnewlib.a,time.c.obj,_times_r,
|
|
||||||
libnewlib.a,time.c.obj,_gettimeofday_r,
|
|
||||||
libpp.a,pp_debug.o,wifi_gpio_debug,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_lock_internal,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_lock,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_unlock,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_handler_get,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_handler_set,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_matrix_route,
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,spi_flash_needs_reset_check,FALSE
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,spi_flash_set_erasing_flag,FALSE
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_guard_set,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_malloc_internal,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_rom_impl_init,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,esp_mspi_pin_init,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_init_chip_state,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,delay_us,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,get_buffer_malloc,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,release_buffer_malloc,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,main_flash_region_protected,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,main_flash_op_status,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,spi1_flash_os_check_yield,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,spi1_flash_os_yield,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,start,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,end,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,delay_us,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
library,path
|
|
||||||
libble_app.a,$IDF_PATH/components/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app.a
|
|
||||||
libpp.a,$IDF_PATH/components/esp_wifi/lib/esp32c2/libpp.a
|
|
||||||
libbootloader_support.a,./esp-idf/bootloader_support/libbootloader_support.a
|
|
||||||
libbt.a,./esp-idf/bt/libbt.a
|
|
||||||
libesp_driver_gpio.a,./esp-idf/esp_driver_gpio/libesp_driver_gpio.a
|
|
||||||
libesp_app_format.a,./esp-idf/esp_app_format/libesp_app_format.a
|
|
||||||
libesp_hw_support.a,./esp-idf/esp_hw_support/libesp_hw_support.a
|
|
||||||
libesp_phy.a,./esp-idf/esp_phy/libesp_phy.a
|
|
||||||
libesp_pm.a,./esp-idf/esp_pm/libesp_pm.a
|
|
||||||
libesp_ringbuf.a,./esp-idf/esp_ringbuf/libesp_ringbuf.a
|
|
||||||
libesp_rom.a,./esp-idf/esp_rom/libesp_rom.a
|
|
||||||
libesp_system.a,./esp-idf/esp_system/libesp_system.a
|
|
||||||
libesp_timer.a,./esp-idf/esp_timer/libesp_timer.a
|
|
||||||
libesp_wifi.a,./esp-idf/esp_wifi/libesp_wifi.a
|
|
||||||
libfreertos.a,./esp-idf/freertos/libfreertos.a
|
|
||||||
libhal.a,./esp-idf/hal/libhal.a
|
|
||||||
libheap.a,./esp-idf/heap/libheap.a
|
|
||||||
liblog.a,./esp-idf/log/liblog.a
|
|
||||||
libmbedcrypto.a,./esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a
|
|
||||||
libnewlib.a,./esp-idf/newlib/libnewlib.a
|
|
||||||
libpthread.a,./esp-idf/pthread/libpthread.a
|
|
||||||
libriscv.a,./esp-idf/riscv/libriscv.a
|
|
||||||
libspi_flash.a,./esp-idf/spi_flash/libspi_flash.a
|
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
library,object,path
|
|
||||||
libbootloader_support.a,bootloader_flash.c.obj,esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj
|
|
||||||
libbootloader_support.a,flash_encrypt.c.obj,esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj
|
|
||||||
libbt.a,bt_osi_mem.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/porting/mem/bt_osi_mem.c.obj
|
|
||||||
libbt.a,bt.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/controller/esp32c2/bt.c.obj
|
|
||||||
libbt.a,npl_os_freertos.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/porting/npl/freertos/src/npl_os_freertos.c.obj
|
|
||||||
libbt.a,nimble_port.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/host/nimble/nimble/porting/nimble/src/nimble_port.c.obj
|
|
||||||
libesp_driver_gpio.a,gpio.c.obj,esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio.c.obj
|
|
||||||
libesp_app_format.a,esp_app_desc.c.obj,esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj
|
|
||||||
libesp_hw_support.a,hw_random.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c2/rtc_clk.c.obj
|
|
||||||
libesp_hw_support.a,rtc_init.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c2/rtc_init.c.obj
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c2/rtc_sleep.c.obj
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c2/rtc_time.c.obj
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj
|
|
||||||
libesp_phy.a,phy_override.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj
|
|
||||||
libesp_rom.a,esp_rom_uart.c.obj,esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj
|
|
||||||
libesp_system.a,brownout.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/brownout.c.obj
|
|
||||||
libesp_system.a,cache_err_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c2/cache_err_int.c.obj
|
|
||||||
libesp_system.a,cpu_start.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj
|
|
||||||
libesp_system.a,esp_system.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c2/reset_reason.c.obj
|
|
||||||
libesp_system.a,ubsan.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj
|
|
||||||
libesp_system.a,esp_system_chip.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_system_chip.c.obj
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_common.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_common.c.obj
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj
|
|
||||||
libesp_timer.a,system_time.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c2/esp_adapter.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj
|
|
||||||
libfreertos.a,heap_idf.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/heap_idf.c.obj
|
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj
|
|
||||||
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
|
||||||
libhal.a,brownout_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/brownout_hal.c.obj
|
|
||||||
libhal.a,efuse_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj
|
|
||||||
libhal.a,efuse_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32c2/efuse_hal.c.obj
|
|
||||||
libheap.a,heap_caps_base.c.obj,esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_base.c.obj
|
|
||||||
libheap.a,heap_caps.c.obj,esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj
|
|
||||||
libheap.a,multi_heap.c.obj,./esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj
|
|
||||||
liblog.a,log_freertos.c.obj,esp-idf/log/CMakeFiles/__idf_log.dir/log_freertos.c.obj
|
|
||||||
liblog.a,log.c.obj,esp-idf/log/CMakeFiles/__idf_log.dir/log.c.obj
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/$IDF_PATH/components/mbedtls/port/esp_mem.c.obj
|
|
||||||
libnewlib.a,assert.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/assert.c.obj
|
|
||||||
libnewlib.a,heap.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/heap.c.obj
|
|
||||||
libnewlib.a,locks.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/locks.c.obj
|
|
||||||
libnewlib.a,reent_init.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/reent_init.c.obj
|
|
||||||
libnewlib.a,time.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/time.c.obj
|
|
||||||
libpthread.a,pthread.c.obj,esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj
|
|
||||||
libriscv.a,interrupt.c.obj,esp-idf/riscv/CMakeFiles/__idf_riscv.dir/interrupt.c.obj
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj
|
|
||||||
libspi_flash.a,flash_ops.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj
|
|
||||||
|
|
|
@ -1,291 +0,0 @@
|
||||||
library,object,function,option
|
|
||||||
libbootloader_support.a,bootloader_flash.c.obj,bootloader_read_flash_id,
|
|
||||||
libbootloader_support.a,flash_encrypt.c.obj,esp_flash_encryption_enabled,
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_calloc,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_malloc,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_malloc_internal,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_free,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,esp_reset_rpa_moudle,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,osi_assert_wrapper,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,osi_random_wrapper,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,nimble_port.c.obj,nimble_port_run,CONFIG_BT_NIMBLE_ENABLED
|
|
||||||
libbt.a,nimble_port.c.obj,nimble_port_get_dflt_eventq,CONFIG_BT_NIMBLE_ENABLED
|
|
||||||
libdriver.a,gpio.c.obj,gpio_intr_service,
|
|
||||||
libesp_app_format.a,esp_app_desc.c.obj,esp_app_get_elf_sha256,
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_wait_for_intr,
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_reset,
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_cpu_freq,FALSE
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_apb_freq,FALSE
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_xtal_freq,
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp_ptr_byte_accessible,
|
|
||||||
libesp_hw_support.a,hw_random.c.obj,esp_random,FALSE
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,shared_intr_isr,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_noniram_disable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_noniram_enable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_enable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_disable,
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_enable,
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_disable,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_read_reg,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_read_reg_mask,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_write_reg,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_write_reg_mask,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_enter_critical,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_exit_critical,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_analog_cali_reg_read,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_analog_cali_reg_write,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_32k_enable_external,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_fast_src_set,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_freq_get_hz,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_src_get,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_slow_src_set,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_dig_clk8m_disable,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_config_fast,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_8m_enable,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_8md256_enabled,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_configure,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_enable,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_get_config,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_mhz_to_config,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_config,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_8m,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_pll_mhz,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_set_xtal,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_xtal_freq_get,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_cpu_freq_to_xtal,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_bbpll_disable,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,rtc_clk_apb_freq_update,
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,clk_ll_rtc_slow_get_src,FALSE
|
|
||||||
libesp_hw_support.a,rtc_init.c.obj,rtc_vddsdio_set_config,
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr,
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr_noniram_disable,
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,rtc_isr_noniram_enable,
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_pu,
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_finish,
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_get_default_config,
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_init,
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_low_init,
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,rtc_sleep_start,
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_clk_cal,
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_clk_cal_internal,
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_get,
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_us_to_slowclk,
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,rtc_time_slowclk_to_us,
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,periph_ll_periph_enabled,
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,flush_uarts,
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,suspend_uarts,
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,resume_uarts,
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp_sleep_start,
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp_deep_sleep_start,
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp_light_sleep_inner,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_enable,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_disable,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_wifi_bt_power_domain_on,
|
|
||||||
libesp_phy.a,phy_override.c.obj,phy_i2c_enter_critical,
|
|
||||||
libesp_phy.a,phy_override.c.obj,phy_i2c_exit_critical,
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_acquire,
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_release,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,get_lowest_allowed_mode,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_switch_mode,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,on_freq_update,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,vApplicationSleep,CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,do_switch,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvCheckItemAvail,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvGetFreeSize,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvReceiveGenericFromISR,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,xRingbufferGetMaxItemSize,
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_init,
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_set_alarm_period,
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_set_alarm_target,
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_set_tick_rate_ops,
|
|
||||||
libesp_rom.a,esp_rom_uart.c.obj,esp_rom_uart_set_clock_baudrate,
|
|
||||||
libesp_system.a,brownout.c.obj,rtc_brownout_isr_handler,
|
|
||||||
libesp_system.a,cache_err_int.c.obj,esp_cache_err_get_cpuid,
|
|
||||||
libesp_system.a,cpu_start.c.obj,call_start_cpu0,
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send,
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send_yield,
|
|
||||||
libesp_system.a,esp_system.c.obj,esp_restart,
|
|
||||||
libesp_system.a,esp_system.c.obj,esp_system_abort,
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp_reset_reason_set_hint,
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp_reset_reason_get_hint,
|
|
||||||
libesp_system.a,ubsan.c.obj,__ubsan_include,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_next_alarm_for_wake_up,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_unlock,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_lock,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_armed,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_remove,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_insert,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_start_once,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_start_periodic,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_stop,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_expiry_time,
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_get_time,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_set_alarm_id,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_update_apb_freq,
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_get_min_period_us,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,timer_initialized,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_arm_us,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_arm,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_disarm,
|
|
||||||
libesp_timer.a,system_time.c.obj,esp_system_get_time,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,semphr_take_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_realloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_event_duration_get_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_schm_interval_set_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp_empty_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_calloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_zalloc_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,env_is_chip_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,is_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,semphr_give_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,mutex_lock_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,mutex_unlock_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,task_ms_to_tick_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_request_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_release_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_arm_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_malloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_disarm_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_arm_us_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_rtc_enable_iso_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_rtc_disable_iso_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,malloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,realloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,calloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,zalloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_status_get_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_wifi_release_wrapper,
|
|
||||||
libfreertos.a,list.c.obj,uxListRemove,FALSE
|
|
||||||
libfreertos.a,list.c.obj,vListInitialise,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInitialiseItem,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInsert,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInsertEnd,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vApplicationStackOverflowHook,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vPortYieldOtherCore,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vPortYield,
|
|
||||||
libfreertos.a,port_common.c.obj,xPortcheckValidStackMem,
|
|
||||||
libfreertos.a,port_common.c.obj,vApplicationGetTimerTaskMemory,
|
|
||||||
libfreertos.a,port_common.c.obj,esp_startup_start_app_common,
|
|
||||||
libfreertos.a,port_common.c.obj,xPortCheckValidTCBMem,
|
|
||||||
libfreertos.a,port_common.c.obj,vApplicationGetIdleTaskMemory,
|
|
||||||
libfreertos.a,port_systick.c.obj,vPortSetupTimer,
|
|
||||||
libfreertos.a,port_systick.c.obj,xPortSysTickHandler,FALSE
|
|
||||||
libfreertos.a,queue.c.obj,prvCopyDataFromQueue,
|
|
||||||
libfreertos.a,queue.c.obj,prvGetDisinheritPriorityAfterTimeout,
|
|
||||||
libfreertos.a,queue.c.obj,prvIsQueueEmpty,
|
|
||||||
libfreertos.a,queue.c.obj,prvNotifyQueueSetContainer,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceive,
|
|
||||||
libfreertos.a,queue.c.obj,prvUnlockQueue,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueSemaphoreTake,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceiveFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,uxQueueMessagesWaitingFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueIsQueueEmptyFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueGiveFromISR,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,__getreent,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,pcTaskGetName,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvAddCurrentTaskToDelayedList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvDeleteTLS,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,pvTaskIncrementMutexHeldCount,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,taskSelectHighestPriorityTaskSMP,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,taskYIELD_OTHER_CORE,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskGetSnapshot,CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskInternalSetTimeOutState,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnEventList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnEventListRestricted,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnUnorderedEventList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPriorityDisinheritAfterTimeout,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskReleaseEventListLock,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskTakeEventListLock,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskCheckForTimeOut,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetCurrentTaskHandle,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetSchedulerState,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetTickCount,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskPriorityDisinherit,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskPriorityInherit,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvGetExpectedIdleTime,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskStepTick,FALSE
|
|
||||||
libhal.a,brownout_hal.c.obj,brownout_hal_intr_clear,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_chip_revision,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_major_chip_version,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_minor_chip_version,
|
|
||||||
libheap.a,heap_caps.c.obj,dram_alloc_to_iram_addr,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_free,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc_base,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_calloc_base,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_calloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc_base,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,find_containing_heap,
|
|
||||||
libheap.a,multi_heap.c.obj,_multi_heap_lock,
|
|
||||||
libheap.a,multi_heap.c.obj,multi_heap_in_rom_init,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_timestamp,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_lock,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_unlock,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_lock_timeout,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_early_timestamp,
|
|
||||||
liblog.a,log.c.obj,esp_log_write,
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp_mbedtls_mem_calloc,!CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp_mbedtls_mem_free,!CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC
|
|
||||||
libnewlib.a,assert.c.obj,__assert_func,
|
|
||||||
libnewlib.a,assert.c.obj,newlib_include_assert_impl,
|
|
||||||
libnewlib.a,heap.c.obj,_calloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,_free_r,
|
|
||||||
libnewlib.a,heap.c.obj,_malloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,_realloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,calloc,
|
|
||||||
libnewlib.a,heap.c.obj,cfree,
|
|
||||||
libnewlib.a,heap.c.obj,free,
|
|
||||||
libnewlib.a,heap.c.obj,malloc,
|
|
||||||
libnewlib.a,heap.c.obj,newlib_include_heap_impl,
|
|
||||||
libnewlib.a,heap.c.obj,realloc,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_try_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,lock_release_generic,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_init,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_init_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_close,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_close_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,check_lock_nonzero,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,lock_init_generic,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_try_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_try_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_release,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_release_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_close,
|
|
||||||
libnewlib.a,locks.c.obj,lock_acquire_generic,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_try_acquire,
|
|
||||||
libnewlib.a,reent_init.c.obj,esp_reent_init,
|
|
||||||
libnewlib.a,time.c.obj,_times_r,
|
|
||||||
libnewlib.a,time.c.obj,_gettimeofday_r,
|
|
||||||
libpp.a,pp_debug.o,wifi_gpio_debug,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_lock_internal,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_lock,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_unlock,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_handler_get,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_handler_set,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_matrix_route,
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,spi_flash_needs_reset_check,FALSE
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,spi_flash_set_erasing_flag,FALSE
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_guard_set,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_malloc_internal,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_rom_impl_init,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,esp_mspi_pin_init,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_init_chip_state,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,delay_us,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,get_buffer_malloc,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,release_buffer_malloc,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,main_flash_region_protected,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,main_flash_op_status,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,spi1_flash_os_check_yield,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,spi1_flash_os_yield,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,start,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,end,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,delay_us,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
library,path
|
|
||||||
libbtdm_app.a,$IDF_PATH/components/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app.a
|
|
||||||
libpp.a,$IDF_PATH/components/esp_wifi/lib/esp32c3/libpp.a
|
|
||||||
libbootloader_support.a,./esp-idf/bootloader_support/libbootloader_support.a
|
|
||||||
libbt.a,./esp-idf/bt/libbt.a
|
|
||||||
libdriver.a,./esp-idf/driver/libdriver.a
|
|
||||||
libesp_app_format.a,./esp-idf/esp_app_format/libesp_app_format.a
|
|
||||||
libesp_hw_support.a,./esp-idf/esp_hw_support/libesp_hw_support.a
|
|
||||||
libesp_phy.a,./esp-idf/esp_phy/libesp_phy.a
|
|
||||||
libesp_pm.a,./esp-idf/esp_pm/libesp_pm.a
|
|
||||||
libesp_ringbuf.a,./esp-idf/esp_ringbuf/libesp_ringbuf.a
|
|
||||||
libesp_rom.a,./esp-idf/esp_rom/libesp_rom.a
|
|
||||||
libesp_system.a,./esp-idf/esp_system/libesp_system.a
|
|
||||||
libesp_timer.a,./esp-idf/esp_timer/libesp_timer.a
|
|
||||||
libesp_wifi.a,./esp-idf/esp_wifi/libesp_wifi.a
|
|
||||||
libfreertos.a,./esp-idf/freertos/libfreertos.a
|
|
||||||
libhal.a,./esp-idf/hal/libhal.a
|
|
||||||
libheap.a,./esp-idf/heap/libheap.a
|
|
||||||
liblog.a,./esp-idf/log/liblog.a
|
|
||||||
libmbedcrypto.a,./esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a
|
|
||||||
libnewlib.a,./esp-idf/newlib/libnewlib.a
|
|
||||||
libpthread.a,./esp-idf/pthread/libpthread.a
|
|
||||||
libriscv.a,./esp-idf/riscv/libriscv.a
|
|
||||||
libspi_flash.a,./esp-idf/spi_flash/libspi_flash.a
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
library,object,path
|
|
||||||
libbootloader_support.a,bootloader_flash.c.obj,esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj
|
|
||||||
libbootloader_support.a,flash_encrypt.c.obj,esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj
|
|
||||||
libbt.a,bt_osi_mem.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/porting/mem/bt_osi_mem.c.obj
|
|
||||||
libbt.a,bt.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/controller/esp32c3/bt.c.obj
|
|
||||||
libbt.a,nimble_port.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/host/nimble/nimble/porting/nimble/src/nimble_port.c.obj
|
|
||||||
libdriver.a,gpio.c.obj,esp-idf/driver/CMakeFiles/__idf_driver.dir/gpio/gpio.c.obj
|
|
||||||
libesp_app_format.a,esp_app_desc.c.obj,esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj
|
|
||||||
libesp_hw_support.a,hw_random.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_clk.c.obj
|
|
||||||
libesp_hw_support.a,rtc_init.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_init.c.obj
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_sleep.c.obj
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_time.c.obj
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj
|
|
||||||
libesp_phy.a,phy_override.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj
|
|
||||||
libesp_rom.a,esp_rom_uart.c.obj,esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj
|
|
||||||
libesp_system.a,brownout.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/brownout.c.obj
|
|
||||||
libesp_system.a,cache_err_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c3/cache_err_int.c.obj
|
|
||||||
libesp_system.a,cpu_start.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj
|
|
||||||
libesp_system.a,esp_system.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c3/reset_reason.c.obj
|
|
||||||
libesp_system.a,ubsan.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj
|
|
||||||
libesp_timer.a,system_time.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c3/esp_adapter.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj
|
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/port_systick.c.obj
|
|
||||||
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
|
||||||
libhal.a,brownout_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32c3/brownout_hal.c.obj
|
|
||||||
libhal.a,efuse_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj
|
|
||||||
libhal.a,efuse_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32c3/efuse_hal.c.obj
|
|
||||||
libheap.a,heap_caps.c.obj,esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj
|
|
||||||
libheap.a,multi_heap.c.obj,./esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj
|
|
||||||
liblog.a,log_freertos.c.obj,esp-idf/log/CMakeFiles/__idf_log.dir/log_freertos.c.obj
|
|
||||||
liblog.a,log.c.obj,esp-idf/log/CMakeFiles/__idf_log.dir/log.c.obj
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/$IDF_PATH/components/mbedtls/port/esp_mem.c.obj
|
|
||||||
libnewlib.a,assert.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/assert.c.obj
|
|
||||||
libnewlib.a,heap.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/heap.c.obj
|
|
||||||
libnewlib.a,locks.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/locks.c.obj
|
|
||||||
libnewlib.a,reent_init.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/reent_init.c.obj
|
|
||||||
libnewlib.a,time.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/time.c.obj
|
|
||||||
libpthread.a,pthread.c.obj,esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj
|
|
||||||
libriscv.a,interrupt.c.obj,esp-idf/riscv/CMakeFiles/__idf_riscv.dir/interrupt.c.obj
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj
|
|
||||||
libspi_flash.a,flash_ops.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj
|
|
||||||
|
|
|
@ -1,258 +0,0 @@
|
||||||
library,object,function,option
|
|
||||||
libbootloader_support.a,bootloader_flash.c.obj,bootloader_read_flash_id,
|
|
||||||
libbootloader_support.a,flash_encrypt.c.obj,esp_flash_encryption_enabled,
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_calloc,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_malloc,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_malloc_internal,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt_osi_mem.c.obj,bt_osi_mem_free,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,esp_reset_rpa_moudle,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,osi_assert_wrapper,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,bt.c.obj,osi_random_wrapper,CONFIG_BT_ENABLED
|
|
||||||
libbt.a,nimble_port.c.obj,nimble_port_run,CONFIG_BT_NIMBLE_ENABLED
|
|
||||||
libbt.a,nimble_port.c.obj,nimble_port_get_dflt_eventq,CONFIG_BT_NIMBLE_ENABLED
|
|
||||||
libesp_driver_gpio.a,gpio.c.obj,gpio_intr_service,
|
|
||||||
libesp_app_format.a,esp_app_desc.c.obj,esp_app_get_elf_sha256,
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_wait_for_intr,
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp_cpu_reset,
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_cpu_freq,FALSE
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_apb_freq,FALSE
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp_clk_xtal_freq,
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp_ptr_byte_accessible,
|
|
||||||
libesp_hw_support.a,hw_random.c.obj,esp_random,FALSE
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,shared_intr_isr,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_noniram_disable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_noniram_enable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_enable,
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp_intr_disable,
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_enable,
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,wifi_bt_common_module_disable,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_read_reg,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_read_reg_mask,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_write_reg,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_ctrl_write_reg_mask,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_enter_critical,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_exit_critical,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_analog_cali_reg_read,
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,regi2c_analog_cali_reg_write,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_enable,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_phy_common_clock_disable,
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp_wifi_bt_power_domain_on,
|
|
||||||
libesp_phy.a,phy_override.c.obj,phy_i2c_enter_critical,
|
|
||||||
libesp_phy.a,phy_override.c.obj,phy_i2c_exit_critical,
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_acquire,
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp_pm_lock_release,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,get_lowest_allowed_mode,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp_pm_impl_switch_mode,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,on_freq_update,
|
|
||||||
libesp_pm.a,pm_impl.c.obj,vApplicationSleep,CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
||||||
libesp_pm.a,pm_impl.c.obj,do_switch,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvCheckItemAvail,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvGetFreeSize,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,prvReceiveGenericFromISR,
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,xRingbufferGetMaxItemSize,
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_init,CONFIG_HAL_SYSTIMER_USE_ROM_IMPL
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_set_alarm_period,CONFIG_HAL_SYSTIMER_USE_ROM_IMPL
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_set_alarm_target,CONFIG_HAL_SYSTIMER_USE_ROM_IMPL
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,systimer_hal_set_tick_rate_ops,CONFIG_HAL_SYSTIMER_USE_ROM_IMPL
|
|
||||||
libesp_system.a,brownout.c.obj,rtc_brownout_isr_handler,
|
|
||||||
libesp_system.a,cache_err_int.c.obj,esp_cache_err_get_cpuid,
|
|
||||||
libesp_system.a,cpu_start.c.obj,call_start_cpu0,
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send,
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp_crosscore_int_send_yield,
|
|
||||||
libesp_system.a,esp_system.c.obj,esp_restart,
|
|
||||||
libesp_system.a,esp_system_chip.c.obj,esp_system_abort,
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp_reset_reason_set_hint,
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp_reset_reason_get_hint,
|
|
||||||
libesp_system.a,ubsan.c.obj,__ubsan_include,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_next_alarm_for_wake_up,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_unlock,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_list_lock,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_armed,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_remove,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,timer_insert,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_start_once,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_start_periodic,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_stop,
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp_timer_get_expiry_time,
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_get_time,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_set_alarm_id,!CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp_timer_impl_update_apb_freq,
|
|
||||||
libesp_timer.a,esp_timer_impl_common.c.obj,esp_timer_impl_get_min_period_us,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,timer_initialized,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_arm_us,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_arm,
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,ets_timer_disarm,
|
|
||||||
libesp_timer.a,system_time.c.obj,esp_system_get_time,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,semphr_take_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_realloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_event_duration_get_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_schm_interval_set_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp_empty_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_calloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_zalloc_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,env_is_chip_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,is_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,semphr_give_from_isr_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,mutex_lock_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,mutex_unlock_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,task_ms_to_tick_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_request_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_apb80m_release_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_arm_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_malloc,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_disarm_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,timer_arm_us_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_rtc_enable_iso_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,wifi_rtc_disable_iso_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,malloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,realloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,calloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,zalloc_internal_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_status_get_wrapper,
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,coex_wifi_release_wrapper,
|
|
||||||
libfreertos.a,list.c.obj,uxListRemove,FALSE
|
|
||||||
libfreertos.a,list.c.obj,vListInitialise,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInitialiseItem,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInsert,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,list.c.obj,vListInsertEnd,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vApplicationStackOverflowHook,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vPortYieldOtherCore,FALSE
|
|
||||||
libfreertos.a,port.c.obj,vPortYield,
|
|
||||||
libfreertos.a,port_common.c.obj,xPortcheckValidStackMem,
|
|
||||||
libfreertos.a,port_common.c.obj,vApplicationGetTimerTaskMemory,
|
|
||||||
libfreertos.a,port_common.c.obj,esp_startup_start_app_common,
|
|
||||||
libfreertos.a,heap_idf.c.obj,xPortCheckValidTCBMem,
|
|
||||||
libfreertos.a,port_common.c.obj,vApplicationGetIdleTaskMemory,
|
|
||||||
libfreertos.a,port_systick.c.obj,vPortSetupTimer,
|
|
||||||
libfreertos.a,port_systick.c.obj,xPortSysTickHandler,FALSE
|
|
||||||
libfreertos.a,queue.c.obj,prvCopyDataFromQueue,
|
|
||||||
libfreertos.a,queue.c.obj,prvGetDisinheritPriorityAfterTimeout,
|
|
||||||
libfreertos.a,queue.c.obj,prvIsQueueEmpty,
|
|
||||||
libfreertos.a,queue.c.obj,prvNotifyQueueSetContainer,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceive,
|
|
||||||
libfreertos.a,queue.c.obj,prvUnlockQueue,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueSemaphoreTake,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueReceiveFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,uxQueueMessagesWaitingFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueIsQueueEmptyFromISR,
|
|
||||||
libfreertos.a,queue.c.obj,xQueueGiveFromISR,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,__getreent,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,pcTaskGetName,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvAddCurrentTaskToDelayedList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvDeleteTLS,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,pvTaskIncrementMutexHeldCount,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,taskSelectHighestPriorityTaskSMP,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,taskYIELD_OTHER_CORE,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskGetSnapshot,CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskInternalSetTimeOutState,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnEventList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnEventListRestricted,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPlaceOnUnorderedEventList,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskPriorityDisinheritAfterTimeout,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskReleaseEventListLock,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskTakeEventListLock,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskCheckForTimeOut,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetCurrentTaskHandle,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetSchedulerState,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskGetTickCount,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskPriorityDisinherit,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,xTaskPriorityInherit,CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
|
|
||||||
libfreertos.a,tasks.c.obj,prvGetExpectedIdleTime,FALSE
|
|
||||||
libfreertos.a,tasks.c.obj,vTaskStepTick,FALSE
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_chip_revision,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_major_chip_version,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_minor_chip_version,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_blk_version,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_disable_wafer_version_major,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_get_disable_blk_version_major,
|
|
||||||
libhal.a,efuse_hal.c.obj,efuse_hal_flash_encryption_enabled,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_free,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_aligned_alloc_base,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_malloc_base,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_realloc_base,
|
|
||||||
libheap.a,heap_caps_base.c.obj,heap_caps_calloc_base,
|
|
||||||
libheap.a,heap_caps.c.obj,hex_to_str,CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
|
|
||||||
libheap.a,heap_caps.c.obj,fmt_abort_str,CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_alloc_failed,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_malloc_prefer,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc_prefer,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_calloc_prefer,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_realloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_calloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_aligned_alloc_default,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_aligned_alloc,
|
|
||||||
libheap.a,heap_caps.c.obj,heap_caps_aligned_free,
|
|
||||||
libheap.a,multi_heap.c.obj,_multi_heap_lock,
|
|
||||||
libheap.a,multi_heap.c.obj,multi_heap_in_rom_init,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_timestamp,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_lock,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_unlock,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_impl_lock_timeout,
|
|
||||||
liblog.a,log_freertos.c.obj,esp_log_early_timestamp,
|
|
||||||
liblog.a,log.c.obj,esp_log_write,
|
|
||||||
liblog.a,log.c.obj,esp_log_writev,
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp_mbedtls_mem_calloc,!CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp_mbedtls_mem_free,!CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC
|
|
||||||
libnewlib.a,assert.c.obj,__assert_func,
|
|
||||||
libnewlib.a,assert.c.obj,newlib_include_assert_impl,
|
|
||||||
libnewlib.a,heap.c.obj,_calloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,_free_r,
|
|
||||||
libnewlib.a,heap.c.obj,_malloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,_realloc_r,
|
|
||||||
libnewlib.a,heap.c.obj,calloc,
|
|
||||||
libnewlib.a,heap.c.obj,cfree,
|
|
||||||
libnewlib.a,heap.c.obj,free,
|
|
||||||
libnewlib.a,heap.c.obj,malloc,
|
|
||||||
libnewlib.a,heap.c.obj,newlib_include_heap_impl,
|
|
||||||
libnewlib.a,heap.c.obj,realloc,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_try_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,lock_release_generic,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_release_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_init,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_init_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_close,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_close_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,check_lock_nonzero,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,lock_init_generic,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_try_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_try_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_release,
|
|
||||||
libnewlib.a,locks.c.obj,__retarget_lock_release_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_close,
|
|
||||||
libnewlib.a,locks.c.obj,lock_acquire_generic,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_acquire_recursive,
|
|
||||||
libnewlib.a,locks.c.obj,_lock_try_acquire,
|
|
||||||
libnewlib.a,reent_init.c.obj,esp_reent_init,
|
|
||||||
libnewlib.a,time.c.obj,_times_r,
|
|
||||||
libnewlib.a,time.c.obj,_gettimeofday_r,
|
|
||||||
libpp.a,pp_debug.o,wifi_gpio_debug,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_lock_internal,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_lock,
|
|
||||||
libpthread.a,pthread.c.obj,pthread_mutex_unlock,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_handler_get,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_handler_set,
|
|
||||||
libriscv.a,interrupt.c.obj,intr_matrix_route,
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,spi_flash_needs_reset_check,FALSE
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,spi_flash_set_erasing_flag,FALSE
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_guard_set,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_malloc_internal,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_rom_impl_init,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,esp_mspi_pin_init,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,flash_ops.c.obj,spi_flash_init_chip_state,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,delay_us,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,get_buffer_malloc,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,release_buffer_malloc,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,main_flash_region_protected,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,main_flash_op_status,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,spi1_flash_os_check_yield,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,spi1_flash_os_yield,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,start,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,end,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,delay_us,CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
library,path
|
|
||||||
libbtdm_app.a,$IDF_PATH/components/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app.a
|
|
||||||
libpp.a,$IDF_PATH/components/esp_wifi/lib/esp32c3/libpp.a
|
|
||||||
libbootloader_support.a,./esp-idf/bootloader_support/libbootloader_support.a
|
|
||||||
libbt.a,./esp-idf/bt/libbt.a
|
|
||||||
libesp_driver_gpio.a,./esp-idf/esp_driver_gpio/libesp_driver_gpio.a
|
|
||||||
libesp_app_format.a,./esp-idf/esp_app_format/libesp_app_format.a
|
|
||||||
libesp_hw_support.a,./esp-idf/esp_hw_support/libesp_hw_support.a
|
|
||||||
libesp_phy.a,./esp-idf/esp_phy/libesp_phy.a
|
|
||||||
libesp_pm.a,./esp-idf/esp_pm/libesp_pm.a
|
|
||||||
libesp_ringbuf.a,./esp-idf/esp_ringbuf/libesp_ringbuf.a
|
|
||||||
libesp_rom.a,./esp-idf/esp_rom/libesp_rom.a
|
|
||||||
libesp_system.a,./esp-idf/esp_system/libesp_system.a
|
|
||||||
libesp_timer.a,./esp-idf/esp_timer/libesp_timer.a
|
|
||||||
libesp_wifi.a,./esp-idf/esp_wifi/libesp_wifi.a
|
|
||||||
libfreertos.a,./esp-idf/freertos/libfreertos.a
|
|
||||||
libhal.a,./esp-idf/hal/libhal.a
|
|
||||||
libheap.a,./esp-idf/heap/libheap.a
|
|
||||||
liblog.a,./esp-idf/log/liblog.a
|
|
||||||
libmbedcrypto.a,./esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a
|
|
||||||
libnewlib.a,./esp-idf/newlib/libnewlib.a
|
|
||||||
libpthread.a,./esp-idf/pthread/libpthread.a
|
|
||||||
libriscv.a,./esp-idf/riscv/libriscv.a
|
|
||||||
libspi_flash.a,./esp-idf/spi_flash/libspi_flash.a
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
library,object,path
|
|
||||||
libbootloader_support.a,bootloader_flash.c.obj,esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj
|
|
||||||
libbootloader_support.a,flash_encrypt.c.obj,esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj
|
|
||||||
libbt.a,bt_osi_mem.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/porting/mem/bt_osi_mem.c.obj
|
|
||||||
libbt.a,bt.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/controller/esp32c3/bt.c.obj
|
|
||||||
libbt.a,nimble_port.c.obj,esp-idf/bt/CMakeFiles/__idf_bt.dir/host/nimble/nimble/porting/nimble/src/nimble_port.c.obj
|
|
||||||
libesp_driver_gpio.a,gpio.c.obj,esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio.c.obj
|
|
||||||
libesp_app_format.a,esp_app_desc.c.obj,esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj
|
|
||||||
libesp_hw_support.a,cpu.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj
|
|
||||||
libesp_hw_support.a,esp_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj
|
|
||||||
libesp_hw_support.a,esp_memory_utils.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj
|
|
||||||
libesp_hw_support.a,hw_random.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj
|
|
||||||
libesp_hw_support.a,intr_alloc.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj
|
|
||||||
libesp_hw_support.a,periph_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,regi2c_ctrl.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj
|
|
||||||
libesp_hw_support.a,rtc_clk.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_clk.c.obj
|
|
||||||
libesp_hw_support.a,rtc_init.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_init.c.obj
|
|
||||||
libesp_hw_support.a,rtc_module.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj
|
|
||||||
libesp_hw_support.a,rtc_sleep.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_sleep.c.obj
|
|
||||||
libesp_hw_support.a,rtc_time.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32c3/rtc_time.c.obj
|
|
||||||
libesp_hw_support.a,sleep_modes.c.obj,esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj
|
|
||||||
libesp_phy.a,phy_init.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj
|
|
||||||
libesp_phy.a,phy_override.c.obj,esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj
|
|
||||||
libesp_pm.a,pm_locks.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj
|
|
||||||
libesp_pm.a,pm_impl.c.obj,esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj
|
|
||||||
libesp_ringbuf.a,ringbuf.c.obj,esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj
|
|
||||||
libesp_rom.a,esp_rom_systimer.c.obj,esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj
|
|
||||||
libesp_rom.a,esp_rom_uart.c.obj,esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj
|
|
||||||
libesp_system.a,brownout.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/brownout.c.obj
|
|
||||||
libesp_system.a,cache_err_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c3/cache_err_int.c.obj
|
|
||||||
libesp_system.a,cpu_start.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj
|
|
||||||
libesp_system.a,crosscore_int.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj
|
|
||||||
libesp_system.a,esp_system.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj
|
|
||||||
libesp_system.a,reset_reason.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32c3/reset_reason.c.obj
|
|
||||||
libesp_system.a,ubsan.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj
|
|
||||||
libesp_system.a,esp_system_chip.c.obj,esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_system_chip.c.obj
|
|
||||||
libesp_timer.a,esp_timer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_systimer.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj
|
|
||||||
libesp_timer.a,esp_timer_impl_common.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_common.c.obj
|
|
||||||
libesp_timer.a,ets_timer_legacy.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj
|
|
||||||
libesp_timer.a,system_time.c.obj,esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj
|
|
||||||
libesp_wifi.a,esp_adapter.c.obj,esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32c3/esp_adapter.c.obj
|
|
||||||
libfreertos.a,list.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj
|
|
||||||
libfreertos.a,port.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/riscv/port.c.obj
|
|
||||||
libfreertos.a,port_common.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj
|
|
||||||
libfreertos.a,heap_idf.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/heap_idf.c.obj
|
|
||||||
libfreertos.a,port_systick.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj
|
|
||||||
libfreertos.a,queue.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj
|
|
||||||
libfreertos.a,tasks.c.obj,esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj
|
|
||||||
libhal.a,brownout_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/brownout_hal.c.obj
|
|
||||||
libhal.a,efuse_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj
|
|
||||||
libhal.a,efuse_hal.c.obj,esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32c3/efuse_hal.c.obj
|
|
||||||
libheap.a,heap_caps_base.c.obj,esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_base.c.obj
|
|
||||||
libheap.a,heap_caps.c.obj,esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj
|
|
||||||
libheap.a,multi_heap.c.obj,./esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj
|
|
||||||
liblog.a,log_freertos.c.obj,esp-idf/log/CMakeFiles/__idf_log.dir/log_freertos.c.obj
|
|
||||||
liblog.a,log.c.obj,esp-idf/log/CMakeFiles/__idf_log.dir/log.c.obj
|
|
||||||
libmbedcrypto.a,esp_mem.c.obj,esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/$IDF_PATH/components/mbedtls/port/esp_mem.c.obj
|
|
||||||
libnewlib.a,assert.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/assert.c.obj
|
|
||||||
libnewlib.a,heap.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/heap.c.obj
|
|
||||||
libnewlib.a,locks.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/locks.c.obj
|
|
||||||
libnewlib.a,reent_init.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/reent_init.c.obj
|
|
||||||
libnewlib.a,time.c.obj,esp-idf/newlib/CMakeFiles/__idf_newlib.dir/time.c.obj
|
|
||||||
libpthread.a,pthread.c.obj,esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj
|
|
||||||
libriscv.a,interrupt.c.obj,esp-idf/riscv/CMakeFiles/__idf_riscv.dir/interrupt.c.obj
|
|
||||||
libspi_flash.a,flash_brownout_hook.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj
|
|
||||||
libspi_flash.a,flash_ops.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj
|
|
||||||
libspi_flash.a,spi_flash_os_func_app.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj
|
|
||||||
libspi_flash.a,spi_flash_os_func_noos.c.obj,esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import argparse
|
import argparse
|
||||||
import csv
|
import csv
|
||||||
|
|
@ -18,32 +19,31 @@ sys.path.append(os.environ['IDF_PATH'] + '/tools/ldgen/ldgen')
|
||||||
from entity import EntityDB
|
from entity import EntityDB
|
||||||
|
|
||||||
espidf_objdump = None
|
espidf_objdump = None
|
||||||
espidf_version = None
|
|
||||||
|
|
||||||
def lib_secs(lib, file, lib_path):
|
def lib_secs(lib, file, lib_path):
|
||||||
new_env = os.environ.copy()
|
new_env = os.environ.copy()
|
||||||
new_env['LC_ALL'] = 'C'
|
new_env['LC_ALL'] = 'C'
|
||||||
try:
|
dump = StringIO(subprocess.check_output([espidf_objdump, '-h', lib_path], env=new_env).decode())
|
||||||
dump_output = subprocess.check_output([espidf_objdump, '-h', lib_path], env=new_env).decode()
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
raise RuntimeError(f"Command '{e.cmd}' failed with exit code {e.returncode}")
|
|
||||||
|
|
||||||
dump = StringIO(dump_output)
|
|
||||||
dump.name = lib
|
dump.name = lib
|
||||||
|
|
||||||
sections_infos = EntityDB()
|
sections_infos = EntityDB()
|
||||||
sections_infos.add_sections_info(dump)
|
sections_infos.add_sections_info(dump)
|
||||||
|
|
||||||
secs = sections_infos.get_sections(lib, file.split('.')[0] + '.c')
|
secs = sections_infos.get_sections(lib, file.split('.')[0] + '.c')
|
||||||
if not secs:
|
if len(secs) == 0:
|
||||||
secs = sections_infos.get_sections(lib, file.split('.')[0])
|
secs = sections_infos.get_sections(lib, file.split('.')[0])
|
||||||
if not secs:
|
if len(secs) == 0:
|
||||||
raise ValueError(f'Failed to get sections from lib {lib_path}')
|
raise ValueError('Failed to get sections from lib %s'%(lib_path))
|
||||||
|
|
||||||
return secs
|
return secs
|
||||||
|
|
||||||
def filter_secs(secs_a, secs_b):
|
def filter_secs(secs_a, secs_b):
|
||||||
return [s_a for s_a in secs_a if any(s_b in s_a for s_b in secs_b)]
|
new_secs = list()
|
||||||
|
for s_a in secs_a:
|
||||||
|
for s_b in secs_b:
|
||||||
|
if s_b in s_a:
|
||||||
|
new_secs.append(s_a)
|
||||||
|
return new_secs
|
||||||
|
|
||||||
def strip_secs(secs_a, secs_b):
|
def strip_secs(secs_a, secs_b):
|
||||||
secs = list(set(secs_a) - set(secs_b))
|
secs = list(set(secs_a) - set(secs_b))
|
||||||
|
|
@ -54,33 +54,33 @@ def func2sect(func):
|
||||||
if ' ' in func:
|
if ' ' in func:
|
||||||
func_l = func.split(' ')
|
func_l = func.split(' ')
|
||||||
else:
|
else:
|
||||||
func_l = [func]
|
func_l = list()
|
||||||
|
func_l.append(func)
|
||||||
|
|
||||||
secs = []
|
secs = list()
|
||||||
for l in func_l:
|
for l in func_l:
|
||||||
if '.iram1.' not in l:
|
if '.iram1.' not in l:
|
||||||
secs.append(f'.literal.{l}')
|
secs.append('.literal.%s'%(l,))
|
||||||
secs.append(f'.text.{l}')
|
secs.append('.text.%s'%(l, ))
|
||||||
else:
|
else:
|
||||||
secs.append(l)
|
secs.append(l)
|
||||||
return secs
|
return secs
|
||||||
|
|
||||||
class filter_c:
|
class filter_c:
|
||||||
def __init__(self, file):
|
def __init__(self, file):
|
||||||
with open(file) as f:
|
lines = open(file).read().splitlines()
|
||||||
lines = f.read().splitlines()
|
|
||||||
self.libs_desc = ''
|
self.libs_desc = ''
|
||||||
self.libs = ''
|
self.libs = ''
|
||||||
for line in lines:
|
for l in lines:
|
||||||
if ') .iram1 EXCLUDE_FILE(*' in line and ') .iram1.*)' in line:
|
if ') .iram1 EXCLUDE_FILE(*' in l and ') .iram1.*)' in l:
|
||||||
desc = r'\(EXCLUDE_FILE\((.*)\) .iram1 '
|
desc = '\(EXCLUDE_FILE\((.*)\) .iram1 '
|
||||||
self.libs_desc = re.search(desc, line)[1]
|
self.libs_desc = re.search(desc, l)[1]
|
||||||
self.libs = self.libs_desc.replace('*', '')
|
self.libs = self.libs_desc.replace('*', '')
|
||||||
return
|
return
|
||||||
|
|
||||||
def match(self, lib):
|
def match(self, lib):
|
||||||
if lib in self.libs:
|
if lib in self.libs:
|
||||||
print(f'Remove lib {lib}')
|
print('Remove lib %s'%(lib))
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -91,80 +91,48 @@ class target_c:
|
||||||
def __init__(self, lib, lib_path, file, fsecs):
|
def __init__(self, lib, lib_path, file, fsecs):
|
||||||
self.lib = lib
|
self.lib = lib
|
||||||
self.file = file
|
self.file = file
|
||||||
|
|
||||||
self.lib_path = lib_path
|
self.lib_path = lib_path
|
||||||
self.fsecs = func2sect(fsecs)
|
self.fsecs = func2sect(fsecs)
|
||||||
self.desc = f'*{lib}:{file.split(".")[0]}.*'
|
self.desc = '*%s:%s.*'%(lib, file.split('.')[0])
|
||||||
|
|
||||||
secs = lib_secs(lib, file, lib_path)
|
secs = lib_secs(lib, file, lib_path)
|
||||||
if '.iram1.' in self.fsecs[0]:
|
if '.iram1.' in self.fsecs[0]:
|
||||||
self.secs = filter_secs(secs, ('.iram1.',))
|
self.secs = filter_secs(secs, ('.iram1.', ))
|
||||||
else:
|
else:
|
||||||
self.secs = filter_secs(secs, ('.iram1.', '.text.', '.literal.'))
|
self.secs = filter_secs(secs, ('.iram1.', '.text.', '.literal.'))
|
||||||
self.isecs = strip_secs(self.secs, self.fsecs)
|
self.isecs = strip_secs(self.secs, self.fsecs)
|
||||||
|
|
||||||
self.has_exclude_iram = True
|
|
||||||
self.has_exclude_dram = True
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
s = 'lib=%s\nfile=%s\lib_path=%s\ndesc=%s\nsecs=%s\nfsecs=%s\nisecs=%s\n'%(\
|
||||||
f'lib={self.lib}\n'
|
self.lib, self.file, self.lib_path, self.desc, self.secs, self.fsecs,\
|
||||||
f'file={self.file}\n'
|
self.isecs)
|
||||||
f'lib_path={self.lib_path}\n'
|
return s
|
||||||
f'desc={self.desc}\n'
|
|
||||||
f'secs={self.secs}\n'
|
|
||||||
f'fsecs={self.fsecs}\n'
|
|
||||||
f'isecs={self.isecs}\n'
|
|
||||||
)
|
|
||||||
|
|
||||||
class target2_c:
|
|
||||||
def __init__(self, lib, file, iram_secs):
|
|
||||||
self.lib = lib
|
|
||||||
self.file = file
|
|
||||||
self.fsecs = iram_secs
|
|
||||||
if file != '*':
|
|
||||||
self.desc = f'*{lib}:{file.split(".")[0]}.*'
|
|
||||||
else:
|
|
||||||
self.desc = f'*{lib}:'
|
|
||||||
self.isecs = iram_secs
|
|
||||||
|
|
||||||
self.has_exclude_iram = False
|
|
||||||
self.has_exclude_dram = False
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return (
|
|
||||||
f'lib={self.lib}\n'
|
|
||||||
f'file={self.file}\n'
|
|
||||||
f'lib_path={self.lib_path}\n'
|
|
||||||
f'desc={self.desc}\n'
|
|
||||||
f'secs={self.secs}\n'
|
|
||||||
f'fsecs={self.fsecs}\n'
|
|
||||||
f'isecs={self.isecs}\n'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Remove specific functions from IRAM
|
|
||||||
class relink_c:
|
class relink_c:
|
||||||
def __init__(self, input_file, library_file, object_file, function_file, sdkconfig_file, missing_function_info):
|
def __init__(self, input, library_file, object_file, function_file, sdkconfig_file, missing_function_info):
|
||||||
self.filter = filter_c(input_file)
|
self.filter = filter_c(input)
|
||||||
|
|
||||||
libraries = configuration.generator(library_file, object_file, function_file, sdkconfig_file, missing_function_info, espidf_objdump)
|
libraries = configuration.generator(library_file, object_file, function_file, sdkconfig_file, missing_function_info, espidf_objdump)
|
||||||
self.targets = []
|
self.targets = list()
|
||||||
for lib_name in libraries.libs:
|
for i in libraries.libs:
|
||||||
lib = libraries.libs[lib_name]
|
lib = libraries.libs[i]
|
||||||
|
|
||||||
if self.filter.match(lib.name):
|
if self.filter.match(lib.name):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for obj_name in lib.objs:
|
for j in lib.objs:
|
||||||
obj = lib.objs[obj_name]
|
obj = lib.objs[j]
|
||||||
target = target_c(lib.name, lib.path, obj.name, ' '.join(obj.sections()))
|
self.targets.append(target_c(lib.name, lib.path, obj.name,
|
||||||
self.targets.append(target)
|
' '.join(obj.sections())))
|
||||||
|
# for i in self.targets:
|
||||||
|
# print(i)
|
||||||
self.__transform__()
|
self.__transform__()
|
||||||
|
|
||||||
def __transform__(self):
|
def __transform__(self):
|
||||||
iram1_exclude = []
|
iram1_exclude = list()
|
||||||
iram1_include = []
|
iram1_include = list()
|
||||||
flash_include = []
|
flash_include = list()
|
||||||
|
|
||||||
for t in self.targets:
|
for t in self.targets:
|
||||||
secs = filter_secs(t.fsecs, ('.iram1.', ))
|
secs = filter_secs(t.fsecs, ('.iram1.', ))
|
||||||
|
|
@ -173,192 +141,100 @@ class relink_c:
|
||||||
|
|
||||||
secs = filter_secs(t.isecs, ('.iram1.', ))
|
secs = filter_secs(t.isecs, ('.iram1.', ))
|
||||||
if len(secs) > 0:
|
if len(secs) > 0:
|
||||||
iram1_include.append(f' {t.desc}({" ".join(secs)})')
|
iram1_include.append(' %s(%s)'%(t.desc, ' '.join(secs)))
|
||||||
|
|
||||||
secs = t.fsecs
|
secs = t.fsecs
|
||||||
if len(secs) > 0:
|
if len(secs) > 0:
|
||||||
flash_include.append(f' {t.desc}({" ".join(secs)})')
|
flash_include.append(' %s(%s)'%(t.desc, ' '.join(secs)))
|
||||||
|
|
||||||
self.iram1_exclude = f' *(EXCLUDE_FILE({self.filter.add()} {" ".join(iram1_exclude)}) .iram1.*) *(EXCLUDE_FILE({self.filter.add()} {" ".join(iram1_exclude)}) .iram1)'
|
self.iram1_exclude = ' *(EXCLUDE_FILE(%s %s) .iram1.*) *(EXCLUDE_FILE(%s %s) .iram1)' % \
|
||||||
|
(self.filter.add(), ' '.join(iram1_exclude), \
|
||||||
|
self.filter.add(), ' '.join(iram1_exclude))
|
||||||
self.iram1_include = '\n'.join(iram1_include)
|
self.iram1_include = '\n'.join(iram1_include)
|
||||||
self.flash_include = '\n'.join(flash_include)
|
self.flash_include = '\n'.join(flash_include)
|
||||||
|
|
||||||
logging.debug(f'IRAM1 Exclude: {self.iram1_exclude}')
|
logging.debug('IRAM1 Exclude: %s'%(self.iram1_exclude))
|
||||||
logging.debug(f'IRAM1 Include: {self.iram1_include}')
|
logging.debug('IRAM1 Include: %s'%(self.iram1_include))
|
||||||
logging.debug(f'Flash Include: {self.flash_include}')
|
logging.debug('Flash Include: %s'%(self.flash_include))
|
||||||
|
|
||||||
def __replace__(self, lines):
|
def __replace__(self, lines):
|
||||||
def is_iram_desc(line):
|
def is_iram_desc(l):
|
||||||
return '*(.iram1 .iram1.*)' in line or (') .iram1 EXCLUDE_FILE(*' in line and ') .iram1.*)' in line)
|
if '*(.iram1 .iram1.*)' in l or (') .iram1 EXCLUDE_FILE(*' in l and ') .iram1.*)' in l):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
iram_start = False
|
iram_start = False
|
||||||
flash_done = False
|
flash_done = False
|
||||||
flash_text = '(.stub)'
|
|
||||||
|
|
||||||
if espidf_version == '5.0':
|
for i in range(0, len(lines) - 1):
|
||||||
flash_text = '(.stub .gnu.warning'
|
l = lines[i]
|
||||||
|
if '.iram0.text :' in l:
|
||||||
new_lines = []
|
|
||||||
for line in lines:
|
|
||||||
if '.iram0.text :' in line:
|
|
||||||
logging.debug('start to process .iram0.text')
|
logging.debug('start to process .iram0.text')
|
||||||
iram_start = True
|
iram_start = True
|
||||||
new_lines.append(line)
|
elif '.dram0.data :' in l:
|
||||||
elif '.dram0.data :' in line:
|
|
||||||
logging.debug('end to process .iram0.text')
|
logging.debug('end to process .iram0.text')
|
||||||
iram_start = False
|
iram_start = False
|
||||||
new_lines.append(line)
|
elif is_iram_desc(l):
|
||||||
elif is_iram_desc(line):
|
|
||||||
if iram_start:
|
if iram_start:
|
||||||
new_lines.extend([self.iram1_exclude, self.iram1_include])
|
lines[i] = '%s\n%s\n'%(self.iram1_exclude, self.iram1_include)
|
||||||
else:
|
elif '(.stub .gnu.warning' in l:
|
||||||
new_lines.append(line)
|
|
||||||
elif flash_text in line:
|
|
||||||
if not flash_done:
|
if not flash_done:
|
||||||
new_lines.extend([self.flash_include, line])
|
lines[i] = '%s\n\n%s'%(self.flash_include, l)
|
||||||
|
elif self.flash_include in l:
|
||||||
flash_done = True
|
flash_done = True
|
||||||
else:
|
else:
|
||||||
new_lines.append(line)
|
if iram_start:
|
||||||
else:
|
new_l = self._replace_func(l)
|
||||||
new_lines.append(self._replace_func(line) if iram_start else line)
|
if new_l:
|
||||||
|
lines[i] = new_l
|
||||||
|
|
||||||
return new_lines
|
return lines
|
||||||
|
|
||||||
def _replace_func(self, line):
|
def _replace_func(self, l):
|
||||||
for t in self.targets:
|
for t in self.targets:
|
||||||
if t.desc in line:
|
if t.desc in l:
|
||||||
S = '.literal .literal.* .text .text.*'
|
S = '.literal .literal.* .text .text.*'
|
||||||
if S in line:
|
if S in l:
|
||||||
if len(t.isecs) > 0:
|
if len(t.isecs) > 0:
|
||||||
return line.replace(S, ' '.join(t.isecs))
|
return l.replace(S, ' '.join(t.isecs))
|
||||||
else:
|
else:
|
||||||
return ''
|
return ' '
|
||||||
|
|
||||||
S = f'{t.desc}({" ".join(t.fsecs)})'
|
S = '%s(%s)'%(t.desc, ' '.join(t.fsecs))
|
||||||
if S in line:
|
if S in l:
|
||||||
return ''
|
return ' '
|
||||||
|
|
||||||
replaced = False
|
replaced = False
|
||||||
for s in t.fsecs:
|
for s in t.fsecs:
|
||||||
s2 = s + ' '
|
s2 = s + ' '
|
||||||
if s2 in line:
|
if s2 in l:
|
||||||
line = line.replace(s2, '')
|
l = l.replace(s2, '')
|
||||||
replaced = True
|
replaced = True
|
||||||
s2 = s + ')'
|
s2 = s + ')'
|
||||||
if s2 in line:
|
if s2 in l:
|
||||||
line = line.replace(s2, ')')
|
l = l.replace(s2, ')')
|
||||||
replaced = True
|
replaced = True
|
||||||
if '( )' in line or '()' in line:
|
if '( )' in l or '()' in l:
|
||||||
return ''
|
return ' '
|
||||||
if replaced:
|
if replaced:
|
||||||
return line
|
return l
|
||||||
|
else:
|
||||||
index = f'*{t.lib}:(EXCLUDE_FILE'
|
index = '*%s:(EXCLUDE_FILE'%(t.lib)
|
||||||
if index in line and t.file.split('.')[0] not in line:
|
if index in l and t.file.split('.')[0] not in l:
|
||||||
for m in self.targets:
|
for m in self.targets:
|
||||||
index = f'*{m.lib}:(EXCLUDE_FILE'
|
index = '*%s:(EXCLUDE_FILE'%(m.lib)
|
||||||
if index in line and m.file.split('.')[0] not in line:
|
if index in l and m.file.split('.')[0] not in l:
|
||||||
line = line.replace('EXCLUDE_FILE(', f'EXCLUDE_FILE({m.desc} ')
|
l = l.replace('EXCLUDE_FILE(', 'EXCLUDE_FILE(%s '%(m.desc))
|
||||||
if len(m.isecs) > 0:
|
if len(m.isecs) > 0:
|
||||||
line += f'\n {m.desc}({" ".join(m.isecs)})'
|
l += '\n %s(%s)'%(m.desc, ' '.join(m.isecs))
|
||||||
return line
|
return l
|
||||||
|
|
||||||
return line
|
return False
|
||||||
|
|
||||||
def save(self, input_file, output_file, target):
|
def save(self, input, output):
|
||||||
with open(input_file) as f:
|
lines = open(input).read().splitlines()
|
||||||
lines = f.read().splitlines()
|
|
||||||
lines = self.__replace__(lines)
|
lines = self.__replace__(lines)
|
||||||
with open(output_file, 'w+') as f:
|
open(output, 'w+').write('\n'.join(lines))
|
||||||
f.write('\n'.join(lines))
|
|
||||||
|
|
||||||
# Link specific functions to IRAM
|
|
||||||
class relink2_c:
|
|
||||||
def __init__(self, input_file, library_file, object_file, function_file, sdkconfig_file, missing_function_info):
|
|
||||||
self.filter = filter_c(input_file)
|
|
||||||
|
|
||||||
rodata_exclude = []
|
|
||||||
iram_exclude = []
|
|
||||||
rodata = []
|
|
||||||
iram = []
|
|
||||||
|
|
||||||
libraries = configuration.generator(library_file, object_file, function_file, sdkconfig_file, missing_function_info, espidf_objdump)
|
|
||||||
self.targets = []
|
|
||||||
|
|
||||||
for lib_name in libraries.libs:
|
|
||||||
lib = libraries.libs[lib_name]
|
|
||||||
|
|
||||||
if self.filter.match(lib.name):
|
|
||||||
continue
|
|
||||||
|
|
||||||
for obj_name in lib.objs:
|
|
||||||
obj = lib.objs[obj_name]
|
|
||||||
if not obj.section_all:
|
|
||||||
self.targets.append(target_c(lib.name, lib.path, obj.name, ' '.join(obj.sections())))
|
|
||||||
else:
|
|
||||||
self.targets.append(target2_c(lib.name, obj.name, obj.sections()))
|
|
||||||
|
|
||||||
for target in self.targets:
|
|
||||||
rodata.append(f' {target.desc}(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)')
|
|
||||||
if target.has_exclude_dram:
|
|
||||||
rodata_exclude.append(target.desc)
|
|
||||||
iram.append(f' {target.desc}({" ".join(target.fsecs)})')
|
|
||||||
if target.has_exclude_iram:
|
|
||||||
iram_exclude.append(target.desc)
|
|
||||||
|
|
||||||
self.rodata_ex = f' *(EXCLUDE_FILE({" ".join(rodata_exclude)}) .rodata EXCLUDE_FILE({" ".join(rodata_exclude)}) .rodata.* EXCLUDE_FILE({" ".join(rodata_exclude)}) .sdata2 EXCLUDE_FILE({" ".join(rodata_exclude)}) .sdata2.* EXCLUDE_FILE({" ".join(rodata_exclude)}) .srodata EXCLUDE_FILE({" ".join(rodata_exclude)}) .srodata.*)'
|
|
||||||
self.rodata_in = '\n'.join(rodata)
|
|
||||||
|
|
||||||
self.iram_ex = f' *(EXCLUDE_FILE({" ".join(iram_exclude)}) .iram1 EXCLUDE_FILE({" ".join(iram_exclude)}) .iram1.*)'
|
|
||||||
self.iram_in = '\n'.join(iram)
|
|
||||||
|
|
||||||
logging.debug(f'RODATA In: {self.rodata_in}')
|
|
||||||
logging.debug(f'RODATA Ex: {self.rodata_ex}')
|
|
||||||
logging.debug(f'IRAM In: {self.iram_in}')
|
|
||||||
logging.debug(f'IRAM Ex: {self.iram_ex}')
|
|
||||||
|
|
||||||
def save(self, input_file, output_file, target):
|
|
||||||
with open(input_file) as f:
|
|
||||||
lines = f.read().splitlines()
|
|
||||||
lines = self.__replace__(lines, target)
|
|
||||||
with open(output_file, 'w+') as f:
|
|
||||||
f.write('\n'.join(lines))
|
|
||||||
|
|
||||||
def __replace__(self, lines, target):
|
|
||||||
iram_start = False
|
|
||||||
new_lines = []
|
|
||||||
iram_cache = []
|
|
||||||
|
|
||||||
flash_text = '*(.stub)'
|
|
||||||
iram_text = '*(.iram1 .iram1.*)'
|
|
||||||
if espidf_version == '5.3' and target == 'esp32c2':
|
|
||||||
iram_text = '_iram_text_start = ABSOLUTE(.);'
|
|
||||||
elif espidf_version == '5.0':
|
|
||||||
flash_text = '*(.stub .gnu.warning'
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
if not iram_start:
|
|
||||||
if iram_text in line:
|
|
||||||
new_lines.append(f'{self.iram_in}\n')
|
|
||||||
iram_start = True
|
|
||||||
elif ' _text_start = ABSOLUTE(.);' in line:
|
|
||||||
new_lines.append(f'{line}\n{self.iram_ex}')
|
|
||||||
continue
|
|
||||||
elif flash_text in line:
|
|
||||||
new_lines.extend(iram_cache)
|
|
||||||
iram_cache = []
|
|
||||||
else:
|
|
||||||
if '} > iram0_0_seg' in line:
|
|
||||||
iram_start = False
|
|
||||||
|
|
||||||
if not iram_start:
|
|
||||||
new_lines.append(line)
|
|
||||||
else:
|
|
||||||
skip_str = ['libriscv.a:interrupt', 'libriscv.a:vectors']
|
|
||||||
if not any(s in line for s in skip_str):
|
|
||||||
iram_cache.append(line)
|
|
||||||
|
|
||||||
return new_lines
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argparser = argparse.ArgumentParser(description='Relinker script generator')
|
argparser = argparse.ArgumentParser(description='Relinker script generator')
|
||||||
|
|
@ -366,100 +242,70 @@ def main():
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--input', '-i',
|
'--input', '-i',
|
||||||
help='Linker template file',
|
help='Linker template file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--output', '-o',
|
'--output', '-o',
|
||||||
help='Output linker script',
|
help='Output linker script',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--library', '-l',
|
'--library', '-l',
|
||||||
help='Library description directory',
|
help='Library description directory',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--object', '-b',
|
'--object', '-b',
|
||||||
help='Object description file',
|
help='Object description file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--function', '-f',
|
'--function', '-f',
|
||||||
help='Function description file',
|
help='Function description file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--sdkconfig', '-s',
|
'--sdkconfig', '-s',
|
||||||
help='sdkconfig file',
|
help='sdkconfig file',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
|
||||||
'--target', '-t',
|
|
||||||
help='target chip',
|
|
||||||
type=str,
|
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
|
||||||
'--version', '-v',
|
|
||||||
help='IDF version',
|
|
||||||
type=str,
|
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--objdump', '-g',
|
'--objdump', '-g',
|
||||||
help='GCC objdump command',
|
help='GCC objdump command',
|
||||||
type=str,
|
type=str)
|
||||||
required=True)
|
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--debug', '-d',
|
'--debug', '-d',
|
||||||
help='Debug level (option is \'debug\')',
|
help='Debug level(option is \'debug\')',
|
||||||
default='no',
|
default='no',
|
||||||
type=str)
|
type=str)
|
||||||
|
|
||||||
argparser.add_argument(
|
argparser.add_argument(
|
||||||
'--missing_function_info',
|
'--missing_function_info',
|
||||||
help='Print error information instead of throwing exception when missing function',
|
help='Print error information instead of throwing exception when missing function',
|
||||||
action='store_true')
|
default=False,
|
||||||
|
type=bool)
|
||||||
argparser.add_argument(
|
|
||||||
'--link_to_iram',
|
|
||||||
help='True: Link specific functions to IRAM, False: Remove specific functions from IRAM',
|
|
||||||
action='store_true')
|
|
||||||
|
|
||||||
args = argparser.parse_args()
|
args = argparser.parse_args()
|
||||||
|
|
||||||
if args.debug == 'debug':
|
if args.debug == 'debug':
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
logging.debug(f'input: {args.input}')
|
logging.debug('input: %s'%(args.input))
|
||||||
logging.debug(f'output: {args.output}')
|
logging.debug('output: %s'%(args.output))
|
||||||
logging.debug(f'library: {args.library}')
|
logging.debug('library: %s'%(args.library))
|
||||||
logging.debug(f'object: {args.object}')
|
logging.debug('object: %s'%(args.object))
|
||||||
logging.debug(f'function: {args.function}')
|
logging.debug('function: %s'%(args.function))
|
||||||
logging.debug(f'version: {args.version}')
|
logging.debug('sdkconfig:%s'%(args.sdkconfig))
|
||||||
logging.debug(f'sdkconfig:{args.sdkconfig}')
|
logging.debug('objdump: %s'%(args.objdump))
|
||||||
logging.debug(f'objdump: {args.objdump}')
|
logging.debug('debug: %s'%(args.debug))
|
||||||
logging.debug(f'debug: {args.debug}')
|
logging.debug('missing_function_info: %s'%(args.missing_function_info))
|
||||||
logging.debug(f'missing_function_info: {args.missing_function_info}')
|
|
||||||
|
|
||||||
global espidf_objdump
|
global espidf_objdump
|
||||||
espidf_objdump = args.objdump
|
espidf_objdump = args.objdump
|
||||||
|
|
||||||
global espidf_version
|
|
||||||
espidf_version = args.version
|
|
||||||
|
|
||||||
if not args.link_to_iram:
|
|
||||||
relink = relink_c(args.input, args.library, args.object, args.function, args.sdkconfig, args.missing_function_info)
|
relink = relink_c(args.input, args.library, args.object, args.function, args.sdkconfig, args.missing_function_info)
|
||||||
else:
|
relink.save(args.input, args.output)
|
||||||
relink = relink2_c(args.input, args.library, args.object, args.function, args.sdkconfig, args.missing_function_info)
|
|
||||||
relink.save(args.input, args.output, args.target)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,3 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int test_component2_version_major()
|
int test_component2_version_major()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,3 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue