From 6e343c1f8bcf4e3b5cf6b62f67a55a2eca51aa09 Mon Sep 17 00:00:00 2001 From: Andrey Starodubtsev Date: Fri, 14 May 2021 18:26:22 +0300 Subject: [PATCH 001/310] Fix typo s/\bUnknow\b/Unknown/g --- components/wpa_supplicant/src/eap_peer/eap_mschapv2.c | 2 +- examples/protocols/pppos_client/main/pppos_client_main.c | 2 +- examples/system/console/components/cmd_system/cmd_system.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c b/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c index 2e87c0e65d..20a1212cad 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c +++ b/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c @@ -600,7 +600,7 @@ eap_mschapv2_process(struct eap_sm *sm, void *priv, case MSCHAPV2_OP_FAILURE: return eap_mschapv2_failure(sm, data, ret, ms, len, id); default: - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Unknow op code %d -ignored\n", + wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Unknown op code %d - ignored\n", ms->op_code); return NULL; } diff --git a/examples/protocols/pppos_client/main/pppos_client_main.c b/examples/protocols/pppos_client/main/pppos_client_main.c index 700bc77b34..5a477a5aa1 100644 --- a/examples/protocols/pppos_client/main/pppos_client_main.c +++ b/examples/protocols/pppos_client/main/pppos_client_main.c @@ -120,7 +120,7 @@ static void modem_event_handler(void *event_handler_arg, esp_event_base_t event_ xEventGroupSetBits(event_group, STOP_BIT); break; case ESP_MODEM_EVENT_UNKNOWN: - ESP_LOGW(TAG, "Unknow line received: %s", (char *)event_data); + ESP_LOGW(TAG, "Unknown line received: %s", (char *)event_data); break; default: break; diff --git a/examples/system/console/components/cmd_system/cmd_system.c b/examples/system/console/components/cmd_system/cmd_system.c index 5d5e9fd225..6e82c3df9a 100644 --- a/examples/system/console/components/cmd_system/cmd_system.c +++ b/examples/system/console/components/cmd_system/cmd_system.c @@ -70,7 +70,7 @@ static int get_version(int argc, char **argv) esp_chip_info(&info); printf("IDF Version:%s\r\n", esp_get_idf_version()); printf("Chip info:\r\n"); - printf("\tmodel:%s\r\n", info.model == CHIP_ESP32 ? "ESP32" : "Unknow"); + printf("\tmodel:%s\r\n", info.model == CHIP_ESP32 ? "ESP32" : "Unknown"); printf("\tcores:%d\r\n", info.cores); printf("\tfeature:%s%s%s%s%d%s\r\n", info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "", From 4ac24549ad967e0e1b51f7ab07824132d081a88d Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Mon, 26 Jul 2021 12:25:19 +0200 Subject: [PATCH 002/310] examples: create a new folder structure for generic network examples simple_sniffer was moved from /wifi folder to /network folder network_tests was moved from /system to /network folder README's were updated accordingly to reflect new structure --- examples/README.md | 1 + examples/network/README.md | 5 +++++ .../network_tests/CMakeLists.txt | 0 examples/{system => network}/network_tests/Makefile | 0 .../{system => network}/network_tests/README.md | 0 .../network_tests/main/CMakeLists.txt | 0 .../network_tests/main/component.mk | 0 .../network_tests/main/net_suite.c | 0 .../network_tests/main/stdinout.c | 0 .../network_tests/main/stdinout.h | 0 .../{wifi => network}/simple_sniffer/CMakeLists.txt | 0 examples/{wifi => network}/simple_sniffer/Makefile | 0 examples/{wifi => network}/simple_sniffer/README.md | 0 .../simple_sniffer/components/pcap/CMakeLists.txt | 0 .../simple_sniffer/components/pcap/component.mk | 0 .../simple_sniffer/components/pcap/pcap.c | 0 .../simple_sniffer/components/pcap/pcap.h | 0 .../simple_sniffer/main/CMakeLists.txt | 0 .../simple_sniffer/main/Kconfig.projbuild | 0 .../simple_sniffer/main/cmd_sniffer.c | 0 .../simple_sniffer/main/cmd_sniffer.h | 0 .../simple_sniffer/main/component.mk | 0 .../main/simple_sniffer_example_main.c | 0 .../simple_sniffer/partitions_example.csv | 0 .../simple_sniffer/sdkconfig.defaults | 0 .../simple_sniffer/sniffer-esp32-pcap.png | Bin examples/wifi/README.md | 1 - 27 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 examples/network/README.md rename examples/{system => network}/network_tests/CMakeLists.txt (100%) rename examples/{system => network}/network_tests/Makefile (100%) rename examples/{system => network}/network_tests/README.md (100%) rename examples/{system => network}/network_tests/main/CMakeLists.txt (100%) rename examples/{system => network}/network_tests/main/component.mk (100%) rename examples/{system => network}/network_tests/main/net_suite.c (100%) rename examples/{system => network}/network_tests/main/stdinout.c (100%) rename examples/{system => network}/network_tests/main/stdinout.h (100%) rename examples/{wifi => network}/simple_sniffer/CMakeLists.txt (100%) rename examples/{wifi => network}/simple_sniffer/Makefile (100%) rename examples/{wifi => network}/simple_sniffer/README.md (100%) rename examples/{wifi => network}/simple_sniffer/components/pcap/CMakeLists.txt (100%) rename examples/{wifi => network}/simple_sniffer/components/pcap/component.mk (100%) rename examples/{wifi => network}/simple_sniffer/components/pcap/pcap.c (100%) rename examples/{wifi => network}/simple_sniffer/components/pcap/pcap.h (100%) rename examples/{wifi => network}/simple_sniffer/main/CMakeLists.txt (100%) rename examples/{wifi => network}/simple_sniffer/main/Kconfig.projbuild (100%) rename examples/{wifi => network}/simple_sniffer/main/cmd_sniffer.c (100%) rename examples/{wifi => network}/simple_sniffer/main/cmd_sniffer.h (100%) rename examples/{wifi => network}/simple_sniffer/main/component.mk (100%) rename examples/{wifi => network}/simple_sniffer/main/simple_sniffer_example_main.c (100%) rename examples/{wifi => network}/simple_sniffer/partitions_example.csv (100%) rename examples/{wifi => network}/simple_sniffer/sdkconfig.defaults (100%) rename examples/{wifi => network}/simple_sniffer/sniffer-esp32-pcap.png (100%) diff --git a/examples/README.md b/examples/README.md index fcd3826f78..191b5286b1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -15,6 +15,7 @@ The examples are grouped into subdirectories by category. Each category director * `ethernet` Ethernet network examples. * `get-started` Simple examples with minimal functionality. Good start point for beginners. * `mesh` Wi-Fi Mesh examples. +* `network` Examples related to general network environment, test & analysis. * `openthread` OpenThread examples. * `peripherals` Examples showing driver functionality for the various onboard ESP32 peripherals. * `protocols` Examples showing network protocol interactions. diff --git a/examples/network/README.md b/examples/network/README.md new file mode 100644 index 0000000000..174ac4b60a --- /dev/null +++ b/examples/network/README.md @@ -0,0 +1,5 @@ +# Network Examples + +Contains examples related to general network environment, test & analysis. + +See the [README.md](../README.md) file in the upper level [examples](../) directory for more information about examples. diff --git a/examples/system/network_tests/CMakeLists.txt b/examples/network/network_tests/CMakeLists.txt similarity index 100% rename from examples/system/network_tests/CMakeLists.txt rename to examples/network/network_tests/CMakeLists.txt diff --git a/examples/system/network_tests/Makefile b/examples/network/network_tests/Makefile similarity index 100% rename from examples/system/network_tests/Makefile rename to examples/network/network_tests/Makefile diff --git a/examples/system/network_tests/README.md b/examples/network/network_tests/README.md similarity index 100% rename from examples/system/network_tests/README.md rename to examples/network/network_tests/README.md diff --git a/examples/system/network_tests/main/CMakeLists.txt b/examples/network/network_tests/main/CMakeLists.txt similarity index 100% rename from examples/system/network_tests/main/CMakeLists.txt rename to examples/network/network_tests/main/CMakeLists.txt diff --git a/examples/system/network_tests/main/component.mk b/examples/network/network_tests/main/component.mk similarity index 100% rename from examples/system/network_tests/main/component.mk rename to examples/network/network_tests/main/component.mk diff --git a/examples/system/network_tests/main/net_suite.c b/examples/network/network_tests/main/net_suite.c similarity index 100% rename from examples/system/network_tests/main/net_suite.c rename to examples/network/network_tests/main/net_suite.c diff --git a/examples/system/network_tests/main/stdinout.c b/examples/network/network_tests/main/stdinout.c similarity index 100% rename from examples/system/network_tests/main/stdinout.c rename to examples/network/network_tests/main/stdinout.c diff --git a/examples/system/network_tests/main/stdinout.h b/examples/network/network_tests/main/stdinout.h similarity index 100% rename from examples/system/network_tests/main/stdinout.h rename to examples/network/network_tests/main/stdinout.h diff --git a/examples/wifi/simple_sniffer/CMakeLists.txt b/examples/network/simple_sniffer/CMakeLists.txt similarity index 100% rename from examples/wifi/simple_sniffer/CMakeLists.txt rename to examples/network/simple_sniffer/CMakeLists.txt diff --git a/examples/wifi/simple_sniffer/Makefile b/examples/network/simple_sniffer/Makefile similarity index 100% rename from examples/wifi/simple_sniffer/Makefile rename to examples/network/simple_sniffer/Makefile diff --git a/examples/wifi/simple_sniffer/README.md b/examples/network/simple_sniffer/README.md similarity index 100% rename from examples/wifi/simple_sniffer/README.md rename to examples/network/simple_sniffer/README.md diff --git a/examples/wifi/simple_sniffer/components/pcap/CMakeLists.txt b/examples/network/simple_sniffer/components/pcap/CMakeLists.txt similarity index 100% rename from examples/wifi/simple_sniffer/components/pcap/CMakeLists.txt rename to examples/network/simple_sniffer/components/pcap/CMakeLists.txt diff --git a/examples/wifi/simple_sniffer/components/pcap/component.mk b/examples/network/simple_sniffer/components/pcap/component.mk similarity index 100% rename from examples/wifi/simple_sniffer/components/pcap/component.mk rename to examples/network/simple_sniffer/components/pcap/component.mk diff --git a/examples/wifi/simple_sniffer/components/pcap/pcap.c b/examples/network/simple_sniffer/components/pcap/pcap.c similarity index 100% rename from examples/wifi/simple_sniffer/components/pcap/pcap.c rename to examples/network/simple_sniffer/components/pcap/pcap.c diff --git a/examples/wifi/simple_sniffer/components/pcap/pcap.h b/examples/network/simple_sniffer/components/pcap/pcap.h similarity index 100% rename from examples/wifi/simple_sniffer/components/pcap/pcap.h rename to examples/network/simple_sniffer/components/pcap/pcap.h diff --git a/examples/wifi/simple_sniffer/main/CMakeLists.txt b/examples/network/simple_sniffer/main/CMakeLists.txt similarity index 100% rename from examples/wifi/simple_sniffer/main/CMakeLists.txt rename to examples/network/simple_sniffer/main/CMakeLists.txt diff --git a/examples/wifi/simple_sniffer/main/Kconfig.projbuild b/examples/network/simple_sniffer/main/Kconfig.projbuild similarity index 100% rename from examples/wifi/simple_sniffer/main/Kconfig.projbuild rename to examples/network/simple_sniffer/main/Kconfig.projbuild diff --git a/examples/wifi/simple_sniffer/main/cmd_sniffer.c b/examples/network/simple_sniffer/main/cmd_sniffer.c similarity index 100% rename from examples/wifi/simple_sniffer/main/cmd_sniffer.c rename to examples/network/simple_sniffer/main/cmd_sniffer.c diff --git a/examples/wifi/simple_sniffer/main/cmd_sniffer.h b/examples/network/simple_sniffer/main/cmd_sniffer.h similarity index 100% rename from examples/wifi/simple_sniffer/main/cmd_sniffer.h rename to examples/network/simple_sniffer/main/cmd_sniffer.h diff --git a/examples/wifi/simple_sniffer/main/component.mk b/examples/network/simple_sniffer/main/component.mk similarity index 100% rename from examples/wifi/simple_sniffer/main/component.mk rename to examples/network/simple_sniffer/main/component.mk diff --git a/examples/wifi/simple_sniffer/main/simple_sniffer_example_main.c b/examples/network/simple_sniffer/main/simple_sniffer_example_main.c similarity index 100% rename from examples/wifi/simple_sniffer/main/simple_sniffer_example_main.c rename to examples/network/simple_sniffer/main/simple_sniffer_example_main.c diff --git a/examples/wifi/simple_sniffer/partitions_example.csv b/examples/network/simple_sniffer/partitions_example.csv similarity index 100% rename from examples/wifi/simple_sniffer/partitions_example.csv rename to examples/network/simple_sniffer/partitions_example.csv diff --git a/examples/wifi/simple_sniffer/sdkconfig.defaults b/examples/network/simple_sniffer/sdkconfig.defaults similarity index 100% rename from examples/wifi/simple_sniffer/sdkconfig.defaults rename to examples/network/simple_sniffer/sdkconfig.defaults diff --git a/examples/wifi/simple_sniffer/sniffer-esp32-pcap.png b/examples/network/simple_sniffer/sniffer-esp32-pcap.png similarity index 100% rename from examples/wifi/simple_sniffer/sniffer-esp32-pcap.png rename to examples/network/simple_sniffer/sniffer-esp32-pcap.png diff --git a/examples/wifi/README.md b/examples/wifi/README.md index d425c186de..f40ecfa8b2 100644 --- a/examples/wifi/README.md +++ b/examples/wifi/README.md @@ -14,7 +14,6 @@ The examples are grouped into sub-directories by category. Each category directo * `power_save` contains a how to use power save mode of Wi-Fi. * `roaming` contains a example using 802.11k and 802.11v APIs. * `scan` shows how to scan for all the available APs. -* `simple_sniffer` demonstrates basic usage of WiFi sniffer mode by saving packets into SD card with pcap format. * `smart_config` shows how ESP connects to a target AP with ESPTOUCH. * `wifi_easy_connect` shows how to configure an ESP device as an enrollee using Device Provisioning Protocol (DPP). * `wpa2_enterprise` connects to AP with WPA2 enterprise encryption. From 80810971c80876bf4f830281c1c8005400fc055d Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Thu, 22 Jul 2021 23:26:05 +0300 Subject: [PATCH 003/310] lwip menuconfig option for max number of SNTP servers LWIP has two definess for setting max number of sntp servers: - Total number of handled servers - max number of sntp's picked via DHCP by default both values are equal to 1, but could be set separately Signed-off-by: Emil Muratov --- components/lwip/Kconfig | 10 +++++++++- components/lwip/port/esp32/include/lwipopts.h | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 3393df5bc5..503ed470ac 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -837,7 +837,7 @@ menu "LWIP" menu "SNTP" - config LWIP_DHCP_MAX_NTP_SERVERS + config LWIP_SNTP_MAX_SERVERS int "Maximum number of NTP servers" default 1 range 1 16 @@ -846,6 +846,14 @@ menu "LWIP" First argument of sntp_setserver/sntp_setservername functions is limited to this value. + config LWIP_DHCP_MAX_NTP_SERVERS + int "Maximum number of NTP servers aquired via DHCP" + default 1 + range 1 16 + help + Set maximum number of NTP servers aquired via DHCP-offer. + Must be less or equal to total "Maximum number of NTP servers". + config LWIP_SNTP_UPDATE_DELAY int "Request interval to update time (ms)" range 15000 4294967295 diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index 72e2bc4a97..faea22fb4a 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -1074,6 +1074,11 @@ LWIP_FORWARD_DECLARE_C_CXX void sntp_sync_time(struct timeval *tv); LWIP_FORWARD_DECLARE_C_CXX uint32_t sntp_get_sync_interval(void); +// Max number of SNTP servers handled (default equal to LWIP_DHCP_MAX_NTP_SERVERS) +#if CONFIG_LWIP_SNTP_MAX_SERVERS_DEFINED && !defined SNTP_MAX_SERVERS +#define SNTP_MAX_SERVERS CONFIG_LWIP_SNTP_MAX_SERVERS +#endif // CONFIG_LWIP_SNTP_MAX_SERVERS_DEFINED + /** Set this to 1 to support DNS names (or IP address strings) to set sntp servers * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: * \#define SNTP_SERVER_ADDRESS "pool.ntp.org" From 34be62665cf6b9dc6293da1e87e054c370ce5b5c Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Wed, 28 Jul 2021 19:45:45 +0300 Subject: [PATCH 004/310] lwip: menuconfig option to enable ntp servers option request via DHCP This could be toggled on/off, off is the default. SNTP debug option. Example update for ntp via DHCP Signed-off-by: Emil Muratov --- components/lwip/Kconfig | 16 +++++++++++++++- components/lwip/port/esp32/include/lwipopts.h | 17 +++++++++++++++-- .../protocols/sntp/main/sntp_example_main.c | 8 ++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 503ed470ac..6db94bc5fc 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -846,13 +846,22 @@ menu "LWIP" First argument of sntp_setserver/sntp_setservername functions is limited to this value. + config LWIP_DHCP_GET_NTP_SRV + bool "Request NTP servers from DHCP" + default n + help + If enabled, LWIP will add 'NTP' to Parameter-Request Option sent via DHCP-request. + DHCP server might reply with an NTP server address in option 42. + SNTP callback for such replies should be set accordingly (see sntp_servermode_dhcp() func.) + config LWIP_DHCP_MAX_NTP_SERVERS int "Maximum number of NTP servers aquired via DHCP" default 1 range 1 16 + depends on LWIP_DHCP_GET_NTP_SRV help Set maximum number of NTP servers aquired via DHCP-offer. - Must be less or equal to total "Maximum number of NTP servers". + Should be less or equal to "Maximum number of NTP servers", any extra servers would be just ignored. config LWIP_SNTP_UPDATE_DELAY int "Request interval to update time (ms)" @@ -1033,4 +1042,9 @@ menu "LWIP" depends on LWIP_DEBUG default n + config LWIP_SNTP_DEBUG + bool "Enable SNTP debug messages" + depends on LWIP_DEBUG + default n + endmenu diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index faea22fb4a..4c00622b94 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -910,6 +910,15 @@ #define TCP_DEBUG LWIP_DBG_OFF #endif +/** + * SNTP_DEBUG: Enable debugging for SNTP. + */ +#ifdef CONFIG_LWIP_SNTP_DEBUG +#define SNTP_DEBUG LWIP_DBG_ON +#else +#define SNTP_DEBUG LWIP_DBG_OFF +#endif + /** * MEMP_DEBUG: Enable debugging in memp.c. */ @@ -1075,9 +1084,13 @@ LWIP_FORWARD_DECLARE_C_CXX void sntp_sync_time(struct timeval *tv); LWIP_FORWARD_DECLARE_C_CXX uint32_t sntp_get_sync_interval(void); // Max number of SNTP servers handled (default equal to LWIP_DHCP_MAX_NTP_SERVERS) -#if CONFIG_LWIP_SNTP_MAX_SERVERS_DEFINED && !defined SNTP_MAX_SERVERS +#if defined CONFIG_LWIP_SNTP_MAX_SERVERS #define SNTP_MAX_SERVERS CONFIG_LWIP_SNTP_MAX_SERVERS -#endif // CONFIG_LWIP_SNTP_MAX_SERVERS_DEFINED +#endif // CONFIG_LWIP_SNTP_MAX_SERVERS + +#ifdef CONFIG_LWIP_DHCP_GET_NTP_SRV +#define LWIP_DHCP_GET_NTP_SRV CONFIG_LWIP_DHCP_GET_NTP_SRV +#endif // CONFIG_LWIP_DHCP_GET_NTP_SRV /** Set this to 1 to support DNS names (or IP address strings) to set sntp servers * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: diff --git a/examples/protocols/sntp/main/sntp_example_main.c b/examples/protocols/sntp/main/sntp_example_main.c index e0e910ce0d..3733241640 100644 --- a/examples/protocols/sntp/main/sntp_example_main.c +++ b/examples/protocols/sntp/main/sntp_example_main.c @@ -122,6 +122,14 @@ static void obtain_time(void) ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK( esp_event_loop_create_default() ); + /** + * NTP server address could be aquired via DHCP, + * see LWIP_DHCP_GET_NTP_SRV menuconfig option + */ +#ifdef LWIP_DHCP_GET_NTP_SRV + sntp_servermode_dhcp(1); +#endif + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. * Read "Establishing Wi-Fi or Ethernet Connection" section in * examples/protocols/README.md for more information about this function. From 02bc5df476e78371023d164118b32593707ef45e Mon Sep 17 00:00:00 2001 From: Jeff Kent Date: Tue, 3 Aug 2021 23:51:55 -0500 Subject: [PATCH 005/310] Typo fix in cmd_nvs.c --- examples/system/console/advanced/components/cmd_nvs/cmd_nvs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/system/console/advanced/components/cmd_nvs/cmd_nvs.c b/examples/system/console/advanced/components/cmd_nvs/cmd_nvs.c index 3878702eb4..febd5cad7a 100644 --- a/examples/system/console/advanced/components/cmd_nvs/cmd_nvs.c +++ b/examples/system/console/advanced/components/cmd_nvs/cmd_nvs.c @@ -538,7 +538,7 @@ void register_nvs(void) .help = "Set key-value pair in selected namespace.\n" "Examples:\n" " nvs_set VarName i32 -v 123 \n" - " nvs_set VarName srt -v YourString \n" + " nvs_set VarName str -v YourString \n" " nvs_set VarName blob -v 0123456789abcdef \n", .hint = NULL, .func = &set_value, From 2f5c0355fea5a26c26a8469279444ae87955224f Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Tue, 10 Aug 2021 15:29:07 +0800 Subject: [PATCH 006/310] I2C: Fix i2c write fake timeout and WDT triggered --- components/hal/i2c_hal_iram.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/components/hal/i2c_hal_iram.c b/components/hal/i2c_hal_iram.c index 80c490009b..f40d4a3a0b 100644 --- a/components/hal/i2c_hal_iram.c +++ b/components/hal/i2c_hal_iram.c @@ -16,25 +16,30 @@ void i2c_hal_master_handle_tx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event) { - i2c_ll_master_get_event(hal->dev, event); - if ((*event < I2C_INTR_EVENT_END_DET) || - (*event == I2C_INTR_EVENT_TRANS_DONE)) { - i2c_ll_master_disable_tx_it(hal->dev); - i2c_ll_master_clr_tx_it(hal->dev); - } else if (*event == I2C_INTR_EVENT_END_DET) { - i2c_ll_master_clr_tx_it(hal->dev); + if (i2c_ll_get_intsts_mask(hal->dev) != 0) { + // If intr status is 0, no need to handle it. + i2c_ll_master_get_event(hal->dev, event); + if ((*event < I2C_INTR_EVENT_END_DET) || + (*event == I2C_INTR_EVENT_TRANS_DONE)) { + i2c_ll_master_disable_tx_it(hal->dev); + i2c_ll_master_clr_tx_it(hal->dev); + } else if (*event == I2C_INTR_EVENT_END_DET) { + i2c_ll_master_clr_tx_it(hal->dev); + } } } void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event) { - i2c_ll_master_get_event(hal->dev, event); - if ((*event < I2C_INTR_EVENT_END_DET) || - (*event == I2C_INTR_EVENT_TRANS_DONE)) { - i2c_ll_master_disable_rx_it(hal->dev); - i2c_ll_master_clr_rx_it(hal->dev); - } else if (*event == I2C_INTR_EVENT_END_DET) { - i2c_ll_master_clr_rx_it(hal->dev); + if (i2c_ll_get_intsts_mask(hal->dev) != 0) { + i2c_ll_master_get_event(hal->dev, event); + if ((*event < I2C_INTR_EVENT_END_DET) || + (*event == I2C_INTR_EVENT_TRANS_DONE)) { + i2c_ll_master_disable_rx_it(hal->dev); + i2c_ll_master_clr_rx_it(hal->dev); + } else if (*event == I2C_INTR_EVENT_END_DET) { + i2c_ll_master_clr_rx_it(hal->dev); + } } } From fbd25c38371f4985e0e749589c65c59a02a139fb Mon Sep 17 00:00:00 2001 From: Chen Yi Qun Date: Fri, 6 Aug 2021 15:47:12 +0800 Subject: [PATCH 007/310] I2C: add conf_update for esp32c3 i2c --- components/driver/i2c.c | 9 ++++++++- components/hal/esp32c3/include/hal/i2c_ll.h | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 1ac074a299..438d1efc12 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -539,6 +539,7 @@ esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, ESP_RETURN_ON_FALSE(rx_trans_mode < I2C_DATA_MODE_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TRANS_MODE_ERR_STR); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_data_mode(&(i2c_context[i2c_num].hal), tx_trans_mode, rx_trans_mode); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -690,13 +691,13 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf) i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), I2C_SLAVE_SDA_SAMPLE_DEFAULT, I2C_SLAVE_SDA_HOLD_DEFAULT); i2c_hal_set_tout(&(i2c_context[i2c_num].hal), I2C_SLAVE_TIMEOUT_DEFAULT); i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal)); - i2c_hal_update_config(&(i2c_context[i2c_num].hal)); } else { i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num); //Default, we enable hardware filter i2c_hal_set_filter(&(i2c_context[i2c_num].hal), I2C_FILTER_CYC_NUM_DEF); i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, src_clk); } + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -709,6 +710,7 @@ esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period) I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_scl_timing(&(i2c_context[i2c_num].hal), high_period, low_period); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -728,6 +730,7 @@ esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num) ESP_RETURN_ON_FALSE(p_i2c_obj[i2c_num] != NULL, ESP_FAIL, I2C_TAG, I2C_DRIVER_ERR_STR); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_filter(&(i2c_context[i2c_num].hal), cyc_num); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -737,6 +740,7 @@ esp_err_t i2c_filter_disable(i2c_port_t i2c_num) ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_filter(&(i2c_context[i2c_num].hal), 0); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -749,6 +753,7 @@ esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_start_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -770,6 +775,7 @@ esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time) I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_stop_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -791,6 +797,7 @@ esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), sample_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } diff --git a/components/hal/esp32c3/include/hal/i2c_ll.h b/components/hal/esp32c3/include/hal/i2c_ll.h index 85c946c23b..d8fbfd206c 100644 --- a/components/hal/esp32c3/include/hal/i2c_ll.h +++ b/components/hal/esp32c3/include/hal/i2c_ll.h @@ -801,9 +801,12 @@ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw) static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw) { hw->scl_sp_conf.scl_rst_slv_num = 9; - hw->scl_sp_conf.scl_rst_slv_en = 0; - hw->ctr.conf_upgate = 1; hw->scl_sp_conf.scl_rst_slv_en = 1; + hw->ctr.conf_upgate = 1; + // hardward will clear scl_rst_slv_en after sending SCL pulses, + // and we should set conf_upgate bit to synchronize register value. + while (hw->scl_sp_conf.scl_rst_slv_en); + hw->ctr.conf_upgate = 1; } /** From f913a10a22f471e93b6ebcc0a25f9fabee17ef81 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 11 Aug 2021 17:35:21 +0800 Subject: [PATCH 008/310] update reset reason for c3/s3/h2 --- components/esp_rom/include/esp32c3/rom/rtc.h | 18 +++++++++++++---- components/esp_rom/include/esp32h2/rom/rtc.h | 20 +++++++++++++++---- components/esp_rom/include/esp32s3/rom/rtc.h | 7 +++++++ .../soc/esp32c3/include/soc/reset_reasons.h | 2 ++ .../soc/esp32h2/include/soc/reset_reasons.h | 3 +++ .../soc/esp32s3/include/soc/reset_reasons.h | 2 ++ 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/components/esp_rom/include/esp32c3/rom/rtc.h b/components/esp_rom/include/esp32c3/rom/rtc.h index 76ece7e819..2a7f6cb614 100644 --- a/components/esp_rom/include/esp32c3/rom/rtc.h +++ b/components/esp_rom/include/esp32c3/rom/rtc.h @@ -85,8 +85,7 @@ typedef enum { NO_MEAN = 0, POWERON_RESET = 1, /**<1, Vbat power on reset*/ RTC_SW_SYS_RESET = 3, /**<3, Software reset digital core*/ - DEEPSLEEP_RESET = 5, /**<3, Deep Sleep reset digital core*/ - SDIO_RESET = 6, /**<6, Reset by SLC module, reset digital core*/ + DEEPSLEEP_RESET = 5, /**<5, Deep Sleep reset digital core*/ TG0WDT_SYS_RESET = 7, /**<7, Timer Group0 Watch dog reset digital core*/ TG1WDT_SYS_RESET = 8, /**<8, Timer Group1 Watch dog reset digital core*/ RTCWDT_SYS_RESET = 9, /**<9, RTC Watch dog Reset digital core*/ @@ -96,8 +95,13 @@ typedef enum { RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/ RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/ RTCWDT_RTC_RESET = 16, /**<16, RTC Watch dog reset digital core and rtc module*/ - TG1WDT_CPU_RESET = 17, /**<11, Time Group1 reset CPU*/ - SUPER_WDT_RESET = 18, /**<11, super watchdog reset digital core and rtc module*/ + TG1WDT_CPU_RESET = 17, /**<17, Time Group1 reset CPU*/ + SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/ + GLITCH_RTC_RESET = 19, /**<19, glitch reset digital core and rtc module*/ + EFUSE_RESET = 20, /**<20, efuse reset digital core*/ + USB_UART_CHIP_RESET = 21, /**<21, usb uart reset digital core */ + USB_JTAG_CHIP_RESET = 22, /**<22, usb jtag reset digital core */ + POWER_GLITCH_RESET = 23, /**<23, power glitch reset digital core and rtc module*/ } RESET_REASON; // Check if the reset reason defined in ROM is compatible with soc/reset_reasons.h @@ -112,7 +116,13 @@ _Static_assert((soc_reset_reason_t)RTC_SW_CPU_RESET == RESET_REASON_CPU0_SW, "RT _Static_assert((soc_reset_reason_t)RTCWDT_CPU_RESET == RESET_REASON_CPU0_RTC_WDT, "RTCWDT_CPU_RESET != RESET_REASON_CPU0_RTC_WDT"); _Static_assert((soc_reset_reason_t)RTCWDT_BROWN_OUT_RESET == RESET_REASON_SYS_BROWN_OUT, "RTCWDT_BROWN_OUT_RESET != RESET_REASON_SYS_BROWN_OUT"); _Static_assert((soc_reset_reason_t)RTCWDT_RTC_RESET == RESET_REASON_SYS_RTC_WDT, "RTCWDT_RTC_RESET != RESET_REASON_SYS_RTC_WDT"); +_Static_assert((soc_reset_reason_t)TG1WDT_CPU_RESET == RESET_REASON_CPU0_MWDT1, "TG1WDT_CPU_RESET != RESET_REASON_CPU0_MWDT1"); _Static_assert((soc_reset_reason_t)SUPER_WDT_RESET == RESET_REASON_SYS_SUPER_WDT, "SUPER_WDT_RESET != RESET_REASON_SYS_SUPER_WDT"); +_Static_assert((soc_reset_reason_t)GLITCH_RTC_RESET == RESET_REASON_SYS_CLK_GLITCH, "GLITCH_RTC_RESET != RESET_REASON_SYS_CLK_GLITCH"); +_Static_assert((soc_reset_reason_t)EFUSE_RESET == RESET_REASON_CORE_EFUSE_CRC, "EFUSE_RESET != RESET_REASON_CORE_EFUSE_CRC"); +_Static_assert((soc_reset_reason_t)USB_UART_CHIP_RESET == RESET_REASON_CORE_USB_UART, "USB_UART_CHIP_RESET != RESET_REASON_CORE_USB_UART"); +_Static_assert((soc_reset_reason_t)USB_JTAG_CHIP_RESET == RESET_REASON_CORE_USB_JTAG, "USB_JTAG_CHIP_RESET != RESET_REASON_CORE_USB_JTAG"); +_Static_assert((soc_reset_reason_t)POWER_GLITCH_RESET == RESET_REASON_CORE_PWR_GLITCH, "POWER_GLITCH_RESET != RESET_REASON_CORE_PWR_GLITCH"); typedef enum { NO_SLEEP = 0, diff --git a/components/esp_rom/include/esp32h2/rom/rtc.h b/components/esp_rom/include/esp32h2/rom/rtc.h index 76ece7e819..ad4f45c2ca 100644 --- a/components/esp_rom/include/esp32h2/rom/rtc.h +++ b/components/esp_rom/include/esp32h2/rom/rtc.h @@ -85,8 +85,7 @@ typedef enum { NO_MEAN = 0, POWERON_RESET = 1, /**<1, Vbat power on reset*/ RTC_SW_SYS_RESET = 3, /**<3, Software reset digital core*/ - DEEPSLEEP_RESET = 5, /**<3, Deep Sleep reset digital core*/ - SDIO_RESET = 6, /**<6, Reset by SLC module, reset digital core*/ + DEEPSLEEP_RESET = 5, /**<5, Deep Sleep reset digital core*/ TG0WDT_SYS_RESET = 7, /**<7, Timer Group0 Watch dog reset digital core*/ TG1WDT_SYS_RESET = 8, /**<8, Timer Group1 Watch dog reset digital core*/ RTCWDT_SYS_RESET = 9, /**<9, RTC Watch dog Reset digital core*/ @@ -96,8 +95,14 @@ typedef enum { RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/ RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/ RTCWDT_RTC_RESET = 16, /**<16, RTC Watch dog reset digital core and rtc module*/ - TG1WDT_CPU_RESET = 17, /**<11, Time Group1 reset CPU*/ - SUPER_WDT_RESET = 18, /**<11, super watchdog reset digital core and rtc module*/ + TG1WDT_CPU_RESET = 17, /**<17, Time Group1 reset CPU*/ + SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/ + GLITCH_RTC_RESET = 19, /**<19, glitch reset digital core and rtc module*/ + EFUSE_RESET = 20, /**<20, efuse reset digital core*/ + USB_UART_CHIP_RESET = 21, /**<21, usb uart reset digital core */ + USB_JTAG_CHIP_RESET = 22, /**<22, usb jtag reset digital core */ + POWER_GLITCH_RESET = 23, /**<23, power glitch reset digital core and rtc module*/ + JTAG_RESET = 24, /**<24, jtag reset CPU*/ } RESET_REASON; // Check if the reset reason defined in ROM is compatible with soc/reset_reasons.h @@ -112,7 +117,14 @@ _Static_assert((soc_reset_reason_t)RTC_SW_CPU_RESET == RESET_REASON_CPU0_SW, "RT _Static_assert((soc_reset_reason_t)RTCWDT_CPU_RESET == RESET_REASON_CPU0_RTC_WDT, "RTCWDT_CPU_RESET != RESET_REASON_CPU0_RTC_WDT"); _Static_assert((soc_reset_reason_t)RTCWDT_BROWN_OUT_RESET == RESET_REASON_SYS_BROWN_OUT, "RTCWDT_BROWN_OUT_RESET != RESET_REASON_SYS_BROWN_OUT"); _Static_assert((soc_reset_reason_t)RTCWDT_RTC_RESET == RESET_REASON_SYS_RTC_WDT, "RTCWDT_RTC_RESET != RESET_REASON_SYS_RTC_WDT"); +_Static_assert((soc_reset_reason_t)TG1WDT_CPU_RESET == RESET_REASON_CPU0_MWDT1, "TG1WDT_CPU_RESET != RESET_REASON_CPU0_MWDT1"); _Static_assert((soc_reset_reason_t)SUPER_WDT_RESET == RESET_REASON_SYS_SUPER_WDT, "SUPER_WDT_RESET != RESET_REASON_SYS_SUPER_WDT"); +_Static_assert((soc_reset_reason_t)GLITCH_RTC_RESET == RESET_REASON_SYS_CLK_GLITCH, "GLITCH_RTC_RESET != RESET_REASON_SYS_CLK_GLITCH"); +_Static_assert((soc_reset_reason_t)EFUSE_RESET == RESET_REASON_CORE_EFUSE_CRC, "EFUSE_RESET != RESET_REASON_CORE_EFUSE_CRC"); +_Static_assert((soc_reset_reason_t)USB_UART_CHIP_RESET == RESET_REASON_CORE_USB_UART, "USB_UART_CHIP_RESET != RESET_REASON_CORE_USB_UART"); +_Static_assert((soc_reset_reason_t)USB_JTAG_CHIP_RESET == RESET_REASON_CORE_USB_JTAG, "USB_JTAG_CHIP_RESET != RESET_REASON_CORE_USB_JTAG"); +_Static_assert((soc_reset_reason_t)POWER_GLITCH_RESET == RESET_REASON_CORE_PWR_GLITCH, "POWER_GLITCH_RESET != RESET_REASON_CORE_PWR_GLITCH"); +_Static_assert((soc_reset_reason_t)JTAG_RESET == RESET_REASON_CPU_JTAG, "JTAG_RESET != RESET_REASON_CPU_JTAG"); typedef enum { NO_SLEEP = 0, diff --git a/components/esp_rom/include/esp32s3/rom/rtc.h b/components/esp_rom/include/esp32s3/rom/rtc.h index 09d2376ef3..d928c4dee4 100644 --- a/components/esp_rom/include/esp32s3/rom/rtc.h +++ b/components/esp_rom/include/esp32s3/rom/rtc.h @@ -92,6 +92,9 @@ typedef enum { SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/ GLITCH_RTC_RESET = 19, /**<19, glitch reset digital core and rtc module*/ EFUSE_RESET = 20, /**<20, efuse reset digital core*/ + USB_UART_CHIP_RESET = 21, /**<21, usb uart reset digital core */ + USB_JTAG_CHIP_RESET = 22, /**<22, usb jtag reset digital core */ + POWER_GLITCH_RESET = 23, /**<23, power glitch reset digital core and rtc module*/ } RESET_REASON; // Check if the reset reason defined in ROM is compatible with soc/reset_reasons.h @@ -106,9 +109,13 @@ _Static_assert((soc_reset_reason_t)RTC_SW_CPU_RESET == RESET_REASON_CPU0_SW, "RT _Static_assert((soc_reset_reason_t)RTCWDT_CPU_RESET == RESET_REASON_CPU0_RTC_WDT, "RTCWDT_CPU_RESET != RESET_REASON_CPU0_RTC_WDT"); _Static_assert((soc_reset_reason_t)RTCWDT_BROWN_OUT_RESET == RESET_REASON_SYS_BROWN_OUT, "RTCWDT_BROWN_OUT_RESET != RESET_REASON_SYS_BROWN_OUT"); _Static_assert((soc_reset_reason_t)RTCWDT_RTC_RESET == RESET_REASON_SYS_RTC_WDT, "RTCWDT_RTC_RESET != RESET_REASON_SYS_RTC_WDT"); +_Static_assert((soc_reset_reason_t)TG1WDT_CPU_RESET == RESET_REASON_CPU0_MWDT1, "TG1WDT_CPU_RESET != RESET_REASON_CPU0_MWDT1"); _Static_assert((soc_reset_reason_t)SUPER_WDT_RESET == RESET_REASON_SYS_SUPER_WDT, "SUPER_WDT_RESET != RESET_REASON_SYS_SUPER_WDT"); _Static_assert((soc_reset_reason_t)GLITCH_RTC_RESET == RESET_REASON_SYS_CLK_GLITCH, "GLITCH_RTC_RESET != RESET_REASON_SYS_CLK_GLITCH"); _Static_assert((soc_reset_reason_t)EFUSE_RESET == RESET_REASON_CORE_EFUSE_CRC, "EFUSE_RESET != RESET_REASON_CORE_EFUSE_CRC"); +_Static_assert((soc_reset_reason_t)USB_UART_CHIP_RESET == RESET_REASON_CORE_USB_UART, "USB_UART_CHIP_RESET != RESET_REASON_CORE_USB_UART"); +_Static_assert((soc_reset_reason_t)USB_JTAG_CHIP_RESET == RESET_REASON_CORE_USB_JTAG, "USB_JTAG_CHIP_RESET != RESET_REASON_CORE_USB_JTAG"); +_Static_assert((soc_reset_reason_t)POWER_GLITCH_RESET == RESET_REASON_CORE_PWR_GLITCH, "POWER_GLITCH_RESET != RESET_REASON_CORE_PWR_GLITCH"); typedef enum { NO_SLEEP = 0, diff --git a/components/soc/esp32c3/include/soc/reset_reasons.h b/components/soc/esp32c3/include/soc/reset_reasons.h index 0bb99f5851..c624619bb3 100644 --- a/components/soc/esp32c3/include/soc/reset_reasons.h +++ b/components/soc/esp32c3/include/soc/reset_reasons.h @@ -52,6 +52,8 @@ typedef enum { RESET_REASON_SYS_SUPER_WDT = 0x12, // Super watch dog resets the digital core and rtc module RESET_REASON_SYS_CLK_GLITCH = 0x13, // Glitch on clock resets the digital core and rtc module RESET_REASON_CORE_EFUSE_CRC = 0x14, // eFuse CRC error resets the digital core + RESET_REASON_CORE_USB_UART = 0x15, // USB UART resets the digital core + RESET_REASON_CORE_USB_JTAG = 0x16, // USB JTAG resets the digital core RESET_REASON_CORE_PWR_GLITCH = 0x17, // Glitch on power resets the digital core } soc_reset_reason_t; diff --git a/components/soc/esp32h2/include/soc/reset_reasons.h b/components/soc/esp32h2/include/soc/reset_reasons.h index 0bb99f5851..b11a6ee52a 100644 --- a/components/soc/esp32h2/include/soc/reset_reasons.h +++ b/components/soc/esp32h2/include/soc/reset_reasons.h @@ -52,7 +52,10 @@ typedef enum { RESET_REASON_SYS_SUPER_WDT = 0x12, // Super watch dog resets the digital core and rtc module RESET_REASON_SYS_CLK_GLITCH = 0x13, // Glitch on clock resets the digital core and rtc module RESET_REASON_CORE_EFUSE_CRC = 0x14, // eFuse CRC error resets the digital core + RESET_REASON_CORE_USB_UART = 0x15, // USB UART resets the digital core + RESET_REASON_CORE_USB_JTAG = 0x16, // USB JTAG resets the digital core RESET_REASON_CORE_PWR_GLITCH = 0x17, // Glitch on power resets the digital core + RESET_REASON_CPU_JTAG = 0x18, // JTAG resets the CPU } soc_reset_reason_t; diff --git a/components/soc/esp32s3/include/soc/reset_reasons.h b/components/soc/esp32s3/include/soc/reset_reasons.h index 6fc0a7391a..2c1c34e9fe 100644 --- a/components/soc/esp32s3/include/soc/reset_reasons.h +++ b/components/soc/esp32s3/include/soc/reset_reasons.h @@ -56,6 +56,8 @@ typedef enum { RESET_REASON_SYS_SUPER_WDT = 0x12, // Super watch dog resets the digital core and rtc module RESET_REASON_SYS_CLK_GLITCH = 0x13, // Glitch on clock resets the digital core and rtc module RESET_REASON_CORE_EFUSE_CRC = 0x14, // eFuse CRC error resets the digital core + RESET_REASON_CORE_USB_UART = 0x15, // USB UART resets the digital core + RESET_REASON_CORE_USB_JTAG = 0x16, // USB JTAG resets the digital core RESET_REASON_CORE_PWR_GLITCH = 0x17, // Glitch on power resets the digital core } soc_reset_reason_t; From 986603cf07413b46c88c76c324bf500edcfb6171 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Thu, 5 Aug 2021 16:59:04 +0800 Subject: [PATCH 009/310] mdns: add notification callback for async APIs --- components/mdns/include/mdns.h | 6 +++++- components/mdns/mdns.c | 14 ++++++++++---- components/mdns/private_include/mdns_private.h | 1 + components/mdns/test_afl_fuzz_host/mdns_di.h | 9 ++++++--- examples/protocols/mdns/main/mdns_example_main.c | 4 ++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 7089eabe6a..4318ef37f7 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -90,6 +90,8 @@ typedef struct mdns_result_s { mdns_ip_addr_t * addr; /*!< linked list of IP addresses found */ } mdns_result_t; +typedef void (*mdns_query_notify_t)(mdns_search_once_t *search); + /** * @brief Initialize mDNS on given interface * @@ -519,11 +521,13 @@ bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, * @param type type of query (MDNS_TYPE_*) * @param timeout time in milliseconds during which mDNS query is active * @param max_results maximum results to be collected + * @param notifier Notification function to be called when the result is ready, can be NULL * * @return mdns_search_once_s pointer to new search object if query initiated successfully. * NULL otherwise. */ -mdns_search_once_t* mdns_query_async_new(const char * name, const char * service_type, const char * proto, uint16_t type, uint32_t timeout, size_t max_results); +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service_type, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier); /** * @brief Query mDNS for host or service diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 508672d30e..8f97914925 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3592,7 +3592,8 @@ static void _mdns_search_free(mdns_search_once_t * search) /** * @brief Allocate new search structure */ -static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t)); if (!search) { @@ -3639,6 +3640,7 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se search->state = SEARCH_INIT; search->sent_at = 0; search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; + search->notifier = notifier; search->next = NULL; return search; @@ -3651,6 +3653,9 @@ static void _mdns_search_finish(mdns_search_once_t * search) { search->state = SEARCH_OFF; queueDetach(mdns_search_once_t, _mdns_server->search_once, search); + if (search->notifier) { + search->notifier(search); + } xSemaphoreGive(search->done_semaphore); } @@ -5310,7 +5315,8 @@ bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, return false; } -mdns_search_once_t* mdns_query_async_new(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, size_t max_results) +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t *search = NULL; @@ -5318,7 +5324,7 @@ mdns_search_once_t* mdns_query_async_new(const char * name, const char * service return NULL; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results); + search = _mdns_search_init(name, service, proto, type, timeout, max_results, notifier); if (!search) { return NULL; } @@ -5345,7 +5351,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto return ESP_ERR_INVALID_ARG; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results); + search = _mdns_search_init(name, service, proto, type, timeout, max_results, NULL); if (!search) { return ESP_ERR_NO_MEM; } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 6931d4f5a7..564219bf6f 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -364,6 +364,7 @@ typedef struct mdns_search_once_s { uint32_t started_at; uint32_t sent_at; uint32_t timeout; + mdns_query_notify_t notifier; SemaphoreHandle_t done_semaphore; uint16_t type; uint8_t max_results; diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h index 4ed0e84cdd..12c0c56f77 100644 --- a/components/mdns/test_afl_fuzz_host/mdns_di.h +++ b/components/mdns/test_afl_fuzz_host/mdns_di.h @@ -8,13 +8,16 @@ void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; mdns_srv_item_t * (*mdns_test_static_mdns_get_service_item)(const char * service, const char * proto, const char *hostname) = NULL; -mdns_search_once_t * (*mdns_test_static_search_init)(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) = NULL; +mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, + uint16_t type, uint32_t timeout, uint8_t max_results, + mdns_query_notify_t notifier) = NULL; esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t * search) = NULL; void (*mdns_test_static_search_free)(mdns_search_once_t * search) = NULL; static void _mdns_execute_action(mdns_action_t * action); static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char *hostname); -static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results); +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); static void _mdns_search_free(mdns_search_once_t * search); @@ -44,7 +47,7 @@ esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) { - return mdns_test_static_search_init(name, service, proto, type, timeout, max_results); + return mdns_test_static_search_init(name, service, proto, type, timeout, max_results, NULL); } mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index fc5b450374..da772b5edb 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -169,9 +169,9 @@ static void query_mdns_hosts_async(const char * host_name) { ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); - mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1); + mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); mdns_query_async_delete(s_a); - mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1); + mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); while (s_a || s_aaaa) { if (s_a && check_and_print_result(s_a)) { ESP_LOGI(TAG, "Query A %s.local finished", host_name); From 0d07569fff5d41ecbadd7606cb9b3c6224597841 Mon Sep 17 00:00:00 2001 From: xueyunfei Date: Tue, 29 Dec 2020 16:10:37 +0800 Subject: [PATCH 010/310] optimization config option LWIP_TCPIP_CORE_LOCKING --- components/esp_netif/lwip/esp_netif_lwip.c | 11 +++++++++-- components/esp_system/include/esp_task.h | 4 ++++ components/lwip/Kconfig | 10 ++++++++++ components/lwip/port/esp32/include/lwipopts.h | 6 +++++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index 3b06f04f8f..8a9fee5029 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -101,11 +101,13 @@ extern sys_thread_t g_lwip_task; static const char *TAG = "esp_netif_lwip"; -static sys_sem_t api_sync_sem = NULL; -static sys_sem_t api_lock_sem = NULL; static bool tcpip_initialized = false; static esp_netif_t *s_last_default_esp_netif = NULL; +#if !LWIP_TCPIP_CORE_LOCKING +static sys_sem_t api_sync_sem = NULL; +static sys_sem_t api_lock_sem = NULL; + /** * @brief Api callback from tcpip thread used to call esp-netif * function in lwip task context @@ -124,6 +126,7 @@ static void esp_netif_api_cb(void *api_msg) sys_sem_signal(&api_sync_sem); } +#endif /** * @brief Initiates a tcpip remote call if called from another task @@ -136,6 +139,7 @@ static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t .data = data, .api_fn = fn }; +#if !LWIP_TCPIP_CORE_LOCKING if (g_lwip_task != xTaskGetCurrentTaskHandle()) { ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", netif, fn); sys_arch_sem_wait(&api_lock_sem, 0); @@ -143,6 +147,7 @@ static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t sys_sem_signal(&api_lock_sem); return msg.ret; } +#endif /* !LWIP_TCPIP_CORE_LOCKING */ ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", netif, fn); return fn(&msg); } @@ -324,6 +329,7 @@ esp_err_t esp_netif_init(void) ESP_LOGD(TAG, "LwIP stack has been initialized"); } +#if !LWIP_TCPIP_CORE_LOCKING if (!api_sync_sem) { if (ERR_OK != sys_sem_new(&api_sync_sem, 0)) { ESP_LOGE(TAG, "esp netif api sync sem init fail"); @@ -337,6 +343,7 @@ esp_err_t esp_netif_init(void) return ESP_FAIL; } } +#endif ESP_LOGD(TAG, "esp-netif has been successfully initialized"); return ESP_OK; diff --git a/components/esp_system/include/esp_task.h b/components/esp_system/include/esp_task.h index 37d78bca6e..adca9cde6b 100644 --- a/components/esp_system/include/esp_task.h +++ b/components/esp_system/include/esp_task.h @@ -52,7 +52,11 @@ #define ESP_TASK_TIMER_PRIO (ESP_TASK_PRIO_MAX - 3) #define ESP_TASK_TIMER_STACK (CONFIG_ESP_TIMER_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) #define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5) +#if CONFIG_LWIP_TCPIP_CORE_LOCKING +#define ESP_TASKD_EVENT_STACK (CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE + 2048) +#else #define ESP_TASKD_EVENT_STACK (CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) +#endif /* CONFIG_LWIP_TCPIP_CORE_LOCKING */ #define ESP_TASK_TCPIP_PRIO (ESP_TASK_PRIO_MAX - 7) #define ESP_TASK_TCPIP_STACK (CONFIG_LWIP_TCPIP_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) #define ESP_TASK_MAIN_PRIO (ESP_TASK_PRIO_MIN + 1) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 3393df5bc5..f6eb55bfcb 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -15,6 +15,16 @@ menu "LWIP" could be used to convert network interface index to name instead of IDF specific esp-netif APIs (such as esp_netif_get_netif_impl_name()) + config LWIP_TCPIP_CORE_LOCKING + bool "Enable tcpip core locking" + default n + help + If Enable tcpip core locking,Creates a global mutex that is held + during TCPIP thread operations.Can be locked by client code to perform + lwIP operations without changing into TCPIP thread using callbacks. + See LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE(). + + If disable tcpip core locking,TCP IP will perform tasks through context switching. config LWIP_DNS_SUPPORT_MDNS_QUERIES bool "Enable mDNS queries in resolving host name" diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index 72e2bc4a97..dd721909aa 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -595,7 +595,7 @@ * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) * Don't use it if you're not an active lwIP project member */ -#define LWIP_TCPIP_CORE_LOCKING 0 +#define LWIP_TCPIP_CORE_LOCKING CONFIG_LWIP_TCPIP_CORE_LOCKING /* ------------------------------------ @@ -1044,7 +1044,11 @@ #define CHECKSUM_CHECK_ICMP CONFIG_LWIP_CHECKSUM_CHECK_ICMP #define LWIP_NETCONN_FULLDUPLEX 1 +#if LWIP_TCPIP_CORE_LOCKING +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#else #define LWIP_NETCONN_SEM_PER_THREAD 1 +#endif /* LWIP_TCPIP_CORE_LOCKING */ #define LWIP_DHCP_MAX_NTP_SERVERS CONFIG_LWIP_DHCP_MAX_NTP_SERVERS #define LWIP_TIMEVAL_PRIVATE 0 From 6deaefde69c3f068d39b76d628b05b21fd142b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Garci=CC=81a=20Hierro?= Date: Wed, 21 Apr 2021 22:01:14 +0100 Subject: [PATCH 011/310] Enable IO20 on ESP32 Some newer ESP32 variants (like ESP32-PICO-V3 and ESP32-PICO-MINI-02) do implement this pin and it can be used as a normal GPIO. Fixes #6016 Fixes #6837 Closes https://github.com/espressif/esp-idf/pull/6918 --- components/soc/esp32/gpio_periph.c | 2 +- components/soc/esp32/include/soc/soc_caps.h | 4 ++-- docs/en/api-reference/peripherals/gpio.rst | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/components/soc/esp32/gpio_periph.c b/components/soc/esp32/gpio_periph.c index a413203741..d993cb42ac 100644 --- a/components/soc/esp32/gpio_periph.c +++ b/components/soc/esp32/gpio_periph.c @@ -35,7 +35,7 @@ const uint32_t GPIO_PIN_MUX_REG[SOC_GPIO_PIN_COUNT] = { IO_MUX_GPIO17_REG, IO_MUX_GPIO18_REG, IO_MUX_GPIO19_REG, - 0, + IO_MUX_GPIO20_REG, // This corresponding pin is only available on ESP32-PICO-V3 chip package IO_MUX_GPIO21_REG, IO_MUX_GPIO22_REG, IO_MUX_GPIO23_REG, diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index ae88415cb4..03597fe989 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -116,8 +116,8 @@ // set pullup/down/capability via RTC register. On ESP32-S2, Digital IOs have their own registers to // control pullup/down/capability, independent with RTC registers. -// 0~39 except from 20, 24, 28~31 are valid -#define SOC_GPIO_VALID_GPIO_MASK (0xFFFFFFFFFFULL & ~(0ULL | BIT20 | BIT24 | BIT28 | BIT29 | BIT30 | BIT31)) +// 0~39 except from 24, 28~31 are valid +#define SOC_GPIO_VALID_GPIO_MASK (0xFFFFFFFFFFULL & ~(0ULL | BIT24 | BIT28 | BIT29 | BIT30 | BIT31)) // GPIO >= 34 are input only #define SOC_GPIO_VALID_OUTPUT_GPIO_MASK (SOC_GPIO_VALID_GPIO_MASK & ~(0ULL | BIT34 | BIT35 | BIT36 | BIT37 | BIT38 | BIT39)) diff --git a/docs/en/api-reference/peripherals/gpio.rst b/docs/en/api-reference/peripherals/gpio.rst index 9f92f8d5be..93a5e05523 100644 --- a/docs/en/api-reference/peripherals/gpio.rst +++ b/docs/en/api-reference/peripherals/gpio.rst @@ -118,6 +118,11 @@ Overview - - - + + * - GPIO20 + - + - + - This pin is only available on ESP32-PICO-V3 chip package * - GPIO21 - From 8b7365ec008af12fa594bf06e77a6b8bd4398a6d Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 17 Aug 2021 14:54:23 +0200 Subject: [PATCH 012/310] Docs: Add chip support matrix to the main README --- README.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 10027f474b..903560c080 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,21 @@ * [中文版](./README_CN.md) -ESP-IDF is the development framework for Espressif SoCs (released after 2016[1](#fn1)) provided for Windows, Linux and macOS. +ESP-IDF is the development framework for Espressif SoCs supported on Windows, Linux and macOS. + +# ESP-IDF Release and SoC Compatibility + +The following table shows ESP-IDF support of Espressif SoCs where :yellow_circle: and :green_circle: denote preview status and support, respectively. In preview status the build is not yet enabled and some crucial parts could be missing (like documentation, datasheet). Please use an ESP-IDF release where the desired SoC is already supported. + +|Chip | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | +|:----------- |:-------------: | :-------------:| :-------------:| :-------------:| :-------------:| :-------------:|:---------------------------------------------------------- | +|ESP32 | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | | +|ESP32-S2 | | | | :green_circle: | :green_circle: | :green_circle: | | +|ESP32-C3 | | | | | :green_circle: | :green_circle: | | +|ESP32-S3 | | | | | :yellow_circle:| :green_circle: | [Announcement](https://www.espressif.com/en/news/ESP32_S3) | +|ESP32-H2 | | | | | | :yellow_circle:| [Announcement](https://www.espressif.com/en/news/ESP32_H2) | + +Espressif SoCs released before 2016 (ESP8266 and ESP8285) are supported by [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead. # Developing With ESP-IDF @@ -99,8 +113,3 @@ This can be combined with other targets, ie `idf.py -p PORT erase_flash flash` w * [Check the Issues section on github](https://github.com/espressif/esp-idf/issues) if you find a bug or have a feature request. Please check existing Issues before opening a new one. * If you're interested in contributing to ESP-IDF, please check the [Contributions Guide](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html). - - -________ - -1: ESP8266 and ESP8285 are not supported in ESP-IDF. See [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead. \ No newline at end of file From b0757dfcfaa40ca789bbac5ae28b9b8120dd0cb2 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 19 Aug 2021 21:57:17 +0800 Subject: [PATCH 013/310] light sleep: separate sleep gpio function --- components/esp_hw_support/CMakeLists.txt | 1 + .../include/esp_private/sleep_gpio.h | 46 ++++++++++++ components/esp_hw_support/sleep_gpio.c | 72 +++++++++++++++++++ components/esp_hw_support/sleep_modes.c | 49 +------------ components/esp_pm/linker.lf | 2 + 5 files changed, 122 insertions(+), 48 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/sleep_gpio.h create mode 100644 components/esp_hw_support/sleep_gpio.c diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 40dcb22947..58c8726ecd 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -15,6 +15,7 @@ if(NOT BOOTLOADER_BUILD) "intr_alloc.c" "mac_addr.c" "sleep_modes.c" + "sleep_gpio.c" "regi2c_ctrl.c") list(APPEND requires esp_ipc) else() diff --git a/components/esp_hw_support/include/esp_private/sleep_gpio.h b/components/esp_hw_support/include/esp_private/sleep_gpio.h new file mode 100644 index 0000000000..abab21871a --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_gpio.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_gpio.h + * + * This file contains declarations of GPIO related functions in light sleep mode. + */ + +#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + +/** + * @brief Save GPIO pull-up and pull-down configuration information in the wake-up state + * + * In light sleep mode, the pull-up and pull-down resistors of GPIO will cause + * leakage current when the system sleeps. In order to reduce the power + * consumption of system sleep, it needs to save the configuration information + * of all GPIO pull-up and pull-down resistors and disable the pull-up and + * pull-down resistors of GPIO before the system enters sleep. + */ +void gpio_sleep_mode_config_apply(void); + +/** + * @brief Restore GPIO pull-up and pull-down configuration information in the wake-up state + * + * In light sleep mode, after the system wakes up, it needs to restore all GPIO + * pull-up and pull-down configurations before the last sleep. + */ +void gpio_sleep_mode_config_unapply(void); + +#endif // SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c new file mode 100644 index 0000000000..776ef053d8 --- /dev/null +++ b/components/esp_hw_support/sleep_gpio.c @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "soc/soc_caps.h" + +#include "sdkconfig.h" + +#include "driver/gpio.h" +#include "esp_private/gpio.h" +#include "esp_private/sleep_gpio.h" + +static const char *TAG = "sleep"; + +#if SOC_GPIO_SUPPORT_SLP_SWITCH + +#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL +void gpio_sleep_mode_config_apply(void) +{ + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + gpio_sleep_pupd_config_apply(gpio_num); + } + } +} + +IRAM_ATTR void gpio_sleep_mode_config_unapply(void) +{ + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + gpio_sleep_pupd_config_unapply(gpio_num); + } + } +} +#endif + +void esp_sleep_config_gpio_isolate(void) +{ + ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state"); + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE); + gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING); + } + } +} + +void esp_sleep_enable_gpio_switch(bool enable) +{ + ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + if (enable) { + gpio_sleep_sel_en(gpio_num); + } else { + gpio_sleep_sel_dis(gpio_num); + } + } + } +} + +#endif // SOC_GPIO_SUPPORT_SLP_SWITCH diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ee68b21f0c..b3b98bc9ab 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -49,6 +49,7 @@ #include "esp32/rom/rtc.h" #include "esp32/clk.h" #include "esp_private/gpio.h" +#include "esp_private/sleep_gpio.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/clk.h" #include "esp32s2/rom/cache.h" @@ -392,54 +393,6 @@ esp_err_t esp_sleep_cpu_pd_low_init(bool enable) } #endif // SOC_PM_SUPPORT_CPU_PD -#if SOC_GPIO_SUPPORT_SLP_SWITCH -#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL -static inline void gpio_sleep_mode_config_apply(void) -{ - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - gpio_sleep_pupd_config_apply(gpio_num); - } - } -} - -static inline void gpio_sleep_mode_config_unapply(void) -{ - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - gpio_sleep_pupd_config_unapply(gpio_num); - } - } -} -#endif - -void esp_sleep_config_gpio_isolate(void) -{ - ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state"); - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE); - gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING); - } - } -} - -void esp_sleep_enable_gpio_switch(bool enable) -{ - ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - if (enable) { - gpio_sleep_sel_en(gpio_num); - } else { - gpio_sleep_sel_dis(gpio_num); - } - } - } -} -#endif // SOC_GPIO_SUPPORT_SLP_SWITCH - - static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { // Stop UART output so that output is not lost due to APB frequency change. diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index 2abbeab151..3f4426b229 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -19,6 +19,8 @@ entries: esp_clk:esp_clk_slowclk_cal_set (noflash) esp_clk:esp_clk_slowclk_cal_get (noflash) esp_clk:esp_rtc_get_time_us (noflash) + if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y: + sleep_gpio:gpio_sleep_mode_config_apply (noflash) [mapping:esp_system_pm] archive: libesp_system.a From 90a0a83c0fdf8272e3477266bda5ee0f0183def6 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 20 Aug 2021 10:15:48 +0800 Subject: [PATCH 014/310] light sleep: separate sleep wifi/bt mac bb function --- components/esp_hw_support/CMakeLists.txt | 1 + .../include/esp_private/sleep_mac_bb.h | 43 +++++++ components/esp_hw_support/sleep_mac_bb.c | 108 ++++++++++++++++++ components/esp_hw_support/sleep_modes.c | 91 +-------------- 4 files changed, 154 insertions(+), 89 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/sleep_mac_bb.h create mode 100644 components/esp_hw_support/sleep_mac_bb.c diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 58c8726ecd..077e6f6191 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -16,6 +16,7 @@ if(NOT BOOTLOADER_BUILD) "mac_addr.c" "sleep_modes.c" "sleep_gpio.c" + "sleep_mac_bb.c" "regi2c_ctrl.c") list(APPEND requires esp_ipc) else() diff --git a/components/esp_hw_support/include/esp_private/sleep_mac_bb.h b/components/esp_hw_support/include/esp_private/sleep_mac_bb.h new file mode 100644 index 0000000000..6b4019639d --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_mac_bb.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_mac_bb.h + * + * This file contains declarations of MAC and baseband power consumption related functions in light sleep mode. + */ + +#if CONFIG_MAC_BB_PD + +/** + * @brief A callback function completes MAC and baseband power down operation + * + * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband + * power down and backup register configuration information operations. + */ +void mac_bb_power_down_cb_execute(void); + +/** + * @brief A callback function completes MAC and baseband power up operation + * + * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband + * power up and restore register configuration information operations. + */ +void mac_bb_power_up_cb_execute(void); + +#endif // CONFIG_MAC_BB_PD + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/sleep_mac_bb.c b/components/esp_hw_support/sleep_mac_bb.c new file mode 100644 index 0000000000..4c53852070 --- /dev/null +++ b/components/esp_hw_support/sleep_mac_bb.c @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "soc/soc_caps.h" +#include "esp_private/sleep_mac_bb.h" +#include "sdkconfig.h" + +#if CONFIG_MAC_BB_PD + +#define MAC_BB_POWER_DOWN_CB_NO (2) +#define MAC_BB_POWER_UP_CB_NO (2) + +static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO]; +static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO]; + +esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) +{ + int index = MAC_BB_POWER_DOWN_CB_NO; + for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_down_cb[i] == cb) { + return ESP_OK; + } + + if (s_mac_bb_power_down_cb[i] == NULL) { + index = i; + } + } + + if (index < MAC_BB_POWER_DOWN_CB_NO) { + s_mac_bb_power_down_cb[index] = cb; + return ESP_OK; + } + + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) +{ + for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_down_cb[i] == cb) { + s_mac_bb_power_down_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void IRAM_ATTR mac_bb_power_down_cb_execute(void) +{ + for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { + if (s_mac_bb_power_down_cb[i]) { + s_mac_bb_power_down_cb[i](); + } + } +} + +esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) +{ + int index = MAC_BB_POWER_UP_CB_NO; + for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_up_cb[i] == cb) { + return ESP_OK; + } + + if (s_mac_bb_power_up_cb[i] == NULL) { + index = i; + } + } + + if (index < MAC_BB_POWER_UP_CB_NO) { + s_mac_bb_power_up_cb[index] = cb; + return ESP_OK; + } + + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) +{ + for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_up_cb[i] == cb) { + s_mac_bb_power_up_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void IRAM_ATTR mac_bb_power_up_cb_execute(void) +{ + for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { + if (s_mac_bb_power_up_cb[i]) { + s_mac_bb_power_up_cb[i](); + } + } +} + +#endif ///CONFIG_MAC_BB_PD diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b3b98bc9ab..be331d05e1 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -61,12 +61,14 @@ #include "esp32s3/rom/cache.h" #include "esp32s3/rom/rtc.h" #include "soc/extmem_reg.h" +#include "esp_private/sleep_mac_bb.h" #elif CONFIG_IDF_TARGET_ESP32C3 #include "esp32c3/clk.h" #include "esp32c3/rom/cache.h" #include "esp32c3/rom/rtc.h" #include "soc/extmem_reg.h" #include "esp_heap_caps.h" +#include "esp_private/sleep_mac_bb.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/clk.h" #include "esp32h2/rom/cache.h" @@ -184,95 +186,6 @@ static void touch_wakeup_prepare(void); static void esp_deep_sleep_wakeup_prepare(void); #endif -#if CONFIG_MAC_BB_PD -#define MAC_BB_POWER_DOWN_CB_NO 2 -#define MAC_BB_POWER_UP_CB_NO 2 -static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO]; -static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO]; - -esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) -{ - int index = MAC_BB_POWER_DOWN_CB_NO; - for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_down_cb[i] == cb) { - return ESP_OK; - } - - if (s_mac_bb_power_down_cb[i] == NULL) { - index = i; - } - } - - if (index < MAC_BB_POWER_DOWN_CB_NO) { - s_mac_bb_power_down_cb[index] = cb; - return ESP_OK; - } - - return ESP_ERR_NO_MEM; -} - -esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) -{ - for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_down_cb[i] == cb) { - s_mac_bb_power_down_cb[i] = NULL; - return ESP_OK; - } - } - return ESP_ERR_INVALID_STATE; -} - -static IRAM_ATTR void mac_bb_power_down_cb_execute(void) -{ - for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { - if (s_mac_bb_power_down_cb[i]) { - s_mac_bb_power_down_cb[i](); - } - } -} - -esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) -{ - int index = MAC_BB_POWER_UP_CB_NO; - for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_up_cb[i] == cb) { - return ESP_OK; - } - - if (s_mac_bb_power_up_cb[i] == NULL) { - index = i; - } - } - - if (index < MAC_BB_POWER_UP_CB_NO) { - s_mac_bb_power_up_cb[index] = cb; - return ESP_OK; - } - - return ESP_ERR_NO_MEM; -} - -esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) -{ - for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_up_cb[i] == cb) { - s_mac_bb_power_up_cb[i] = NULL; - return ESP_OK; - } - } - return ESP_ERR_INVALID_STATE; -} - -static IRAM_ATTR void mac_bb_power_up_cb_execute(void) -{ - for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { - if (s_mac_bb_power_up_cb[i]) { - s_mac_bb_power_up_cb[i](); - } - } -} -#endif ///CONFIG_MAC_BB_PD - /* Wake from deep sleep stub See esp_deepsleep.h esp_wake_deep_sleep() comments for details. */ From a8667790708c1cce7d0a260b3f7fcc32d77135d7 Mon Sep 17 00:00:00 2001 From: Martin Vychodil Date: Fri, 20 Aug 2021 13:47:25 +0200 Subject: [PATCH 015/310] Examples/Storage: sufficient timeout for SD formatting Too short timeouts often cause useless failures on large-capacity SDs (16GB+) Fixed by adding 60 sec timeout on new "Filesystem mounted" checkpoint JIRA IDF-3741 --- examples/storage/sd_card/sdmmc/main/sd_card_example_main.c | 2 ++ examples/storage/sd_card/sdmmc/sd_card_example_test.py | 3 +++ examples/storage/sd_card/sdspi/main/sd_card_example_main.c | 2 ++ examples/storage/sd_card/sdspi/sd_card_example_test.py | 3 +++ 4 files changed, 10 insertions(+) diff --git a/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c b/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c index 6146b16538..3260324283 100644 --- a/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c +++ b/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c @@ -71,6 +71,7 @@ void app_main(void) // connected on the bus. This is for debug / example purpose only. slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP; + ESP_LOGI(TAG, "Mounting filesystem"); ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card); if (ret != ESP_OK) { @@ -83,6 +84,7 @@ void app_main(void) } return; } + ESP_LOGI(TAG, "Filesystem mounted"); // Card has been initialized, print its properties sdmmc_card_print_info(stdout, card); diff --git a/examples/storage/sd_card/sdmmc/sd_card_example_test.py b/examples/storage/sd_card/sdmmc/sd_card_example_test.py index 3e7cc28530..18a9516f14 100644 --- a/examples/storage/sd_card/sdmmc/sd_card_example_test.py +++ b/examples/storage/sd_card/sdmmc/sd_card_example_test.py @@ -12,6 +12,9 @@ def test_examples_sd_card(env, extra_data): # type: (ttfw_idf.Env.Env, None ) - dut.expect('example: Initializing SD card', timeout=20) dut.expect('example: Using SDMMC peripheral', timeout=10) + # Provide enough time for possible SD card formatting + dut.expect('Filesystem mounted', timeout=60) + # These lines are matched separately because of ASCII color codes in the output name = dut.expect(re.compile(r'Name: (\w+)'), timeout=10)[0] _type = dut.expect(re.compile(r'Type: (\S+)'), timeout=10)[0] diff --git a/examples/storage/sd_card/sdspi/main/sd_card_example_main.c b/examples/storage/sd_card/sdspi/main/sd_card_example_main.c index 243370c644..38f34c12a6 100644 --- a/examples/storage/sd_card/sdspi/main/sd_card_example_main.c +++ b/examples/storage/sd_card/sdspi/main/sd_card_example_main.c @@ -88,6 +88,7 @@ void app_main(void) slot_config.gpio_cs = PIN_NUM_CS; slot_config.host_id = host.slot; + ESP_LOGI(TAG, "Mounting filesystem"); ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card); if (ret != ESP_OK) { @@ -100,6 +101,7 @@ void app_main(void) } return; } + ESP_LOGI(TAG, "Filesystem mounted"); // Card has been initialized, print its properties sdmmc_card_print_info(stdout, card); diff --git a/examples/storage/sd_card/sdspi/sd_card_example_test.py b/examples/storage/sd_card/sdspi/sd_card_example_test.py index 0438eb105e..72fe104164 100644 --- a/examples/storage/sd_card/sdspi/sd_card_example_test.py +++ b/examples/storage/sd_card/sdspi/sd_card_example_test.py @@ -12,6 +12,9 @@ def test_examples_sd_card(env, extra_data): # type: (ttfw_idf.Env.Env, None ) - dut.expect('example: Initializing SD card', timeout=20) dut.expect('example: Using SPI peripheral', timeout=20) + # Provide enough time for possible SD card formatting + dut.expect('Filesystem mounted', timeout=60) + # These lines are matched separately because of ASCII color codes in the output name = dut.expect(re.compile(r'Name: (\w+)'), timeout=20)[0] _type = dut.expect(re.compile(r'Type: (\S+)'), timeout=20)[0] From 03baf4f8be43ab576308fabc4069dec716b228db Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Mon, 23 Aug 2021 12:19:32 +0500 Subject: [PATCH 016/310] espefuse: Fixes execute_scripts, it should call BURN once at the end --- components/esptool_py/esptool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esptool_py/esptool b/components/esptool_py/esptool index 9876dfe583..2583017317 160000 --- a/components/esptool_py/esptool +++ b/components/esptool_py/esptool @@ -1 +1 @@ -Subproject commit 9876dfe58353f01c873e1543dd0654c5b04314a4 +Subproject commit 258301731780493365bb249553ae7855a3e753ea From 3c6efbe5a59d9513a44632b9d1cacb5c8d2b17bc Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 23 Aug 2021 09:20:12 +0200 Subject: [PATCH 017/310] wifi/netif: Fix wifi_ap_handlers comments to relate to AP --- components/esp_wifi/include/esp_wifi_default.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_wifi/include/esp_wifi_default.h b/components/esp_wifi/include/esp_wifi_default.h index 958977bf25..908ea2c113 100644 --- a/components/esp_wifi/include/esp_wifi_default.h +++ b/components/esp_wifi/include/esp_wifi_default.h @@ -50,7 +50,7 @@ esp_err_t esp_netif_attach_wifi_ap(esp_netif_t *esp_netif); esp_err_t esp_wifi_set_default_wifi_sta_handlers(void); /** - * @brief Sets default wifi event handlers for STA interface + * @brief Sets default wifi event handlers for AP interface * * @return * - ESP_OK on success, error returned from esp_event_handler_register if failed From 307bbf0b67bda451c1d1767d343bc3dc1c03c947 Mon Sep 17 00:00:00 2001 From: mjcross Date: Fri, 6 Aug 2021 11:48:28 +0100 Subject: [PATCH 018/310] Add hint about sdkconfig.ci in IDF examples Individual developers may not know about CI and may be confused by the sdkconfig.ci files in the examples. Signed-off-by: Laukik Hase Closes https://github.com/espressif/esp-idf/pull/7379 --- docs/en/api-guides/build-system.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index 9885bf3e3b..8bc616d65e 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -1019,6 +1019,8 @@ For example projects or other projects where you don't want to specify a full sd To override the name of this file or to specify multiple files, set the ``SDKCONFIG_DEFAULTS`` environment variable or set ``SDKCONFIG_DEFAULTS`` in top-level CMakeLists.txt. If specifying multiple files, use semicolon as the list separator. File names not specified as full paths are resolved relative to current project. +Some of the IDF examples include a ``sdkconfig.ci`` file. This is part of the continuous integration (CI) test framework and is ignored by the normal build process. + Target-dependent sdkconfig defaults ----------------------------------- From 124169a7dde62b3212aaed70b459fb81c3121339 Mon Sep 17 00:00:00 2001 From: liaowenhao Date: Fri, 19 Mar 2021 19:53:15 +0800 Subject: [PATCH 019/310] bugfix acl doesn't disconnect when hfp_client disconnect --- components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c index dcaf665dbc..4158f015f6 100644 --- a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c +++ b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c @@ -214,7 +214,7 @@ const UINT8 bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = { /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, - /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CONN_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, #if (BTM_SCO_HCI_INCLUDED == TRUE ) /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, From 15fc449793528481f3448f2c1fc63abc25484b50 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 20 Aug 2021 15:15:58 +0800 Subject: [PATCH 020/310] light sleep: separate sleep retention function --- components/esp_hw_support/CMakeLists.txt | 3 + components/esp_hw_support/component.mk | 10 ++ .../include/esp_private/sleep_retention.h | 55 +++++++++++ components/esp_hw_support/include/esp_sleep.h | 2 + components/esp_hw_support/sleep_modes.c | 94 ++++++++----------- components/esp_hw_support/sleep_retention.c | 81 ++++++++++++++++ components/esp_pm/linker.lf | 3 + 7 files changed, 191 insertions(+), 57 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/sleep_retention.h create mode 100644 components/esp_hw_support/sleep_retention.c diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 077e6f6191..2846fab097 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -18,6 +18,9 @@ if(NOT BOOTLOADER_BUILD) "sleep_gpio.c" "sleep_mac_bb.c" "regi2c_ctrl.c") + if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2) + list(APPEND srcs "sleep_retention.c") + endif() list(APPEND requires esp_ipc) else() # Requires "_esp_error_check_failed()" function diff --git a/components/esp_hw_support/component.mk b/components/esp_hw_support/component.mk index 5e75d5e0e3..f0f472034f 100644 --- a/components/esp_hw_support/component.mk +++ b/components/esp_hw_support/component.mk @@ -6,6 +6,9 @@ ifdef IS_BOOTLOADER_BUILD COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \ intr_alloc.o \ sleep_modes.o \ + sleep_gpio.o \ + sleep_mac_bb.o \ + sleep_retention.o \ esp_async_memcpy.o \ mac_addr.o \ regi2c_ctrl.o \ @@ -16,4 +19,11 @@ COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \ port/$(IDF_TARGET)/spiram_psram.o endif +ifdef CONFIG_IDF_TARGET_ESP32 +COMPONENT_OBJEXCLUDE += sleep_retention.o +endif +ifdef CONFIG_IDF_TARGET_ESP32S2 +COMPONENT_OBJEXCLUDE += sleep_retention.o +endif + COMPONENT_OBJEXCLUDE += esp_async_memcpy.o diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_retention.h new file mode 100644 index 0000000000..001e559c0c --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_retention.h + * + * This file contains declarations of memory retention related functions in light sleeo mode. + */ + +#if SOC_PM_SUPPORT_CPU_PD + +/** + * @brief Whether to allow the cpu power domain to be powered off. + * + * In light sleep mode, only when the system can provide enough memory + * for cpu retention, the cpu power domain can be powered off. + */ +bool cpu_domain_pd_allowed(void); + +#endif + +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + +/** + * @brief Enable memory retention of some modules. + * + * In light sleep mode, before the system goes to sleep, enable the memory + * retention of modules such as CPU and I/D-cache tag memory. + */ +void sleep_enable_memory_retention(void); + +/** + * @brief Disable memory retention of some modules. + * + * In light sleep mode, after the system exits sleep, disable the memory + * retention of moudles such as CPU and I/D-cache tag memory. + */ +void sleep_disable_memory_retention(void); + +#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 6a0b9d7d21..0ae44b3071 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -41,7 +41,9 @@ typedef enum { ESP_PD_DOMAIN_RTC_SLOW_MEM, //!< RTC slow memory ESP_PD_DOMAIN_RTC_FAST_MEM, //!< RTC fast memory ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator +#if SOC_PM_SUPPORT_CPU_PD ESP_PD_DOMAIN_CPU, //!< CPU core +#endif ESP_PD_DOMAIN_VDDSDIO, //!< VDD_SDIO ESP_PD_DOMAIN_MAX //!< Number of domains } esp_sleep_pd_domain_t; diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index be331d05e1..d7f6d86a01 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -43,6 +43,7 @@ #include "esp_rom_uart.h" #include "esp_rom_sys.h" #include "brownout.h" +#include "esp_private/sleep_retention.h" #ifdef CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/cache.h" @@ -67,14 +68,12 @@ #include "esp32c3/rom/cache.h" #include "esp32c3/rom/rtc.h" #include "soc/extmem_reg.h" -#include "esp_heap_caps.h" #include "esp_private/sleep_mac_bb.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/clk.h" #include "esp32h2/rom/cache.h" #include "esp32h2/rom/rtc.h" #include "soc/extmem_reg.h" -#include "esp_heap_caps.h" #endif // If light sleep time is less than that, don't power down flash @@ -151,13 +150,16 @@ typedef struct { uint32_t sleep_time_overhead_out; uint32_t rtc_clk_cal_period; uint64_t rtc_ticks_at_sleep_start; -#if SOC_PM_SUPPORT_CPU_PD - void *cpu_pd_mem; -#endif } sleep_config_t; static sleep_config_t s_config = { - .pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO }, + .pd_options = { + ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, +#if SOC_PM_SUPPORT_CPU_PD + ESP_PD_OPTION_AUTO, +#endif + ESP_PD_OPTION_AUTO + }, .ccount_ticks_record = 0, .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, .wakeup_triggers = 0 @@ -278,33 +280,33 @@ static void IRAM_ATTR resume_uarts(void) } } -inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu); - -#if SOC_PM_SUPPORT_CPU_PD -esp_err_t esp_sleep_cpu_pd_low_init(bool enable) +inline static void IRAM_ATTR misc_modules_sleep_prepare(void) { - if (enable) { - if (s_config.cpu_pd_mem == NULL) { - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, - SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, - MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT); - if (buf) { - memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); - s_config.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, - buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); - } else { - return ESP_ERR_NO_MEM; - } - } - } else { - if (s_config.cpu_pd_mem) { - heap_caps_free(s_config.cpu_pd_mem); - s_config.cpu_pd_mem = NULL; - } - } - return ESP_OK; +#if CONFIG_MAC_BB_PD + mac_bb_power_down_cb_execute(); +#endif +#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + gpio_sleep_mode_config_apply(); +#endif +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + sleep_enable_memory_retention(); +#endif } -#endif // SOC_PM_SUPPORT_CPU_PD + +inline static void IRAM_ATTR misc_modules_wake_prepare(void) +{ +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + sleep_disable_memory_retention(); +#endif +#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + gpio_sleep_mode_config_unapply(); +#endif +#if CONFIG_MAC_BB_PD + mac_bb_power_up_cb_execute(); +#endif +} + +inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu); static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { @@ -333,10 +335,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) rtc_clk_cpu_freq_get_config(&cpu_freq_config); rtc_clk_cpu_freq_set_xtal(); -#if CONFIG_MAC_BB_PD - mac_bb_power_down_cb_execute(); -#endif - #if SOC_PM_SUPPORT_EXT_WAKEUP // Configure pins for external wakeup if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { @@ -358,11 +356,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) { rtc_hal_ulp_wakeup_enable(); } -#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL - gpio_sleep_mode_config_apply(); -#endif #endif + misc_modules_sleep_prepare(); + #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (deep_sleep) { if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) { @@ -443,17 +440,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) s_config.ccount_ticks_record = cpu_ll_get_cycle_count(); } -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_disable_cpu_retention(); -#endif + misc_modules_wake_prepare(); -#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL - gpio_sleep_mode_config_unapply(); -#endif - -#if CONFIG_MAC_BB_PD - mac_bb_power_up_cb_execute(); -#endif // re-enable UART output resume_uarts(); @@ -637,10 +625,6 @@ esp_err_t esp_light_sleep_start(void) periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in); -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_enable_cpu_retention(s_config.cpu_pd_mem); -#endif - rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // Safety net: enable WDT in case exit from light sleep fails @@ -1176,11 +1160,7 @@ static uint32_t get_power_down_flags(void) } #if SOC_PM_SUPPORT_CPU_PD - if (s_config.cpu_pd_mem == NULL) { - s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; - } -#else - if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) { + if (!cpu_domain_pd_allowed()) { s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; } #endif diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c new file mode 100644 index 0000000000..f915f3f107 --- /dev/null +++ b/components/esp_hw_support/sleep_retention.c @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "soc/soc_caps.h" +#include "hal/rtc_hal.h" +#include "esp_private/sleep_retention.h" +#include "sdkconfig.h" + +/** + * Internal structure which holds all requested light sleep memory retention parameters + */ +typedef struct { + rtc_cntl_sleep_retent_t retent; +} sleep_retention_t; + +static DRAM_ATTR sleep_retention_t s_retention; + +#if SOC_PM_SUPPORT_CPU_PD + +#define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT) + +esp_err_t esp_sleep_cpu_pd_low_init(bool enable) +{ + if (enable) { + if (s_retention.retent.cpu_pd_mem == NULL) { + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, + SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, + CPU_PD_MEM_TYPE_CAPS); + if (buf) { + memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); + s_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); + } else { + return ESP_ERR_NO_MEM; + } + } + } else { + if (s_retention.retent.cpu_pd_mem) { + heap_caps_free(s_retention.retent.cpu_pd_mem); + s_retention.retent.cpu_pd_mem = NULL; + } + } + return ESP_OK; +} + +bool cpu_domain_pd_allowed(void) +{ + return (s_retention.retent.cpu_pd_mem != NULL); +} + +#endif // SOC_PM_SUPPORT_CPU_PD + +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + +void sleep_enable_memory_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD + rtc_cntl_hal_enable_cpu_retention(&s_retention.retent); +#endif +} + +void IRAM_ATTR sleep_disable_memory_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD + rtc_cntl_hal_disable_cpu_retention(&s_retention.retent); +#endif +} + +#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index 3f4426b229..a8f3a9e6ab 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -21,6 +21,9 @@ entries: esp_clk:esp_rtc_get_time_us (noflash) if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y: sleep_gpio:gpio_sleep_mode_config_apply (noflash) + if IDF_TARGET_ESP32 = n && IDF_TARGET_ESP32S2 = n: + sleep_retention:sleep_enable_memory_retention (noflash) + sleep_retention:cpu_domain_pd_allowed (noflash) [mapping:esp_system_pm] archive: libesp_system.a From dd3d27a03c6c0593be9d33e3951e6ef2bd2a62f3 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Tue, 24 Aug 2021 10:22:53 +0530 Subject: [PATCH 021/310] Added Feature: Example for Captive Portal system. Feature note: Sets up a simple DNS server that answers all questions with the ESP softAP's IP as well as a HTTP server which redirects all requests to a captive portal welcoming page. Triggers captive portal detection (log-in screen popup) for iOS, Android and Windows. Includes example test for testing DNS redirect and HTTP redirect. Closes https://github.com/espressif/esp-idf/issues/7099 Closes https://github.com/espressif/esp-idf/issues/4075 --- .../http_server/captive_portal/CMakeLists.txt | 6 + .../http_server/captive_portal/Makefile | 8 + .../http_server/captive_portal/README.md | 96 +++++++ .../captive_portal/example_test.py | 142 ++++++++++ .../captive_portal/main/CMakeLists.txt | 3 + .../captive_portal/main/Kconfig.projbuild | 20 ++ .../captive_portal/main/component.mk | 6 + .../captive_portal/main/dns_server.c | 247 ++++++++++++++++++ .../captive_portal/main/include/dns_server.h | 26 ++ .../http_server/captive_portal/main/main.c | 163 ++++++++++++ .../http_server/captive_portal/main/root.html | 15 ++ .../captive_portal/sdkconfig.defaults | 2 + 12 files changed, 734 insertions(+) create mode 100644 examples/protocols/http_server/captive_portal/CMakeLists.txt create mode 100644 examples/protocols/http_server/captive_portal/Makefile create mode 100644 examples/protocols/http_server/captive_portal/README.md create mode 100644 examples/protocols/http_server/captive_portal/example_test.py create mode 100644 examples/protocols/http_server/captive_portal/main/CMakeLists.txt create mode 100644 examples/protocols/http_server/captive_portal/main/Kconfig.projbuild create mode 100644 examples/protocols/http_server/captive_portal/main/component.mk create mode 100644 examples/protocols/http_server/captive_portal/main/dns_server.c create mode 100644 examples/protocols/http_server/captive_portal/main/include/dns_server.h create mode 100644 examples/protocols/http_server/captive_portal/main/main.c create mode 100644 examples/protocols/http_server/captive_portal/main/root.html create mode 100644 examples/protocols/http_server/captive_portal/sdkconfig.defaults diff --git a/examples/protocols/http_server/captive_portal/CMakeLists.txt b/examples/protocols/http_server/captive_portal/CMakeLists.txt new file mode 100644 index 0000000000..61f0006df4 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following 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(captive_portal) diff --git a/examples/protocols/http_server/captive_portal/Makefile b/examples/protocols/http_server/captive_portal/Makefile new file mode 100644 index 0000000000..8b1eca9313 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := captive_portal + +include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/http_server/captive_portal/README.md b/examples/protocols/http_server/captive_portal/README.md new file mode 100644 index 0000000000..052e3cafe8 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/README.md @@ -0,0 +1,96 @@ +# Captive Portal Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates a simple captive portal that will redirect all DNS IP questions to point to the softAP and redirect all HTTP requests to the captive portal root page. Triggers captive portal (sign in) pop up on Android, iOS and Windows. Note that the example will not redirect HTTPS requests. + +## How to Use Example + +Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. + +### Hardware Required + +* A development board with ESP32/ESP32-S2/ESP32-C3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +* A USB cable for power supply and programming +* WiFi interface + +### Configure the project + +Open the project configuration menu (`idf.py menuconfig`). + +In the `Example Configuration` menu: + +* Set the Wi-Fi configuration. + * Set `SoftAP SSID` + * Set `SoftAP Password` + * Set `Maximal STA connections` + +When using the legacy GNU Make build system, set `Default serial port` under `Serial flasher config`. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +``` +I (733) example: Set up softAP with IP: 192.168.4.1 +I (743) example: wifi_init_softap finished. SSID:'esp32_ssid' password:'esp32_pwd' +I (753) example: Starting server on port: '80' +I (753) example: Registering URI handlers +I (763) example_dns_redirect_server: Socket created +I (763) example_dns_redirect_server: Socket bound, port 53 +I (773) example_dns_redirect_server: Waiting for data +I (1873) wifi:new:<1,1>, old:<1,1>, ap:<1,1>, sta:<255,255>, prof:1 +I (1873) wifi:station: e8:84:a5:18:8f:80 join, AID=1, bgn, 40U +I (2203) example: station e8:84:a5:18:8f:80 join, AID=1 +I (2833) example_dns_redirect_server: Received 50 bytes from 192.168.4.2 | DNS reply with len: 66 +I (2843) example_dns_redirect_server: Waiting for data +I (3043) example_dns_redirect_server: Received 39 bytes from 192.168.4.2 | DNS reply with len: 55 +I (3043) example_dns_redirect_server: Waiting for data +I (3043) example_dns_redirect_server: Received 42 bytes from 192.168.4.2 | DNS reply with len: 58 +I (3053) example_dns_redirect_server: Waiting for data +W (3203) wifi:idx:4 (ifx:1, e8:84:a5:18:8f:80), tid:0, ssn:9, winSize:64 +I (3533) example: Redirecting to root +I (5693) example_dns_redirect_server: Received 37 bytes from 192.168.4.2 | DNS reply with len: 53 +I (5693) example_dns_redirect_server: Waiting for data +I (5783) example_dns_redirect_server: Received 46 bytes from 192.168.4.2 | DNS reply with len: 62 +I (5783) example_dns_redirect_server: Waiting for data +I (6303) example_dns_redirect_server: Received 41 bytes from 192.168.4.2 | DNS reply with len: 57 +I (6303) example_dns_redirect_server: Waiting for data +I (6303) example_dns_redirect_server: Received 41 bytes from 192.168.4.2 | DNS reply with len: 57 +I (6313) example_dns_redirect_server: Waiting for data +I (6593) example: Redirecting to root +I (9623) example: Redirecting to root +I (12913) example: Redirecting to root +I (13263) example_dns_redirect_server: Received 34 bytes from 192.168.4.2 | DNS reply with len: 50 +I (13273) example_dns_redirect_server: Waiting for data +I (13273) example_dns_redirect_server: Received 34 bytes from 192.168.4.2 | DNS reply with len: 50 +I (13283) example_dns_redirect_server: Waiting for data +I (16303) example_dns_redirect_server: Received 32 bytes from 192.168.4.2 | DNS reply with len: 48 +I (16303) example_dns_redirect_server: Waiting for data +I (18073) example: Redirecting to root +I (18273) example_dns_redirect_server: Received 34 bytes from 192.168.4.2 | DNS reply with len: 50 +I (18273) example_dns_redirect_server: Waiting for data +I (18273) example_dns_redirect_server: Received 34 bytes from 192.168.4.2 | DNS reply with len: 50 +I (18283) example_dns_redirect_server: Waiting for data +I (20683) example_dns_redirect_server: Received 42 bytes from 192.168.4.2 | DNS reply with len: 58 +I (20683) example_dns_redirect_server: Waiting for data +I (20753) example: Redirecting to root +I (21323) example: Redirecting to root +I (22683) example_dns_redirect_server: Received 48 bytes from 192.168.4.2 | DNS reply with len: 64 +I (22693) example_dns_redirect_server: Waiting for data +I (23443) example_dns_redirect_server: Received 48 bytes from 192.168.4.2 | DNS reply with len: 64 +I (23453) example_dns_redirect_server: Waiting for data +I (23473) example: Serve root +I (23503) example_dns_redirect_server: Received 48 bytes from 192.168.4.2 | DNS reply with len: 64 +I (23513) example_dns_redirect_server: Waiting for data +``` diff --git a/examples/protocols/http_server/captive_portal/example_test.py b/examples/protocols/http_server/captive_portal/example_test.py new file mode 100644 index 0000000000..25a3b816d1 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/example_test.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# +# Copyright 2021 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function + +import http.client +import os +import re +import socket +import sys + +import tiny_test_fw +import ttfw_idf +from tiny_test_fw import Utility + +try: + import wifi_tools +except ImportError: + wifi_tools_path = str(os.getenv('IDF_PATH')) + '/examples/provisioning/softap_prov/utils' + if wifi_tools_path and wifi_tools_path not in sys.path: + sys.path.insert(0, wifi_tools_path) + import wifi_tools + + +def test_redirect(ip, port): # type: (str, str) -> str # pylint: disable=unused-argument + # Establish HTTP connection + sess = http.client.HTTPConnection(ip + ':' + port, timeout=15) + + uri = '/test' + # GET response + sess.request('GET', url=uri) + resp = sess.getresponse() + resp_hdrs = resp.getheaders() + + if resp.status != 302: + raise RuntimeError('Redirect failed, response status: {}'.format(resp.status)) + + for hdr in resp_hdrs: + if hdr[0] == 'location': + uri = hdr[1] + + print('Redirected to uri: {}'.format(uri)) + + # Close HTTP connection + sess.close() + + return uri + + +def test_captive_page(ip, port, uri): # type: (str, str, str) -> bool # pylint: disable=unused-argument + # Establish HTTP connection + sess = http.client.HTTPConnection(ip + ':' + port, timeout=15) + + # GET response + sess.request('GET', url=uri) + resp = sess.getresponse() + + resp_data = resp.read().decode() + search_str = 'Redirect to the captive portal' + + if search_str not in resp_data: + raise RuntimeError('Failed to match {} with data from captive portal: {}'.format(search_str, resp_data)) + + # Close HTTP connection + sess.close() + return True + + +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_BT', ignore=True) +def test_example_captive_portal(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument + # Acquire DUT + dut1 = env.get_dut('captive_portal', 'examples/protocols/http_server/captive_portal', dut_class=ttfw_idf.ESP32DUT) + + # Get binary file + binary_file = os.path.join(dut1.app.binary_path, 'captive_portal.bin') + bin_size = os.path.getsize(binary_file) + ttfw_idf.log_performance('captive_portal_bin_size', '{}KB'.format(bin_size // 1024)) + + # Upload binary and start testing + dut1.start_app() + + # Parse IP address of STA + Utility.console_log('Waiting to connect with softAP') + ap_ip = dut1.expect(re.compile(r'Set up softAP with IP: (\d+.\d+.\d+.\d+)'), timeout=60)[0] + + [ssid, password] = dut1.expect(re.compile(r"wifi_init_softap finished. SSID:'(\S+)' password:'(\S+)'"), timeout=30) + port = dut1.expect(re.compile(r"(?:[\s\S]*)Starting server on port: '(\d+)'"), timeout=30)[0] + + iface = wifi_tools.get_wiface_name() + if iface is None: + raise RuntimeError('Failed to get Wi-Fi interface on host') + print('Interface name : ' + iface) + print('SoftAP SSID : ' + ssid) + print('SoftAP Password : ' + password) + + try: + ctrl = wifi_tools.wpa_cli(iface, reset_on_exit=True) + print('Connecting to DUT SoftAP...') + try: + ip = ctrl.connect(ssid, password) + except RuntimeError as err: + Utility.console_log('error: {}'.format(err)) + try: + got_ip = dut1.expect(re.compile(r'DHCP server assigned IP to a station, IP is: (\d+.\d+.\d+.\d+)'), timeout=60) + Utility.console_log('got_ip: {}'.format(got_ip)) + got_ip = got_ip[0] + if ip != got_ip: + raise RuntimeError('SoftAP connected to another host! {} != {}'.format(ip, got_ip)) + except tiny_test_fw.DUT.ExpectTimeout: + # print what is happening on DUT side + Utility.console_log('in exception tiny_test_fw.DUT.ExpectTimeout') + Utility.console_log(dut1.read()) + raise + print('Connected to DUT SoftAP') + + host_name = 'www.google.com' + host = socket.gethostbyname(host_name) + print('hostname: {} resolved to: {}'.format(host_name, host)) + if host != ap_ip: + raise RuntimeError("DNS server failed to redirect question to the softAP's IP") + + uri = test_redirect(ap_ip, port) + test_captive_page(ap_ip, port, uri) + finally: + ctrl.reset() + + +if __name__ == '__main__': + test_example_captive_portal() # pylint: disable=no-value-for-parameter diff --git a/examples/protocols/http_server/captive_portal/main/CMakeLists.txt b/examples/protocols/http_server/captive_portal/main/CMakeLists.txt new file mode 100644 index 0000000000..3e85f1d9b4 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "main.c" "dns_server.c" + INCLUDE_DIRS "include" + EMBED_FILES root.html) diff --git a/examples/protocols/http_server/captive_portal/main/Kconfig.projbuild b/examples/protocols/http_server/captive_portal/main/Kconfig.projbuild new file mode 100644 index 0000000000..959cd4287d --- /dev/null +++ b/examples/protocols/http_server/captive_portal/main/Kconfig.projbuild @@ -0,0 +1,20 @@ +menu "Example Configuration" + + config ESP_WIFI_SSID + string "SoftAP SSID" + default "esp32_ssid" + help + SSID (network name) to set up the softAP with. + + config ESP_WIFI_PASSWORD + string "SoftAP Password" + default "esp32_pwd" + help + WiFi password (WPA or WPA2) for the example to use for the softAP. + + config ESP_MAX_STA_CONN + int "Maximal STA connections" + default 4 + help + Max number of the STA connects to AP. +endmenu diff --git a/examples/protocols/http_server/captive_portal/main/component.mk b/examples/protocols/http_server/captive_portal/main/component.mk new file mode 100644 index 0000000000..178849a573 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/main/component.mk @@ -0,0 +1,6 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +COMPONENT_EMBED_FILES := root.html diff --git a/examples/protocols/http_server/captive_portal/main/dns_server.c b/examples/protocols/http_server/captive_portal/main/dns_server.c new file mode 100644 index 0000000000..fdc74469d2 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/main/dns_server.c @@ -0,0 +1,247 @@ +/* Captive Portal Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include + +#include "esp_log.h" +#include "esp_system.h" +#include "esp_netif.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" + +#define DNS_PORT (53) +#define DNS_MAX_LEN (256) + +#define OPCODE_MASK (0x7800) +#define QR_FLAG (1 << 7) +#define QD_TYPE_A (0x0001) +#define ANS_TTL_SEC (300) + +static const char *TAG = "example_dns_redirect_server"; + +// DNS Header Packet +typedef struct __attribute__((__packed__)) +{ + uint16_t id; + uint16_t flags; + uint16_t qd_count; + uint16_t an_count; + uint16_t ns_count; + uint16_t ar_count; +} dns_header_t; + +// DNS Question Packet +typedef struct { + uint16_t type; + uint16_t class; +} dns_question_t; + +// DNS Answer Packet +typedef struct __attribute__((__packed__)) +{ + uint16_t ptr_offset; + uint16_t type; + uint16_t class; + uint32_t ttl; + uint16_t addr_len; + uint32_t ip_addr; +} dns_answer_t; + +/* + Parse the name from the packet from the DNS name format to a regular .-seperated name + returns the pointer to the next part of the packet +*/ +static char *parse_dns_name(char *raw_name, char *parsed_name, size_t parsed_name_max_len) +{ + + char *label = raw_name; + char *name_itr = parsed_name; + int name_len = 0; + + do { + int sub_name_len = *label; + // (len + 1) since we are adding a '.' + name_len += (sub_name_len + 1); + if (name_len > parsed_name_max_len) { + return NULL; + } + + // Copy the sub name that follows the the label + memcpy(name_itr, label + 1, sub_name_len); + name_itr[sub_name_len] = '.'; + name_itr += (sub_name_len + 1); + label += sub_name_len + 1; + } while (*label != 0); + + // Terminate the final string, replacing the last '.' + parsed_name[name_len - 1] = '\0'; + // Return pointer to first char after the name + return label + 1; +} + +// Parses the DNS request and prepares a DNS response with the IP of the softAP +static int parse_dns_request(char *req, size_t req_len, char *dns_reply, size_t dns_reply_max_len) +{ + if (req_len > dns_reply_max_len) { + return -1; + } + + // Prepare the reply + memset(dns_reply, 0, dns_reply_max_len); + memcpy(dns_reply, req, req_len); + + // Endianess of NW packet different from chip + dns_header_t *header = (dns_header_t *)dns_reply; + ESP_LOGD(TAG, "DNS query with header id: 0x%X, flags: 0x%X, qd_count: %d", + ntohs(header->id), ntohs(header->flags), ntohs(header->qd_count)); + + // Not a standard query + if ((header->flags & OPCODE_MASK) != 0) { + return 0; + } + + // Set question response flag + header->flags |= QR_FLAG; + + uint16_t qd_count = ntohs(header->qd_count); + header->an_count = htons(qd_count); + + int reply_len = qd_count * sizeof(dns_answer_t) + req_len; + if (reply_len > dns_reply_max_len) { + return -1; + } + + // Pointer to current answer and question + char *cur_ans_ptr = dns_reply + req_len; + char *cur_qd_ptr = dns_reply + sizeof(dns_header_t); + char name[128]; + + // Respond to all questions with the ESP32's IP address + for (int i = 0; i < qd_count; i++) { + char *name_end_ptr = parse_dns_name(cur_qd_ptr, name, sizeof(name)); + if (name_end_ptr == NULL) { + ESP_LOGE(TAG, "Failed to parse DNS question: %s", cur_qd_ptr); + return -1; + } + + dns_question_t *question = (dns_question_t *)(name_end_ptr); + uint16_t qd_type = ntohs(question->type); + uint16_t qd_class = ntohs(question->class); + + ESP_LOGD(TAG, "Received type: %d | Class: %d | Question for: %s", qd_type, qd_class, name); + + if (qd_type == QD_TYPE_A) { + dns_answer_t *answer = (dns_answer_t *)cur_ans_ptr; + + answer->ptr_offset = htons(0xC000 | (cur_qd_ptr - dns_reply)); + answer->type = htons(qd_type); + answer->class = htons(qd_class); + answer->ttl = htonl(ANS_TTL_SEC); + + esp_netif_ip_info_t ip_info; + esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"), &ip_info); + ESP_LOGD(TAG, "Answer with PTR offset: 0x%X and IP 0x%X", ntohs(answer->ptr_offset), ip_info.ip.addr); + + answer->addr_len = htons(sizeof(ip_info.ip.addr)); + answer->ip_addr = ip_info.ip.addr; + } + } + return reply_len; +} + +/* + Sets up a socket and listen for DNS queries, + replies to all type A queries with the IP of the softAP +*/ +void dns_server_task(void *pvParameters) +{ + char rx_buffer[128]; + char addr_str[128]; + int addr_family; + int ip_protocol; + + while (1) { + + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(DNS_PORT); + addr_family = AF_INET; + ip_protocol = IPPROTO_IP; + inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1); + + int sock = socket(addr_family, SOCK_DGRAM, ip_protocol); + if (sock < 0) { + ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + break; + } + ESP_LOGI(TAG, "Socket created"); + + int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); + if (err < 0) { + ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); + } + ESP_LOGI(TAG, "Socket bound, port %d", DNS_PORT); + + while (1) { + ESP_LOGI(TAG, "Waiting for data"); + struct sockaddr_in6 source_addr; // Large enough for both IPv4 or IPv6 + socklen_t socklen = sizeof(source_addr); + int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen); + + // Error occurred during receiving + if (len < 0) { + ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); + close(sock); + break; + } + // Data received + else { + // Get the sender's ip address as string + if (source_addr.sin6_family == PF_INET) { + inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + } else if (source_addr.sin6_family == PF_INET6) { + inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); + } + + // Null-terminate whatever we received and treat like a string... + rx_buffer[len] = 0; + + char reply[DNS_MAX_LEN]; + int reply_len = parse_dns_request(rx_buffer, len, reply, DNS_MAX_LEN); + + ESP_LOGI(TAG, "Received %d bytes from %s | DNS reply with len: %d", len, addr_str, reply_len); + if (reply_len <= 0) { + ESP_LOGE(TAG, "Failed to prepare a DNS reply"); + } else { + int err = sendto(sock, reply, reply_len, 0, (struct sockaddr *)&source_addr, sizeof(source_addr)); + if (err < 0) { + ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); + break; + } + } + } + } + + if (sock != -1) { + ESP_LOGE(TAG, "Shutting down socket"); + shutdown(sock, 0); + close(sock); + } + } + vTaskDelete(NULL); +} + +void start_dns_server(void) +{ + xTaskCreate(dns_server_task, "dns_server", 4096, NULL, 5, NULL); +} diff --git a/examples/protocols/http_server/captive_portal/main/include/dns_server.h b/examples/protocols/http_server/captive_portal/main/include/dns_server.h new file mode 100644 index 0000000000..3059a40e0e --- /dev/null +++ b/examples/protocols/http_server/captive_portal/main/include/dns_server.h @@ -0,0 +1,26 @@ +/* Captive Portal Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set ups and starts a simple DNS server that will respond to all queries + * with the soft AP's IP address + * + */ +void start_dns_server(void); + + +#ifdef __cplusplus +} +#endif diff --git a/examples/protocols/http_server/captive_portal/main/main.c b/examples/protocols/http_server/captive_portal/main/main.c new file mode 100644 index 0000000000..a6cd33c368 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/main/main.c @@ -0,0 +1,163 @@ +/* Captive Portal Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include + +#include "esp_event.h" +#include "esp_log.h" +#include "esp_system.h" + +#include "nvs_flash.h" +#include "esp_wifi.h" +#include "esp_netif.h" +#include "lwip/inet.h" + +#include "esp_http_server.h" +#include "dns_server.h" + +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN + +extern const char root_start[] asm("_binary_root_html_start"); +extern const char root_end[] asm("_binary_root_html_end"); + +static const char *TAG = "example"; + +static void wifi_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + if (event_id == WIFI_EVENT_AP_STACONNECTED) { + wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data; + ESP_LOGI(TAG, "station " MACSTR " join, AID=%d", + MAC2STR(event->mac), event->aid); + } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) { + wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data; + ESP_LOGI(TAG, "station " MACSTR " leave, AID=%d", + MAC2STR(event->mac), event->aid); + } +} + +static void wifi_init_softap(void) +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL)); + + wifi_config_t wifi_config = { + .ap = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID), + .password = EXAMPLE_ESP_WIFI_PASS, + .max_connection = EXAMPLE_MAX_STA_CONN, + .authmode = WIFI_AUTH_WPA_WPA2_PSK + }, + }; + if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) { + wifi_config.ap.authmode = WIFI_AUTH_OPEN; + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + esp_netif_ip_info_t ip_info; + esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"), &ip_info); + + char ip_addr[16]; + inet_ntoa_r(ip_info.ip.addr, ip_addr, 16); + ESP_LOGI(TAG, "Set up softAP with IP: %s", ip_addr); + + ESP_LOGI(TAG, "wifi_init_softap finished. SSID:'%s' password:'%s'", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +// HTTP GET Handler +static esp_err_t root_get_handler(httpd_req_t *req) +{ + const uint32_t root_len = root_end - root_start; + + ESP_LOGI(TAG, "Serve root"); + httpd_resp_set_type(req, "text/html"); + httpd_resp_send(req, root_start, root_len); + + return ESP_OK; +} + +static const httpd_uri_t root = { + .uri = "/", + .method = HTTP_GET, + .handler = root_get_handler +}; + +// HTTP Error (404) Handler - Redirects all requests to the root page +esp_err_t http_404_error_handler(httpd_req_t *req, httpd_err_code_t err) +{ + // Set status + httpd_resp_set_status(req, "302 Temporary Redirect"); + // Redirect to the "/" root directory + httpd_resp_set_hdr(req, "Location", "/"); + // iOS requires content in the response to detect a captive portal, simply redirecting is not sufficient. + httpd_resp_send(req, "Redirect to the captive portal", HTTPD_RESP_USE_STRLEN); + + ESP_LOGI(TAG, "Redirecting to root"); + return ESP_OK; +} + +static httpd_handle_t start_webserver(void) +{ + httpd_handle_t server = NULL; + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + config.max_open_sockets = 13; + config.lru_purge_enable = true; + + // Start the httpd server + ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port); + if (httpd_start(&server, &config) == ESP_OK) { + // Set URI handlers + ESP_LOGI(TAG, "Registering URI handlers"); + httpd_register_uri_handler(server, &root); + httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, http_404_error_handler); + } + return server; +} + +void app_main(void) +{ + /* + Turn of warnings from HTTP server as redirecting traffic will yield + lots of invalid requests + */ + esp_log_level_set("httpd_uri", ESP_LOG_ERROR); + esp_log_level_set("httpd_txrx", ESP_LOG_ERROR); + esp_log_level_set("httpd_parse", ESP_LOG_ERROR); + + + // Initialize networking stack + ESP_ERROR_CHECK(esp_netif_init()); + + // Create default event loop needed by the main app + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Initialize NVS needed by Wi-Fi + ESP_ERROR_CHECK(nvs_flash_init()); + + // Initialize Wi-Fi including netif with default config + esp_netif_create_default_wifi_ap(); + + // Initialise ESP32 in SoftAP mode + wifi_init_softap(); + + // Start the server for the first time + start_webserver(); + + // Start the DNS server that will redirect all queries to the softAP IP + start_dns_server(); +} diff --git a/examples/protocols/http_server/captive_portal/main/root.html b/examples/protocols/http_server/captive_portal/main/root.html new file mode 100644 index 0000000000..ed0ee30164 --- /dev/null +++ b/examples/protocols/http_server/captive_portal/main/root.html @@ -0,0 +1,15 @@ + + + + + ESP Captive Portal + + +

ESP Captive Portal

+

Hello World, this is ESP32!

+ + diff --git a/examples/protocols/http_server/captive_portal/sdkconfig.defaults b/examples/protocols/http_server/captive_portal/sdkconfig.defaults new file mode 100644 index 0000000000..a2fbe3e18b --- /dev/null +++ b/examples/protocols/http_server/captive_portal/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 +CONFIG_LWIP_MAX_SOCKETS=16 From 3bfd8f5d5fd2cd6d8cc8318877ed3ffb36456c24 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 24 Aug 2021 14:42:07 +0800 Subject: [PATCH 022/310] mcpwm: update register file according to TRM --- components/hal/esp32/include/hal/mcpwm_ll.h | 337 +- components/hal/esp32s3/include/hal/mcpwm_ll.h | 345 +- components/soc/esp32/include/soc/mcpwm_reg.h | 6556 +++++++++-------- .../soc/esp32/include/soc/mcpwm_struct.h | 1889 +++-- .../soc/esp32s3/include/soc/mcpwm_reg.h | 6457 +++++++++------- .../soc/esp32s3/include/soc/mcpwm_struct.h | 1901 +++-- 6 files changed, 10618 insertions(+), 6867 deletions(-) diff --git a/components/hal/esp32/include/hal/mcpwm_ll.h b/components/hal/esp32/include/hal/mcpwm_ll.h index f2e3b34183..ab443f6019 100644 --- a/components/hal/esp32/include/hal/mcpwm_ll.h +++ b/components/hal/esp32/include/hal/mcpwm_ll.h @@ -41,15 +41,20 @@ extern "C" { /********************* Group registers *******************/ -// Set/Get group clock: PWM_clk = CLK_160M / (clk_cfg.prescale + 1) +// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1) static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale) { - mcpwm->clk_cfg.prescale = pre_scale - 1; + // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) + // We take care of the "read-modify-write" procedure by ourselves. + mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; + clkcfg.clk_prescale = pre_scale - 1; + mcpwm->clk_cfg = clkcfg; } static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) { - return mcpwm->clk_cfg.prescale + 1; + mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; + return clkcfg.clk_prescale + 1; } static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) @@ -265,20 +270,25 @@ static inline void mcpwm_ll_intr_enable_capture(mcpwm_dev_t *mcpwm, uint32_t cap static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale) { - mcpwm->timer[timer_id].period.prescale = prescale - 1; + // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) + // We take care of the "read-modify-write" procedure by ourselves. + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + cfg0.timer_prescale = prescale - 1; + mcpwm->timer[timer_id].timer_cfg0 = cfg0; } static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].period.prescale + 1; + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + return cfg0.timer_prescale + 1; } static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] - mcpwm->timer[timer_id].period.period = peak - 1; + mcpwm->timer[timer_id].timer_cfg0.timer_period = peak - 1; } else { // in symmetric mode, period = [0,peak-1] + [peak,1] - mcpwm->timer[timer_id].period.period = peak; + mcpwm->timer[timer_id].timer_cfg0.timer_period = peak; } } @@ -286,32 +296,32 @@ static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, { // asymmetric mode if (!symmetric) { - return mcpwm->timer[timer_id].period.period + 1; + return mcpwm->timer[timer_id].timer_cfg0.timer_period + 1; } // symmetric mode - return mcpwm->timer[timer_id].period.period; + return mcpwm->timer[timer_id].timer_cfg0.timer_period; } static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].period.upmethod = 0; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; } static inline void mcpwm_ll_timer_enable_update_period_on_tez(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; } } static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x02; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x02; } } @@ -319,23 +329,23 @@ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_i { switch (mode) { case MCPWM_TIMER_COUNT_MODE_PAUSE: - mcpwm->timer[timer_id].mode.mode = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 0; break; case MCPWM_TIMER_COUNT_MODE_UP: - mcpwm->timer[timer_id].mode.mode = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 1; break; case MCPWM_TIMER_COUNT_MODE_DOWN: - mcpwm->timer[timer_id].mode.mode = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 2; break; case MCPWM_TIMER_COUNT_MODE_UP_DOWN: - mcpwm->timer[timer_id].mode.mode = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 3; break; } } static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id) { - switch (mcpwm->timer[timer_id].mode.mode) { + switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) { case 0: return MCPWM_TIMER_COUNT_MODE_PAUSE; case 1: @@ -344,6 +354,9 @@ static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t return MCPWM_TIMER_COUNT_MODE_DOWN; case 3: return MCPWM_TIMER_COUNT_MODE_UP_DOWN; + default: + HAL_ASSERT(false && "unknown count mode"); + return mcpwm->timer[timer_id].timer_cfg1.timer_mod; } } @@ -351,74 +364,74 @@ static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int ti { switch (cmd) { case MCPWM_TIMER_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 0; break; case MCPWM_TIMER_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 1; break; case MCPWM_TIMER_START_NO_STOP: - mcpwm->timer[timer_id].mode.start = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 2; break; case MCPWM_TIMER_START_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 3; break; case MCPWM_TIMER_START_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 4; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 4; break; } } static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].status.value; + return mcpwm->timer[timer_id].timer_status.timer_value; } static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].status.direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; + return mcpwm->timer[timer_id].timer_status.timer_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; } static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { - mcpwm->timer[timer_id].sync.in_en = enable; + mcpwm->timer[timer_id].timer_sync.timer_synci_en = enable; } static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out is selected to sync_in - mcpwm->timer[timer_id].sync.out_sel = 0; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 0; } static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) { if (event == MCPWM_TIMER_EVENT_ZERO) { - mcpwm->timer[timer_id].sync.out_sel = 1; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 1; } else if (event == MCPWM_TIMER_EVENT_PEAK) { - mcpwm->timer[timer_id].sync.out_sel = 2; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 2; } else { - HAL_ASSERT(false); + HAL_ASSERT(false && "unknown sync out event"); } } static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out will always be zero - mcpwm->timer[timer_id].sync.out_sel = 3; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 3; } static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw; + mcpwm->timer[timer_id].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_sync_sw; } static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) { - mcpwm->timer[timer_id].sync.timer_phase = phase_value; + mcpwm->timer[timer_id].timer_sync.timer_phase = phase_value; } static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) { - mcpwm->timer[timer_id].sync.phase_direct = direction; + mcpwm->timer[timer_id].timer_sync.timer_phase_direction = direction; } static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) @@ -458,117 +471,117 @@ static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operat static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) { if (operator_id == 0) { - mcpwm->timer_sel.operator0_sel = timer_id; + mcpwm->operator_timersel.operator0_timersel = timer_id; } else if (operator_id == 1) { - mcpwm->timer_sel.operator1_sel = timer_id; + mcpwm->operator_timersel.operator1_timersel = timer_id; } else { - mcpwm->timer_sel.operator2_sel = timer_id; + mcpwm->operator_timersel.operator2_timersel = timer_id; } } static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~(0x0F << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); } static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 0) << (4 * compare_id); + mcpwm->operator[operator_id].gen_stmp_cfg.val |= (1 << 0) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 0) << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~((1 << 0) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 1) << (4 * compare_id); + mcpwm->operator[operator_id].gen_stmp_cfg.val |= (1 << 1) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 1) << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~((1 << 1) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 2) << (4 * compare_id); + mcpwm->operator[operator_id].gen_stmp_cfg.val |= (1 << 2) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 2) << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~((1 << 2) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) { - mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val = compare_value; + mcpwm->operator[operator_id].timestamp[compare_id].gen = compare_value; } static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - return mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val; + return mcpwm->operator[operator_id].timestamp[compare_id].gen; } static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].gen_cfg0.upmethod = 0; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod = 0; } static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 0; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 0); + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 1; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 1); + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 2; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 2); + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 2); } } static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id) { - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); } static inline void mcpwm_ll_operator_set_trigger_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) { // the timer here is not selectable, must be the one connected with the operator - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); } /********************* Generator registers *******************/ static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].generator[generator_id].val = 0; + mcpwm->operator[operator_id].generator[generator_id].val = 0; } static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (event * 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2 + 12); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (event * 2 + 12); } } @@ -576,11 +589,11 @@ static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int cmp_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); } } @@ -588,58 +601,58 @@ static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int trig_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); } } static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce = ~mcpwm->channel[operator_id].gen_force.a_nciforce; + mcpwm->operator[operator_id].gen_force.gen_a_nciforce = ~mcpwm->operator[operator_id].gen_force.gen_a_nciforce; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce = ~mcpwm->channel[operator_id].gen_force.b_nciforce; + mcpwm->operator[operator_id].gen_force.gen_b_nciforce = ~mcpwm->operator[operator_id].gen_force.gen_b_nciforce; } } static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operator[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_a_cntuforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_b_cntuforce_mode = 0; } } static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_a_nciforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_b_nciforce_mode = 0; } } static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operator[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_a_cntuforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_b_cntuforce_mode = level + 1; } } static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_a_nciforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_b_nciforce_mode = level + 1; } } @@ -648,116 +661,116 @@ static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same) { // whether to make the resolution of dead time delay module the same to the timer connected with operator - mcpwm->channel[operator_id].db_cfg.clk_sel = same; + mcpwm->operator[operator_id].dt_cfg.dt_clk_sel = same; } static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.red_insel = generator; + mcpwm->operator[operator_id].dt_cfg.dt_red_insel = generator; } static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.fed_insel = generator; + mcpwm->operator[operator_id].dt_cfg.dt_fed_insel = generator; } static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) { if (bypass) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 15); + mcpwm->operator[operator_id].dt_cfg.val |= 1 << (path + 15); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 15)); + mcpwm->operator[operator_id].dt_cfg.val &= ~(1 << (path + 15)); } } static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) { if (invert) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 13); + mcpwm->operator[operator_id].dt_cfg.val |= 1 << (path + 13); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 13)); + mcpwm->operator[operator_id].dt_cfg.val &= ~(1 << (path + 13)); } } static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) { if (swap) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 9); + mcpwm->operator[operator_id].dt_cfg.val |= 1 << (path + 9); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 9)); + mcpwm->operator[operator_id].dt_cfg.val &= ~(1 << (path + 9)); } } static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].db_cfg.deb_mode = enable; + mcpwm->operator[operator_id].dt_cfg.dt_deb_mode = enable; } static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) { - return (mcpwm->channel[operator_id].db_cfg.deb_mode << 8) | (mcpwm->channel[operator_id].db_cfg.b_outswap << 7) | - (mcpwm->channel[operator_id].db_cfg.a_outswap << 6) | (mcpwm->channel[operator_id].db_cfg.fed_insel << 5) | - (mcpwm->channel[operator_id].db_cfg.red_insel << 4) | (mcpwm->channel[operator_id].db_cfg.fed_outinvert << 3) | - (mcpwm->channel[operator_id].db_cfg.red_outinvert << 2) | (mcpwm->channel[operator_id].db_cfg.a_outbypass << 1) | - (mcpwm->channel[operator_id].db_cfg.b_outbypass << 0); + return (mcpwm->operator[operator_id].dt_cfg.dt_deb_mode << 8) | (mcpwm->operator[operator_id].dt_cfg.dt_b_outswap << 7) | + (mcpwm->operator[operator_id].dt_cfg.dt_a_outswap << 6) | (mcpwm->operator[operator_id].dt_cfg.dt_fed_insel << 5) | + (mcpwm->operator[operator_id].dt_cfg.dt_red_insel << 4) | (mcpwm->operator[operator_id].dt_cfg.dt_fed_outinvert << 3) | + (mcpwm->operator[operator_id].dt_cfg.dt_red_outinvert << 2) | (mcpwm->operator[operator_id].dt_cfg.dt_a_outbypass << 1) | + (mcpwm->operator[operator_id].dt_cfg.dt_b_outbypass << 0); } static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) { - mcpwm->channel[operator_id].db_fed_cfg.fed = fed - 1; + mcpwm->operator[operator_id].dt_fed_cfg.dt_fed = fed - 1; } static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_fed_cfg.fed + 1; + return mcpwm->operator[operator_id].dt_fed_cfg.dt_fed + 1; } static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) { - mcpwm->channel[operator_id].db_red_cfg.red = red - 1; + mcpwm->operator[operator_id].dt_red_cfg.dt_red = red - 1; } static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_red_cfg.red + 1; + return mcpwm->operator[operator_id].dt_red_cfg.dt_red + 1; } static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod = 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod = 0; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod = 0; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod = 0; } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 0; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 0; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 0); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 0); + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 0); + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 1; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 1; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 1; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 1); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 1); + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 1); + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 2; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 2; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 2; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 2); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 2); + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 2); + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 2); } } @@ -765,47 +778,47 @@ static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mc static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].carrier_cfg.en = enable; + mcpwm->operator[operator_id].carrier_cfg.carrier_en = enable; } static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) { - mcpwm->channel[operator_id].carrier_cfg.prescale = prescale - 1; + mcpwm->operator[operator_id].carrier_cfg.carrier_prescale = prescale - 1; } static inline uint8_t mcpwm_ll_carrier_get_prescale(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.prescale + 1; + return mcpwm->operator[operator_id].carrier_cfg.carrier_prescale + 1; } static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) { - mcpwm->channel[operator_id].carrier_cfg.duty = carrier_duty; + mcpwm->operator[operator_id].carrier_cfg.carrier_duty = carrier_duty; } static inline uint8_t mcpwm_ll_carrier_get_duty(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.duty; + return mcpwm->operator[operator_id].carrier_cfg.carrier_duty; } static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.out_invert = invert; + mcpwm->operator[operator_id].carrier_cfg.carrier_out_invert = invert; } static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.in_invert = invert; + mcpwm->operator[operator_id].carrier_cfg.carrier_in_invert = invert; } static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) { - mcpwm->channel[operator_id].carrier_cfg.oshtwth = pulse_width - 1; + mcpwm->operator[operator_id].carrier_cfg.carrier_oshtwth = pulse_width - 1; } static inline uint8_t mcpwm_ll_carrier_get_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.oshtwth + 1; + return mcpwm->operator[operator_id].carrier_cfg.carrier_oshtwth + 1; } /********************* Fault detector registers *******************/ @@ -831,155 +844,155 @@ static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) { // a posedge can clear the ost fault status - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 0; - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 1; + mcpwm->operator[operator_id].fh_cfg1.fh_clr_ost = 0; + mcpwm->operator[operator_id].fh_cfg1.fh_clr_ost = 1; } static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (7 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (7 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val |= (enable << (7 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (3 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (3 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 1; + mcpwm->operator[operator_id].fh_cfg1.val |= 1 << 1; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 1); + mcpwm->operator[operator_id].fh_cfg1.val &= ~(1 << 1); } } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 2; + mcpwm->operator[operator_id].fh_cfg1.val |= 1 << 2; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 2); + mcpwm->operator[operator_id].fh_cfg1.val &= ~(1 << 2); } } static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_cbc = enable; + mcpwm->operator[operator_id].fh_cfg0.fh_sw_cbc = enable; } static inline void mcpwm_ll_fault_enable_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_ost = enable; + mcpwm->operator[operator_id].fh_cfg0.fh_sw_ost = enable; } static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_cbc = ~mcpwm->channel[operator_id].tz_cfg1.force_cbc; + mcpwm->operator[operator_id].fh_cfg1.fh_force_cbc = ~mcpwm->operator[operator_id].fh_cfg1.fh_force_cbc; } static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_ost = ~mcpwm->channel[operator_id].tz_cfg1.force_ost; + mcpwm->operator[operator_id].fh_cfg1.fh_force_ost = ~mcpwm->operator[operator_id].fh_cfg1.fh_force_ost; } static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); + mcpwm->operator[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); + mcpwm->operator[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); } } static inline bool mcpwm_ll_fault_is_ost_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.ost_on; + return mcpwm->operator[op].fh_status.fh_ost_on; } static inline bool mcpwm_ll_fault_is_cbc_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.cbc_on; + return mcpwm->operator[op].fh_status.fh_cbc_on; } /********************* Capture registers *******************/ static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.timer_en = enable; + mcpwm->cap_timer_cfg.cap_timer_en = enable; } static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) { - mcpwm->cap_cfg_ch[channel].en = enable; + mcpwm->cap_chn_cfg[channel].capn_en = enable; } static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) { - mcpwm->cap_timer_phase = phase_value; + mcpwm->cap_timer_phase.cap_timer_phase = phase_value; } static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm) { - return mcpwm->cap_timer_phase; + return mcpwm->cap_timer_phase.cap_timer_phase; } static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.synci_en = enable; + mcpwm->cap_timer_cfg.cap_synci_en = enable; } static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer) { - mcpwm->cap_timer_cfg.synci_sel = sync_out_timer + 1; + mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; } static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro) { - mcpwm->cap_timer_cfg.synci_sel = extern_synchro + 4; + mcpwm->cap_timer_cfg.cap_synci_sel = extern_synchro + 4; } static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) { - mcpwm->cap_timer_cfg.sync_sw = 1; // auto clear + mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear } static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 2; + mcpwm->cap_chn_cfg[channel].val |= 1 << 2; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 2); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 2); } } static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 1; + mcpwm->cap_chn_cfg[channel].val |= 1 << 1; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 1); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 1); } } static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) { - mcpwm->cap_cfg_ch[channel].in_invert = invert; + mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; } static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) { - mcpwm->cap_cfg_ch[channel].sw = 1; // auto clear + mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear } static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_val_ch[channel]; + return mcpwm->cap_chn[channel].capn_value; } static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) @@ -989,12 +1002,12 @@ static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) { - mcpwm->cap_cfg_ch[channel].prescale = prescale - 1; + mcpwm->cap_chn_cfg[channel].capn_prescale = prescale - 1; } static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_cfg_ch[channel].prescale + 1; + return mcpwm->cap_chn_cfg[channel].capn_prescale + 1; } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/mcpwm_ll.h b/components/hal/esp32s3/include/hal/mcpwm_ll.h index 93f44e2470..8790aa42b8 100644 --- a/components/hal/esp32s3/include/hal/mcpwm_ll.h +++ b/components/hal/esp32s3/include/hal/mcpwm_ll.h @@ -41,20 +41,20 @@ extern "C" { /********************* Group registers *******************/ -// Set/Get group clock: PWM_clk = CLK_160M / (clk_cfg.prescale + 1) +// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1) static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale) { // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) // We take care of the "read-modify-write" procedure by ourselves. - typeof(mcpwm->clk_cfg) clkcfg = mcpwm->clk_cfg; - clkcfg.prescale = pre_scale - 1; + mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; + clkcfg.clk_prescale = pre_scale - 1; mcpwm->clk_cfg = clkcfg; } static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) { - typeof(mcpwm->clk_cfg) clkcfg = mcpwm->clk_cfg; - return clkcfg.prescale + 1; + mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; + return clkcfg.clk_prescale + 1; } static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) @@ -272,23 +272,23 @@ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int tim { // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) // We take care of the "read-modify-write" procedure by ourselves. - typeof(mcpwm->timer[timer_id].period) period = mcpwm->timer[timer_id].period; - period.prescale = prescale - 1; - mcpwm->timer[timer_id].period = period; + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + cfg0.timer_prescale = prescale - 1; + mcpwm->timer[timer_id].timer_cfg0 = cfg0; } static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) { - typeof(mcpwm->timer[timer_id].period) period = mcpwm->timer[timer_id].period; - return period.prescale + 1; + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + return cfg0.timer_prescale + 1; } static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] - mcpwm->timer[timer_id].period.period = peak - 1; + mcpwm->timer[timer_id].timer_cfg0.timer_period = peak - 1; } else { // in symmetric mode, period = [0,peak-1] + [peak,1] - mcpwm->timer[timer_id].period.period = peak; + mcpwm->timer[timer_id].timer_cfg0.timer_period = peak; } } @@ -296,32 +296,32 @@ static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, { // asymmetric mode if (!symmetric) { - return mcpwm->timer[timer_id].period.period + 1; + return mcpwm->timer[timer_id].timer_cfg0.timer_period + 1; } // symmetric mode - return mcpwm->timer[timer_id].period.period; + return mcpwm->timer[timer_id].timer_cfg0.timer_period; } static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].period.upmethod = 0; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; } static inline void mcpwm_ll_timer_enable_update_period_on_tez(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; } } static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x02; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x02; } } @@ -329,23 +329,23 @@ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_i { switch (mode) { case MCPWM_TIMER_COUNT_MODE_PAUSE: - mcpwm->timer[timer_id].mode.mode = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 0; break; case MCPWM_TIMER_COUNT_MODE_UP: - mcpwm->timer[timer_id].mode.mode = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 1; break; case MCPWM_TIMER_COUNT_MODE_DOWN: - mcpwm->timer[timer_id].mode.mode = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 2; break; case MCPWM_TIMER_COUNT_MODE_UP_DOWN: - mcpwm->timer[timer_id].mode.mode = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 3; break; } } static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id) { - switch (mcpwm->timer[timer_id].mode.mode) { + switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) { case 0: return MCPWM_TIMER_COUNT_MODE_PAUSE; case 1: @@ -354,6 +354,9 @@ static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t return MCPWM_TIMER_COUNT_MODE_DOWN; case 3: return MCPWM_TIMER_COUNT_MODE_UP_DOWN; + default: + HAL_ASSERT(false && "unknown count mode"); + return mcpwm->timer[timer_id].timer_cfg1.timer_mod; } } @@ -361,19 +364,19 @@ static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int ti { switch (cmd) { case MCPWM_TIMER_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 0; break; case MCPWM_TIMER_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 1; break; case MCPWM_TIMER_START_NO_STOP: - mcpwm->timer[timer_id].mode.start = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 2; break; case MCPWM_TIMER_START_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 3; break; case MCPWM_TIMER_START_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 4; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 4; break; } } @@ -382,62 +385,62 @@ static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int ti { // status.value saves the "next count value", so need an extra round up here to get the current count value according to count mode // timer is paused - if (mcpwm->timer[timer_id].mode.mode == 0) { - return mcpwm->timer[timer_id].status.value; + if (mcpwm->timer[timer_id].timer_cfg1.timer_mod == 0) { + return mcpwm->timer[timer_id].timer_status.timer_value; } - if (mcpwm->timer[timer_id].status.direction) { // down direction - return (mcpwm->timer[timer_id].status.value + 1) % (mcpwm->timer[timer_id].period.period + 1); + if (mcpwm->timer[timer_id].timer_status.timer_direction) { // down direction + return (mcpwm->timer[timer_id].timer_status.timer_value + 1) % (mcpwm->timer[timer_id].timer_cfg0.timer_period + 1); } // up direction - return (mcpwm->timer[timer_id].status.value + mcpwm->timer[timer_id].period.period) % (mcpwm->timer[timer_id].period.period + 1); + return (mcpwm->timer[timer_id].timer_status.timer_value + mcpwm->timer[timer_id].timer_cfg0.timer_period) % (mcpwm->timer[timer_id].timer_cfg0.timer_period + 1); } static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].status.direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; + return mcpwm->timer[timer_id].timer_status.timer_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; } static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { - mcpwm->timer[timer_id].sync.in_en = enable; + mcpwm->timer[timer_id].timer_sync.timer_synci_en = enable; } static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out is selected to sync_in - mcpwm->timer[timer_id].sync.out_sel = 0; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 0; } static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) { if (event == MCPWM_TIMER_EVENT_ZERO) { - mcpwm->timer[timer_id].sync.out_sel = 1; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 1; } else if (event == MCPWM_TIMER_EVENT_PEAK) { - mcpwm->timer[timer_id].sync.out_sel = 2; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 2; } else { - HAL_ASSERT(false); + HAL_ASSERT(false && "unknown sync out event"); } } static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out will always be zero - mcpwm->timer[timer_id].sync.out_sel = 3; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 3; } static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw; + mcpwm->timer[timer_id].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_sync_sw; } static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) { - mcpwm->timer[timer_id].sync.timer_phase = phase_value; + mcpwm->timer[timer_id].timer_sync.timer_phase = phase_value; } static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) { - mcpwm->timer[timer_id].sync.phase_direct = direction; + mcpwm->timer[timer_id].timer_sync.timer_phase_direction = direction; } static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) @@ -477,117 +480,117 @@ static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operat static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) { if (operator_id == 0) { - mcpwm->timer_sel.operator0_sel = timer_id; + mcpwm->operator_timersel.operator0_timersel = timer_id; } else if (operator_id == 1) { - mcpwm->timer_sel.operator1_sel = timer_id; + mcpwm->operator_timersel.operator1_timersel = timer_id; } else { - mcpwm->timer_sel.operator2_sel = timer_id; + mcpwm->operator_timersel.operator2_timersel = timer_id; } } static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~(0x0F << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); } static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 0) << (4 * compare_id); + mcpwm->operator[operator_id].gen_stmp_cfg.val |= (1 << 0) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 0) << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~((1 << 0) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 1) << (4 * compare_id); + mcpwm->operator[operator_id].gen_stmp_cfg.val |= (1 << 1) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 1) << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~((1 << 1) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 2) << (4 * compare_id); + mcpwm->operator[operator_id].gen_stmp_cfg.val |= (1 << 2) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 2) << (4 * compare_id)); + mcpwm->operator[operator_id].gen_stmp_cfg.val &= ~((1 << 2) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) { - mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val = compare_value; + mcpwm->operator[operator_id].timestamp[compare_id].gen = compare_value; } static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - return mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val; + return mcpwm->operator[operator_id].timestamp[compare_id].gen; } static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].gen_cfg0.upmethod = 0; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod = 0; } static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 0; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 0); + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 1; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 1); + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 2; + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 2); + mcpwm->operator[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 2); } } static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id) { - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); } static inline void mcpwm_ll_operator_set_trigger_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) { // the timer here is not selectable, must be the one connected with the operator - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operator[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); } /********************* Generator registers *******************/ static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].generator[generator_id].val = 0; + mcpwm->operator[operator_id].generator[generator_id].val = 0; } static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (event * 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2 + 12); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (event * 2 + 12); } } @@ -595,11 +598,11 @@ static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int cmp_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); } } @@ -607,58 +610,58 @@ static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int trig_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); + mcpwm->operator[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); + mcpwm->operator[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); } } static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce = ~mcpwm->channel[operator_id].gen_force.a_nciforce; + mcpwm->operator[operator_id].gen_force.gen_a_nciforce = ~mcpwm->operator[operator_id].gen_force.gen_a_nciforce; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce = ~mcpwm->channel[operator_id].gen_force.b_nciforce; + mcpwm->operator[operator_id].gen_force.gen_b_nciforce = ~mcpwm->operator[operator_id].gen_force.gen_b_nciforce; } } static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operator[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_a_cntuforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_b_cntuforce_mode = 0; } } static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_a_nciforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = 0; + mcpwm->operator[operator_id].gen_force.gen_b_nciforce_mode = 0; } } static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operator[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_a_cntuforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_b_cntuforce_mode = level + 1; } } static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_a_nciforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = level + 1; + mcpwm->operator[operator_id].gen_force.gen_b_nciforce_mode = level + 1; } } @@ -667,116 +670,116 @@ static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same) { // whether to make the resolution of dead time delay module the same to the timer connected with operator - mcpwm->channel[operator_id].db_cfg.clk_sel = same; + mcpwm->operator[operator_id].dt_cfg.dt_clk_sel = same; } static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.red_insel = generator; + mcpwm->operator[operator_id].dt_cfg.dt_red_insel = generator; } static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.fed_insel = generator; + mcpwm->operator[operator_id].dt_cfg.dt_fed_insel = generator; } static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) { if (bypass) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 15); + mcpwm->operator[operator_id].dt_cfg.val |= 1 << (path + 15); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 15)); + mcpwm->operator[operator_id].dt_cfg.val &= ~(1 << (path + 15)); } } static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) { if (invert) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 13); + mcpwm->operator[operator_id].dt_cfg.val |= 1 << (path + 13); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 13)); + mcpwm->operator[operator_id].dt_cfg.val &= ~(1 << (path + 13)); } } static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) { if (swap) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 9); + mcpwm->operator[operator_id].dt_cfg.val |= 1 << (path + 9); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 9)); + mcpwm->operator[operator_id].dt_cfg.val &= ~(1 << (path + 9)); } } static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].db_cfg.deb_mode = enable; + mcpwm->operator[operator_id].dt_cfg.dt_deb_mode = enable; } static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) { - return (mcpwm->channel[operator_id].db_cfg.deb_mode << 8) | (mcpwm->channel[operator_id].db_cfg.b_outswap << 7) | - (mcpwm->channel[operator_id].db_cfg.a_outswap << 6) | (mcpwm->channel[operator_id].db_cfg.fed_insel << 5) | - (mcpwm->channel[operator_id].db_cfg.red_insel << 4) | (mcpwm->channel[operator_id].db_cfg.fed_outinvert << 3) | - (mcpwm->channel[operator_id].db_cfg.red_outinvert << 2) | (mcpwm->channel[operator_id].db_cfg.a_outbypass << 1) | - (mcpwm->channel[operator_id].db_cfg.b_outbypass << 0); + return (mcpwm->operator[operator_id].dt_cfg.dt_deb_mode << 8) | (mcpwm->operator[operator_id].dt_cfg.dt_b_outswap << 7) | + (mcpwm->operator[operator_id].dt_cfg.dt_a_outswap << 6) | (mcpwm->operator[operator_id].dt_cfg.dt_fed_insel << 5) | + (mcpwm->operator[operator_id].dt_cfg.dt_red_insel << 4) | (mcpwm->operator[operator_id].dt_cfg.dt_fed_outinvert << 3) | + (mcpwm->operator[operator_id].dt_cfg.dt_red_outinvert << 2) | (mcpwm->operator[operator_id].dt_cfg.dt_a_outbypass << 1) | + (mcpwm->operator[operator_id].dt_cfg.dt_b_outbypass << 0); } static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) { - mcpwm->channel[operator_id].db_fed_cfg.fed = fed - 1; + mcpwm->operator[operator_id].dt_fed_cfg.dt_fed = fed - 1; } static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_fed_cfg.fed + 1; + return mcpwm->operator[operator_id].dt_fed_cfg.dt_fed + 1; } static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) { - mcpwm->channel[operator_id].db_red_cfg.red = red - 1; + mcpwm->operator[operator_id].dt_red_cfg.dt_red = red - 1; } static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_red_cfg.red + 1; + return mcpwm->operator[operator_id].dt_red_cfg.dt_red + 1; } static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod = 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod = 0; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod = 0; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod = 0; } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 0; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 0; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 0); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 0); + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 0); + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 1; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 1; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 1; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 1); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 1); + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 1); + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 2; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 2; + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 2; + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 2); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 2); + mcpwm->operator[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 2); + mcpwm->operator[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 2); } } @@ -784,47 +787,47 @@ static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mc static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].carrier_cfg.en = enable; + mcpwm->operator[operator_id].carrier_cfg.carrier_en = enable; } static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) { - mcpwm->channel[operator_id].carrier_cfg.prescale = prescale - 1; + mcpwm->operator[operator_id].carrier_cfg.carrier_prescale = prescale - 1; } static inline uint8_t mcpwm_ll_carrier_get_prescale(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.prescale + 1; + return mcpwm->operator[operator_id].carrier_cfg.carrier_prescale + 1; } static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) { - mcpwm->channel[operator_id].carrier_cfg.duty = carrier_duty; + mcpwm->operator[operator_id].carrier_cfg.carrier_duty = carrier_duty; } static inline uint8_t mcpwm_ll_carrier_get_duty(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.duty; + return mcpwm->operator[operator_id].carrier_cfg.carrier_duty; } static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.out_invert = invert; + mcpwm->operator[operator_id].carrier_cfg.carrier_out_invert = invert; } static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.in_invert = invert; + mcpwm->operator[operator_id].carrier_cfg.carrier_in_invert = invert; } static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) { - mcpwm->channel[operator_id].carrier_cfg.oshtwth = pulse_width - 1; + mcpwm->operator[operator_id].carrier_cfg.carrier_oshtwth = pulse_width - 1; } static inline uint8_t mcpwm_ll_carrier_get_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.oshtwth + 1; + return mcpwm->operator[operator_id].carrier_cfg.carrier_oshtwth + 1; } /********************* Fault detector registers *******************/ @@ -850,155 +853,155 @@ static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) { // a posedge can clear the ost fault status - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 0; - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 1; + mcpwm->operator[operator_id].fh_cfg1.fh_clr_ost = 0; + mcpwm->operator[operator_id].fh_cfg1.fh_clr_ost = 1; } static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (7 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (7 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val |= (enable << (7 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (3 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (3 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); + mcpwm->operator[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 1; + mcpwm->operator[operator_id].fh_cfg1.val |= 1 << 1; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 1); + mcpwm->operator[operator_id].fh_cfg1.val &= ~(1 << 1); } } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 2; + mcpwm->operator[operator_id].fh_cfg1.val |= 1 << 2; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 2); + mcpwm->operator[operator_id].fh_cfg1.val &= ~(1 << 2); } } static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_cbc = enable; + mcpwm->operator[operator_id].fh_cfg0.fh_sw_cbc = enable; } static inline void mcpwm_ll_fault_enable_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_ost = enable; + mcpwm->operator[operator_id].fh_cfg0.fh_sw_ost = enable; } static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_cbc = ~mcpwm->channel[operator_id].tz_cfg1.force_cbc; + mcpwm->operator[operator_id].fh_cfg1.fh_force_cbc = ~mcpwm->operator[operator_id].fh_cfg1.fh_force_cbc; } static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_ost = ~mcpwm->channel[operator_id].tz_cfg1.force_ost; + mcpwm->operator[operator_id].fh_cfg1.fh_force_ost = ~mcpwm->operator[operator_id].fh_cfg1.fh_force_ost; } static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); + mcpwm->operator[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); + mcpwm->operator[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); + mcpwm->operator[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); } } static inline bool mcpwm_ll_fault_is_ost_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.ost_on; + return mcpwm->operator[op].fh_status.fh_ost_on; } static inline bool mcpwm_ll_fault_is_cbc_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.cbc_on; + return mcpwm->operator[op].fh_status.fh_cbc_on; } /********************* Capture registers *******************/ static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.timer_en = enable; + mcpwm->cap_timer_cfg.cap_timer_en = enable; } static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) { - mcpwm->cap_cfg_ch[channel].en = enable; + mcpwm->cap_chn_cfg[channel].capn_en = enable; } static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) { - mcpwm->cap_timer_phase = phase_value; + mcpwm->cap_timer_phase.cap_timer_phase = phase_value; } static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm) { - return mcpwm->cap_timer_phase; + return mcpwm->cap_timer_phase.cap_timer_phase; } static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.synci_en = enable; + mcpwm->cap_timer_cfg.cap_synci_en = enable; } static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer) { - mcpwm->cap_timer_cfg.synci_sel = sync_out_timer + 1; + mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; } static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro) { - mcpwm->cap_timer_cfg.synci_sel = extern_synchro + 4; + mcpwm->cap_timer_cfg.cap_synci_sel = extern_synchro + 4; } static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) { - mcpwm->cap_timer_cfg.sync_sw = 1; // auto clear + mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear } static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 2; + mcpwm->cap_chn_cfg[channel].val |= 1 << 2; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 2); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 2); } } static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 1; + mcpwm->cap_chn_cfg[channel].val |= 1 << 1; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 1); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 1); } } static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) { - mcpwm->cap_cfg_ch[channel].in_invert = invert; + mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; } static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) { - mcpwm->cap_cfg_ch[channel].sw = 1; // auto clear + mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear } static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_val_ch[channel]; + return mcpwm->cap_chn[channel].capn_value; } static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) @@ -1008,12 +1011,12 @@ static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) { - mcpwm->cap_cfg_ch[channel].prescale = prescale - 1; + mcpwm->cap_chn_cfg[channel].capn_prescale = prescale - 1; } static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_cfg_ch[channel].prescale + 1; + return mcpwm->cap_chn_cfg[channel].capn_prescale + 1; } #ifdef __cplusplus diff --git a/components/soc/esp32/include/soc/mcpwm_reg.h b/components/soc/esp32/include/soc/mcpwm_reg.h index e919d16a70..6a370aa691 100644 --- a/components/soc/esp32/include/soc/mcpwm_reg.h +++ b/components/soc/esp32/include/soc/mcpwm_reg.h @@ -1,3027 +1,3829 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _SOC_MCPWM_REG_H_ -#define _SOC_MCPWM_REG_H_ -#include "soc.h" +#include +#include "soc/soc.h" +#ifdef __cplusplus +extern "C" { +#endif -#define REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) +#define DR_REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) -#define MCPWM_CLK_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0000) -/* MCPWM_CLK_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1)*/ -#define MCPWM_CLK_PRESCALE 0x000000FF -#define MCPWM_CLK_PRESCALE_M ((MCPWM_CLK_PRESCALE_V)<<(MCPWM_CLK_PRESCALE_S)) -#define MCPWM_CLK_PRESCALE_V 0xFF +/** MCPWM_CLK_CFG_REG register + * PWM clock prescaler register. + */ +#define MCPWM_CLK_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x0) +/** MCPWM_CLK_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ +#define MCPWM_CLK_PRESCALE 0x000000FFU +#define MCPWM_CLK_PRESCALE_M (MCPWM_CLK_PRESCALE_V << MCPWM_CLK_PRESCALE_S) +#define MCPWM_CLK_PRESCALE_V 0x000000FFU #define MCPWM_CLK_PRESCALE_S 0 -#define MCPWM_TIMER0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0004) -/* MCPWM_TIMER0_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: Update method for active reg of PWM timer0 period 0: immediate - 1: TEZ 2: sync 3: TEZ or sync. TEZ here and below means timer equal zero event*/ -#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_M ((MCPWM_TIMER0_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER0_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER0_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: Period shadow reg of PWM timer0*/ -#define MCPWM_TIMER0_PERIOD 0x0000FFFF -#define MCPWM_TIMER0_PERIOD_M ((MCPWM_TIMER0_PERIOD_V)<<(MCPWM_TIMER0_PERIOD_S)) -#define MCPWM_TIMER0_PERIOD_V 0xFFFF -#define MCPWM_TIMER0_PERIOD_S 8 -/* MCPWM_TIMER0_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1)*/ -#define MCPWM_TIMER0_PRESCALE 0x000000FF -#define MCPWM_TIMER0_PRESCALE_M ((MCPWM_TIMER0_PRESCALE_V)<<(MCPWM_TIMER0_PRESCALE_S)) -#define MCPWM_TIMER0_PRESCALE_V 0xFF +/** MCPWM_TIMER0_CFG0_REG register + * PWM timer0 period and update method configuration register. + */ +#define MCPWM_TIMER0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4) +/** MCPWM_TIMER0_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer0 stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1) + */ +#define MCPWM_TIMER0_PRESCALE 0x000000FFU +#define MCPWM_TIMER0_PRESCALE_M (MCPWM_TIMER0_PRESCALE_V << MCPWM_TIMER0_PRESCALE_S) +#define MCPWM_TIMER0_PRESCALE_V 0x000000FFU #define MCPWM_TIMER0_PRESCALE_S 0 +/** MCPWM_TIMER0_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer0 + */ +#define MCPWM_TIMER0_PERIOD 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_M (MCPWM_TIMER0_PERIOD_V << MCPWM_TIMER0_PERIOD_S) +#define MCPWM_TIMER0_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_S 8 +/** MCPWM_TIMER0_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer0 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_M (MCPWM_TIMER0_PERIOD_UPMETHOD_V << MCPWM_TIMER0_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x0008) -/* MCPWM_TIMER0_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: PWM timer0 working mode 0: freeze 1: increase mod 2: decrease - mod 3: up-down mod*/ -#define MCPWM_TIMER0_MOD 0x00000003 -#define MCPWM_TIMER0_MOD_M ((MCPWM_TIMER0_MOD_V)<<(MCPWM_TIMER0_MOD_S)) -#define MCPWM_TIMER0_MOD_V 0x3 -#define MCPWM_TIMER0_MOD_S 3 -/* MCPWM_TIMER0_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: PWM timer0 start and stop control. 0: stop @ TEZ 1: stop @ TEP - 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP. TEP here and below means timer equal period event*/ -#define MCPWM_TIMER0_START 0x00000007 -#define MCPWM_TIMER0_START_M ((MCPWM_TIMER0_START_V)<<(MCPWM_TIMER0_START_S)) -#define MCPWM_TIMER0_START_V 0x7 +/** MCPWM_TIMER0_CFG1_REG register + * PWM timer0 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8) +/** MCPWM_TIMER0_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer0 start and stop control. 0: if PWM timer0 starts, then stops at TEZ, 1: + * if timer0 starts, then stops at TEP, 2: PWM timer0 starts and runs on, 3: timer0 + * starts and stops at the next TEZ, 4: timer0 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER0_START 0x00000007U +#define MCPWM_TIMER0_START_M (MCPWM_TIMER0_START_V << MCPWM_TIMER0_START_S) +#define MCPWM_TIMER0_START_V 0x00000007U #define MCPWM_TIMER0_START_S 0 +/** MCPWM_TIMER0_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer0 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER0_MOD 0x00000003U +#define MCPWM_TIMER0_MOD_M (MCPWM_TIMER0_MOD_V << MCPWM_TIMER0_MOD_S) +#define MCPWM_TIMER0_MOD_V 0x00000003U +#define MCPWM_TIMER0_MOD_S 3 -#define MCPWM_TIMER0_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x000c) -/* MCPWM_TIMER0_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: Phase for timer reload on sync event*/ -#define MCPWM_TIMER0_PHASE 0x0001FFFF -#define MCPWM_TIMER0_PHASE_M ((MCPWM_TIMER0_PHASE_V)<<(MCPWM_TIMER0_PHASE_S)) -#define MCPWM_TIMER0_PHASE_V 0x1FFFF -#define MCPWM_TIMER0_PHASE_S 4 -/* MCPWM_TIMER0_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: PWM timer0 synco selection 0: synci 1: TEZ 2: TEP else 0*/ -#define MCPWM_TIMER0_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER0_SYNCO_SEL_M ((MCPWM_TIMER0_SYNCO_SEL_V)<<(MCPWM_TIMER0_SYNCO_SEL_S)) -#define MCPWM_TIMER0_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER0_SYNCO_SEL_S 2 -/* MCPWM_TIMER0_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Toggling this bit will trigger a software sync*/ -#define MCPWM_TIMER0_SYNC_SW (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_V 0x1 -#define MCPWM_TIMER0_SYNC_SW_S 1 -/* MCPWM_TIMER0_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: When set timer reload with phase on sync input event is enabled*/ -#define MCPWM_TIMER0_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_V 0x1 +/** MCPWM_TIMER0_SYNC_REG register + * PWM timer0 sync function configuration register. + */ +#define MCPWM_TIMER0_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc) +/** MCPWM_TIMER0_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ +#define MCPWM_TIMER0_SYNCI_EN (BIT(0)) +#define MCPWM_TIMER0_SYNCI_EN_M (MCPWM_TIMER0_SYNCI_EN_V << MCPWM_TIMER0_SYNCI_EN_S) +#define MCPWM_TIMER0_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER0_SYNCI_EN_S 0 +/** MCPWM_TIMER0_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER0_SYNC_SW (BIT(1)) +#define MCPWM_TIMER0_SYNC_SW_M (MCPWM_TIMER0_SYNC_SW_V << MCPWM_TIMER0_SYNC_SW_S) +#define MCPWM_TIMER0_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER0_SYNC_SW_S 1 +/** MCPWM_TIMER0_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer0 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER0_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_M (MCPWM_TIMER0_SYNCO_SEL_V << MCPWM_TIMER0_SYNCO_SEL_S) +#define MCPWM_TIMER0_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_S 2 +/** MCPWM_TIMER0_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER0_PHASE 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_M (MCPWM_TIMER0_PHASE_V << MCPWM_TIMER0_PHASE_S) +#define MCPWM_TIMER0_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_S 4 +/** MCPWM_TIMER0_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer0's direction at the time sync event occurs when timer0 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER0_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER0_PHASE_DIRECTION_M (MCPWM_TIMER0_PHASE_DIRECTION_V << MCPWM_TIMER0_PHASE_DIRECTION_S) +#define MCPWM_TIMER0_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0010) -/* MCPWM_TIMER0_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Current PWM timer0 counter direction 0: increment 1: decrement*/ -#define MCPWM_TIMER0_DIRECTION (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_V 0x1 -#define MCPWM_TIMER0_DIRECTION_S 16 -/* MCPWM_TIMER0_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Current PWM timer0 counter value*/ -#define MCPWM_TIMER0_VALUE 0x0000FFFF -#define MCPWM_TIMER0_VALUE_M ((MCPWM_TIMER0_VALUE_V)<<(MCPWM_TIMER0_VALUE_S)) -#define MCPWM_TIMER0_VALUE_V 0xFFFF +/** MCPWM_TIMER0_STATUS_REG register + * PWM timer0 status register. + */ +#define MCPWM_TIMER0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10) +/** MCPWM_TIMER0_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer0 counter value + */ +#define MCPWM_TIMER0_VALUE 0x0000FFFFU +#define MCPWM_TIMER0_VALUE_M (MCPWM_TIMER0_VALUE_V << MCPWM_TIMER0_VALUE_S) +#define MCPWM_TIMER0_VALUE_V 0x0000FFFFU #define MCPWM_TIMER0_VALUE_S 0 +/** MCPWM_TIMER0_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer0 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER0_DIRECTION (BIT(16)) +#define MCPWM_TIMER0_DIRECTION_M (MCPWM_TIMER0_DIRECTION_V << MCPWM_TIMER0_DIRECTION_S) +#define MCPWM_TIMER0_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_DIRECTION_S 16 -#define MCPWM_TIMER1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0014) -/* MCPWM_TIMER1_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: Update method for active reg of PWM timer1 period 0: immediate - 1: TEZ 2: sync 3: TEZ or sync*/ -#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_M ((MCPWM_TIMER1_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER1_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER1_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: Period shadow reg of PWM timer1*/ -#define MCPWM_TIMER1_PERIOD 0x0000FFFF -#define MCPWM_TIMER1_PERIOD_M ((MCPWM_TIMER1_PERIOD_V)<<(MCPWM_TIMER1_PERIOD_S)) -#define MCPWM_TIMER1_PERIOD_V 0xFFFF -#define MCPWM_TIMER1_PERIOD_S 8 -/* MCPWM_TIMER1_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PT1_clk = Period of PWM_clk * (PWM_TIMER1_PRESCALE + 1)*/ -#define MCPWM_TIMER1_PRESCALE 0x000000FF -#define MCPWM_TIMER1_PRESCALE_M ((MCPWM_TIMER1_PRESCALE_V)<<(MCPWM_TIMER1_PRESCALE_S)) -#define MCPWM_TIMER1_PRESCALE_V 0xFF +/** MCPWM_TIMER1_CFG0_REG register + * PWM timer1 period and update method configuration register. + */ +#define MCPWM_TIMER1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x14) +/** MCPWM_TIMER1_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT1_clk, takes effect when PWM timer1 stops and starts + * agsin. period of PT1_clk = Period of PWM_clk * (PWM_TIMER1_PRESCALE + 1) + */ +#define MCPWM_TIMER1_PRESCALE 0x000000FFU +#define MCPWM_TIMER1_PRESCALE_M (MCPWM_TIMER1_PRESCALE_V << MCPWM_TIMER1_PRESCALE_S) +#define MCPWM_TIMER1_PRESCALE_V 0x000000FFU #define MCPWM_TIMER1_PRESCALE_S 0 +/** MCPWM_TIMER1_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer1 + */ +#define MCPWM_TIMER1_PERIOD 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_M (MCPWM_TIMER1_PERIOD_V << MCPWM_TIMER1_PERIOD_S) +#define MCPWM_TIMER1_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_S 8 +/** MCPWM_TIMER1_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer1 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_M (MCPWM_TIMER1_PERIOD_UPMETHOD_V << MCPWM_TIMER1_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x0018) -/* MCPWM_TIMER1_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: PWM timer1 working mode 0: freeze 1: increase mod 2: decrease - mod 3: up-down mod*/ -#define MCPWM_TIMER1_MOD 0x00000003 -#define MCPWM_TIMER1_MOD_M ((MCPWM_TIMER1_MOD_V)<<(MCPWM_TIMER1_MOD_S)) -#define MCPWM_TIMER1_MOD_V 0x3 -#define MCPWM_TIMER1_MOD_S 3 -/* MCPWM_TIMER1_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: PWM timer1 start and stop control. 0: stop @ TEZ 1: stop @ TEP - 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP.*/ -#define MCPWM_TIMER1_START 0x00000007 -#define MCPWM_TIMER1_START_M ((MCPWM_TIMER1_START_V)<<(MCPWM_TIMER1_START_S)) -#define MCPWM_TIMER1_START_V 0x7 +/** MCPWM_TIMER1_CFG1_REG register + * PWM timer1 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x18) +/** MCPWM_TIMER1_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer1 start and stop control. 0: if PWM timer1 starts, then stops at TEZ, 1: + * if timer1 starts, then stops at TEP, 2: PWM timer1 starts and runs on, 3: timer1 + * starts and stops at the next TEZ, 4: timer1 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER1_START 0x00000007U +#define MCPWM_TIMER1_START_M (MCPWM_TIMER1_START_V << MCPWM_TIMER1_START_S) +#define MCPWM_TIMER1_START_V 0x00000007U #define MCPWM_TIMER1_START_S 0 +/** MCPWM_TIMER1_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer1 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER1_MOD 0x00000003U +#define MCPWM_TIMER1_MOD_M (MCPWM_TIMER1_MOD_V << MCPWM_TIMER1_MOD_S) +#define MCPWM_TIMER1_MOD_V 0x00000003U +#define MCPWM_TIMER1_MOD_S 3 -#define MCPWM_TIMER1_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x001c) -/* MCPWM_TIMER1_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: Phase for timer reload on sync event*/ -#define MCPWM_TIMER1_PHASE 0x0001FFFF -#define MCPWM_TIMER1_PHASE_M ((MCPWM_TIMER1_PHASE_V)<<(MCPWM_TIMER1_PHASE_S)) -#define MCPWM_TIMER1_PHASE_V 0x1FFFF -#define MCPWM_TIMER1_PHASE_S 4 -/* MCPWM_TIMER1_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: PWM timer1 synco selection 0: synci 1: TEZ 2: TEP else 0*/ -#define MCPWM_TIMER1_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER1_SYNCO_SEL_M ((MCPWM_TIMER1_SYNCO_SEL_V)<<(MCPWM_TIMER1_SYNCO_SEL_S)) -#define MCPWM_TIMER1_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER1_SYNCO_SEL_S 2 -/* MCPWM_TIMER1_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Toggling this bit will trigger a software sync*/ -#define MCPWM_TIMER1_SYNC_SW (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_V 0x1 -#define MCPWM_TIMER1_SYNC_SW_S 1 -/* MCPWM_TIMER1_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: When set timer reload with phase on sync input event is enabled*/ -#define MCPWM_TIMER1_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_V 0x1 +/** MCPWM_TIMER1_SYNC_REG register + * PWM timer1 sync function configuration register. + */ +#define MCPWM_TIMER1_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x1c) +/** MCPWM_TIMER1_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ +#define MCPWM_TIMER1_SYNCI_EN (BIT(0)) +#define MCPWM_TIMER1_SYNCI_EN_M (MCPWM_TIMER1_SYNCI_EN_V << MCPWM_TIMER1_SYNCI_EN_S) +#define MCPWM_TIMER1_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER1_SYNCI_EN_S 0 +/** MCPWM_TIMER1_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER1_SYNC_SW (BIT(1)) +#define MCPWM_TIMER1_SYNC_SW_M (MCPWM_TIMER1_SYNC_SW_V << MCPWM_TIMER1_SYNC_SW_S) +#define MCPWM_TIMER1_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER1_SYNC_SW_S 1 +/** MCPWM_TIMER1_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer1 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer1_sync_sw bit + */ +#define MCPWM_TIMER1_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_M (MCPWM_TIMER1_SYNCO_SEL_V << MCPWM_TIMER1_SYNCO_SEL_S) +#define MCPWM_TIMER1_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_S 2 +/** MCPWM_TIMER1_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER1_PHASE 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_M (MCPWM_TIMER1_PHASE_V << MCPWM_TIMER1_PHASE_S) +#define MCPWM_TIMER1_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_S 4 +/** MCPWM_TIMER1_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer1's direction at the time sync event occurs when timer1 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER1_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER1_PHASE_DIRECTION_M (MCPWM_TIMER1_PHASE_DIRECTION_V << MCPWM_TIMER1_PHASE_DIRECTION_S) +#define MCPWM_TIMER1_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0020) -/* MCPWM_TIMER1_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Current PWM timer1 counter direction 0: increment 1: decrement*/ -#define MCPWM_TIMER1_DIRECTION (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_V 0x1 -#define MCPWM_TIMER1_DIRECTION_S 16 -/* MCPWM_TIMER1_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Current PWM timer1 counter value*/ -#define MCPWM_TIMER1_VALUE 0x0000FFFF -#define MCPWM_TIMER1_VALUE_M ((MCPWM_TIMER1_VALUE_V)<<(MCPWM_TIMER1_VALUE_S)) -#define MCPWM_TIMER1_VALUE_V 0xFFFF +/** MCPWM_TIMER1_STATUS_REG register + * PWM timer1 status register. + */ +#define MCPWM_TIMER1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x20) +/** MCPWM_TIMER1_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer1 counter value + */ +#define MCPWM_TIMER1_VALUE 0x0000FFFFU +#define MCPWM_TIMER1_VALUE_M (MCPWM_TIMER1_VALUE_V << MCPWM_TIMER1_VALUE_S) +#define MCPWM_TIMER1_VALUE_V 0x0000FFFFU #define MCPWM_TIMER1_VALUE_S 0 +/** MCPWM_TIMER1_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer1 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER1_DIRECTION (BIT(16)) +#define MCPWM_TIMER1_DIRECTION_M (MCPWM_TIMER1_DIRECTION_V << MCPWM_TIMER1_DIRECTION_S) +#define MCPWM_TIMER1_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_DIRECTION_S 16 -#define MCPWM_TIMER2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0024) -/* MCPWM_TIMER2_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: Update method for active reg of PWM timer2 period 0: immediate - 1: TEZ 2: sync 3: TEZ or sync*/ -#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_M ((MCPWM_TIMER2_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER2_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER2_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: Period shadow reg of PWM timer2*/ -#define MCPWM_TIMER2_PERIOD 0x0000FFFF -#define MCPWM_TIMER2_PERIOD_M ((MCPWM_TIMER2_PERIOD_V)<<(MCPWM_TIMER2_PERIOD_S)) -#define MCPWM_TIMER2_PERIOD_V 0xFFFF -#define MCPWM_TIMER2_PERIOD_S 8 -/* MCPWM_TIMER2_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PT2_clk = Period of PWM_clk * (PWM_TIMER2_PRESCALE + 1)*/ -#define MCPWM_TIMER2_PRESCALE 0x000000FF -#define MCPWM_TIMER2_PRESCALE_M ((MCPWM_TIMER2_PRESCALE_V)<<(MCPWM_TIMER2_PRESCALE_S)) -#define MCPWM_TIMER2_PRESCALE_V 0xFF +/** MCPWM_TIMER2_CFG0_REG register + * PWM timer2 period and update method configuration register. + */ +#define MCPWM_TIMER2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x24) +/** MCPWM_TIMER2_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT2_clk, takes effect when PWM timer2 stops and starts + * agsin. period of PT2_clk = Period of PWM_clk * (PWM_TIMER2_PRESCALE + 1) + */ +#define MCPWM_TIMER2_PRESCALE 0x000000FFU +#define MCPWM_TIMER2_PRESCALE_M (MCPWM_TIMER2_PRESCALE_V << MCPWM_TIMER2_PRESCALE_S) +#define MCPWM_TIMER2_PRESCALE_V 0x000000FFU #define MCPWM_TIMER2_PRESCALE_S 0 +/** MCPWM_TIMER2_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer2 + */ +#define MCPWM_TIMER2_PERIOD 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_M (MCPWM_TIMER2_PERIOD_V << MCPWM_TIMER2_PERIOD_S) +#define MCPWM_TIMER2_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_S 8 +/** MCPWM_TIMER2_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer2 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_M (MCPWM_TIMER2_PERIOD_UPMETHOD_V << MCPWM_TIMER2_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x0028) -/* MCPWM_TIMER2_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: PWM timer2 working mode 0: freeze 1: increase mod 2: decrease - mod 3: up-down mod*/ -#define MCPWM_TIMER2_MOD 0x00000003 -#define MCPWM_TIMER2_MOD_M ((MCPWM_TIMER2_MOD_V)<<(MCPWM_TIMER2_MOD_S)) -#define MCPWM_TIMER2_MOD_V 0x3 -#define MCPWM_TIMER2_MOD_S 3 -/* MCPWM_TIMER2_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: PWM timer2 start and stop control. 0: stop @ TEZ 1: stop @ TEP - 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP.*/ -#define MCPWM_TIMER2_START 0x00000007 -#define MCPWM_TIMER2_START_M ((MCPWM_TIMER2_START_V)<<(MCPWM_TIMER2_START_S)) -#define MCPWM_TIMER2_START_V 0x7 +/** MCPWM_TIMER2_CFG1_REG register + * PWM timer2 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x28) +/** MCPWM_TIMER2_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer2 start and stop control. 0: if PWM timer2 starts, then stops at TEZ, 1: + * if timer2 starts, then stops at TEP, 2: PWM timer2 starts and runs on, 3: timer2 + * starts and stops at the next TEZ, 4: timer2 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER2_START 0x00000007U +#define MCPWM_TIMER2_START_M (MCPWM_TIMER2_START_V << MCPWM_TIMER2_START_S) +#define MCPWM_TIMER2_START_V 0x00000007U #define MCPWM_TIMER2_START_S 0 +/** MCPWM_TIMER2_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer2 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER2_MOD 0x00000003U +#define MCPWM_TIMER2_MOD_M (MCPWM_TIMER2_MOD_V << MCPWM_TIMER2_MOD_S) +#define MCPWM_TIMER2_MOD_V 0x00000003U +#define MCPWM_TIMER2_MOD_S 3 -#define MCPWM_TIMER2_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x002c) -/* MCPWM_TIMER2_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: Phase for timer reload on sync event*/ -#define MCPWM_TIMER2_PHASE 0x0001FFFF -#define MCPWM_TIMER2_PHASE_M ((MCPWM_TIMER2_PHASE_V)<<(MCPWM_TIMER2_PHASE_S)) -#define MCPWM_TIMER2_PHASE_V 0x1FFFF -#define MCPWM_TIMER2_PHASE_S 4 -/* MCPWM_TIMER2_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: PWM timer2 synco selection 0: synci 1: TEZ 2: TEP else 0*/ -#define MCPWM_TIMER2_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER2_SYNCO_SEL_M ((MCPWM_TIMER2_SYNCO_SEL_V)<<(MCPWM_TIMER2_SYNCO_SEL_S)) -#define MCPWM_TIMER2_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER2_SYNCO_SEL_S 2 -/* MCPWM_TIMER2_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Toggling this bit will trigger a software sync*/ -#define MCPWM_TIMER2_SYNC_SW (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_V 0x1 -#define MCPWM_TIMER2_SYNC_SW_S 1 -/* MCPWM_TIMER2_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: When set timer reload with phase on sync input event is enabled*/ -#define MCPWM_TIMER2_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_V 0x1 +/** MCPWM_TIMER2_SYNC_REG register + * PWM timer2 sync function configuration register. + */ +#define MCPWM_TIMER2_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x2c) +/** MCPWM_TIMER2_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ +#define MCPWM_TIMER2_SYNCI_EN (BIT(0)) +#define MCPWM_TIMER2_SYNCI_EN_M (MCPWM_TIMER2_SYNCI_EN_V << MCPWM_TIMER2_SYNCI_EN_S) +#define MCPWM_TIMER2_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER2_SYNCI_EN_S 0 +/** MCPWM_TIMER2_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER2_SYNC_SW (BIT(1)) +#define MCPWM_TIMER2_SYNC_SW_M (MCPWM_TIMER2_SYNC_SW_V << MCPWM_TIMER2_SYNC_SW_S) +#define MCPWM_TIMER2_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER2_SYNC_SW_S 1 +/** MCPWM_TIMER2_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer2 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER2_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_M (MCPWM_TIMER2_SYNCO_SEL_V << MCPWM_TIMER2_SYNCO_SEL_S) +#define MCPWM_TIMER2_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_S 2 +/** MCPWM_TIMER2_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER2_PHASE 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_M (MCPWM_TIMER2_PHASE_V << MCPWM_TIMER2_PHASE_S) +#define MCPWM_TIMER2_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_S 4 +/** MCPWM_TIMER2_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer2's direction at the time sync event occurs when timer2 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER2_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER2_PHASE_DIRECTION_M (MCPWM_TIMER2_PHASE_DIRECTION_V << MCPWM_TIMER2_PHASE_DIRECTION_S) +#define MCPWM_TIMER2_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0030) -/* MCPWM_TIMER2_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Current PWM timer2 counter direction 0: increment 1: decrement*/ -#define MCPWM_TIMER2_DIRECTION (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_V 0x1 -#define MCPWM_TIMER2_DIRECTION_S 16 -/* MCPWM_TIMER2_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Current PWM timer2 counter value*/ -#define MCPWM_TIMER2_VALUE 0x0000FFFF -#define MCPWM_TIMER2_VALUE_M ((MCPWM_TIMER2_VALUE_V)<<(MCPWM_TIMER2_VALUE_S)) -#define MCPWM_TIMER2_VALUE_V 0xFFFF +/** MCPWM_TIMER2_STATUS_REG register + * PWM timer2 status register. + */ +#define MCPWM_TIMER2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x30) +/** MCPWM_TIMER2_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer2 counter value + */ +#define MCPWM_TIMER2_VALUE 0x0000FFFFU +#define MCPWM_TIMER2_VALUE_M (MCPWM_TIMER2_VALUE_V << MCPWM_TIMER2_VALUE_S) +#define MCPWM_TIMER2_VALUE_V 0x0000FFFFU #define MCPWM_TIMER2_VALUE_S 0 +/** MCPWM_TIMER2_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer2 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER2_DIRECTION (BIT(16)) +#define MCPWM_TIMER2_DIRECTION_M (MCPWM_TIMER2_DIRECTION_V << MCPWM_TIMER2_DIRECTION_S) +#define MCPWM_TIMER2_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_DIRECTION_S 16 -#define MCPWM_TIMER_SYNCI_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0034) -/* MCPWM_EXTERNAL_SYNCI2_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: Onvert SYNC2 from GPIO matrix*/ -#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -/* MCPWM_EXTERNAL_SYNCI1_INVERT : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Invert SYNC1 from GPIO matrix*/ -#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 -/* MCPWM_EXTERNAL_SYNCI0_INVERT : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Invert SYNC0 from GPIO matrix*/ -#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 -/* MCPWM_TIMER2_SYNCISEL : R/W ;bitpos:[8:6] ;default: 3'd0 ; */ -/*description: Select sync input for PWM timer2 1: PWM timer0 synco 2: PWM - timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix other values: no sync input selected*/ -#define MCPWM_TIMER2_SYNCISEL 0x00000007 -#define MCPWM_TIMER2_SYNCISEL_M ((MCPWM_TIMER2_SYNCISEL_V)<<(MCPWM_TIMER2_SYNCISEL_S)) -#define MCPWM_TIMER2_SYNCISEL_V 0x7 -#define MCPWM_TIMER2_SYNCISEL_S 6 -/* MCPWM_TIMER1_SYNCISEL : R/W ;bitpos:[5:3] ;default: 3'd0 ; */ -/*description: Select sync input for PWM timer1 1: PWM timer0 synco 2: PWM - timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix other values: no sync input selected*/ -#define MCPWM_TIMER1_SYNCISEL 0x00000007 -#define MCPWM_TIMER1_SYNCISEL_M ((MCPWM_TIMER1_SYNCISEL_V)<<(MCPWM_TIMER1_SYNCISEL_S)) -#define MCPWM_TIMER1_SYNCISEL_V 0x7 -#define MCPWM_TIMER1_SYNCISEL_S 3 -/* MCPWM_TIMER0_SYNCISEL : R/W ;bitpos:[2:0] ;default: 3'd0 ; */ -/*description: Select sync input for PWM timer0 1: PWM timer0 synco 2: PWM - timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix other values: no sync input selected*/ -#define MCPWM_TIMER0_SYNCISEL 0x00000007 -#define MCPWM_TIMER0_SYNCISEL_M ((MCPWM_TIMER0_SYNCISEL_V)<<(MCPWM_TIMER0_SYNCISEL_S)) -#define MCPWM_TIMER0_SYNCISEL_V 0x7 +/** MCPWM_TIMER_SYNCI_CFG_REG register + * Synchronization input selection for three PWM timers. + */ +#define MCPWM_TIMER_SYNCI_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x34) +/** MCPWM_TIMER0_SYNCISEL : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER0_SYNCISEL 0x00000007U +#define MCPWM_TIMER0_SYNCISEL_M (MCPWM_TIMER0_SYNCISEL_V << MCPWM_TIMER0_SYNCISEL_S) +#define MCPWM_TIMER0_SYNCISEL_V 0x00000007U #define MCPWM_TIMER0_SYNCISEL_S 0 +/** MCPWM_TIMER1_SYNCISEL : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER1_SYNCISEL 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_M (MCPWM_TIMER1_SYNCISEL_V << MCPWM_TIMER1_SYNCISEL_S) +#define MCPWM_TIMER1_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_S 3 +/** MCPWM_TIMER2_SYNCISEL : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER2_SYNCISEL 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_M (MCPWM_TIMER2_SYNCISEL_V << MCPWM_TIMER2_SYNCISEL_S) +#define MCPWM_TIMER2_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_S 6 +/** MCPWM_EXTERNAL_SYNCI0_INVERT : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (MCPWM_EXTERNAL_SYNCI0_INVERT_V << MCPWM_EXTERNAL_SYNCI0_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 +/** MCPWM_EXTERNAL_SYNCI1_INVERT : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (MCPWM_EXTERNAL_SYNCI1_INVERT_V << MCPWM_EXTERNAL_SYNCI1_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 +/** MCPWM_EXTERNAL_SYNCI2_INVERT : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (MCPWM_EXTERNAL_SYNCI2_INVERT_V << MCPWM_EXTERNAL_SYNCI2_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -#define MCPWM_OPERATOR_TIMERSEL_REG(i) (REG_MCPWM_BASE(i) + 0x0038) -/* MCPWM_OPERATOR2_TIMERSEL : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Select which PWM timer's is the timing reference for PWM operator2 - 0: timer0 1: timer1 2: timer2*/ -#define MCPWM_OPERATOR2_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR2_TIMERSEL_M ((MCPWM_OPERATOR2_TIMERSEL_V)<<(MCPWM_OPERATOR2_TIMERSEL_S)) -#define MCPWM_OPERATOR2_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR2_TIMERSEL_S 4 -/* MCPWM_OPERATOR1_TIMERSEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Select which PWM timer's is the timing reference for PWM operator1 - 0: timer0 1: timer1 2: timer2*/ -#define MCPWM_OPERATOR1_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR1_TIMERSEL_M ((MCPWM_OPERATOR1_TIMERSEL_V)<<(MCPWM_OPERATOR1_TIMERSEL_S)) -#define MCPWM_OPERATOR1_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR1_TIMERSEL_S 2 -/* MCPWM_OPERATOR0_TIMERSEL : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Select which PWM timer's is the timing reference for PWM operator0 - 0: timer0 1: timer1 2: timer2*/ -#define MCPWM_OPERATOR0_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR0_TIMERSEL_M ((MCPWM_OPERATOR0_TIMERSEL_V)<<(MCPWM_OPERATOR0_TIMERSEL_S)) -#define MCPWM_OPERATOR0_TIMERSEL_V 0x3 +/** MCPWM_OPERATOR_TIMERSEL_REG register + * Select specific timer for PWM operators. + */ +#define MCPWM_OPERATOR_TIMERSEL_REG(i) (DR_REG_MCPWM_BASE(i) + 0x38) +/** MCPWM_OPERATOR0_TIMERSEL : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR0_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR0_TIMERSEL_M (MCPWM_OPERATOR0_TIMERSEL_V << MCPWM_OPERATOR0_TIMERSEL_S) +#define MCPWM_OPERATOR0_TIMERSEL_V 0x00000003U #define MCPWM_OPERATOR0_TIMERSEL_S 0 +/** MCPWM_OPERATOR1_TIMERSEL : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR1_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_M (MCPWM_OPERATOR1_TIMERSEL_V << MCPWM_OPERATOR1_TIMERSEL_S) +#define MCPWM_OPERATOR1_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_S 2 +/** MCPWM_OPERATOR2_TIMERSEL : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR2_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_M (MCPWM_OPERATOR2_TIMERSEL_V << MCPWM_OPERATOR2_TIMERSEL_S) +#define MCPWM_OPERATOR2_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_S 4 -#define MCPWM_GEN0_STMP_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x003c) -/* MCPWM_GEN0_B_SHDW_FULL : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 0 time stamp - B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN0_B_SHDW_FULL (BIT(9)) -#define MCPWM_GEN0_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_GEN0_B_SHDW_FULL_V 0x1 -#define MCPWM_GEN0_B_SHDW_FULL_S 9 -/* MCPWM_GEN0_A_SHDW_FULL : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 0 time stamp - A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN0_A_SHDW_FULL (BIT(8)) -#define MCPWM_GEN0_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_GEN0_A_SHDW_FULL_V 0x1 -#define MCPWM_GEN0_A_SHDW_FULL_S 8 -/* MCPWM_GEN0_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 0 time stamp B's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN0_B_UPMETHOD 0x0000000F -#define MCPWM_GEN0_B_UPMETHOD_M ((MCPWM_GEN0_B_UPMETHOD_V)<<(MCPWM_GEN0_B_UPMETHOD_S)) -#define MCPWM_GEN0_B_UPMETHOD_V 0xF -#define MCPWM_GEN0_B_UPMETHOD_S 4 -/* MCPWM_GEN0_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 0 time stamp A's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN0_A_UPMETHOD 0x0000000F -#define MCPWM_GEN0_A_UPMETHOD_M ((MCPWM_GEN0_A_UPMETHOD_V)<<(MCPWM_GEN0_A_UPMETHOD_S)) -#define MCPWM_GEN0_A_UPMETHOD_V 0xF +/** MCPWM_GEN0_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN0_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x3c) +/** MCPWM_GEN0_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_A_UPMETHOD_M (MCPWM_GEN0_A_UPMETHOD_V << MCPWM_GEN0_A_UPMETHOD_S) +#define MCPWM_GEN0_A_UPMETHOD_V 0x0000000FU #define MCPWM_GEN0_A_UPMETHOD_S 0 +/** MCPWM_GEN0_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 0 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_M (MCPWM_GEN0_B_UPMETHOD_V << MCPWM_GEN0_B_UPMETHOD_S) +#define MCPWM_GEN0_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_S 4 +/** MCPWM_GEN0_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN0_A_SHDW_FULL_M (MCPWM_GEN0_A_SHDW_FULL_V << MCPWM_GEN0_A_SHDW_FULL_S) +#define MCPWM_GEN0_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_A_SHDW_FULL_S 8 +/** MCPWM_GEN0_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN0_B_SHDW_FULL_M (MCPWM_GEN0_B_SHDW_FULL_V << MCPWM_GEN0_B_SHDW_FULL_S) +#define MCPWM_GEN0_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_B_SHDW_FULL_S 9 -#define MCPWM_GEN0_TSTMP_A_REG(i) (REG_MCPWM_BASE(i) + 0x0040) -/* MCPWM_GEN0_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 0 time stamp A's shadow reg*/ -#define MCPWM_GEN0_A 0x0000FFFF -#define MCPWM_GEN0_A_M ((MCPWM_GEN0_A_V)<<(MCPWM_GEN0_A_S)) -#define MCPWM_GEN0_A_V 0xFFFF +/** MCPWM_GEN0_TSTMP_A_REG register + * PWM generator 0 shadow register for timer stamp A. + */ +#define MCPWM_GEN0_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x40) +/** MCPWM_GEN0_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp A's shadow register + */ +#define MCPWM_GEN0_A 0x0000FFFFU +#define MCPWM_GEN0_A_M (MCPWM_GEN0_A_V << MCPWM_GEN0_A_S) +#define MCPWM_GEN0_A_V 0x0000FFFFU #define MCPWM_GEN0_A_S 0 -#define MCPWM_GEN0_TSTMP_B_REG(i) (REG_MCPWM_BASE(i) + 0x0044) -/* MCPWM_GEN0_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 0 time stamp B's shadow reg*/ -#define MCPWM_GEN0_B 0x0000FFFF -#define MCPWM_GEN0_B_M ((MCPWM_GEN0_B_V)<<(MCPWM_GEN0_B_S)) -#define MCPWM_GEN0_B_V 0xFFFF +/** MCPWM_GEN0_TSTMP_B_REG register + * PWM generator 0 shadow register for timer stamp B. + */ +#define MCPWM_GEN0_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x44) +/** MCPWM_GEN0_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp B's shadow register + */ +#define MCPWM_GEN0_B 0x0000FFFFU +#define MCPWM_GEN0_B_M (MCPWM_GEN0_B_V << MCPWM_GEN0_B_S) +#define MCPWM_GEN0_B_V 0x0000FFFFU #define MCPWM_GEN0_B_S 0 -#define MCPWM_GEN0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0048) -/* MCPWM_GEN0_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: Source selection for PWM generator 0 event_t1 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN0_T1_SEL 0x00000007 -#define MCPWM_GEN0_T1_SEL_M ((MCPWM_GEN0_T1_SEL_V)<<(MCPWM_GEN0_T1_SEL_S)) -#define MCPWM_GEN0_T1_SEL_V 0x7 -#define MCPWM_GEN0_T1_SEL_S 7 -/* MCPWM_GEN0_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: Source selection for PWM generator 0 event_t0 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN0_T0_SEL 0x00000007 -#define MCPWM_GEN0_T0_SEL_M ((MCPWM_GEN0_T0_SEL_V)<<(MCPWM_GEN0_T0_SEL_S)) -#define MCPWM_GEN0_T0_SEL_V 0x7 -#define MCPWM_GEN0_T0_SEL_S 4 -/* MCPWM_GEN0_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 0's active reg of configuration. - 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: disable update*/ -#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN0_CFG_UPMETHOD_M ((MCPWM_GEN0_CFG_UPMETHOD_V)<<(MCPWM_GEN0_CFG_UPMETHOD_S)) -#define MCPWM_GEN0_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN0_CFG0_REG register + * PWM generator 0 event T0 and T1 handling + */ +#define MCPWM_GEN0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x48) +/** MCPWM_GEN0_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ +#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_CFG_UPMETHOD_M (MCPWM_GEN0_CFG_UPMETHOD_V << MCPWM_GEN0_CFG_UPMETHOD_S) +#define MCPWM_GEN0_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN0_CFG_UPMETHOD_S 0 +/** MCPWM_GEN0_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 0 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T0_SEL 0x00000007U +#define MCPWM_GEN0_T0_SEL_M (MCPWM_GEN0_T0_SEL_V << MCPWM_GEN0_T0_SEL_S) +#define MCPWM_GEN0_T0_SEL_V 0x00000007U +#define MCPWM_GEN0_T0_SEL_S 4 +/** MCPWM_GEN0_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 0 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T1_SEL 0x00000007U +#define MCPWM_GEN0_T1_SEL_M (MCPWM_GEN0_T1_SEL_V << MCPWM_GEN0_T1_SEL_S) +#define MCPWM_GEN0_T1_SEL_V 0x00000007U +#define MCPWM_GEN0_T1_SEL_S 7 -#define MCPWM_GEN0_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x004c) -/* MCPWM_GEN0_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM0B 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_NCIFORCE_MODE_M ((MCPWM_GEN0_B_NCIFORCE_MODE_V)<<(MCPWM_GEN0_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN0_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM0B a - toggle will trigger a force event*/ -#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_V 0x1 -#define MCPWM_GEN0_B_NCIFORCE_S 13 -/* MCPWM_GEN0_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM0A 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_NCIFORCE_MODE_M ((MCPWM_GEN0_A_NCIFORCE_MODE_V)<<(MCPWM_GEN0_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN0_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM0A a - toggle will trigger a force event*/ -#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_V 0x1 -#define MCPWM_GEN0_A_NCIFORCE_S 10 -/* MCPWM_GEN0_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM0B. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_M ((MCPWM_GEN0_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN0_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM0A. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_M ((MCPWM_GEN0_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: Update method for continuous software force of PWM generator0. - 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: disable update. (TEA/B here and below means an event generated when timer value equals A/B register)*/ -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN0_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN0_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN0_FORCE_REG register + * Permissives to force PWM0A and PWM0B outputs by software + */ +#define MCPWM_GEN0_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4c) +/** MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M (MCPWM_GEN0_CNTUFORCE_UPMETHOD_V << MCPWM_GEN0_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN0_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN0_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_M (MCPWM_GEN0_A_CNTUFORCE_MODE_V << MCPWM_GEN0_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN0_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_M (MCPWM_GEN0_B_CNTUFORCE_MODE_V << MCPWM_GEN0_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN0_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN0_A_NCIFORCE_M (MCPWM_GEN0_A_NCIFORCE_V << MCPWM_GEN0_A_NCIFORCE_S) +#define MCPWM_GEN0_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_A_NCIFORCE_S 10 +/** MCPWM_GEN0_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_M (MCPWM_GEN0_A_NCIFORCE_MODE_V << MCPWM_GEN0_A_NCIFORCE_MODE_S) +#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN0_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN0_B_NCIFORCE_M (MCPWM_GEN0_B_NCIFORCE_V << MCPWM_GEN0_B_NCIFORCE_S) +#define MCPWM_GEN0_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_B_NCIFORCE_S 13 +/** MCPWM_GEN0_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_M (MCPWM_GEN0_B_NCIFORCE_MODE_V << MCPWM_GEN0_B_NCIFORCE_MODE_S) +#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN0_A_REG(i) (REG_MCPWM_BASE(i) + 0x0050) -/* MCPWM_GEN0_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN0_A_DT1 0x00000003 -#define MCPWM_GEN0_A_DT1_M ((MCPWM_GEN0_A_DT1_V)<<(MCPWM_GEN0_A_DT1_S)) -#define MCPWM_GEN0_A_DT1_V 0x3 -#define MCPWM_GEN0_A_DT1_S 22 -/* MCPWM_GEN0_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN0_A_DT0 0x00000003 -#define MCPWM_GEN0_A_DT0_M ((MCPWM_GEN0_A_DT0_V)<<(MCPWM_GEN0_A_DT0_S)) -#define MCPWM_GEN0_A_DT0_V 0x3 -#define MCPWM_GEN0_A_DT0_S 20 -/* MCPWM_GEN0_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN0_A_DTEB 0x00000003 -#define MCPWM_GEN0_A_DTEB_M ((MCPWM_GEN0_A_DTEB_V)<<(MCPWM_GEN0_A_DTEB_S)) -#define MCPWM_GEN0_A_DTEB_V 0x3 -#define MCPWM_GEN0_A_DTEB_S 18 -/* MCPWM_GEN0_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN0_A_DTEA 0x00000003 -#define MCPWM_GEN0_A_DTEA_M ((MCPWM_GEN0_A_DTEA_V)<<(MCPWM_GEN0_A_DTEA_S)) -#define MCPWM_GEN0_A_DTEA_V 0x3 -#define MCPWM_GEN0_A_DTEA_S 16 -/* MCPWM_GEN0_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN0_A_DTEP 0x00000003 -#define MCPWM_GEN0_A_DTEP_M ((MCPWM_GEN0_A_DTEP_V)<<(MCPWM_GEN0_A_DTEP_S)) -#define MCPWM_GEN0_A_DTEP_V 0x3 -#define MCPWM_GEN0_A_DTEP_S 14 -/* MCPWM_GEN0_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN0_A_DTEZ 0x00000003 -#define MCPWM_GEN0_A_DTEZ_M ((MCPWM_GEN0_A_DTEZ_V)<<(MCPWM_GEN0_A_DTEZ_S)) -#define MCPWM_GEN0_A_DTEZ_V 0x3 -#define MCPWM_GEN0_A_DTEZ_S 12 -/* MCPWM_GEN0_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN0_A_UT1 0x00000003 -#define MCPWM_GEN0_A_UT1_M ((MCPWM_GEN0_A_UT1_V)<<(MCPWM_GEN0_A_UT1_S)) -#define MCPWM_GEN0_A_UT1_V 0x3 -#define MCPWM_GEN0_A_UT1_S 10 -/* MCPWM_GEN0_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN0_A_UT0 0x00000003 -#define MCPWM_GEN0_A_UT0_M ((MCPWM_GEN0_A_UT0_V)<<(MCPWM_GEN0_A_UT0_S)) -#define MCPWM_GEN0_A_UT0_V 0x3 -#define MCPWM_GEN0_A_UT0_S 8 -/* MCPWM_GEN0_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEB when timer increasing*/ -#define MCPWM_GEN0_A_UTEB 0x00000003 -#define MCPWM_GEN0_A_UTEB_M ((MCPWM_GEN0_A_UTEB_V)<<(MCPWM_GEN0_A_UTEB_S)) -#define MCPWM_GEN0_A_UTEB_V 0x3 -#define MCPWM_GEN0_A_UTEB_S 6 -/* MCPWM_GEN0_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEA when timer increasing*/ -#define MCPWM_GEN0_A_UTEA 0x00000003 -#define MCPWM_GEN0_A_UTEA_M ((MCPWM_GEN0_A_UTEA_V)<<(MCPWM_GEN0_A_UTEA_S)) -#define MCPWM_GEN0_A_UTEA_V 0x3 -#define MCPWM_GEN0_A_UTEA_S 4 -/* MCPWM_GEN0_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEP when timer increasing*/ -#define MCPWM_GEN0_A_UTEP 0x00000003 -#define MCPWM_GEN0_A_UTEP_M ((MCPWM_GEN0_A_UTEP_V)<<(MCPWM_GEN0_A_UTEP_S)) -#define MCPWM_GEN0_A_UTEP_V 0x3 -#define MCPWM_GEN0_A_UTEP_S 2 -/* MCPWM_GEN0_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN0_A_UTEZ 0x00000003 -#define MCPWM_GEN0_A_UTEZ_M ((MCPWM_GEN0_A_UTEZ_V)<<(MCPWM_GEN0_A_UTEZ_S)) -#define MCPWM_GEN0_A_UTEZ_V 0x3 +/** MCPWM_GEN0_A_REG register + * Actions triggered by events on PWM0A + */ +#define MCPWM_GEN0_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x50) +/** MCPWM_GEN0_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEZ 0x00000003U +#define MCPWM_GEN0_A_UTEZ_M (MCPWM_GEN0_A_UTEZ_V << MCPWM_GEN0_A_UTEZ_S) +#define MCPWM_GEN0_A_UTEZ_V 0x00000003U #define MCPWM_GEN0_A_UTEZ_S 0 +/** MCPWM_GEN0_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEP 0x00000003U +#define MCPWM_GEN0_A_UTEP_M (MCPWM_GEN0_A_UTEP_V << MCPWM_GEN0_A_UTEP_S) +#define MCPWM_GEN0_A_UTEP_V 0x00000003U +#define MCPWM_GEN0_A_UTEP_S 2 +/** MCPWM_GEN0_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEA 0x00000003U +#define MCPWM_GEN0_A_UTEA_M (MCPWM_GEN0_A_UTEA_V << MCPWM_GEN0_A_UTEA_S) +#define MCPWM_GEN0_A_UTEA_V 0x00000003U +#define MCPWM_GEN0_A_UTEA_S 4 +/** MCPWM_GEN0_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEB 0x00000003U +#define MCPWM_GEN0_A_UTEB_M (MCPWM_GEN0_A_UTEB_V << MCPWM_GEN0_A_UTEB_S) +#define MCPWM_GEN0_A_UTEB_V 0x00000003U +#define MCPWM_GEN0_A_UTEB_S 6 +/** MCPWM_GEN0_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT0 0x00000003U +#define MCPWM_GEN0_A_UT0_M (MCPWM_GEN0_A_UT0_V << MCPWM_GEN0_A_UT0_S) +#define MCPWM_GEN0_A_UT0_V 0x00000003U +#define MCPWM_GEN0_A_UT0_S 8 +/** MCPWM_GEN0_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT1 0x00000003U +#define MCPWM_GEN0_A_UT1_M (MCPWM_GEN0_A_UT1_V << MCPWM_GEN0_A_UT1_S) +#define MCPWM_GEN0_A_UT1_V 0x00000003U +#define MCPWM_GEN0_A_UT1_S 10 +/** MCPWM_GEN0_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEZ 0x00000003U +#define MCPWM_GEN0_A_DTEZ_M (MCPWM_GEN0_A_DTEZ_V << MCPWM_GEN0_A_DTEZ_S) +#define MCPWM_GEN0_A_DTEZ_V 0x00000003U +#define MCPWM_GEN0_A_DTEZ_S 12 +/** MCPWM_GEN0_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEP 0x00000003U +#define MCPWM_GEN0_A_DTEP_M (MCPWM_GEN0_A_DTEP_V << MCPWM_GEN0_A_DTEP_S) +#define MCPWM_GEN0_A_DTEP_V 0x00000003U +#define MCPWM_GEN0_A_DTEP_S 14 +/** MCPWM_GEN0_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEA 0x00000003U +#define MCPWM_GEN0_A_DTEA_M (MCPWM_GEN0_A_DTEA_V << MCPWM_GEN0_A_DTEA_S) +#define MCPWM_GEN0_A_DTEA_V 0x00000003U +#define MCPWM_GEN0_A_DTEA_S 16 +/** MCPWM_GEN0_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEB 0x00000003U +#define MCPWM_GEN0_A_DTEB_M (MCPWM_GEN0_A_DTEB_V << MCPWM_GEN0_A_DTEB_S) +#define MCPWM_GEN0_A_DTEB_V 0x00000003U +#define MCPWM_GEN0_A_DTEB_S 18 +/** MCPWM_GEN0_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT0 0x00000003U +#define MCPWM_GEN0_A_DT0_M (MCPWM_GEN0_A_DT0_V << MCPWM_GEN0_A_DT0_S) +#define MCPWM_GEN0_A_DT0_V 0x00000003U +#define MCPWM_GEN0_A_DT0_S 20 +/** MCPWM_GEN0_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT1 0x00000003U +#define MCPWM_GEN0_A_DT1_M (MCPWM_GEN0_A_DT1_V << MCPWM_GEN0_A_DT1_S) +#define MCPWM_GEN0_A_DT1_V 0x00000003U +#define MCPWM_GEN0_A_DT1_S 22 -#define MCPWM_GEN0_B_REG(i) (REG_MCPWM_BASE(i) + 0x0054) -/* MCPWM_GEN0_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN0_B_DT1 0x00000003 -#define MCPWM_GEN0_B_DT1_M ((MCPWM_GEN0_B_DT1_V)<<(MCPWM_GEN0_B_DT1_S)) -#define MCPWM_GEN0_B_DT1_V 0x3 -#define MCPWM_GEN0_B_DT1_S 22 -/* MCPWM_GEN0_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN0_B_DT0 0x00000003 -#define MCPWM_GEN0_B_DT0_M ((MCPWM_GEN0_B_DT0_V)<<(MCPWM_GEN0_B_DT0_S)) -#define MCPWM_GEN0_B_DT0_V 0x3 -#define MCPWM_GEN0_B_DT0_S 20 -/* MCPWM_GEN0_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN0_B_DTEB 0x00000003 -#define MCPWM_GEN0_B_DTEB_M ((MCPWM_GEN0_B_DTEB_V)<<(MCPWM_GEN0_B_DTEB_S)) -#define MCPWM_GEN0_B_DTEB_V 0x3 -#define MCPWM_GEN0_B_DTEB_S 18 -/* MCPWM_GEN0_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN0_B_DTEA 0x00000003 -#define MCPWM_GEN0_B_DTEA_M ((MCPWM_GEN0_B_DTEA_V)<<(MCPWM_GEN0_B_DTEA_S)) -#define MCPWM_GEN0_B_DTEA_V 0x3 -#define MCPWM_GEN0_B_DTEA_S 16 -/* MCPWM_GEN0_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN0_B_DTEP 0x00000003 -#define MCPWM_GEN0_B_DTEP_M ((MCPWM_GEN0_B_DTEP_V)<<(MCPWM_GEN0_B_DTEP_S)) -#define MCPWM_GEN0_B_DTEP_V 0x3 -#define MCPWM_GEN0_B_DTEP_S 14 -/* MCPWM_GEN0_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN0_B_DTEZ 0x00000003 -#define MCPWM_GEN0_B_DTEZ_M ((MCPWM_GEN0_B_DTEZ_V)<<(MCPWM_GEN0_B_DTEZ_S)) -#define MCPWM_GEN0_B_DTEZ_V 0x3 -#define MCPWM_GEN0_B_DTEZ_S 12 -/* MCPWM_GEN0_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN0_B_UT1 0x00000003 -#define MCPWM_GEN0_B_UT1_M ((MCPWM_GEN0_B_UT1_V)<<(MCPWM_GEN0_B_UT1_S)) -#define MCPWM_GEN0_B_UT1_V 0x3 -#define MCPWM_GEN0_B_UT1_S 10 -/* MCPWM_GEN0_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN0_B_UT0 0x00000003 -#define MCPWM_GEN0_B_UT0_M ((MCPWM_GEN0_B_UT0_V)<<(MCPWM_GEN0_B_UT0_S)) -#define MCPWM_GEN0_B_UT0_V 0x3 -#define MCPWM_GEN0_B_UT0_S 8 -/* MCPWM_GEN0_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEB when timer increasing*/ -#define MCPWM_GEN0_B_UTEB 0x00000003 -#define MCPWM_GEN0_B_UTEB_M ((MCPWM_GEN0_B_UTEB_V)<<(MCPWM_GEN0_B_UTEB_S)) -#define MCPWM_GEN0_B_UTEB_V 0x3 -#define MCPWM_GEN0_B_UTEB_S 6 -/* MCPWM_GEN0_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEA when timer increasing*/ -#define MCPWM_GEN0_B_UTEA 0x00000003 -#define MCPWM_GEN0_B_UTEA_M ((MCPWM_GEN0_B_UTEA_V)<<(MCPWM_GEN0_B_UTEA_S)) -#define MCPWM_GEN0_B_UTEA_V 0x3 -#define MCPWM_GEN0_B_UTEA_S 4 -/* MCPWM_GEN0_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEP when timer increasing*/ -#define MCPWM_GEN0_B_UTEP 0x00000003 -#define MCPWM_GEN0_B_UTEP_M ((MCPWM_GEN0_B_UTEP_V)<<(MCPWM_GEN0_B_UTEP_S)) -#define MCPWM_GEN0_B_UTEP_V 0x3 -#define MCPWM_GEN0_B_UTEP_S 2 -/* MCPWM_GEN0_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN0_B_UTEZ 0x00000003 -#define MCPWM_GEN0_B_UTEZ_M ((MCPWM_GEN0_B_UTEZ_V)<<(MCPWM_GEN0_B_UTEZ_S)) -#define MCPWM_GEN0_B_UTEZ_V 0x3 +/** MCPWM_GEN0_B_REG register + * Actions triggered by events on PWM0B + */ +#define MCPWM_GEN0_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x54) +/** MCPWM_GEN0_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEZ 0x00000003U +#define MCPWM_GEN0_B_UTEZ_M (MCPWM_GEN0_B_UTEZ_V << MCPWM_GEN0_B_UTEZ_S) +#define MCPWM_GEN0_B_UTEZ_V 0x00000003U #define MCPWM_GEN0_B_UTEZ_S 0 +/** MCPWM_GEN0_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEP 0x00000003U +#define MCPWM_GEN0_B_UTEP_M (MCPWM_GEN0_B_UTEP_V << MCPWM_GEN0_B_UTEP_S) +#define MCPWM_GEN0_B_UTEP_V 0x00000003U +#define MCPWM_GEN0_B_UTEP_S 2 +/** MCPWM_GEN0_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEA 0x00000003U +#define MCPWM_GEN0_B_UTEA_M (MCPWM_GEN0_B_UTEA_V << MCPWM_GEN0_B_UTEA_S) +#define MCPWM_GEN0_B_UTEA_V 0x00000003U +#define MCPWM_GEN0_B_UTEA_S 4 +/** MCPWM_GEN0_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEB 0x00000003U +#define MCPWM_GEN0_B_UTEB_M (MCPWM_GEN0_B_UTEB_V << MCPWM_GEN0_B_UTEB_S) +#define MCPWM_GEN0_B_UTEB_V 0x00000003U +#define MCPWM_GEN0_B_UTEB_S 6 +/** MCPWM_GEN0_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT0 0x00000003U +#define MCPWM_GEN0_B_UT0_M (MCPWM_GEN0_B_UT0_V << MCPWM_GEN0_B_UT0_S) +#define MCPWM_GEN0_B_UT0_V 0x00000003U +#define MCPWM_GEN0_B_UT0_S 8 +/** MCPWM_GEN0_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT1 0x00000003U +#define MCPWM_GEN0_B_UT1_M (MCPWM_GEN0_B_UT1_V << MCPWM_GEN0_B_UT1_S) +#define MCPWM_GEN0_B_UT1_V 0x00000003U +#define MCPWM_GEN0_B_UT1_S 10 +/** MCPWM_GEN0_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEZ 0x00000003U +#define MCPWM_GEN0_B_DTEZ_M (MCPWM_GEN0_B_DTEZ_V << MCPWM_GEN0_B_DTEZ_S) +#define MCPWM_GEN0_B_DTEZ_V 0x00000003U +#define MCPWM_GEN0_B_DTEZ_S 12 +/** MCPWM_GEN0_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEP 0x00000003U +#define MCPWM_GEN0_B_DTEP_M (MCPWM_GEN0_B_DTEP_V << MCPWM_GEN0_B_DTEP_S) +#define MCPWM_GEN0_B_DTEP_V 0x00000003U +#define MCPWM_GEN0_B_DTEP_S 14 +/** MCPWM_GEN0_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEA 0x00000003U +#define MCPWM_GEN0_B_DTEA_M (MCPWM_GEN0_B_DTEA_V << MCPWM_GEN0_B_DTEA_S) +#define MCPWM_GEN0_B_DTEA_V 0x00000003U +#define MCPWM_GEN0_B_DTEA_S 16 +/** MCPWM_GEN0_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEB 0x00000003U +#define MCPWM_GEN0_B_DTEB_M (MCPWM_GEN0_B_DTEB_V << MCPWM_GEN0_B_DTEB_S) +#define MCPWM_GEN0_B_DTEB_V 0x00000003U +#define MCPWM_GEN0_B_DTEB_S 18 +/** MCPWM_GEN0_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT0 0x00000003U +#define MCPWM_GEN0_B_DT0_M (MCPWM_GEN0_B_DT0_V << MCPWM_GEN0_B_DT0_S) +#define MCPWM_GEN0_B_DT0_V 0x00000003U +#define MCPWM_GEN0_B_DT0_S 20 +/** MCPWM_GEN0_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT1 0x00000003U +#define MCPWM_GEN0_B_DT1_M (MCPWM_GEN0_B_DT1_V << MCPWM_GEN0_B_DT1_S) +#define MCPWM_GEN0_B_DT1_V 0x00000003U +#define MCPWM_GEN0_B_DT1_S 22 -#define MCPWM_DT0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0058) -/* MCPWM_DT0_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Dead time generator 0 clock selection. 0: PWM_clk 1: PT_clk*/ -#define MCPWM_DT0_CLK_SEL (BIT(17)) -#define MCPWM_DT0_CLK_SEL_M (BIT(17)) -#define MCPWM_DT0_CLK_SEL_V 0x1 -#define MCPWM_DT0_CLK_SEL_S 17 -/* MCPWM_DT0_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: S0 in documentation*/ -#define MCPWM_DT0_B_OUTBYPASS (BIT(16)) -#define MCPWM_DT0_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DT0_B_OUTBYPASS_V 0x1 -#define MCPWM_DT0_B_OUTBYPASS_S 16 -/* MCPWM_DT0_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: S1 in documentation*/ -#define MCPWM_DT0_A_OUTBYPASS (BIT(15)) -#define MCPWM_DT0_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DT0_A_OUTBYPASS_V 0x1 -#define MCPWM_DT0_A_OUTBYPASS_S 15 -/* MCPWM_DT0_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: S3 in documentation*/ -#define MCPWM_DT0_FED_OUTINVERT (BIT(14)) -#define MCPWM_DT0_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DT0_FED_OUTINVERT_V 0x1 -#define MCPWM_DT0_FED_OUTINVERT_S 14 -/* MCPWM_DT0_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: S2 in documentation*/ -#define MCPWM_DT0_RED_OUTINVERT (BIT(13)) -#define MCPWM_DT0_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DT0_RED_OUTINVERT_V 0x1 -#define MCPWM_DT0_RED_OUTINVERT_S 13 -/* MCPWM_DT0_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: S5 in documentation*/ -#define MCPWM_DT0_FED_INSEL (BIT(12)) -#define MCPWM_DT0_FED_INSEL_M (BIT(12)) -#define MCPWM_DT0_FED_INSEL_V 0x1 -#define MCPWM_DT0_FED_INSEL_S 12 -/* MCPWM_DT0_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: S4 in documentation*/ -#define MCPWM_DT0_RED_INSEL (BIT(11)) -#define MCPWM_DT0_RED_INSEL_M (BIT(11)) -#define MCPWM_DT0_RED_INSEL_V 0x1 -#define MCPWM_DT0_RED_INSEL_S 11 -/* MCPWM_DT0_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: S7 in documentation*/ -#define MCPWM_DT0_B_OUTSWAP (BIT(10)) -#define MCPWM_DT0_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DT0_B_OUTSWAP_V 0x1 -#define MCPWM_DT0_B_OUTSWAP_S 10 -/* MCPWM_DT0_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: S6 in documentation*/ -#define MCPWM_DT0_A_OUTSWAP (BIT(9)) -#define MCPWM_DT0_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DT0_A_OUTSWAP_V 0x1 -#define MCPWM_DT0_A_OUTSWAP_S 9 -/* MCPWM_DT0_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: S8 in documentation dual-edge B mode 0: FED/RED take effect - on different path separately 1: FED/RED take effect on B path A out is in bypass or normal operation mode*/ -#define MCPWM_DT0_DEB_MODE (BIT(8)) -#define MCPWM_DT0_DEB_MODE_M (BIT(8)) -#define MCPWM_DT0_DEB_MODE_V 0x1 -#define MCPWM_DT0_DEB_MODE_S 8 -/* MCPWM_DT0_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for RED (rising edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT0_RED_UPMETHOD 0x0000000F -#define MCPWM_DT0_RED_UPMETHOD_M ((MCPWM_DT0_RED_UPMETHOD_V)<<(MCPWM_DT0_RED_UPMETHOD_S)) -#define MCPWM_DT0_RED_UPMETHOD_V 0xF -#define MCPWM_DT0_RED_UPMETHOD_S 4 -/* MCPWM_DT0_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for FED (falling edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT0_FED_UPMETHOD 0x0000000F -#define MCPWM_DT0_FED_UPMETHOD_M ((MCPWM_DT0_FED_UPMETHOD_V)<<(MCPWM_DT0_FED_UPMETHOD_S)) -#define MCPWM_DT0_FED_UPMETHOD_V 0xF +/** MCPWM_DT0_CFG_REG register + * PWM generator 0 dead time type selection and configuration + */ +#define MCPWM_DT0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x58) +/** MCPWM_DT0_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_FED_UPMETHOD_M (MCPWM_DT0_FED_UPMETHOD_V << MCPWM_DT0_FED_UPMETHOD_S) +#define MCPWM_DT0_FED_UPMETHOD_V 0x0000000FU #define MCPWM_DT0_FED_UPMETHOD_S 0 +/** MCPWM_DT0_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_M (MCPWM_DT0_RED_UPMETHOD_V << MCPWM_DT0_RED_UPMETHOD_S) +#define MCPWM_DT0_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_S 4 +/** MCPWM_DT0_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT0_DEB_MODE (BIT(8)) +#define MCPWM_DT0_DEB_MODE_M (MCPWM_DT0_DEB_MODE_V << MCPWM_DT0_DEB_MODE_S) +#define MCPWM_DT0_DEB_MODE_V 0x00000001U +#define MCPWM_DT0_DEB_MODE_S 8 +/** MCPWM_DT0_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT0_A_OUTSWAP (BIT(9)) +#define MCPWM_DT0_A_OUTSWAP_M (MCPWM_DT0_A_OUTSWAP_V << MCPWM_DT0_A_OUTSWAP_S) +#define MCPWM_DT0_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_A_OUTSWAP_S 9 +/** MCPWM_DT0_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT0_B_OUTSWAP (BIT(10)) +#define MCPWM_DT0_B_OUTSWAP_M (MCPWM_DT0_B_OUTSWAP_V << MCPWM_DT0_B_OUTSWAP_S) +#define MCPWM_DT0_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_B_OUTSWAP_S 10 +/** MCPWM_DT0_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT0_RED_INSEL (BIT(11)) +#define MCPWM_DT0_RED_INSEL_M (MCPWM_DT0_RED_INSEL_V << MCPWM_DT0_RED_INSEL_S) +#define MCPWM_DT0_RED_INSEL_V 0x00000001U +#define MCPWM_DT0_RED_INSEL_S 11 +/** MCPWM_DT0_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT0_FED_INSEL (BIT(12)) +#define MCPWM_DT0_FED_INSEL_M (MCPWM_DT0_FED_INSEL_V << MCPWM_DT0_FED_INSEL_S) +#define MCPWM_DT0_FED_INSEL_V 0x00000001U +#define MCPWM_DT0_FED_INSEL_S 12 +/** MCPWM_DT0_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT0_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT0_RED_OUTINVERT_M (MCPWM_DT0_RED_OUTINVERT_V << MCPWM_DT0_RED_OUTINVERT_S) +#define MCPWM_DT0_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_RED_OUTINVERT_S 13 +/** MCPWM_DT0_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT0_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT0_FED_OUTINVERT_M (MCPWM_DT0_FED_OUTINVERT_V << MCPWM_DT0_FED_OUTINVERT_S) +#define MCPWM_DT0_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_FED_OUTINVERT_S 14 +/** MCPWM_DT0_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT0_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT0_A_OUTBYPASS_M (MCPWM_DT0_A_OUTBYPASS_V << MCPWM_DT0_A_OUTBYPASS_S) +#define MCPWM_DT0_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_A_OUTBYPASS_S 15 +/** MCPWM_DT0_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT0_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT0_B_OUTBYPASS_M (MCPWM_DT0_B_OUTBYPASS_V << MCPWM_DT0_B_OUTBYPASS_S) +#define MCPWM_DT0_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_B_OUTBYPASS_S 16 +/** MCPWM_DT0_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT0_CLK_SEL (BIT(17)) +#define MCPWM_DT0_CLK_SEL_M (MCPWM_DT0_CLK_SEL_V << MCPWM_DT0_CLK_SEL_S) +#define MCPWM_DT0_CLK_SEL_V 0x00000001U +#define MCPWM_DT0_CLK_SEL_S 17 -#define MCPWM_DT0_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x005c) -/* MCPWM_DT0_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for FED*/ -#define MCPWM_DT0_FED 0x0000FFFF -#define MCPWM_DT0_FED_M ((MCPWM_DT0_FED_V)<<(MCPWM_DT0_FED_S)) -#define MCPWM_DT0_FED_V 0xFFFF +/** MCPWM_DT0_FED_CFG_REG register + * PWM generator 0 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT0_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x5c) +/** MCPWM_DT0_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT0_FED 0x0000FFFFU +#define MCPWM_DT0_FED_M (MCPWM_DT0_FED_V << MCPWM_DT0_FED_S) +#define MCPWM_DT0_FED_V 0x0000FFFFU #define MCPWM_DT0_FED_S 0 -#define MCPWM_DT0_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0060) -/* MCPWM_DT0_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for RED*/ -#define MCPWM_DT0_RED 0x0000FFFF -#define MCPWM_DT0_RED_M ((MCPWM_DT0_RED_V)<<(MCPWM_DT0_RED_S)) -#define MCPWM_DT0_RED_V 0xFFFF +/** MCPWM_DT0_RED_CFG_REG register + * PWM generator 0 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT0_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x60) +/** MCPWM_DT0_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT0_RED 0x0000FFFFU +#define MCPWM_DT0_RED_M (MCPWM_DT0_RED_V << MCPWM_DT0_RED_S) +#define MCPWM_DT0_RED_V 0x0000FFFFU #define MCPWM_DT0_RED_S 0 -#define MCPWM_CARRIER0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0064) -/* MCPWM_CARRIER0_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: When set invert the input of PWM0A and PWM0B for this submodule*/ -#define MCPWM_CARRIER0_IN_INVERT (BIT(13)) -#define MCPWM_CARRIER0_IN_INVERT_M (BIT(13)) -#define MCPWM_CARRIER0_IN_INVERT_V 0x1 -#define MCPWM_CARRIER0_IN_INVERT_S 13 -/* MCPWM_CARRIER0_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: When set invert the output of PWM0A and PWM0B for this submodule*/ -#define MCPWM_CARRIER0_OUT_INVERT (BIT(12)) -#define MCPWM_CARRIER0_OUT_INVERT_M (BIT(12)) -#define MCPWM_CARRIER0_OUT_INVERT_V 0x1 -#define MCPWM_CARRIER0_OUT_INVERT_S 12 -/* MCPWM_CARRIER0_OSHWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: Width of the fist pulse in number of periods of the carrier*/ -#define MCPWM_CARRIER0_OSHWTH 0x0000000F -#define MCPWM_CARRIER0_OSHWTH_M ((MCPWM_CARRIER0_OSHWTH_V)<<(MCPWM_CARRIER0_OSHWTH_S)) -#define MCPWM_CARRIER0_OSHWTH_V 0xF -#define MCPWM_CARRIER0_OSHWTH_S 8 -/* MCPWM_CARRIER0_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: Carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8*/ -#define MCPWM_CARRIER0_DUTY 0x00000007 -#define MCPWM_CARRIER0_DUTY_M ((MCPWM_CARRIER0_DUTY_V)<<(MCPWM_CARRIER0_DUTY_S)) -#define MCPWM_CARRIER0_DUTY_V 0x7 -#define MCPWM_CARRIER0_DUTY_S 5 -/* MCPWM_CARRIER0_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk - = period of PWM_clk * (PWM_CARRIER0_PRESCALE + 1)*/ -#define MCPWM_CARRIER0_PRESCALE 0x0000000F -#define MCPWM_CARRIER0_PRESCALE_M ((MCPWM_CARRIER0_PRESCALE_V)<<(MCPWM_CARRIER0_PRESCALE_S)) -#define MCPWM_CARRIER0_PRESCALE_V 0xF -#define MCPWM_CARRIER0_PRESCALE_S 1 -/* MCPWM_CARRIER0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set carrier0 function is enabled. When cleared carrier0 is bypassed*/ -#define MCPWM_CARRIER0_EN (BIT(0)) -#define MCPWM_CARRIER0_EN_M (BIT(0)) -#define MCPWM_CARRIER0_EN_V 0x1 +/** MCPWM_CARRIER0_CFG_REG register + * PWM generator 0 carrier enable and configuratoin + */ +#define MCPWM_CARRIER0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x64) +/** MCPWM_CARRIER0_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier0 function is enabled. When cleared, carrier0 is bypassed + */ +#define MCPWM_CARRIER0_EN (BIT(0)) +#define MCPWM_CARRIER0_EN_M (MCPWM_CARRIER0_EN_V << MCPWM_CARRIER0_EN_S) +#define MCPWM_CARRIER0_EN_V 0x00000001U #define MCPWM_CARRIER0_EN_S 0 +/** MCPWM_CARRIER0_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER0_PRESCALE 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_M (MCPWM_CARRIER0_PRESCALE_V << MCPWM_CARRIER0_PRESCALE_S) +#define MCPWM_CARRIER0_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_S 1 +/** MCPWM_CARRIER0_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER0_DUTY 0x00000007U +#define MCPWM_CARRIER0_DUTY_M (MCPWM_CARRIER0_DUTY_V << MCPWM_CARRIER0_DUTY_S) +#define MCPWM_CARRIER0_DUTY_V 0x00000007U +#define MCPWM_CARRIER0_DUTY_S 5 +/** MCPWM_CARRIER0_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER0_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_M (MCPWM_CARRIER0_OSHTWTH_V << MCPWM_CARRIER0_OSHTWTH_S) +#define MCPWM_CARRIER0_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_S 8 +/** MCPWM_CARRIER0_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER0_OUT_INVERT_M (MCPWM_CARRIER0_OUT_INVERT_V << MCPWM_CARRIER0_OUT_INVERT_S) +#define MCPWM_CARRIER0_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_OUT_INVERT_S 12 +/** MCPWM_CARRIER0_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER0_IN_INVERT_M (MCPWM_CARRIER0_IN_INVERT_V << MCPWM_CARRIER0_IN_INVERT_S) +#define MCPWM_CARRIER0_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_IN_INVERT_S 13 -#define MCPWM_FH0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0068) -/* MCPWM_FH0_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0B when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_OST_U 0x00000003 -#define MCPWM_FH0_B_OST_U_M ((MCPWM_FH0_B_OST_U_V)<<(MCPWM_FH0_B_OST_U_S)) -#define MCPWM_FH0_B_OST_U_V 0x3 -#define MCPWM_FH0_B_OST_U_S 22 -/* MCPWM_FH0_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0B when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_OST_D 0x00000003 -#define MCPWM_FH0_B_OST_D_M ((MCPWM_FH0_B_OST_D_V)<<(MCPWM_FH0_B_OST_D_S)) -#define MCPWM_FH0_B_OST_D_V 0x3 -#define MCPWM_FH0_B_OST_D_S 20 -/* MCPWM_FH0_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0B when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_CBC_U 0x00000003 -#define MCPWM_FH0_B_CBC_U_M ((MCPWM_FH0_B_CBC_U_V)<<(MCPWM_FH0_B_CBC_U_S)) -#define MCPWM_FH0_B_CBC_U_V 0x3 -#define MCPWM_FH0_B_CBC_U_S 18 -/* MCPWM_FH0_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0B when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_CBC_D 0x00000003 -#define MCPWM_FH0_B_CBC_D_M ((MCPWM_FH0_B_CBC_D_V)<<(MCPWM_FH0_B_CBC_D_S)) -#define MCPWM_FH0_B_CBC_D_V 0x3 -#define MCPWM_FH0_B_CBC_D_S 16 -/* MCPWM_FH0_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0A when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_OST_U 0x00000003 -#define MCPWM_FH0_A_OST_U_M ((MCPWM_FH0_A_OST_U_V)<<(MCPWM_FH0_A_OST_U_S)) -#define MCPWM_FH0_A_OST_U_V 0x3 -#define MCPWM_FH0_A_OST_U_S 14 -/* MCPWM_FH0_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0A when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_OST_D 0x00000003 -#define MCPWM_FH0_A_OST_D_M ((MCPWM_FH0_A_OST_D_V)<<(MCPWM_FH0_A_OST_D_S)) -#define MCPWM_FH0_A_OST_D_V 0x3 -#define MCPWM_FH0_A_OST_D_S 12 -/* MCPWM_FH0_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0A when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_CBC_U 0x00000003 -#define MCPWM_FH0_A_CBC_U_M ((MCPWM_FH0_A_CBC_U_V)<<(MCPWM_FH0_A_CBC_U_S)) -#define MCPWM_FH0_A_CBC_U_V 0x3 -#define MCPWM_FH0_A_CBC_U_S 10 -/* MCPWM_FH0_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0A when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_CBC_D 0x00000003 -#define MCPWM_FH0_A_CBC_D_M ((MCPWM_FH0_A_CBC_D_V)<<(MCPWM_FH0_A_CBC_D_S)) -#define MCPWM_FH0_A_CBC_D_V 0x3 -#define MCPWM_FH0_A_CBC_D_S 8 -/* MCPWM_FH0_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: event_f0 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F0_OST (BIT(7)) -#define MCPWM_FH0_F0_OST_M (BIT(7)) -#define MCPWM_FH0_F0_OST_V 0x1 -#define MCPWM_FH0_F0_OST_S 7 -/* MCPWM_FH0_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: event_f1 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F1_OST (BIT(6)) -#define MCPWM_FH0_F1_OST_M (BIT(6)) -#define MCPWM_FH0_F1_OST_V 0x1 -#define MCPWM_FH0_F1_OST_S 6 -/* MCPWM_FH0_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: event_f2 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F2_OST (BIT(5)) -#define MCPWM_FH0_F2_OST_M (BIT(5)) -#define MCPWM_FH0_F2_OST_V 0x1 -#define MCPWM_FH0_F2_OST_S 5 -/* MCPWM_FH0_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Enable register for software force one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_SW_OST (BIT(4)) -#define MCPWM_FH0_SW_OST_M (BIT(4)) -#define MCPWM_FH0_SW_OST_V 0x1 -#define MCPWM_FH0_SW_OST_S 4 -/* MCPWM_FH0_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: event_f0 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F0_CBC (BIT(3)) -#define MCPWM_FH0_F0_CBC_M (BIT(3)) -#define MCPWM_FH0_F0_CBC_V 0x1 -#define MCPWM_FH0_F0_CBC_S 3 -/* MCPWM_FH0_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: event_f1 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F1_CBC (BIT(2)) -#define MCPWM_FH0_F1_CBC_M (BIT(2)) -#define MCPWM_FH0_F1_CBC_V 0x1 -#define MCPWM_FH0_F1_CBC_S 2 -/* MCPWM_FH0_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: event_f2 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F2_CBC (BIT(1)) -#define MCPWM_FH0_F2_CBC_M (BIT(1)) -#define MCPWM_FH0_F2_CBC_V 0x1 -#define MCPWM_FH0_F2_CBC_S 1 -/* MCPWM_FH0_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Enable register for software force cycle-by-cycle mode action. - 0: disable 1: enable*/ -#define MCPWM_FH0_SW_CBC (BIT(0)) -#define MCPWM_FH0_SW_CBC_M (BIT(0)) -#define MCPWM_FH0_SW_CBC_V 0x1 +/** MCPWM_FH0_CFG0_REG register + * Actions on PWM0A and PWM0B trip events + */ +#define MCPWM_FH0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x68) +/** MCPWM_FH0_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_CBC (BIT(0)) +#define MCPWM_FH0_SW_CBC_M (MCPWM_FH0_SW_CBC_V << MCPWM_FH0_SW_CBC_S) +#define MCPWM_FH0_SW_CBC_V 0x00000001U #define MCPWM_FH0_SW_CBC_S 0 +/** MCPWM_FH0_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_CBC (BIT(1)) +#define MCPWM_FH0_F2_CBC_M (MCPWM_FH0_F2_CBC_V << MCPWM_FH0_F2_CBC_S) +#define MCPWM_FH0_F2_CBC_V 0x00000001U +#define MCPWM_FH0_F2_CBC_S 1 +/** MCPWM_FH0_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_CBC (BIT(2)) +#define MCPWM_FH0_F1_CBC_M (MCPWM_FH0_F1_CBC_V << MCPWM_FH0_F1_CBC_S) +#define MCPWM_FH0_F1_CBC_V 0x00000001U +#define MCPWM_FH0_F1_CBC_S 2 +/** MCPWM_FH0_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_CBC (BIT(3)) +#define MCPWM_FH0_F0_CBC_M (MCPWM_FH0_F0_CBC_V << MCPWM_FH0_F0_CBC_S) +#define MCPWM_FH0_F0_CBC_V 0x00000001U +#define MCPWM_FH0_F0_CBC_S 3 +/** MCPWM_FH0_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_OST (BIT(4)) +#define MCPWM_FH0_SW_OST_M (MCPWM_FH0_SW_OST_V << MCPWM_FH0_SW_OST_S) +#define MCPWM_FH0_SW_OST_V 0x00000001U +#define MCPWM_FH0_SW_OST_S 4 +/** MCPWM_FH0_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_OST (BIT(5)) +#define MCPWM_FH0_F2_OST_M (MCPWM_FH0_F2_OST_V << MCPWM_FH0_F2_OST_S) +#define MCPWM_FH0_F2_OST_V 0x00000001U +#define MCPWM_FH0_F2_OST_S 5 +/** MCPWM_FH0_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_OST (BIT(6)) +#define MCPWM_FH0_F1_OST_M (MCPWM_FH0_F1_OST_V << MCPWM_FH0_F1_OST_S) +#define MCPWM_FH0_F1_OST_V 0x00000001U +#define MCPWM_FH0_F1_OST_S 6 +/** MCPWM_FH0_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_OST (BIT(7)) +#define MCPWM_FH0_F0_OST_M (MCPWM_FH0_F0_OST_V << MCPWM_FH0_F0_OST_S) +#define MCPWM_FH0_F0_OST_V 0x00000001U +#define MCPWM_FH0_F0_OST_S 7 +/** MCPWM_FH0_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_D 0x00000003U +#define MCPWM_FH0_A_CBC_D_M (MCPWM_FH0_A_CBC_D_V << MCPWM_FH0_A_CBC_D_S) +#define MCPWM_FH0_A_CBC_D_V 0x00000003U +#define MCPWM_FH0_A_CBC_D_S 8 +/** MCPWM_FH0_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_U 0x00000003U +#define MCPWM_FH0_A_CBC_U_M (MCPWM_FH0_A_CBC_U_V << MCPWM_FH0_A_CBC_U_S) +#define MCPWM_FH0_A_CBC_U_V 0x00000003U +#define MCPWM_FH0_A_CBC_U_S 10 +/** MCPWM_FH0_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_D 0x00000003U +#define MCPWM_FH0_A_OST_D_M (MCPWM_FH0_A_OST_D_V << MCPWM_FH0_A_OST_D_S) +#define MCPWM_FH0_A_OST_D_V 0x00000003U +#define MCPWM_FH0_A_OST_D_S 12 +/** MCPWM_FH0_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_U 0x00000003U +#define MCPWM_FH0_A_OST_U_M (MCPWM_FH0_A_OST_U_V << MCPWM_FH0_A_OST_U_S) +#define MCPWM_FH0_A_OST_U_V 0x00000003U +#define MCPWM_FH0_A_OST_U_S 14 +/** MCPWM_FH0_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_D 0x00000003U +#define MCPWM_FH0_B_CBC_D_M (MCPWM_FH0_B_CBC_D_V << MCPWM_FH0_B_CBC_D_S) +#define MCPWM_FH0_B_CBC_D_V 0x00000003U +#define MCPWM_FH0_B_CBC_D_S 16 +/** MCPWM_FH0_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_U 0x00000003U +#define MCPWM_FH0_B_CBC_U_M (MCPWM_FH0_B_CBC_U_V << MCPWM_FH0_B_CBC_U_S) +#define MCPWM_FH0_B_CBC_U_V 0x00000003U +#define MCPWM_FH0_B_CBC_U_S 18 +/** MCPWM_FH0_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_D 0x00000003U +#define MCPWM_FH0_B_OST_D_M (MCPWM_FH0_B_OST_D_V << MCPWM_FH0_B_OST_D_S) +#define MCPWM_FH0_B_OST_D_V 0x00000003U +#define MCPWM_FH0_B_OST_D_S 20 +/** MCPWM_FH0_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_U 0x00000003U +#define MCPWM_FH0_B_OST_U_M (MCPWM_FH0_B_OST_U_V << MCPWM_FH0_B_OST_U_S) +#define MCPWM_FH0_B_OST_U_V 0x00000003U +#define MCPWM_FH0_B_OST_U_S 22 -#define MCPWM_FH0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x006c) -/* MCPWM_FH0_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) triggers a - one-shot mode action*/ -#define MCPWM_FH0_FORCE_OST (BIT(4)) -#define MCPWM_FH0_FORCE_OST_M (BIT(4)) -#define MCPWM_FH0_FORCE_OST_V 0x1 -#define MCPWM_FH0_FORCE_OST_S 4 -/* MCPWM_FH0_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle triggers a cycle-by-cycle mode action*/ -#define MCPWM_FH0_FORCE_CBC (BIT(3)) -#define MCPWM_FH0_FORCE_CBC_M (BIT(3)) -#define MCPWM_FH0_FORCE_CBC_V 0x1 -#define MCPWM_FH0_FORCE_CBC_S 3 -/* MCPWM_FH0_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: The cycle-by-cycle mode action refresh moment selection. Bit0: TEZ bit1:TEP*/ -#define MCPWM_FH0_CBCPULSE 0x00000003 -#define MCPWM_FH0_CBCPULSE_M ((MCPWM_FH0_CBCPULSE_V)<<(MCPWM_FH0_CBCPULSE_S)) -#define MCPWM_FH0_CBCPULSE_V 0x3 -#define MCPWM_FH0_CBCPULSE_S 1 -/* MCPWM_FH0_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: A toggle will clear on going one-shot mode action*/ -#define MCPWM_FH0_CLR_OST (BIT(0)) -#define MCPWM_FH0_CLR_OST_M (BIT(0)) -#define MCPWM_FH0_CLR_OST_V 0x1 +/** MCPWM_FH0_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x6c) +/** MCPWM_FH0_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH0_CLR_OST (BIT(0)) +#define MCPWM_FH0_CLR_OST_M (MCPWM_FH0_CLR_OST_V << MCPWM_FH0_CLR_OST_S) +#define MCPWM_FH0_CLR_OST_V 0x00000001U #define MCPWM_FH0_CLR_OST_S 0 +/** MCPWM_FH0_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ +#define MCPWM_FH0_CBCPULSE 0x00000003U +#define MCPWM_FH0_CBCPULSE_M (MCPWM_FH0_CBCPULSE_V << MCPWM_FH0_CBCPULSE_S) +#define MCPWM_FH0_CBCPULSE_V 0x00000003U +#define MCPWM_FH0_CBCPULSE_S 1 +/** MCPWM_FH0_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH0_FORCE_CBC (BIT(3)) +#define MCPWM_FH0_FORCE_CBC_M (MCPWM_FH0_FORCE_CBC_V << MCPWM_FH0_FORCE_CBC_S) +#define MCPWM_FH0_FORCE_CBC_V 0x00000001U +#define MCPWM_FH0_FORCE_CBC_S 3 +/** MCPWM_FH0_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH0_FORCE_OST (BIT(4)) +#define MCPWM_FH0_FORCE_OST_M (MCPWM_FH0_FORCE_OST_V << MCPWM_FH0_FORCE_OST_S) +#define MCPWM_FH0_FORCE_OST_V 0x00000001U +#define MCPWM_FH0_FORCE_OST_S 4 -#define MCPWM_FH0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0070) -/* MCPWM_FH0_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an one-shot mode action is on going*/ -#define MCPWM_FH0_OST_ON (BIT(1)) -#define MCPWM_FH0_OST_ON_M (BIT(1)) -#define MCPWM_FH0_OST_ON_V 0x1 -#define MCPWM_FH0_OST_ON_S 1 -/* MCPWM_FH0_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an cycle-by-cycle mode action is on going*/ -#define MCPWM_FH0_CBC_ON (BIT(0)) -#define MCPWM_FH0_CBC_ON_M (BIT(0)) -#define MCPWM_FH0_CBC_ON_V 0x1 +/** MCPWM_FH0_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x70) +/** MCPWM_FH0_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH0_CBC_ON (BIT(0)) +#define MCPWM_FH0_CBC_ON_M (MCPWM_FH0_CBC_ON_V << MCPWM_FH0_CBC_ON_S) +#define MCPWM_FH0_CBC_ON_V 0x00000001U #define MCPWM_FH0_CBC_ON_S 0 +/** MCPWM_FH0_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH0_OST_ON (BIT(1)) +#define MCPWM_FH0_OST_ON_M (MCPWM_FH0_OST_ON_V << MCPWM_FH0_OST_ON_S) +#define MCPWM_FH0_OST_ON_V 0x00000001U +#define MCPWM_FH0_OST_ON_S 1 -#define MCPWM_GEN1_STMP_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0074) -/* MCPWM_GEN1_B_SHDW_FULL : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 1 time stamp - B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN1_B_SHDW_FULL (BIT(9)) -#define MCPWM_GEN1_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_GEN1_B_SHDW_FULL_V 0x1 -#define MCPWM_GEN1_B_SHDW_FULL_S 9 -/* MCPWM_GEN1_A_SHDW_FULL : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 1 time stamp - A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN1_A_SHDW_FULL (BIT(8)) -#define MCPWM_GEN1_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_GEN1_A_SHDW_FULL_V 0x1 -#define MCPWM_GEN1_A_SHDW_FULL_S 8 -/* MCPWM_GEN1_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 1 time stamp B's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN1_B_UPMETHOD 0x0000000F -#define MCPWM_GEN1_B_UPMETHOD_M ((MCPWM_GEN1_B_UPMETHOD_V)<<(MCPWM_GEN1_B_UPMETHOD_S)) -#define MCPWM_GEN1_B_UPMETHOD_V 0xF -#define MCPWM_GEN1_B_UPMETHOD_S 4 -/* MCPWM_GEN1_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 1 time stamp A's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN1_A_UPMETHOD 0x0000000F -#define MCPWM_GEN1_A_UPMETHOD_M ((MCPWM_GEN1_A_UPMETHOD_V)<<(MCPWM_GEN1_A_UPMETHOD_S)) -#define MCPWM_GEN1_A_UPMETHOD_V 0xF +/** MCPWM_GEN1_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN1_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x74) +/** MCPWM_GEN1_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_A_UPMETHOD_M (MCPWM_GEN1_A_UPMETHOD_V << MCPWM_GEN1_A_UPMETHOD_S) +#define MCPWM_GEN1_A_UPMETHOD_V 0x0000000FU #define MCPWM_GEN1_A_UPMETHOD_S 0 +/** MCPWM_GEN1_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 1 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_M (MCPWM_GEN1_B_UPMETHOD_V << MCPWM_GEN1_B_UPMETHOD_S) +#define MCPWM_GEN1_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_S 4 +/** MCPWM_GEN1_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN1_A_SHDW_FULL_M (MCPWM_GEN1_A_SHDW_FULL_V << MCPWM_GEN1_A_SHDW_FULL_S) +#define MCPWM_GEN1_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_A_SHDW_FULL_S 8 +/** MCPWM_GEN1_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN1_B_SHDW_FULL_M (MCPWM_GEN1_B_SHDW_FULL_V << MCPWM_GEN1_B_SHDW_FULL_S) +#define MCPWM_GEN1_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_B_SHDW_FULL_S 9 -#define MCPWM_GEN1_TSTMP_A_REG(i) (REG_MCPWM_BASE(i) + 0x0078) -/* MCPWM_GEN1_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 1 time stamp A's shadow reg*/ -#define MCPWM_GEN1_A 0x0000FFFF -#define MCPWM_GEN1_A_M ((MCPWM_GEN1_A_V)<<(MCPWM_GEN1_A_S)) -#define MCPWM_GEN1_A_V 0xFFFF +/** MCPWM_GEN1_TSTMP_A_REG register + * PWM generator 1 shadow register for timer stamp A. + */ +#define MCPWM_GEN1_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x78) +/** MCPWM_GEN1_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp A's shadow register + */ +#define MCPWM_GEN1_A 0x0000FFFFU +#define MCPWM_GEN1_A_M (MCPWM_GEN1_A_V << MCPWM_GEN1_A_S) +#define MCPWM_GEN1_A_V 0x0000FFFFU #define MCPWM_GEN1_A_S 0 -#define MCPWM_GEN1_TSTMP_B_REG(i) (REG_MCPWM_BASE(i) + 0x007c) -/* MCPWM_GEN1_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 1 time stamp B's shadow reg*/ -#define MCPWM_GEN1_B 0x0000FFFF -#define MCPWM_GEN1_B_M ((MCPWM_GEN1_B_V)<<(MCPWM_GEN1_B_S)) -#define MCPWM_GEN1_B_V 0xFFFF +/** MCPWM_GEN1_TSTMP_B_REG register + * PWM generator 1 shadow register for timer stamp B. + */ +#define MCPWM_GEN1_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x7c) +/** MCPWM_GEN1_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp B's shadow register + */ +#define MCPWM_GEN1_B 0x0000FFFFU +#define MCPWM_GEN1_B_M (MCPWM_GEN1_B_V << MCPWM_GEN1_B_S) +#define MCPWM_GEN1_B_V 0x0000FFFFU #define MCPWM_GEN1_B_S 0 -#define MCPWM_GEN1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0080) -/* MCPWM_GEN1_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate1 event_t1 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN1_T1_SEL 0x00000007 -#define MCPWM_GEN1_T1_SEL_M ((MCPWM_GEN1_T1_SEL_V)<<(MCPWM_GEN1_T1_SEL_S)) -#define MCPWM_GEN1_T1_SEL_V 0x7 -#define MCPWM_GEN1_T1_SEL_S 7 -/* MCPWM_GEN1_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate1 event_t0 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN1_T0_SEL 0x00000007 -#define MCPWM_GEN1_T0_SEL_M ((MCPWM_GEN1_T0_SEL_V)<<(MCPWM_GEN1_T0_SEL_S)) -#define MCPWM_GEN1_T0_SEL_V 0x7 -#define MCPWM_GEN1_T0_SEL_S 4 -/* MCPWM_GEN1_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generate1's active reg of configuration. - 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: disable update*/ -#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN1_CFG_UPMETHOD_M ((MCPWM_GEN1_CFG_UPMETHOD_V)<<(MCPWM_GEN1_CFG_UPMETHOD_S)) -#define MCPWM_GEN1_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN1_CFG0_REG register + * PWM generator 1 event T0 and T1 handling + */ +#define MCPWM_GEN1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x80) +/** MCPWM_GEN1_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:sync;when bit3 is set to 1:disable the update. + */ +#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_CFG_UPMETHOD_M (MCPWM_GEN1_CFG_UPMETHOD_V << MCPWM_GEN1_CFG_UPMETHOD_S) +#define MCPWM_GEN1_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN1_CFG_UPMETHOD_S 0 +/** MCPWM_GEN1_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 1 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T0_SEL 0x00000007U +#define MCPWM_GEN1_T0_SEL_M (MCPWM_GEN1_T0_SEL_V << MCPWM_GEN1_T0_SEL_S) +#define MCPWM_GEN1_T0_SEL_V 0x00000007U +#define MCPWM_GEN1_T0_SEL_S 4 +/** MCPWM_GEN1_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 1 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T1_SEL 0x00000007U +#define MCPWM_GEN1_T1_SEL_M (MCPWM_GEN1_T1_SEL_V << MCPWM_GEN1_T1_SEL_S) +#define MCPWM_GEN1_T1_SEL_V 0x00000007U +#define MCPWM_GEN1_T1_SEL_S 7 -#define MCPWM_GEN1_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x0084) -/* MCPWM_GEN1_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM1B 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_NCIFORCE_MODE_M ((MCPWM_GEN1_B_NCIFORCE_MODE_V)<<(MCPWM_GEN1_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN1_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM1B a - toggle will trigger a force event*/ -#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_V 0x1 -#define MCPWM_GEN1_B_NCIFORCE_S 13 -/* MCPWM_GEN1_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM1A 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_NCIFORCE_MODE_M ((MCPWM_GEN1_A_NCIFORCE_MODE_V)<<(MCPWM_GEN1_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN1_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM1A a - toggle will trigger a force event*/ -#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_V 0x1 -#define MCPWM_GEN1_A_NCIFORCE_S 10 -/* MCPWM_GEN1_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM1B. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_M ((MCPWM_GEN1_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN1_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM1A. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_M ((MCPWM_GEN1_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: Update method for continuous software force of PWM generator1. - 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: disable update. (TEA/B here and below means an event generated when timer value equals A/B register)*/ -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN1_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN1_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN1_FORCE_REG register + * Permissives to force PWM1A and PWM1B outputs by software + */ +#define MCPWM_GEN1_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x84) +/** MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 1. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M (MCPWM_GEN1_CNTUFORCE_UPMETHOD_V << MCPWM_GEN1_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN1_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN1_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM1A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_M (MCPWM_GEN1_A_CNTUFORCE_MODE_V << MCPWM_GEN1_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN1_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM1B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_M (MCPWM_GEN1_B_CNTUFORCE_MODE_V << MCPWM_GEN1_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN1_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN1_A_NCIFORCE_M (MCPWM_GEN1_A_NCIFORCE_V << MCPWM_GEN1_A_NCIFORCE_S) +#define MCPWM_GEN1_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_A_NCIFORCE_S 10 +/** MCPWM_GEN1_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM1A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_M (MCPWM_GEN1_A_NCIFORCE_MODE_V << MCPWM_GEN1_A_NCIFORCE_MODE_S) +#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN1_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN1_B_NCIFORCE_M (MCPWM_GEN1_B_NCIFORCE_V << MCPWM_GEN1_B_NCIFORCE_S) +#define MCPWM_GEN1_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_B_NCIFORCE_S 13 +/** MCPWM_GEN1_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM1B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_M (MCPWM_GEN1_B_NCIFORCE_MODE_V << MCPWM_GEN1_B_NCIFORCE_MODE_S) +#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN1_A_REG(i) (REG_MCPWM_BASE(i) + 0x0088) -/* MCPWM_GEN1_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN1_A_DT1 0x00000003 -#define MCPWM_GEN1_A_DT1_M ((MCPWM_GEN1_A_DT1_V)<<(MCPWM_GEN1_A_DT1_S)) -#define MCPWM_GEN1_A_DT1_V 0x3 -#define MCPWM_GEN1_A_DT1_S 22 -/* MCPWM_GEN1_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN1_A_DT0 0x00000003 -#define MCPWM_GEN1_A_DT0_M ((MCPWM_GEN1_A_DT0_V)<<(MCPWM_GEN1_A_DT0_S)) -#define MCPWM_GEN1_A_DT0_V 0x3 -#define MCPWM_GEN1_A_DT0_S 20 -/* MCPWM_GEN1_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN1_A_DTEB 0x00000003 -#define MCPWM_GEN1_A_DTEB_M ((MCPWM_GEN1_A_DTEB_V)<<(MCPWM_GEN1_A_DTEB_S)) -#define MCPWM_GEN1_A_DTEB_V 0x3 -#define MCPWM_GEN1_A_DTEB_S 18 -/* MCPWM_GEN1_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN1_A_DTEA 0x00000003 -#define MCPWM_GEN1_A_DTEA_M ((MCPWM_GEN1_A_DTEA_V)<<(MCPWM_GEN1_A_DTEA_S)) -#define MCPWM_GEN1_A_DTEA_V 0x3 -#define MCPWM_GEN1_A_DTEA_S 16 -/* MCPWM_GEN1_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN1_A_DTEP 0x00000003 -#define MCPWM_GEN1_A_DTEP_M ((MCPWM_GEN1_A_DTEP_V)<<(MCPWM_GEN1_A_DTEP_S)) -#define MCPWM_GEN1_A_DTEP_V 0x3 -#define MCPWM_GEN1_A_DTEP_S 14 -/* MCPWM_GEN1_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN1_A_DTEZ 0x00000003 -#define MCPWM_GEN1_A_DTEZ_M ((MCPWM_GEN1_A_DTEZ_V)<<(MCPWM_GEN1_A_DTEZ_S)) -#define MCPWM_GEN1_A_DTEZ_V 0x3 -#define MCPWM_GEN1_A_DTEZ_S 12 -/* MCPWM_GEN1_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN1_A_UT1 0x00000003 -#define MCPWM_GEN1_A_UT1_M ((MCPWM_GEN1_A_UT1_V)<<(MCPWM_GEN1_A_UT1_S)) -#define MCPWM_GEN1_A_UT1_V 0x3 -#define MCPWM_GEN1_A_UT1_S 10 -/* MCPWM_GEN1_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN1_A_UT0 0x00000003 -#define MCPWM_GEN1_A_UT0_M ((MCPWM_GEN1_A_UT0_V)<<(MCPWM_GEN1_A_UT0_S)) -#define MCPWM_GEN1_A_UT0_V 0x3 -#define MCPWM_GEN1_A_UT0_S 8 -/* MCPWM_GEN1_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEB when timer increasing*/ -#define MCPWM_GEN1_A_UTEB 0x00000003 -#define MCPWM_GEN1_A_UTEB_M ((MCPWM_GEN1_A_UTEB_V)<<(MCPWM_GEN1_A_UTEB_S)) -#define MCPWM_GEN1_A_UTEB_V 0x3 -#define MCPWM_GEN1_A_UTEB_S 6 -/* MCPWM_GEN1_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEA when timer increasing*/ -#define MCPWM_GEN1_A_UTEA 0x00000003 -#define MCPWM_GEN1_A_UTEA_M ((MCPWM_GEN1_A_UTEA_V)<<(MCPWM_GEN1_A_UTEA_S)) -#define MCPWM_GEN1_A_UTEA_V 0x3 -#define MCPWM_GEN1_A_UTEA_S 4 -/* MCPWM_GEN1_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEP when timer increasing*/ -#define MCPWM_GEN1_A_UTEP 0x00000003 -#define MCPWM_GEN1_A_UTEP_M ((MCPWM_GEN1_A_UTEP_V)<<(MCPWM_GEN1_A_UTEP_S)) -#define MCPWM_GEN1_A_UTEP_V 0x3 -#define MCPWM_GEN1_A_UTEP_S 2 -/* MCPWM_GEN1_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN1_A_UTEZ 0x00000003 -#define MCPWM_GEN1_A_UTEZ_M ((MCPWM_GEN1_A_UTEZ_V)<<(MCPWM_GEN1_A_UTEZ_S)) -#define MCPWM_GEN1_A_UTEZ_V 0x3 +/** MCPWM_GEN1_A_REG register + * Actions triggered by events on PWM1A + */ +#define MCPWM_GEN1_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x88) +/** MCPWM_GEN1_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEZ 0x00000003U +#define MCPWM_GEN1_A_UTEZ_M (MCPWM_GEN1_A_UTEZ_V << MCPWM_GEN1_A_UTEZ_S) +#define MCPWM_GEN1_A_UTEZ_V 0x00000003U #define MCPWM_GEN1_A_UTEZ_S 0 +/** MCPWM_GEN1_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEP 0x00000003U +#define MCPWM_GEN1_A_UTEP_M (MCPWM_GEN1_A_UTEP_V << MCPWM_GEN1_A_UTEP_S) +#define MCPWM_GEN1_A_UTEP_V 0x00000003U +#define MCPWM_GEN1_A_UTEP_S 2 +/** MCPWM_GEN1_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEA 0x00000003U +#define MCPWM_GEN1_A_UTEA_M (MCPWM_GEN1_A_UTEA_V << MCPWM_GEN1_A_UTEA_S) +#define MCPWM_GEN1_A_UTEA_V 0x00000003U +#define MCPWM_GEN1_A_UTEA_S 4 +/** MCPWM_GEN1_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEB 0x00000003U +#define MCPWM_GEN1_A_UTEB_M (MCPWM_GEN1_A_UTEB_V << MCPWM_GEN1_A_UTEB_S) +#define MCPWM_GEN1_A_UTEB_V 0x00000003U +#define MCPWM_GEN1_A_UTEB_S 6 +/** MCPWM_GEN1_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT0 0x00000003U +#define MCPWM_GEN1_A_UT0_M (MCPWM_GEN1_A_UT0_V << MCPWM_GEN1_A_UT0_S) +#define MCPWM_GEN1_A_UT0_V 0x00000003U +#define MCPWM_GEN1_A_UT0_S 8 +/** MCPWM_GEN1_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT1 0x00000003U +#define MCPWM_GEN1_A_UT1_M (MCPWM_GEN1_A_UT1_V << MCPWM_GEN1_A_UT1_S) +#define MCPWM_GEN1_A_UT1_V 0x00000003U +#define MCPWM_GEN1_A_UT1_S 10 +/** MCPWM_GEN1_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEZ 0x00000003U +#define MCPWM_GEN1_A_DTEZ_M (MCPWM_GEN1_A_DTEZ_V << MCPWM_GEN1_A_DTEZ_S) +#define MCPWM_GEN1_A_DTEZ_V 0x00000003U +#define MCPWM_GEN1_A_DTEZ_S 12 +/** MCPWM_GEN1_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEP 0x00000003U +#define MCPWM_GEN1_A_DTEP_M (MCPWM_GEN1_A_DTEP_V << MCPWM_GEN1_A_DTEP_S) +#define MCPWM_GEN1_A_DTEP_V 0x00000003U +#define MCPWM_GEN1_A_DTEP_S 14 +/** MCPWM_GEN1_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEA 0x00000003U +#define MCPWM_GEN1_A_DTEA_M (MCPWM_GEN1_A_DTEA_V << MCPWM_GEN1_A_DTEA_S) +#define MCPWM_GEN1_A_DTEA_V 0x00000003U +#define MCPWM_GEN1_A_DTEA_S 16 +/** MCPWM_GEN1_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEB 0x00000003U +#define MCPWM_GEN1_A_DTEB_M (MCPWM_GEN1_A_DTEB_V << MCPWM_GEN1_A_DTEB_S) +#define MCPWM_GEN1_A_DTEB_V 0x00000003U +#define MCPWM_GEN1_A_DTEB_S 18 +/** MCPWM_GEN1_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT0 0x00000003U +#define MCPWM_GEN1_A_DT0_M (MCPWM_GEN1_A_DT0_V << MCPWM_GEN1_A_DT0_S) +#define MCPWM_GEN1_A_DT0_V 0x00000003U +#define MCPWM_GEN1_A_DT0_S 20 +/** MCPWM_GEN1_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT1 0x00000003U +#define MCPWM_GEN1_A_DT1_M (MCPWM_GEN1_A_DT1_V << MCPWM_GEN1_A_DT1_S) +#define MCPWM_GEN1_A_DT1_V 0x00000003U +#define MCPWM_GEN1_A_DT1_S 22 -#define MCPWM_GEN1_B_REG(i) (REG_MCPWM_BASE(i) + 0x008c) -/* MCPWM_GEN1_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN1_B_DT1 0x00000003 -#define MCPWM_GEN1_B_DT1_M ((MCPWM_GEN1_B_DT1_V)<<(MCPWM_GEN1_B_DT1_S)) -#define MCPWM_GEN1_B_DT1_V 0x3 -#define MCPWM_GEN1_B_DT1_S 22 -/* MCPWM_GEN1_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN1_B_DT0 0x00000003 -#define MCPWM_GEN1_B_DT0_M ((MCPWM_GEN1_B_DT0_V)<<(MCPWM_GEN1_B_DT0_S)) -#define MCPWM_GEN1_B_DT0_V 0x3 -#define MCPWM_GEN1_B_DT0_S 20 -/* MCPWM_GEN1_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN1_B_DTEB 0x00000003 -#define MCPWM_GEN1_B_DTEB_M ((MCPWM_GEN1_B_DTEB_V)<<(MCPWM_GEN1_B_DTEB_S)) -#define MCPWM_GEN1_B_DTEB_V 0x3 -#define MCPWM_GEN1_B_DTEB_S 18 -/* MCPWM_GEN1_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN1_B_DTEA 0x00000003 -#define MCPWM_GEN1_B_DTEA_M ((MCPWM_GEN1_B_DTEA_V)<<(MCPWM_GEN1_B_DTEA_S)) -#define MCPWM_GEN1_B_DTEA_V 0x3 -#define MCPWM_GEN1_B_DTEA_S 16 -/* MCPWM_GEN1_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN1_B_DTEP 0x00000003 -#define MCPWM_GEN1_B_DTEP_M ((MCPWM_GEN1_B_DTEP_V)<<(MCPWM_GEN1_B_DTEP_S)) -#define MCPWM_GEN1_B_DTEP_V 0x3 -#define MCPWM_GEN1_B_DTEP_S 14 -/* MCPWM_GEN1_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN1_B_DTEZ 0x00000003 -#define MCPWM_GEN1_B_DTEZ_M ((MCPWM_GEN1_B_DTEZ_V)<<(MCPWM_GEN1_B_DTEZ_S)) -#define MCPWM_GEN1_B_DTEZ_V 0x3 -#define MCPWM_GEN1_B_DTEZ_S 12 -/* MCPWM_GEN1_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN1_B_UT1 0x00000003 -#define MCPWM_GEN1_B_UT1_M ((MCPWM_GEN1_B_UT1_V)<<(MCPWM_GEN1_B_UT1_S)) -#define MCPWM_GEN1_B_UT1_V 0x3 -#define MCPWM_GEN1_B_UT1_S 10 -/* MCPWM_GEN1_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN1_B_UT0 0x00000003 -#define MCPWM_GEN1_B_UT0_M ((MCPWM_GEN1_B_UT0_V)<<(MCPWM_GEN1_B_UT0_S)) -#define MCPWM_GEN1_B_UT0_V 0x3 -#define MCPWM_GEN1_B_UT0_S 8 -/* MCPWM_GEN1_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEB when timer increasing*/ -#define MCPWM_GEN1_B_UTEB 0x00000003 -#define MCPWM_GEN1_B_UTEB_M ((MCPWM_GEN1_B_UTEB_V)<<(MCPWM_GEN1_B_UTEB_S)) -#define MCPWM_GEN1_B_UTEB_V 0x3 -#define MCPWM_GEN1_B_UTEB_S 6 -/* MCPWM_GEN1_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEA when timer increasing*/ -#define MCPWM_GEN1_B_UTEA 0x00000003 -#define MCPWM_GEN1_B_UTEA_M ((MCPWM_GEN1_B_UTEA_V)<<(MCPWM_GEN1_B_UTEA_S)) -#define MCPWM_GEN1_B_UTEA_V 0x3 -#define MCPWM_GEN1_B_UTEA_S 4 -/* MCPWM_GEN1_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEP when timer increasing*/ -#define MCPWM_GEN1_B_UTEP 0x00000003 -#define MCPWM_GEN1_B_UTEP_M ((MCPWM_GEN1_B_UTEP_V)<<(MCPWM_GEN1_B_UTEP_S)) -#define MCPWM_GEN1_B_UTEP_V 0x3 -#define MCPWM_GEN1_B_UTEP_S 2 -/* MCPWM_GEN1_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN1_B_UTEZ 0x00000003 -#define MCPWM_GEN1_B_UTEZ_M ((MCPWM_GEN1_B_UTEZ_V)<<(MCPWM_GEN1_B_UTEZ_S)) -#define MCPWM_GEN1_B_UTEZ_V 0x3 +/** MCPWM_GEN1_B_REG register + * Actions triggered by events on PWM1B + */ +#define MCPWM_GEN1_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8c) +/** MCPWM_GEN1_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEZ 0x00000003U +#define MCPWM_GEN1_B_UTEZ_M (MCPWM_GEN1_B_UTEZ_V << MCPWM_GEN1_B_UTEZ_S) +#define MCPWM_GEN1_B_UTEZ_V 0x00000003U #define MCPWM_GEN1_B_UTEZ_S 0 +/** MCPWM_GEN1_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEP 0x00000003U +#define MCPWM_GEN1_B_UTEP_M (MCPWM_GEN1_B_UTEP_V << MCPWM_GEN1_B_UTEP_S) +#define MCPWM_GEN1_B_UTEP_V 0x00000003U +#define MCPWM_GEN1_B_UTEP_S 2 +/** MCPWM_GEN1_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEA 0x00000003U +#define MCPWM_GEN1_B_UTEA_M (MCPWM_GEN1_B_UTEA_V << MCPWM_GEN1_B_UTEA_S) +#define MCPWM_GEN1_B_UTEA_V 0x00000003U +#define MCPWM_GEN1_B_UTEA_S 4 +/** MCPWM_GEN1_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEB 0x00000003U +#define MCPWM_GEN1_B_UTEB_M (MCPWM_GEN1_B_UTEB_V << MCPWM_GEN1_B_UTEB_S) +#define MCPWM_GEN1_B_UTEB_V 0x00000003U +#define MCPWM_GEN1_B_UTEB_S 6 +/** MCPWM_GEN1_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT0 0x00000003U +#define MCPWM_GEN1_B_UT0_M (MCPWM_GEN1_B_UT0_V << MCPWM_GEN1_B_UT0_S) +#define MCPWM_GEN1_B_UT0_V 0x00000003U +#define MCPWM_GEN1_B_UT0_S 8 +/** MCPWM_GEN1_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT1 0x00000003U +#define MCPWM_GEN1_B_UT1_M (MCPWM_GEN1_B_UT1_V << MCPWM_GEN1_B_UT1_S) +#define MCPWM_GEN1_B_UT1_V 0x00000003U +#define MCPWM_GEN1_B_UT1_S 10 +/** MCPWM_GEN1_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEZ 0x00000003U +#define MCPWM_GEN1_B_DTEZ_M (MCPWM_GEN1_B_DTEZ_V << MCPWM_GEN1_B_DTEZ_S) +#define MCPWM_GEN1_B_DTEZ_V 0x00000003U +#define MCPWM_GEN1_B_DTEZ_S 12 +/** MCPWM_GEN1_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEP 0x00000003U +#define MCPWM_GEN1_B_DTEP_M (MCPWM_GEN1_B_DTEP_V << MCPWM_GEN1_B_DTEP_S) +#define MCPWM_GEN1_B_DTEP_V 0x00000003U +#define MCPWM_GEN1_B_DTEP_S 14 +/** MCPWM_GEN1_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEA 0x00000003U +#define MCPWM_GEN1_B_DTEA_M (MCPWM_GEN1_B_DTEA_V << MCPWM_GEN1_B_DTEA_S) +#define MCPWM_GEN1_B_DTEA_V 0x00000003U +#define MCPWM_GEN1_B_DTEA_S 16 +/** MCPWM_GEN1_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEB 0x00000003U +#define MCPWM_GEN1_B_DTEB_M (MCPWM_GEN1_B_DTEB_V << MCPWM_GEN1_B_DTEB_S) +#define MCPWM_GEN1_B_DTEB_V 0x00000003U +#define MCPWM_GEN1_B_DTEB_S 18 +/** MCPWM_GEN1_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT0 0x00000003U +#define MCPWM_GEN1_B_DT0_M (MCPWM_GEN1_B_DT0_V << MCPWM_GEN1_B_DT0_S) +#define MCPWM_GEN1_B_DT0_V 0x00000003U +#define MCPWM_GEN1_B_DT0_S 20 +/** MCPWM_GEN1_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT1 0x00000003U +#define MCPWM_GEN1_B_DT1_M (MCPWM_GEN1_B_DT1_V << MCPWM_GEN1_B_DT1_S) +#define MCPWM_GEN1_B_DT1_V 0x00000003U +#define MCPWM_GEN1_B_DT1_S 22 -#define MCPWM_DT1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0090) -/* MCPWM_DT1_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Dead time generator 1 clock selection. 0: PWM_clk 1: PT_clk*/ -#define MCPWM_DT1_CLK_SEL (BIT(17)) -#define MCPWM_DT1_CLK_SEL_M (BIT(17)) -#define MCPWM_DT1_CLK_SEL_V 0x1 -#define MCPWM_DT1_CLK_SEL_S 17 -/* MCPWM_DT1_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: S0 in documentation*/ -#define MCPWM_DT1_B_OUTBYPASS (BIT(16)) -#define MCPWM_DT1_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DT1_B_OUTBYPASS_V 0x1 -#define MCPWM_DT1_B_OUTBYPASS_S 16 -/* MCPWM_DT1_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: S1 in documentation*/ -#define MCPWM_DT1_A_OUTBYPASS (BIT(15)) -#define MCPWM_DT1_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DT1_A_OUTBYPASS_V 0x1 -#define MCPWM_DT1_A_OUTBYPASS_S 15 -/* MCPWM_DT1_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: S3 in documentation*/ -#define MCPWM_DT1_FED_OUTINVERT (BIT(14)) -#define MCPWM_DT1_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DT1_FED_OUTINVERT_V 0x1 -#define MCPWM_DT1_FED_OUTINVERT_S 14 -/* MCPWM_DT1_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: S2 in documentation*/ -#define MCPWM_DT1_RED_OUTINVERT (BIT(13)) -#define MCPWM_DT1_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DT1_RED_OUTINVERT_V 0x1 -#define MCPWM_DT1_RED_OUTINVERT_S 13 -/* MCPWM_DT1_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: S5 in documentation*/ -#define MCPWM_DT1_FED_INSEL (BIT(12)) -#define MCPWM_DT1_FED_INSEL_M (BIT(12)) -#define MCPWM_DT1_FED_INSEL_V 0x1 -#define MCPWM_DT1_FED_INSEL_S 12 -/* MCPWM_DT1_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: S4 in documentation*/ -#define MCPWM_DT1_RED_INSEL (BIT(11)) -#define MCPWM_DT1_RED_INSEL_M (BIT(11)) -#define MCPWM_DT1_RED_INSEL_V 0x1 -#define MCPWM_DT1_RED_INSEL_S 11 -/* MCPWM_DT1_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: S7 in documentation*/ -#define MCPWM_DT1_B_OUTSWAP (BIT(10)) -#define MCPWM_DT1_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DT1_B_OUTSWAP_V 0x1 -#define MCPWM_DT1_B_OUTSWAP_S 10 -/* MCPWM_DT1_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: S6 in documentation*/ -#define MCPWM_DT1_A_OUTSWAP (BIT(9)) -#define MCPWM_DT1_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DT1_A_OUTSWAP_V 0x1 -#define MCPWM_DT1_A_OUTSWAP_S 9 -/* MCPWM_DT1_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: S8 in documentation dual-edge B mode 0: FED/RED take effect - on different path separately 1: FED/RED take effect on B path A out is in bypass or normal operation mode*/ -#define MCPWM_DT1_DEB_MODE (BIT(8)) -#define MCPWM_DT1_DEB_MODE_M (BIT(8)) -#define MCPWM_DT1_DEB_MODE_V 0x1 -#define MCPWM_DT1_DEB_MODE_S 8 -/* MCPWM_DT1_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for RED (rising edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT1_RED_UPMETHOD 0x0000000F -#define MCPWM_DT1_RED_UPMETHOD_M ((MCPWM_DT1_RED_UPMETHOD_V)<<(MCPWM_DT1_RED_UPMETHOD_S)) -#define MCPWM_DT1_RED_UPMETHOD_V 0xF -#define MCPWM_DT1_RED_UPMETHOD_S 4 -/* MCPWM_DT1_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for FED (falling edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT1_FED_UPMETHOD 0x0000000F -#define MCPWM_DT1_FED_UPMETHOD_M ((MCPWM_DT1_FED_UPMETHOD_V)<<(MCPWM_DT1_FED_UPMETHOD_S)) -#define MCPWM_DT1_FED_UPMETHOD_V 0xF +/** MCPWM_DT1_CFG_REG register + * PWM generator 1 dead time type selection and configuration + */ +#define MCPWM_DT1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x90) +/** MCPWM_DT1_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_FED_UPMETHOD_M (MCPWM_DT1_FED_UPMETHOD_V << MCPWM_DT1_FED_UPMETHOD_S) +#define MCPWM_DT1_FED_UPMETHOD_V 0x0000000FU #define MCPWM_DT1_FED_UPMETHOD_S 0 +/** MCPWM_DT1_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_M (MCPWM_DT1_RED_UPMETHOD_V << MCPWM_DT1_RED_UPMETHOD_S) +#define MCPWM_DT1_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_S 4 +/** MCPWM_DT1_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT1_DEB_MODE (BIT(8)) +#define MCPWM_DT1_DEB_MODE_M (MCPWM_DT1_DEB_MODE_V << MCPWM_DT1_DEB_MODE_S) +#define MCPWM_DT1_DEB_MODE_V 0x00000001U +#define MCPWM_DT1_DEB_MODE_S 8 +/** MCPWM_DT1_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT1_A_OUTSWAP (BIT(9)) +#define MCPWM_DT1_A_OUTSWAP_M (MCPWM_DT1_A_OUTSWAP_V << MCPWM_DT1_A_OUTSWAP_S) +#define MCPWM_DT1_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_A_OUTSWAP_S 9 +/** MCPWM_DT1_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT1_B_OUTSWAP (BIT(10)) +#define MCPWM_DT1_B_OUTSWAP_M (MCPWM_DT1_B_OUTSWAP_V << MCPWM_DT1_B_OUTSWAP_S) +#define MCPWM_DT1_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_B_OUTSWAP_S 10 +/** MCPWM_DT1_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT1_RED_INSEL (BIT(11)) +#define MCPWM_DT1_RED_INSEL_M (MCPWM_DT1_RED_INSEL_V << MCPWM_DT1_RED_INSEL_S) +#define MCPWM_DT1_RED_INSEL_V 0x00000001U +#define MCPWM_DT1_RED_INSEL_S 11 +/** MCPWM_DT1_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT1_FED_INSEL (BIT(12)) +#define MCPWM_DT1_FED_INSEL_M (MCPWM_DT1_FED_INSEL_V << MCPWM_DT1_FED_INSEL_S) +#define MCPWM_DT1_FED_INSEL_V 0x00000001U +#define MCPWM_DT1_FED_INSEL_S 12 +/** MCPWM_DT1_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT1_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT1_RED_OUTINVERT_M (MCPWM_DT1_RED_OUTINVERT_V << MCPWM_DT1_RED_OUTINVERT_S) +#define MCPWM_DT1_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_RED_OUTINVERT_S 13 +/** MCPWM_DT1_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT1_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT1_FED_OUTINVERT_M (MCPWM_DT1_FED_OUTINVERT_V << MCPWM_DT1_FED_OUTINVERT_S) +#define MCPWM_DT1_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_FED_OUTINVERT_S 14 +/** MCPWM_DT1_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT1_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT1_A_OUTBYPASS_M (MCPWM_DT1_A_OUTBYPASS_V << MCPWM_DT1_A_OUTBYPASS_S) +#define MCPWM_DT1_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_A_OUTBYPASS_S 15 +/** MCPWM_DT1_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT1_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT1_B_OUTBYPASS_M (MCPWM_DT1_B_OUTBYPASS_V << MCPWM_DT1_B_OUTBYPASS_S) +#define MCPWM_DT1_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_B_OUTBYPASS_S 16 +/** MCPWM_DT1_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT1_CLK_SEL (BIT(17)) +#define MCPWM_DT1_CLK_SEL_M (MCPWM_DT1_CLK_SEL_V << MCPWM_DT1_CLK_SEL_S) +#define MCPWM_DT1_CLK_SEL_V 0x00000001U +#define MCPWM_DT1_CLK_SEL_S 17 -#define MCPWM_DT1_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0094) -/* MCPWM_DT1_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for FED*/ -#define MCPWM_DT1_FED 0x0000FFFF -#define MCPWM_DT1_FED_M ((MCPWM_DT1_FED_V)<<(MCPWM_DT1_FED_S)) -#define MCPWM_DT1_FED_V 0xFFFF +/** MCPWM_DT1_FED_CFG_REG register + * PWM generator 1 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT1_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x94) +/** MCPWM_DT1_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT1_FED 0x0000FFFFU +#define MCPWM_DT1_FED_M (MCPWM_DT1_FED_V << MCPWM_DT1_FED_S) +#define MCPWM_DT1_FED_V 0x0000FFFFU #define MCPWM_DT1_FED_S 0 -#define MCPWM_DT1_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0098) -/* MCPWM_DT1_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for RED*/ -#define MCPWM_DT1_RED 0x0000FFFF -#define MCPWM_DT1_RED_M ((MCPWM_DT1_RED_V)<<(MCPWM_DT1_RED_S)) -#define MCPWM_DT1_RED_V 0xFFFF +/** MCPWM_DT1_RED_CFG_REG register + * PWM generator 1 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT1_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x98) +/** MCPWM_DT1_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT1_RED 0x0000FFFFU +#define MCPWM_DT1_RED_M (MCPWM_DT1_RED_V << MCPWM_DT1_RED_S) +#define MCPWM_DT1_RED_V 0x0000FFFFU #define MCPWM_DT1_RED_S 0 -#define MCPWM_CARRIER1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x009c) -/* MCPWM_CARRIER1_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: When set invert the input of PWM1A and PWM1B for this submodule*/ -#define MCPWM_CARRIER1_IN_INVERT (BIT(13)) -#define MCPWM_CARRIER1_IN_INVERT_M (BIT(13)) -#define MCPWM_CARRIER1_IN_INVERT_V 0x1 -#define MCPWM_CARRIER1_IN_INVERT_S 13 -/* MCPWM_CARRIER1_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: When set invert the output of PWM1A and PWM1B for this submodule*/ -#define MCPWM_CARRIER1_OUT_INVERT (BIT(12)) -#define MCPWM_CARRIER1_OUT_INVERT_M (BIT(12)) -#define MCPWM_CARRIER1_OUT_INVERT_V 0x1 -#define MCPWM_CARRIER1_OUT_INVERT_S 12 -/* MCPWM_CARRIER1_OSHWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: Width of the fist pulse in number of periods of the carrier*/ -#define MCPWM_CARRIER1_OSHWTH 0x0000000F -#define MCPWM_CARRIER1_OSHWTH_M ((MCPWM_CARRIER1_OSHWTH_V)<<(MCPWM_CARRIER1_OSHWTH_S)) -#define MCPWM_CARRIER1_OSHWTH_V 0xF -#define MCPWM_CARRIER1_OSHWTH_S 8 -/* MCPWM_CARRIER1_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: Carrier duty selection. Duty = PWM_CARRIER1_DUTY / 8*/ -#define MCPWM_CARRIER1_DUTY 0x00000007 -#define MCPWM_CARRIER1_DUTY_M ((MCPWM_CARRIER1_DUTY_V)<<(MCPWM_CARRIER1_DUTY_S)) -#define MCPWM_CARRIER1_DUTY_V 0x7 -#define MCPWM_CARRIER1_DUTY_S 5 -/* MCPWM_CARRIER1_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: PWM carrier1 clock (PC_clk) prescale value. Period of PC_clk - = period of PWM_clk * (PWM_CARRIER1_PRESCALE + 1)*/ -#define MCPWM_CARRIER1_PRESCALE 0x0000000F -#define MCPWM_CARRIER1_PRESCALE_M ((MCPWM_CARRIER1_PRESCALE_V)<<(MCPWM_CARRIER1_PRESCALE_S)) -#define MCPWM_CARRIER1_PRESCALE_V 0xF -#define MCPWM_CARRIER1_PRESCALE_S 1 -/* MCPWM_CARRIER1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set carrier1 function is enabled. When cleared carrier1 is bypassed*/ -#define MCPWM_CARRIER1_EN (BIT(0)) -#define MCPWM_CARRIER1_EN_M (BIT(0)) -#define MCPWM_CARRIER1_EN_V 0x1 +/** MCPWM_CARRIER1_CFG_REG register + * PWM generator 1 carrier enable and configuratoin + */ +#define MCPWM_CARRIER1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x9c) +/** MCPWM_CARRIER1_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier1 function is enabled. When cleared, carrier1 is bypassed + */ +#define MCPWM_CARRIER1_EN (BIT(0)) +#define MCPWM_CARRIER1_EN_M (MCPWM_CARRIER1_EN_V << MCPWM_CARRIER1_EN_S) +#define MCPWM_CARRIER1_EN_V 0x00000001U #define MCPWM_CARRIER1_EN_S 0 +/** MCPWM_CARRIER1_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier1 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER1_PRESCALE 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_M (MCPWM_CARRIER1_PRESCALE_V << MCPWM_CARRIER1_PRESCALE_S) +#define MCPWM_CARRIER1_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_S 1 +/** MCPWM_CARRIER1_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER1_DUTY 0x00000007U +#define MCPWM_CARRIER1_DUTY_M (MCPWM_CARRIER1_DUTY_V << MCPWM_CARRIER1_DUTY_S) +#define MCPWM_CARRIER1_DUTY_V 0x00000007U +#define MCPWM_CARRIER1_DUTY_S 5 +/** MCPWM_CARRIER1_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER1_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_M (MCPWM_CARRIER1_OSHTWTH_V << MCPWM_CARRIER1_OSHTWTH_S) +#define MCPWM_CARRIER1_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_S 8 +/** MCPWM_CARRIER1_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER1_OUT_INVERT_M (MCPWM_CARRIER1_OUT_INVERT_V << MCPWM_CARRIER1_OUT_INVERT_S) +#define MCPWM_CARRIER1_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_OUT_INVERT_S 12 +/** MCPWM_CARRIER1_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER1_IN_INVERT_M (MCPWM_CARRIER1_IN_INVERT_V << MCPWM_CARRIER1_IN_INVERT_S) +#define MCPWM_CARRIER1_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_IN_INVERT_S 13 -#define MCPWM_FH1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x00a0) -/* MCPWM_FH1_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1B when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_OST_U 0x00000003 -#define MCPWM_FH1_B_OST_U_M ((MCPWM_FH1_B_OST_U_V)<<(MCPWM_FH1_B_OST_U_S)) -#define MCPWM_FH1_B_OST_U_V 0x3 -#define MCPWM_FH1_B_OST_U_S 22 -/* MCPWM_FH1_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1B when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_OST_D 0x00000003 -#define MCPWM_FH1_B_OST_D_M ((MCPWM_FH1_B_OST_D_V)<<(MCPWM_FH1_B_OST_D_S)) -#define MCPWM_FH1_B_OST_D_V 0x3 -#define MCPWM_FH1_B_OST_D_S 20 -/* MCPWM_FH1_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1B when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_CBC_U 0x00000003 -#define MCPWM_FH1_B_CBC_U_M ((MCPWM_FH1_B_CBC_U_V)<<(MCPWM_FH1_B_CBC_U_S)) -#define MCPWM_FH1_B_CBC_U_V 0x3 -#define MCPWM_FH1_B_CBC_U_S 18 -/* MCPWM_FH1_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1B when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_CBC_D 0x00000003 -#define MCPWM_FH1_B_CBC_D_M ((MCPWM_FH1_B_CBC_D_V)<<(MCPWM_FH1_B_CBC_D_S)) -#define MCPWM_FH1_B_CBC_D_V 0x3 -#define MCPWM_FH1_B_CBC_D_S 16 -/* MCPWM_FH1_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1A when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_OST_U 0x00000003 -#define MCPWM_FH1_A_OST_U_M ((MCPWM_FH1_A_OST_U_V)<<(MCPWM_FH1_A_OST_U_S)) -#define MCPWM_FH1_A_OST_U_V 0x3 -#define MCPWM_FH1_A_OST_U_S 14 -/* MCPWM_FH1_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1A when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_OST_D 0x00000003 -#define MCPWM_FH1_A_OST_D_M ((MCPWM_FH1_A_OST_D_V)<<(MCPWM_FH1_A_OST_D_S)) -#define MCPWM_FH1_A_OST_D_V 0x3 -#define MCPWM_FH1_A_OST_D_S 12 -/* MCPWM_FH1_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1A when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_CBC_U 0x00000003 -#define MCPWM_FH1_A_CBC_U_M ((MCPWM_FH1_A_CBC_U_V)<<(MCPWM_FH1_A_CBC_U_S)) -#define MCPWM_FH1_A_CBC_U_V 0x3 -#define MCPWM_FH1_A_CBC_U_S 10 -/* MCPWM_FH1_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1A when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_CBC_D 0x00000003 -#define MCPWM_FH1_A_CBC_D_M ((MCPWM_FH1_A_CBC_D_V)<<(MCPWM_FH1_A_CBC_D_S)) -#define MCPWM_FH1_A_CBC_D_V 0x3 -#define MCPWM_FH1_A_CBC_D_S 8 -/* MCPWM_FH1_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: event_f0 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F0_OST (BIT(7)) -#define MCPWM_FH1_F0_OST_M (BIT(7)) -#define MCPWM_FH1_F0_OST_V 0x1 -#define MCPWM_FH1_F0_OST_S 7 -/* MCPWM_FH1_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: event_f1 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F1_OST (BIT(6)) -#define MCPWM_FH1_F1_OST_M (BIT(6)) -#define MCPWM_FH1_F1_OST_V 0x1 -#define MCPWM_FH1_F1_OST_S 6 -/* MCPWM_FH1_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: event_f2 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F2_OST (BIT(5)) -#define MCPWM_FH1_F2_OST_M (BIT(5)) -#define MCPWM_FH1_F2_OST_V 0x1 -#define MCPWM_FH1_F2_OST_S 5 -/* MCPWM_FH1_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Enable register for software force one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_SW_OST (BIT(4)) -#define MCPWM_FH1_SW_OST_M (BIT(4)) -#define MCPWM_FH1_SW_OST_V 0x1 -#define MCPWM_FH1_SW_OST_S 4 -/* MCPWM_FH1_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: event_f0 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F0_CBC (BIT(3)) -#define MCPWM_FH1_F0_CBC_M (BIT(3)) -#define MCPWM_FH1_F0_CBC_V 0x1 -#define MCPWM_FH1_F0_CBC_S 3 -/* MCPWM_FH1_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: event_f1 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F1_CBC (BIT(2)) -#define MCPWM_FH1_F1_CBC_M (BIT(2)) -#define MCPWM_FH1_F1_CBC_V 0x1 -#define MCPWM_FH1_F1_CBC_S 2 -/* MCPWM_FH1_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: event_f2 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F2_CBC (BIT(1)) -#define MCPWM_FH1_F2_CBC_M (BIT(1)) -#define MCPWM_FH1_F2_CBC_V 0x1 -#define MCPWM_FH1_F2_CBC_S 1 -/* MCPWM_FH1_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Enable register for software force cycle-by-cycle mode action. - 0: disable 1: enable*/ -#define MCPWM_FH1_SW_CBC (BIT(0)) -#define MCPWM_FH1_SW_CBC_M (BIT(0)) -#define MCPWM_FH1_SW_CBC_V 0x1 +/** MCPWM_FH1_CFG0_REG register + * Actions on PWM1A and PWM1B trip events + */ +#define MCPWM_FH1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa0) +/** MCPWM_FH1_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_CBC (BIT(0)) +#define MCPWM_FH1_SW_CBC_M (MCPWM_FH1_SW_CBC_V << MCPWM_FH1_SW_CBC_S) +#define MCPWM_FH1_SW_CBC_V 0x00000001U #define MCPWM_FH1_SW_CBC_S 0 +/** MCPWM_FH1_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_CBC (BIT(1)) +#define MCPWM_FH1_F2_CBC_M (MCPWM_FH1_F2_CBC_V << MCPWM_FH1_F2_CBC_S) +#define MCPWM_FH1_F2_CBC_V 0x00000001U +#define MCPWM_FH1_F2_CBC_S 1 +/** MCPWM_FH1_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_CBC (BIT(2)) +#define MCPWM_FH1_F1_CBC_M (MCPWM_FH1_F1_CBC_V << MCPWM_FH1_F1_CBC_S) +#define MCPWM_FH1_F1_CBC_V 0x00000001U +#define MCPWM_FH1_F1_CBC_S 2 +/** MCPWM_FH1_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_CBC (BIT(3)) +#define MCPWM_FH1_F0_CBC_M (MCPWM_FH1_F0_CBC_V << MCPWM_FH1_F0_CBC_S) +#define MCPWM_FH1_F0_CBC_V 0x00000001U +#define MCPWM_FH1_F0_CBC_S 3 +/** MCPWM_FH1_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_OST (BIT(4)) +#define MCPWM_FH1_SW_OST_M (MCPWM_FH1_SW_OST_V << MCPWM_FH1_SW_OST_S) +#define MCPWM_FH1_SW_OST_V 0x00000001U +#define MCPWM_FH1_SW_OST_S 4 +/** MCPWM_FH1_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_OST (BIT(5)) +#define MCPWM_FH1_F2_OST_M (MCPWM_FH1_F2_OST_V << MCPWM_FH1_F2_OST_S) +#define MCPWM_FH1_F2_OST_V 0x00000001U +#define MCPWM_FH1_F2_OST_S 5 +/** MCPWM_FH1_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_OST (BIT(6)) +#define MCPWM_FH1_F1_OST_M (MCPWM_FH1_F1_OST_V << MCPWM_FH1_F1_OST_S) +#define MCPWM_FH1_F1_OST_V 0x00000001U +#define MCPWM_FH1_F1_OST_S 6 +/** MCPWM_FH1_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_OST (BIT(7)) +#define MCPWM_FH1_F0_OST_M (MCPWM_FH1_F0_OST_V << MCPWM_FH1_F0_OST_S) +#define MCPWM_FH1_F0_OST_V 0x00000001U +#define MCPWM_FH1_F0_OST_S 7 +/** MCPWM_FH1_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_D 0x00000003U +#define MCPWM_FH1_A_CBC_D_M (MCPWM_FH1_A_CBC_D_V << MCPWM_FH1_A_CBC_D_S) +#define MCPWM_FH1_A_CBC_D_V 0x00000003U +#define MCPWM_FH1_A_CBC_D_S 8 +/** MCPWM_FH1_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_U 0x00000003U +#define MCPWM_FH1_A_CBC_U_M (MCPWM_FH1_A_CBC_U_V << MCPWM_FH1_A_CBC_U_S) +#define MCPWM_FH1_A_CBC_U_V 0x00000003U +#define MCPWM_FH1_A_CBC_U_S 10 +/** MCPWM_FH1_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is decreasing. 0: + * do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_D 0x00000003U +#define MCPWM_FH1_A_OST_D_M (MCPWM_FH1_A_OST_D_V << MCPWM_FH1_A_OST_D_S) +#define MCPWM_FH1_A_OST_D_V 0x00000003U +#define MCPWM_FH1_A_OST_D_S 12 +/** MCPWM_FH1_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_U 0x00000003U +#define MCPWM_FH1_A_OST_U_M (MCPWM_FH1_A_OST_U_V << MCPWM_FH1_A_OST_U_S) +#define MCPWM_FH1_A_OST_U_V 0x00000003U +#define MCPWM_FH1_A_OST_U_S 14 +/** MCPWM_FH1_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_D 0x00000003U +#define MCPWM_FH1_B_CBC_D_M (MCPWM_FH1_B_CBC_D_V << MCPWM_FH1_B_CBC_D_S) +#define MCPWM_FH1_B_CBC_D_V 0x00000003U +#define MCPWM_FH1_B_CBC_D_S 16 +/** MCPWM_FH1_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_U 0x00000003U +#define MCPWM_FH1_B_CBC_U_M (MCPWM_FH1_B_CBC_U_V << MCPWM_FH1_B_CBC_U_S) +#define MCPWM_FH1_B_CBC_U_V 0x00000003U +#define MCPWM_FH1_B_CBC_U_S 18 +/** MCPWM_FH1_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_D 0x00000003U +#define MCPWM_FH1_B_OST_D_M (MCPWM_FH1_B_OST_D_V << MCPWM_FH1_B_OST_D_S) +#define MCPWM_FH1_B_OST_D_V 0x00000003U +#define MCPWM_FH1_B_OST_D_S 20 +/** MCPWM_FH1_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_U 0x00000003U +#define MCPWM_FH1_B_OST_U_M (MCPWM_FH1_B_OST_U_V << MCPWM_FH1_B_OST_U_S) +#define MCPWM_FH1_B_OST_U_V 0x00000003U +#define MCPWM_FH1_B_OST_U_S 22 -#define MCPWM_FH1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x00a4) -/* MCPWM_FH1_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) triggers a - one-shot mode action*/ -#define MCPWM_FH1_FORCE_OST (BIT(4)) -#define MCPWM_FH1_FORCE_OST_M (BIT(4)) -#define MCPWM_FH1_FORCE_OST_V 0x1 -#define MCPWM_FH1_FORCE_OST_S 4 -/* MCPWM_FH1_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle triggers a cycle-by-cycle mode action*/ -#define MCPWM_FH1_FORCE_CBC (BIT(3)) -#define MCPWM_FH1_FORCE_CBC_M (BIT(3)) -#define MCPWM_FH1_FORCE_CBC_V 0x1 -#define MCPWM_FH1_FORCE_CBC_S 3 -/* MCPWM_FH1_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: The cycle-by-cycle mode action refresh moment selection. Bit0: TEZ bit1:TEP*/ -#define MCPWM_FH1_CBCPULSE 0x00000003 -#define MCPWM_FH1_CBCPULSE_M ((MCPWM_FH1_CBCPULSE_V)<<(MCPWM_FH1_CBCPULSE_S)) -#define MCPWM_FH1_CBCPULSE_V 0x3 -#define MCPWM_FH1_CBCPULSE_S 1 -/* MCPWM_FH1_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: A toggle will clear on going one-shot mode action*/ -#define MCPWM_FH1_CLR_OST (BIT(0)) -#define MCPWM_FH1_CLR_OST_M (BIT(0)) -#define MCPWM_FH1_CLR_OST_V 0x1 +/** MCPWM_FH1_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa4) +/** MCPWM_FH1_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH1_CLR_OST (BIT(0)) +#define MCPWM_FH1_CLR_OST_M (MCPWM_FH1_CLR_OST_V << MCPWM_FH1_CLR_OST_S) +#define MCPWM_FH1_CLR_OST_V 0x00000001U #define MCPWM_FH1_CLR_OST_S 0 +/** MCPWM_FH1_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH1_CBCPULSE 0x00000003U +#define MCPWM_FH1_CBCPULSE_M (MCPWM_FH1_CBCPULSE_V << MCPWM_FH1_CBCPULSE_S) +#define MCPWM_FH1_CBCPULSE_V 0x00000003U +#define MCPWM_FH1_CBCPULSE_S 1 +/** MCPWM_FH1_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH1_FORCE_CBC (BIT(3)) +#define MCPWM_FH1_FORCE_CBC_M (MCPWM_FH1_FORCE_CBC_V << MCPWM_FH1_FORCE_CBC_S) +#define MCPWM_FH1_FORCE_CBC_V 0x00000001U +#define MCPWM_FH1_FORCE_CBC_S 3 +/** MCPWM_FH1_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH1_FORCE_OST (BIT(4)) +#define MCPWM_FH1_FORCE_OST_M (MCPWM_FH1_FORCE_OST_V << MCPWM_FH1_FORCE_OST_S) +#define MCPWM_FH1_FORCE_OST_V 0x00000001U +#define MCPWM_FH1_FORCE_OST_S 4 -#define MCPWM_FH1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x00a8) -/* MCPWM_FH1_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an one-shot mode action is on going*/ -#define MCPWM_FH1_OST_ON (BIT(1)) -#define MCPWM_FH1_OST_ON_M (BIT(1)) -#define MCPWM_FH1_OST_ON_V 0x1 -#define MCPWM_FH1_OST_ON_S 1 -/* MCPWM_FH1_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an cycle-by-cycle mode action is on going*/ -#define MCPWM_FH1_CBC_ON (BIT(0)) -#define MCPWM_FH1_CBC_ON_M (BIT(0)) -#define MCPWM_FH1_CBC_ON_V 0x1 +/** MCPWM_FH1_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa8) +/** MCPWM_FH1_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH1_CBC_ON (BIT(0)) +#define MCPWM_FH1_CBC_ON_M (MCPWM_FH1_CBC_ON_V << MCPWM_FH1_CBC_ON_S) +#define MCPWM_FH1_CBC_ON_V 0x00000001U #define MCPWM_FH1_CBC_ON_S 0 +/** MCPWM_FH1_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH1_OST_ON (BIT(1)) +#define MCPWM_FH1_OST_ON_M (MCPWM_FH1_OST_ON_V << MCPWM_FH1_OST_ON_S) +#define MCPWM_FH1_OST_ON_V 0x00000001U +#define MCPWM_FH1_OST_ON_S 1 -#define MCPWM_GEN2_STMP_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00ac) -/* MCPWM_GEN2_B_SHDW_FULL : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 2 time stamp - B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN2_B_SHDW_FULL (BIT(9)) -#define MCPWM_GEN2_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_GEN2_B_SHDW_FULL_V 0x1 -#define MCPWM_GEN2_B_SHDW_FULL_S 9 -/* MCPWM_GEN2_A_SHDW_FULL : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 2 time stamp - A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN2_A_SHDW_FULL (BIT(8)) -#define MCPWM_GEN2_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_GEN2_A_SHDW_FULL_V 0x1 -#define MCPWM_GEN2_A_SHDW_FULL_S 8 -/* MCPWM_GEN2_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 2 time stamp B's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN2_B_UPMETHOD 0x0000000F -#define MCPWM_GEN2_B_UPMETHOD_M ((MCPWM_GEN2_B_UPMETHOD_V)<<(MCPWM_GEN2_B_UPMETHOD_S)) -#define MCPWM_GEN2_B_UPMETHOD_V 0xF -#define MCPWM_GEN2_B_UPMETHOD_S 4 -/* MCPWM_GEN2_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 2 time stamp A's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN2_A_UPMETHOD 0x0000000F -#define MCPWM_GEN2_A_UPMETHOD_M ((MCPWM_GEN2_A_UPMETHOD_V)<<(MCPWM_GEN2_A_UPMETHOD_S)) -#define MCPWM_GEN2_A_UPMETHOD_V 0xF +/** MCPWM_GEN2_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN2_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xac) +/** MCPWM_GEN2_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_A_UPMETHOD_M (MCPWM_GEN2_A_UPMETHOD_V << MCPWM_GEN2_A_UPMETHOD_S) +#define MCPWM_GEN2_A_UPMETHOD_V 0x0000000FU #define MCPWM_GEN2_A_UPMETHOD_S 0 +/** MCPWM_GEN2_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 2 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_M (MCPWM_GEN2_B_UPMETHOD_V << MCPWM_GEN2_B_UPMETHOD_S) +#define MCPWM_GEN2_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_S 4 +/** MCPWM_GEN2_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN2_A_SHDW_FULL_M (MCPWM_GEN2_A_SHDW_FULL_V << MCPWM_GEN2_A_SHDW_FULL_S) +#define MCPWM_GEN2_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_A_SHDW_FULL_S 8 +/** MCPWM_GEN2_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN2_B_SHDW_FULL_M (MCPWM_GEN2_B_SHDW_FULL_V << MCPWM_GEN2_B_SHDW_FULL_S) +#define MCPWM_GEN2_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_B_SHDW_FULL_S 9 -#define MCPWM_GEN2_TSTMP_A_REG(i) (REG_MCPWM_BASE(i) + 0x00b0) -/* MCPWM_GEN2_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 2 time stamp A's shadow reg*/ -#define MCPWM_GEN2_A 0x0000FFFF -#define MCPWM_GEN2_A_M ((MCPWM_GEN2_A_V)<<(MCPWM_GEN2_A_S)) -#define MCPWM_GEN2_A_V 0xFFFF +/** MCPWM_GEN2_TSTMP_A_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb0) +/** MCPWM_GEN2_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp A's shadow register + */ +#define MCPWM_GEN2_A 0x0000FFFFU +#define MCPWM_GEN2_A_M (MCPWM_GEN2_A_V << MCPWM_GEN2_A_S) +#define MCPWM_GEN2_A_V 0x0000FFFFU #define MCPWM_GEN2_A_S 0 -#define MCPWM_GEN2_TSTMP_B_REG(i) (REG_MCPWM_BASE(i) + 0x00b4) -/* MCPWM_GEN2_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 2 time stamp B's shadow reg*/ -#define MCPWM_GEN2_B 0x0000FFFF -#define MCPWM_GEN2_B_M ((MCPWM_GEN2_B_V)<<(MCPWM_GEN2_B_S)) -#define MCPWM_GEN2_B_V 0xFFFF +/** MCPWM_GEN2_TSTMP_B_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb4) +/** MCPWM_GEN2_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp B's shadow register + */ +#define MCPWM_GEN2_B 0x0000FFFFU +#define MCPWM_GEN2_B_M (MCPWM_GEN2_B_V << MCPWM_GEN2_B_S) +#define MCPWM_GEN2_B_V 0x0000FFFFU #define MCPWM_GEN2_B_S 0 -#define MCPWM_GEN2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x00b8) -/* MCPWM_GEN2_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate2 event_t1 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN2_T1_SEL 0x00000007 -#define MCPWM_GEN2_T1_SEL_M ((MCPWM_GEN2_T1_SEL_V)<<(MCPWM_GEN2_T1_SEL_S)) -#define MCPWM_GEN2_T1_SEL_V 0x7 -#define MCPWM_GEN2_T1_SEL_S 7 -/* MCPWM_GEN2_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate2 event_t0 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN2_T0_SEL 0x00000007 -#define MCPWM_GEN2_T0_SEL_M ((MCPWM_GEN2_T0_SEL_V)<<(MCPWM_GEN2_T0_SEL_S)) -#define MCPWM_GEN2_T0_SEL_V 0x7 -#define MCPWM_GEN2_T0_SEL_S 4 -/* MCPWM_GEN2_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generate2's active reg of configuration. - 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: disable update*/ -#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN2_CFG_UPMETHOD_M ((MCPWM_GEN2_CFG_UPMETHOD_V)<<(MCPWM_GEN2_CFG_UPMETHOD_S)) -#define MCPWM_GEN2_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN2_CFG0_REG register + * PWM generator 2 event T0 and T1 handling + */ +#define MCPWM_GEN2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb8) +/** MCPWM_GEN2_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2's active register of configuration. 0: + * immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1:sync;when bit3 is + * set to 1:disable the update. + */ +#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_CFG_UPMETHOD_M (MCPWM_GEN2_CFG_UPMETHOD_V << MCPWM_GEN2_CFG_UPMETHOD_S) +#define MCPWM_GEN2_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN2_CFG_UPMETHOD_S 0 +/** MCPWM_GEN2_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 2 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T0_SEL 0x00000007U +#define MCPWM_GEN2_T0_SEL_M (MCPWM_GEN2_T0_SEL_V << MCPWM_GEN2_T0_SEL_S) +#define MCPWM_GEN2_T0_SEL_V 0x00000007U +#define MCPWM_GEN2_T0_SEL_S 4 +/** MCPWM_GEN2_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 2 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T1_SEL 0x00000007U +#define MCPWM_GEN2_T1_SEL_M (MCPWM_GEN2_T1_SEL_V << MCPWM_GEN2_T1_SEL_S) +#define MCPWM_GEN2_T1_SEL_V 0x00000007U +#define MCPWM_GEN2_T1_SEL_S 7 -#define MCPWM_GEN2_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x00bc) -/* MCPWM_GEN2_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM2B 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_NCIFORCE_MODE_M ((MCPWM_GEN2_B_NCIFORCE_MODE_V)<<(MCPWM_GEN2_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN2_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM2B a - toggle will trigger a force event*/ -#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_V 0x1 -#define MCPWM_GEN2_B_NCIFORCE_S 13 -/* MCPWM_GEN2_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM2A 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_NCIFORCE_MODE_M ((MCPWM_GEN2_A_NCIFORCE_MODE_V)<<(MCPWM_GEN2_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN2_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM2A a - toggle will trigger a force event*/ -#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_V 0x1 -#define MCPWM_GEN2_A_NCIFORCE_S 10 -/* MCPWM_GEN2_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM2B. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_M ((MCPWM_GEN2_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN2_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM2A. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_M ((MCPWM_GEN2_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: Update method for continuous software force of PWM generator2. - 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: disable update. (TEA/B here and below means an event generated when timer value equals A/B register)*/ -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN2_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN2_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN2_FORCE_REG register + * Permissives to force PWM2A and PWM2B outputs by software + */ +#define MCPWM_GEN2_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xbc) +/** MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 2. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M (MCPWM_GEN2_CNTUFORCE_UPMETHOD_V << MCPWM_GEN2_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN2_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN2_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM2A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_M (MCPWM_GEN2_A_CNTUFORCE_MODE_V << MCPWM_GEN2_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN2_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM2B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_M (MCPWM_GEN2_B_CNTUFORCE_MODE_V << MCPWM_GEN2_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN2_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN2_A_NCIFORCE_M (MCPWM_GEN2_A_NCIFORCE_V << MCPWM_GEN2_A_NCIFORCE_S) +#define MCPWM_GEN2_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_A_NCIFORCE_S 10 +/** MCPWM_GEN2_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM2A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_M (MCPWM_GEN2_A_NCIFORCE_MODE_V << MCPWM_GEN2_A_NCIFORCE_MODE_S) +#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN2_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN2_B_NCIFORCE_M (MCPWM_GEN2_B_NCIFORCE_V << MCPWM_GEN2_B_NCIFORCE_S) +#define MCPWM_GEN2_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_B_NCIFORCE_S 13 +/** MCPWM_GEN2_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM2B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_M (MCPWM_GEN2_B_NCIFORCE_MODE_V << MCPWM_GEN2_B_NCIFORCE_MODE_S) +#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN2_A_REG(i) (REG_MCPWM_BASE(i) + 0x00c0) -/* MCPWM_GEN2_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN2_A_DT1 0x00000003 -#define MCPWM_GEN2_A_DT1_M ((MCPWM_GEN2_A_DT1_V)<<(MCPWM_GEN2_A_DT1_S)) -#define MCPWM_GEN2_A_DT1_V 0x3 -#define MCPWM_GEN2_A_DT1_S 22 -/* MCPWM_GEN2_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN2_A_DT0 0x00000003 -#define MCPWM_GEN2_A_DT0_M ((MCPWM_GEN2_A_DT0_V)<<(MCPWM_GEN2_A_DT0_S)) -#define MCPWM_GEN2_A_DT0_V 0x3 -#define MCPWM_GEN2_A_DT0_S 20 -/* MCPWM_GEN2_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN2_A_DTEB 0x00000003 -#define MCPWM_GEN2_A_DTEB_M ((MCPWM_GEN2_A_DTEB_V)<<(MCPWM_GEN2_A_DTEB_S)) -#define MCPWM_GEN2_A_DTEB_V 0x3 -#define MCPWM_GEN2_A_DTEB_S 18 -/* MCPWM_GEN2_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN2_A_DTEA 0x00000003 -#define MCPWM_GEN2_A_DTEA_M ((MCPWM_GEN2_A_DTEA_V)<<(MCPWM_GEN2_A_DTEA_S)) -#define MCPWM_GEN2_A_DTEA_V 0x3 -#define MCPWM_GEN2_A_DTEA_S 16 -/* MCPWM_GEN2_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN2_A_DTEP 0x00000003 -#define MCPWM_GEN2_A_DTEP_M ((MCPWM_GEN2_A_DTEP_V)<<(MCPWM_GEN2_A_DTEP_S)) -#define MCPWM_GEN2_A_DTEP_V 0x3 -#define MCPWM_GEN2_A_DTEP_S 14 -/* MCPWM_GEN2_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN2_A_DTEZ 0x00000003 -#define MCPWM_GEN2_A_DTEZ_M ((MCPWM_GEN2_A_DTEZ_V)<<(MCPWM_GEN2_A_DTEZ_S)) -#define MCPWM_GEN2_A_DTEZ_V 0x3 -#define MCPWM_GEN2_A_DTEZ_S 12 -/* MCPWM_GEN2_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN2_A_UT1 0x00000003 -#define MCPWM_GEN2_A_UT1_M ((MCPWM_GEN2_A_UT1_V)<<(MCPWM_GEN2_A_UT1_S)) -#define MCPWM_GEN2_A_UT1_V 0x3 -#define MCPWM_GEN2_A_UT1_S 10 -/* MCPWM_GEN2_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN2_A_UT0 0x00000003 -#define MCPWM_GEN2_A_UT0_M ((MCPWM_GEN2_A_UT0_V)<<(MCPWM_GEN2_A_UT0_S)) -#define MCPWM_GEN2_A_UT0_V 0x3 -#define MCPWM_GEN2_A_UT0_S 8 -/* MCPWM_GEN2_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEB when timer increasing*/ -#define MCPWM_GEN2_A_UTEB 0x00000003 -#define MCPWM_GEN2_A_UTEB_M ((MCPWM_GEN2_A_UTEB_V)<<(MCPWM_GEN2_A_UTEB_S)) -#define MCPWM_GEN2_A_UTEB_V 0x3 -#define MCPWM_GEN2_A_UTEB_S 6 -/* MCPWM_GEN2_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEA when timer increasing*/ -#define MCPWM_GEN2_A_UTEA 0x00000003 -#define MCPWM_GEN2_A_UTEA_M ((MCPWM_GEN2_A_UTEA_V)<<(MCPWM_GEN2_A_UTEA_S)) -#define MCPWM_GEN2_A_UTEA_V 0x3 -#define MCPWM_GEN2_A_UTEA_S 4 -/* MCPWM_GEN2_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEP when timer increasing*/ -#define MCPWM_GEN2_A_UTEP 0x00000003 -#define MCPWM_GEN2_A_UTEP_M ((MCPWM_GEN2_A_UTEP_V)<<(MCPWM_GEN2_A_UTEP_S)) -#define MCPWM_GEN2_A_UTEP_V 0x3 -#define MCPWM_GEN2_A_UTEP_S 2 -/* MCPWM_GEN2_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN2_A_UTEZ 0x00000003 -#define MCPWM_GEN2_A_UTEZ_M ((MCPWM_GEN2_A_UTEZ_V)<<(MCPWM_GEN2_A_UTEZ_S)) -#define MCPWM_GEN2_A_UTEZ_V 0x3 +/** MCPWM_GEN2_A_REG register + * Actions triggered by events on PWM2A + */ +#define MCPWM_GEN2_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc0) +/** MCPWM_GEN2_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEZ 0x00000003U +#define MCPWM_GEN2_A_UTEZ_M (MCPWM_GEN2_A_UTEZ_V << MCPWM_GEN2_A_UTEZ_S) +#define MCPWM_GEN2_A_UTEZ_V 0x00000003U #define MCPWM_GEN2_A_UTEZ_S 0 +/** MCPWM_GEN2_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEP 0x00000003U +#define MCPWM_GEN2_A_UTEP_M (MCPWM_GEN2_A_UTEP_V << MCPWM_GEN2_A_UTEP_S) +#define MCPWM_GEN2_A_UTEP_V 0x00000003U +#define MCPWM_GEN2_A_UTEP_S 2 +/** MCPWM_GEN2_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEA 0x00000003U +#define MCPWM_GEN2_A_UTEA_M (MCPWM_GEN2_A_UTEA_V << MCPWM_GEN2_A_UTEA_S) +#define MCPWM_GEN2_A_UTEA_V 0x00000003U +#define MCPWM_GEN2_A_UTEA_S 4 +/** MCPWM_GEN2_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEB 0x00000003U +#define MCPWM_GEN2_A_UTEB_M (MCPWM_GEN2_A_UTEB_V << MCPWM_GEN2_A_UTEB_S) +#define MCPWM_GEN2_A_UTEB_V 0x00000003U +#define MCPWM_GEN2_A_UTEB_S 6 +/** MCPWM_GEN2_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT0 0x00000003U +#define MCPWM_GEN2_A_UT0_M (MCPWM_GEN2_A_UT0_V << MCPWM_GEN2_A_UT0_S) +#define MCPWM_GEN2_A_UT0_V 0x00000003U +#define MCPWM_GEN2_A_UT0_S 8 +/** MCPWM_GEN2_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT1 0x00000003U +#define MCPWM_GEN2_A_UT1_M (MCPWM_GEN2_A_UT1_V << MCPWM_GEN2_A_UT1_S) +#define MCPWM_GEN2_A_UT1_V 0x00000003U +#define MCPWM_GEN2_A_UT1_S 10 +/** MCPWM_GEN2_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEZ 0x00000003U +#define MCPWM_GEN2_A_DTEZ_M (MCPWM_GEN2_A_DTEZ_V << MCPWM_GEN2_A_DTEZ_S) +#define MCPWM_GEN2_A_DTEZ_V 0x00000003U +#define MCPWM_GEN2_A_DTEZ_S 12 +/** MCPWM_GEN2_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEP 0x00000003U +#define MCPWM_GEN2_A_DTEP_M (MCPWM_GEN2_A_DTEP_V << MCPWM_GEN2_A_DTEP_S) +#define MCPWM_GEN2_A_DTEP_V 0x00000003U +#define MCPWM_GEN2_A_DTEP_S 14 +/** MCPWM_GEN2_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEA 0x00000003U +#define MCPWM_GEN2_A_DTEA_M (MCPWM_GEN2_A_DTEA_V << MCPWM_GEN2_A_DTEA_S) +#define MCPWM_GEN2_A_DTEA_V 0x00000003U +#define MCPWM_GEN2_A_DTEA_S 16 +/** MCPWM_GEN2_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEB 0x00000003U +#define MCPWM_GEN2_A_DTEB_M (MCPWM_GEN2_A_DTEB_V << MCPWM_GEN2_A_DTEB_S) +#define MCPWM_GEN2_A_DTEB_V 0x00000003U +#define MCPWM_GEN2_A_DTEB_S 18 +/** MCPWM_GEN2_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT0 0x00000003U +#define MCPWM_GEN2_A_DT0_M (MCPWM_GEN2_A_DT0_V << MCPWM_GEN2_A_DT0_S) +#define MCPWM_GEN2_A_DT0_V 0x00000003U +#define MCPWM_GEN2_A_DT0_S 20 +/** MCPWM_GEN2_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT1 0x00000003U +#define MCPWM_GEN2_A_DT1_M (MCPWM_GEN2_A_DT1_V << MCPWM_GEN2_A_DT1_S) +#define MCPWM_GEN2_A_DT1_V 0x00000003U +#define MCPWM_GEN2_A_DT1_S 22 -#define MCPWM_GEN2_B_REG(i) (REG_MCPWM_BASE(i) + 0x00c4) -/* MCPWM_GEN2_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN2_B_DT1 0x00000003 -#define MCPWM_GEN2_B_DT1_M ((MCPWM_GEN2_B_DT1_V)<<(MCPWM_GEN2_B_DT1_S)) -#define MCPWM_GEN2_B_DT1_V 0x3 -#define MCPWM_GEN2_B_DT1_S 22 -/* MCPWM_GEN2_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN2_B_DT0 0x00000003 -#define MCPWM_GEN2_B_DT0_M ((MCPWM_GEN2_B_DT0_V)<<(MCPWM_GEN2_B_DT0_S)) -#define MCPWM_GEN2_B_DT0_V 0x3 -#define MCPWM_GEN2_B_DT0_S 20 -/* MCPWM_GEN2_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN2_B_DTEB 0x00000003 -#define MCPWM_GEN2_B_DTEB_M ((MCPWM_GEN2_B_DTEB_V)<<(MCPWM_GEN2_B_DTEB_S)) -#define MCPWM_GEN2_B_DTEB_V 0x3 -#define MCPWM_GEN2_B_DTEB_S 18 -/* MCPWM_GEN2_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN2_B_DTEA 0x00000003 -#define MCPWM_GEN2_B_DTEA_M ((MCPWM_GEN2_B_DTEA_V)<<(MCPWM_GEN2_B_DTEA_S)) -#define MCPWM_GEN2_B_DTEA_V 0x3 -#define MCPWM_GEN2_B_DTEA_S 16 -/* MCPWM_GEN2_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN2_B_DTEP 0x00000003 -#define MCPWM_GEN2_B_DTEP_M ((MCPWM_GEN2_B_DTEP_V)<<(MCPWM_GEN2_B_DTEP_S)) -#define MCPWM_GEN2_B_DTEP_V 0x3 -#define MCPWM_GEN2_B_DTEP_S 14 -/* MCPWM_GEN2_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN2_B_DTEZ 0x00000003 -#define MCPWM_GEN2_B_DTEZ_M ((MCPWM_GEN2_B_DTEZ_V)<<(MCPWM_GEN2_B_DTEZ_S)) -#define MCPWM_GEN2_B_DTEZ_V 0x3 -#define MCPWM_GEN2_B_DTEZ_S 12 -/* MCPWM_GEN2_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN2_B_UT1 0x00000003 -#define MCPWM_GEN2_B_UT1_M ((MCPWM_GEN2_B_UT1_V)<<(MCPWM_GEN2_B_UT1_S)) -#define MCPWM_GEN2_B_UT1_V 0x3 -#define MCPWM_GEN2_B_UT1_S 10 -/* MCPWM_GEN2_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN2_B_UT0 0x00000003 -#define MCPWM_GEN2_B_UT0_M ((MCPWM_GEN2_B_UT0_V)<<(MCPWM_GEN2_B_UT0_S)) -#define MCPWM_GEN2_B_UT0_V 0x3 -#define MCPWM_GEN2_B_UT0_S 8 -/* MCPWM_GEN2_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEB when timer increasing*/ -#define MCPWM_GEN2_B_UTEB 0x00000003 -#define MCPWM_GEN2_B_UTEB_M ((MCPWM_GEN2_B_UTEB_V)<<(MCPWM_GEN2_B_UTEB_S)) -#define MCPWM_GEN2_B_UTEB_V 0x3 -#define MCPWM_GEN2_B_UTEB_S 6 -/* MCPWM_GEN2_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEA when timer increasing*/ -#define MCPWM_GEN2_B_UTEA 0x00000003 -#define MCPWM_GEN2_B_UTEA_M ((MCPWM_GEN2_B_UTEA_V)<<(MCPWM_GEN2_B_UTEA_S)) -#define MCPWM_GEN2_B_UTEA_V 0x3 -#define MCPWM_GEN2_B_UTEA_S 4 -/* MCPWM_GEN2_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEP when timer increasing*/ -#define MCPWM_GEN2_B_UTEP 0x00000003 -#define MCPWM_GEN2_B_UTEP_M ((MCPWM_GEN2_B_UTEP_V)<<(MCPWM_GEN2_B_UTEP_S)) -#define MCPWM_GEN2_B_UTEP_V 0x3 -#define MCPWM_GEN2_B_UTEP_S 2 -/* MCPWM_GEN2_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN2_B_UTEZ 0x00000003 -#define MCPWM_GEN2_B_UTEZ_M ((MCPWM_GEN2_B_UTEZ_V)<<(MCPWM_GEN2_B_UTEZ_S)) -#define MCPWM_GEN2_B_UTEZ_V 0x3 +/** MCPWM_GEN2_B_REG register + * Actions triggered by events on PWM2B + */ +#define MCPWM_GEN2_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc4) +/** MCPWM_GEN2_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEZ 0x00000003U +#define MCPWM_GEN2_B_UTEZ_M (MCPWM_GEN2_B_UTEZ_V << MCPWM_GEN2_B_UTEZ_S) +#define MCPWM_GEN2_B_UTEZ_V 0x00000003U #define MCPWM_GEN2_B_UTEZ_S 0 +/** MCPWM_GEN2_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEP 0x00000003U +#define MCPWM_GEN2_B_UTEP_M (MCPWM_GEN2_B_UTEP_V << MCPWM_GEN2_B_UTEP_S) +#define MCPWM_GEN2_B_UTEP_V 0x00000003U +#define MCPWM_GEN2_B_UTEP_S 2 +/** MCPWM_GEN2_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEA 0x00000003U +#define MCPWM_GEN2_B_UTEA_M (MCPWM_GEN2_B_UTEA_V << MCPWM_GEN2_B_UTEA_S) +#define MCPWM_GEN2_B_UTEA_V 0x00000003U +#define MCPWM_GEN2_B_UTEA_S 4 +/** MCPWM_GEN2_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEB 0x00000003U +#define MCPWM_GEN2_B_UTEB_M (MCPWM_GEN2_B_UTEB_V << MCPWM_GEN2_B_UTEB_S) +#define MCPWM_GEN2_B_UTEB_V 0x00000003U +#define MCPWM_GEN2_B_UTEB_S 6 +/** MCPWM_GEN2_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT0 0x00000003U +#define MCPWM_GEN2_B_UT0_M (MCPWM_GEN2_B_UT0_V << MCPWM_GEN2_B_UT0_S) +#define MCPWM_GEN2_B_UT0_V 0x00000003U +#define MCPWM_GEN2_B_UT0_S 8 +/** MCPWM_GEN2_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT1 0x00000003U +#define MCPWM_GEN2_B_UT1_M (MCPWM_GEN2_B_UT1_V << MCPWM_GEN2_B_UT1_S) +#define MCPWM_GEN2_B_UT1_V 0x00000003U +#define MCPWM_GEN2_B_UT1_S 10 +/** MCPWM_GEN2_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEZ 0x00000003U +#define MCPWM_GEN2_B_DTEZ_M (MCPWM_GEN2_B_DTEZ_V << MCPWM_GEN2_B_DTEZ_S) +#define MCPWM_GEN2_B_DTEZ_V 0x00000003U +#define MCPWM_GEN2_B_DTEZ_S 12 +/** MCPWM_GEN2_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEP 0x00000003U +#define MCPWM_GEN2_B_DTEP_M (MCPWM_GEN2_B_DTEP_V << MCPWM_GEN2_B_DTEP_S) +#define MCPWM_GEN2_B_DTEP_V 0x00000003U +#define MCPWM_GEN2_B_DTEP_S 14 +/** MCPWM_GEN2_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEA 0x00000003U +#define MCPWM_GEN2_B_DTEA_M (MCPWM_GEN2_B_DTEA_V << MCPWM_GEN2_B_DTEA_S) +#define MCPWM_GEN2_B_DTEA_V 0x00000003U +#define MCPWM_GEN2_B_DTEA_S 16 +/** MCPWM_GEN2_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEB 0x00000003U +#define MCPWM_GEN2_B_DTEB_M (MCPWM_GEN2_B_DTEB_V << MCPWM_GEN2_B_DTEB_S) +#define MCPWM_GEN2_B_DTEB_V 0x00000003U +#define MCPWM_GEN2_B_DTEB_S 18 +/** MCPWM_GEN2_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT0 0x00000003U +#define MCPWM_GEN2_B_DT0_M (MCPWM_GEN2_B_DT0_V << MCPWM_GEN2_B_DT0_S) +#define MCPWM_GEN2_B_DT0_V 0x00000003U +#define MCPWM_GEN2_B_DT0_S 20 +/** MCPWM_GEN2_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT1 0x00000003U +#define MCPWM_GEN2_B_DT1_M (MCPWM_GEN2_B_DT1_V << MCPWM_GEN2_B_DT1_S) +#define MCPWM_GEN2_B_DT1_V 0x00000003U +#define MCPWM_GEN2_B_DT1_S 22 -#define MCPWM_DT2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00c8) -/* MCPWM_DT2_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Dead time generator 1 clock selection. 0: PWM_clk 1: PT_clk*/ -#define MCPWM_DT2_CLK_SEL (BIT(17)) -#define MCPWM_DT2_CLK_SEL_M (BIT(17)) -#define MCPWM_DT2_CLK_SEL_V 0x1 -#define MCPWM_DT2_CLK_SEL_S 17 -/* MCPWM_DT2_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: S0 in documentation*/ -#define MCPWM_DT2_B_OUTBYPASS (BIT(16)) -#define MCPWM_DT2_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DT2_B_OUTBYPASS_V 0x1 -#define MCPWM_DT2_B_OUTBYPASS_S 16 -/* MCPWM_DT2_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: S1 in documentation*/ -#define MCPWM_DT2_A_OUTBYPASS (BIT(15)) -#define MCPWM_DT2_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DT2_A_OUTBYPASS_V 0x1 -#define MCPWM_DT2_A_OUTBYPASS_S 15 -/* MCPWM_DT2_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: S3 in documentation*/ -#define MCPWM_DT2_FED_OUTINVERT (BIT(14)) -#define MCPWM_DT2_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DT2_FED_OUTINVERT_V 0x1 -#define MCPWM_DT2_FED_OUTINVERT_S 14 -/* MCPWM_DT2_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: S2 in documentation*/ -#define MCPWM_DT2_RED_OUTINVERT (BIT(13)) -#define MCPWM_DT2_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DT2_RED_OUTINVERT_V 0x1 -#define MCPWM_DT2_RED_OUTINVERT_S 13 -/* MCPWM_DT2_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: S5 in documentation*/ -#define MCPWM_DT2_FED_INSEL (BIT(12)) -#define MCPWM_DT2_FED_INSEL_M (BIT(12)) -#define MCPWM_DT2_FED_INSEL_V 0x1 -#define MCPWM_DT2_FED_INSEL_S 12 -/* MCPWM_DT2_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: S4 in documentation*/ -#define MCPWM_DT2_RED_INSEL (BIT(11)) -#define MCPWM_DT2_RED_INSEL_M (BIT(11)) -#define MCPWM_DT2_RED_INSEL_V 0x1 -#define MCPWM_DT2_RED_INSEL_S 11 -/* MCPWM_DT2_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: S7 in documentation*/ -#define MCPWM_DT2_B_OUTSWAP (BIT(10)) -#define MCPWM_DT2_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DT2_B_OUTSWAP_V 0x1 -#define MCPWM_DT2_B_OUTSWAP_S 10 -/* MCPWM_DT2_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: S6 in documentation*/ -#define MCPWM_DT2_A_OUTSWAP (BIT(9)) -#define MCPWM_DT2_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DT2_A_OUTSWAP_V 0x1 -#define MCPWM_DT2_A_OUTSWAP_S 9 -/* MCPWM_DT2_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: S8 in documentation dual-edge B mode 0: FED/RED take effect - on different path separately 1: FED/RED take effect on B path A out is in bypass or normal operation mode*/ -#define MCPWM_DT2_DEB_MODE (BIT(8)) -#define MCPWM_DT2_DEB_MODE_M (BIT(8)) -#define MCPWM_DT2_DEB_MODE_V 0x1 -#define MCPWM_DT2_DEB_MODE_S 8 -/* MCPWM_DT2_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for RED (rising edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT2_RED_UPMETHOD 0x0000000F -#define MCPWM_DT2_RED_UPMETHOD_M ((MCPWM_DT2_RED_UPMETHOD_V)<<(MCPWM_DT2_RED_UPMETHOD_S)) -#define MCPWM_DT2_RED_UPMETHOD_V 0xF -#define MCPWM_DT2_RED_UPMETHOD_S 4 -/* MCPWM_DT2_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for FED (falling edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT2_FED_UPMETHOD 0x0000000F -#define MCPWM_DT2_FED_UPMETHOD_M ((MCPWM_DT2_FED_UPMETHOD_V)<<(MCPWM_DT2_FED_UPMETHOD_S)) -#define MCPWM_DT2_FED_UPMETHOD_V 0xF +/** MCPWM_DT2_CFG_REG register + * PWM generator 2 dead time type selection and configuration + */ +#define MCPWM_DT2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc8) +/** MCPWM_DT2_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_FED_UPMETHOD_M (MCPWM_DT2_FED_UPMETHOD_V << MCPWM_DT2_FED_UPMETHOD_S) +#define MCPWM_DT2_FED_UPMETHOD_V 0x0000000FU #define MCPWM_DT2_FED_UPMETHOD_S 0 +/** MCPWM_DT2_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_M (MCPWM_DT2_RED_UPMETHOD_V << MCPWM_DT2_RED_UPMETHOD_S) +#define MCPWM_DT2_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_S 4 +/** MCPWM_DT2_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT2_DEB_MODE (BIT(8)) +#define MCPWM_DT2_DEB_MODE_M (MCPWM_DT2_DEB_MODE_V << MCPWM_DT2_DEB_MODE_S) +#define MCPWM_DT2_DEB_MODE_V 0x00000001U +#define MCPWM_DT2_DEB_MODE_S 8 +/** MCPWM_DT2_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT2_A_OUTSWAP (BIT(9)) +#define MCPWM_DT2_A_OUTSWAP_M (MCPWM_DT2_A_OUTSWAP_V << MCPWM_DT2_A_OUTSWAP_S) +#define MCPWM_DT2_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_A_OUTSWAP_S 9 +/** MCPWM_DT2_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT2_B_OUTSWAP (BIT(10)) +#define MCPWM_DT2_B_OUTSWAP_M (MCPWM_DT2_B_OUTSWAP_V << MCPWM_DT2_B_OUTSWAP_S) +#define MCPWM_DT2_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_B_OUTSWAP_S 10 +/** MCPWM_DT2_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT2_RED_INSEL (BIT(11)) +#define MCPWM_DT2_RED_INSEL_M (MCPWM_DT2_RED_INSEL_V << MCPWM_DT2_RED_INSEL_S) +#define MCPWM_DT2_RED_INSEL_V 0x00000001U +#define MCPWM_DT2_RED_INSEL_S 11 +/** MCPWM_DT2_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT2_FED_INSEL (BIT(12)) +#define MCPWM_DT2_FED_INSEL_M (MCPWM_DT2_FED_INSEL_V << MCPWM_DT2_FED_INSEL_S) +#define MCPWM_DT2_FED_INSEL_V 0x00000001U +#define MCPWM_DT2_FED_INSEL_S 12 +/** MCPWM_DT2_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT2_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT2_RED_OUTINVERT_M (MCPWM_DT2_RED_OUTINVERT_V << MCPWM_DT2_RED_OUTINVERT_S) +#define MCPWM_DT2_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_RED_OUTINVERT_S 13 +/** MCPWM_DT2_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT2_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT2_FED_OUTINVERT_M (MCPWM_DT2_FED_OUTINVERT_V << MCPWM_DT2_FED_OUTINVERT_S) +#define MCPWM_DT2_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_FED_OUTINVERT_S 14 +/** MCPWM_DT2_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT2_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT2_A_OUTBYPASS_M (MCPWM_DT2_A_OUTBYPASS_V << MCPWM_DT2_A_OUTBYPASS_S) +#define MCPWM_DT2_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_A_OUTBYPASS_S 15 +/** MCPWM_DT2_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT2_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT2_B_OUTBYPASS_M (MCPWM_DT2_B_OUTBYPASS_V << MCPWM_DT2_B_OUTBYPASS_S) +#define MCPWM_DT2_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_B_OUTBYPASS_S 16 +/** MCPWM_DT2_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT2_CLK_SEL (BIT(17)) +#define MCPWM_DT2_CLK_SEL_M (MCPWM_DT2_CLK_SEL_V << MCPWM_DT2_CLK_SEL_S) +#define MCPWM_DT2_CLK_SEL_V 0x00000001U +#define MCPWM_DT2_CLK_SEL_S 17 -#define MCPWM_DT2_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00cc) -/* MCPWM_DT2_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for FED*/ -#define MCPWM_DT2_FED 0x0000FFFF -#define MCPWM_DT2_FED_M ((MCPWM_DT2_FED_V)<<(MCPWM_DT2_FED_S)) -#define MCPWM_DT2_FED_V 0xFFFF +/** MCPWM_DT2_FED_CFG_REG register + * PWM generator 2 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT2_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xcc) +/** MCPWM_DT2_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT2_FED 0x0000FFFFU +#define MCPWM_DT2_FED_M (MCPWM_DT2_FED_V << MCPWM_DT2_FED_S) +#define MCPWM_DT2_FED_V 0x0000FFFFU #define MCPWM_DT2_FED_S 0 -#define MCPWM_DT2_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00d0) -/* MCPWM_DT2_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for RED*/ -#define MCPWM_DT2_RED 0x0000FFFF -#define MCPWM_DT2_RED_M ((MCPWM_DT2_RED_V)<<(MCPWM_DT2_RED_S)) -#define MCPWM_DT2_RED_V 0xFFFF +/** MCPWM_DT2_RED_CFG_REG register + * PWM generator 2 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT2_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd0) +/** MCPWM_DT2_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT2_RED 0x0000FFFFU +#define MCPWM_DT2_RED_M (MCPWM_DT2_RED_V << MCPWM_DT2_RED_S) +#define MCPWM_DT2_RED_V 0x0000FFFFU #define MCPWM_DT2_RED_S 0 -#define MCPWM_CARRIER2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00d4) -/* MCPWM_CARRIER2_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: When set invert the input of PWM2A and PWM2B for this submodule*/ -#define MCPWM_CARRIER2_IN_INVERT (BIT(13)) -#define MCPWM_CARRIER2_IN_INVERT_M (BIT(13)) -#define MCPWM_CARRIER2_IN_INVERT_V 0x1 -#define MCPWM_CARRIER2_IN_INVERT_S 13 -/* MCPWM_CARRIER2_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: When set invert the output of PWM2A and PWM2B for this submodule*/ -#define MCPWM_CARRIER2_OUT_INVERT (BIT(12)) -#define MCPWM_CARRIER2_OUT_INVERT_M (BIT(12)) -#define MCPWM_CARRIER2_OUT_INVERT_V 0x1 -#define MCPWM_CARRIER2_OUT_INVERT_S 12 -/* MCPWM_CARRIER2_OSHWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: Width of the fist pulse in number of periods of the carrier*/ -#define MCPWM_CARRIER2_OSHWTH 0x0000000F -#define MCPWM_CARRIER2_OSHWTH_M ((MCPWM_CARRIER2_OSHWTH_V)<<(MCPWM_CARRIER2_OSHWTH_S)) -#define MCPWM_CARRIER2_OSHWTH_V 0xF -#define MCPWM_CARRIER2_OSHWTH_S 8 -/* MCPWM_CARRIER2_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: Carrier duty selection. Duty = PWM_CARRIER2_DUTY / 8*/ -#define MCPWM_CARRIER2_DUTY 0x00000007 -#define MCPWM_CARRIER2_DUTY_M ((MCPWM_CARRIER2_DUTY_V)<<(MCPWM_CARRIER2_DUTY_S)) -#define MCPWM_CARRIER2_DUTY_V 0x7 -#define MCPWM_CARRIER2_DUTY_S 5 -/* MCPWM_CARRIER2_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: PWM carrier2 clock (PC_clk) prescale value. Period of PC_clk - = period of PWM_clk * (PWM_CARRIER2_PRESCALE + 1)*/ -#define MCPWM_CARRIER2_PRESCALE 0x0000000F -#define MCPWM_CARRIER2_PRESCALE_M ((MCPWM_CARRIER2_PRESCALE_V)<<(MCPWM_CARRIER2_PRESCALE_S)) -#define MCPWM_CARRIER2_PRESCALE_V 0xF -#define MCPWM_CARRIER2_PRESCALE_S 1 -/* MCPWM_CARRIER2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set carrier2 function is enabled. When cleared carrier2 is bypassed*/ -#define MCPWM_CARRIER2_EN (BIT(0)) -#define MCPWM_CARRIER2_EN_M (BIT(0)) -#define MCPWM_CARRIER2_EN_V 0x1 +/** MCPWM_CARRIER2_CFG_REG register + * PWM generator 2 carrier enable and configuratoin + */ +#define MCPWM_CARRIER2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd4) +/** MCPWM_CARRIER2_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier2 function is enabled. When cleared, carrier2 is bypassed + */ +#define MCPWM_CARRIER2_EN (BIT(0)) +#define MCPWM_CARRIER2_EN_M (MCPWM_CARRIER2_EN_V << MCPWM_CARRIER2_EN_S) +#define MCPWM_CARRIER2_EN_V 0x00000001U #define MCPWM_CARRIER2_EN_S 0 +/** MCPWM_CARRIER2_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier2 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER2_PRESCALE 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_M (MCPWM_CARRIER2_PRESCALE_V << MCPWM_CARRIER2_PRESCALE_S) +#define MCPWM_CARRIER2_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_S 1 +/** MCPWM_CARRIER2_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER2_DUTY 0x00000007U +#define MCPWM_CARRIER2_DUTY_M (MCPWM_CARRIER2_DUTY_V << MCPWM_CARRIER2_DUTY_S) +#define MCPWM_CARRIER2_DUTY_V 0x00000007U +#define MCPWM_CARRIER2_DUTY_S 5 +/** MCPWM_CARRIER2_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER2_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_M (MCPWM_CARRIER2_OSHTWTH_V << MCPWM_CARRIER2_OSHTWTH_S) +#define MCPWM_CARRIER2_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_S 8 +/** MCPWM_CARRIER2_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER2_OUT_INVERT_M (MCPWM_CARRIER2_OUT_INVERT_V << MCPWM_CARRIER2_OUT_INVERT_S) +#define MCPWM_CARRIER2_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_OUT_INVERT_S 12 +/** MCPWM_CARRIER2_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER2_IN_INVERT_M (MCPWM_CARRIER2_IN_INVERT_V << MCPWM_CARRIER2_IN_INVERT_S) +#define MCPWM_CARRIER2_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_IN_INVERT_S 13 -#define MCPWM_FH2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x00d8) -/* MCPWM_FH2_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2B when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_OST_U 0x00000003 -#define MCPWM_FH2_B_OST_U_M ((MCPWM_FH2_B_OST_U_V)<<(MCPWM_FH2_B_OST_U_S)) -#define MCPWM_FH2_B_OST_U_V 0x3 -#define MCPWM_FH2_B_OST_U_S 22 -/* MCPWM_FH2_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2B when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_OST_D 0x00000003 -#define MCPWM_FH2_B_OST_D_M ((MCPWM_FH2_B_OST_D_V)<<(MCPWM_FH2_B_OST_D_S)) -#define MCPWM_FH2_B_OST_D_V 0x3 -#define MCPWM_FH2_B_OST_D_S 20 -/* MCPWM_FH2_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2B when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_CBC_U 0x00000003 -#define MCPWM_FH2_B_CBC_U_M ((MCPWM_FH2_B_CBC_U_V)<<(MCPWM_FH2_B_CBC_U_S)) -#define MCPWM_FH2_B_CBC_U_V 0x3 -#define MCPWM_FH2_B_CBC_U_S 18 -/* MCPWM_FH2_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2B when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_CBC_D 0x00000003 -#define MCPWM_FH2_B_CBC_D_M ((MCPWM_FH2_B_CBC_D_V)<<(MCPWM_FH2_B_CBC_D_S)) -#define MCPWM_FH2_B_CBC_D_V 0x3 -#define MCPWM_FH2_B_CBC_D_S 16 -/* MCPWM_FH2_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2A when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_OST_U 0x00000003 -#define MCPWM_FH2_A_OST_U_M ((MCPWM_FH2_A_OST_U_V)<<(MCPWM_FH2_A_OST_U_S)) -#define MCPWM_FH2_A_OST_U_V 0x3 -#define MCPWM_FH2_A_OST_U_S 14 -/* MCPWM_FH2_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2A when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_OST_D 0x00000003 -#define MCPWM_FH2_A_OST_D_M ((MCPWM_FH2_A_OST_D_V)<<(MCPWM_FH2_A_OST_D_S)) -#define MCPWM_FH2_A_OST_D_V 0x3 -#define MCPWM_FH2_A_OST_D_S 12 -/* MCPWM_FH2_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2A when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_CBC_U 0x00000003 -#define MCPWM_FH2_A_CBC_U_M ((MCPWM_FH2_A_CBC_U_V)<<(MCPWM_FH2_A_CBC_U_S)) -#define MCPWM_FH2_A_CBC_U_V 0x3 -#define MCPWM_FH2_A_CBC_U_S 10 -/* MCPWM_FH2_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2A when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_CBC_D 0x00000003 -#define MCPWM_FH2_A_CBC_D_M ((MCPWM_FH2_A_CBC_D_V)<<(MCPWM_FH2_A_CBC_D_S)) -#define MCPWM_FH2_A_CBC_D_V 0x3 -#define MCPWM_FH2_A_CBC_D_S 8 -/* MCPWM_FH2_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: event_f0 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F0_OST (BIT(7)) -#define MCPWM_FH2_F0_OST_M (BIT(7)) -#define MCPWM_FH2_F0_OST_V 0x1 -#define MCPWM_FH2_F0_OST_S 7 -/* MCPWM_FH2_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: event_f1 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F1_OST (BIT(6)) -#define MCPWM_FH2_F1_OST_M (BIT(6)) -#define MCPWM_FH2_F1_OST_V 0x1 -#define MCPWM_FH2_F1_OST_S 6 -/* MCPWM_FH2_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: event_f2 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F2_OST (BIT(5)) -#define MCPWM_FH2_F2_OST_M (BIT(5)) -#define MCPWM_FH2_F2_OST_V 0x1 -#define MCPWM_FH2_F2_OST_S 5 -/* MCPWM_FH2_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Enable register for software force one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_SW_OST (BIT(4)) -#define MCPWM_FH2_SW_OST_M (BIT(4)) -#define MCPWM_FH2_SW_OST_V 0x1 -#define MCPWM_FH2_SW_OST_S 4 -/* MCPWM_FH2_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: event_f0 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F0_CBC (BIT(3)) -#define MCPWM_FH2_F0_CBC_M (BIT(3)) -#define MCPWM_FH2_F0_CBC_V 0x1 -#define MCPWM_FH2_F0_CBC_S 3 -/* MCPWM_FH2_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: event_f1 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F1_CBC (BIT(2)) -#define MCPWM_FH2_F1_CBC_M (BIT(2)) -#define MCPWM_FH2_F1_CBC_V 0x1 -#define MCPWM_FH2_F1_CBC_S 2 -/* MCPWM_FH2_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: event_f2 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F2_CBC (BIT(1)) -#define MCPWM_FH2_F2_CBC_M (BIT(1)) -#define MCPWM_FH2_F2_CBC_V 0x1 -#define MCPWM_FH2_F2_CBC_S 1 -/* MCPWM_FH2_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Enable register for software force cycle-by-cycle mode action. - 0: disable 1: enable*/ -#define MCPWM_FH2_SW_CBC (BIT(0)) -#define MCPWM_FH2_SW_CBC_M (BIT(0)) -#define MCPWM_FH2_SW_CBC_V 0x1 +/** MCPWM_FH2_CFG0_REG register + * Actions on PWM2A and PWM2B trip events + */ +#define MCPWM_FH2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd8) +/** MCPWM_FH2_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_CBC (BIT(0)) +#define MCPWM_FH2_SW_CBC_M (MCPWM_FH2_SW_CBC_V << MCPWM_FH2_SW_CBC_S) +#define MCPWM_FH2_SW_CBC_V 0x00000001U #define MCPWM_FH2_SW_CBC_S 0 +/** MCPWM_FH2_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_CBC (BIT(1)) +#define MCPWM_FH2_F2_CBC_M (MCPWM_FH2_F2_CBC_V << MCPWM_FH2_F2_CBC_S) +#define MCPWM_FH2_F2_CBC_V 0x00000001U +#define MCPWM_FH2_F2_CBC_S 1 +/** MCPWM_FH2_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_CBC (BIT(2)) +#define MCPWM_FH2_F1_CBC_M (MCPWM_FH2_F1_CBC_V << MCPWM_FH2_F1_CBC_S) +#define MCPWM_FH2_F1_CBC_V 0x00000001U +#define MCPWM_FH2_F1_CBC_S 2 +/** MCPWM_FH2_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_CBC (BIT(3)) +#define MCPWM_FH2_F0_CBC_M (MCPWM_FH2_F0_CBC_V << MCPWM_FH2_F0_CBC_S) +#define MCPWM_FH2_F0_CBC_V 0x00000001U +#define MCPWM_FH2_F0_CBC_S 3 +/** MCPWM_FH2_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_OST (BIT(4)) +#define MCPWM_FH2_SW_OST_M (MCPWM_FH2_SW_OST_V << MCPWM_FH2_SW_OST_S) +#define MCPWM_FH2_SW_OST_V 0x00000001U +#define MCPWM_FH2_SW_OST_S 4 +/** MCPWM_FH2_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_OST (BIT(5)) +#define MCPWM_FH2_F2_OST_M (MCPWM_FH2_F2_OST_V << MCPWM_FH2_F2_OST_S) +#define MCPWM_FH2_F2_OST_V 0x00000001U +#define MCPWM_FH2_F2_OST_S 5 +/** MCPWM_FH2_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_OST (BIT(6)) +#define MCPWM_FH2_F1_OST_M (MCPWM_FH2_F1_OST_V << MCPWM_FH2_F1_OST_S) +#define MCPWM_FH2_F1_OST_V 0x00000001U +#define MCPWM_FH2_F1_OST_S 6 +/** MCPWM_FH2_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_OST (BIT(7)) +#define MCPWM_FH2_F0_OST_M (MCPWM_FH2_F0_OST_V << MCPWM_FH2_F0_OST_S) +#define MCPWM_FH2_F0_OST_V 0x00000001U +#define MCPWM_FH2_F0_OST_S 7 +/** MCPWM_FH2_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_D 0x00000003U +#define MCPWM_FH2_A_CBC_D_M (MCPWM_FH2_A_CBC_D_V << MCPWM_FH2_A_CBC_D_S) +#define MCPWM_FH2_A_CBC_D_V 0x00000003U +#define MCPWM_FH2_A_CBC_D_S 8 +/** MCPWM_FH2_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_U 0x00000003U +#define MCPWM_FH2_A_CBC_U_M (MCPWM_FH2_A_CBC_U_V << MCPWM_FH2_A_CBC_U_S) +#define MCPWM_FH2_A_CBC_U_V 0x00000003U +#define MCPWM_FH2_A_CBC_U_S 10 +/** MCPWM_FH2_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_D 0x00000003U +#define MCPWM_FH2_A_OST_D_M (MCPWM_FH2_A_OST_D_V << MCPWM_FH2_A_OST_D_S) +#define MCPWM_FH2_A_OST_D_V 0x00000003U +#define MCPWM_FH2_A_OST_D_S 12 +/** MCPWM_FH2_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_U 0x00000003U +#define MCPWM_FH2_A_OST_U_M (MCPWM_FH2_A_OST_U_V << MCPWM_FH2_A_OST_U_S) +#define MCPWM_FH2_A_OST_U_V 0x00000003U +#define MCPWM_FH2_A_OST_U_S 14 +/** MCPWM_FH2_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_D 0x00000003U +#define MCPWM_FH2_B_CBC_D_M (MCPWM_FH2_B_CBC_D_V << MCPWM_FH2_B_CBC_D_S) +#define MCPWM_FH2_B_CBC_D_V 0x00000003U +#define MCPWM_FH2_B_CBC_D_S 16 +/** MCPWM_FH2_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_U 0x00000003U +#define MCPWM_FH2_B_CBC_U_M (MCPWM_FH2_B_CBC_U_V << MCPWM_FH2_B_CBC_U_S) +#define MCPWM_FH2_B_CBC_U_V 0x00000003U +#define MCPWM_FH2_B_CBC_U_S 18 +/** MCPWM_FH2_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_D 0x00000003U +#define MCPWM_FH2_B_OST_D_M (MCPWM_FH2_B_OST_D_V << MCPWM_FH2_B_OST_D_S) +#define MCPWM_FH2_B_OST_D_V 0x00000003U +#define MCPWM_FH2_B_OST_D_S 20 +/** MCPWM_FH2_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_U 0x00000003U +#define MCPWM_FH2_B_OST_U_M (MCPWM_FH2_B_OST_U_V << MCPWM_FH2_B_OST_U_S) +#define MCPWM_FH2_B_OST_U_V 0x00000003U +#define MCPWM_FH2_B_OST_U_S 22 -#define MCPWM_FH2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x00dc) -/* MCPWM_FH2_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) triggers a - one-shot mode action*/ -#define MCPWM_FH2_FORCE_OST (BIT(4)) -#define MCPWM_FH2_FORCE_OST_M (BIT(4)) -#define MCPWM_FH2_FORCE_OST_V 0x1 -#define MCPWM_FH2_FORCE_OST_S 4 -/* MCPWM_FH2_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle triggers a cycle-by-cycle mode action*/ -#define MCPWM_FH2_FORCE_CBC (BIT(3)) -#define MCPWM_FH2_FORCE_CBC_M (BIT(3)) -#define MCPWM_FH2_FORCE_CBC_V 0x1 -#define MCPWM_FH2_FORCE_CBC_S 3 -/* MCPWM_FH2_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: The cycle-by-cycle mode action refresh moment selection. Bit0: TEZ bit1:TEP*/ -#define MCPWM_FH2_CBCPULSE 0x00000003 -#define MCPWM_FH2_CBCPULSE_M ((MCPWM_FH2_CBCPULSE_V)<<(MCPWM_FH2_CBCPULSE_S)) -#define MCPWM_FH2_CBCPULSE_V 0x3 -#define MCPWM_FH2_CBCPULSE_S 1 -/* MCPWM_FH2_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: A toggle will clear on going one-shot mode action*/ -#define MCPWM_FH2_CLR_OST (BIT(0)) -#define MCPWM_FH2_CLR_OST_M (BIT(0)) -#define MCPWM_FH2_CLR_OST_V 0x1 +/** MCPWM_FH2_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xdc) +/** MCPWM_FH2_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH2_CLR_OST (BIT(0)) +#define MCPWM_FH2_CLR_OST_M (MCPWM_FH2_CLR_OST_V << MCPWM_FH2_CLR_OST_S) +#define MCPWM_FH2_CLR_OST_V 0x00000001U #define MCPWM_FH2_CLR_OST_S 0 +/** MCPWM_FH2_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH2_CBCPULSE 0x00000003U +#define MCPWM_FH2_CBCPULSE_M (MCPWM_FH2_CBCPULSE_V << MCPWM_FH2_CBCPULSE_S) +#define MCPWM_FH2_CBCPULSE_V 0x00000003U +#define MCPWM_FH2_CBCPULSE_S 1 +/** MCPWM_FH2_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH2_FORCE_CBC (BIT(3)) +#define MCPWM_FH2_FORCE_CBC_M (MCPWM_FH2_FORCE_CBC_V << MCPWM_FH2_FORCE_CBC_S) +#define MCPWM_FH2_FORCE_CBC_V 0x00000001U +#define MCPWM_FH2_FORCE_CBC_S 3 +/** MCPWM_FH2_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH2_FORCE_OST (BIT(4)) +#define MCPWM_FH2_FORCE_OST_M (MCPWM_FH2_FORCE_OST_V << MCPWM_FH2_FORCE_OST_S) +#define MCPWM_FH2_FORCE_OST_V 0x00000001U +#define MCPWM_FH2_FORCE_OST_S 4 -#define MCPWM_FH2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x00e0) -/* MCPWM_FH2_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an one-shot mode action is on going*/ -#define MCPWM_FH2_OST_ON (BIT(1)) -#define MCPWM_FH2_OST_ON_M (BIT(1)) -#define MCPWM_FH2_OST_ON_V 0x1 -#define MCPWM_FH2_OST_ON_S 1 -/* MCPWM_FH2_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an cycle-by-cycle mode action is on going*/ -#define MCPWM_FH2_CBC_ON (BIT(0)) -#define MCPWM_FH2_CBC_ON_M (BIT(0)) -#define MCPWM_FH2_CBC_ON_V 0x1 +/** MCPWM_FH2_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe0) +/** MCPWM_FH2_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH2_CBC_ON (BIT(0)) +#define MCPWM_FH2_CBC_ON_M (MCPWM_FH2_CBC_ON_V << MCPWM_FH2_CBC_ON_S) +#define MCPWM_FH2_CBC_ON_V 0x00000001U #define MCPWM_FH2_CBC_ON_S 0 +/** MCPWM_FH2_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH2_OST_ON (BIT(1)) +#define MCPWM_FH2_OST_ON_M (MCPWM_FH2_OST_ON_V << MCPWM_FH2_OST_ON_S) +#define MCPWM_FH2_OST_ON_V 0x00000001U +#define MCPWM_FH2_OST_ON_S 1 -#define MCPWM_FAULT_DETECT_REG(i) (REG_MCPWM_BASE(i) + 0x00e4) -/* MCPWM_EVENT_F2 : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set event_f2 is on going*/ -#define MCPWM_EVENT_F2 (BIT(8)) -#define MCPWM_EVENT_F2_M (BIT(8)) -#define MCPWM_EVENT_F2_V 0x1 -#define MCPWM_EVENT_F2_S 8 -/* MCPWM_EVENT_F1 : RO ;bitpos:[7] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set event_f1 is on going*/ -#define MCPWM_EVENT_F1 (BIT(7)) -#define MCPWM_EVENT_F1_M (BIT(7)) -#define MCPWM_EVENT_F1_V 0x1 -#define MCPWM_EVENT_F1_S 7 -/* MCPWM_EVENT_F0 : RO ;bitpos:[6] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set event_f0 is on going*/ -#define MCPWM_EVENT_F0 (BIT(6)) -#define MCPWM_EVENT_F0_M (BIT(6)) -#define MCPWM_EVENT_F0_V 0x1 -#define MCPWM_EVENT_F0_S 6 -/* MCPWM_F2_POLE : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: Set event_f2 trigger polarity on FAULT2 source from GPIO matrix. - 0: level low 1: level high*/ -#define MCPWM_F2_POLE (BIT(5)) -#define MCPWM_F2_POLE_M (BIT(5)) -#define MCPWM_F2_POLE_V 0x1 -#define MCPWM_F2_POLE_S 5 -/* MCPWM_F1_POLE : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Set event_f1 trigger polarity on FAULT2 source from GPIO matrix. - 0: level low 1: level high*/ -#define MCPWM_F1_POLE (BIT(4)) -#define MCPWM_F1_POLE_M (BIT(4)) -#define MCPWM_F1_POLE_V 0x1 -#define MCPWM_F1_POLE_S 4 -/* MCPWM_F0_POLE : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: Set event_f0 trigger polarity on FAULT2 source from GPIO matrix. - 0: level low 1: level high*/ -#define MCPWM_F0_POLE (BIT(3)) -#define MCPWM_F0_POLE_M (BIT(3)) -#define MCPWM_F0_POLE_V 0x1 -#define MCPWM_F0_POLE_S 3 -/* MCPWM_F2_EN : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: Set to enable generation of event_f2*/ -#define MCPWM_F2_EN (BIT(2)) -#define MCPWM_F2_EN_M (BIT(2)) -#define MCPWM_F2_EN_V 0x1 -#define MCPWM_F2_EN_S 2 -/* MCPWM_F1_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set to enable generation of event_f1*/ -#define MCPWM_F1_EN (BIT(1)) -#define MCPWM_F1_EN_M (BIT(1)) -#define MCPWM_F1_EN_V 0x1 -#define MCPWM_F1_EN_S 1 -/* MCPWM_F0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set to enable generation of event_f0*/ -#define MCPWM_F0_EN (BIT(0)) -#define MCPWM_F0_EN_M (BIT(0)) -#define MCPWM_F0_EN_V 0x1 +/** MCPWM_FAULT_DETECT_REG register + * Fault detection configuration and status + */ +#define MCPWM_FAULT_DETECT_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe4) +/** MCPWM_F0_EN : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ +#define MCPWM_F0_EN (BIT(0)) +#define MCPWM_F0_EN_M (MCPWM_F0_EN_V << MCPWM_F0_EN_S) +#define MCPWM_F0_EN_V 0x00000001U #define MCPWM_F0_EN_S 0 +/** MCPWM_F1_EN : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ +#define MCPWM_F1_EN (BIT(1)) +#define MCPWM_F1_EN_M (MCPWM_F1_EN_V << MCPWM_F1_EN_S) +#define MCPWM_F1_EN_V 0x00000001U +#define MCPWM_F1_EN_S 1 +/** MCPWM_F2_EN : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ +#define MCPWM_F2_EN (BIT(2)) +#define MCPWM_F2_EN_M (MCPWM_F2_EN_V << MCPWM_F2_EN_S) +#define MCPWM_F2_EN_V 0x00000001U +#define MCPWM_F2_EN_S 2 +/** MCPWM_F0_POLE : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F0_POLE (BIT(3)) +#define MCPWM_F0_POLE_M (MCPWM_F0_POLE_V << MCPWM_F0_POLE_S) +#define MCPWM_F0_POLE_V 0x00000001U +#define MCPWM_F0_POLE_S 3 +/** MCPWM_F1_POLE : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F1_POLE (BIT(4)) +#define MCPWM_F1_POLE_M (MCPWM_F1_POLE_V << MCPWM_F1_POLE_S) +#define MCPWM_F1_POLE_V 0x00000001U +#define MCPWM_F1_POLE_S 4 +/** MCPWM_F2_POLE : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F2_POLE (BIT(5)) +#define MCPWM_F2_POLE_M (MCPWM_F2_POLE_V << MCPWM_F2_POLE_S) +#define MCPWM_F2_POLE_V 0x00000001U +#define MCPWM_F2_POLE_S 5 +/** MCPWM_EVENT_F0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ +#define MCPWM_EVENT_F0 (BIT(6)) +#define MCPWM_EVENT_F0_M (MCPWM_EVENT_F0_V << MCPWM_EVENT_F0_S) +#define MCPWM_EVENT_F0_V 0x00000001U +#define MCPWM_EVENT_F0_S 6 +/** MCPWM_EVENT_F1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ +#define MCPWM_EVENT_F1 (BIT(7)) +#define MCPWM_EVENT_F1_M (MCPWM_EVENT_F1_V << MCPWM_EVENT_F1_S) +#define MCPWM_EVENT_F1_V 0x00000001U +#define MCPWM_EVENT_F1_S 7 +/** MCPWM_EVENT_F2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ +#define MCPWM_EVENT_F2 (BIT(8)) +#define MCPWM_EVENT_F2_M (MCPWM_EVENT_F2_V << MCPWM_EVENT_F2_S) +#define MCPWM_EVENT_F2_V 0x00000001U +#define MCPWM_EVENT_F2_S 8 -#define MCPWM_CAP_TIMER_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00e8) -/* MCPWM_CAP_SYNC_SW : WO ;bitpos:[5] ;default: 1'd0 ; */ -/*description: Set this bit to force a capture timer sync capture timer is - loaded with value in phase register.*/ -#define MCPWM_CAP_SYNC_SW (BIT(5)) -#define MCPWM_CAP_SYNC_SW_M (BIT(5)) -#define MCPWM_CAP_SYNC_SW_V 0x1 -#define MCPWM_CAP_SYNC_SW_S 5 -/* MCPWM_CAP_SYNCI_SEL : R/W ;bitpos:[4:2] ;default: 3'd0 ; */ -/*description: Capture module sync input selection. 0: none 1: timer0 synco - 2: timer1 synco 3: timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix*/ -#define MCPWM_CAP_SYNCI_SEL 0x00000007 -#define MCPWM_CAP_SYNCI_SEL_M ((MCPWM_CAP_SYNCI_SEL_V)<<(MCPWM_CAP_SYNCI_SEL_S)) -#define MCPWM_CAP_SYNCI_SEL_V 0x7 -#define MCPWM_CAP_SYNCI_SEL_S 2 -/* MCPWM_CAP_SYNCI_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: When set capture timer sync is enabled.*/ -#define MCPWM_CAP_SYNCI_EN (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_M (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_V 0x1 -#define MCPWM_CAP_SYNCI_EN_S 1 -/* MCPWM_CAP_TIMER_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture timer incrementing under APB_clk is enabled.*/ -#define MCPWM_CAP_TIMER_EN (BIT(0)) -#define MCPWM_CAP_TIMER_EN_M (BIT(0)) -#define MCPWM_CAP_TIMER_EN_V 0x1 +/** MCPWM_CAP_TIMER_CFG_REG register + * Configure capture timer + */ +#define MCPWM_CAP_TIMER_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe8) +/** MCPWM_CAP_TIMER_EN : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ +#define MCPWM_CAP_TIMER_EN (BIT(0)) +#define MCPWM_CAP_TIMER_EN_M (MCPWM_CAP_TIMER_EN_V << MCPWM_CAP_TIMER_EN_S) +#define MCPWM_CAP_TIMER_EN_V 0x00000001U #define MCPWM_CAP_TIMER_EN_S 0 +/** MCPWM_CAP_SYNCI_EN : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ +#define MCPWM_CAP_SYNCI_EN (BIT(1)) +#define MCPWM_CAP_SYNCI_EN_M (MCPWM_CAP_SYNCI_EN_V << MCPWM_CAP_SYNCI_EN_S) +#define MCPWM_CAP_SYNCI_EN_V 0x00000001U +#define MCPWM_CAP_SYNCI_EN_S 1 +/** MCPWM_CAP_SYNCI_SEL : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ +#define MCPWM_CAP_SYNCI_SEL 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_M (MCPWM_CAP_SYNCI_SEL_V << MCPWM_CAP_SYNCI_SEL_S) +#define MCPWM_CAP_SYNCI_SEL_V 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_S 2 +/** MCPWM_CAP_SYNC_SW : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ +#define MCPWM_CAP_SYNC_SW (BIT(5)) +#define MCPWM_CAP_SYNC_SW_M (MCPWM_CAP_SYNC_SW_V << MCPWM_CAP_SYNC_SW_S) +#define MCPWM_CAP_SYNC_SW_V 0x00000001U +#define MCPWM_CAP_SYNC_SW_S 5 -#define MCPWM_CAP_TIMER_PHASE_REG(i) (REG_MCPWM_BASE(i) + 0x00ec) -/* MCPWM_CAP_PHASE : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Phase value for capture timer sync operation.*/ -#define MCPWM_CAP_PHASE 0xFFFFFFFF -#define MCPWM_CAP_PHASE_M ((MCPWM_CAP_PHASE_V)<<(MCPWM_CAP_PHASE_S)) -#define MCPWM_CAP_PHASE_V 0xFFFFFFFF -#define MCPWM_CAP_PHASE_S 0 +/** MCPWM_CAP_TIMER_PHASE_REG register + * Phase for capture timer sync + */ +#define MCPWM_CAP_TIMER_PHASE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xec) +/** MCPWM_CAP_TIMER_PHASE : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ +#define MCPWM_CAP_TIMER_PHASE 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_M (MCPWM_CAP_TIMER_PHASE_V << MCPWM_CAP_TIMER_PHASE_S) +#define MCPWM_CAP_TIMER_PHASE_V 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_S 0 -#define MCPWM_CAP_CH0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00f0) -/* MCPWM_CAP0_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a software forced capture on channel 0*/ -#define MCPWM_CAP0_SW (BIT(12)) -#define MCPWM_CAP0_SW_M (BIT(12)) -#define MCPWM_CAP0_SW_V 0x1 -#define MCPWM_CAP0_SW_S 12 -/* MCPWM_CAP0_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: When set CAP0 form GPIO matrix is inverted before prescale*/ -#define MCPWM_CAP0_IN_INVERT (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_V 0x1 -#define MCPWM_CAP0_IN_INVERT_S 11 -/* MCPWM_CAP0_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: Value of prescale on possitive edge of CAP0. Prescale value = - PWM_CAP0_PRESCALE + 1*/ -#define MCPWM_CAP0_PRESCALE 0x000000FF -#define MCPWM_CAP0_PRESCALE_M ((MCPWM_CAP0_PRESCALE_V)<<(MCPWM_CAP0_PRESCALE_S)) -#define MCPWM_CAP0_PRESCALE_V 0xFF -#define MCPWM_CAP0_PRESCALE_S 3 -/* MCPWM_CAP0_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: Edge of capture on channel 0 after prescale. bit0: negedge cap - en bit1: posedge cap en*/ -#define MCPWM_CAP0_MODE 0x00000003 -#define MCPWM_CAP0_MODE_M ((MCPWM_CAP0_MODE_V)<<(MCPWM_CAP0_MODE_S)) -#define MCPWM_CAP0_MODE_V 0x3 -#define MCPWM_CAP0_MODE_S 1 -/* MCPWM_CAP0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture on channel 0 is enabled*/ -#define MCPWM_CAP0_EN (BIT(0)) -#define MCPWM_CAP0_EN_M (BIT(0)) -#define MCPWM_CAP0_EN_V 0x1 +/** MCPWM_CAP_CH0_CFG_REG register + * Capture channel 0 configuration and enable + */ +#define MCPWM_CAP_CH0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf0) +/** MCPWM_CAP0_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ +#define MCPWM_CAP0_EN (BIT(0)) +#define MCPWM_CAP0_EN_M (MCPWM_CAP0_EN_V << MCPWM_CAP0_EN_S) +#define MCPWM_CAP0_EN_V 0x00000001U #define MCPWM_CAP0_EN_S 0 +/** MCPWM_CAP0_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP0_MODE 0x00000003U +#define MCPWM_CAP0_MODE_M (MCPWM_CAP0_MODE_V << MCPWM_CAP0_MODE_S) +#define MCPWM_CAP0_MODE_V 0x00000003U +#define MCPWM_CAP0_MODE_S 1 +/** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + + * 1 + */ +#define MCPWM_CAP0_PRESCALE 0x000000FFU +#define MCPWM_CAP0_PRESCALE_M (MCPWM_CAP0_PRESCALE_V << MCPWM_CAP0_PRESCALE_S) +#define MCPWM_CAP0_PRESCALE_V 0x000000FFU +#define MCPWM_CAP0_PRESCALE_S 3 +/** MCPWM_CAP0_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP0 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP0_IN_INVERT (BIT(11)) +#define MCPWM_CAP0_IN_INVERT_M (MCPWM_CAP0_IN_INVERT_V << MCPWM_CAP0_IN_INVERT_S) +#define MCPWM_CAP0_IN_INVERT_V 0x00000001U +#define MCPWM_CAP0_IN_INVERT_S 11 +/** MCPWM_CAP0_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ +#define MCPWM_CAP0_SW (BIT(12)) +#define MCPWM_CAP0_SW_M (MCPWM_CAP0_SW_V << MCPWM_CAP0_SW_S) +#define MCPWM_CAP0_SW_V 0x00000001U +#define MCPWM_CAP0_SW_S 12 -#define MCPWM_CAP_CH1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00f4) -/* MCPWM_CAP1_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a software forced capture on channel 1*/ -#define MCPWM_CAP1_SW (BIT(12)) -#define MCPWM_CAP1_SW_M (BIT(12)) -#define MCPWM_CAP1_SW_V 0x1 -#define MCPWM_CAP1_SW_S 12 -/* MCPWM_CAP1_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: When set CAP1 form GPIO matrix is inverted before prescale*/ -#define MCPWM_CAP1_IN_INVERT (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_V 0x1 -#define MCPWM_CAP1_IN_INVERT_S 11 -/* MCPWM_CAP1_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: Value of prescale on possitive edge of CAP1. Prescale value = - PWM_CAP1_PRESCALE + 1*/ -#define MCPWM_CAP1_PRESCALE 0x000000FF -#define MCPWM_CAP1_PRESCALE_M ((MCPWM_CAP1_PRESCALE_V)<<(MCPWM_CAP1_PRESCALE_S)) -#define MCPWM_CAP1_PRESCALE_V 0xFF -#define MCPWM_CAP1_PRESCALE_S 3 -/* MCPWM_CAP1_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: Edge of capture on channel 1 after prescale. bit0: negedge cap - en bit1: posedge cap en*/ -#define MCPWM_CAP1_MODE 0x00000003 -#define MCPWM_CAP1_MODE_M ((MCPWM_CAP1_MODE_V)<<(MCPWM_CAP1_MODE_S)) -#define MCPWM_CAP1_MODE_V 0x3 -#define MCPWM_CAP1_MODE_S 1 -/* MCPWM_CAP1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture on channel 1 is enabled*/ -#define MCPWM_CAP1_EN (BIT(0)) -#define MCPWM_CAP1_EN_M (BIT(0)) -#define MCPWM_CAP1_EN_V 0x1 +/** MCPWM_CAP_CH1_CFG_REG register + * Capture channel 1 configuration and enable + */ +#define MCPWM_CAP_CH1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf4) +/** MCPWM_CAP1_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ +#define MCPWM_CAP1_EN (BIT(0)) +#define MCPWM_CAP1_EN_M (MCPWM_CAP1_EN_V << MCPWM_CAP1_EN_S) +#define MCPWM_CAP1_EN_V 0x00000001U #define MCPWM_CAP1_EN_S 0 +/** MCPWM_CAP1_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 1 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP1_MODE 0x00000003U +#define MCPWM_CAP1_MODE_M (MCPWM_CAP1_MODE_V << MCPWM_CAP1_MODE_S) +#define MCPWM_CAP1_MODE_V 0x00000003U +#define MCPWM_CAP1_MODE_S 1 +/** MCPWM_CAP1_PRESCALE : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + + * 1 + */ +#define MCPWM_CAP1_PRESCALE 0x000000FFU +#define MCPWM_CAP1_PRESCALE_M (MCPWM_CAP1_PRESCALE_V << MCPWM_CAP1_PRESCALE_S) +#define MCPWM_CAP1_PRESCALE_V 0x000000FFU +#define MCPWM_CAP1_PRESCALE_S 3 +/** MCPWM_CAP1_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP1 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP1_IN_INVERT (BIT(11)) +#define MCPWM_CAP1_IN_INVERT_M (MCPWM_CAP1_IN_INVERT_V << MCPWM_CAP1_IN_INVERT_S) +#define MCPWM_CAP1_IN_INVERT_V 0x00000001U +#define MCPWM_CAP1_IN_INVERT_S 11 +/** MCPWM_CAP1_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 1 + */ +#define MCPWM_CAP1_SW (BIT(12)) +#define MCPWM_CAP1_SW_M (MCPWM_CAP1_SW_V << MCPWM_CAP1_SW_S) +#define MCPWM_CAP1_SW_V 0x00000001U +#define MCPWM_CAP1_SW_S 12 -#define MCPWM_CAP_CH2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00f8) -/* MCPWM_CAP2_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a software forced capture on channel 2*/ -#define MCPWM_CAP2_SW (BIT(12)) -#define MCPWM_CAP2_SW_M (BIT(12)) -#define MCPWM_CAP2_SW_V 0x1 -#define MCPWM_CAP2_SW_S 12 -/* MCPWM_CAP2_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: When set CAP2 form GPIO matrix is inverted before prescale*/ -#define MCPWM_CAP2_IN_INVERT (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_V 0x1 -#define MCPWM_CAP2_IN_INVERT_S 11 -/* MCPWM_CAP2_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: Value of prescale on possitive edge of CAP2. Prescale value = - PWM_CAP2_PRESCALE + 1*/ -#define MCPWM_CAP2_PRESCALE 0x000000FF -#define MCPWM_CAP2_PRESCALE_M ((MCPWM_CAP2_PRESCALE_V)<<(MCPWM_CAP2_PRESCALE_S)) -#define MCPWM_CAP2_PRESCALE_V 0xFF -#define MCPWM_CAP2_PRESCALE_S 3 -/* MCPWM_CAP2_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: Edge of capture on channel 2 after prescale. bit0: negedge cap - en bit1: posedge cap en*/ -#define MCPWM_CAP2_MODE 0x00000003 -#define MCPWM_CAP2_MODE_M ((MCPWM_CAP2_MODE_V)<<(MCPWM_CAP2_MODE_S)) -#define MCPWM_CAP2_MODE_V 0x3 -#define MCPWM_CAP2_MODE_S 1 -/* MCPWM_CAP2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture on channel 2 is enabled*/ -#define MCPWM_CAP2_EN (BIT(0)) -#define MCPWM_CAP2_EN_M (BIT(0)) -#define MCPWM_CAP2_EN_V 0x1 +/** MCPWM_CAP_CH2_CFG_REG register + * Capture channel 2 configuration and enable + */ +#define MCPWM_CAP_CH2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf8) +/** MCPWM_CAP2_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ +#define MCPWM_CAP2_EN (BIT(0)) +#define MCPWM_CAP2_EN_M (MCPWM_CAP2_EN_V << MCPWM_CAP2_EN_S) +#define MCPWM_CAP2_EN_V 0x00000001U #define MCPWM_CAP2_EN_S 0 +/** MCPWM_CAP2_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 2 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP2_MODE 0x00000003U +#define MCPWM_CAP2_MODE_M (MCPWM_CAP2_MODE_V << MCPWM_CAP2_MODE_S) +#define MCPWM_CAP2_MODE_V 0x00000003U +#define MCPWM_CAP2_MODE_S 1 +/** MCPWM_CAP2_PRESCALE : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + + * 1 + */ +#define MCPWM_CAP2_PRESCALE 0x000000FFU +#define MCPWM_CAP2_PRESCALE_M (MCPWM_CAP2_PRESCALE_V << MCPWM_CAP2_PRESCALE_S) +#define MCPWM_CAP2_PRESCALE_V 0x000000FFU +#define MCPWM_CAP2_PRESCALE_S 3 +/** MCPWM_CAP2_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP2 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP2_IN_INVERT (BIT(11)) +#define MCPWM_CAP2_IN_INVERT_M (MCPWM_CAP2_IN_INVERT_V << MCPWM_CAP2_IN_INVERT_S) +#define MCPWM_CAP2_IN_INVERT_V 0x00000001U +#define MCPWM_CAP2_IN_INVERT_S 11 +/** MCPWM_CAP2_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 2 + */ +#define MCPWM_CAP2_SW (BIT(12)) +#define MCPWM_CAP2_SW_M (MCPWM_CAP2_SW_V << MCPWM_CAP2_SW_S) +#define MCPWM_CAP2_SW_V 0x00000001U +#define MCPWM_CAP2_SW_S 12 -#define MCPWM_CAP_CH0_REG(i) (REG_MCPWM_BASE(i) + 0x00fc) -/* MCPWM_CAP0_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Value of last capture on channel 0*/ -#define MCPWM_CAP0_VALUE 0xFFFFFFFF -#define MCPWM_CAP0_VALUE_M ((MCPWM_CAP0_VALUE_V)<<(MCPWM_CAP0_VALUE_S)) -#define MCPWM_CAP0_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH0_REG register + * ch0 capture value status register + */ +#define MCPWM_CAP_CH0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xfc) +/** MCPWM_CAP0_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 0 + */ +#define MCPWM_CAP0_VALUE 0xFFFFFFFFU +#define MCPWM_CAP0_VALUE_M (MCPWM_CAP0_VALUE_V << MCPWM_CAP0_VALUE_S) +#define MCPWM_CAP0_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP0_VALUE_S 0 -#define MCPWM_CAP_CH1_REG(i) (REG_MCPWM_BASE(i) + 0x0100) -/* MCPWM_CAP1_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Value of last capture on channel 1*/ -#define MCPWM_CAP1_VALUE 0xFFFFFFFF -#define MCPWM_CAP1_VALUE_M ((MCPWM_CAP1_VALUE_V)<<(MCPWM_CAP1_VALUE_S)) -#define MCPWM_CAP1_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH1_REG register + * ch1 capture value status register + */ +#define MCPWM_CAP_CH1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x100) +/** MCPWM_CAP1_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 1 + */ +#define MCPWM_CAP1_VALUE 0xFFFFFFFFU +#define MCPWM_CAP1_VALUE_M (MCPWM_CAP1_VALUE_V << MCPWM_CAP1_VALUE_S) +#define MCPWM_CAP1_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP1_VALUE_S 0 -#define MCPWM_CAP_CH2_REG(i) (REG_MCPWM_BASE(i) + 0x0104) -/* MCPWM_CAP2_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Value of last capture on channel 2*/ -#define MCPWM_CAP2_VALUE 0xFFFFFFFF -#define MCPWM_CAP2_VALUE_M ((MCPWM_CAP2_VALUE_V)<<(MCPWM_CAP2_VALUE_S)) -#define MCPWM_CAP2_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH2_REG register + * ch2 capture value status register + */ +#define MCPWM_CAP_CH2_REG(i) (DR_REG_MCPWM_BASE(i) + 0x104) +/** MCPWM_CAP2_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 2 + */ +#define MCPWM_CAP2_VALUE 0xFFFFFFFFU +#define MCPWM_CAP2_VALUE_M (MCPWM_CAP2_VALUE_V << MCPWM_CAP2_VALUE_S) +#define MCPWM_CAP2_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP2_VALUE_S 0 -#define MCPWM_CAP_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0108) -/* MCPWM_CAP2_EDGE : RO ;bitpos:[2] ;default: 1'd0 ; */ -/*description: Edge of last capture trigger on channel 2 0: posedge 1: negedge*/ -#define MCPWM_CAP2_EDGE (BIT(2)) -#define MCPWM_CAP2_EDGE_M (BIT(2)) -#define MCPWM_CAP2_EDGE_V 0x1 -#define MCPWM_CAP2_EDGE_S 2 -/* MCPWM_CAP1_EDGE : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Edge of last capture trigger on channel 1 0: posedge 1: negedge*/ -#define MCPWM_CAP1_EDGE (BIT(1)) -#define MCPWM_CAP1_EDGE_M (BIT(1)) -#define MCPWM_CAP1_EDGE_V 0x1 -#define MCPWM_CAP1_EDGE_S 1 -/* MCPWM_CAP0_EDGE : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Edge of last capture trigger on channel 0 0: posedge 1: negedge*/ -#define MCPWM_CAP0_EDGE (BIT(0)) -#define MCPWM_CAP0_EDGE_M (BIT(0)) -#define MCPWM_CAP0_EDGE_V 0x1 +/** MCPWM_CAP_STATUS_REG register + * Edge of last capture trigger + */ +#define MCPWM_CAP_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x108) +/** MCPWM_CAP0_EDGE : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ +#define MCPWM_CAP0_EDGE (BIT(0)) +#define MCPWM_CAP0_EDGE_M (MCPWM_CAP0_EDGE_V << MCPWM_CAP0_EDGE_S) +#define MCPWM_CAP0_EDGE_V 0x00000001U #define MCPWM_CAP0_EDGE_S 0 +/** MCPWM_CAP1_EDGE : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ +#define MCPWM_CAP1_EDGE (BIT(1)) +#define MCPWM_CAP1_EDGE_M (MCPWM_CAP1_EDGE_V << MCPWM_CAP1_EDGE_S) +#define MCPWM_CAP1_EDGE_V 0x00000001U +#define MCPWM_CAP1_EDGE_S 1 +/** MCPWM_CAP2_EDGE : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ +#define MCPWM_CAP2_EDGE (BIT(2)) +#define MCPWM_CAP2_EDGE_M (MCPWM_CAP2_EDGE_V << MCPWM_CAP2_EDGE_S) +#define MCPWM_CAP2_EDGE_V 0x00000001U +#define MCPWM_CAP2_EDGE_S 2 -#define MCPWM_UPDATE_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x010c) -/* MCPWM_OP2_FORCE_UP : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of active registers in PWM operator 2*/ -#define MCPWM_OP2_FORCE_UP (BIT(7)) -#define MCPWM_OP2_FORCE_UP_M (BIT(7)) -#define MCPWM_OP2_FORCE_UP_V 0x1 -#define MCPWM_OP2_FORCE_UP_S 7 -/* MCPWM_OP2_UP_EN : R/W ;bitpos:[6] ;default: 1'd1 ; */ -/*description: When set and PWM_GLOBAL_UP_EN is set update of active registers - in PWM operator 2 are enabled*/ -#define MCPWM_OP2_UP_EN (BIT(6)) -#define MCPWM_OP2_UP_EN_M (BIT(6)) -#define MCPWM_OP2_UP_EN_V 0x1 -#define MCPWM_OP2_UP_EN_S 6 -/* MCPWM_OP1_FORCE_UP : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of active registers in PWM operator 1*/ -#define MCPWM_OP1_FORCE_UP (BIT(5)) -#define MCPWM_OP1_FORCE_UP_M (BIT(5)) -#define MCPWM_OP1_FORCE_UP_V 0x1 -#define MCPWM_OP1_FORCE_UP_S 5 -/* MCPWM_OP1_UP_EN : R/W ;bitpos:[4] ;default: 1'd1 ; */ -/*description: When set and PWM_GLOBAL_UP_EN is set update of active registers - in PWM operator 1 are enabled*/ -#define MCPWM_OP1_UP_EN (BIT(4)) -#define MCPWM_OP1_UP_EN_M (BIT(4)) -#define MCPWM_OP1_UP_EN_V 0x1 -#define MCPWM_OP1_UP_EN_S 4 -/* MCPWM_OP0_FORCE_UP : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of active registers in PWM operator 0*/ -#define MCPWM_OP0_FORCE_UP (BIT(3)) -#define MCPWM_OP0_FORCE_UP_M (BIT(3)) -#define MCPWM_OP0_FORCE_UP_V 0x1 -#define MCPWM_OP0_FORCE_UP_S 3 -/* MCPWM_OP0_UP_EN : R/W ;bitpos:[2] ;default: 1'd1 ; */ -/*description: When set and PWM_GLOBAL_UP_EN is set update of active registers - in PWM operator 0 are enabled*/ -#define MCPWM_OP0_UP_EN (BIT(2)) -#define MCPWM_OP0_UP_EN_M (BIT(2)) -#define MCPWM_OP0_UP_EN_V 0x1 -#define MCPWM_OP0_UP_EN_S 2 -/* MCPWM_GLOBAL_FORCE_UP : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of all active registers in MCPWM module*/ -#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_M (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_V 0x1 -#define MCPWM_GLOBAL_FORCE_UP_S 1 -/* MCPWM_GLOBAL_UP_EN : R/W ;bitpos:[0] ;default: 1'd1 ; */ -/*description: The global enable of update of all active registers in MCPWM module*/ -#define MCPWM_GLOBAL_UP_EN (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_M (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_V 0x1 +/** MCPWM_UPDATE_CFG_REG register + * Enable update. + */ +#define MCPWM_UPDATE_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10c) +/** MCPWM_GLOBAL_UP_EN : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ +#define MCPWM_GLOBAL_UP_EN (BIT(0)) +#define MCPWM_GLOBAL_UP_EN_M (MCPWM_GLOBAL_UP_EN_V << MCPWM_GLOBAL_UP_EN_S) +#define MCPWM_GLOBAL_UP_EN_V 0x00000001U #define MCPWM_GLOBAL_UP_EN_S 0 +/** MCPWM_GLOBAL_FORCE_UP : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ +#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) +#define MCPWM_GLOBAL_FORCE_UP_M (MCPWM_GLOBAL_FORCE_UP_V << MCPWM_GLOBAL_FORCE_UP_S) +#define MCPWM_GLOBAL_FORCE_UP_V 0x00000001U +#define MCPWM_GLOBAL_FORCE_UP_S 1 +/** MCPWM_OP0_UP_EN : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ +#define MCPWM_OP0_UP_EN (BIT(2)) +#define MCPWM_OP0_UP_EN_M (MCPWM_OP0_UP_EN_V << MCPWM_OP0_UP_EN_S) +#define MCPWM_OP0_UP_EN_V 0x00000001U +#define MCPWM_OP0_UP_EN_S 2 +/** MCPWM_OP0_FORCE_UP : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ +#define MCPWM_OP0_FORCE_UP (BIT(3)) +#define MCPWM_OP0_FORCE_UP_M (MCPWM_OP0_FORCE_UP_V << MCPWM_OP0_FORCE_UP_S) +#define MCPWM_OP0_FORCE_UP_V 0x00000001U +#define MCPWM_OP0_FORCE_UP_S 3 +/** MCPWM_OP1_UP_EN : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ +#define MCPWM_OP1_UP_EN (BIT(4)) +#define MCPWM_OP1_UP_EN_M (MCPWM_OP1_UP_EN_V << MCPWM_OP1_UP_EN_S) +#define MCPWM_OP1_UP_EN_V 0x00000001U +#define MCPWM_OP1_UP_EN_S 4 +/** MCPWM_OP1_FORCE_UP : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ +#define MCPWM_OP1_FORCE_UP (BIT(5)) +#define MCPWM_OP1_FORCE_UP_M (MCPWM_OP1_FORCE_UP_V << MCPWM_OP1_FORCE_UP_S) +#define MCPWM_OP1_FORCE_UP_V 0x00000001U +#define MCPWM_OP1_FORCE_UP_S 5 +/** MCPWM_OP2_UP_EN : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ +#define MCPWM_OP2_UP_EN (BIT(6)) +#define MCPWM_OP2_UP_EN_M (MCPWM_OP2_UP_EN_V << MCPWM_OP2_UP_EN_S) +#define MCPWM_OP2_UP_EN_V 0x00000001U +#define MCPWM_OP2_UP_EN_S 6 +/** MCPWM_OP2_FORCE_UP : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ +#define MCPWM_OP2_FORCE_UP (BIT(7)) +#define MCPWM_OP2_FORCE_UP_M (MCPWM_OP2_FORCE_UP_V << MCPWM_OP2_FORCE_UP_S) +#define MCPWM_OP2_FORCE_UP_V 0x00000001U +#define MCPWM_OP2_FORCE_UP_S 7 -#define MCMCPWM_INT_ENA_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x0110) -/* MCPWM_CAP2_INT_ENA : R/W ;bitpos:[29] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_ENA (BIT(29)) -#define MCPWM_CAP2_INT_ENA_M (BIT(29)) -#define MCPWM_CAP2_INT_ENA_V 0x1 -#define MCPWM_CAP2_INT_ENA_S 29 -/* MCPWM_CAP1_INT_ENA : R/W ;bitpos:[28] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_ENA (BIT(28)) -#define MCPWM_CAP1_INT_ENA_M (BIT(28)) -#define MCPWM_CAP1_INT_ENA_V 0x1 -#define MCPWM_CAP1_INT_ENA_S 28 -/* MCPWM_CAP0_INT_ENA : R/W ;bitpos:[27] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_ENA (BIT(27)) -#define MCPWM_CAP0_INT_ENA_M (BIT(27)) -#define MCPWM_CAP0_INT_ENA_V 0x1 -#define MCPWM_CAP0_INT_ENA_S 27 -/* MCPWM_FH2_OST_INT_ENA : R/W ;bitpos:[26] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_ENA (BIT(26)) -#define MCPWM_FH2_OST_INT_ENA_M (BIT(26)) -#define MCPWM_FH2_OST_INT_ENA_V 0x1 -#define MCPWM_FH2_OST_INT_ENA_S 26 -/* MCPWM_FH1_OST_INT_ENA : R/W ;bitpos:[25] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_ENA (BIT(25)) -#define MCPWM_FH1_OST_INT_ENA_M (BIT(25)) -#define MCPWM_FH1_OST_INT_ENA_V 0x1 -#define MCPWM_FH1_OST_INT_ENA_S 25 -/* MCPWM_FH0_OST_INT_ENA : R/W ;bitpos:[24] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_ENA (BIT(24)) -#define MCPWM_FH0_OST_INT_ENA_M (BIT(24)) -#define MCPWM_FH0_OST_INT_ENA_V 0x1 -#define MCPWM_FH0_OST_INT_ENA_S 24 -/* MCPWM_FH2_CBC_INT_ENA : R/W ;bitpos:[23] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an cycle-by-cycle mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_ENA (BIT(23)) -#define MCPWM_FH2_CBC_INT_ENA_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_ENA_V 0x1 -#define MCPWM_FH2_CBC_INT_ENA_S 23 -/* MCPWM_FH1_CBC_INT_ENA : R/W ;bitpos:[22] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an cycle-by-cycle mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_ENA (BIT(22)) -#define MCPWM_FH1_CBC_INT_ENA_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_ENA_V 0x1 -#define MCPWM_FH1_CBC_INT_ENA_S 22 -/* MCPWM_FH0_CBC_INT_ENA : R/W ;bitpos:[21] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an cycle-by-cycle mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_ENA (BIT(21)) -#define MCPWM_FH0_CBC_INT_ENA_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_ENA_V 0x1 -#define MCPWM_FH0_CBC_INT_ENA_S 21 -/* MCPWM_OP2_TEB_INT_ENA : R/W ;bitpos:[20] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_ENA (BIT(20)) -#define MCPWM_OP2_TEB_INT_ENA_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_ENA_V 0x1 -#define MCPWM_OP2_TEB_INT_ENA_S 20 -/* MCPWM_OP1_TEB_INT_ENA : R/W ;bitpos:[19] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_ENA (BIT(19)) -#define MCPWM_OP1_TEB_INT_ENA_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_ENA_V 0x1 -#define MCPWM_OP1_TEB_INT_ENA_S 19 -/* MCPWM_OP0_TEB_INT_ENA : R/W ;bitpos:[18] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_ENA (BIT(18)) -#define MCPWM_OP0_TEB_INT_ENA_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_ENA_V 0x1 -#define MCPWM_OP0_TEB_INT_ENA_S 18 -/* MCPWM_OP2_TEA_INT_ENA : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_ENA (BIT(17)) -#define MCPWM_OP2_TEA_INT_ENA_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_ENA_V 0x1 -#define MCPWM_OP2_TEA_INT_ENA_S 17 -/* MCPWM_OP1_TEA_INT_ENA : R/W ;bitpos:[16] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_ENA (BIT(16)) -#define MCPWM_OP1_TEA_INT_ENA_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_ENA_V 0x1 -#define MCPWM_OP1_TEA_INT_ENA_S 16 -/* MCPWM_OP0_TEA_INT_ENA : R/W ;bitpos:[15] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_ENA (BIT(15)) -#define MCPWM_OP0_TEA_INT_ENA_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_ENA_V 0x1 -#define MCPWM_OP0_TEA_INT_ENA_S 15 -/* MCPWM_FAULT2_CLR_INT_ENA : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ENA_S 14 -/* MCPWM_FAULT1_CLR_INT_ENA : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ENA_S 13 -/* MCPWM_FAULT0_CLR_INT_ENA : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ENA_S 12 -/* MCPWM_FAULT2_INT_ENA : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_ENA (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_M (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_V 0x1 -#define MCPWM_FAULT2_INT_ENA_S 11 -/* MCPWM_FAULT1_INT_ENA : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_ENA (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_M (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_V 0x1 -#define MCPWM_FAULT1_INT_ENA_S 10 -/* MCPWM_FAULT0_INT_ENA : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_ENA (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_M (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_V 0x1 -#define MCPWM_FAULT0_INT_ENA_S 9 -/* MCPWM_TIMER2_TEP_INT_ENA : R/W ;bitpos:[8] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ENA_S 8 -/* MCPWM_TIMER1_TEP_INT_ENA : R/W ;bitpos:[7] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ENA_S 7 -/* MCPWM_TIMER0_TEP_INT_ENA : R/W ;bitpos:[6] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ENA_S 6 -/* MCPWM_TIMER2_TEZ_INT_ENA : R/W ;bitpos:[5] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 -/* MCPWM_TIMER1_TEZ_INT_ENA : R/W ;bitpos:[4] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 -/* MCPWM_TIMER0_TEZ_INT_ENA : R/W ;bitpos:[3] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 -/* MCPWM_TIMER2_STOP_INT_ENA : R/W ;bitpos:[2] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ENA_S 2 -/* MCPWM_TIMER1_STOP_INT_ENA : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ENA_S 1 -/* MCPWM_TIMER0_STOP_INT_ENA : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_ENA (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_V 0x1 +/** MCPWM_INT_ENA_REG register + * Interrupt enable bits + */ +#define MCPWM_INT_ENA_REG(i) (DR_REG_MCPWM_BASE(i) + 0x110) +/** MCPWM_TIMER0_STOP_INT_ENA : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_ENA (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_ENA_M (MCPWM_TIMER0_STOP_INT_ENA_V << MCPWM_TIMER0_STOP_INT_ENA_S) +#define MCPWM_TIMER0_STOP_INT_ENA_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ENA_S 0 +/** MCPWM_TIMER1_STOP_INT_ENA : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ENA_M (MCPWM_TIMER1_STOP_INT_ENA_V << MCPWM_TIMER1_STOP_INT_ENA_S) +#define MCPWM_TIMER1_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ENA_S 1 +/** MCPWM_TIMER2_STOP_INT_ENA : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ENA_M (MCPWM_TIMER2_STOP_INT_ENA_V << MCPWM_TIMER2_STOP_INT_ENA_S) +#define MCPWM_TIMER2_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ENA_S 2 +/** MCPWM_TIMER0_TEZ_INT_ENA : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ENA_M (MCPWM_TIMER0_TEZ_INT_ENA_V << MCPWM_TIMER0_TEZ_INT_ENA_S) +#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 +/** MCPWM_TIMER1_TEZ_INT_ENA : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ENA_M (MCPWM_TIMER1_TEZ_INT_ENA_V << MCPWM_TIMER1_TEZ_INT_ENA_S) +#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 +/** MCPWM_TIMER2_TEZ_INT_ENA : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ENA_M (MCPWM_TIMER2_TEZ_INT_ENA_V << MCPWM_TIMER2_TEZ_INT_ENA_S) +#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 +/** MCPWM_TIMER0_TEP_INT_ENA : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ENA_M (MCPWM_TIMER0_TEP_INT_ENA_V << MCPWM_TIMER0_TEP_INT_ENA_S) +#define MCPWM_TIMER0_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ENA_S 6 +/** MCPWM_TIMER1_TEP_INT_ENA : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ENA_M (MCPWM_TIMER1_TEP_INT_ENA_V << MCPWM_TIMER1_TEP_INT_ENA_S) +#define MCPWM_TIMER1_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ENA_S 7 +/** MCPWM_TIMER2_TEP_INT_ENA : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ENA_M (MCPWM_TIMER2_TEP_INT_ENA_V << MCPWM_TIMER2_TEP_INT_ENA_S) +#define MCPWM_TIMER2_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ENA_S 8 +/** MCPWM_FAULT0_INT_ENA : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ENA (BIT(9)) +#define MCPWM_FAULT0_INT_ENA_M (MCPWM_FAULT0_INT_ENA_V << MCPWM_FAULT0_INT_ENA_S) +#define MCPWM_FAULT0_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_INT_ENA_S 9 +/** MCPWM_FAULT1_INT_ENA : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ENA (BIT(10)) +#define MCPWM_FAULT1_INT_ENA_M (MCPWM_FAULT1_INT_ENA_V << MCPWM_FAULT1_INT_ENA_S) +#define MCPWM_FAULT1_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_INT_ENA_S 10 +/** MCPWM_FAULT2_INT_ENA : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ENA (BIT(11)) +#define MCPWM_FAULT2_INT_ENA_M (MCPWM_FAULT2_INT_ENA_V << MCPWM_FAULT2_INT_ENA_S) +#define MCPWM_FAULT2_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_INT_ENA_S 11 +/** MCPWM_FAULT0_CLR_INT_ENA : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ENA_M (MCPWM_FAULT0_CLR_INT_ENA_V << MCPWM_FAULT0_CLR_INT_ENA_S) +#define MCPWM_FAULT0_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ENA_S 12 +/** MCPWM_FAULT1_CLR_INT_ENA : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ENA_M (MCPWM_FAULT1_CLR_INT_ENA_V << MCPWM_FAULT1_CLR_INT_ENA_S) +#define MCPWM_FAULT1_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ENA_S 13 +/** MCPWM_FAULT2_CLR_INT_ENA : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ENA_M (MCPWM_FAULT2_CLR_INT_ENA_V << MCPWM_FAULT2_CLR_INT_ENA_S) +#define MCPWM_FAULT2_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ENA_S 14 +/** MCPWM_OP0_TEA_INT_ENA : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ENA (BIT(15)) +#define MCPWM_OP0_TEA_INT_ENA_M (MCPWM_OP0_TEA_INT_ENA_V << MCPWM_OP0_TEA_INT_ENA_S) +#define MCPWM_OP0_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ENA_S 15 +/** MCPWM_OP1_TEA_INT_ENA : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ENA (BIT(16)) +#define MCPWM_OP1_TEA_INT_ENA_M (MCPWM_OP1_TEA_INT_ENA_V << MCPWM_OP1_TEA_INT_ENA_S) +#define MCPWM_OP1_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ENA_S 16 +/** MCPWM_OP2_TEA_INT_ENA : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ENA (BIT(17)) +#define MCPWM_OP2_TEA_INT_ENA_M (MCPWM_OP2_TEA_INT_ENA_V << MCPWM_OP2_TEA_INT_ENA_S) +#define MCPWM_OP2_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ENA_S 17 +/** MCPWM_OP0_TEB_INT_ENA : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ENA (BIT(18)) +#define MCPWM_OP0_TEB_INT_ENA_M (MCPWM_OP0_TEB_INT_ENA_V << MCPWM_OP0_TEB_INT_ENA_S) +#define MCPWM_OP0_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ENA_S 18 +/** MCPWM_OP1_TEB_INT_ENA : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ENA (BIT(19)) +#define MCPWM_OP1_TEB_INT_ENA_M (MCPWM_OP1_TEB_INT_ENA_V << MCPWM_OP1_TEB_INT_ENA_S) +#define MCPWM_OP1_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ENA_S 19 +/** MCPWM_OP2_TEB_INT_ENA : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ENA (BIT(20)) +#define MCPWM_OP2_TEB_INT_ENA_M (MCPWM_OP2_TEB_INT_ENA_V << MCPWM_OP2_TEB_INT_ENA_S) +#define MCPWM_OP2_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ENA_S 20 +/** MCPWM_FH0_CBC_INT_ENA : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ENA (BIT(21)) +#define MCPWM_FH0_CBC_INT_ENA_M (MCPWM_FH0_CBC_INT_ENA_V << MCPWM_FH0_CBC_INT_ENA_S) +#define MCPWM_FH0_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ENA_S 21 +/** MCPWM_FH1_CBC_INT_ENA : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ENA (BIT(22)) +#define MCPWM_FH1_CBC_INT_ENA_M (MCPWM_FH1_CBC_INT_ENA_V << MCPWM_FH1_CBC_INT_ENA_S) +#define MCPWM_FH1_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ENA_S 22 +/** MCPWM_FH2_CBC_INT_ENA : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ENA (BIT(23)) +#define MCPWM_FH2_CBC_INT_ENA_M (MCPWM_FH2_CBC_INT_ENA_V << MCPWM_FH2_CBC_INT_ENA_S) +#define MCPWM_FH2_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ENA_S 23 +/** MCPWM_FH0_OST_INT_ENA : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ENA (BIT(24)) +#define MCPWM_FH0_OST_INT_ENA_M (MCPWM_FH0_OST_INT_ENA_V << MCPWM_FH0_OST_INT_ENA_S) +#define MCPWM_FH0_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH0_OST_INT_ENA_S 24 +/** MCPWM_FH1_OST_INT_ENA : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ENA (BIT(25)) +#define MCPWM_FH1_OST_INT_ENA_M (MCPWM_FH1_OST_INT_ENA_V << MCPWM_FH1_OST_INT_ENA_S) +#define MCPWM_FH1_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH1_OST_INT_ENA_S 25 +/** MCPWM_FH2_OST_INT_ENA : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ENA (BIT(26)) +#define MCPWM_FH2_OST_INT_ENA_M (MCPWM_FH2_OST_INT_ENA_V << MCPWM_FH2_OST_INT_ENA_S) +#define MCPWM_FH2_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH2_OST_INT_ENA_S 26 +/** MCPWM_CAP0_INT_ENA : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ENA (BIT(27)) +#define MCPWM_CAP0_INT_ENA_M (MCPWM_CAP0_INT_ENA_V << MCPWM_CAP0_INT_ENA_S) +#define MCPWM_CAP0_INT_ENA_V 0x00000001U +#define MCPWM_CAP0_INT_ENA_S 27 +/** MCPWM_CAP1_INT_ENA : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ENA (BIT(28)) +#define MCPWM_CAP1_INT_ENA_M (MCPWM_CAP1_INT_ENA_V << MCPWM_CAP1_INT_ENA_S) +#define MCPWM_CAP1_INT_ENA_V 0x00000001U +#define MCPWM_CAP1_INT_ENA_S 28 +/** MCPWM_CAP2_INT_ENA : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ENA (BIT(29)) +#define MCPWM_CAP2_INT_ENA_M (MCPWM_CAP2_INT_ENA_V << MCPWM_CAP2_INT_ENA_S) +#define MCPWM_CAP2_INT_ENA_V 0x00000001U +#define MCPWM_CAP2_INT_ENA_S 29 -#define MCMCPWM_INT_RAW_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x0114) -/* MCPWM_CAP2_INT_RAW : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_RAW (BIT(29)) -#define MCPWM_CAP2_INT_RAW_M (BIT(29)) -#define MCPWM_CAP2_INT_RAW_V 0x1 -#define MCPWM_CAP2_INT_RAW_S 29 -/* MCPWM_CAP1_INT_RAW : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_RAW (BIT(28)) -#define MCPWM_CAP1_INT_RAW_M (BIT(28)) -#define MCPWM_CAP1_INT_RAW_V 0x1 -#define MCPWM_CAP1_INT_RAW_S 28 -/* MCPWM_CAP0_INT_RAW : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_RAW (BIT(27)) -#define MCPWM_CAP0_INT_RAW_M (BIT(27)) -#define MCPWM_CAP0_INT_RAW_V 0x1 -#define MCPWM_CAP0_INT_RAW_S 27 -/* MCPWM_FH2_OST_INT_RAW : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_RAW (BIT(26)) -#define MCPWM_FH2_OST_INT_RAW_M (BIT(26)) -#define MCPWM_FH2_OST_INT_RAW_V 0x1 -#define MCPWM_FH2_OST_INT_RAW_S 26 -/* MCPWM_FH1_OST_INT_RAW : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_RAW (BIT(25)) -#define MCPWM_FH1_OST_INT_RAW_M (BIT(25)) -#define MCPWM_FH1_OST_INT_RAW_V 0x1 -#define MCPWM_FH1_OST_INT_RAW_S 25 -/* MCPWM_FH0_OST_INT_RAW : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_RAW (BIT(24)) -#define MCPWM_FH0_OST_INT_RAW_M (BIT(24)) -#define MCPWM_FH0_OST_INT_RAW_V 0x1 -#define MCPWM_FH0_OST_INT_RAW_S 24 -/* MCPWM_FH2_CBC_INT_RAW : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_RAW (BIT(23)) -#define MCPWM_FH2_CBC_INT_RAW_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_RAW_V 0x1 -#define MCPWM_FH2_CBC_INT_RAW_S 23 -/* MCPWM_FH1_CBC_INT_RAW : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_RAW (BIT(22)) -#define MCPWM_FH1_CBC_INT_RAW_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_RAW_V 0x1 -#define MCPWM_FH1_CBC_INT_RAW_S 22 -/* MCPWM_FH0_CBC_INT_RAW : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_RAW (BIT(21)) -#define MCPWM_FH0_CBC_INT_RAW_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_RAW_V 0x1 -#define MCPWM_FH0_CBC_INT_RAW_S 21 -/* MCPWM_OP2_TEB_INT_RAW : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_RAW (BIT(20)) -#define MCPWM_OP2_TEB_INT_RAW_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_RAW_V 0x1 -#define MCPWM_OP2_TEB_INT_RAW_S 20 -/* MCPWM_OP1_TEB_INT_RAW : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_RAW (BIT(19)) -#define MCPWM_OP1_TEB_INT_RAW_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_RAW_V 0x1 -#define MCPWM_OP1_TEB_INT_RAW_S 19 -/* MCPWM_OP0_TEB_INT_RAW : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_RAW (BIT(18)) -#define MCPWM_OP0_TEB_INT_RAW_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_RAW_V 0x1 -#define MCPWM_OP0_TEB_INT_RAW_S 18 -/* MCPWM_OP2_TEA_INT_RAW : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_RAW (BIT(17)) -#define MCPWM_OP2_TEA_INT_RAW_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_RAW_V 0x1 -#define MCPWM_OP2_TEA_INT_RAW_S 17 -/* MCPWM_OP1_TEA_INT_RAW : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_RAW (BIT(16)) -#define MCPWM_OP1_TEA_INT_RAW_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_RAW_V 0x1 -#define MCPWM_OP1_TEA_INT_RAW_S 16 -/* MCPWM_OP0_TEA_INT_RAW : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_RAW (BIT(15)) -#define MCPWM_OP0_TEA_INT_RAW_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_RAW_V 0x1 -#define MCPWM_OP0_TEA_INT_RAW_S 15 -/* MCPWM_FAULT2_CLR_INT_RAW : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT2_CLR_INT_RAW_S 14 -/* MCPWM_FAULT1_CLR_INT_RAW : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT1_CLR_INT_RAW_S 13 -/* MCPWM_FAULT0_CLR_INT_RAW : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT0_CLR_INT_RAW_S 12 -/* MCPWM_FAULT2_INT_RAW : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_RAW (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_M (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_V 0x1 -#define MCPWM_FAULT2_INT_RAW_S 11 -/* MCPWM_FAULT1_INT_RAW : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_RAW (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_M (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_V 0x1 -#define MCPWM_FAULT1_INT_RAW_S 10 -/* MCPWM_FAULT0_INT_RAW : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_RAW (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_M (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_V 0x1 -#define MCPWM_FAULT0_INT_RAW_S 9 -/* MCPWM_TIMER2_TEP_INT_RAW : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEP_INT_RAW_S 8 -/* MCPWM_TIMER1_TEP_INT_RAW : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEP_INT_RAW_S 7 -/* MCPWM_TIMER0_TEP_INT_RAW : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEP_INT_RAW_S 6 -/* MCPWM_TIMER2_TEZ_INT_RAW : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 -/* MCPWM_TIMER1_TEZ_INT_RAW : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 -/* MCPWM_TIMER0_TEZ_INT_RAW : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 -/* MCPWM_TIMER2_STOP_INT_RAW : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_STOP_INT_RAW_S 2 -/* MCPWM_TIMER1_STOP_INT_RAW : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_STOP_INT_RAW_S 1 -/* MCPWM_TIMER0_STOP_INT_RAW : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_RAW (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_V 0x1 +/** MCPWM_INT_RAW_REG register + * Raw interrupt status + */ +#define MCPWM_INT_RAW_REG(i) (DR_REG_MCPWM_BASE(i) + 0x114) +/** MCPWM_TIMER0_STOP_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_RAW (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_RAW_M (MCPWM_TIMER0_STOP_INT_RAW_V << MCPWM_TIMER0_STOP_INT_RAW_S) +#define MCPWM_TIMER0_STOP_INT_RAW_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_RAW_S 0 +/** MCPWM_TIMER1_STOP_INT_RAW : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_RAW_M (MCPWM_TIMER1_STOP_INT_RAW_V << MCPWM_TIMER1_STOP_INT_RAW_S) +#define MCPWM_TIMER1_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_RAW_S 1 +/** MCPWM_TIMER2_STOP_INT_RAW : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_RAW_M (MCPWM_TIMER2_STOP_INT_RAW_V << MCPWM_TIMER2_STOP_INT_RAW_S) +#define MCPWM_TIMER2_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_RAW_S 2 +/** MCPWM_TIMER0_TEZ_INT_RAW : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_RAW_M (MCPWM_TIMER0_TEZ_INT_RAW_V << MCPWM_TIMER0_TEZ_INT_RAW_S) +#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 +/** MCPWM_TIMER1_TEZ_INT_RAW : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_RAW_M (MCPWM_TIMER1_TEZ_INT_RAW_V << MCPWM_TIMER1_TEZ_INT_RAW_S) +#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 +/** MCPWM_TIMER2_TEZ_INT_RAW : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_RAW_M (MCPWM_TIMER2_TEZ_INT_RAW_V << MCPWM_TIMER2_TEZ_INT_RAW_S) +#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 +/** MCPWM_TIMER0_TEP_INT_RAW : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_RAW_M (MCPWM_TIMER0_TEP_INT_RAW_V << MCPWM_TIMER0_TEP_INT_RAW_S) +#define MCPWM_TIMER0_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_RAW_S 6 +/** MCPWM_TIMER1_TEP_INT_RAW : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_RAW_M (MCPWM_TIMER1_TEP_INT_RAW_V << MCPWM_TIMER1_TEP_INT_RAW_S) +#define MCPWM_TIMER1_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_RAW_S 7 +/** MCPWM_TIMER2_TEP_INT_RAW : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_RAW_M (MCPWM_TIMER2_TEP_INT_RAW_V << MCPWM_TIMER2_TEP_INT_RAW_S) +#define MCPWM_TIMER2_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_RAW_S 8 +/** MCPWM_FAULT0_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_RAW (BIT(9)) +#define MCPWM_FAULT0_INT_RAW_M (MCPWM_FAULT0_INT_RAW_V << MCPWM_FAULT0_INT_RAW_S) +#define MCPWM_FAULT0_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_INT_RAW_S 9 +/** MCPWM_FAULT1_INT_RAW : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_RAW (BIT(10)) +#define MCPWM_FAULT1_INT_RAW_M (MCPWM_FAULT1_INT_RAW_V << MCPWM_FAULT1_INT_RAW_S) +#define MCPWM_FAULT1_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_INT_RAW_S 10 +/** MCPWM_FAULT2_INT_RAW : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_RAW (BIT(11)) +#define MCPWM_FAULT2_INT_RAW_M (MCPWM_FAULT2_INT_RAW_V << MCPWM_FAULT2_INT_RAW_S) +#define MCPWM_FAULT2_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_INT_RAW_S 11 +/** MCPWM_FAULT0_CLR_INT_RAW : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_RAW_M (MCPWM_FAULT0_CLR_INT_RAW_V << MCPWM_FAULT0_CLR_INT_RAW_S) +#define MCPWM_FAULT0_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_RAW_S 12 +/** MCPWM_FAULT1_CLR_INT_RAW : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_RAW_M (MCPWM_FAULT1_CLR_INT_RAW_V << MCPWM_FAULT1_CLR_INT_RAW_S) +#define MCPWM_FAULT1_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_RAW_S 13 +/** MCPWM_FAULT2_CLR_INT_RAW : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_RAW_M (MCPWM_FAULT2_CLR_INT_RAW_V << MCPWM_FAULT2_CLR_INT_RAW_S) +#define MCPWM_FAULT2_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_RAW_S 14 +/** MCPWM_OP0_TEA_INT_RAW : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_RAW (BIT(15)) +#define MCPWM_OP0_TEA_INT_RAW_M (MCPWM_OP0_TEA_INT_RAW_V << MCPWM_OP0_TEA_INT_RAW_S) +#define MCPWM_OP0_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEA_INT_RAW_S 15 +/** MCPWM_OP1_TEA_INT_RAW : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_RAW (BIT(16)) +#define MCPWM_OP1_TEA_INT_RAW_M (MCPWM_OP1_TEA_INT_RAW_V << MCPWM_OP1_TEA_INT_RAW_S) +#define MCPWM_OP1_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEA_INT_RAW_S 16 +/** MCPWM_OP2_TEA_INT_RAW : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_RAW (BIT(17)) +#define MCPWM_OP2_TEA_INT_RAW_M (MCPWM_OP2_TEA_INT_RAW_V << MCPWM_OP2_TEA_INT_RAW_S) +#define MCPWM_OP2_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEA_INT_RAW_S 17 +/** MCPWM_OP0_TEB_INT_RAW : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_RAW (BIT(18)) +#define MCPWM_OP0_TEB_INT_RAW_M (MCPWM_OP0_TEB_INT_RAW_V << MCPWM_OP0_TEB_INT_RAW_S) +#define MCPWM_OP0_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEB_INT_RAW_S 18 +/** MCPWM_OP1_TEB_INT_RAW : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_RAW (BIT(19)) +#define MCPWM_OP1_TEB_INT_RAW_M (MCPWM_OP1_TEB_INT_RAW_V << MCPWM_OP1_TEB_INT_RAW_S) +#define MCPWM_OP1_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEB_INT_RAW_S 19 +/** MCPWM_OP2_TEB_INT_RAW : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_RAW (BIT(20)) +#define MCPWM_OP2_TEB_INT_RAW_M (MCPWM_OP2_TEB_INT_RAW_V << MCPWM_OP2_TEB_INT_RAW_S) +#define MCPWM_OP2_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEB_INT_RAW_S 20 +/** MCPWM_FH0_CBC_INT_RAW : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_RAW (BIT(21)) +#define MCPWM_FH0_CBC_INT_RAW_M (MCPWM_FH0_CBC_INT_RAW_V << MCPWM_FH0_CBC_INT_RAW_S) +#define MCPWM_FH0_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH0_CBC_INT_RAW_S 21 +/** MCPWM_FH1_CBC_INT_RAW : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_RAW (BIT(22)) +#define MCPWM_FH1_CBC_INT_RAW_M (MCPWM_FH1_CBC_INT_RAW_V << MCPWM_FH1_CBC_INT_RAW_S) +#define MCPWM_FH1_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH1_CBC_INT_RAW_S 22 +/** MCPWM_FH2_CBC_INT_RAW : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_RAW (BIT(23)) +#define MCPWM_FH2_CBC_INT_RAW_M (MCPWM_FH2_CBC_INT_RAW_V << MCPWM_FH2_CBC_INT_RAW_S) +#define MCPWM_FH2_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH2_CBC_INT_RAW_S 23 +/** MCPWM_FH0_OST_INT_RAW : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_RAW (BIT(24)) +#define MCPWM_FH0_OST_INT_RAW_M (MCPWM_FH0_OST_INT_RAW_V << MCPWM_FH0_OST_INT_RAW_S) +#define MCPWM_FH0_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH0_OST_INT_RAW_S 24 +/** MCPWM_FH1_OST_INT_RAW : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_RAW (BIT(25)) +#define MCPWM_FH1_OST_INT_RAW_M (MCPWM_FH1_OST_INT_RAW_V << MCPWM_FH1_OST_INT_RAW_S) +#define MCPWM_FH1_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH1_OST_INT_RAW_S 25 +/** MCPWM_FH2_OST_INT_RAW : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_RAW (BIT(26)) +#define MCPWM_FH2_OST_INT_RAW_M (MCPWM_FH2_OST_INT_RAW_V << MCPWM_FH2_OST_INT_RAW_S) +#define MCPWM_FH2_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH2_OST_INT_RAW_S 26 +/** MCPWM_CAP0_INT_RAW : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_RAW (BIT(27)) +#define MCPWM_CAP0_INT_RAW_M (MCPWM_CAP0_INT_RAW_V << MCPWM_CAP0_INT_RAW_S) +#define MCPWM_CAP0_INT_RAW_V 0x00000001U +#define MCPWM_CAP0_INT_RAW_S 27 +/** MCPWM_CAP1_INT_RAW : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_RAW (BIT(28)) +#define MCPWM_CAP1_INT_RAW_M (MCPWM_CAP1_INT_RAW_V << MCPWM_CAP1_INT_RAW_S) +#define MCPWM_CAP1_INT_RAW_V 0x00000001U +#define MCPWM_CAP1_INT_RAW_S 28 +/** MCPWM_CAP2_INT_RAW : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_RAW (BIT(29)) +#define MCPWM_CAP2_INT_RAW_M (MCPWM_CAP2_INT_RAW_V << MCPWM_CAP2_INT_RAW_S) +#define MCPWM_CAP2_INT_RAW_V 0x00000001U +#define MCPWM_CAP2_INT_RAW_S 29 -#define MCMCPWM_INT_ST_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x0118) -/* MCPWM_CAP2_INT_ST : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_ST (BIT(29)) -#define MCPWM_CAP2_INT_ST_M (BIT(29)) -#define MCPWM_CAP2_INT_ST_V 0x1 -#define MCPWM_CAP2_INT_ST_S 29 -/* MCPWM_CAP1_INT_ST : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_ST (BIT(28)) -#define MCPWM_CAP1_INT_ST_M (BIT(28)) -#define MCPWM_CAP1_INT_ST_V 0x1 -#define MCPWM_CAP1_INT_ST_S 28 -/* MCPWM_CAP0_INT_ST : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_ST (BIT(27)) -#define MCPWM_CAP0_INT_ST_M (BIT(27)) -#define MCPWM_CAP0_INT_ST_V 0x1 -#define MCPWM_CAP0_INT_ST_S 27 -/* MCPWM_FH2_OST_INT_ST : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_ST (BIT(26)) -#define MCPWM_FH2_OST_INT_ST_M (BIT(26)) -#define MCPWM_FH2_OST_INT_ST_V 0x1 -#define MCPWM_FH2_OST_INT_ST_S 26 -/* MCPWM_FH1_OST_INT_ST : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_ST (BIT(25)) -#define MCPWM_FH1_OST_INT_ST_M (BIT(25)) -#define MCPWM_FH1_OST_INT_ST_V 0x1 -#define MCPWM_FH1_OST_INT_ST_S 25 -/* MCPWM_FH0_OST_INT_ST : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_ST (BIT(24)) -#define MCPWM_FH0_OST_INT_ST_M (BIT(24)) -#define MCPWM_FH0_OST_INT_ST_V 0x1 -#define MCPWM_FH0_OST_INT_ST_S 24 -/* MCPWM_FH2_CBC_INT_ST : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_ST (BIT(23)) -#define MCPWM_FH2_CBC_INT_ST_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_ST_V 0x1 -#define MCPWM_FH2_CBC_INT_ST_S 23 -/* MCPWM_FH1_CBC_INT_ST : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_ST (BIT(22)) -#define MCPWM_FH1_CBC_INT_ST_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_ST_V 0x1 -#define MCPWM_FH1_CBC_INT_ST_S 22 -/* MCPWM_FH0_CBC_INT_ST : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_ST (BIT(21)) -#define MCPWM_FH0_CBC_INT_ST_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_ST_V 0x1 -#define MCPWM_FH0_CBC_INT_ST_S 21 -/* MCPWM_OP2_TEB_INT_ST : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_ST (BIT(20)) -#define MCPWM_OP2_TEB_INT_ST_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_ST_V 0x1 -#define MCPWM_OP2_TEB_INT_ST_S 20 -/* MCPWM_OP1_TEB_INT_ST : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_ST (BIT(19)) -#define MCPWM_OP1_TEB_INT_ST_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_ST_V 0x1 -#define MCPWM_OP1_TEB_INT_ST_S 19 -/* MCPWM_OP0_TEB_INT_ST : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_ST (BIT(18)) -#define MCPWM_OP0_TEB_INT_ST_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_ST_V 0x1 -#define MCPWM_OP0_TEB_INT_ST_S 18 -/* MCPWM_OP2_TEA_INT_ST : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_ST (BIT(17)) -#define MCPWM_OP2_TEA_INT_ST_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_ST_V 0x1 -#define MCPWM_OP2_TEA_INT_ST_S 17 -/* MCPWM_OP1_TEA_INT_ST : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_ST (BIT(16)) -#define MCPWM_OP1_TEA_INT_ST_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_ST_V 0x1 -#define MCPWM_OP1_TEA_INT_ST_S 16 -/* MCPWM_OP0_TEA_INT_ST : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_ST (BIT(15)) -#define MCPWM_OP0_TEA_INT_ST_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_ST_V 0x1 -#define MCPWM_OP0_TEA_INT_ST_S 15 -/* MCPWM_FAULT2_CLR_INT_ST : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ST_S 14 -/* MCPWM_FAULT1_CLR_INT_ST : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ST_S 13 -/* MCPWM_FAULT0_CLR_INT_ST : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ST_S 12 -/* MCPWM_FAULT2_INT_ST : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_ST (BIT(11)) -#define MCPWM_FAULT2_INT_ST_M (BIT(11)) -#define MCPWM_FAULT2_INT_ST_V 0x1 -#define MCPWM_FAULT2_INT_ST_S 11 -/* MCPWM_FAULT1_INT_ST : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_ST (BIT(10)) -#define MCPWM_FAULT1_INT_ST_M (BIT(10)) -#define MCPWM_FAULT1_INT_ST_V 0x1 -#define MCPWM_FAULT1_INT_ST_S 10 -/* MCPWM_FAULT0_INT_ST : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_ST (BIT(9)) -#define MCPWM_FAULT0_INT_ST_M (BIT(9)) -#define MCPWM_FAULT0_INT_ST_V 0x1 -#define MCPWM_FAULT0_INT_ST_S 9 -/* MCPWM_TIMER2_TEP_INT_ST : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ST_S 8 -/* MCPWM_TIMER1_TEP_INT_ST : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ST_S 7 -/* MCPWM_TIMER0_TEP_INT_ST : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ST_S 6 -/* MCPWM_TIMER2_TEZ_INT_ST : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ST_S 5 -/* MCPWM_TIMER1_TEZ_INT_ST : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ST_S 4 -/* MCPWM_TIMER0_TEZ_INT_ST : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ST_S 3 -/* MCPWM_TIMER2_STOP_INT_ST : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ST_S 2 -/* MCPWM_TIMER1_STOP_INT_ST : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ST_S 1 -/* MCPWM_TIMER0_STOP_INT_ST : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_ST (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_V 0x1 +/** MCPWM_INT_ST_REG register + * Masked interrupt status + */ +#define MCPWM_INT_ST_REG(i) (DR_REG_MCPWM_BASE(i) + 0x118) +/** MCPWM_TIMER0_STOP_INT_ST : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_ST (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_ST_M (MCPWM_TIMER0_STOP_INT_ST_V << MCPWM_TIMER0_STOP_INT_ST_S) +#define MCPWM_TIMER0_STOP_INT_ST_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ST_S 0 +/** MCPWM_TIMER1_STOP_INT_ST : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ST_M (MCPWM_TIMER1_STOP_INT_ST_V << MCPWM_TIMER1_STOP_INT_ST_S) +#define MCPWM_TIMER1_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ST_S 1 +/** MCPWM_TIMER2_STOP_INT_ST : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ST_M (MCPWM_TIMER2_STOP_INT_ST_V << MCPWM_TIMER2_STOP_INT_ST_S) +#define MCPWM_TIMER2_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ST_S 2 +/** MCPWM_TIMER0_TEZ_INT_ST : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ST_M (MCPWM_TIMER0_TEZ_INT_ST_V << MCPWM_TIMER0_TEZ_INT_ST_S) +#define MCPWM_TIMER0_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ST_S 3 +/** MCPWM_TIMER1_TEZ_INT_ST : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ST_M (MCPWM_TIMER1_TEZ_INT_ST_V << MCPWM_TIMER1_TEZ_INT_ST_S) +#define MCPWM_TIMER1_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ST_S 4 +/** MCPWM_TIMER2_TEZ_INT_ST : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ST_M (MCPWM_TIMER2_TEZ_INT_ST_V << MCPWM_TIMER2_TEZ_INT_ST_S) +#define MCPWM_TIMER2_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ST_S 5 +/** MCPWM_TIMER0_TEP_INT_ST : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ST_M (MCPWM_TIMER0_TEP_INT_ST_V << MCPWM_TIMER0_TEP_INT_ST_S) +#define MCPWM_TIMER0_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ST_S 6 +/** MCPWM_TIMER1_TEP_INT_ST : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ST_M (MCPWM_TIMER1_TEP_INT_ST_V << MCPWM_TIMER1_TEP_INT_ST_S) +#define MCPWM_TIMER1_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ST_S 7 +/** MCPWM_TIMER2_TEP_INT_ST : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ST_M (MCPWM_TIMER2_TEP_INT_ST_V << MCPWM_TIMER2_TEP_INT_ST_S) +#define MCPWM_TIMER2_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ST_S 8 +/** MCPWM_FAULT0_INT_ST : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ST (BIT(9)) +#define MCPWM_FAULT0_INT_ST_M (MCPWM_FAULT0_INT_ST_V << MCPWM_FAULT0_INT_ST_S) +#define MCPWM_FAULT0_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_INT_ST_S 9 +/** MCPWM_FAULT1_INT_ST : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ST (BIT(10)) +#define MCPWM_FAULT1_INT_ST_M (MCPWM_FAULT1_INT_ST_V << MCPWM_FAULT1_INT_ST_S) +#define MCPWM_FAULT1_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_INT_ST_S 10 +/** MCPWM_FAULT2_INT_ST : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ST (BIT(11)) +#define MCPWM_FAULT2_INT_ST_M (MCPWM_FAULT2_INT_ST_V << MCPWM_FAULT2_INT_ST_S) +#define MCPWM_FAULT2_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_INT_ST_S 11 +/** MCPWM_FAULT0_CLR_INT_ST : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ST_M (MCPWM_FAULT0_CLR_INT_ST_V << MCPWM_FAULT0_CLR_INT_ST_S) +#define MCPWM_FAULT0_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ST_S 12 +/** MCPWM_FAULT1_CLR_INT_ST : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ST_M (MCPWM_FAULT1_CLR_INT_ST_V << MCPWM_FAULT1_CLR_INT_ST_S) +#define MCPWM_FAULT1_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ST_S 13 +/** MCPWM_FAULT2_CLR_INT_ST : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ST_M (MCPWM_FAULT2_CLR_INT_ST_V << MCPWM_FAULT2_CLR_INT_ST_S) +#define MCPWM_FAULT2_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ST_S 14 +/** MCPWM_OP0_TEA_INT_ST : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ST (BIT(15)) +#define MCPWM_OP0_TEA_INT_ST_M (MCPWM_OP0_TEA_INT_ST_V << MCPWM_OP0_TEA_INT_ST_S) +#define MCPWM_OP0_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ST_S 15 +/** MCPWM_OP1_TEA_INT_ST : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ST (BIT(16)) +#define MCPWM_OP1_TEA_INT_ST_M (MCPWM_OP1_TEA_INT_ST_V << MCPWM_OP1_TEA_INT_ST_S) +#define MCPWM_OP1_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ST_S 16 +/** MCPWM_OP2_TEA_INT_ST : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ST (BIT(17)) +#define MCPWM_OP2_TEA_INT_ST_M (MCPWM_OP2_TEA_INT_ST_V << MCPWM_OP2_TEA_INT_ST_S) +#define MCPWM_OP2_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ST_S 17 +/** MCPWM_OP0_TEB_INT_ST : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ST (BIT(18)) +#define MCPWM_OP0_TEB_INT_ST_M (MCPWM_OP0_TEB_INT_ST_V << MCPWM_OP0_TEB_INT_ST_S) +#define MCPWM_OP0_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ST_S 18 +/** MCPWM_OP1_TEB_INT_ST : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ST (BIT(19)) +#define MCPWM_OP1_TEB_INT_ST_M (MCPWM_OP1_TEB_INT_ST_V << MCPWM_OP1_TEB_INT_ST_S) +#define MCPWM_OP1_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ST_S 19 +/** MCPWM_OP2_TEB_INT_ST : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ST (BIT(20)) +#define MCPWM_OP2_TEB_INT_ST_M (MCPWM_OP2_TEB_INT_ST_V << MCPWM_OP2_TEB_INT_ST_S) +#define MCPWM_OP2_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ST_S 20 +/** MCPWM_FH0_CBC_INT_ST : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ST (BIT(21)) +#define MCPWM_FH0_CBC_INT_ST_M (MCPWM_FH0_CBC_INT_ST_V << MCPWM_FH0_CBC_INT_ST_S) +#define MCPWM_FH0_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ST_S 21 +/** MCPWM_FH1_CBC_INT_ST : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ST (BIT(22)) +#define MCPWM_FH1_CBC_INT_ST_M (MCPWM_FH1_CBC_INT_ST_V << MCPWM_FH1_CBC_INT_ST_S) +#define MCPWM_FH1_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ST_S 22 +/** MCPWM_FH2_CBC_INT_ST : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ST (BIT(23)) +#define MCPWM_FH2_CBC_INT_ST_M (MCPWM_FH2_CBC_INT_ST_V << MCPWM_FH2_CBC_INT_ST_S) +#define MCPWM_FH2_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ST_S 23 +/** MCPWM_FH0_OST_INT_ST : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ST (BIT(24)) +#define MCPWM_FH0_OST_INT_ST_M (MCPWM_FH0_OST_INT_ST_V << MCPWM_FH0_OST_INT_ST_S) +#define MCPWM_FH0_OST_INT_ST_V 0x00000001U +#define MCPWM_FH0_OST_INT_ST_S 24 +/** MCPWM_FH1_OST_INT_ST : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ST (BIT(25)) +#define MCPWM_FH1_OST_INT_ST_M (MCPWM_FH1_OST_INT_ST_V << MCPWM_FH1_OST_INT_ST_S) +#define MCPWM_FH1_OST_INT_ST_V 0x00000001U +#define MCPWM_FH1_OST_INT_ST_S 25 +/** MCPWM_FH2_OST_INT_ST : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ST (BIT(26)) +#define MCPWM_FH2_OST_INT_ST_M (MCPWM_FH2_OST_INT_ST_V << MCPWM_FH2_OST_INT_ST_S) +#define MCPWM_FH2_OST_INT_ST_V 0x00000001U +#define MCPWM_FH2_OST_INT_ST_S 26 +/** MCPWM_CAP0_INT_ST : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ST (BIT(27)) +#define MCPWM_CAP0_INT_ST_M (MCPWM_CAP0_INT_ST_V << MCPWM_CAP0_INT_ST_S) +#define MCPWM_CAP0_INT_ST_V 0x00000001U +#define MCPWM_CAP0_INT_ST_S 27 +/** MCPWM_CAP1_INT_ST : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ST (BIT(28)) +#define MCPWM_CAP1_INT_ST_M (MCPWM_CAP1_INT_ST_V << MCPWM_CAP1_INT_ST_S) +#define MCPWM_CAP1_INT_ST_V 0x00000001U +#define MCPWM_CAP1_INT_ST_S 28 +/** MCPWM_CAP2_INT_ST : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ST (BIT(29)) +#define MCPWM_CAP2_INT_ST_M (MCPWM_CAP2_INT_ST_V << MCPWM_CAP2_INT_ST_S) +#define MCPWM_CAP2_INT_ST_V 0x00000001U +#define MCPWM_CAP2_INT_ST_S 29 -#define MCMCPWM_INT_CLR_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x011c) -/* MCPWM_CAP2_INT_CLR : WO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_CLR (BIT(29)) -#define MCPWM_CAP2_INT_CLR_M (BIT(29)) -#define MCPWM_CAP2_INT_CLR_V 0x1 -#define MCPWM_CAP2_INT_CLR_S 29 -/* MCPWM_CAP1_INT_CLR : WO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_CLR (BIT(28)) -#define MCPWM_CAP1_INT_CLR_M (BIT(28)) -#define MCPWM_CAP1_INT_CLR_V 0x1 -#define MCPWM_CAP1_INT_CLR_S 28 -/* MCPWM_CAP0_INT_CLR : WO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_CLR (BIT(27)) -#define MCPWM_CAP0_INT_CLR_M (BIT(27)) -#define MCPWM_CAP0_INT_CLR_V 0x1 -#define MCPWM_CAP0_INT_CLR_S 27 -/* MCPWM_FH2_OST_INT_CLR : WO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_CLR (BIT(26)) -#define MCPWM_FH2_OST_INT_CLR_M (BIT(26)) -#define MCPWM_FH2_OST_INT_CLR_V 0x1 -#define MCPWM_FH2_OST_INT_CLR_S 26 -/* MCPWM_FH1_OST_INT_CLR : WO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_CLR (BIT(25)) -#define MCPWM_FH1_OST_INT_CLR_M (BIT(25)) -#define MCPWM_FH1_OST_INT_CLR_V 0x1 -#define MCPWM_FH1_OST_INT_CLR_S 25 -/* MCPWM_FH0_OST_INT_CLR : WO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_CLR (BIT(24)) -#define MCPWM_FH0_OST_INT_CLR_M (BIT(24)) -#define MCPWM_FH0_OST_INT_CLR_V 0x1 -#define MCPWM_FH0_OST_INT_CLR_S 24 -/* MCPWM_FH2_CBC_INT_CLR : WO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an cycle-by-cycle - mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_CLR (BIT(23)) -#define MCPWM_FH2_CBC_INT_CLR_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_CLR_V 0x1 -#define MCPWM_FH2_CBC_INT_CLR_S 23 -/* MCPWM_FH1_CBC_INT_CLR : WO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an cycle-by-cycle - mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_CLR (BIT(22)) -#define MCPWM_FH1_CBC_INT_CLR_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_CLR_V 0x1 -#define MCPWM_FH1_CBC_INT_CLR_S 22 -/* MCPWM_FH0_CBC_INT_CLR : WO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an cycle-by-cycle - mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_CLR (BIT(21)) -#define MCPWM_FH0_CBC_INT_CLR_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_CLR_V 0x1 -#define MCPWM_FH0_CBC_INT_CLR_S 21 -/* MCPWM_OP2_TEB_INT_CLR : WO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_CLR (BIT(20)) -#define MCPWM_OP2_TEB_INT_CLR_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_CLR_V 0x1 -#define MCPWM_OP2_TEB_INT_CLR_S 20 -/* MCPWM_OP1_TEB_INT_CLR : WO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_CLR (BIT(19)) -#define MCPWM_OP1_TEB_INT_CLR_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_CLR_V 0x1 -#define MCPWM_OP1_TEB_INT_CLR_S 19 -/* MCPWM_OP0_TEB_INT_CLR : WO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_CLR (BIT(18)) -#define MCPWM_OP0_TEB_INT_CLR_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_CLR_V 0x1 -#define MCPWM_OP0_TEB_INT_CLR_S 18 -/* MCPWM_OP2_TEA_INT_CLR : WO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_CLR (BIT(17)) -#define MCPWM_OP2_TEA_INT_CLR_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_CLR_V 0x1 -#define MCPWM_OP2_TEA_INT_CLR_S 17 -/* MCPWM_OP1_TEA_INT_CLR : WO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_CLR (BIT(16)) -#define MCPWM_OP1_TEA_INT_CLR_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_CLR_V 0x1 -#define MCPWM_OP1_TEA_INT_CLR_S 16 -/* MCPWM_OP0_TEA_INT_CLR : WO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_CLR (BIT(15)) -#define MCPWM_OP0_TEA_INT_CLR_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_CLR_V 0x1 -#define MCPWM_OP0_TEA_INT_CLR_S 15 -/* MCPWM_FAULT2_CLR_INT_CLR : WO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT2_CLR_INT_CLR_S 14 -/* MCPWM_FAULT1_CLR_INT_CLR : WO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT1_CLR_INT_CLR_S 13 -/* MCPWM_FAULT0_CLR_INT_CLR : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT0_CLR_INT_CLR_S 12 -/* MCPWM_FAULT2_INT_CLR : WO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_CLR (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_M (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_V 0x1 -#define MCPWM_FAULT2_INT_CLR_S 11 -/* MCPWM_FAULT1_INT_CLR : WO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_CLR (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_M (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_V 0x1 -#define MCPWM_FAULT1_INT_CLR_S 10 -/* MCPWM_FAULT0_INT_CLR : WO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_CLR (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_M (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_V 0x1 -#define MCPWM_FAULT0_INT_CLR_S 9 -/* MCPWM_TIMER2_TEP_INT_CLR : WO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEP_INT_CLR_S 8 -/* MCPWM_TIMER1_TEP_INT_CLR : WO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEP_INT_CLR_S 7 -/* MCPWM_TIMER0_TEP_INT_CLR : WO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEP_INT_CLR_S 6 -/* MCPWM_TIMER2_TEZ_INT_CLR : WO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 -/* MCPWM_TIMER1_TEZ_INT_CLR : WO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 -/* MCPWM_TIMER0_TEZ_INT_CLR : WO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 -/* MCPWM_TIMER2_STOP_INT_CLR : WO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_STOP_INT_CLR_S 2 -/* MCPWM_TIMER1_STOP_INT_CLR : WO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_STOP_INT_CLR_S 1 -/* MCPWM_TIMER0_STOP_INT_CLR : WO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_CLR (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_V 0x1 +/** MCPWM_INT_CLR_REG register + * Interrupt clear bits + */ +#define MCPWM_INT_CLR_REG(i) (DR_REG_MCPWM_BASE(i) + 0x11c) +/** MCPWM_TIMER0_STOP_INT_CLR : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_CLR (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_CLR_M (MCPWM_TIMER0_STOP_INT_CLR_V << MCPWM_TIMER0_STOP_INT_CLR_S) +#define MCPWM_TIMER0_STOP_INT_CLR_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_CLR_S 0 +/** MCPWM_TIMER1_STOP_INT_CLR : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_CLR_M (MCPWM_TIMER1_STOP_INT_CLR_V << MCPWM_TIMER1_STOP_INT_CLR_S) +#define MCPWM_TIMER1_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_CLR_S 1 +/** MCPWM_TIMER2_STOP_INT_CLR : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_CLR_M (MCPWM_TIMER2_STOP_INT_CLR_V << MCPWM_TIMER2_STOP_INT_CLR_S) +#define MCPWM_TIMER2_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_CLR_S 2 +/** MCPWM_TIMER0_TEZ_INT_CLR : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_CLR_M (MCPWM_TIMER0_TEZ_INT_CLR_V << MCPWM_TIMER0_TEZ_INT_CLR_S) +#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 +/** MCPWM_TIMER1_TEZ_INT_CLR : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_CLR_M (MCPWM_TIMER1_TEZ_INT_CLR_V << MCPWM_TIMER1_TEZ_INT_CLR_S) +#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 +/** MCPWM_TIMER2_TEZ_INT_CLR : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_CLR_M (MCPWM_TIMER2_TEZ_INT_CLR_V << MCPWM_TIMER2_TEZ_INT_CLR_S) +#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 +/** MCPWM_TIMER0_TEP_INT_CLR : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_CLR_M (MCPWM_TIMER0_TEP_INT_CLR_V << MCPWM_TIMER0_TEP_INT_CLR_S) +#define MCPWM_TIMER0_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_CLR_S 6 +/** MCPWM_TIMER1_TEP_INT_CLR : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_CLR_M (MCPWM_TIMER1_TEP_INT_CLR_V << MCPWM_TIMER1_TEP_INT_CLR_S) +#define MCPWM_TIMER1_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_CLR_S 7 +/** MCPWM_TIMER2_TEP_INT_CLR : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_CLR_M (MCPWM_TIMER2_TEP_INT_CLR_V << MCPWM_TIMER2_TEP_INT_CLR_S) +#define MCPWM_TIMER2_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_CLR_S 8 +/** MCPWM_FAULT0_INT_CLR : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_CLR (BIT(9)) +#define MCPWM_FAULT0_INT_CLR_M (MCPWM_FAULT0_INT_CLR_V << MCPWM_FAULT0_INT_CLR_S) +#define MCPWM_FAULT0_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_INT_CLR_S 9 +/** MCPWM_FAULT1_INT_CLR : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_CLR (BIT(10)) +#define MCPWM_FAULT1_INT_CLR_M (MCPWM_FAULT1_INT_CLR_V << MCPWM_FAULT1_INT_CLR_S) +#define MCPWM_FAULT1_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_INT_CLR_S 10 +/** MCPWM_FAULT2_INT_CLR : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_CLR (BIT(11)) +#define MCPWM_FAULT2_INT_CLR_M (MCPWM_FAULT2_INT_CLR_V << MCPWM_FAULT2_INT_CLR_S) +#define MCPWM_FAULT2_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_INT_CLR_S 11 +/** MCPWM_FAULT0_CLR_INT_CLR : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_CLR_M (MCPWM_FAULT0_CLR_INT_CLR_V << MCPWM_FAULT0_CLR_INT_CLR_S) +#define MCPWM_FAULT0_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_CLR_S 12 +/** MCPWM_FAULT1_CLR_INT_CLR : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_CLR_M (MCPWM_FAULT1_CLR_INT_CLR_V << MCPWM_FAULT1_CLR_INT_CLR_S) +#define MCPWM_FAULT1_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_CLR_S 13 +/** MCPWM_FAULT2_CLR_INT_CLR : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_CLR_M (MCPWM_FAULT2_CLR_INT_CLR_V << MCPWM_FAULT2_CLR_INT_CLR_S) +#define MCPWM_FAULT2_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_CLR_S 14 +/** MCPWM_OP0_TEA_INT_CLR : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_CLR (BIT(15)) +#define MCPWM_OP0_TEA_INT_CLR_M (MCPWM_OP0_TEA_INT_CLR_V << MCPWM_OP0_TEA_INT_CLR_S) +#define MCPWM_OP0_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEA_INT_CLR_S 15 +/** MCPWM_OP1_TEA_INT_CLR : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_CLR (BIT(16)) +#define MCPWM_OP1_TEA_INT_CLR_M (MCPWM_OP1_TEA_INT_CLR_V << MCPWM_OP1_TEA_INT_CLR_S) +#define MCPWM_OP1_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEA_INT_CLR_S 16 +/** MCPWM_OP2_TEA_INT_CLR : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_CLR (BIT(17)) +#define MCPWM_OP2_TEA_INT_CLR_M (MCPWM_OP2_TEA_INT_CLR_V << MCPWM_OP2_TEA_INT_CLR_S) +#define MCPWM_OP2_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEA_INT_CLR_S 17 +/** MCPWM_OP0_TEB_INT_CLR : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_CLR (BIT(18)) +#define MCPWM_OP0_TEB_INT_CLR_M (MCPWM_OP0_TEB_INT_CLR_V << MCPWM_OP0_TEB_INT_CLR_S) +#define MCPWM_OP0_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEB_INT_CLR_S 18 +/** MCPWM_OP1_TEB_INT_CLR : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_CLR (BIT(19)) +#define MCPWM_OP1_TEB_INT_CLR_M (MCPWM_OP1_TEB_INT_CLR_V << MCPWM_OP1_TEB_INT_CLR_S) +#define MCPWM_OP1_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEB_INT_CLR_S 19 +/** MCPWM_OP2_TEB_INT_CLR : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_CLR (BIT(20)) +#define MCPWM_OP2_TEB_INT_CLR_M (MCPWM_OP2_TEB_INT_CLR_V << MCPWM_OP2_TEB_INT_CLR_S) +#define MCPWM_OP2_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEB_INT_CLR_S 20 +/** MCPWM_FH0_CBC_INT_CLR : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_CLR (BIT(21)) +#define MCPWM_FH0_CBC_INT_CLR_M (MCPWM_FH0_CBC_INT_CLR_V << MCPWM_FH0_CBC_INT_CLR_S) +#define MCPWM_FH0_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH0_CBC_INT_CLR_S 21 +/** MCPWM_FH1_CBC_INT_CLR : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_CLR (BIT(22)) +#define MCPWM_FH1_CBC_INT_CLR_M (MCPWM_FH1_CBC_INT_CLR_V << MCPWM_FH1_CBC_INT_CLR_S) +#define MCPWM_FH1_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH1_CBC_INT_CLR_S 22 +/** MCPWM_FH2_CBC_INT_CLR : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_CLR (BIT(23)) +#define MCPWM_FH2_CBC_INT_CLR_M (MCPWM_FH2_CBC_INT_CLR_V << MCPWM_FH2_CBC_INT_CLR_S) +#define MCPWM_FH2_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH2_CBC_INT_CLR_S 23 +/** MCPWM_FH0_OST_INT_CLR : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_CLR (BIT(24)) +#define MCPWM_FH0_OST_INT_CLR_M (MCPWM_FH0_OST_INT_CLR_V << MCPWM_FH0_OST_INT_CLR_S) +#define MCPWM_FH0_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH0_OST_INT_CLR_S 24 +/** MCPWM_FH1_OST_INT_CLR : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_CLR (BIT(25)) +#define MCPWM_FH1_OST_INT_CLR_M (MCPWM_FH1_OST_INT_CLR_V << MCPWM_FH1_OST_INT_CLR_S) +#define MCPWM_FH1_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH1_OST_INT_CLR_S 25 +/** MCPWM_FH2_OST_INT_CLR : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_CLR (BIT(26)) +#define MCPWM_FH2_OST_INT_CLR_M (MCPWM_FH2_OST_INT_CLR_V << MCPWM_FH2_OST_INT_CLR_S) +#define MCPWM_FH2_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH2_OST_INT_CLR_S 26 +/** MCPWM_CAP0_INT_CLR : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_CLR (BIT(27)) +#define MCPWM_CAP0_INT_CLR_M (MCPWM_CAP0_INT_CLR_V << MCPWM_CAP0_INT_CLR_S) +#define MCPWM_CAP0_INT_CLR_V 0x00000001U +#define MCPWM_CAP0_INT_CLR_S 27 +/** MCPWM_CAP1_INT_CLR : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_CLR (BIT(28)) +#define MCPWM_CAP1_INT_CLR_M (MCPWM_CAP1_INT_CLR_V << MCPWM_CAP1_INT_CLR_S) +#define MCPWM_CAP1_INT_CLR_V 0x00000001U +#define MCPWM_CAP1_INT_CLR_S 28 +/** MCPWM_CAP2_INT_CLR : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_CLR (BIT(29)) +#define MCPWM_CAP2_INT_CLR_M (MCPWM_CAP2_INT_CLR_V << MCPWM_CAP2_INT_CLR_S) +#define MCPWM_CAP2_INT_CLR_V 0x00000001U +#define MCPWM_CAP2_INT_CLR_S 29 -#define MCPWM_CLK_REG(i) (REG_MCPWM_BASE(i) + 0x0120) -/* MCPWM_CLK_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Force clock on for this reg file*/ -#define MCPWM_CLK_EN (BIT(0)) -#define MCPWM_CLK_EN_M (BIT(0)) -#define MCPWM_CLK_EN_V 0x1 +/** MCPWM_CLK_REG register + * MCPWM APB configuration register + */ +#define MCPWM_CLK_REG(i) (DR_REG_MCPWM_BASE(i) + 0x120) +/** MCPWM_CLK_EN : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ +#define MCPWM_CLK_EN (BIT(0)) +#define MCPWM_CLK_EN_M (MCPWM_CLK_EN_V << MCPWM_CLK_EN_S) +#define MCPWM_CLK_EN_V 0x00000001U #define MCPWM_CLK_EN_S 0 -#define MCPWM_VERSION_REG(i) (REG_MCPWM_BASE(i) + 0x0124) -/* MCPWM_DATE : R/W ;bitpos:[27:0] ;default: 28'h1509110 ; */ -/*description: Version of this reg file*/ -#define MCPWM_DATE 0x0FFFFFFF -#define MCPWM_DATE_M ((MCPWM_DATE_V)<<(MCPWM_DATE_S)) -#define MCPWM_DATE_V 0xFFFFFFF +/** MCPWM_VERSION_REG register + * Version register. + */ +#define MCPWM_VERSION_REG(i) (DR_REG_MCPWM_BASE(i) + 0x124) +/** MCPWM_DATE : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ +#define MCPWM_DATE 0x0FFFFFFFU +#define MCPWM_DATE_M (MCPWM_DATE_V << MCPWM_DATE_S) +#define MCPWM_DATE_V 0x0FFFFFFFU #define MCPWM_DATE_S 0 - - - -#endif /*_SOC_MCPWM_REG_H_ */ +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32/include/soc/mcpwm_struct.h b/components/soc/esp32/include/soc/mcpwm_struct.h index 87f3f22727..afd2a5633c 100644 --- a/components/soc/esp32/include/soc/mcpwm_struct.h +++ b/components/soc/esp32/include/soc/mcpwm_struct.h @@ -1,461 +1,1468 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include - #ifdef __cplusplus extern "C" { #endif -typedef volatile struct mcpwm_dev_s { - union { - struct { - uint32_t prescale : 8; /*Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1)*/ - uint32_t reserved8 : 24; - }; - uint32_t val; - } clk_cfg; +/** Group: Prescaler configuration */ +/** Type of clk_cfg register + * PWM clock prescaler register. + */ +typedef union { struct { - union { - struct { - uint32_t prescale : 8; /*period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1)*/ - uint32_t period : 16; /*period shadow reg of PWM timer0*/ - uint32_t upmethod : 2; /*Update method for active reg of PWM timer0 period 0: immediate 1: TEZ 2: sync 3: TEZ | sync. TEZ here and below means timer equal zero event*/ - uint32_t reserved26 : 6; - }; - uint32_t val; - } period; - union { - struct { - uint32_t start : 3; /*PWM timer0 start and stop control. 0: stop @ TEZ 1: stop @ TEP 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP. TEP here and below means timer equal period event*/ - uint32_t mode : 2; /*PWM timer0 working mode 0: freeze 1: increase mod 2: decrease mod 3: up-down mod*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } mode; - union { - struct { - uint32_t in_en : 1; /*when set timer reload with phase on sync input event is enabled*/ - uint32_t sync_sw : 1; /*write the negate value will trigger a software sync*/ - uint32_t out_sel : 2; /*PWM timer0 synco selection 0: synci 1: TEZ 2: TEP else 0*/ - uint32_t timer_phase : 16; /*phase for timer reload on sync event*/ - uint32_t phase_direct : 1; /*counter direction to apply on sync event*/ - uint32_t reserved21 : 11; - }; - uint32_t val; - } sync; - union { - struct { - uint32_t value : 16; /*current PWM timer0 counter value*/ - uint32_t direction : 1; /*current PWM timer0 counter direction 0: increment 1: decrement*/ - uint32_t reserved17 : 15; - }; - uint32_t val; - } status; - } timer[3]; + /** clk_prescale : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ + uint32_t clk_prescale: 8; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_clk_cfg_reg_t; - union { - struct { - uint32_t t0_in_sel : 3; /*select sync input for PWM timer0 1: PWM timer0 synco 2: PWM timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix else: none*/ - uint32_t t1_in_sel : 3; /*select sync input for PWM timer1 1: PWM timer0 synco 2: PWM timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix else: none*/ - uint32_t t2_in_sel : 3; /*select sync input for PWM timer2 1: PWM timer0 synco 2: PWM timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix else: none*/ - uint32_t ext_in0_inv : 1; /*invert SYNC0 from GPIO matrix*/ - uint32_t ext_in1_inv : 1; /*invert SYNC1 from GPIO matrix*/ - uint32_t ext_in2_inv : 1; /*invert SYNC2 from GPIO matrix*/ - uint32_t reserved12 : 20; - }; - uint32_t val; - } timer_synci_cfg; - union { - struct { - uint32_t operator0_sel : 2; /*Select which PWM timer's is the timing reference for PWM operator0 0: timer0 1: timer1 2: timer2*/ - uint32_t operator1_sel : 2; /*Select which PWM timer's is the timing reference for PWM operator1 0: timer0 1: timer1 2: timer2*/ - uint32_t operator2_sel : 2; /*Select which PWM timer's is the timing reference for PWM operator2 0: timer0 1: timer1 2: timer2*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } timer_sel; +/** Group: MCPWM Timer Configuration and status */ +/** Type of timer_cfg0 register + * PWM timer period and update method configuration register. + */ +typedef union { struct { - union { - struct { - uint32_t a_upmethod : 4; /*Update method for PWM compare0 A's active reg. 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: freeze*/ - uint32_t b_upmethod : 4; /*Update method for PWM compare0 B's active reg. 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: freeze*/ - uint32_t a_shdw_full : 1; /*Set and reset by hardware. If set PWM compare0 A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ - uint32_t b_shdw_full : 1; /*Set and reset by hardware. If set PWM compare0 B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ - uint32_t reserved10 : 22; - }; - uint32_t val; - } cmpr_cfg; - union { - struct { - uint32_t cmpr_val : 16; /*PWM compare0 A's shadow reg*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } cmpr_value[2]; - union { - struct { - uint32_t upmethod : 4; /*Update method for PWM generate0's active reg of configuration. 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: freeze*/ - uint32_t t0_sel : 3; /*Source selection for PWM generate0 event_t0 take effect immediately 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ - uint32_t t1_sel : 3; /*Source selection for PWM generate0 event_t1 take effect immediately 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ - uint32_t reserved10 : 22; - }; - uint32_t val; - } gen_cfg0; - union { - struct { - uint32_t cntu_force_upmethod : 6; /*Update method for continuous software force of PWM generate0. 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: freeze. (TEA/B here and below means timer equals A/B event)*/ - uint32_t a_cntuforce_mode : 2; /*Continuous software force mode for PWM0A. 0: disabled 1: low 2: high 3: disabled*/ - uint32_t b_cntuforce_mode : 2; /*Continuous software force mode for PWM0B. 0: disabled 1: low 2: high 3: disabled*/ - uint32_t a_nciforce : 1; /*non-continuous immediate software force trigger for PWM0A a toggle will trigger a force event*/ - uint32_t a_nciforce_mode : 2; /*non-continuous immediate software force mode for PWM0A 0: disabled 1: low 2: high 3: disabled*/ - uint32_t b_nciforce : 1; /*non-continuous immediate software force trigger for PWM0B a toggle will trigger a force event*/ - uint32_t b_nciforce_mode : 2; /*non-continuous immediate software force mode for PWM0B 0: disabled 1: low 2: high 3: disabled*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } gen_force; - union { - struct { - uint32_t utez : 2; /*Action on PWM0A triggered by event TEZ when timer increasing*/ - uint32_t utep : 2; /*Action on PWM0A triggered by event TEP when timer increasing*/ - uint32_t utea : 2; /*Action on PWM0A triggered by event TEA when timer increasing*/ - uint32_t uteb : 2; /*Action on PWM0A triggered by event TEB when timer increasing*/ - uint32_t ut0 : 2; /*Action on PWM0A triggered by event_t0 when timer increasing*/ - uint32_t ut1 : 2; /*Action on PWM0A triggered by event_t1 when timer increasing*/ - uint32_t dtez : 2; /*Action on PWM0A triggered by event TEZ when timer decreasing*/ - uint32_t dtep : 2; /*Action on PWM0A triggered by event TEP when timer decreasing*/ - uint32_t dtea : 2; /*Action on PWM0A triggered by event TEA when timer decreasing*/ - uint32_t dteb : 2; /*Action on PWM0A triggered by event TEB when timer decreasing*/ - uint32_t dt0 : 2; /*Action on PWM0A triggered by event_t0 when timer decreasing*/ - uint32_t dt1 : 2; /*Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change 1: low 2: high 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } generator[2]; - union { - struct { - uint32_t fed_upmethod : 4; /*Update method for FED (falling edge delay) active reg. 0: immediate bit0: tez bit1: tep bit2: sync bit3: freeze*/ - uint32_t red_upmethod : 4; /*Update method for RED (rising edge delay) active reg. 0: immediate bit0: tez bit1: tep bit2: sync bit3: freeze*/ - uint32_t deb_mode : 1; /*S8 in documentation dual-edge B mode 0: fed/red take effect on different path separately 1: fed/red take effect on B path A out is in bypass or dulpB mode*/ - uint32_t a_outswap : 1; /*S6 in documentation*/ - uint32_t b_outswap : 1; /*S7 in documentation*/ - uint32_t red_insel : 1; /*S4 in documentation*/ - uint32_t fed_insel : 1; /*S5 in documentation*/ - uint32_t red_outinvert : 1; /*S2 in documentation*/ - uint32_t fed_outinvert : 1; /*S3 in documentation*/ - uint32_t a_outbypass : 1; /*S1 in documentation*/ - uint32_t b_outbypass : 1; /*S0 in documentation*/ - uint32_t clk_sel : 1; /*Dead band0 clock selection. 0: PWM_clk 1: PT_clk*/ - uint32_t reserved18 : 14; - }; - uint32_t val; - } db_cfg; - union { - struct { - uint32_t fed : 16; /*Shadow reg for FED*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_fed_cfg; - union { - struct { - uint32_t red : 16; /*Shadow reg for RED*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_red_cfg; - union { - struct { - uint32_t en : 1; /*When set carrier0 function is enabled. When reset carrier0 is bypassed*/ - uint32_t prescale : 4; /*carrier0 clk (CP_clk) prescale value. Period of CP_clk = period of PWM_clk * (PWM_CARRIER0_PRESCALE + 1)*/ - uint32_t duty : 3; /*carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8*/ - uint32_t oshtwth : 4; /*width of the fist pulse in number of periods of the carrier*/ - uint32_t out_invert : 1; /*when set invert the output of PWM0A and PWM0B for this submodule*/ - uint32_t in_invert : 1; /*when set invert the input of PWM0A and PWM0B for this submodule*/ - uint32_t reserved14 : 18; - }; - uint32_t val; - } carrier_cfg; - union { - struct { - uint32_t sw_cbc : 1; /*Cycle-by-cycle tripping software force event will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t f2_cbc : 1; /*event_f2 will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t f1_cbc : 1; /*event_f1 will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t f0_cbc : 1; /*event_f0 will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t sw_ost : 1; /*one-shot tripping software force event will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t f2_ost : 1; /*event_f2 will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t f1_ost : 1; /*event_f1 will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t f0_ost : 1; /*event_f0 will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t a_cbc_d : 2; /*Action on PWM0A when cycle-by-cycle trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t a_cbc_u : 2; /*Action on PWM0A when cycle-by-cycle trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t a_ost_d : 2; /*Action on PWM0A when one-shot trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t a_ost_u : 2; /*Action on PWM0A when one-shot trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_cbc_d : 2; /*Action on PWM0B when cycle-by-cycle trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_cbc_u : 2; /*Action on PWM0B when cycle-by-cycle trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_ost_d : 2; /*Action on PWM0B when one-shot trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_ost_u : 2; /*Action on PWM0B when one-shot trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } tz_cfg0; - union { - struct { - uint32_t clr_ost : 1; /*a posedge will clear on going one-shot tripping*/ - uint32_t cbcpulse : 2; /*cycle-by-cycle tripping refresh moment selection. Bit0: TEZ bit1:TEP*/ - uint32_t force_cbc : 1; /*a toggle trigger a cycle-by-cycle tripping software force event*/ - uint32_t force_ost : 1; /*a toggle (software negate its value) trigger a one-shot tripping software force event*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } tz_cfg1; - union { - struct { - uint32_t cbc_on : 1; /*Set and reset by hardware. If set an cycle-by-cycle trip event is on going*/ - uint32_t ost_on : 1; /*Set and reset by hardware. If set an one-shot trip event is on going*/ - uint32_t reserved2 : 30; - }; - uint32_t val; - } tz_status; - } channel[3]; + /** timer_prescale : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER_PRESCALE + 1) + */ + uint32_t timer_prescale: 8; + /** timer_period : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer + */ + uint32_t timer_period: 16; + /** timer_period_upmethod : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ + uint32_t timer_period_upmethod: 2; + uint32_t reserved_26: 6; + }; + uint32_t val; +} mcpwm_timer_cfg0_reg_t; - union { - struct { - uint32_t f0_en : 1; /*When set event_f0 generation is enabled*/ - uint32_t f1_en : 1; /*When set event_f1 generation is enabled*/ - uint32_t f2_en : 1; /*When set event_f2 generation is enabled*/ - uint32_t f0_pole : 1; /*Set event_f0 trigger polarity on FAULT0 source from GPIO matrix. 0: level low 1: level high*/ - uint32_t f1_pole : 1; /*Set event_f1 trigger polarity on FAULT1 source from GPIO matrix. 0: level low 1: level high*/ - uint32_t f2_pole : 1; /*Set event_f2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low 1: level high*/ - uint32_t event_f0 : 1; /*Set and reset by hardware. If set event_f0 is on going*/ - uint32_t event_f1 : 1; /*Set and reset by hardware. If set event_f1 is on going*/ - uint32_t event_f2 : 1; /*Set and reset by hardware. If set event_f2 is on going*/ - uint32_t reserved9 : 23; - }; - uint32_t val; - } fault_detect; - union { - struct { - uint32_t timer_en : 1; /*When set capture timer incrementing under APB_clk is enabled.*/ - uint32_t synci_en : 1; /*When set capture timer sync is enabled.*/ - uint32_t synci_sel : 3; /*capture module sync input selection. 0: none 1: timer0 synco 2: timer1 synco 3: timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix*/ - uint32_t sync_sw : 1; /*Write 1 will force a capture timer sync capture timer is loaded with value in phase register.*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } cap_timer_cfg; - uint32_t cap_timer_phase; /*Phase value for capture timer sync operation.*/ - union { - struct { - uint32_t en : 1; /*When set capture on channel 0 is enabled*/ - uint32_t mode : 2; /*Edge of capture on channel 0 after prescale. bit0: negedge cap en bit1: posedge cap en*/ - uint32_t prescale : 8; /*Value of prescale on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + 1*/ - uint32_t in_invert : 1; /*when set CAP0 form GPIO matrix is inverted before prescale*/ - uint32_t sw : 1; /*Write 1 will trigger a software forced capture on channel 0*/ - uint32_t reserved13 : 19; - }; - uint32_t val; - } cap_cfg_ch[3]; - uint32_t cap_val_ch[3]; /*Value of last capture on channel 0*/ - union { - struct { - uint32_t cap0_edge : 1; /*Edge of last capture trigger on channel 0 0: posedge 1: negedge*/ - uint32_t cap1_edge : 1; /*Edge of last capture trigger on channel 1 0: posedge 1: negedge*/ - uint32_t cap2_edge : 1; /*Edge of last capture trigger on channel 2 0: posedge 1: negedge*/ - uint32_t reserved3 : 29; - }; - uint32_t val; - } cap_status; - union { - struct { - uint32_t global_up_en : 1; /*The global enable of update of all active registers in MCPWM module*/ - uint32_t global_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of all active registers in MCPWM module*/ - uint32_t op0_up_en : 1; /*When set and PWM_GLOBAL_UP_EN is set update of active registers in PWM operator 0 are enabled*/ - uint32_t op0_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 0*/ - uint32_t op1_up_en : 1; /*When set and PWM_GLOBAL_UP_EN is set update of active registers in PWM operator 1 are enabled*/ - uint32_t op1_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 1*/ - uint32_t op2_up_en : 1; /*When set and PWM_GLOBAL_UP_EN is set update of active registers in PWM operator 2 are enabled*/ - uint32_t op2_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 2*/ - uint32_t reserved8 : 24; - }; - uint32_t val; - } update_cfg; - union { - struct { - uint32_t timer0_stop_int_ena : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_ena : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_ena : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_ena : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_ena : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_ena : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_ena : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_ena : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_ena : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_ena : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_ena : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_ena : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_ena : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_ena : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_ena : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_ena : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_ena : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_ena : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_ena : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_ena : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_ena : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_ena : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_ena : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_ena : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_ena : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_ena : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_ena : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_ena : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_ena : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_ena : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t timer0_stop_int_raw : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_raw : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_raw : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_raw : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_raw : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_raw : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_raw : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_raw : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_raw : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_raw : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_raw : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_raw : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_raw : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_raw : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_raw : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_raw : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_raw : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_raw : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_raw : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_raw : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_raw : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_raw : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_raw : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_raw : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_raw : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_raw : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_raw : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_raw : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_raw : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_raw : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t timer0_stop_int_st : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_st : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_st : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_st : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_st : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_st : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_st : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_st : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_st : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_st : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_st : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_st : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_st : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_st : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_st : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_st : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_st : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_st : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_st : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_st : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_st : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_st : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_st : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_st : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_st : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_st : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_st : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_st : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_st : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_st : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t timer0_stop_int_clr : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_clr : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_clr : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_clr : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_clr : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_clr : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_clr : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_clr : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_clr : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_clr : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_clr : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_clr : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_clr : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_clr : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_clr : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_clr : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_clr : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_clr : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_clr : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_clr : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_clr : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_clr : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_clr : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_clr : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_clr : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_clr : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_clr : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_clr : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_clr : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_clr : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t clk_en : 1; /*Force clock on for this reg file*/ - uint32_t reserved1 : 31; - }; - uint32_t val; - } reg_clk; - union { - struct { - uint32_t date : 28; /*Version of this reg file*/ - uint32_t reserved28 : 4; - }; - uint32_t val; - } version; +/** Type of timer_cfg1 register + * PWM timer working mode and start/stop control configuration register. + */ +typedef union { + struct { + /** timer_start : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer start and stop control. 0: if PWM timer starts, then stops at TEZ, 1: + * if timer starts, then stops at TEP, 2: PWM timer starts and runs on, 3: timer + * starts and stops at the next TEZ, 4: timer starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ + uint32_t timer_start: 3; + /** timer_mod : R/W; bitpos: [4:3]; default: 0; + * PWM timer working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ + uint32_t timer_mod: 2; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_timer_cfg1_reg_t; + +/** Type of timer_sync register + * PWM timer sync function configuration register. + */ +typedef union { + struct { + /** timer_synci_en : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ + uint32_t timer_synci_en: 1; + /** timer_sync_sw : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ + uint32_t timer_sync_sw: 1; + /** timer_synco_sel : R/W; bitpos: [3:2]; default: 0; + * PWM timer sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer_sync_sw bit + */ + uint32_t timer_synco_sel: 2; + /** timer_phase : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ + uint32_t timer_phase: 16; + /** timer_phase_direction : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer's direction at the time sync event occurs when timer mode + * is up-down mode: 0-increase,1-decrease + */ + uint32_t timer_phase_direction: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} mcpwm_timer_sync_reg_t; + +/** Type of timer_status register + * PWM timer status register. + */ +typedef union { + struct { + /** timer_value : RO; bitpos: [15:0]; default: 0; + * current PWM timer counter value + */ + uint32_t timer_value: 16; + /** timer_direction : RO; bitpos: [16]; default: 0; + * current PWM timer counter direction, 0: increment 1: decrement + */ + uint32_t timer_direction: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} mcpwm_timer_status_reg_t; + + +/** Group: Common configuration for MCPWM timers */ +/** Type of timer_synci_cfg register + * Synchronization input selection for three PWM timers. + */ +typedef union { + struct { + /** timer0_syncisel : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer0_syncisel: 3; + /** timer1_syncisel : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer1_syncisel: 3; + /** timer2_syncisel : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer2_syncisel: 3; + /** external_synci0_invert : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ + uint32_t external_synci0_invert: 1; + /** external_synci1_invert : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ + uint32_t external_synci1_invert: 1; + /** external_synci2_invert : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ + uint32_t external_synci2_invert: 1; + uint32_t reserved_12: 20; + }; + uint32_t val; +} mcpwm_timer_synci_cfg_reg_t; + +/** Type of operator_timersel register + * Select specific timer for PWM operators. + */ +typedef union { + struct { + /** operator0_timersel : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator0_timersel: 2; + /** operator1_timersel : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator1_timersel: 2; + /** operator2_timersel : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator2_timersel: 2; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_operator_timersel_reg_t; + + +/** Group: MCPWM Operator Configuration and Status */ +/** Type of gen_stmp_cfg register + * Transfer status and update method for time stamp registers A and B + */ +typedef union { + struct { + /** gen_a_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_a_upmethod: 4; + /** gen_b_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_b_upmethod: 4; + /** gen_a_shdw_full : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_a_shdw_full: 1; + /** gen_b_shdw_full : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_b_shdw_full: 1; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_stmp_cfg_reg_t; + +/** Type of gen_tstmp register + * PWM generator shadow register for timer stamp + */ +typedef union { + struct { + /** gen : R/W; bitpos: [15:0]; default: 0; + * PWM generator time stamp's shadow register + */ + uint32_t gen: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_tstmp_reg_t; + +/** Type of gen_cfg0 register + * PWM generator event T0 and T1 handling + */ +typedef union { + struct { + /** gen_cfg_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ + uint32_t gen_cfg_upmethod: 4; + /** gen_t0_sel : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t0_sel: 3; + /** gen_t1_sel : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t1_sel: 3; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_cfg0_reg_t; + +/** Type of gen_force register + * Permissives to force PWM0A and PWM0B outputs by software + */ +typedef union { + struct { + /** gen_cntuforce_upmethod : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ + uint32_t gen_cntuforce_upmethod: 6; + /** gen_a_cntuforce_mode : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_a_cntuforce_mode: 2; + /** gen_b_cntuforce_mode : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_b_cntuforce_mode: 2; + /** gen_a_nciforce : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ + uint32_t gen_a_nciforce: 1; + /** gen_a_nciforce_mode : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_a_nciforce_mode: 2; + /** gen_b_nciforce : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ + uint32_t gen_b_nciforce: 1; + /** gen_b_nciforce_mode : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_b_nciforce_mode: 2; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_force_reg_t; + +/** Type of generator register + * Actions triggered by events on PWM0A + */ +typedef union { + struct { + /** gen_utez : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utez: 2; + /** gen_utep : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utep: 2; + /** gen_utea : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utea: 2; + /** gen_uteb : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_uteb: 2; + /** gen_ut0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut0: 2; + /** gen_ut1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut1: 2; + /** gen_dtez : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtez: 2; + /** gen_dtep : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtep: 2; + /** gen_dtea : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtea: 2; + /** gen_dteb : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dteb: 2; + /** gen_dt0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt0: 2; + /** gen_dt1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt1: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_gen_reg_t; + +/** Type of dt_cfg register + * PWM generator dead time type selection and configuration + */ +typedef union { + struct { + /** dt_fed_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_fed_upmethod: 4; + /** dt_red_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_red_upmethod: 4; + /** dt_deb_mode : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ + uint32_t dt_deb_mode: 1; + /** dt_a_outswap : R/W; bitpos: [9]; default: 0; + * S6 in table + */ + uint32_t dt_a_outswap: 1; + /** dt_b_outswap : R/W; bitpos: [10]; default: 0; + * S7 in table + */ + uint32_t dt_b_outswap: 1; + /** dt_red_insel : R/W; bitpos: [11]; default: 0; + * S4 in table + */ + uint32_t dt_red_insel: 1; + /** dt_fed_insel : R/W; bitpos: [12]; default: 0; + * S5 in table + */ + uint32_t dt_fed_insel: 1; + /** dt_red_outinvert : R/W; bitpos: [13]; default: 0; + * S2 in table + */ + uint32_t dt_red_outinvert: 1; + /** dt_fed_outinvert : R/W; bitpos: [14]; default: 0; + * S3 in table + */ + uint32_t dt_fed_outinvert: 1; + /** dt_a_outbypass : R/W; bitpos: [15]; default: 1; + * S1 in table + */ + uint32_t dt_a_outbypass: 1; + /** dt_b_outbypass : R/W; bitpos: [16]; default: 1; + * S0 in table + */ + uint32_t dt_b_outbypass: 1; + /** dt_clk_sel : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ + uint32_t dt_clk_sel: 1; + uint32_t reserved_18: 14; + }; + uint32_t val; +} mcpwm_dt_cfg_reg_t; + +/** Type of dt_fed_cfg register + * PWM generator shadow register for falling edge delay (FED). + */ +typedef union { + struct { + /** dt_fed : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ + uint32_t dt_fed: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_fed_cfg_reg_t; + +/** Type of dt_red_cfg register + * PWM generator shadow register for rising edge delay (RED). + */ +typedef union { + struct { + /** dt_red : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ + uint32_t dt_red: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_red_cfg_reg_t; + +/** Type of carrier_cfg register + * PWM generator carrier enable and configuratoin + */ +typedef union { + struct { + /** carrier_en : R/W; bitpos: [0]; default: 0; + * When set, carrier function is enabled. When cleared, carrier is bypassed + */ + uint32_t carrier_en: 1; + /** carrier_prescale : R/W; bitpos: [4:1]; default: 0; + * PWM carrier clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER_PRESCALE + 1) + */ + uint32_t carrier_prescale: 4; + /** carrier_duty : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER_DUTY / 8 + */ + uint32_t carrier_duty: 3; + /** carrier_oshtwth : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ + uint32_t carrier_oshtwth: 4; + /** carrier_out_invert : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_out_invert: 1; + /** carrier_in_invert : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_in_invert: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} mcpwm_carrier_cfg_reg_t; + +/** Type of fh_cfg0 register + * Actions on PWM0A and PWM0B trip events + */ +typedef union { + struct { + /** fh_sw_cbc : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_cbc: 1; + /** fh_f2_cbc : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_cbc: 1; + /** fh_f1_cbc : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_cbc: 1; + /** fh_f0_cbc : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_cbc: 1; + /** fh_sw_ost : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_ost: 1; + /** fh_f2_ost : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_ost: 1; + /** fh_f1_ost : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_ost: 1; + /** fh_f0_ost : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_ost: 1; + /** fh_a_cbc_d : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_d: 2; + /** fh_a_cbc_u : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_u: 2; + /** fh_a_ost_d : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_d: 2; + /** fh_a_ost_u : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_u: 2; + /** fh_b_cbc_d : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_d: 2; + /** fh_b_cbc_u : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_u: 2; + /** fh_b_ost_d : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_d: 2; + /** fh_b_ost_u : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_u: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_fh_cfg0_reg_t; + +/** Type of fh_cfg1 register + * Software triggers for fault handler actions + */ +typedef union { + struct { + /** fh_clr_ost : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ + uint32_t fh_clr_ost: 1; + /** fh_cbcpulse : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ + uint32_t fh_cbcpulse: 2; + /** fh_force_cbc : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ + uint32_t fh_force_cbc: 1; + /** fh_force_ost : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ + uint32_t fh_force_ost: 1; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_fh_cfg1_reg_t; + +/** Type of fh_status register + * Status of fault events. + */ +typedef union { + struct { + /** fh_cbc_on : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ + uint32_t fh_cbc_on: 1; + /** fh_ost_on : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ + uint32_t fh_ost_on: 1; + uint32_t reserved_2: 30; + }; + uint32_t val; +} mcpwm_fh_status_reg_t; + +/** Group: Fault Detection Configuration and Status */ +/** Type of fault_detect register + * Fault detection configuration and status + */ +typedef union { + struct { + /** f0_en : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ + uint32_t f0_en: 1; + /** f1_en : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ + uint32_t f1_en: 1; + /** f2_en : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ + uint32_t f2_en: 1; + /** f0_pole : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f0_pole: 1; + /** f1_pole : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f1_pole: 1; + /** f2_pole : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f2_pole: 1; + /** event_f0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ + uint32_t event_f0: 1; + /** event_f1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ + uint32_t event_f1: 1; + /** event_f2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ + uint32_t event_f2: 1; + uint32_t reserved_9: 23; + }; + uint32_t val; +} mcpwm_fault_detect_reg_t; + + +/** Group: Capture Configuration and Status */ +/** Type of cap_timer_cfg register + * Configure capture timer + */ +typedef union { + struct { + /** cap_timer_en : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ + uint32_t cap_timer_en: 1; + /** cap_synci_en : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ + uint32_t cap_synci_en: 1; + /** cap_synci_sel : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ + uint32_t cap_synci_sel: 3; + /** cap_sync_sw : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ + uint32_t cap_sync_sw: 1; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_cap_timer_cfg_reg_t; + +/** Type of cap_timer_phase register + * Phase for capture timer sync + */ +typedef union { + struct { + /** cap_timer_phase : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ + uint32_t cap_timer_phase: 32; + }; + uint32_t val; +} mcpwm_cap_timer_phase_reg_t; + +/** Type of cap_chn_cfg register + * Capture channel 0 configuration and enable + */ +typedef union { + struct { + /** capn_en : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ + uint32_t capn_en: 1; + /** capn_mode : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ + uint32_t capn_mode: 2; + /** capn_prescale : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAPn. Prescale value = PWM_CAPn_PRESCALE + + * 1 + */ + uint32_t capn_prescale: 8; + /** capn_in_invert : R/W; bitpos: [11]; default: 0; + * when set, CAPn form GPIO matrix is inverted before prescale + */ + uint32_t capn_in_invert: 1; + /** capn_sw : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ + uint32_t capn_sw: 1; + uint32_t reserved_13: 19; + }; + uint32_t val; +} mcpwm_cap_chn_cfg_reg_t; + +/** Type of cap_chn register + * chn capture value status register + */ +typedef union { + struct { + /** capn_value : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel n + */ + uint32_t capn_value: 32; + }; + uint32_t val; +} mcpwm_cap_chn_reg_t; + +/** Type of cap_status register + * Edge of last capture trigger + */ +typedef union { + struct { + /** cap0_edge : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ + uint32_t cap0_edge: 1; + /** cap1_edge : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ + uint32_t cap1_edge: 1; + /** cap2_edge : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ + uint32_t cap2_edge: 1; + uint32_t reserved_3: 29; + }; + uint32_t val; +} mcpwm_cap_status_reg_t; + + +/** Group: Enable update of active registers */ +/** Type of update_cfg register + * Enable update. + */ +typedef union { + struct { + /** global_up_en : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ + uint32_t global_up_en: 1; + /** global_force_up : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ + uint32_t global_force_up: 1; + /** op0_up_en : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ + uint32_t op0_up_en: 1; + /** op0_force_up : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ + uint32_t op0_force_up: 1; + /** op1_up_en : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ + uint32_t op1_up_en: 1; + /** op1_force_up : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ + uint32_t op1_force_up: 1; + /** op2_up_en : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ + uint32_t op2_up_en: 1; + /** op2_force_up : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ + uint32_t op2_force_up: 1; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_update_cfg_reg_t; + + +/** Group: Manage Interrupts */ +/** Type of int_ena register + * Interrupt enable bits + */ +typedef union { + struct { + /** timer0_stop_int_ena : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_ena: 1; + /** timer1_stop_int_ena : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_ena: 1; + /** timer2_stop_int_ena : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_ena: 1; + /** timer0_tez_int_ena : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_ena: 1; + /** timer1_tez_int_ena : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_ena: 1; + /** timer2_tez_int_ena : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_ena: 1; + /** timer0_tep_int_ena : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_ena: 1; + /** timer1_tep_int_ena : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_ena: 1; + /** timer2_tep_int_ena : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_ena: 1; + /** fault0_int_ena : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_ena: 1; + /** fault1_int_ena : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_ena: 1; + /** fault2_int_ena : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_ena: 1; + /** fault0_clr_int_ena : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_ena: 1; + /** fault1_clr_int_ena : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_ena: 1; + /** fault2_clr_int_ena : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_ena: 1; + /** op0_tea_int_ena : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_ena: 1; + /** op1_tea_int_ena : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_ena: 1; + /** op2_tea_int_ena : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_ena: 1; + /** op0_teb_int_ena : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_ena: 1; + /** op1_teb_int_ena : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_ena: 1; + /** op2_teb_int_ena : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_ena: 1; + /** fh0_cbc_int_ena : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ + uint32_t fh0_cbc_int_ena: 1; + /** fh1_cbc_int_ena : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ + uint32_t fh1_cbc_int_ena: 1; + /** fh2_cbc_int_ena : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ + uint32_t fh2_cbc_int_ena: 1; + /** fh0_ost_int_ena : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_ena: 1; + /** fh1_ost_int_ena : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_ena: 1; + /** fh2_ost_int_ena : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_ena: 1; + /** cap0_int_ena : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_ena: 1; + /** cap1_int_ena : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_ena: 1; + /** cap2_int_ena : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_ena: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_ena_reg_t; + +/** Type of int_raw register + * Raw interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_raw : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_raw: 1; + /** timer1_stop_int_raw : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_raw: 1; + /** timer2_stop_int_raw : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_raw: 1; + /** timer0_tez_int_raw : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_raw: 1; + /** timer1_tez_int_raw : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_raw: 1; + /** timer2_tez_int_raw : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_raw: 1; + /** timer0_tep_int_raw : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_raw: 1; + /** timer1_tep_int_raw : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_raw: 1; + /** timer2_tep_int_raw : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_raw: 1; + /** fault0_int_raw : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_raw: 1; + /** fault1_int_raw : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_raw: 1; + /** fault2_int_raw : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_raw: 1; + /** fault0_clr_int_raw : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_raw: 1; + /** fault1_clr_int_raw : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_raw: 1; + /** fault2_clr_int_raw : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_raw: 1; + /** op0_tea_int_raw : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_raw: 1; + /** op1_tea_int_raw : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_raw: 1; + /** op2_tea_int_raw : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_raw: 1; + /** op0_teb_int_raw : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_raw: 1; + /** op1_teb_int_raw : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_raw: 1; + /** op2_teb_int_raw : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_raw: 1; + /** fh0_cbc_int_raw : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_raw: 1; + /** fh1_cbc_int_raw : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_raw: 1; + /** fh2_cbc_int_raw : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_raw: 1; + /** fh0_ost_int_raw : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_raw: 1; + /** fh1_ost_int_raw : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_raw: 1; + /** fh2_ost_int_raw : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_raw: 1; + /** cap0_int_raw : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_raw: 1; + /** cap1_int_raw : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_raw: 1; + /** cap2_int_raw : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_raw: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_raw_reg_t; + +/** Type of int_st register + * Masked interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_st : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_st: 1; + /** timer1_stop_int_st : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_st: 1; + /** timer2_stop_int_st : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_st: 1; + /** timer0_tez_int_st : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_st: 1; + /** timer1_tez_int_st : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_st: 1; + /** timer2_tez_int_st : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_st: 1; + /** timer0_tep_int_st : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_st: 1; + /** timer1_tep_int_st : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_st: 1; + /** timer2_tep_int_st : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_st: 1; + /** fault0_int_st : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_st: 1; + /** fault1_int_st : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_st: 1; + /** fault2_int_st : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_st: 1; + /** fault0_clr_int_st : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_st: 1; + /** fault1_clr_int_st : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_st: 1; + /** fault2_clr_int_st : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_st: 1; + /** op0_tea_int_st : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_st: 1; + /** op1_tea_int_st : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_st: 1; + /** op2_tea_int_st : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_st: 1; + /** op0_teb_int_st : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_st: 1; + /** op1_teb_int_st : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_st: 1; + /** op2_teb_int_st : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_st: 1; + /** fh0_cbc_int_st : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ + uint32_t fh0_cbc_int_st: 1; + /** fh1_cbc_int_st : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ + uint32_t fh1_cbc_int_st: 1; + /** fh2_cbc_int_st : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ + uint32_t fh2_cbc_int_st: 1; + /** fh0_ost_int_st : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_st: 1; + /** fh1_ost_int_st : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_st: 1; + /** fh2_ost_int_st : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_st: 1; + /** cap0_int_st : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_st: 1; + /** cap1_int_st : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_st: 1; + /** cap2_int_st : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_st: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_st_reg_t; + +/** Type of int_clr register + * Interrupt clear bits + */ +typedef union { + struct { + /** timer0_stop_int_clr : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_clr: 1; + /** timer1_stop_int_clr : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_clr: 1; + /** timer2_stop_int_clr : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_clr: 1; + /** timer0_tez_int_clr : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_clr: 1; + /** timer1_tez_int_clr : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_clr: 1; + /** timer2_tez_int_clr : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_clr: 1; + /** timer0_tep_int_clr : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_clr: 1; + /** timer1_tep_int_clr : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_clr: 1; + /** timer2_tep_int_clr : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_clr: 1; + /** fault0_int_clr : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_clr: 1; + /** fault1_int_clr : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_clr: 1; + /** fault2_int_clr : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_clr: 1; + /** fault0_clr_int_clr : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_clr: 1; + /** fault1_clr_int_clr : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_clr: 1; + /** fault2_clr_int_clr : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_clr: 1; + /** op0_tea_int_clr : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_clr: 1; + /** op1_tea_int_clr : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_clr: 1; + /** op2_tea_int_clr : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_clr: 1; + /** op0_teb_int_clr : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_clr: 1; + /** op1_teb_int_clr : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_clr: 1; + /** op2_teb_int_clr : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_clr: 1; + /** fh0_cbc_int_clr : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_clr: 1; + /** fh1_cbc_int_clr : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_clr: 1; + /** fh2_cbc_int_clr : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_clr: 1; + /** fh0_ost_int_clr : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_clr: 1; + /** fh1_ost_int_clr : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_clr: 1; + /** fh2_ost_int_clr : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_clr: 1; + /** cap0_int_clr : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_clr: 1; + /** cap1_int_clr : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_clr: 1; + /** cap2_int_clr : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_clr: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_clr_reg_t; + + +/** Group: MCMCPWM APB configuration register */ +/** Type of clk register + * MCPWM APB configuration register + */ +typedef union { + struct { + /** clk_en : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ + uint32_t clk_en: 1; + uint32_t reserved_1: 31; + }; + uint32_t val; +} mcpwm_clk_reg_t; + + +/** Group: Version Register */ +/** Type of version register + * Version register. + */ +typedef union { + struct { + /** date : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ + uint32_t date: 28; + uint32_t reserved_28: 4; + }; + uint32_t val; +} mcpwm_version_reg_t; + + +typedef struct { + mcpwm_timer_cfg0_reg_t timer_cfg0; + mcpwm_timer_cfg1_reg_t timer_cfg1; + mcpwm_timer_sync_reg_t timer_sync; + mcpwm_timer_status_reg_t timer_status; +} mcpwm_timer_regs_t; + +typedef struct { + mcpwm_gen_stmp_cfg_reg_t gen_stmp_cfg; + mcpwm_gen_tstmp_reg_t timestamp[2]; + mcpwm_gen_cfg0_reg_t gen_cfg0; + mcpwm_gen_force_reg_t gen_force; + mcpwm_gen_reg_t generator[2]; + mcpwm_dt_cfg_reg_t dt_cfg; + mcpwm_dt_fed_cfg_reg_t dt_fed_cfg; + mcpwm_dt_red_cfg_reg_t dt_red_cfg; + mcpwm_carrier_cfg_reg_t carrier_cfg; + mcpwm_fh_cfg0_reg_t fh_cfg0; + mcpwm_fh_cfg1_reg_t fh_cfg1; + mcpwm_fh_status_reg_t fh_status; +} mcpwm_operator_reg_t; + +typedef struct { + volatile mcpwm_clk_cfg_reg_t clk_cfg; + volatile mcpwm_timer_regs_t timer[3]; + volatile mcpwm_timer_synci_cfg_reg_t timer_synci_cfg; + volatile mcpwm_operator_timersel_reg_t operator_timersel; + volatile mcpwm_operator_reg_t operator[3]; + volatile mcpwm_fault_detect_reg_t fault_detect; + volatile mcpwm_cap_timer_cfg_reg_t cap_timer_cfg; + volatile mcpwm_cap_timer_phase_reg_t cap_timer_phase; + volatile mcpwm_cap_chn_cfg_reg_t cap_chn_cfg[3]; + volatile mcpwm_cap_chn_reg_t cap_chn[3]; + volatile mcpwm_cap_status_reg_t cap_status; + volatile mcpwm_update_cfg_reg_t update_cfg; + volatile mcpwm_int_ena_reg_t int_ena; + volatile mcpwm_int_raw_reg_t int_raw; + volatile mcpwm_int_st_reg_t int_st; + volatile mcpwm_int_clr_reg_t int_clr; + volatile mcpwm_clk_reg_t clk; + volatile mcpwm_version_reg_t version; } mcpwm_dev_t; extern mcpwm_dev_t MCPWM0; extern mcpwm_dev_t MCPWM1; +#ifndef __cplusplus +_Static_assert(sizeof(mcpwm_dev_t) == 0x128, "Invalid size of mcpwm_dev_t structure"); +#endif + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32s3/include/soc/mcpwm_reg.h b/components/soc/esp32s3/include/soc/mcpwm_reg.h index 5ca6eadd7f..6a370aa691 100644 --- a/components/soc/esp32s3/include/soc/mcpwm_reg.h +++ b/components/soc/esp32s3/include/soc/mcpwm_reg.h @@ -1,2910 +1,3829 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _SOC_MCPWM_REG_H_ -#define _SOC_MCPWM_REG_H_ +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once - -#include "soc.h" +#include +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#define REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) +#define DR_REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) -#define MCPWM_CLK_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0) -/* MCPWM_CLK_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_CLK_PRESCALE 0x000000FF -#define MCPWM_CLK_PRESCALE_M ((MCPWM_CLK_PRESCALE_V)<<(MCPWM_CLK_PRESCALE_S)) -#define MCPWM_CLK_PRESCALE_V 0xFF +/** MCPWM_CLK_CFG_REG register + * PWM clock prescaler register. + */ +#define MCPWM_CLK_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x0) +/** MCPWM_CLK_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ +#define MCPWM_CLK_PRESCALE 0x000000FFU +#define MCPWM_CLK_PRESCALE_M (MCPWM_CLK_PRESCALE_V << MCPWM_CLK_PRESCALE_S) +#define MCPWM_CLK_PRESCALE_V 0x000000FFU #define MCPWM_CLK_PRESCALE_S 0 -#define MCPWM_TIMER0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x4) -/* MCPWM_TIMER0_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: 0: immediate, 1: eqz, 2: sync, 3: eqz | sync.*/ -#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_M ((MCPWM_TIMER0_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER0_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER0_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: .*/ -#define MCPWM_TIMER0_PERIOD 0x0000FFFF -#define MCPWM_TIMER0_PERIOD_M ((MCPWM_TIMER0_PERIOD_V)<<(MCPWM_TIMER0_PERIOD_S)) -#define MCPWM_TIMER0_PERIOD_V 0xFFFF -#define MCPWM_TIMER0_PERIOD_S 8 -/* MCPWM_TIMER0_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_PRESCALE 0x000000FF -#define MCPWM_TIMER0_PRESCALE_M ((MCPWM_TIMER0_PRESCALE_V)<<(MCPWM_TIMER0_PRESCALE_S)) -#define MCPWM_TIMER0_PRESCALE_V 0xFF +/** MCPWM_TIMER0_CFG0_REG register + * PWM timer0 period and update method configuration register. + */ +#define MCPWM_TIMER0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4) +/** MCPWM_TIMER0_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer0 stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1) + */ +#define MCPWM_TIMER0_PRESCALE 0x000000FFU +#define MCPWM_TIMER0_PRESCALE_M (MCPWM_TIMER0_PRESCALE_V << MCPWM_TIMER0_PRESCALE_S) +#define MCPWM_TIMER0_PRESCALE_V 0x000000FFU #define MCPWM_TIMER0_PRESCALE_S 0 +/** MCPWM_TIMER0_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer0 + */ +#define MCPWM_TIMER0_PERIOD 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_M (MCPWM_TIMER0_PERIOD_V << MCPWM_TIMER0_PERIOD_S) +#define MCPWM_TIMER0_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_S 8 +/** MCPWM_TIMER0_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer0 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_M (MCPWM_TIMER0_PERIOD_UPMETHOD_V << MCPWM_TIMER0_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x8) -/* MCPWM_TIMER0_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: 0: freeze, 1: inc, 2: dec, 3: up-down.*/ -#define MCPWM_TIMER0_MOD 0x00000003 -#define MCPWM_TIMER0_MOD_M ((MCPWM_TIMER0_MOD_V)<<(MCPWM_TIMER0_MOD_S)) -#define MCPWM_TIMER0_MOD_V 0x3 -#define MCPWM_TIMER0_MOD_S 3 -/* MCPWM_TIMER0_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: 0: stop @ eqz, 1: stop @ eqp, 2: free run, 3: start and stop @ next eqz, 4: star -t and stop @ next eqp,.*/ -#define MCPWM_TIMER0_START 0x00000007 -#define MCPWM_TIMER0_START_M ((MCPWM_TIMER0_START_V)<<(MCPWM_TIMER0_START_S)) -#define MCPWM_TIMER0_START_V 0x7 +/** MCPWM_TIMER0_CFG1_REG register + * PWM timer0 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8) +/** MCPWM_TIMER0_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer0 start and stop control. 0: if PWM timer0 starts, then stops at TEZ, 1: + * if timer0 starts, then stops at TEP, 2: PWM timer0 starts and runs on, 3: timer0 + * starts and stops at the next TEZ, 4: timer0 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER0_START 0x00000007U +#define MCPWM_TIMER0_START_M (MCPWM_TIMER0_START_V << MCPWM_TIMER0_START_S) +#define MCPWM_TIMER0_START_V 0x00000007U #define MCPWM_TIMER0_START_S 0 +/** MCPWM_TIMER0_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer0 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER0_MOD 0x00000003U +#define MCPWM_TIMER0_MOD_M (MCPWM_TIMER0_MOD_V << MCPWM_TIMER0_MOD_S) +#define MCPWM_TIMER0_MOD_V 0x00000003U +#define MCPWM_TIMER0_MOD_S 3 -#define MCPWM_TIMER0_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0xC) -/* MCPWM_TIMER0_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_PHASE 0x0001FFFF -#define MCPWM_TIMER0_PHASE_M ((MCPWM_TIMER0_PHASE_V)<<(MCPWM_TIMER0_PHASE_S)) -#define MCPWM_TIMER0_PHASE_V 0x1FFFF -#define MCPWM_TIMER0_PHASE_S 4 -/* MCPWM_TIMER0_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER0_SYNCO_SEL_M ((MCPWM_TIMER0_SYNCO_SEL_V)<<(MCPWM_TIMER0_SYNCO_SEL_S)) -#define MCPWM_TIMER0_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER0_SYNCO_SEL_S 2 -/* MCPWM_TIMER0_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: write the negate value will trigger a sw sync.*/ -#define MCPWM_TIMER0_SYNC_SW (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_V 0x1 -#define MCPWM_TIMER0_SYNC_SW_S 1 -/* MCPWM_TIMER0_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_TIMER0_SYNC_REG register + * PWM timer0 sync function configuration register. + */ +#define MCPWM_TIMER0_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc) +/** MCPWM_TIMER0_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ #define MCPWM_TIMER0_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_V 0x1 +#define MCPWM_TIMER0_SYNCI_EN_M (MCPWM_TIMER0_SYNCI_EN_V << MCPWM_TIMER0_SYNCI_EN_S) +#define MCPWM_TIMER0_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER0_SYNCI_EN_S 0 +/** MCPWM_TIMER0_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER0_SYNC_SW (BIT(1)) +#define MCPWM_TIMER0_SYNC_SW_M (MCPWM_TIMER0_SYNC_SW_V << MCPWM_TIMER0_SYNC_SW_S) +#define MCPWM_TIMER0_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER0_SYNC_SW_S 1 +/** MCPWM_TIMER0_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer0 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER0_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_M (MCPWM_TIMER0_SYNCO_SEL_V << MCPWM_TIMER0_SYNCO_SEL_S) +#define MCPWM_TIMER0_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_S 2 +/** MCPWM_TIMER0_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER0_PHASE 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_M (MCPWM_TIMER0_PHASE_V << MCPWM_TIMER0_PHASE_S) +#define MCPWM_TIMER0_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_S 4 +/** MCPWM_TIMER0_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer0's direction at the time sync event occurs when timer0 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER0_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER0_PHASE_DIRECTION_M (MCPWM_TIMER0_PHASE_DIRECTION_V << MCPWM_TIMER0_PHASE_DIRECTION_S) +#define MCPWM_TIMER0_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x10) -/* MCPWM_TIMER0_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_DIRECTION (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_V 0x1 -#define MCPWM_TIMER0_DIRECTION_S 16 -/* MCPWM_TIMER0_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_VALUE 0x0000FFFF -#define MCPWM_TIMER0_VALUE_M ((MCPWM_TIMER0_VALUE_V)<<(MCPWM_TIMER0_VALUE_S)) -#define MCPWM_TIMER0_VALUE_V 0xFFFF +/** MCPWM_TIMER0_STATUS_REG register + * PWM timer0 status register. + */ +#define MCPWM_TIMER0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10) +/** MCPWM_TIMER0_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer0 counter value + */ +#define MCPWM_TIMER0_VALUE 0x0000FFFFU +#define MCPWM_TIMER0_VALUE_M (MCPWM_TIMER0_VALUE_V << MCPWM_TIMER0_VALUE_S) +#define MCPWM_TIMER0_VALUE_V 0x0000FFFFU #define MCPWM_TIMER0_VALUE_S 0 +/** MCPWM_TIMER0_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer0 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER0_DIRECTION (BIT(16)) +#define MCPWM_TIMER0_DIRECTION_M (MCPWM_TIMER0_DIRECTION_V << MCPWM_TIMER0_DIRECTION_S) +#define MCPWM_TIMER0_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_DIRECTION_S 16 -#define MCPWM_TIMER1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x14) -/* MCPWM_TIMER1_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_M ((MCPWM_TIMER1_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER1_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER1_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: .*/ -#define MCPWM_TIMER1_PERIOD 0x0000FFFF -#define MCPWM_TIMER1_PERIOD_M ((MCPWM_TIMER1_PERIOD_V)<<(MCPWM_TIMER1_PERIOD_S)) -#define MCPWM_TIMER1_PERIOD_V 0xFFFF -#define MCPWM_TIMER1_PERIOD_S 8 -/* MCPWM_TIMER1_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_PRESCALE 0x000000FF -#define MCPWM_TIMER1_PRESCALE_M ((MCPWM_TIMER1_PRESCALE_V)<<(MCPWM_TIMER1_PRESCALE_S)) -#define MCPWM_TIMER1_PRESCALE_V 0xFF +/** MCPWM_TIMER1_CFG0_REG register + * PWM timer1 period and update method configuration register. + */ +#define MCPWM_TIMER1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x14) +/** MCPWM_TIMER1_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT1_clk, takes effect when PWM timer1 stops and starts + * agsin. period of PT1_clk = Period of PWM_clk * (PWM_TIMER1_PRESCALE + 1) + */ +#define MCPWM_TIMER1_PRESCALE 0x000000FFU +#define MCPWM_TIMER1_PRESCALE_M (MCPWM_TIMER1_PRESCALE_V << MCPWM_TIMER1_PRESCALE_S) +#define MCPWM_TIMER1_PRESCALE_V 0x000000FFU #define MCPWM_TIMER1_PRESCALE_S 0 +/** MCPWM_TIMER1_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer1 + */ +#define MCPWM_TIMER1_PERIOD 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_M (MCPWM_TIMER1_PERIOD_V << MCPWM_TIMER1_PERIOD_S) +#define MCPWM_TIMER1_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_S 8 +/** MCPWM_TIMER1_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer1 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_M (MCPWM_TIMER1_PERIOD_UPMETHOD_V << MCPWM_TIMER1_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x18) -/* MCPWM_TIMER1_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: 0: freeze, 1: inc, 2: dec, 3: up-down.*/ -#define MCPWM_TIMER1_MOD 0x00000003 -#define MCPWM_TIMER1_MOD_M ((MCPWM_TIMER1_MOD_V)<<(MCPWM_TIMER1_MOD_S)) -#define MCPWM_TIMER1_MOD_V 0x3 -#define MCPWM_TIMER1_MOD_S 3 -/* MCPWM_TIMER1_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_START 0x00000007 -#define MCPWM_TIMER1_START_M ((MCPWM_TIMER1_START_V)<<(MCPWM_TIMER1_START_S)) -#define MCPWM_TIMER1_START_V 0x7 +/** MCPWM_TIMER1_CFG1_REG register + * PWM timer1 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x18) +/** MCPWM_TIMER1_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer1 start and stop control. 0: if PWM timer1 starts, then stops at TEZ, 1: + * if timer1 starts, then stops at TEP, 2: PWM timer1 starts and runs on, 3: timer1 + * starts and stops at the next TEZ, 4: timer1 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER1_START 0x00000007U +#define MCPWM_TIMER1_START_M (MCPWM_TIMER1_START_V << MCPWM_TIMER1_START_S) +#define MCPWM_TIMER1_START_V 0x00000007U #define MCPWM_TIMER1_START_S 0 +/** MCPWM_TIMER1_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer1 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER1_MOD 0x00000003U +#define MCPWM_TIMER1_MOD_M (MCPWM_TIMER1_MOD_V << MCPWM_TIMER1_MOD_S) +#define MCPWM_TIMER1_MOD_V 0x00000003U +#define MCPWM_TIMER1_MOD_S 3 -#define MCPWM_TIMER1_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x1C) -/* MCPWM_TIMER1_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_PHASE 0x0001FFFF -#define MCPWM_TIMER1_PHASE_M ((MCPWM_TIMER1_PHASE_V)<<(MCPWM_TIMER1_PHASE_S)) -#define MCPWM_TIMER1_PHASE_V 0x1FFFF -#define MCPWM_TIMER1_PHASE_S 4 -/* MCPWM_TIMER1_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: 0: synci, 1: tez, 2: tep, else 0.*/ -#define MCPWM_TIMER1_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER1_SYNCO_SEL_M ((MCPWM_TIMER1_SYNCO_SEL_V)<<(MCPWM_TIMER1_SYNCO_SEL_S)) -#define MCPWM_TIMER1_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER1_SYNCO_SEL_S 2 -/* MCPWM_TIMER1_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: write the negate value will trigger a sw sync.*/ -#define MCPWM_TIMER1_SYNC_SW (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_V 0x1 -#define MCPWM_TIMER1_SYNC_SW_S 1 -/* MCPWM_TIMER1_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_TIMER1_SYNC_REG register + * PWM timer1 sync function configuration register. + */ +#define MCPWM_TIMER1_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x1c) +/** MCPWM_TIMER1_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ #define MCPWM_TIMER1_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_V 0x1 +#define MCPWM_TIMER1_SYNCI_EN_M (MCPWM_TIMER1_SYNCI_EN_V << MCPWM_TIMER1_SYNCI_EN_S) +#define MCPWM_TIMER1_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER1_SYNCI_EN_S 0 +/** MCPWM_TIMER1_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER1_SYNC_SW (BIT(1)) +#define MCPWM_TIMER1_SYNC_SW_M (MCPWM_TIMER1_SYNC_SW_V << MCPWM_TIMER1_SYNC_SW_S) +#define MCPWM_TIMER1_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER1_SYNC_SW_S 1 +/** MCPWM_TIMER1_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer1 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer1_sync_sw bit + */ +#define MCPWM_TIMER1_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_M (MCPWM_TIMER1_SYNCO_SEL_V << MCPWM_TIMER1_SYNCO_SEL_S) +#define MCPWM_TIMER1_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_S 2 +/** MCPWM_TIMER1_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER1_PHASE 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_M (MCPWM_TIMER1_PHASE_V << MCPWM_TIMER1_PHASE_S) +#define MCPWM_TIMER1_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_S 4 +/** MCPWM_TIMER1_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer1's direction at the time sync event occurs when timer1 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER1_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER1_PHASE_DIRECTION_M (MCPWM_TIMER1_PHASE_DIRECTION_V << MCPWM_TIMER1_PHASE_DIRECTION_S) +#define MCPWM_TIMER1_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x20) -/* MCPWM_TIMER1_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_DIRECTION (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_V 0x1 -#define MCPWM_TIMER1_DIRECTION_S 16 -/* MCPWM_TIMER1_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_VALUE 0x0000FFFF -#define MCPWM_TIMER1_VALUE_M ((MCPWM_TIMER1_VALUE_V)<<(MCPWM_TIMER1_VALUE_S)) -#define MCPWM_TIMER1_VALUE_V 0xFFFF +/** MCPWM_TIMER1_STATUS_REG register + * PWM timer1 status register. + */ +#define MCPWM_TIMER1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x20) +/** MCPWM_TIMER1_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer1 counter value + */ +#define MCPWM_TIMER1_VALUE 0x0000FFFFU +#define MCPWM_TIMER1_VALUE_M (MCPWM_TIMER1_VALUE_V << MCPWM_TIMER1_VALUE_S) +#define MCPWM_TIMER1_VALUE_V 0x0000FFFFU #define MCPWM_TIMER1_VALUE_S 0 +/** MCPWM_TIMER1_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer1 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER1_DIRECTION (BIT(16)) +#define MCPWM_TIMER1_DIRECTION_M (MCPWM_TIMER1_DIRECTION_V << MCPWM_TIMER1_DIRECTION_S) +#define MCPWM_TIMER1_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_DIRECTION_S 16 -#define MCPWM_TIMER2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x24) -/* MCPWM_TIMER2_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_M ((MCPWM_TIMER2_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER2_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER2_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: .*/ -#define MCPWM_TIMER2_PERIOD 0x0000FFFF -#define MCPWM_TIMER2_PERIOD_M ((MCPWM_TIMER2_PERIOD_V)<<(MCPWM_TIMER2_PERIOD_S)) -#define MCPWM_TIMER2_PERIOD_V 0xFFFF -#define MCPWM_TIMER2_PERIOD_S 8 -/* MCPWM_TIMER2_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_PRESCALE 0x000000FF -#define MCPWM_TIMER2_PRESCALE_M ((MCPWM_TIMER2_PRESCALE_V)<<(MCPWM_TIMER2_PRESCALE_S)) -#define MCPWM_TIMER2_PRESCALE_V 0xFF +/** MCPWM_TIMER2_CFG0_REG register + * PWM timer2 period and update method configuration register. + */ +#define MCPWM_TIMER2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x24) +/** MCPWM_TIMER2_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT2_clk, takes effect when PWM timer2 stops and starts + * agsin. period of PT2_clk = Period of PWM_clk * (PWM_TIMER2_PRESCALE + 1) + */ +#define MCPWM_TIMER2_PRESCALE 0x000000FFU +#define MCPWM_TIMER2_PRESCALE_M (MCPWM_TIMER2_PRESCALE_V << MCPWM_TIMER2_PRESCALE_S) +#define MCPWM_TIMER2_PRESCALE_V 0x000000FFU #define MCPWM_TIMER2_PRESCALE_S 0 +/** MCPWM_TIMER2_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer2 + */ +#define MCPWM_TIMER2_PERIOD 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_M (MCPWM_TIMER2_PERIOD_V << MCPWM_TIMER2_PERIOD_S) +#define MCPWM_TIMER2_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_S 8 +/** MCPWM_TIMER2_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer2 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_M (MCPWM_TIMER2_PERIOD_UPMETHOD_V << MCPWM_TIMER2_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x28) -/* MCPWM_TIMER2_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_MOD 0x00000003 -#define MCPWM_TIMER2_MOD_M ((MCPWM_TIMER2_MOD_V)<<(MCPWM_TIMER2_MOD_S)) -#define MCPWM_TIMER2_MOD_V 0x3 -#define MCPWM_TIMER2_MOD_S 3 -/* MCPWM_TIMER2_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_START 0x00000007 -#define MCPWM_TIMER2_START_M ((MCPWM_TIMER2_START_V)<<(MCPWM_TIMER2_START_S)) -#define MCPWM_TIMER2_START_V 0x7 +/** MCPWM_TIMER2_CFG1_REG register + * PWM timer2 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x28) +/** MCPWM_TIMER2_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer2 start and stop control. 0: if PWM timer2 starts, then stops at TEZ, 1: + * if timer2 starts, then stops at TEP, 2: PWM timer2 starts and runs on, 3: timer2 + * starts and stops at the next TEZ, 4: timer2 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER2_START 0x00000007U +#define MCPWM_TIMER2_START_M (MCPWM_TIMER2_START_V << MCPWM_TIMER2_START_S) +#define MCPWM_TIMER2_START_V 0x00000007U #define MCPWM_TIMER2_START_S 0 +/** MCPWM_TIMER2_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer2 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER2_MOD 0x00000003U +#define MCPWM_TIMER2_MOD_M (MCPWM_TIMER2_MOD_V << MCPWM_TIMER2_MOD_S) +#define MCPWM_TIMER2_MOD_V 0x00000003U +#define MCPWM_TIMER2_MOD_S 3 -#define MCPWM_TIMER2_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x2C) -/* MCPWM_TIMER2_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_PHASE 0x0001FFFF -#define MCPWM_TIMER2_PHASE_M ((MCPWM_TIMER2_PHASE_V)<<(MCPWM_TIMER2_PHASE_S)) -#define MCPWM_TIMER2_PHASE_V 0x1FFFF -#define MCPWM_TIMER2_PHASE_S 4 -/* MCPWM_TIMER2_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER2_SYNCO_SEL_M ((MCPWM_TIMER2_SYNCO_SEL_V)<<(MCPWM_TIMER2_SYNCO_SEL_S)) -#define MCPWM_TIMER2_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER2_SYNCO_SEL_S 2 -/* MCPWM_TIMER2_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: write the negate value will trigger a sw sync.*/ -#define MCPWM_TIMER2_SYNC_SW (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_V 0x1 -#define MCPWM_TIMER2_SYNC_SW_S 1 -/* MCPWM_TIMER2_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_TIMER2_SYNC_REG register + * PWM timer2 sync function configuration register. + */ +#define MCPWM_TIMER2_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x2c) +/** MCPWM_TIMER2_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ #define MCPWM_TIMER2_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_V 0x1 +#define MCPWM_TIMER2_SYNCI_EN_M (MCPWM_TIMER2_SYNCI_EN_V << MCPWM_TIMER2_SYNCI_EN_S) +#define MCPWM_TIMER2_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER2_SYNCI_EN_S 0 +/** MCPWM_TIMER2_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER2_SYNC_SW (BIT(1)) +#define MCPWM_TIMER2_SYNC_SW_M (MCPWM_TIMER2_SYNC_SW_V << MCPWM_TIMER2_SYNC_SW_S) +#define MCPWM_TIMER2_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER2_SYNC_SW_S 1 +/** MCPWM_TIMER2_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer2 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER2_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_M (MCPWM_TIMER2_SYNCO_SEL_V << MCPWM_TIMER2_SYNCO_SEL_S) +#define MCPWM_TIMER2_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_S 2 +/** MCPWM_TIMER2_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER2_PHASE 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_M (MCPWM_TIMER2_PHASE_V << MCPWM_TIMER2_PHASE_S) +#define MCPWM_TIMER2_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_S 4 +/** MCPWM_TIMER2_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer2's direction at the time sync event occurs when timer2 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER2_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER2_PHASE_DIRECTION_M (MCPWM_TIMER2_PHASE_DIRECTION_V << MCPWM_TIMER2_PHASE_DIRECTION_S) +#define MCPWM_TIMER2_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x30) -/* MCPWM_TIMER2_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_DIRECTION (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_V 0x1 -#define MCPWM_TIMER2_DIRECTION_S 16 -/* MCPWM_TIMER2_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_VALUE 0x0000FFFF -#define MCPWM_TIMER2_VALUE_M ((MCPWM_TIMER2_VALUE_V)<<(MCPWM_TIMER2_VALUE_S)) -#define MCPWM_TIMER2_VALUE_V 0xFFFF +/** MCPWM_TIMER2_STATUS_REG register + * PWM timer2 status register. + */ +#define MCPWM_TIMER2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x30) +/** MCPWM_TIMER2_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer2 counter value + */ +#define MCPWM_TIMER2_VALUE 0x0000FFFFU +#define MCPWM_TIMER2_VALUE_M (MCPWM_TIMER2_VALUE_V << MCPWM_TIMER2_VALUE_S) +#define MCPWM_TIMER2_VALUE_V 0x0000FFFFU #define MCPWM_TIMER2_VALUE_S 0 +/** MCPWM_TIMER2_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer2 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER2_DIRECTION (BIT(16)) +#define MCPWM_TIMER2_DIRECTION_M (MCPWM_TIMER2_DIRECTION_V << MCPWM_TIMER2_DIRECTION_S) +#define MCPWM_TIMER2_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_DIRECTION_S 16 -#define MCPWM_TIMER_SYNCI_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x34) -/* MCPWM_EXTERNAL_SYNCI2_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -/* MCPWM_EXTERNAL_SYNCI1_INVERT : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 -/* MCPWM_EXTERNAL_SYNCI0_INVERT : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 -/* MCPWM_TIMER2_SYNCISEL : R/W ;bitpos:[8:6] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_SYNCISEL 0x00000007 -#define MCPWM_TIMER2_SYNCISEL_M ((MCPWM_TIMER2_SYNCISEL_V)<<(MCPWM_TIMER2_SYNCISEL_S)) -#define MCPWM_TIMER2_SYNCISEL_V 0x7 -#define MCPWM_TIMER2_SYNCISEL_S 6 -/* MCPWM_TIMER1_SYNCISEL : R/W ;bitpos:[5:3] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_SYNCISEL 0x00000007 -#define MCPWM_TIMER1_SYNCISEL_M ((MCPWM_TIMER1_SYNCISEL_V)<<(MCPWM_TIMER1_SYNCISEL_S)) -#define MCPWM_TIMER1_SYNCISEL_V 0x7 -#define MCPWM_TIMER1_SYNCISEL_S 3 -/* MCPWM_TIMER0_SYNCISEL : R/W ;bitpos:[2:0] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_SYNCISEL 0x00000007 -#define MCPWM_TIMER0_SYNCISEL_M ((MCPWM_TIMER0_SYNCISEL_V)<<(MCPWM_TIMER0_SYNCISEL_S)) -#define MCPWM_TIMER0_SYNCISEL_V 0x7 +/** MCPWM_TIMER_SYNCI_CFG_REG register + * Synchronization input selection for three PWM timers. + */ +#define MCPWM_TIMER_SYNCI_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x34) +/** MCPWM_TIMER0_SYNCISEL : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER0_SYNCISEL 0x00000007U +#define MCPWM_TIMER0_SYNCISEL_M (MCPWM_TIMER0_SYNCISEL_V << MCPWM_TIMER0_SYNCISEL_S) +#define MCPWM_TIMER0_SYNCISEL_V 0x00000007U #define MCPWM_TIMER0_SYNCISEL_S 0 +/** MCPWM_TIMER1_SYNCISEL : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER1_SYNCISEL 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_M (MCPWM_TIMER1_SYNCISEL_V << MCPWM_TIMER1_SYNCISEL_S) +#define MCPWM_TIMER1_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_S 3 +/** MCPWM_TIMER2_SYNCISEL : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER2_SYNCISEL 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_M (MCPWM_TIMER2_SYNCISEL_V << MCPWM_TIMER2_SYNCISEL_S) +#define MCPWM_TIMER2_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_S 6 +/** MCPWM_EXTERNAL_SYNCI0_INVERT : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (MCPWM_EXTERNAL_SYNCI0_INVERT_V << MCPWM_EXTERNAL_SYNCI0_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 +/** MCPWM_EXTERNAL_SYNCI1_INVERT : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (MCPWM_EXTERNAL_SYNCI1_INVERT_V << MCPWM_EXTERNAL_SYNCI1_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 +/** MCPWM_EXTERNAL_SYNCI2_INVERT : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (MCPWM_EXTERNAL_SYNCI2_INVERT_V << MCPWM_EXTERNAL_SYNCI2_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -#define MCPWM_OPERATOR_TIMERSEL_REG(i) (REG_MCPWM_BASE(i) + 0x38) -/* MCPWM_OPERATOR2_TIMERSEL : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: 0: timer0, 1: timer1, 2: timer2.*/ -#define MCPWM_OPERATOR2_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR2_TIMERSEL_M ((MCPWM_OPERATOR2_TIMERSEL_V)<<(MCPWM_OPERATOR2_TIMERSEL_S)) -#define MCPWM_OPERATOR2_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR2_TIMERSEL_S 4 -/* MCPWM_OPERATOR1_TIMERSEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: 0: timer0, 1: timer1, 2: timer2.*/ -#define MCPWM_OPERATOR1_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR1_TIMERSEL_M ((MCPWM_OPERATOR1_TIMERSEL_V)<<(MCPWM_OPERATOR1_TIMERSEL_S)) -#define MCPWM_OPERATOR1_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR1_TIMERSEL_S 2 -/* MCPWM_OPERATOR0_TIMERSEL : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: 0: timer0, 1: timer1, 2: timer2.*/ -#define MCPWM_OPERATOR0_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR0_TIMERSEL_M ((MCPWM_OPERATOR0_TIMERSEL_V)<<(MCPWM_OPERATOR0_TIMERSEL_S)) -#define MCPWM_OPERATOR0_TIMERSEL_V 0x3 +/** MCPWM_OPERATOR_TIMERSEL_REG register + * Select specific timer for PWM operators. + */ +#define MCPWM_OPERATOR_TIMERSEL_REG(i) (DR_REG_MCPWM_BASE(i) + 0x38) +/** MCPWM_OPERATOR0_TIMERSEL : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR0_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR0_TIMERSEL_M (MCPWM_OPERATOR0_TIMERSEL_V << MCPWM_OPERATOR0_TIMERSEL_S) +#define MCPWM_OPERATOR0_TIMERSEL_V 0x00000003U #define MCPWM_OPERATOR0_TIMERSEL_S 0 +/** MCPWM_OPERATOR1_TIMERSEL : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR1_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_M (MCPWM_OPERATOR1_TIMERSEL_V << MCPWM_OPERATOR1_TIMERSEL_S) +#define MCPWM_OPERATOR1_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_S 2 +/** MCPWM_OPERATOR2_TIMERSEL : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR2_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_M (MCPWM_OPERATOR2_TIMERSEL_V << MCPWM_OPERATOR2_TIMERSEL_S) +#define MCPWM_OPERATOR2_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_S 4 -#define MCPWM_CMPR0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x3C) -/* MCPWM_CMPR0_B_SHDW_FULL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_B_SHDW_FULL (BIT(9)) -#define MCPWM_CMPR0_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_CMPR0_B_SHDW_FULL_V 0x1 -#define MCPWM_CMPR0_B_SHDW_FULL_S 9 -/* MCPWM_CMPR0_A_SHDW_FULL : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_A_SHDW_FULL (BIT(8)) -#define MCPWM_CMPR0_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_CMPR0_A_SHDW_FULL_V 0x1 -#define MCPWM_CMPR0_A_SHDW_FULL_S 8 -/* MCPWM_CMPR0_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR0_B_UPMETHOD 0x0000000F -#define MCPWM_CMPR0_B_UPMETHOD_M ((MCPWM_CMPR0_B_UPMETHOD_V)<<(MCPWM_CMPR0_B_UPMETHOD_S)) -#define MCPWM_CMPR0_B_UPMETHOD_V 0xF -#define MCPWM_CMPR0_B_UPMETHOD_S 4 -/* MCPWM_CMPR0_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR0_A_UPMETHOD 0x0000000F -#define MCPWM_CMPR0_A_UPMETHOD_M ((MCPWM_CMPR0_A_UPMETHOD_V)<<(MCPWM_CMPR0_A_UPMETHOD_S)) -#define MCPWM_CMPR0_A_UPMETHOD_V 0xF -#define MCPWM_CMPR0_A_UPMETHOD_S 0 +/** MCPWM_GEN0_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN0_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x3c) +/** MCPWM_GEN0_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_A_UPMETHOD_M (MCPWM_GEN0_A_UPMETHOD_V << MCPWM_GEN0_A_UPMETHOD_S) +#define MCPWM_GEN0_A_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN0_A_UPMETHOD_S 0 +/** MCPWM_GEN0_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 0 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_M (MCPWM_GEN0_B_UPMETHOD_V << MCPWM_GEN0_B_UPMETHOD_S) +#define MCPWM_GEN0_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_S 4 +/** MCPWM_GEN0_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN0_A_SHDW_FULL_M (MCPWM_GEN0_A_SHDW_FULL_V << MCPWM_GEN0_A_SHDW_FULL_S) +#define MCPWM_GEN0_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_A_SHDW_FULL_S 8 +/** MCPWM_GEN0_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN0_B_SHDW_FULL_M (MCPWM_GEN0_B_SHDW_FULL_V << MCPWM_GEN0_B_SHDW_FULL_S) +#define MCPWM_GEN0_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_B_SHDW_FULL_S 9 -#define MCPWM_CMPR0_VALUE0_REG(i) (REG_MCPWM_BASE(i) + 0x40) -/* MCPWM_CMPR0_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_A 0x0000FFFF -#define MCPWM_CMPR0_A_M ((MCPWM_CMPR0_A_V)<<(MCPWM_CMPR0_A_S)) -#define MCPWM_CMPR0_A_V 0xFFFF -#define MCPWM_CMPR0_A_S 0 +/** MCPWM_GEN0_TSTMP_A_REG register + * PWM generator 0 shadow register for timer stamp A. + */ +#define MCPWM_GEN0_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x40) +/** MCPWM_GEN0_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp A's shadow register + */ +#define MCPWM_GEN0_A 0x0000FFFFU +#define MCPWM_GEN0_A_M (MCPWM_GEN0_A_V << MCPWM_GEN0_A_S) +#define MCPWM_GEN0_A_V 0x0000FFFFU +#define MCPWM_GEN0_A_S 0 -#define MCPWM_CMPR0_VALUE1_REG(i) (REG_MCPWM_BASE(i) + 0x44) -/* MCPWM_CMPR0_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_B 0x0000FFFF -#define MCPWM_CMPR0_B_M ((MCPWM_CMPR0_B_V)<<(MCPWM_CMPR0_B_S)) -#define MCPWM_CMPR0_B_V 0xFFFF -#define MCPWM_CMPR0_B_S 0 +/** MCPWM_GEN0_TSTMP_B_REG register + * PWM generator 0 shadow register for timer stamp B. + */ +#define MCPWM_GEN0_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x44) +/** MCPWM_GEN0_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp B's shadow register + */ +#define MCPWM_GEN0_B 0x0000FFFFU +#define MCPWM_GEN0_B_M (MCPWM_GEN0_B_V << MCPWM_GEN0_B_S) +#define MCPWM_GEN0_B_V 0x0000FFFFU +#define MCPWM_GEN0_B_S 0 -#define MCPWM_GEN0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x48) -/* MCPWM_GEN0_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN0_T1_SEL 0x00000007 -#define MCPWM_GEN0_T1_SEL_M ((MCPWM_GEN0_T1_SEL_V)<<(MCPWM_GEN0_T1_SEL_S)) -#define MCPWM_GEN0_T1_SEL_V 0x7 -#define MCPWM_GEN0_T1_SEL_S 7 -/* MCPWM_GEN0_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN0_T0_SEL 0x00000007 -#define MCPWM_GEN0_T0_SEL_M ((MCPWM_GEN0_T0_SEL_V)<<(MCPWM_GEN0_T0_SEL_S)) -#define MCPWM_GEN0_T0_SEL_V 0x7 -#define MCPWM_GEN0_T0_SEL_S 4 -/* MCPWM_GEN0_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze.*/ -#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN0_CFG_UPMETHOD_M ((MCPWM_GEN0_CFG_UPMETHOD_V)<<(MCPWM_GEN0_CFG_UPMETHOD_S)) -#define MCPWM_GEN0_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN0_CFG0_REG register + * PWM generator 0 event T0 and T1 handling + */ +#define MCPWM_GEN0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x48) +/** MCPWM_GEN0_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ +#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_CFG_UPMETHOD_M (MCPWM_GEN0_CFG_UPMETHOD_V << MCPWM_GEN0_CFG_UPMETHOD_S) +#define MCPWM_GEN0_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN0_CFG_UPMETHOD_S 0 +/** MCPWM_GEN0_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 0 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T0_SEL 0x00000007U +#define MCPWM_GEN0_T0_SEL_M (MCPWM_GEN0_T0_SEL_V << MCPWM_GEN0_T0_SEL_S) +#define MCPWM_GEN0_T0_SEL_V 0x00000007U +#define MCPWM_GEN0_T0_SEL_S 4 +/** MCPWM_GEN0_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 0 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T1_SEL 0x00000007U +#define MCPWM_GEN0_T1_SEL_M (MCPWM_GEN0_T1_SEL_V << MCPWM_GEN0_T1_SEL_S) +#define MCPWM_GEN0_T1_SEL_V 0x00000007U +#define MCPWM_GEN0_T1_SEL_S 7 -#define MCPWM_GEN0_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x4C) -/* MCPWM_GEN0_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_NCIFORCE_MODE_M ((MCPWM_GEN0_B_NCIFORCE_MODE_V)<<(MCPWM_GEN0_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN0_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_V 0x1 -#define MCPWM_GEN0_B_NCIFORCE_S 13 -/* MCPWM_GEN0_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_NCIFORCE_MODE_M ((MCPWM_GEN0_A_NCIFORCE_MODE_V)<<(MCPWM_GEN0_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN0_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_V 0x1 -#define MCPWM_GEN0_A_NCIFORCE_S 10 -/* MCPWM_GEN0_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_M ((MCPWM_GEN0_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN0_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_M ((MCPWM_GEN0_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: free -ze.*/ -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN0_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN0_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN0_FORCE_REG register + * Permissives to force PWM0A and PWM0B outputs by software + */ +#define MCPWM_GEN0_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4c) +/** MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M (MCPWM_GEN0_CNTUFORCE_UPMETHOD_V << MCPWM_GEN0_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN0_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN0_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_M (MCPWM_GEN0_A_CNTUFORCE_MODE_V << MCPWM_GEN0_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN0_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_M (MCPWM_GEN0_B_CNTUFORCE_MODE_V << MCPWM_GEN0_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN0_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN0_A_NCIFORCE_M (MCPWM_GEN0_A_NCIFORCE_V << MCPWM_GEN0_A_NCIFORCE_S) +#define MCPWM_GEN0_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_A_NCIFORCE_S 10 +/** MCPWM_GEN0_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_M (MCPWM_GEN0_A_NCIFORCE_MODE_V << MCPWM_GEN0_A_NCIFORCE_MODE_S) +#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN0_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN0_B_NCIFORCE_M (MCPWM_GEN0_B_NCIFORCE_V << MCPWM_GEN0_B_NCIFORCE_S) +#define MCPWM_GEN0_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_B_NCIFORCE_S 13 +/** MCPWM_GEN0_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_M (MCPWM_GEN0_B_NCIFORCE_MODE_V << MCPWM_GEN0_B_NCIFORCE_MODE_S) +#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN0_A_REG(i) (REG_MCPWM_BASE(i) + 0x50) -/* MCPWM_GEN0_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: no change, 1: low, 2: high, 3: toggle.*/ -#define MCPWM_GEN0_A_DT1 0x00000003 -#define MCPWM_GEN0_A_DT1_M ((MCPWM_GEN0_A_DT1_V)<<(MCPWM_GEN0_A_DT1_S)) -#define MCPWM_GEN0_A_DT1_V 0x3 -#define MCPWM_GEN0_A_DT1_S 22 -/* MCPWM_GEN0_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DT0 0x00000003 -#define MCPWM_GEN0_A_DT0_M ((MCPWM_GEN0_A_DT0_V)<<(MCPWM_GEN0_A_DT0_S)) -#define MCPWM_GEN0_A_DT0_V 0x3 -#define MCPWM_GEN0_A_DT0_S 20 -/* MCPWM_GEN0_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEB 0x00000003 -#define MCPWM_GEN0_A_DTEB_M ((MCPWM_GEN0_A_DTEB_V)<<(MCPWM_GEN0_A_DTEB_S)) -#define MCPWM_GEN0_A_DTEB_V 0x3 -#define MCPWM_GEN0_A_DTEB_S 18 -/* MCPWM_GEN0_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEA 0x00000003 -#define MCPWM_GEN0_A_DTEA_M ((MCPWM_GEN0_A_DTEA_V)<<(MCPWM_GEN0_A_DTEA_S)) -#define MCPWM_GEN0_A_DTEA_V 0x3 -#define MCPWM_GEN0_A_DTEA_S 16 -/* MCPWM_GEN0_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEP 0x00000003 -#define MCPWM_GEN0_A_DTEP_M ((MCPWM_GEN0_A_DTEP_V)<<(MCPWM_GEN0_A_DTEP_S)) -#define MCPWM_GEN0_A_DTEP_V 0x3 -#define MCPWM_GEN0_A_DTEP_S 14 -/* MCPWM_GEN0_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEZ 0x00000003 -#define MCPWM_GEN0_A_DTEZ_M ((MCPWM_GEN0_A_DTEZ_V)<<(MCPWM_GEN0_A_DTEZ_S)) -#define MCPWM_GEN0_A_DTEZ_V 0x3 -#define MCPWM_GEN0_A_DTEZ_S 12 -/* MCPWM_GEN0_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UT1 0x00000003 -#define MCPWM_GEN0_A_UT1_M ((MCPWM_GEN0_A_UT1_V)<<(MCPWM_GEN0_A_UT1_S)) -#define MCPWM_GEN0_A_UT1_V 0x3 -#define MCPWM_GEN0_A_UT1_S 10 -/* MCPWM_GEN0_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UT0 0x00000003 -#define MCPWM_GEN0_A_UT0_M ((MCPWM_GEN0_A_UT0_V)<<(MCPWM_GEN0_A_UT0_S)) -#define MCPWM_GEN0_A_UT0_V 0x3 -#define MCPWM_GEN0_A_UT0_S 8 -/* MCPWM_GEN0_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEB 0x00000003 -#define MCPWM_GEN0_A_UTEB_M ((MCPWM_GEN0_A_UTEB_V)<<(MCPWM_GEN0_A_UTEB_S)) -#define MCPWM_GEN0_A_UTEB_V 0x3 -#define MCPWM_GEN0_A_UTEB_S 6 -/* MCPWM_GEN0_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEA 0x00000003 -#define MCPWM_GEN0_A_UTEA_M ((MCPWM_GEN0_A_UTEA_V)<<(MCPWM_GEN0_A_UTEA_S)) -#define MCPWM_GEN0_A_UTEA_V 0x3 -#define MCPWM_GEN0_A_UTEA_S 4 -/* MCPWM_GEN0_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEP 0x00000003 -#define MCPWM_GEN0_A_UTEP_M ((MCPWM_GEN0_A_UTEP_V)<<(MCPWM_GEN0_A_UTEP_S)) -#define MCPWM_GEN0_A_UTEP_V 0x3 -#define MCPWM_GEN0_A_UTEP_S 2 -/* MCPWM_GEN0_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEZ 0x00000003 -#define MCPWM_GEN0_A_UTEZ_M ((MCPWM_GEN0_A_UTEZ_V)<<(MCPWM_GEN0_A_UTEZ_S)) -#define MCPWM_GEN0_A_UTEZ_V 0x3 +/** MCPWM_GEN0_A_REG register + * Actions triggered by events on PWM0A + */ +#define MCPWM_GEN0_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x50) +/** MCPWM_GEN0_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEZ 0x00000003U +#define MCPWM_GEN0_A_UTEZ_M (MCPWM_GEN0_A_UTEZ_V << MCPWM_GEN0_A_UTEZ_S) +#define MCPWM_GEN0_A_UTEZ_V 0x00000003U #define MCPWM_GEN0_A_UTEZ_S 0 +/** MCPWM_GEN0_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEP 0x00000003U +#define MCPWM_GEN0_A_UTEP_M (MCPWM_GEN0_A_UTEP_V << MCPWM_GEN0_A_UTEP_S) +#define MCPWM_GEN0_A_UTEP_V 0x00000003U +#define MCPWM_GEN0_A_UTEP_S 2 +/** MCPWM_GEN0_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEA 0x00000003U +#define MCPWM_GEN0_A_UTEA_M (MCPWM_GEN0_A_UTEA_V << MCPWM_GEN0_A_UTEA_S) +#define MCPWM_GEN0_A_UTEA_V 0x00000003U +#define MCPWM_GEN0_A_UTEA_S 4 +/** MCPWM_GEN0_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEB 0x00000003U +#define MCPWM_GEN0_A_UTEB_M (MCPWM_GEN0_A_UTEB_V << MCPWM_GEN0_A_UTEB_S) +#define MCPWM_GEN0_A_UTEB_V 0x00000003U +#define MCPWM_GEN0_A_UTEB_S 6 +/** MCPWM_GEN0_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT0 0x00000003U +#define MCPWM_GEN0_A_UT0_M (MCPWM_GEN0_A_UT0_V << MCPWM_GEN0_A_UT0_S) +#define MCPWM_GEN0_A_UT0_V 0x00000003U +#define MCPWM_GEN0_A_UT0_S 8 +/** MCPWM_GEN0_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT1 0x00000003U +#define MCPWM_GEN0_A_UT1_M (MCPWM_GEN0_A_UT1_V << MCPWM_GEN0_A_UT1_S) +#define MCPWM_GEN0_A_UT1_V 0x00000003U +#define MCPWM_GEN0_A_UT1_S 10 +/** MCPWM_GEN0_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEZ 0x00000003U +#define MCPWM_GEN0_A_DTEZ_M (MCPWM_GEN0_A_DTEZ_V << MCPWM_GEN0_A_DTEZ_S) +#define MCPWM_GEN0_A_DTEZ_V 0x00000003U +#define MCPWM_GEN0_A_DTEZ_S 12 +/** MCPWM_GEN0_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEP 0x00000003U +#define MCPWM_GEN0_A_DTEP_M (MCPWM_GEN0_A_DTEP_V << MCPWM_GEN0_A_DTEP_S) +#define MCPWM_GEN0_A_DTEP_V 0x00000003U +#define MCPWM_GEN0_A_DTEP_S 14 +/** MCPWM_GEN0_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEA 0x00000003U +#define MCPWM_GEN0_A_DTEA_M (MCPWM_GEN0_A_DTEA_V << MCPWM_GEN0_A_DTEA_S) +#define MCPWM_GEN0_A_DTEA_V 0x00000003U +#define MCPWM_GEN0_A_DTEA_S 16 +/** MCPWM_GEN0_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEB 0x00000003U +#define MCPWM_GEN0_A_DTEB_M (MCPWM_GEN0_A_DTEB_V << MCPWM_GEN0_A_DTEB_S) +#define MCPWM_GEN0_A_DTEB_V 0x00000003U +#define MCPWM_GEN0_A_DTEB_S 18 +/** MCPWM_GEN0_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT0 0x00000003U +#define MCPWM_GEN0_A_DT0_M (MCPWM_GEN0_A_DT0_V << MCPWM_GEN0_A_DT0_S) +#define MCPWM_GEN0_A_DT0_V 0x00000003U +#define MCPWM_GEN0_A_DT0_S 20 +/** MCPWM_GEN0_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT1 0x00000003U +#define MCPWM_GEN0_A_DT1_M (MCPWM_GEN0_A_DT1_V << MCPWM_GEN0_A_DT1_S) +#define MCPWM_GEN0_A_DT1_V 0x00000003U +#define MCPWM_GEN0_A_DT1_S 22 -#define MCPWM_GEN0_B_REG(i) (REG_MCPWM_BASE(i) + 0x54) -/* MCPWM_GEN0_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DT1 0x00000003 -#define MCPWM_GEN0_B_DT1_M ((MCPWM_GEN0_B_DT1_V)<<(MCPWM_GEN0_B_DT1_S)) -#define MCPWM_GEN0_B_DT1_V 0x3 -#define MCPWM_GEN0_B_DT1_S 22 -/* MCPWM_GEN0_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DT0 0x00000003 -#define MCPWM_GEN0_B_DT0_M ((MCPWM_GEN0_B_DT0_V)<<(MCPWM_GEN0_B_DT0_S)) -#define MCPWM_GEN0_B_DT0_V 0x3 -#define MCPWM_GEN0_B_DT0_S 20 -/* MCPWM_GEN0_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEB 0x00000003 -#define MCPWM_GEN0_B_DTEB_M ((MCPWM_GEN0_B_DTEB_V)<<(MCPWM_GEN0_B_DTEB_S)) -#define MCPWM_GEN0_B_DTEB_V 0x3 -#define MCPWM_GEN0_B_DTEB_S 18 -/* MCPWM_GEN0_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEA 0x00000003 -#define MCPWM_GEN0_B_DTEA_M ((MCPWM_GEN0_B_DTEA_V)<<(MCPWM_GEN0_B_DTEA_S)) -#define MCPWM_GEN0_B_DTEA_V 0x3 -#define MCPWM_GEN0_B_DTEA_S 16 -/* MCPWM_GEN0_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEP 0x00000003 -#define MCPWM_GEN0_B_DTEP_M ((MCPWM_GEN0_B_DTEP_V)<<(MCPWM_GEN0_B_DTEP_S)) -#define MCPWM_GEN0_B_DTEP_V 0x3 -#define MCPWM_GEN0_B_DTEP_S 14 -/* MCPWM_GEN0_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEZ 0x00000003 -#define MCPWM_GEN0_B_DTEZ_M ((MCPWM_GEN0_B_DTEZ_V)<<(MCPWM_GEN0_B_DTEZ_S)) -#define MCPWM_GEN0_B_DTEZ_V 0x3 -#define MCPWM_GEN0_B_DTEZ_S 12 -/* MCPWM_GEN0_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UT1 0x00000003 -#define MCPWM_GEN0_B_UT1_M ((MCPWM_GEN0_B_UT1_V)<<(MCPWM_GEN0_B_UT1_S)) -#define MCPWM_GEN0_B_UT1_V 0x3 -#define MCPWM_GEN0_B_UT1_S 10 -/* MCPWM_GEN0_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UT0 0x00000003 -#define MCPWM_GEN0_B_UT0_M ((MCPWM_GEN0_B_UT0_V)<<(MCPWM_GEN0_B_UT0_S)) -#define MCPWM_GEN0_B_UT0_V 0x3 -#define MCPWM_GEN0_B_UT0_S 8 -/* MCPWM_GEN0_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEB 0x00000003 -#define MCPWM_GEN0_B_UTEB_M ((MCPWM_GEN0_B_UTEB_V)<<(MCPWM_GEN0_B_UTEB_S)) -#define MCPWM_GEN0_B_UTEB_V 0x3 -#define MCPWM_GEN0_B_UTEB_S 6 -/* MCPWM_GEN0_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEA 0x00000003 -#define MCPWM_GEN0_B_UTEA_M ((MCPWM_GEN0_B_UTEA_V)<<(MCPWM_GEN0_B_UTEA_S)) -#define MCPWM_GEN0_B_UTEA_V 0x3 -#define MCPWM_GEN0_B_UTEA_S 4 -/* MCPWM_GEN0_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEP 0x00000003 -#define MCPWM_GEN0_B_UTEP_M ((MCPWM_GEN0_B_UTEP_V)<<(MCPWM_GEN0_B_UTEP_S)) -#define MCPWM_GEN0_B_UTEP_V 0x3 -#define MCPWM_GEN0_B_UTEP_S 2 -/* MCPWM_GEN0_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEZ 0x00000003 -#define MCPWM_GEN0_B_UTEZ_M ((MCPWM_GEN0_B_UTEZ_V)<<(MCPWM_GEN0_B_UTEZ_S)) -#define MCPWM_GEN0_B_UTEZ_V 0x3 +/** MCPWM_GEN0_B_REG register + * Actions triggered by events on PWM0B + */ +#define MCPWM_GEN0_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x54) +/** MCPWM_GEN0_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEZ 0x00000003U +#define MCPWM_GEN0_B_UTEZ_M (MCPWM_GEN0_B_UTEZ_V << MCPWM_GEN0_B_UTEZ_S) +#define MCPWM_GEN0_B_UTEZ_V 0x00000003U #define MCPWM_GEN0_B_UTEZ_S 0 +/** MCPWM_GEN0_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEP 0x00000003U +#define MCPWM_GEN0_B_UTEP_M (MCPWM_GEN0_B_UTEP_V << MCPWM_GEN0_B_UTEP_S) +#define MCPWM_GEN0_B_UTEP_V 0x00000003U +#define MCPWM_GEN0_B_UTEP_S 2 +/** MCPWM_GEN0_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEA 0x00000003U +#define MCPWM_GEN0_B_UTEA_M (MCPWM_GEN0_B_UTEA_V << MCPWM_GEN0_B_UTEA_S) +#define MCPWM_GEN0_B_UTEA_V 0x00000003U +#define MCPWM_GEN0_B_UTEA_S 4 +/** MCPWM_GEN0_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEB 0x00000003U +#define MCPWM_GEN0_B_UTEB_M (MCPWM_GEN0_B_UTEB_V << MCPWM_GEN0_B_UTEB_S) +#define MCPWM_GEN0_B_UTEB_V 0x00000003U +#define MCPWM_GEN0_B_UTEB_S 6 +/** MCPWM_GEN0_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT0 0x00000003U +#define MCPWM_GEN0_B_UT0_M (MCPWM_GEN0_B_UT0_V << MCPWM_GEN0_B_UT0_S) +#define MCPWM_GEN0_B_UT0_V 0x00000003U +#define MCPWM_GEN0_B_UT0_S 8 +/** MCPWM_GEN0_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT1 0x00000003U +#define MCPWM_GEN0_B_UT1_M (MCPWM_GEN0_B_UT1_V << MCPWM_GEN0_B_UT1_S) +#define MCPWM_GEN0_B_UT1_V 0x00000003U +#define MCPWM_GEN0_B_UT1_S 10 +/** MCPWM_GEN0_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEZ 0x00000003U +#define MCPWM_GEN0_B_DTEZ_M (MCPWM_GEN0_B_DTEZ_V << MCPWM_GEN0_B_DTEZ_S) +#define MCPWM_GEN0_B_DTEZ_V 0x00000003U +#define MCPWM_GEN0_B_DTEZ_S 12 +/** MCPWM_GEN0_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEP 0x00000003U +#define MCPWM_GEN0_B_DTEP_M (MCPWM_GEN0_B_DTEP_V << MCPWM_GEN0_B_DTEP_S) +#define MCPWM_GEN0_B_DTEP_V 0x00000003U +#define MCPWM_GEN0_B_DTEP_S 14 +/** MCPWM_GEN0_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEA 0x00000003U +#define MCPWM_GEN0_B_DTEA_M (MCPWM_GEN0_B_DTEA_V << MCPWM_GEN0_B_DTEA_S) +#define MCPWM_GEN0_B_DTEA_V 0x00000003U +#define MCPWM_GEN0_B_DTEA_S 16 +/** MCPWM_GEN0_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEB 0x00000003U +#define MCPWM_GEN0_B_DTEB_M (MCPWM_GEN0_B_DTEB_V << MCPWM_GEN0_B_DTEB_S) +#define MCPWM_GEN0_B_DTEB_V 0x00000003U +#define MCPWM_GEN0_B_DTEB_S 18 +/** MCPWM_GEN0_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT0 0x00000003U +#define MCPWM_GEN0_B_DT0_M (MCPWM_GEN0_B_DT0_V << MCPWM_GEN0_B_DT0_S) +#define MCPWM_GEN0_B_DT0_V 0x00000003U +#define MCPWM_GEN0_B_DT0_S 20 +/** MCPWM_GEN0_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT1 0x00000003U +#define MCPWM_GEN0_B_DT1_M (MCPWM_GEN0_B_DT1_V << MCPWM_GEN0_B_DT1_S) +#define MCPWM_GEN0_B_DT1_V 0x00000003U +#define MCPWM_GEN0_B_DT1_S 22 -#define MCPWM_DB0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x58) -/* MCPWM_DB0_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_CLK_SEL (BIT(17)) -#define MCPWM_DB0_CLK_SEL_M (BIT(17)) -#define MCPWM_DB0_CLK_SEL_V 0x1 -#define MCPWM_DB0_CLK_SEL_S 17 -/* MCPWM_DB0_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB0_B_OUTBYPASS (BIT(16)) -#define MCPWM_DB0_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DB0_B_OUTBYPASS_V 0x1 -#define MCPWM_DB0_B_OUTBYPASS_S 16 -/* MCPWM_DB0_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB0_A_OUTBYPASS (BIT(15)) -#define MCPWM_DB0_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DB0_A_OUTBYPASS_V 0x1 -#define MCPWM_DB0_A_OUTBYPASS_S 15 -/* MCPWM_DB0_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_FED_OUTINVERT (BIT(14)) -#define MCPWM_DB0_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DB0_FED_OUTINVERT_V 0x1 -#define MCPWM_DB0_FED_OUTINVERT_S 14 -/* MCPWM_DB0_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_RED_OUTINVERT (BIT(13)) -#define MCPWM_DB0_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DB0_RED_OUTINVERT_V 0x1 -#define MCPWM_DB0_RED_OUTINVERT_S 13 -/* MCPWM_DB0_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_FED_INSEL (BIT(12)) -#define MCPWM_DB0_FED_INSEL_M (BIT(12)) -#define MCPWM_DB0_FED_INSEL_V 0x1 -#define MCPWM_DB0_FED_INSEL_S 12 -/* MCPWM_DB0_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_RED_INSEL (BIT(11)) -#define MCPWM_DB0_RED_INSEL_M (BIT(11)) -#define MCPWM_DB0_RED_INSEL_V 0x1 -#define MCPWM_DB0_RED_INSEL_S 11 -/* MCPWM_DB0_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_B_OUTSWAP (BIT(10)) -#define MCPWM_DB0_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DB0_B_OUTSWAP_V 0x1 -#define MCPWM_DB0_B_OUTSWAP_S 10 -/* MCPWM_DB0_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_A_OUTSWAP (BIT(9)) -#define MCPWM_DB0_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DB0_A_OUTSWAP_V 0x1 -#define MCPWM_DB0_A_OUTSWAP_S 9 -/* MCPWM_DB0_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: immediate, dual-edge B mode, 0: fed/red take effect on different path separately -, 1: fed/red take effect on B path, A out is in bypass or dulpB mode.*/ -#define MCPWM_DB0_DEB_MODE (BIT(8)) -#define MCPWM_DB0_DEB_MODE_M (BIT(8)) -#define MCPWM_DB0_DEB_MODE_V 0x1 -#define MCPWM_DB0_DEB_MODE_S 8 -/* MCPWM_DB0_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_DB0_RED_UPMETHOD 0x0000000F -#define MCPWM_DB0_RED_UPMETHOD_M ((MCPWM_DB0_RED_UPMETHOD_V)<<(MCPWM_DB0_RED_UPMETHOD_S)) -#define MCPWM_DB0_RED_UPMETHOD_V 0xF -#define MCPWM_DB0_RED_UPMETHOD_S 4 -/* MCPWM_DB0_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_DB0_FED_UPMETHOD 0x0000000F -#define MCPWM_DB0_FED_UPMETHOD_M ((MCPWM_DB0_FED_UPMETHOD_V)<<(MCPWM_DB0_FED_UPMETHOD_S)) -#define MCPWM_DB0_FED_UPMETHOD_V 0xF -#define MCPWM_DB0_FED_UPMETHOD_S 0 +/** MCPWM_DT0_CFG_REG register + * PWM generator 0 dead time type selection and configuration + */ +#define MCPWM_DT0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x58) +/** MCPWM_DT0_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_FED_UPMETHOD_M (MCPWM_DT0_FED_UPMETHOD_V << MCPWM_DT0_FED_UPMETHOD_S) +#define MCPWM_DT0_FED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT0_FED_UPMETHOD_S 0 +/** MCPWM_DT0_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_M (MCPWM_DT0_RED_UPMETHOD_V << MCPWM_DT0_RED_UPMETHOD_S) +#define MCPWM_DT0_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_S 4 +/** MCPWM_DT0_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT0_DEB_MODE (BIT(8)) +#define MCPWM_DT0_DEB_MODE_M (MCPWM_DT0_DEB_MODE_V << MCPWM_DT0_DEB_MODE_S) +#define MCPWM_DT0_DEB_MODE_V 0x00000001U +#define MCPWM_DT0_DEB_MODE_S 8 +/** MCPWM_DT0_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT0_A_OUTSWAP (BIT(9)) +#define MCPWM_DT0_A_OUTSWAP_M (MCPWM_DT0_A_OUTSWAP_V << MCPWM_DT0_A_OUTSWAP_S) +#define MCPWM_DT0_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_A_OUTSWAP_S 9 +/** MCPWM_DT0_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT0_B_OUTSWAP (BIT(10)) +#define MCPWM_DT0_B_OUTSWAP_M (MCPWM_DT0_B_OUTSWAP_V << MCPWM_DT0_B_OUTSWAP_S) +#define MCPWM_DT0_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_B_OUTSWAP_S 10 +/** MCPWM_DT0_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT0_RED_INSEL (BIT(11)) +#define MCPWM_DT0_RED_INSEL_M (MCPWM_DT0_RED_INSEL_V << MCPWM_DT0_RED_INSEL_S) +#define MCPWM_DT0_RED_INSEL_V 0x00000001U +#define MCPWM_DT0_RED_INSEL_S 11 +/** MCPWM_DT0_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT0_FED_INSEL (BIT(12)) +#define MCPWM_DT0_FED_INSEL_M (MCPWM_DT0_FED_INSEL_V << MCPWM_DT0_FED_INSEL_S) +#define MCPWM_DT0_FED_INSEL_V 0x00000001U +#define MCPWM_DT0_FED_INSEL_S 12 +/** MCPWM_DT0_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT0_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT0_RED_OUTINVERT_M (MCPWM_DT0_RED_OUTINVERT_V << MCPWM_DT0_RED_OUTINVERT_S) +#define MCPWM_DT0_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_RED_OUTINVERT_S 13 +/** MCPWM_DT0_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT0_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT0_FED_OUTINVERT_M (MCPWM_DT0_FED_OUTINVERT_V << MCPWM_DT0_FED_OUTINVERT_S) +#define MCPWM_DT0_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_FED_OUTINVERT_S 14 +/** MCPWM_DT0_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT0_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT0_A_OUTBYPASS_M (MCPWM_DT0_A_OUTBYPASS_V << MCPWM_DT0_A_OUTBYPASS_S) +#define MCPWM_DT0_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_A_OUTBYPASS_S 15 +/** MCPWM_DT0_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT0_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT0_B_OUTBYPASS_M (MCPWM_DT0_B_OUTBYPASS_V << MCPWM_DT0_B_OUTBYPASS_S) +#define MCPWM_DT0_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_B_OUTBYPASS_S 16 +/** MCPWM_DT0_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT0_CLK_SEL (BIT(17)) +#define MCPWM_DT0_CLK_SEL_M (MCPWM_DT0_CLK_SEL_V << MCPWM_DT0_CLK_SEL_S) +#define MCPWM_DT0_CLK_SEL_V 0x00000001U +#define MCPWM_DT0_CLK_SEL_S 17 -#define MCPWM_DB0_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x5C) -/* MCPWM_DB0_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_FED 0x0000FFFF -#define MCPWM_DB0_FED_M ((MCPWM_DB0_FED_V)<<(MCPWM_DB0_FED_S)) -#define MCPWM_DB0_FED_V 0xFFFF -#define MCPWM_DB0_FED_S 0 +/** MCPWM_DT0_FED_CFG_REG register + * PWM generator 0 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT0_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x5c) +/** MCPWM_DT0_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT0_FED 0x0000FFFFU +#define MCPWM_DT0_FED_M (MCPWM_DT0_FED_V << MCPWM_DT0_FED_S) +#define MCPWM_DT0_FED_V 0x0000FFFFU +#define MCPWM_DT0_FED_S 0 -#define MCPWM_DB0_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x60) -/* MCPWM_DB0_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_RED 0x0000FFFF -#define MCPWM_DB0_RED_M ((MCPWM_DB0_RED_V)<<(MCPWM_DB0_RED_S)) -#define MCPWM_DB0_RED_V 0xFFFF -#define MCPWM_DB0_RED_S 0 +/** MCPWM_DT0_RED_CFG_REG register + * PWM generator 0 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT0_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x60) +/** MCPWM_DT0_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT0_RED 0x0000FFFFU +#define MCPWM_DT0_RED_M (MCPWM_DT0_RED_V << MCPWM_DT0_RED_S) +#define MCPWM_DT0_RED_V 0x0000FFFFU +#define MCPWM_DT0_RED_S 0 -#define MCPWM_CHOPPER0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x64) -/* MCPWM_CHOPPER0_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_IN_INVERT (BIT(13)) -#define MCPWM_CHOPPER0_IN_INVERT_M (BIT(13)) -#define MCPWM_CHOPPER0_IN_INVERT_V 0x1 -#define MCPWM_CHOPPER0_IN_INVERT_S 13 -/* MCPWM_CHOPPER0_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_OUT_INVERT (BIT(12)) -#define MCPWM_CHOPPER0_OUT_INVERT_M (BIT(12)) -#define MCPWM_CHOPPER0_OUT_INVERT_V 0x1 -#define MCPWM_CHOPPER0_OUT_INVERT_S 12 -/* MCPWM_CHOPPER0_OSHTWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_OSHTWTH 0x0000000F -#define MCPWM_CHOPPER0_OSHTWTH_M ((MCPWM_CHOPPER0_OSHTWTH_V)<<(MCPWM_CHOPPER0_OSHTWTH_S)) -#define MCPWM_CHOPPER0_OSHTWTH_V 0xF -#define MCPWM_CHOPPER0_OSHTWTH_S 8 -/* MCPWM_CHOPPER0_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_DUTY 0x00000007 -#define MCPWM_CHOPPER0_DUTY_M ((MCPWM_CHOPPER0_DUTY_V)<<(MCPWM_CHOPPER0_DUTY_S)) -#define MCPWM_CHOPPER0_DUTY_V 0x7 -#define MCPWM_CHOPPER0_DUTY_S 5 -/* MCPWM_CHOPPER0_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_PRESCALE 0x0000000F -#define MCPWM_CHOPPER0_PRESCALE_M ((MCPWM_CHOPPER0_PRESCALE_V)<<(MCPWM_CHOPPER0_PRESCALE_S)) -#define MCPWM_CHOPPER0_PRESCALE_V 0xF -#define MCPWM_CHOPPER0_PRESCALE_S 1 -/* MCPWM_CHOPPER0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_EN (BIT(0)) -#define MCPWM_CHOPPER0_EN_M (BIT(0)) -#define MCPWM_CHOPPER0_EN_V 0x1 -#define MCPWM_CHOPPER0_EN_S 0 +/** MCPWM_CARRIER0_CFG_REG register + * PWM generator 0 carrier enable and configuratoin + */ +#define MCPWM_CARRIER0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x64) +/** MCPWM_CARRIER0_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier0 function is enabled. When cleared, carrier0 is bypassed + */ +#define MCPWM_CARRIER0_EN (BIT(0)) +#define MCPWM_CARRIER0_EN_M (MCPWM_CARRIER0_EN_V << MCPWM_CARRIER0_EN_S) +#define MCPWM_CARRIER0_EN_V 0x00000001U +#define MCPWM_CARRIER0_EN_S 0 +/** MCPWM_CARRIER0_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER0_PRESCALE 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_M (MCPWM_CARRIER0_PRESCALE_V << MCPWM_CARRIER0_PRESCALE_S) +#define MCPWM_CARRIER0_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_S 1 +/** MCPWM_CARRIER0_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER0_DUTY 0x00000007U +#define MCPWM_CARRIER0_DUTY_M (MCPWM_CARRIER0_DUTY_V << MCPWM_CARRIER0_DUTY_S) +#define MCPWM_CARRIER0_DUTY_V 0x00000007U +#define MCPWM_CARRIER0_DUTY_S 5 +/** MCPWM_CARRIER0_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER0_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_M (MCPWM_CARRIER0_OSHTWTH_V << MCPWM_CARRIER0_OSHTWTH_S) +#define MCPWM_CARRIER0_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_S 8 +/** MCPWM_CARRIER0_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER0_OUT_INVERT_M (MCPWM_CARRIER0_OUT_INVERT_V << MCPWM_CARRIER0_OUT_INVERT_S) +#define MCPWM_CARRIER0_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_OUT_INVERT_S 12 +/** MCPWM_CARRIER0_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER0_IN_INVERT_M (MCPWM_CARRIER0_IN_INVERT_V << MCPWM_CARRIER0_IN_INVERT_S) +#define MCPWM_CARRIER0_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_IN_INVERT_S 13 -#define MCPWM_TZ0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x68) -/* MCPWM_TZ0_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_OST_U 0x00000003 -#define MCPWM_TZ0_B_OST_U_M ((MCPWM_TZ0_B_OST_U_V)<<(MCPWM_TZ0_B_OST_U_S)) -#define MCPWM_TZ0_B_OST_U_V 0x3 -#define MCPWM_TZ0_B_OST_U_S 22 -/* MCPWM_TZ0_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_OST_D 0x00000003 -#define MCPWM_TZ0_B_OST_D_M ((MCPWM_TZ0_B_OST_D_V)<<(MCPWM_TZ0_B_OST_D_S)) -#define MCPWM_TZ0_B_OST_D_V 0x3 -#define MCPWM_TZ0_B_OST_D_S 20 -/* MCPWM_TZ0_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_CBC_U 0x00000003 -#define MCPWM_TZ0_B_CBC_U_M ((MCPWM_TZ0_B_CBC_U_V)<<(MCPWM_TZ0_B_CBC_U_S)) -#define MCPWM_TZ0_B_CBC_U_V 0x3 -#define MCPWM_TZ0_B_CBC_U_S 18 -/* MCPWM_TZ0_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_CBC_D 0x00000003 -#define MCPWM_TZ0_B_CBC_D_M ((MCPWM_TZ0_B_CBC_D_V)<<(MCPWM_TZ0_B_CBC_D_S)) -#define MCPWM_TZ0_B_CBC_D_V 0x3 -#define MCPWM_TZ0_B_CBC_D_S 16 -/* MCPWM_TZ0_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_OST_U 0x00000003 -#define MCPWM_TZ0_A_OST_U_M ((MCPWM_TZ0_A_OST_U_V)<<(MCPWM_TZ0_A_OST_U_S)) -#define MCPWM_TZ0_A_OST_U_V 0x3 -#define MCPWM_TZ0_A_OST_U_S 14 -/* MCPWM_TZ0_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_OST_D 0x00000003 -#define MCPWM_TZ0_A_OST_D_M ((MCPWM_TZ0_A_OST_D_V)<<(MCPWM_TZ0_A_OST_D_S)) -#define MCPWM_TZ0_A_OST_D_V 0x3 -#define MCPWM_TZ0_A_OST_D_S 12 -/* MCPWM_TZ0_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_CBC_U 0x00000003 -#define MCPWM_TZ0_A_CBC_U_M ((MCPWM_TZ0_A_CBC_U_V)<<(MCPWM_TZ0_A_CBC_U_S)) -#define MCPWM_TZ0_A_CBC_U_V 0x3 -#define MCPWM_TZ0_A_CBC_U_S 10 -/* MCPWM_TZ0_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_CBC_D 0x00000003 -#define MCPWM_TZ0_A_CBC_D_M ((MCPWM_TZ0_A_CBC_D_V)<<(MCPWM_TZ0_A_CBC_D_S)) -#define MCPWM_TZ0_A_CBC_D_V 0x3 -#define MCPWM_TZ0_A_CBC_D_S 8 -/* MCPWM_TZ0_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F0_OST (BIT(7)) -#define MCPWM_TZ0_F0_OST_M (BIT(7)) -#define MCPWM_TZ0_F0_OST_V 0x1 -#define MCPWM_TZ0_F0_OST_S 7 -/* MCPWM_TZ0_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F1_OST (BIT(6)) -#define MCPWM_TZ0_F1_OST_M (BIT(6)) -#define MCPWM_TZ0_F1_OST_V 0x1 -#define MCPWM_TZ0_F1_OST_S 6 -/* MCPWM_TZ0_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F2_OST (BIT(5)) -#define MCPWM_TZ0_F2_OST_M (BIT(5)) -#define MCPWM_TZ0_F2_OST_V 0x1 -#define MCPWM_TZ0_F2_OST_S 5 -/* MCPWM_TZ0_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_SW_OST (BIT(4)) -#define MCPWM_TZ0_SW_OST_M (BIT(4)) -#define MCPWM_TZ0_SW_OST_V 0x1 -#define MCPWM_TZ0_SW_OST_S 4 -/* MCPWM_TZ0_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F0_CBC (BIT(3)) -#define MCPWM_TZ0_F0_CBC_M (BIT(3)) -#define MCPWM_TZ0_F0_CBC_V 0x1 -#define MCPWM_TZ0_F0_CBC_S 3 -/* MCPWM_TZ0_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F1_CBC (BIT(2)) -#define MCPWM_TZ0_F1_CBC_M (BIT(2)) -#define MCPWM_TZ0_F1_CBC_V 0x1 -#define MCPWM_TZ0_F1_CBC_S 2 -/* MCPWM_TZ0_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F2_CBC (BIT(1)) -#define MCPWM_TZ0_F2_CBC_M (BIT(1)) -#define MCPWM_TZ0_F2_CBC_V 0x1 -#define MCPWM_TZ0_F2_CBC_S 1 -/* MCPWM_TZ0_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_SW_CBC (BIT(0)) -#define MCPWM_TZ0_SW_CBC_M (BIT(0)) -#define MCPWM_TZ0_SW_CBC_V 0x1 -#define MCPWM_TZ0_SW_CBC_S 0 +/** MCPWM_FH0_CFG0_REG register + * Actions on PWM0A and PWM0B trip events + */ +#define MCPWM_FH0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x68) +/** MCPWM_FH0_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_CBC (BIT(0)) +#define MCPWM_FH0_SW_CBC_M (MCPWM_FH0_SW_CBC_V << MCPWM_FH0_SW_CBC_S) +#define MCPWM_FH0_SW_CBC_V 0x00000001U +#define MCPWM_FH0_SW_CBC_S 0 +/** MCPWM_FH0_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_CBC (BIT(1)) +#define MCPWM_FH0_F2_CBC_M (MCPWM_FH0_F2_CBC_V << MCPWM_FH0_F2_CBC_S) +#define MCPWM_FH0_F2_CBC_V 0x00000001U +#define MCPWM_FH0_F2_CBC_S 1 +/** MCPWM_FH0_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_CBC (BIT(2)) +#define MCPWM_FH0_F1_CBC_M (MCPWM_FH0_F1_CBC_V << MCPWM_FH0_F1_CBC_S) +#define MCPWM_FH0_F1_CBC_V 0x00000001U +#define MCPWM_FH0_F1_CBC_S 2 +/** MCPWM_FH0_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_CBC (BIT(3)) +#define MCPWM_FH0_F0_CBC_M (MCPWM_FH0_F0_CBC_V << MCPWM_FH0_F0_CBC_S) +#define MCPWM_FH0_F0_CBC_V 0x00000001U +#define MCPWM_FH0_F0_CBC_S 3 +/** MCPWM_FH0_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_OST (BIT(4)) +#define MCPWM_FH0_SW_OST_M (MCPWM_FH0_SW_OST_V << MCPWM_FH0_SW_OST_S) +#define MCPWM_FH0_SW_OST_V 0x00000001U +#define MCPWM_FH0_SW_OST_S 4 +/** MCPWM_FH0_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_OST (BIT(5)) +#define MCPWM_FH0_F2_OST_M (MCPWM_FH0_F2_OST_V << MCPWM_FH0_F2_OST_S) +#define MCPWM_FH0_F2_OST_V 0x00000001U +#define MCPWM_FH0_F2_OST_S 5 +/** MCPWM_FH0_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_OST (BIT(6)) +#define MCPWM_FH0_F1_OST_M (MCPWM_FH0_F1_OST_V << MCPWM_FH0_F1_OST_S) +#define MCPWM_FH0_F1_OST_V 0x00000001U +#define MCPWM_FH0_F1_OST_S 6 +/** MCPWM_FH0_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_OST (BIT(7)) +#define MCPWM_FH0_F0_OST_M (MCPWM_FH0_F0_OST_V << MCPWM_FH0_F0_OST_S) +#define MCPWM_FH0_F0_OST_V 0x00000001U +#define MCPWM_FH0_F0_OST_S 7 +/** MCPWM_FH0_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_D 0x00000003U +#define MCPWM_FH0_A_CBC_D_M (MCPWM_FH0_A_CBC_D_V << MCPWM_FH0_A_CBC_D_S) +#define MCPWM_FH0_A_CBC_D_V 0x00000003U +#define MCPWM_FH0_A_CBC_D_S 8 +/** MCPWM_FH0_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_U 0x00000003U +#define MCPWM_FH0_A_CBC_U_M (MCPWM_FH0_A_CBC_U_V << MCPWM_FH0_A_CBC_U_S) +#define MCPWM_FH0_A_CBC_U_V 0x00000003U +#define MCPWM_FH0_A_CBC_U_S 10 +/** MCPWM_FH0_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_D 0x00000003U +#define MCPWM_FH0_A_OST_D_M (MCPWM_FH0_A_OST_D_V << MCPWM_FH0_A_OST_D_S) +#define MCPWM_FH0_A_OST_D_V 0x00000003U +#define MCPWM_FH0_A_OST_D_S 12 +/** MCPWM_FH0_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_U 0x00000003U +#define MCPWM_FH0_A_OST_U_M (MCPWM_FH0_A_OST_U_V << MCPWM_FH0_A_OST_U_S) +#define MCPWM_FH0_A_OST_U_V 0x00000003U +#define MCPWM_FH0_A_OST_U_S 14 +/** MCPWM_FH0_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_D 0x00000003U +#define MCPWM_FH0_B_CBC_D_M (MCPWM_FH0_B_CBC_D_V << MCPWM_FH0_B_CBC_D_S) +#define MCPWM_FH0_B_CBC_D_V 0x00000003U +#define MCPWM_FH0_B_CBC_D_S 16 +/** MCPWM_FH0_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_U 0x00000003U +#define MCPWM_FH0_B_CBC_U_M (MCPWM_FH0_B_CBC_U_V << MCPWM_FH0_B_CBC_U_S) +#define MCPWM_FH0_B_CBC_U_V 0x00000003U +#define MCPWM_FH0_B_CBC_U_S 18 +/** MCPWM_FH0_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_D 0x00000003U +#define MCPWM_FH0_B_OST_D_M (MCPWM_FH0_B_OST_D_V << MCPWM_FH0_B_OST_D_S) +#define MCPWM_FH0_B_OST_D_V 0x00000003U +#define MCPWM_FH0_B_OST_D_S 20 +/** MCPWM_FH0_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_U 0x00000003U +#define MCPWM_FH0_B_OST_U_M (MCPWM_FH0_B_OST_U_V << MCPWM_FH0_B_OST_U_S) +#define MCPWM_FH0_B_OST_U_V 0x00000003U +#define MCPWM_FH0_B_OST_U_S 22 -#define MCPWM_TZ0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x6C) -/* MCPWM_TZ0_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: a toggle trigger a oneshot tripping.*/ -#define MCPWM_TZ0_FORCE_OST (BIT(4)) -#define MCPWM_TZ0_FORCE_OST_M (BIT(4)) -#define MCPWM_TZ0_FORCE_OST_V 0x1 -#define MCPWM_TZ0_FORCE_OST_S 4 -/* MCPWM_TZ0_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle trigger a cycle-by-cycle tripping.*/ -#define MCPWM_TZ0_FORCE_CBC (BIT(3)) -#define MCPWM_TZ0_FORCE_CBC_M (BIT(3)) -#define MCPWM_TZ0_FORCE_CBC_V 0x1 -#define MCPWM_TZ0_FORCE_CBC_S 3 -/* MCPWM_TZ0_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: tez, bit1: tep.*/ -#define MCPWM_TZ0_CBCPULSE 0x00000003 -#define MCPWM_TZ0_CBCPULSE_M ((MCPWM_TZ0_CBCPULSE_V)<<(MCPWM_TZ0_CBCPULSE_S)) -#define MCPWM_TZ0_CBCPULSE_V 0x3 -#define MCPWM_TZ0_CBCPULSE_S 1 -/* MCPWM_TZ0_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: a toggle will clear oneshot tripping.*/ -#define MCPWM_TZ0_CLR_OST (BIT(0)) -#define MCPWM_TZ0_CLR_OST_M (BIT(0)) -#define MCPWM_TZ0_CLR_OST_V 0x1 -#define MCPWM_TZ0_CLR_OST_S 0 +/** MCPWM_FH0_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x6c) +/** MCPWM_FH0_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH0_CLR_OST (BIT(0)) +#define MCPWM_FH0_CLR_OST_M (MCPWM_FH0_CLR_OST_V << MCPWM_FH0_CLR_OST_S) +#define MCPWM_FH0_CLR_OST_V 0x00000001U +#define MCPWM_FH0_CLR_OST_S 0 +/** MCPWM_FH0_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ +#define MCPWM_FH0_CBCPULSE 0x00000003U +#define MCPWM_FH0_CBCPULSE_M (MCPWM_FH0_CBCPULSE_V << MCPWM_FH0_CBCPULSE_S) +#define MCPWM_FH0_CBCPULSE_V 0x00000003U +#define MCPWM_FH0_CBCPULSE_S 1 +/** MCPWM_FH0_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH0_FORCE_CBC (BIT(3)) +#define MCPWM_FH0_FORCE_CBC_M (MCPWM_FH0_FORCE_CBC_V << MCPWM_FH0_FORCE_CBC_S) +#define MCPWM_FH0_FORCE_CBC_V 0x00000001U +#define MCPWM_FH0_FORCE_CBC_S 3 +/** MCPWM_FH0_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH0_FORCE_OST (BIT(4)) +#define MCPWM_FH0_FORCE_OST_M (MCPWM_FH0_FORCE_OST_V << MCPWM_FH0_FORCE_OST_S) +#define MCPWM_FH0_FORCE_OST_V 0x00000001U +#define MCPWM_FH0_FORCE_OST_S 4 -#define MCPWM_TZ0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x70) -/* MCPWM_TZ0_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_ON (BIT(1)) -#define MCPWM_TZ0_OST_ON_M (BIT(1)) -#define MCPWM_TZ0_OST_ON_V 0x1 -#define MCPWM_TZ0_OST_ON_S 1 -/* MCPWM_TZ0_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_ON (BIT(0)) -#define MCPWM_TZ0_CBC_ON_M (BIT(0)) -#define MCPWM_TZ0_CBC_ON_V 0x1 -#define MCPWM_TZ0_CBC_ON_S 0 +/** MCPWM_FH0_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x70) +/** MCPWM_FH0_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH0_CBC_ON (BIT(0)) +#define MCPWM_FH0_CBC_ON_M (MCPWM_FH0_CBC_ON_V << MCPWM_FH0_CBC_ON_S) +#define MCPWM_FH0_CBC_ON_V 0x00000001U +#define MCPWM_FH0_CBC_ON_S 0 +/** MCPWM_FH0_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH0_OST_ON (BIT(1)) +#define MCPWM_FH0_OST_ON_M (MCPWM_FH0_OST_ON_V << MCPWM_FH0_OST_ON_S) +#define MCPWM_FH0_OST_ON_V 0x00000001U +#define MCPWM_FH0_OST_ON_S 1 -#define MCPWM_CMPR1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x74) -/* MCPWM_CMPR1_B_SHDW_FULL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_B_SHDW_FULL (BIT(9)) -#define MCPWM_CMPR1_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_CMPR1_B_SHDW_FULL_V 0x1 -#define MCPWM_CMPR1_B_SHDW_FULL_S 9 -/* MCPWM_CMPR1_A_SHDW_FULL : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_A_SHDW_FULL (BIT(8)) -#define MCPWM_CMPR1_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_CMPR1_A_SHDW_FULL_V 0x1 -#define MCPWM_CMPR1_A_SHDW_FULL_S 8 -/* MCPWM_CMPR1_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR1_B_UPMETHOD 0x0000000F -#define MCPWM_CMPR1_B_UPMETHOD_M ((MCPWM_CMPR1_B_UPMETHOD_V)<<(MCPWM_CMPR1_B_UPMETHOD_S)) -#define MCPWM_CMPR1_B_UPMETHOD_V 0xF -#define MCPWM_CMPR1_B_UPMETHOD_S 4 -/* MCPWM_CMPR1_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR1_A_UPMETHOD 0x0000000F -#define MCPWM_CMPR1_A_UPMETHOD_M ((MCPWM_CMPR1_A_UPMETHOD_V)<<(MCPWM_CMPR1_A_UPMETHOD_S)) -#define MCPWM_CMPR1_A_UPMETHOD_V 0xF -#define MCPWM_CMPR1_A_UPMETHOD_S 0 +/** MCPWM_GEN1_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN1_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x74) +/** MCPWM_GEN1_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_A_UPMETHOD_M (MCPWM_GEN1_A_UPMETHOD_V << MCPWM_GEN1_A_UPMETHOD_S) +#define MCPWM_GEN1_A_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN1_A_UPMETHOD_S 0 +/** MCPWM_GEN1_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 1 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_M (MCPWM_GEN1_B_UPMETHOD_V << MCPWM_GEN1_B_UPMETHOD_S) +#define MCPWM_GEN1_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_S 4 +/** MCPWM_GEN1_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN1_A_SHDW_FULL_M (MCPWM_GEN1_A_SHDW_FULL_V << MCPWM_GEN1_A_SHDW_FULL_S) +#define MCPWM_GEN1_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_A_SHDW_FULL_S 8 +/** MCPWM_GEN1_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN1_B_SHDW_FULL_M (MCPWM_GEN1_B_SHDW_FULL_V << MCPWM_GEN1_B_SHDW_FULL_S) +#define MCPWM_GEN1_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_B_SHDW_FULL_S 9 -#define MCPWM_CMPR1_VALUE0_REG(i) (REG_MCPWM_BASE(i) + 0x78) -/* MCPWM_CMPR1_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_A 0x0000FFFF -#define MCPWM_CMPR1_A_M ((MCPWM_CMPR1_A_V)<<(MCPWM_CMPR1_A_S)) -#define MCPWM_CMPR1_A_V 0xFFFF -#define MCPWM_CMPR1_A_S 0 +/** MCPWM_GEN1_TSTMP_A_REG register + * PWM generator 1 shadow register for timer stamp A. + */ +#define MCPWM_GEN1_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x78) +/** MCPWM_GEN1_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp A's shadow register + */ +#define MCPWM_GEN1_A 0x0000FFFFU +#define MCPWM_GEN1_A_M (MCPWM_GEN1_A_V << MCPWM_GEN1_A_S) +#define MCPWM_GEN1_A_V 0x0000FFFFU +#define MCPWM_GEN1_A_S 0 -#define MCPWM_CMPR1_VALUE1_REG(i) (REG_MCPWM_BASE(i) + 0x7C) -/* MCPWM_CMPR1_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_B 0x0000FFFF -#define MCPWM_CMPR1_B_M ((MCPWM_CMPR1_B_V)<<(MCPWM_CMPR1_B_S)) -#define MCPWM_CMPR1_B_V 0xFFFF -#define MCPWM_CMPR1_B_S 0 +/** MCPWM_GEN1_TSTMP_B_REG register + * PWM generator 1 shadow register for timer stamp B. + */ +#define MCPWM_GEN1_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x7c) +/** MCPWM_GEN1_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp B's shadow register + */ +#define MCPWM_GEN1_B 0x0000FFFFU +#define MCPWM_GEN1_B_M (MCPWM_GEN1_B_V << MCPWM_GEN1_B_S) +#define MCPWM_GEN1_B_V 0x0000FFFFU +#define MCPWM_GEN1_B_S 0 -#define MCPWM_GEN1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x80) -/* MCPWM_GEN1_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN1_T1_SEL 0x00000007 -#define MCPWM_GEN1_T1_SEL_M ((MCPWM_GEN1_T1_SEL_V)<<(MCPWM_GEN1_T1_SEL_S)) -#define MCPWM_GEN1_T1_SEL_V 0x7 -#define MCPWM_GEN1_T1_SEL_S 7 -/* MCPWM_GEN1_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN1_T0_SEL 0x00000007 -#define MCPWM_GEN1_T0_SEL_M ((MCPWM_GEN1_T0_SEL_V)<<(MCPWM_GEN1_T0_SEL_S)) -#define MCPWM_GEN1_T0_SEL_V 0x7 -#define MCPWM_GEN1_T0_SEL_S 4 -/* MCPWM_GEN1_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze.*/ -#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN1_CFG_UPMETHOD_M ((MCPWM_GEN1_CFG_UPMETHOD_V)<<(MCPWM_GEN1_CFG_UPMETHOD_S)) -#define MCPWM_GEN1_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN1_CFG0_REG register + * PWM generator 1 event T0 and T1 handling + */ +#define MCPWM_GEN1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x80) +/** MCPWM_GEN1_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:sync;when bit3 is set to 1:disable the update. + */ +#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_CFG_UPMETHOD_M (MCPWM_GEN1_CFG_UPMETHOD_V << MCPWM_GEN1_CFG_UPMETHOD_S) +#define MCPWM_GEN1_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN1_CFG_UPMETHOD_S 0 +/** MCPWM_GEN1_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 1 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T0_SEL 0x00000007U +#define MCPWM_GEN1_T0_SEL_M (MCPWM_GEN1_T0_SEL_V << MCPWM_GEN1_T0_SEL_S) +#define MCPWM_GEN1_T0_SEL_V 0x00000007U +#define MCPWM_GEN1_T0_SEL_S 4 +/** MCPWM_GEN1_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 1 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T1_SEL 0x00000007U +#define MCPWM_GEN1_T1_SEL_M (MCPWM_GEN1_T1_SEL_V << MCPWM_GEN1_T1_SEL_S) +#define MCPWM_GEN1_T1_SEL_V 0x00000007U +#define MCPWM_GEN1_T1_SEL_S 7 -#define MCPWM_GEN1_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x84) -/* MCPWM_GEN1_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_NCIFORCE_MODE_M ((MCPWM_GEN1_B_NCIFORCE_MODE_V)<<(MCPWM_GEN1_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN1_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_V 0x1 -#define MCPWM_GEN1_B_NCIFORCE_S 13 -/* MCPWM_GEN1_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_NCIFORCE_MODE_M ((MCPWM_GEN1_A_NCIFORCE_MODE_V)<<(MCPWM_GEN1_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN1_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_V 0x1 -#define MCPWM_GEN1_A_NCIFORCE_S 10 -/* MCPWM_GEN1_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_M ((MCPWM_GEN1_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN1_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_M ((MCPWM_GEN1_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: free -ze.*/ -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN1_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN1_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN1_FORCE_REG register + * Permissives to force PWM1A and PWM1B outputs by software + */ +#define MCPWM_GEN1_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x84) +/** MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 1. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M (MCPWM_GEN1_CNTUFORCE_UPMETHOD_V << MCPWM_GEN1_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN1_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN1_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM1A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_M (MCPWM_GEN1_A_CNTUFORCE_MODE_V << MCPWM_GEN1_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN1_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM1B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_M (MCPWM_GEN1_B_CNTUFORCE_MODE_V << MCPWM_GEN1_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN1_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN1_A_NCIFORCE_M (MCPWM_GEN1_A_NCIFORCE_V << MCPWM_GEN1_A_NCIFORCE_S) +#define MCPWM_GEN1_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_A_NCIFORCE_S 10 +/** MCPWM_GEN1_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM1A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_M (MCPWM_GEN1_A_NCIFORCE_MODE_V << MCPWM_GEN1_A_NCIFORCE_MODE_S) +#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN1_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN1_B_NCIFORCE_M (MCPWM_GEN1_B_NCIFORCE_V << MCPWM_GEN1_B_NCIFORCE_S) +#define MCPWM_GEN1_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_B_NCIFORCE_S 13 +/** MCPWM_GEN1_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM1B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_M (MCPWM_GEN1_B_NCIFORCE_MODE_V << MCPWM_GEN1_B_NCIFORCE_MODE_S) +#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN1_A_REG(i) (REG_MCPWM_BASE(i) + 0x88) -/* MCPWM_GEN1_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: no change, 1: low, 2: high, 3: toggle.*/ -#define MCPWM_GEN1_A_DT1 0x00000003 -#define MCPWM_GEN1_A_DT1_M ((MCPWM_GEN1_A_DT1_V)<<(MCPWM_GEN1_A_DT1_S)) -#define MCPWM_GEN1_A_DT1_V 0x3 -#define MCPWM_GEN1_A_DT1_S 22 -/* MCPWM_GEN1_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DT0 0x00000003 -#define MCPWM_GEN1_A_DT0_M ((MCPWM_GEN1_A_DT0_V)<<(MCPWM_GEN1_A_DT0_S)) -#define MCPWM_GEN1_A_DT0_V 0x3 -#define MCPWM_GEN1_A_DT0_S 20 -/* MCPWM_GEN1_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEB 0x00000003 -#define MCPWM_GEN1_A_DTEB_M ((MCPWM_GEN1_A_DTEB_V)<<(MCPWM_GEN1_A_DTEB_S)) -#define MCPWM_GEN1_A_DTEB_V 0x3 -#define MCPWM_GEN1_A_DTEB_S 18 -/* MCPWM_GEN1_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEA 0x00000003 -#define MCPWM_GEN1_A_DTEA_M ((MCPWM_GEN1_A_DTEA_V)<<(MCPWM_GEN1_A_DTEA_S)) -#define MCPWM_GEN1_A_DTEA_V 0x3 -#define MCPWM_GEN1_A_DTEA_S 16 -/* MCPWM_GEN1_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEP 0x00000003 -#define MCPWM_GEN1_A_DTEP_M ((MCPWM_GEN1_A_DTEP_V)<<(MCPWM_GEN1_A_DTEP_S)) -#define MCPWM_GEN1_A_DTEP_V 0x3 -#define MCPWM_GEN1_A_DTEP_S 14 -/* MCPWM_GEN1_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEZ 0x00000003 -#define MCPWM_GEN1_A_DTEZ_M ((MCPWM_GEN1_A_DTEZ_V)<<(MCPWM_GEN1_A_DTEZ_S)) -#define MCPWM_GEN1_A_DTEZ_V 0x3 -#define MCPWM_GEN1_A_DTEZ_S 12 -/* MCPWM_GEN1_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UT1 0x00000003 -#define MCPWM_GEN1_A_UT1_M ((MCPWM_GEN1_A_UT1_V)<<(MCPWM_GEN1_A_UT1_S)) -#define MCPWM_GEN1_A_UT1_V 0x3 -#define MCPWM_GEN1_A_UT1_S 10 -/* MCPWM_GEN1_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UT0 0x00000003 -#define MCPWM_GEN1_A_UT0_M ((MCPWM_GEN1_A_UT0_V)<<(MCPWM_GEN1_A_UT0_S)) -#define MCPWM_GEN1_A_UT0_V 0x3 -#define MCPWM_GEN1_A_UT0_S 8 -/* MCPWM_GEN1_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEB 0x00000003 -#define MCPWM_GEN1_A_UTEB_M ((MCPWM_GEN1_A_UTEB_V)<<(MCPWM_GEN1_A_UTEB_S)) -#define MCPWM_GEN1_A_UTEB_V 0x3 -#define MCPWM_GEN1_A_UTEB_S 6 -/* MCPWM_GEN1_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEA 0x00000003 -#define MCPWM_GEN1_A_UTEA_M ((MCPWM_GEN1_A_UTEA_V)<<(MCPWM_GEN1_A_UTEA_S)) -#define MCPWM_GEN1_A_UTEA_V 0x3 -#define MCPWM_GEN1_A_UTEA_S 4 -/* MCPWM_GEN1_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEP 0x00000003 -#define MCPWM_GEN1_A_UTEP_M ((MCPWM_GEN1_A_UTEP_V)<<(MCPWM_GEN1_A_UTEP_S)) -#define MCPWM_GEN1_A_UTEP_V 0x3 -#define MCPWM_GEN1_A_UTEP_S 2 -/* MCPWM_GEN1_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEZ 0x00000003 -#define MCPWM_GEN1_A_UTEZ_M ((MCPWM_GEN1_A_UTEZ_V)<<(MCPWM_GEN1_A_UTEZ_S)) -#define MCPWM_GEN1_A_UTEZ_V 0x3 +/** MCPWM_GEN1_A_REG register + * Actions triggered by events on PWM1A + */ +#define MCPWM_GEN1_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x88) +/** MCPWM_GEN1_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEZ 0x00000003U +#define MCPWM_GEN1_A_UTEZ_M (MCPWM_GEN1_A_UTEZ_V << MCPWM_GEN1_A_UTEZ_S) +#define MCPWM_GEN1_A_UTEZ_V 0x00000003U #define MCPWM_GEN1_A_UTEZ_S 0 +/** MCPWM_GEN1_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEP 0x00000003U +#define MCPWM_GEN1_A_UTEP_M (MCPWM_GEN1_A_UTEP_V << MCPWM_GEN1_A_UTEP_S) +#define MCPWM_GEN1_A_UTEP_V 0x00000003U +#define MCPWM_GEN1_A_UTEP_S 2 +/** MCPWM_GEN1_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEA 0x00000003U +#define MCPWM_GEN1_A_UTEA_M (MCPWM_GEN1_A_UTEA_V << MCPWM_GEN1_A_UTEA_S) +#define MCPWM_GEN1_A_UTEA_V 0x00000003U +#define MCPWM_GEN1_A_UTEA_S 4 +/** MCPWM_GEN1_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEB 0x00000003U +#define MCPWM_GEN1_A_UTEB_M (MCPWM_GEN1_A_UTEB_V << MCPWM_GEN1_A_UTEB_S) +#define MCPWM_GEN1_A_UTEB_V 0x00000003U +#define MCPWM_GEN1_A_UTEB_S 6 +/** MCPWM_GEN1_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT0 0x00000003U +#define MCPWM_GEN1_A_UT0_M (MCPWM_GEN1_A_UT0_V << MCPWM_GEN1_A_UT0_S) +#define MCPWM_GEN1_A_UT0_V 0x00000003U +#define MCPWM_GEN1_A_UT0_S 8 +/** MCPWM_GEN1_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT1 0x00000003U +#define MCPWM_GEN1_A_UT1_M (MCPWM_GEN1_A_UT1_V << MCPWM_GEN1_A_UT1_S) +#define MCPWM_GEN1_A_UT1_V 0x00000003U +#define MCPWM_GEN1_A_UT1_S 10 +/** MCPWM_GEN1_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEZ 0x00000003U +#define MCPWM_GEN1_A_DTEZ_M (MCPWM_GEN1_A_DTEZ_V << MCPWM_GEN1_A_DTEZ_S) +#define MCPWM_GEN1_A_DTEZ_V 0x00000003U +#define MCPWM_GEN1_A_DTEZ_S 12 +/** MCPWM_GEN1_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEP 0x00000003U +#define MCPWM_GEN1_A_DTEP_M (MCPWM_GEN1_A_DTEP_V << MCPWM_GEN1_A_DTEP_S) +#define MCPWM_GEN1_A_DTEP_V 0x00000003U +#define MCPWM_GEN1_A_DTEP_S 14 +/** MCPWM_GEN1_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEA 0x00000003U +#define MCPWM_GEN1_A_DTEA_M (MCPWM_GEN1_A_DTEA_V << MCPWM_GEN1_A_DTEA_S) +#define MCPWM_GEN1_A_DTEA_V 0x00000003U +#define MCPWM_GEN1_A_DTEA_S 16 +/** MCPWM_GEN1_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEB 0x00000003U +#define MCPWM_GEN1_A_DTEB_M (MCPWM_GEN1_A_DTEB_V << MCPWM_GEN1_A_DTEB_S) +#define MCPWM_GEN1_A_DTEB_V 0x00000003U +#define MCPWM_GEN1_A_DTEB_S 18 +/** MCPWM_GEN1_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT0 0x00000003U +#define MCPWM_GEN1_A_DT0_M (MCPWM_GEN1_A_DT0_V << MCPWM_GEN1_A_DT0_S) +#define MCPWM_GEN1_A_DT0_V 0x00000003U +#define MCPWM_GEN1_A_DT0_S 20 +/** MCPWM_GEN1_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT1 0x00000003U +#define MCPWM_GEN1_A_DT1_M (MCPWM_GEN1_A_DT1_V << MCPWM_GEN1_A_DT1_S) +#define MCPWM_GEN1_A_DT1_V 0x00000003U +#define MCPWM_GEN1_A_DT1_S 22 -#define MCPWM_GEN1_B_REG(i) (REG_MCPWM_BASE(i) + 0x8C) -/* MCPWM_GEN1_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DT1 0x00000003 -#define MCPWM_GEN1_B_DT1_M ((MCPWM_GEN1_B_DT1_V)<<(MCPWM_GEN1_B_DT1_S)) -#define MCPWM_GEN1_B_DT1_V 0x3 -#define MCPWM_GEN1_B_DT1_S 22 -/* MCPWM_GEN1_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DT0 0x00000003 -#define MCPWM_GEN1_B_DT0_M ((MCPWM_GEN1_B_DT0_V)<<(MCPWM_GEN1_B_DT0_S)) -#define MCPWM_GEN1_B_DT0_V 0x3 -#define MCPWM_GEN1_B_DT0_S 20 -/* MCPWM_GEN1_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEB 0x00000003 -#define MCPWM_GEN1_B_DTEB_M ((MCPWM_GEN1_B_DTEB_V)<<(MCPWM_GEN1_B_DTEB_S)) -#define MCPWM_GEN1_B_DTEB_V 0x3 -#define MCPWM_GEN1_B_DTEB_S 18 -/* MCPWM_GEN1_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEA 0x00000003 -#define MCPWM_GEN1_B_DTEA_M ((MCPWM_GEN1_B_DTEA_V)<<(MCPWM_GEN1_B_DTEA_S)) -#define MCPWM_GEN1_B_DTEA_V 0x3 -#define MCPWM_GEN1_B_DTEA_S 16 -/* MCPWM_GEN1_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEP 0x00000003 -#define MCPWM_GEN1_B_DTEP_M ((MCPWM_GEN1_B_DTEP_V)<<(MCPWM_GEN1_B_DTEP_S)) -#define MCPWM_GEN1_B_DTEP_V 0x3 -#define MCPWM_GEN1_B_DTEP_S 14 -/* MCPWM_GEN1_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEZ 0x00000003 -#define MCPWM_GEN1_B_DTEZ_M ((MCPWM_GEN1_B_DTEZ_V)<<(MCPWM_GEN1_B_DTEZ_S)) -#define MCPWM_GEN1_B_DTEZ_V 0x3 -#define MCPWM_GEN1_B_DTEZ_S 12 -/* MCPWM_GEN1_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UT1 0x00000003 -#define MCPWM_GEN1_B_UT1_M ((MCPWM_GEN1_B_UT1_V)<<(MCPWM_GEN1_B_UT1_S)) -#define MCPWM_GEN1_B_UT1_V 0x3 -#define MCPWM_GEN1_B_UT1_S 10 -/* MCPWM_GEN1_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UT0 0x00000003 -#define MCPWM_GEN1_B_UT0_M ((MCPWM_GEN1_B_UT0_V)<<(MCPWM_GEN1_B_UT0_S)) -#define MCPWM_GEN1_B_UT0_V 0x3 -#define MCPWM_GEN1_B_UT0_S 8 -/* MCPWM_GEN1_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEB 0x00000003 -#define MCPWM_GEN1_B_UTEB_M ((MCPWM_GEN1_B_UTEB_V)<<(MCPWM_GEN1_B_UTEB_S)) -#define MCPWM_GEN1_B_UTEB_V 0x3 -#define MCPWM_GEN1_B_UTEB_S 6 -/* MCPWM_GEN1_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEA 0x00000003 -#define MCPWM_GEN1_B_UTEA_M ((MCPWM_GEN1_B_UTEA_V)<<(MCPWM_GEN1_B_UTEA_S)) -#define MCPWM_GEN1_B_UTEA_V 0x3 -#define MCPWM_GEN1_B_UTEA_S 4 -/* MCPWM_GEN1_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEP 0x00000003 -#define MCPWM_GEN1_B_UTEP_M ((MCPWM_GEN1_B_UTEP_V)<<(MCPWM_GEN1_B_UTEP_S)) -#define MCPWM_GEN1_B_UTEP_V 0x3 -#define MCPWM_GEN1_B_UTEP_S 2 -/* MCPWM_GEN1_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEZ 0x00000003 -#define MCPWM_GEN1_B_UTEZ_M ((MCPWM_GEN1_B_UTEZ_V)<<(MCPWM_GEN1_B_UTEZ_S)) -#define MCPWM_GEN1_B_UTEZ_V 0x3 +/** MCPWM_GEN1_B_REG register + * Actions triggered by events on PWM1B + */ +#define MCPWM_GEN1_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8c) +/** MCPWM_GEN1_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEZ 0x00000003U +#define MCPWM_GEN1_B_UTEZ_M (MCPWM_GEN1_B_UTEZ_V << MCPWM_GEN1_B_UTEZ_S) +#define MCPWM_GEN1_B_UTEZ_V 0x00000003U #define MCPWM_GEN1_B_UTEZ_S 0 +/** MCPWM_GEN1_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEP 0x00000003U +#define MCPWM_GEN1_B_UTEP_M (MCPWM_GEN1_B_UTEP_V << MCPWM_GEN1_B_UTEP_S) +#define MCPWM_GEN1_B_UTEP_V 0x00000003U +#define MCPWM_GEN1_B_UTEP_S 2 +/** MCPWM_GEN1_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEA 0x00000003U +#define MCPWM_GEN1_B_UTEA_M (MCPWM_GEN1_B_UTEA_V << MCPWM_GEN1_B_UTEA_S) +#define MCPWM_GEN1_B_UTEA_V 0x00000003U +#define MCPWM_GEN1_B_UTEA_S 4 +/** MCPWM_GEN1_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEB 0x00000003U +#define MCPWM_GEN1_B_UTEB_M (MCPWM_GEN1_B_UTEB_V << MCPWM_GEN1_B_UTEB_S) +#define MCPWM_GEN1_B_UTEB_V 0x00000003U +#define MCPWM_GEN1_B_UTEB_S 6 +/** MCPWM_GEN1_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT0 0x00000003U +#define MCPWM_GEN1_B_UT0_M (MCPWM_GEN1_B_UT0_V << MCPWM_GEN1_B_UT0_S) +#define MCPWM_GEN1_B_UT0_V 0x00000003U +#define MCPWM_GEN1_B_UT0_S 8 +/** MCPWM_GEN1_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT1 0x00000003U +#define MCPWM_GEN1_B_UT1_M (MCPWM_GEN1_B_UT1_V << MCPWM_GEN1_B_UT1_S) +#define MCPWM_GEN1_B_UT1_V 0x00000003U +#define MCPWM_GEN1_B_UT1_S 10 +/** MCPWM_GEN1_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEZ 0x00000003U +#define MCPWM_GEN1_B_DTEZ_M (MCPWM_GEN1_B_DTEZ_V << MCPWM_GEN1_B_DTEZ_S) +#define MCPWM_GEN1_B_DTEZ_V 0x00000003U +#define MCPWM_GEN1_B_DTEZ_S 12 +/** MCPWM_GEN1_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEP 0x00000003U +#define MCPWM_GEN1_B_DTEP_M (MCPWM_GEN1_B_DTEP_V << MCPWM_GEN1_B_DTEP_S) +#define MCPWM_GEN1_B_DTEP_V 0x00000003U +#define MCPWM_GEN1_B_DTEP_S 14 +/** MCPWM_GEN1_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEA 0x00000003U +#define MCPWM_GEN1_B_DTEA_M (MCPWM_GEN1_B_DTEA_V << MCPWM_GEN1_B_DTEA_S) +#define MCPWM_GEN1_B_DTEA_V 0x00000003U +#define MCPWM_GEN1_B_DTEA_S 16 +/** MCPWM_GEN1_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEB 0x00000003U +#define MCPWM_GEN1_B_DTEB_M (MCPWM_GEN1_B_DTEB_V << MCPWM_GEN1_B_DTEB_S) +#define MCPWM_GEN1_B_DTEB_V 0x00000003U +#define MCPWM_GEN1_B_DTEB_S 18 +/** MCPWM_GEN1_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT0 0x00000003U +#define MCPWM_GEN1_B_DT0_M (MCPWM_GEN1_B_DT0_V << MCPWM_GEN1_B_DT0_S) +#define MCPWM_GEN1_B_DT0_V 0x00000003U +#define MCPWM_GEN1_B_DT0_S 20 +/** MCPWM_GEN1_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT1 0x00000003U +#define MCPWM_GEN1_B_DT1_M (MCPWM_GEN1_B_DT1_V << MCPWM_GEN1_B_DT1_S) +#define MCPWM_GEN1_B_DT1_V 0x00000003U +#define MCPWM_GEN1_B_DT1_S 22 -#define MCPWM_DB1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x90) -/* MCPWM_DB1_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_CLK_SEL (BIT(17)) -#define MCPWM_DB1_CLK_SEL_M (BIT(17)) -#define MCPWM_DB1_CLK_SEL_V 0x1 -#define MCPWM_DB1_CLK_SEL_S 17 -/* MCPWM_DB1_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB1_B_OUTBYPASS (BIT(16)) -#define MCPWM_DB1_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DB1_B_OUTBYPASS_V 0x1 -#define MCPWM_DB1_B_OUTBYPASS_S 16 -/* MCPWM_DB1_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB1_A_OUTBYPASS (BIT(15)) -#define MCPWM_DB1_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DB1_A_OUTBYPASS_V 0x1 -#define MCPWM_DB1_A_OUTBYPASS_S 15 -/* MCPWM_DB1_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED_OUTINVERT (BIT(14)) -#define MCPWM_DB1_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DB1_FED_OUTINVERT_V 0x1 -#define MCPWM_DB1_FED_OUTINVERT_S 14 -/* MCPWM_DB1_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED_OUTINVERT (BIT(13)) -#define MCPWM_DB1_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DB1_RED_OUTINVERT_V 0x1 -#define MCPWM_DB1_RED_OUTINVERT_S 13 -/* MCPWM_DB1_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED_INSEL (BIT(12)) -#define MCPWM_DB1_FED_INSEL_M (BIT(12)) -#define MCPWM_DB1_FED_INSEL_V 0x1 -#define MCPWM_DB1_FED_INSEL_S 12 -/* MCPWM_DB1_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED_INSEL (BIT(11)) -#define MCPWM_DB1_RED_INSEL_M (BIT(11)) -#define MCPWM_DB1_RED_INSEL_V 0x1 -#define MCPWM_DB1_RED_INSEL_S 11 -/* MCPWM_DB1_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_B_OUTSWAP (BIT(10)) -#define MCPWM_DB1_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DB1_B_OUTSWAP_V 0x1 -#define MCPWM_DB1_B_OUTSWAP_S 10 -/* MCPWM_DB1_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_A_OUTSWAP (BIT(9)) -#define MCPWM_DB1_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DB1_A_OUTSWAP_V 0x1 -#define MCPWM_DB1_A_OUTSWAP_S 9 -/* MCPWM_DB1_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_DEB_MODE (BIT(8)) -#define MCPWM_DB1_DEB_MODE_M (BIT(8)) -#define MCPWM_DB1_DEB_MODE_V 0x1 -#define MCPWM_DB1_DEB_MODE_S 8 -/* MCPWM_DB1_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED_UPMETHOD 0x0000000F -#define MCPWM_DB1_RED_UPMETHOD_M ((MCPWM_DB1_RED_UPMETHOD_V)<<(MCPWM_DB1_RED_UPMETHOD_S)) -#define MCPWM_DB1_RED_UPMETHOD_V 0xF -#define MCPWM_DB1_RED_UPMETHOD_S 4 -/* MCPWM_DB1_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED_UPMETHOD 0x0000000F -#define MCPWM_DB1_FED_UPMETHOD_M ((MCPWM_DB1_FED_UPMETHOD_V)<<(MCPWM_DB1_FED_UPMETHOD_S)) -#define MCPWM_DB1_FED_UPMETHOD_V 0xF -#define MCPWM_DB1_FED_UPMETHOD_S 0 +/** MCPWM_DT1_CFG_REG register + * PWM generator 1 dead time type selection and configuration + */ +#define MCPWM_DT1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x90) +/** MCPWM_DT1_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_FED_UPMETHOD_M (MCPWM_DT1_FED_UPMETHOD_V << MCPWM_DT1_FED_UPMETHOD_S) +#define MCPWM_DT1_FED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT1_FED_UPMETHOD_S 0 +/** MCPWM_DT1_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_M (MCPWM_DT1_RED_UPMETHOD_V << MCPWM_DT1_RED_UPMETHOD_S) +#define MCPWM_DT1_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_S 4 +/** MCPWM_DT1_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT1_DEB_MODE (BIT(8)) +#define MCPWM_DT1_DEB_MODE_M (MCPWM_DT1_DEB_MODE_V << MCPWM_DT1_DEB_MODE_S) +#define MCPWM_DT1_DEB_MODE_V 0x00000001U +#define MCPWM_DT1_DEB_MODE_S 8 +/** MCPWM_DT1_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT1_A_OUTSWAP (BIT(9)) +#define MCPWM_DT1_A_OUTSWAP_M (MCPWM_DT1_A_OUTSWAP_V << MCPWM_DT1_A_OUTSWAP_S) +#define MCPWM_DT1_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_A_OUTSWAP_S 9 +/** MCPWM_DT1_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT1_B_OUTSWAP (BIT(10)) +#define MCPWM_DT1_B_OUTSWAP_M (MCPWM_DT1_B_OUTSWAP_V << MCPWM_DT1_B_OUTSWAP_S) +#define MCPWM_DT1_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_B_OUTSWAP_S 10 +/** MCPWM_DT1_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT1_RED_INSEL (BIT(11)) +#define MCPWM_DT1_RED_INSEL_M (MCPWM_DT1_RED_INSEL_V << MCPWM_DT1_RED_INSEL_S) +#define MCPWM_DT1_RED_INSEL_V 0x00000001U +#define MCPWM_DT1_RED_INSEL_S 11 +/** MCPWM_DT1_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT1_FED_INSEL (BIT(12)) +#define MCPWM_DT1_FED_INSEL_M (MCPWM_DT1_FED_INSEL_V << MCPWM_DT1_FED_INSEL_S) +#define MCPWM_DT1_FED_INSEL_V 0x00000001U +#define MCPWM_DT1_FED_INSEL_S 12 +/** MCPWM_DT1_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT1_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT1_RED_OUTINVERT_M (MCPWM_DT1_RED_OUTINVERT_V << MCPWM_DT1_RED_OUTINVERT_S) +#define MCPWM_DT1_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_RED_OUTINVERT_S 13 +/** MCPWM_DT1_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT1_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT1_FED_OUTINVERT_M (MCPWM_DT1_FED_OUTINVERT_V << MCPWM_DT1_FED_OUTINVERT_S) +#define MCPWM_DT1_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_FED_OUTINVERT_S 14 +/** MCPWM_DT1_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT1_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT1_A_OUTBYPASS_M (MCPWM_DT1_A_OUTBYPASS_V << MCPWM_DT1_A_OUTBYPASS_S) +#define MCPWM_DT1_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_A_OUTBYPASS_S 15 +/** MCPWM_DT1_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT1_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT1_B_OUTBYPASS_M (MCPWM_DT1_B_OUTBYPASS_V << MCPWM_DT1_B_OUTBYPASS_S) +#define MCPWM_DT1_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_B_OUTBYPASS_S 16 +/** MCPWM_DT1_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT1_CLK_SEL (BIT(17)) +#define MCPWM_DT1_CLK_SEL_M (MCPWM_DT1_CLK_SEL_V << MCPWM_DT1_CLK_SEL_S) +#define MCPWM_DT1_CLK_SEL_V 0x00000001U +#define MCPWM_DT1_CLK_SEL_S 17 -#define MCPWM_DB1_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x94) -/* MCPWM_DB1_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED 0x0000FFFF -#define MCPWM_DB1_FED_M ((MCPWM_DB1_FED_V)<<(MCPWM_DB1_FED_S)) -#define MCPWM_DB1_FED_V 0xFFFF -#define MCPWM_DB1_FED_S 0 +/** MCPWM_DT1_FED_CFG_REG register + * PWM generator 1 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT1_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x94) +/** MCPWM_DT1_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT1_FED 0x0000FFFFU +#define MCPWM_DT1_FED_M (MCPWM_DT1_FED_V << MCPWM_DT1_FED_S) +#define MCPWM_DT1_FED_V 0x0000FFFFU +#define MCPWM_DT1_FED_S 0 -#define MCPWM_DB1_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x98) -/* MCPWM_DB1_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED 0x0000FFFF -#define MCPWM_DB1_RED_M ((MCPWM_DB1_RED_V)<<(MCPWM_DB1_RED_S)) -#define MCPWM_DB1_RED_V 0xFFFF -#define MCPWM_DB1_RED_S 0 +/** MCPWM_DT1_RED_CFG_REG register + * PWM generator 1 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT1_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x98) +/** MCPWM_DT1_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT1_RED 0x0000FFFFU +#define MCPWM_DT1_RED_M (MCPWM_DT1_RED_V << MCPWM_DT1_RED_S) +#define MCPWM_DT1_RED_V 0x0000FFFFU +#define MCPWM_DT1_RED_S 0 -#define MCPWM_CHOPPER1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x9C) -/* MCPWM_CHOPPER1_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_IN_INVERT (BIT(13)) -#define MCPWM_CHOPPER1_IN_INVERT_M (BIT(13)) -#define MCPWM_CHOPPER1_IN_INVERT_V 0x1 -#define MCPWM_CHOPPER1_IN_INVERT_S 13 -/* MCPWM_CHOPPER1_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_OUT_INVERT (BIT(12)) -#define MCPWM_CHOPPER1_OUT_INVERT_M (BIT(12)) -#define MCPWM_CHOPPER1_OUT_INVERT_V 0x1 -#define MCPWM_CHOPPER1_OUT_INVERT_S 12 -/* MCPWM_CHOPPER1_OSHTWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_OSHTWTH 0x0000000F -#define MCPWM_CHOPPER1_OSHTWTH_M ((MCPWM_CHOPPER1_OSHTWTH_V)<<(MCPWM_CHOPPER1_OSHTWTH_S)) -#define MCPWM_CHOPPER1_OSHTWTH_V 0xF -#define MCPWM_CHOPPER1_OSHTWTH_S 8 -/* MCPWM_CHOPPER1_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_DUTY 0x00000007 -#define MCPWM_CHOPPER1_DUTY_M ((MCPWM_CHOPPER1_DUTY_V)<<(MCPWM_CHOPPER1_DUTY_S)) -#define MCPWM_CHOPPER1_DUTY_V 0x7 -#define MCPWM_CHOPPER1_DUTY_S 5 -/* MCPWM_CHOPPER1_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_PRESCALE 0x0000000F -#define MCPWM_CHOPPER1_PRESCALE_M ((MCPWM_CHOPPER1_PRESCALE_V)<<(MCPWM_CHOPPER1_PRESCALE_S)) -#define MCPWM_CHOPPER1_PRESCALE_V 0xF -#define MCPWM_CHOPPER1_PRESCALE_S 1 -/* MCPWM_CHOPPER1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_EN (BIT(0)) -#define MCPWM_CHOPPER1_EN_M (BIT(0)) -#define MCPWM_CHOPPER1_EN_V 0x1 -#define MCPWM_CHOPPER1_EN_S 0 +/** MCPWM_CARRIER1_CFG_REG register + * PWM generator 1 carrier enable and configuratoin + */ +#define MCPWM_CARRIER1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x9c) +/** MCPWM_CARRIER1_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier1 function is enabled. When cleared, carrier1 is bypassed + */ +#define MCPWM_CARRIER1_EN (BIT(0)) +#define MCPWM_CARRIER1_EN_M (MCPWM_CARRIER1_EN_V << MCPWM_CARRIER1_EN_S) +#define MCPWM_CARRIER1_EN_V 0x00000001U +#define MCPWM_CARRIER1_EN_S 0 +/** MCPWM_CARRIER1_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier1 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER1_PRESCALE 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_M (MCPWM_CARRIER1_PRESCALE_V << MCPWM_CARRIER1_PRESCALE_S) +#define MCPWM_CARRIER1_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_S 1 +/** MCPWM_CARRIER1_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER1_DUTY 0x00000007U +#define MCPWM_CARRIER1_DUTY_M (MCPWM_CARRIER1_DUTY_V << MCPWM_CARRIER1_DUTY_S) +#define MCPWM_CARRIER1_DUTY_V 0x00000007U +#define MCPWM_CARRIER1_DUTY_S 5 +/** MCPWM_CARRIER1_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER1_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_M (MCPWM_CARRIER1_OSHTWTH_V << MCPWM_CARRIER1_OSHTWTH_S) +#define MCPWM_CARRIER1_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_S 8 +/** MCPWM_CARRIER1_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER1_OUT_INVERT_M (MCPWM_CARRIER1_OUT_INVERT_V << MCPWM_CARRIER1_OUT_INVERT_S) +#define MCPWM_CARRIER1_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_OUT_INVERT_S 12 +/** MCPWM_CARRIER1_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER1_IN_INVERT_M (MCPWM_CARRIER1_IN_INVERT_V << MCPWM_CARRIER1_IN_INVERT_S) +#define MCPWM_CARRIER1_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_IN_INVERT_S 13 -#define MCPWM_TZ1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0xA0) -/* MCPWM_TZ1_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_OST_U 0x00000003 -#define MCPWM_TZ1_B_OST_U_M ((MCPWM_TZ1_B_OST_U_V)<<(MCPWM_TZ1_B_OST_U_S)) -#define MCPWM_TZ1_B_OST_U_V 0x3 -#define MCPWM_TZ1_B_OST_U_S 22 -/* MCPWM_TZ1_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_OST_D 0x00000003 -#define MCPWM_TZ1_B_OST_D_M ((MCPWM_TZ1_B_OST_D_V)<<(MCPWM_TZ1_B_OST_D_S)) -#define MCPWM_TZ1_B_OST_D_V 0x3 -#define MCPWM_TZ1_B_OST_D_S 20 -/* MCPWM_TZ1_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_CBC_U 0x00000003 -#define MCPWM_TZ1_B_CBC_U_M ((MCPWM_TZ1_B_CBC_U_V)<<(MCPWM_TZ1_B_CBC_U_S)) -#define MCPWM_TZ1_B_CBC_U_V 0x3 -#define MCPWM_TZ1_B_CBC_U_S 18 -/* MCPWM_TZ1_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_CBC_D 0x00000003 -#define MCPWM_TZ1_B_CBC_D_M ((MCPWM_TZ1_B_CBC_D_V)<<(MCPWM_TZ1_B_CBC_D_S)) -#define MCPWM_TZ1_B_CBC_D_V 0x3 -#define MCPWM_TZ1_B_CBC_D_S 16 -/* MCPWM_TZ1_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_OST_U 0x00000003 -#define MCPWM_TZ1_A_OST_U_M ((MCPWM_TZ1_A_OST_U_V)<<(MCPWM_TZ1_A_OST_U_S)) -#define MCPWM_TZ1_A_OST_U_V 0x3 -#define MCPWM_TZ1_A_OST_U_S 14 -/* MCPWM_TZ1_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_OST_D 0x00000003 -#define MCPWM_TZ1_A_OST_D_M ((MCPWM_TZ1_A_OST_D_V)<<(MCPWM_TZ1_A_OST_D_S)) -#define MCPWM_TZ1_A_OST_D_V 0x3 -#define MCPWM_TZ1_A_OST_D_S 12 -/* MCPWM_TZ1_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_CBC_U 0x00000003 -#define MCPWM_TZ1_A_CBC_U_M ((MCPWM_TZ1_A_CBC_U_V)<<(MCPWM_TZ1_A_CBC_U_S)) -#define MCPWM_TZ1_A_CBC_U_V 0x3 -#define MCPWM_TZ1_A_CBC_U_S 10 -/* MCPWM_TZ1_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_CBC_D 0x00000003 -#define MCPWM_TZ1_A_CBC_D_M ((MCPWM_TZ1_A_CBC_D_V)<<(MCPWM_TZ1_A_CBC_D_S)) -#define MCPWM_TZ1_A_CBC_D_V 0x3 -#define MCPWM_TZ1_A_CBC_D_S 8 -/* MCPWM_TZ1_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F0_OST (BIT(7)) -#define MCPWM_TZ1_F0_OST_M (BIT(7)) -#define MCPWM_TZ1_F0_OST_V 0x1 -#define MCPWM_TZ1_F0_OST_S 7 -/* MCPWM_TZ1_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F1_OST (BIT(6)) -#define MCPWM_TZ1_F1_OST_M (BIT(6)) -#define MCPWM_TZ1_F1_OST_V 0x1 -#define MCPWM_TZ1_F1_OST_S 6 -/* MCPWM_TZ1_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F2_OST (BIT(5)) -#define MCPWM_TZ1_F2_OST_M (BIT(5)) -#define MCPWM_TZ1_F2_OST_V 0x1 -#define MCPWM_TZ1_F2_OST_S 5 -/* MCPWM_TZ1_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_SW_OST (BIT(4)) -#define MCPWM_TZ1_SW_OST_M (BIT(4)) -#define MCPWM_TZ1_SW_OST_V 0x1 -#define MCPWM_TZ1_SW_OST_S 4 -/* MCPWM_TZ1_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F0_CBC (BIT(3)) -#define MCPWM_TZ1_F0_CBC_M (BIT(3)) -#define MCPWM_TZ1_F0_CBC_V 0x1 -#define MCPWM_TZ1_F0_CBC_S 3 -/* MCPWM_TZ1_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F1_CBC (BIT(2)) -#define MCPWM_TZ1_F1_CBC_M (BIT(2)) -#define MCPWM_TZ1_F1_CBC_V 0x1 -#define MCPWM_TZ1_F1_CBC_S 2 -/* MCPWM_TZ1_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F2_CBC (BIT(1)) -#define MCPWM_TZ1_F2_CBC_M (BIT(1)) -#define MCPWM_TZ1_F2_CBC_V 0x1 -#define MCPWM_TZ1_F2_CBC_S 1 -/* MCPWM_TZ1_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_SW_CBC (BIT(0)) -#define MCPWM_TZ1_SW_CBC_M (BIT(0)) -#define MCPWM_TZ1_SW_CBC_V 0x1 -#define MCPWM_TZ1_SW_CBC_S 0 +/** MCPWM_FH1_CFG0_REG register + * Actions on PWM1A and PWM1B trip events + */ +#define MCPWM_FH1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa0) +/** MCPWM_FH1_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_CBC (BIT(0)) +#define MCPWM_FH1_SW_CBC_M (MCPWM_FH1_SW_CBC_V << MCPWM_FH1_SW_CBC_S) +#define MCPWM_FH1_SW_CBC_V 0x00000001U +#define MCPWM_FH1_SW_CBC_S 0 +/** MCPWM_FH1_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_CBC (BIT(1)) +#define MCPWM_FH1_F2_CBC_M (MCPWM_FH1_F2_CBC_V << MCPWM_FH1_F2_CBC_S) +#define MCPWM_FH1_F2_CBC_V 0x00000001U +#define MCPWM_FH1_F2_CBC_S 1 +/** MCPWM_FH1_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_CBC (BIT(2)) +#define MCPWM_FH1_F1_CBC_M (MCPWM_FH1_F1_CBC_V << MCPWM_FH1_F1_CBC_S) +#define MCPWM_FH1_F1_CBC_V 0x00000001U +#define MCPWM_FH1_F1_CBC_S 2 +/** MCPWM_FH1_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_CBC (BIT(3)) +#define MCPWM_FH1_F0_CBC_M (MCPWM_FH1_F0_CBC_V << MCPWM_FH1_F0_CBC_S) +#define MCPWM_FH1_F0_CBC_V 0x00000001U +#define MCPWM_FH1_F0_CBC_S 3 +/** MCPWM_FH1_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_OST (BIT(4)) +#define MCPWM_FH1_SW_OST_M (MCPWM_FH1_SW_OST_V << MCPWM_FH1_SW_OST_S) +#define MCPWM_FH1_SW_OST_V 0x00000001U +#define MCPWM_FH1_SW_OST_S 4 +/** MCPWM_FH1_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_OST (BIT(5)) +#define MCPWM_FH1_F2_OST_M (MCPWM_FH1_F2_OST_V << MCPWM_FH1_F2_OST_S) +#define MCPWM_FH1_F2_OST_V 0x00000001U +#define MCPWM_FH1_F2_OST_S 5 +/** MCPWM_FH1_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_OST (BIT(6)) +#define MCPWM_FH1_F1_OST_M (MCPWM_FH1_F1_OST_V << MCPWM_FH1_F1_OST_S) +#define MCPWM_FH1_F1_OST_V 0x00000001U +#define MCPWM_FH1_F1_OST_S 6 +/** MCPWM_FH1_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_OST (BIT(7)) +#define MCPWM_FH1_F0_OST_M (MCPWM_FH1_F0_OST_V << MCPWM_FH1_F0_OST_S) +#define MCPWM_FH1_F0_OST_V 0x00000001U +#define MCPWM_FH1_F0_OST_S 7 +/** MCPWM_FH1_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_D 0x00000003U +#define MCPWM_FH1_A_CBC_D_M (MCPWM_FH1_A_CBC_D_V << MCPWM_FH1_A_CBC_D_S) +#define MCPWM_FH1_A_CBC_D_V 0x00000003U +#define MCPWM_FH1_A_CBC_D_S 8 +/** MCPWM_FH1_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_U 0x00000003U +#define MCPWM_FH1_A_CBC_U_M (MCPWM_FH1_A_CBC_U_V << MCPWM_FH1_A_CBC_U_S) +#define MCPWM_FH1_A_CBC_U_V 0x00000003U +#define MCPWM_FH1_A_CBC_U_S 10 +/** MCPWM_FH1_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is decreasing. 0: + * do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_D 0x00000003U +#define MCPWM_FH1_A_OST_D_M (MCPWM_FH1_A_OST_D_V << MCPWM_FH1_A_OST_D_S) +#define MCPWM_FH1_A_OST_D_V 0x00000003U +#define MCPWM_FH1_A_OST_D_S 12 +/** MCPWM_FH1_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_U 0x00000003U +#define MCPWM_FH1_A_OST_U_M (MCPWM_FH1_A_OST_U_V << MCPWM_FH1_A_OST_U_S) +#define MCPWM_FH1_A_OST_U_V 0x00000003U +#define MCPWM_FH1_A_OST_U_S 14 +/** MCPWM_FH1_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_D 0x00000003U +#define MCPWM_FH1_B_CBC_D_M (MCPWM_FH1_B_CBC_D_V << MCPWM_FH1_B_CBC_D_S) +#define MCPWM_FH1_B_CBC_D_V 0x00000003U +#define MCPWM_FH1_B_CBC_D_S 16 +/** MCPWM_FH1_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_U 0x00000003U +#define MCPWM_FH1_B_CBC_U_M (MCPWM_FH1_B_CBC_U_V << MCPWM_FH1_B_CBC_U_S) +#define MCPWM_FH1_B_CBC_U_V 0x00000003U +#define MCPWM_FH1_B_CBC_U_S 18 +/** MCPWM_FH1_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_D 0x00000003U +#define MCPWM_FH1_B_OST_D_M (MCPWM_FH1_B_OST_D_V << MCPWM_FH1_B_OST_D_S) +#define MCPWM_FH1_B_OST_D_V 0x00000003U +#define MCPWM_FH1_B_OST_D_S 20 +/** MCPWM_FH1_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_U 0x00000003U +#define MCPWM_FH1_B_OST_U_M (MCPWM_FH1_B_OST_U_V << MCPWM_FH1_B_OST_U_S) +#define MCPWM_FH1_B_OST_U_V 0x00000003U +#define MCPWM_FH1_B_OST_U_S 22 -#define MCPWM_TZ1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0xA4) -/* MCPWM_TZ1_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: a toggle trigger a oneshot tripping.*/ -#define MCPWM_TZ1_FORCE_OST (BIT(4)) -#define MCPWM_TZ1_FORCE_OST_M (BIT(4)) -#define MCPWM_TZ1_FORCE_OST_V 0x1 -#define MCPWM_TZ1_FORCE_OST_S 4 -/* MCPWM_TZ1_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle trigger a cycle-by-cycle tripping.*/ -#define MCPWM_TZ1_FORCE_CBC (BIT(3)) -#define MCPWM_TZ1_FORCE_CBC_M (BIT(3)) -#define MCPWM_TZ1_FORCE_CBC_V 0x1 -#define MCPWM_TZ1_FORCE_CBC_S 3 -/* MCPWM_TZ1_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: tez, bit1: tep.*/ -#define MCPWM_TZ1_CBCPULSE 0x00000003 -#define MCPWM_TZ1_CBCPULSE_M ((MCPWM_TZ1_CBCPULSE_V)<<(MCPWM_TZ1_CBCPULSE_S)) -#define MCPWM_TZ1_CBCPULSE_V 0x3 -#define MCPWM_TZ1_CBCPULSE_S 1 -/* MCPWM_TZ1_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: a toggle will clear oneshot tripping.*/ -#define MCPWM_TZ1_CLR_OST (BIT(0)) -#define MCPWM_TZ1_CLR_OST_M (BIT(0)) -#define MCPWM_TZ1_CLR_OST_V 0x1 -#define MCPWM_TZ1_CLR_OST_S 0 +/** MCPWM_FH1_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa4) +/** MCPWM_FH1_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH1_CLR_OST (BIT(0)) +#define MCPWM_FH1_CLR_OST_M (MCPWM_FH1_CLR_OST_V << MCPWM_FH1_CLR_OST_S) +#define MCPWM_FH1_CLR_OST_V 0x00000001U +#define MCPWM_FH1_CLR_OST_S 0 +/** MCPWM_FH1_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH1_CBCPULSE 0x00000003U +#define MCPWM_FH1_CBCPULSE_M (MCPWM_FH1_CBCPULSE_V << MCPWM_FH1_CBCPULSE_S) +#define MCPWM_FH1_CBCPULSE_V 0x00000003U +#define MCPWM_FH1_CBCPULSE_S 1 +/** MCPWM_FH1_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH1_FORCE_CBC (BIT(3)) +#define MCPWM_FH1_FORCE_CBC_M (MCPWM_FH1_FORCE_CBC_V << MCPWM_FH1_FORCE_CBC_S) +#define MCPWM_FH1_FORCE_CBC_V 0x00000001U +#define MCPWM_FH1_FORCE_CBC_S 3 +/** MCPWM_FH1_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH1_FORCE_OST (BIT(4)) +#define MCPWM_FH1_FORCE_OST_M (MCPWM_FH1_FORCE_OST_V << MCPWM_FH1_FORCE_OST_S) +#define MCPWM_FH1_FORCE_OST_V 0x00000001U +#define MCPWM_FH1_FORCE_OST_S 4 -#define MCPWM_TZ1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0xA8) -/* MCPWM_TZ1_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_ON (BIT(1)) -#define MCPWM_TZ1_OST_ON_M (BIT(1)) -#define MCPWM_TZ1_OST_ON_V 0x1 -#define MCPWM_TZ1_OST_ON_S 1 -/* MCPWM_TZ1_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_ON (BIT(0)) -#define MCPWM_TZ1_CBC_ON_M (BIT(0)) -#define MCPWM_TZ1_CBC_ON_V 0x1 -#define MCPWM_TZ1_CBC_ON_S 0 +/** MCPWM_FH1_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa8) +/** MCPWM_FH1_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH1_CBC_ON (BIT(0)) +#define MCPWM_FH1_CBC_ON_M (MCPWM_FH1_CBC_ON_V << MCPWM_FH1_CBC_ON_S) +#define MCPWM_FH1_CBC_ON_V 0x00000001U +#define MCPWM_FH1_CBC_ON_S 0 +/** MCPWM_FH1_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH1_OST_ON (BIT(1)) +#define MCPWM_FH1_OST_ON_M (MCPWM_FH1_OST_ON_V << MCPWM_FH1_OST_ON_S) +#define MCPWM_FH1_OST_ON_V 0x00000001U +#define MCPWM_FH1_OST_ON_S 1 -#define MCPWM_CMPR2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xAC) -/* MCPWM_CMPR2_B_SHDW_FULL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_B_SHDW_FULL (BIT(9)) -#define MCPWM_CMPR2_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_CMPR2_B_SHDW_FULL_V 0x1 -#define MCPWM_CMPR2_B_SHDW_FULL_S 9 -/* MCPWM_CMPR2_A_SHDW_FULL : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_A_SHDW_FULL (BIT(8)) -#define MCPWM_CMPR2_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_CMPR2_A_SHDW_FULL_V 0x1 -#define MCPWM_CMPR2_A_SHDW_FULL_S 8 -/* MCPWM_CMPR2_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR2_B_UPMETHOD 0x0000000F -#define MCPWM_CMPR2_B_UPMETHOD_M ((MCPWM_CMPR2_B_UPMETHOD_V)<<(MCPWM_CMPR2_B_UPMETHOD_S)) -#define MCPWM_CMPR2_B_UPMETHOD_V 0xF -#define MCPWM_CMPR2_B_UPMETHOD_S 4 -/* MCPWM_CMPR2_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR2_A_UPMETHOD 0x0000000F -#define MCPWM_CMPR2_A_UPMETHOD_M ((MCPWM_CMPR2_A_UPMETHOD_V)<<(MCPWM_CMPR2_A_UPMETHOD_S)) -#define MCPWM_CMPR2_A_UPMETHOD_V 0xF -#define MCPWM_CMPR2_A_UPMETHOD_S 0 +/** MCPWM_GEN2_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN2_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xac) +/** MCPWM_GEN2_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_A_UPMETHOD_M (MCPWM_GEN2_A_UPMETHOD_V << MCPWM_GEN2_A_UPMETHOD_S) +#define MCPWM_GEN2_A_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN2_A_UPMETHOD_S 0 +/** MCPWM_GEN2_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 2 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_M (MCPWM_GEN2_B_UPMETHOD_V << MCPWM_GEN2_B_UPMETHOD_S) +#define MCPWM_GEN2_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_S 4 +/** MCPWM_GEN2_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN2_A_SHDW_FULL_M (MCPWM_GEN2_A_SHDW_FULL_V << MCPWM_GEN2_A_SHDW_FULL_S) +#define MCPWM_GEN2_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_A_SHDW_FULL_S 8 +/** MCPWM_GEN2_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN2_B_SHDW_FULL_M (MCPWM_GEN2_B_SHDW_FULL_V << MCPWM_GEN2_B_SHDW_FULL_S) +#define MCPWM_GEN2_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_B_SHDW_FULL_S 9 -#define MCPWM_CMPR2_VALUE0_REG(i) (REG_MCPWM_BASE(i) + 0xB0) -/* MCPWM_CMPR2_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_A 0x0000FFFF -#define MCPWM_CMPR2_A_M ((MCPWM_CMPR2_A_V)<<(MCPWM_CMPR2_A_S)) -#define MCPWM_CMPR2_A_V 0xFFFF -#define MCPWM_CMPR2_A_S 0 +/** MCPWM_GEN2_TSTMP_A_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb0) +/** MCPWM_GEN2_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp A's shadow register + */ +#define MCPWM_GEN2_A 0x0000FFFFU +#define MCPWM_GEN2_A_M (MCPWM_GEN2_A_V << MCPWM_GEN2_A_S) +#define MCPWM_GEN2_A_V 0x0000FFFFU +#define MCPWM_GEN2_A_S 0 -#define MCPWM_CMPR2_VALUE1_REG(i) (REG_MCPWM_BASE(i) + 0xB4) -/* MCPWM_CMPR2_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_B 0x0000FFFF -#define MCPWM_CMPR2_B_M ((MCPWM_CMPR2_B_V)<<(MCPWM_CMPR2_B_S)) -#define MCPWM_CMPR2_B_V 0xFFFF -#define MCPWM_CMPR2_B_S 0 +/** MCPWM_GEN2_TSTMP_B_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb4) +/** MCPWM_GEN2_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp B's shadow register + */ +#define MCPWM_GEN2_B 0x0000FFFFU +#define MCPWM_GEN2_B_M (MCPWM_GEN2_B_V << MCPWM_GEN2_B_S) +#define MCPWM_GEN2_B_V 0x0000FFFFU +#define MCPWM_GEN2_B_S 0 -#define MCPWM_GEN2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0xB8) -/* MCPWM_GEN2_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN2_T1_SEL 0x00000007 -#define MCPWM_GEN2_T1_SEL_M ((MCPWM_GEN2_T1_SEL_V)<<(MCPWM_GEN2_T1_SEL_S)) -#define MCPWM_GEN2_T1_SEL_V 0x7 -#define MCPWM_GEN2_T1_SEL_S 7 -/* MCPWM_GEN2_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN2_T0_SEL 0x00000007 -#define MCPWM_GEN2_T0_SEL_M ((MCPWM_GEN2_T0_SEL_V)<<(MCPWM_GEN2_T0_SEL_S)) -#define MCPWM_GEN2_T0_SEL_V 0x7 -#define MCPWM_GEN2_T0_SEL_S 4 -/* MCPWM_GEN2_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze.*/ -#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN2_CFG_UPMETHOD_M ((MCPWM_GEN2_CFG_UPMETHOD_V)<<(MCPWM_GEN2_CFG_UPMETHOD_S)) -#define MCPWM_GEN2_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN2_CFG0_REG register + * PWM generator 2 event T0 and T1 handling + */ +#define MCPWM_GEN2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb8) +/** MCPWM_GEN2_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2's active register of configuration. 0: + * immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1:sync;when bit3 is + * set to 1:disable the update. + */ +#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_CFG_UPMETHOD_M (MCPWM_GEN2_CFG_UPMETHOD_V << MCPWM_GEN2_CFG_UPMETHOD_S) +#define MCPWM_GEN2_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN2_CFG_UPMETHOD_S 0 +/** MCPWM_GEN2_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 2 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T0_SEL 0x00000007U +#define MCPWM_GEN2_T0_SEL_M (MCPWM_GEN2_T0_SEL_V << MCPWM_GEN2_T0_SEL_S) +#define MCPWM_GEN2_T0_SEL_V 0x00000007U +#define MCPWM_GEN2_T0_SEL_S 4 +/** MCPWM_GEN2_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 2 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T1_SEL 0x00000007U +#define MCPWM_GEN2_T1_SEL_M (MCPWM_GEN2_T1_SEL_V << MCPWM_GEN2_T1_SEL_S) +#define MCPWM_GEN2_T1_SEL_V 0x00000007U +#define MCPWM_GEN2_T1_SEL_S 7 -#define MCPWM_GEN2_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0xBC) -/* MCPWM_GEN2_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_NCIFORCE_MODE_M ((MCPWM_GEN2_B_NCIFORCE_MODE_V)<<(MCPWM_GEN2_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN2_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_V 0x1 -#define MCPWM_GEN2_B_NCIFORCE_S 13 -/* MCPWM_GEN2_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_NCIFORCE_MODE_M ((MCPWM_GEN2_A_NCIFORCE_MODE_V)<<(MCPWM_GEN2_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN2_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_V 0x1 -#define MCPWM_GEN2_A_NCIFORCE_S 10 -/* MCPWM_GEN2_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_M ((MCPWM_GEN2_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN2_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_M ((MCPWM_GEN2_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: free -ze.*/ -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN2_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN2_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN2_FORCE_REG register + * Permissives to force PWM2A and PWM2B outputs by software + */ +#define MCPWM_GEN2_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xbc) +/** MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 2. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M (MCPWM_GEN2_CNTUFORCE_UPMETHOD_V << MCPWM_GEN2_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN2_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN2_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM2A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_M (MCPWM_GEN2_A_CNTUFORCE_MODE_V << MCPWM_GEN2_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN2_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM2B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_M (MCPWM_GEN2_B_CNTUFORCE_MODE_V << MCPWM_GEN2_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN2_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN2_A_NCIFORCE_M (MCPWM_GEN2_A_NCIFORCE_V << MCPWM_GEN2_A_NCIFORCE_S) +#define MCPWM_GEN2_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_A_NCIFORCE_S 10 +/** MCPWM_GEN2_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM2A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_M (MCPWM_GEN2_A_NCIFORCE_MODE_V << MCPWM_GEN2_A_NCIFORCE_MODE_S) +#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN2_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN2_B_NCIFORCE_M (MCPWM_GEN2_B_NCIFORCE_V << MCPWM_GEN2_B_NCIFORCE_S) +#define MCPWM_GEN2_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_B_NCIFORCE_S 13 +/** MCPWM_GEN2_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM2B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_M (MCPWM_GEN2_B_NCIFORCE_MODE_V << MCPWM_GEN2_B_NCIFORCE_MODE_S) +#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN2_A_REG(i) (REG_MCPWM_BASE(i) + 0xC0) -/* MCPWM_GEN2_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: no change, 1: low, 2: high, 3: toggle.*/ -#define MCPWM_GEN2_A_DT1 0x00000003 -#define MCPWM_GEN2_A_DT1_M ((MCPWM_GEN2_A_DT1_V)<<(MCPWM_GEN2_A_DT1_S)) -#define MCPWM_GEN2_A_DT1_V 0x3 -#define MCPWM_GEN2_A_DT1_S 22 -/* MCPWM_GEN2_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DT0 0x00000003 -#define MCPWM_GEN2_A_DT0_M ((MCPWM_GEN2_A_DT0_V)<<(MCPWM_GEN2_A_DT0_S)) -#define MCPWM_GEN2_A_DT0_V 0x3 -#define MCPWM_GEN2_A_DT0_S 20 -/* MCPWM_GEN2_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEB 0x00000003 -#define MCPWM_GEN2_A_DTEB_M ((MCPWM_GEN2_A_DTEB_V)<<(MCPWM_GEN2_A_DTEB_S)) -#define MCPWM_GEN2_A_DTEB_V 0x3 -#define MCPWM_GEN2_A_DTEB_S 18 -/* MCPWM_GEN2_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEA 0x00000003 -#define MCPWM_GEN2_A_DTEA_M ((MCPWM_GEN2_A_DTEA_V)<<(MCPWM_GEN2_A_DTEA_S)) -#define MCPWM_GEN2_A_DTEA_V 0x3 -#define MCPWM_GEN2_A_DTEA_S 16 -/* MCPWM_GEN2_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEP 0x00000003 -#define MCPWM_GEN2_A_DTEP_M ((MCPWM_GEN2_A_DTEP_V)<<(MCPWM_GEN2_A_DTEP_S)) -#define MCPWM_GEN2_A_DTEP_V 0x3 -#define MCPWM_GEN2_A_DTEP_S 14 -/* MCPWM_GEN2_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEZ 0x00000003 -#define MCPWM_GEN2_A_DTEZ_M ((MCPWM_GEN2_A_DTEZ_V)<<(MCPWM_GEN2_A_DTEZ_S)) -#define MCPWM_GEN2_A_DTEZ_V 0x3 -#define MCPWM_GEN2_A_DTEZ_S 12 -/* MCPWM_GEN2_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UT1 0x00000003 -#define MCPWM_GEN2_A_UT1_M ((MCPWM_GEN2_A_UT1_V)<<(MCPWM_GEN2_A_UT1_S)) -#define MCPWM_GEN2_A_UT1_V 0x3 -#define MCPWM_GEN2_A_UT1_S 10 -/* MCPWM_GEN2_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UT0 0x00000003 -#define MCPWM_GEN2_A_UT0_M ((MCPWM_GEN2_A_UT0_V)<<(MCPWM_GEN2_A_UT0_S)) -#define MCPWM_GEN2_A_UT0_V 0x3 -#define MCPWM_GEN2_A_UT0_S 8 -/* MCPWM_GEN2_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEB 0x00000003 -#define MCPWM_GEN2_A_UTEB_M ((MCPWM_GEN2_A_UTEB_V)<<(MCPWM_GEN2_A_UTEB_S)) -#define MCPWM_GEN2_A_UTEB_V 0x3 -#define MCPWM_GEN2_A_UTEB_S 6 -/* MCPWM_GEN2_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEA 0x00000003 -#define MCPWM_GEN2_A_UTEA_M ((MCPWM_GEN2_A_UTEA_V)<<(MCPWM_GEN2_A_UTEA_S)) -#define MCPWM_GEN2_A_UTEA_V 0x3 -#define MCPWM_GEN2_A_UTEA_S 4 -/* MCPWM_GEN2_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEP 0x00000003 -#define MCPWM_GEN2_A_UTEP_M ((MCPWM_GEN2_A_UTEP_V)<<(MCPWM_GEN2_A_UTEP_S)) -#define MCPWM_GEN2_A_UTEP_V 0x3 -#define MCPWM_GEN2_A_UTEP_S 2 -/* MCPWM_GEN2_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEZ 0x00000003 -#define MCPWM_GEN2_A_UTEZ_M ((MCPWM_GEN2_A_UTEZ_V)<<(MCPWM_GEN2_A_UTEZ_S)) -#define MCPWM_GEN2_A_UTEZ_V 0x3 +/** MCPWM_GEN2_A_REG register + * Actions triggered by events on PWM2A + */ +#define MCPWM_GEN2_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc0) +/** MCPWM_GEN2_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEZ 0x00000003U +#define MCPWM_GEN2_A_UTEZ_M (MCPWM_GEN2_A_UTEZ_V << MCPWM_GEN2_A_UTEZ_S) +#define MCPWM_GEN2_A_UTEZ_V 0x00000003U #define MCPWM_GEN2_A_UTEZ_S 0 +/** MCPWM_GEN2_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEP 0x00000003U +#define MCPWM_GEN2_A_UTEP_M (MCPWM_GEN2_A_UTEP_V << MCPWM_GEN2_A_UTEP_S) +#define MCPWM_GEN2_A_UTEP_V 0x00000003U +#define MCPWM_GEN2_A_UTEP_S 2 +/** MCPWM_GEN2_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEA 0x00000003U +#define MCPWM_GEN2_A_UTEA_M (MCPWM_GEN2_A_UTEA_V << MCPWM_GEN2_A_UTEA_S) +#define MCPWM_GEN2_A_UTEA_V 0x00000003U +#define MCPWM_GEN2_A_UTEA_S 4 +/** MCPWM_GEN2_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEB 0x00000003U +#define MCPWM_GEN2_A_UTEB_M (MCPWM_GEN2_A_UTEB_V << MCPWM_GEN2_A_UTEB_S) +#define MCPWM_GEN2_A_UTEB_V 0x00000003U +#define MCPWM_GEN2_A_UTEB_S 6 +/** MCPWM_GEN2_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT0 0x00000003U +#define MCPWM_GEN2_A_UT0_M (MCPWM_GEN2_A_UT0_V << MCPWM_GEN2_A_UT0_S) +#define MCPWM_GEN2_A_UT0_V 0x00000003U +#define MCPWM_GEN2_A_UT0_S 8 +/** MCPWM_GEN2_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT1 0x00000003U +#define MCPWM_GEN2_A_UT1_M (MCPWM_GEN2_A_UT1_V << MCPWM_GEN2_A_UT1_S) +#define MCPWM_GEN2_A_UT1_V 0x00000003U +#define MCPWM_GEN2_A_UT1_S 10 +/** MCPWM_GEN2_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEZ 0x00000003U +#define MCPWM_GEN2_A_DTEZ_M (MCPWM_GEN2_A_DTEZ_V << MCPWM_GEN2_A_DTEZ_S) +#define MCPWM_GEN2_A_DTEZ_V 0x00000003U +#define MCPWM_GEN2_A_DTEZ_S 12 +/** MCPWM_GEN2_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEP 0x00000003U +#define MCPWM_GEN2_A_DTEP_M (MCPWM_GEN2_A_DTEP_V << MCPWM_GEN2_A_DTEP_S) +#define MCPWM_GEN2_A_DTEP_V 0x00000003U +#define MCPWM_GEN2_A_DTEP_S 14 +/** MCPWM_GEN2_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEA 0x00000003U +#define MCPWM_GEN2_A_DTEA_M (MCPWM_GEN2_A_DTEA_V << MCPWM_GEN2_A_DTEA_S) +#define MCPWM_GEN2_A_DTEA_V 0x00000003U +#define MCPWM_GEN2_A_DTEA_S 16 +/** MCPWM_GEN2_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEB 0x00000003U +#define MCPWM_GEN2_A_DTEB_M (MCPWM_GEN2_A_DTEB_V << MCPWM_GEN2_A_DTEB_S) +#define MCPWM_GEN2_A_DTEB_V 0x00000003U +#define MCPWM_GEN2_A_DTEB_S 18 +/** MCPWM_GEN2_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT0 0x00000003U +#define MCPWM_GEN2_A_DT0_M (MCPWM_GEN2_A_DT0_V << MCPWM_GEN2_A_DT0_S) +#define MCPWM_GEN2_A_DT0_V 0x00000003U +#define MCPWM_GEN2_A_DT0_S 20 +/** MCPWM_GEN2_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT1 0x00000003U +#define MCPWM_GEN2_A_DT1_M (MCPWM_GEN2_A_DT1_V << MCPWM_GEN2_A_DT1_S) +#define MCPWM_GEN2_A_DT1_V 0x00000003U +#define MCPWM_GEN2_A_DT1_S 22 -#define MCPWM_GEN2_B_REG(i) (REG_MCPWM_BASE(i) + 0xC4) -/* MCPWM_GEN2_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DT1 0x00000003 -#define MCPWM_GEN2_B_DT1_M ((MCPWM_GEN2_B_DT1_V)<<(MCPWM_GEN2_B_DT1_S)) -#define MCPWM_GEN2_B_DT1_V 0x3 -#define MCPWM_GEN2_B_DT1_S 22 -/* MCPWM_GEN2_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DT0 0x00000003 -#define MCPWM_GEN2_B_DT0_M ((MCPWM_GEN2_B_DT0_V)<<(MCPWM_GEN2_B_DT0_S)) -#define MCPWM_GEN2_B_DT0_V 0x3 -#define MCPWM_GEN2_B_DT0_S 20 -/* MCPWM_GEN2_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEB 0x00000003 -#define MCPWM_GEN2_B_DTEB_M ((MCPWM_GEN2_B_DTEB_V)<<(MCPWM_GEN2_B_DTEB_S)) -#define MCPWM_GEN2_B_DTEB_V 0x3 -#define MCPWM_GEN2_B_DTEB_S 18 -/* MCPWM_GEN2_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEA 0x00000003 -#define MCPWM_GEN2_B_DTEA_M ((MCPWM_GEN2_B_DTEA_V)<<(MCPWM_GEN2_B_DTEA_S)) -#define MCPWM_GEN2_B_DTEA_V 0x3 -#define MCPWM_GEN2_B_DTEA_S 16 -/* MCPWM_GEN2_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEP 0x00000003 -#define MCPWM_GEN2_B_DTEP_M ((MCPWM_GEN2_B_DTEP_V)<<(MCPWM_GEN2_B_DTEP_S)) -#define MCPWM_GEN2_B_DTEP_V 0x3 -#define MCPWM_GEN2_B_DTEP_S 14 -/* MCPWM_GEN2_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEZ 0x00000003 -#define MCPWM_GEN2_B_DTEZ_M ((MCPWM_GEN2_B_DTEZ_V)<<(MCPWM_GEN2_B_DTEZ_S)) -#define MCPWM_GEN2_B_DTEZ_V 0x3 -#define MCPWM_GEN2_B_DTEZ_S 12 -/* MCPWM_GEN2_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UT1 0x00000003 -#define MCPWM_GEN2_B_UT1_M ((MCPWM_GEN2_B_UT1_V)<<(MCPWM_GEN2_B_UT1_S)) -#define MCPWM_GEN2_B_UT1_V 0x3 -#define MCPWM_GEN2_B_UT1_S 10 -/* MCPWM_GEN2_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UT0 0x00000003 -#define MCPWM_GEN2_B_UT0_M ((MCPWM_GEN2_B_UT0_V)<<(MCPWM_GEN2_B_UT0_S)) -#define MCPWM_GEN2_B_UT0_V 0x3 -#define MCPWM_GEN2_B_UT0_S 8 -/* MCPWM_GEN2_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEB 0x00000003 -#define MCPWM_GEN2_B_UTEB_M ((MCPWM_GEN2_B_UTEB_V)<<(MCPWM_GEN2_B_UTEB_S)) -#define MCPWM_GEN2_B_UTEB_V 0x3 -#define MCPWM_GEN2_B_UTEB_S 6 -/* MCPWM_GEN2_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEA 0x00000003 -#define MCPWM_GEN2_B_UTEA_M ((MCPWM_GEN2_B_UTEA_V)<<(MCPWM_GEN2_B_UTEA_S)) -#define MCPWM_GEN2_B_UTEA_V 0x3 -#define MCPWM_GEN2_B_UTEA_S 4 -/* MCPWM_GEN2_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEP 0x00000003 -#define MCPWM_GEN2_B_UTEP_M ((MCPWM_GEN2_B_UTEP_V)<<(MCPWM_GEN2_B_UTEP_S)) -#define MCPWM_GEN2_B_UTEP_V 0x3 -#define MCPWM_GEN2_B_UTEP_S 2 -/* MCPWM_GEN2_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEZ 0x00000003 -#define MCPWM_GEN2_B_UTEZ_M ((MCPWM_GEN2_B_UTEZ_V)<<(MCPWM_GEN2_B_UTEZ_S)) -#define MCPWM_GEN2_B_UTEZ_V 0x3 +/** MCPWM_GEN2_B_REG register + * Actions triggered by events on PWM2B + */ +#define MCPWM_GEN2_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc4) +/** MCPWM_GEN2_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEZ 0x00000003U +#define MCPWM_GEN2_B_UTEZ_M (MCPWM_GEN2_B_UTEZ_V << MCPWM_GEN2_B_UTEZ_S) +#define MCPWM_GEN2_B_UTEZ_V 0x00000003U #define MCPWM_GEN2_B_UTEZ_S 0 +/** MCPWM_GEN2_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEP 0x00000003U +#define MCPWM_GEN2_B_UTEP_M (MCPWM_GEN2_B_UTEP_V << MCPWM_GEN2_B_UTEP_S) +#define MCPWM_GEN2_B_UTEP_V 0x00000003U +#define MCPWM_GEN2_B_UTEP_S 2 +/** MCPWM_GEN2_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEA 0x00000003U +#define MCPWM_GEN2_B_UTEA_M (MCPWM_GEN2_B_UTEA_V << MCPWM_GEN2_B_UTEA_S) +#define MCPWM_GEN2_B_UTEA_V 0x00000003U +#define MCPWM_GEN2_B_UTEA_S 4 +/** MCPWM_GEN2_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEB 0x00000003U +#define MCPWM_GEN2_B_UTEB_M (MCPWM_GEN2_B_UTEB_V << MCPWM_GEN2_B_UTEB_S) +#define MCPWM_GEN2_B_UTEB_V 0x00000003U +#define MCPWM_GEN2_B_UTEB_S 6 +/** MCPWM_GEN2_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT0 0x00000003U +#define MCPWM_GEN2_B_UT0_M (MCPWM_GEN2_B_UT0_V << MCPWM_GEN2_B_UT0_S) +#define MCPWM_GEN2_B_UT0_V 0x00000003U +#define MCPWM_GEN2_B_UT0_S 8 +/** MCPWM_GEN2_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT1 0x00000003U +#define MCPWM_GEN2_B_UT1_M (MCPWM_GEN2_B_UT1_V << MCPWM_GEN2_B_UT1_S) +#define MCPWM_GEN2_B_UT1_V 0x00000003U +#define MCPWM_GEN2_B_UT1_S 10 +/** MCPWM_GEN2_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEZ 0x00000003U +#define MCPWM_GEN2_B_DTEZ_M (MCPWM_GEN2_B_DTEZ_V << MCPWM_GEN2_B_DTEZ_S) +#define MCPWM_GEN2_B_DTEZ_V 0x00000003U +#define MCPWM_GEN2_B_DTEZ_S 12 +/** MCPWM_GEN2_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEP 0x00000003U +#define MCPWM_GEN2_B_DTEP_M (MCPWM_GEN2_B_DTEP_V << MCPWM_GEN2_B_DTEP_S) +#define MCPWM_GEN2_B_DTEP_V 0x00000003U +#define MCPWM_GEN2_B_DTEP_S 14 +/** MCPWM_GEN2_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEA 0x00000003U +#define MCPWM_GEN2_B_DTEA_M (MCPWM_GEN2_B_DTEA_V << MCPWM_GEN2_B_DTEA_S) +#define MCPWM_GEN2_B_DTEA_V 0x00000003U +#define MCPWM_GEN2_B_DTEA_S 16 +/** MCPWM_GEN2_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEB 0x00000003U +#define MCPWM_GEN2_B_DTEB_M (MCPWM_GEN2_B_DTEB_V << MCPWM_GEN2_B_DTEB_S) +#define MCPWM_GEN2_B_DTEB_V 0x00000003U +#define MCPWM_GEN2_B_DTEB_S 18 +/** MCPWM_GEN2_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT0 0x00000003U +#define MCPWM_GEN2_B_DT0_M (MCPWM_GEN2_B_DT0_V << MCPWM_GEN2_B_DT0_S) +#define MCPWM_GEN2_B_DT0_V 0x00000003U +#define MCPWM_GEN2_B_DT0_S 20 +/** MCPWM_GEN2_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT1 0x00000003U +#define MCPWM_GEN2_B_DT1_M (MCPWM_GEN2_B_DT1_V << MCPWM_GEN2_B_DT1_S) +#define MCPWM_GEN2_B_DT1_V 0x00000003U +#define MCPWM_GEN2_B_DT1_S 22 -#define MCPWM_DB2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xC8) -/* MCPWM_DB2_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_CLK_SEL (BIT(17)) -#define MCPWM_DB2_CLK_SEL_M (BIT(17)) -#define MCPWM_DB2_CLK_SEL_V 0x1 -#define MCPWM_DB2_CLK_SEL_S 17 -/* MCPWM_DB2_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB2_B_OUTBYPASS (BIT(16)) -#define MCPWM_DB2_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DB2_B_OUTBYPASS_V 0x1 -#define MCPWM_DB2_B_OUTBYPASS_S 16 -/* MCPWM_DB2_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB2_A_OUTBYPASS (BIT(15)) -#define MCPWM_DB2_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DB2_A_OUTBYPASS_V 0x1 -#define MCPWM_DB2_A_OUTBYPASS_S 15 -/* MCPWM_DB2_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED_OUTINVERT (BIT(14)) -#define MCPWM_DB2_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DB2_FED_OUTINVERT_V 0x1 -#define MCPWM_DB2_FED_OUTINVERT_S 14 -/* MCPWM_DB2_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED_OUTINVERT (BIT(13)) -#define MCPWM_DB2_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DB2_RED_OUTINVERT_V 0x1 -#define MCPWM_DB2_RED_OUTINVERT_S 13 -/* MCPWM_DB2_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED_INSEL (BIT(12)) -#define MCPWM_DB2_FED_INSEL_M (BIT(12)) -#define MCPWM_DB2_FED_INSEL_V 0x1 -#define MCPWM_DB2_FED_INSEL_S 12 -/* MCPWM_DB2_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED_INSEL (BIT(11)) -#define MCPWM_DB2_RED_INSEL_M (BIT(11)) -#define MCPWM_DB2_RED_INSEL_V 0x1 -#define MCPWM_DB2_RED_INSEL_S 11 -/* MCPWM_DB2_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_B_OUTSWAP (BIT(10)) -#define MCPWM_DB2_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DB2_B_OUTSWAP_V 0x1 -#define MCPWM_DB2_B_OUTSWAP_S 10 -/* MCPWM_DB2_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_A_OUTSWAP (BIT(9)) -#define MCPWM_DB2_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DB2_A_OUTSWAP_V 0x1 -#define MCPWM_DB2_A_OUTSWAP_S 9 -/* MCPWM_DB2_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_DEB_MODE (BIT(8)) -#define MCPWM_DB2_DEB_MODE_M (BIT(8)) -#define MCPWM_DB2_DEB_MODE_V 0x1 -#define MCPWM_DB2_DEB_MODE_S 8 -/* MCPWM_DB2_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED_UPMETHOD 0x0000000F -#define MCPWM_DB2_RED_UPMETHOD_M ((MCPWM_DB2_RED_UPMETHOD_V)<<(MCPWM_DB2_RED_UPMETHOD_S)) -#define MCPWM_DB2_RED_UPMETHOD_V 0xF -#define MCPWM_DB2_RED_UPMETHOD_S 4 -/* MCPWM_DB2_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED_UPMETHOD 0x0000000F -#define MCPWM_DB2_FED_UPMETHOD_M ((MCPWM_DB2_FED_UPMETHOD_V)<<(MCPWM_DB2_FED_UPMETHOD_S)) -#define MCPWM_DB2_FED_UPMETHOD_V 0xF -#define MCPWM_DB2_FED_UPMETHOD_S 0 +/** MCPWM_DT2_CFG_REG register + * PWM generator 2 dead time type selection and configuration + */ +#define MCPWM_DT2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc8) +/** MCPWM_DT2_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_FED_UPMETHOD_M (MCPWM_DT2_FED_UPMETHOD_V << MCPWM_DT2_FED_UPMETHOD_S) +#define MCPWM_DT2_FED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT2_FED_UPMETHOD_S 0 +/** MCPWM_DT2_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_M (MCPWM_DT2_RED_UPMETHOD_V << MCPWM_DT2_RED_UPMETHOD_S) +#define MCPWM_DT2_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_S 4 +/** MCPWM_DT2_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT2_DEB_MODE (BIT(8)) +#define MCPWM_DT2_DEB_MODE_M (MCPWM_DT2_DEB_MODE_V << MCPWM_DT2_DEB_MODE_S) +#define MCPWM_DT2_DEB_MODE_V 0x00000001U +#define MCPWM_DT2_DEB_MODE_S 8 +/** MCPWM_DT2_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT2_A_OUTSWAP (BIT(9)) +#define MCPWM_DT2_A_OUTSWAP_M (MCPWM_DT2_A_OUTSWAP_V << MCPWM_DT2_A_OUTSWAP_S) +#define MCPWM_DT2_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_A_OUTSWAP_S 9 +/** MCPWM_DT2_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT2_B_OUTSWAP (BIT(10)) +#define MCPWM_DT2_B_OUTSWAP_M (MCPWM_DT2_B_OUTSWAP_V << MCPWM_DT2_B_OUTSWAP_S) +#define MCPWM_DT2_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_B_OUTSWAP_S 10 +/** MCPWM_DT2_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT2_RED_INSEL (BIT(11)) +#define MCPWM_DT2_RED_INSEL_M (MCPWM_DT2_RED_INSEL_V << MCPWM_DT2_RED_INSEL_S) +#define MCPWM_DT2_RED_INSEL_V 0x00000001U +#define MCPWM_DT2_RED_INSEL_S 11 +/** MCPWM_DT2_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT2_FED_INSEL (BIT(12)) +#define MCPWM_DT2_FED_INSEL_M (MCPWM_DT2_FED_INSEL_V << MCPWM_DT2_FED_INSEL_S) +#define MCPWM_DT2_FED_INSEL_V 0x00000001U +#define MCPWM_DT2_FED_INSEL_S 12 +/** MCPWM_DT2_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT2_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT2_RED_OUTINVERT_M (MCPWM_DT2_RED_OUTINVERT_V << MCPWM_DT2_RED_OUTINVERT_S) +#define MCPWM_DT2_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_RED_OUTINVERT_S 13 +/** MCPWM_DT2_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT2_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT2_FED_OUTINVERT_M (MCPWM_DT2_FED_OUTINVERT_V << MCPWM_DT2_FED_OUTINVERT_S) +#define MCPWM_DT2_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_FED_OUTINVERT_S 14 +/** MCPWM_DT2_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT2_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT2_A_OUTBYPASS_M (MCPWM_DT2_A_OUTBYPASS_V << MCPWM_DT2_A_OUTBYPASS_S) +#define MCPWM_DT2_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_A_OUTBYPASS_S 15 +/** MCPWM_DT2_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT2_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT2_B_OUTBYPASS_M (MCPWM_DT2_B_OUTBYPASS_V << MCPWM_DT2_B_OUTBYPASS_S) +#define MCPWM_DT2_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_B_OUTBYPASS_S 16 +/** MCPWM_DT2_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT2_CLK_SEL (BIT(17)) +#define MCPWM_DT2_CLK_SEL_M (MCPWM_DT2_CLK_SEL_V << MCPWM_DT2_CLK_SEL_S) +#define MCPWM_DT2_CLK_SEL_V 0x00000001U +#define MCPWM_DT2_CLK_SEL_S 17 -#define MCPWM_DB2_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xCC) -/* MCPWM_DB2_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED 0x0000FFFF -#define MCPWM_DB2_FED_M ((MCPWM_DB2_FED_V)<<(MCPWM_DB2_FED_S)) -#define MCPWM_DB2_FED_V 0xFFFF -#define MCPWM_DB2_FED_S 0 +/** MCPWM_DT2_FED_CFG_REG register + * PWM generator 2 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT2_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xcc) +/** MCPWM_DT2_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT2_FED 0x0000FFFFU +#define MCPWM_DT2_FED_M (MCPWM_DT2_FED_V << MCPWM_DT2_FED_S) +#define MCPWM_DT2_FED_V 0x0000FFFFU +#define MCPWM_DT2_FED_S 0 -#define MCPWM_DB2_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xD0) -/* MCPWM_DB2_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED 0x0000FFFF -#define MCPWM_DB2_RED_M ((MCPWM_DB2_RED_V)<<(MCPWM_DB2_RED_S)) -#define MCPWM_DB2_RED_V 0xFFFF -#define MCPWM_DB2_RED_S 0 +/** MCPWM_DT2_RED_CFG_REG register + * PWM generator 2 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT2_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd0) +/** MCPWM_DT2_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT2_RED 0x0000FFFFU +#define MCPWM_DT2_RED_M (MCPWM_DT2_RED_V << MCPWM_DT2_RED_S) +#define MCPWM_DT2_RED_V 0x0000FFFFU +#define MCPWM_DT2_RED_S 0 -#define MCPWM_CHOPPER2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xD4) -/* MCPWM_CHOPPER2_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_IN_INVERT (BIT(13)) -#define MCPWM_CHOPPER2_IN_INVERT_M (BIT(13)) -#define MCPWM_CHOPPER2_IN_INVERT_V 0x1 -#define MCPWM_CHOPPER2_IN_INVERT_S 13 -/* MCPWM_CHOPPER2_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_OUT_INVERT (BIT(12)) -#define MCPWM_CHOPPER2_OUT_INVERT_M (BIT(12)) -#define MCPWM_CHOPPER2_OUT_INVERT_V 0x1 -#define MCPWM_CHOPPER2_OUT_INVERT_S 12 -/* MCPWM_CHOPPER2_OSHTWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_OSHTWTH 0x0000000F -#define MCPWM_CHOPPER2_OSHTWTH_M ((MCPWM_CHOPPER2_OSHTWTH_V)<<(MCPWM_CHOPPER2_OSHTWTH_S)) -#define MCPWM_CHOPPER2_OSHTWTH_V 0xF -#define MCPWM_CHOPPER2_OSHTWTH_S 8 -/* MCPWM_CHOPPER2_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_DUTY 0x00000007 -#define MCPWM_CHOPPER2_DUTY_M ((MCPWM_CHOPPER2_DUTY_V)<<(MCPWM_CHOPPER2_DUTY_S)) -#define MCPWM_CHOPPER2_DUTY_V 0x7 -#define MCPWM_CHOPPER2_DUTY_S 5 -/* MCPWM_CHOPPER2_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_PRESCALE 0x0000000F -#define MCPWM_CHOPPER2_PRESCALE_M ((MCPWM_CHOPPER2_PRESCALE_V)<<(MCPWM_CHOPPER2_PRESCALE_S)) -#define MCPWM_CHOPPER2_PRESCALE_V 0xF -#define MCPWM_CHOPPER2_PRESCALE_S 1 -/* MCPWM_CHOPPER2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_EN (BIT(0)) -#define MCPWM_CHOPPER2_EN_M (BIT(0)) -#define MCPWM_CHOPPER2_EN_V 0x1 -#define MCPWM_CHOPPER2_EN_S 0 +/** MCPWM_CARRIER2_CFG_REG register + * PWM generator 2 carrier enable and configuratoin + */ +#define MCPWM_CARRIER2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd4) +/** MCPWM_CARRIER2_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier2 function is enabled. When cleared, carrier2 is bypassed + */ +#define MCPWM_CARRIER2_EN (BIT(0)) +#define MCPWM_CARRIER2_EN_M (MCPWM_CARRIER2_EN_V << MCPWM_CARRIER2_EN_S) +#define MCPWM_CARRIER2_EN_V 0x00000001U +#define MCPWM_CARRIER2_EN_S 0 +/** MCPWM_CARRIER2_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier2 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER2_PRESCALE 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_M (MCPWM_CARRIER2_PRESCALE_V << MCPWM_CARRIER2_PRESCALE_S) +#define MCPWM_CARRIER2_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_S 1 +/** MCPWM_CARRIER2_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER2_DUTY 0x00000007U +#define MCPWM_CARRIER2_DUTY_M (MCPWM_CARRIER2_DUTY_V << MCPWM_CARRIER2_DUTY_S) +#define MCPWM_CARRIER2_DUTY_V 0x00000007U +#define MCPWM_CARRIER2_DUTY_S 5 +/** MCPWM_CARRIER2_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER2_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_M (MCPWM_CARRIER2_OSHTWTH_V << MCPWM_CARRIER2_OSHTWTH_S) +#define MCPWM_CARRIER2_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_S 8 +/** MCPWM_CARRIER2_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER2_OUT_INVERT_M (MCPWM_CARRIER2_OUT_INVERT_V << MCPWM_CARRIER2_OUT_INVERT_S) +#define MCPWM_CARRIER2_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_OUT_INVERT_S 12 +/** MCPWM_CARRIER2_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER2_IN_INVERT_M (MCPWM_CARRIER2_IN_INVERT_V << MCPWM_CARRIER2_IN_INVERT_S) +#define MCPWM_CARRIER2_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_IN_INVERT_S 13 -#define MCPWM_TZ2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0xD8) -/* MCPWM_TZ2_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_OST_U 0x00000003 -#define MCPWM_TZ2_B_OST_U_M ((MCPWM_TZ2_B_OST_U_V)<<(MCPWM_TZ2_B_OST_U_S)) -#define MCPWM_TZ2_B_OST_U_V 0x3 -#define MCPWM_TZ2_B_OST_U_S 22 -/* MCPWM_TZ2_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_OST_D 0x00000003 -#define MCPWM_TZ2_B_OST_D_M ((MCPWM_TZ2_B_OST_D_V)<<(MCPWM_TZ2_B_OST_D_S)) -#define MCPWM_TZ2_B_OST_D_V 0x3 -#define MCPWM_TZ2_B_OST_D_S 20 -/* MCPWM_TZ2_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_CBC_U 0x00000003 -#define MCPWM_TZ2_B_CBC_U_M ((MCPWM_TZ2_B_CBC_U_V)<<(MCPWM_TZ2_B_CBC_U_S)) -#define MCPWM_TZ2_B_CBC_U_V 0x3 -#define MCPWM_TZ2_B_CBC_U_S 18 -/* MCPWM_TZ2_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_CBC_D 0x00000003 -#define MCPWM_TZ2_B_CBC_D_M ((MCPWM_TZ2_B_CBC_D_V)<<(MCPWM_TZ2_B_CBC_D_S)) -#define MCPWM_TZ2_B_CBC_D_V 0x3 -#define MCPWM_TZ2_B_CBC_D_S 16 -/* MCPWM_TZ2_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_OST_U 0x00000003 -#define MCPWM_TZ2_A_OST_U_M ((MCPWM_TZ2_A_OST_U_V)<<(MCPWM_TZ2_A_OST_U_S)) -#define MCPWM_TZ2_A_OST_U_V 0x3 -#define MCPWM_TZ2_A_OST_U_S 14 -/* MCPWM_TZ2_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_OST_D 0x00000003 -#define MCPWM_TZ2_A_OST_D_M ((MCPWM_TZ2_A_OST_D_V)<<(MCPWM_TZ2_A_OST_D_S)) -#define MCPWM_TZ2_A_OST_D_V 0x3 -#define MCPWM_TZ2_A_OST_D_S 12 -/* MCPWM_TZ2_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_CBC_U 0x00000003 -#define MCPWM_TZ2_A_CBC_U_M ((MCPWM_TZ2_A_CBC_U_V)<<(MCPWM_TZ2_A_CBC_U_S)) -#define MCPWM_TZ2_A_CBC_U_V 0x3 -#define MCPWM_TZ2_A_CBC_U_S 10 -/* MCPWM_TZ2_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_CBC_D 0x00000003 -#define MCPWM_TZ2_A_CBC_D_M ((MCPWM_TZ2_A_CBC_D_V)<<(MCPWM_TZ2_A_CBC_D_S)) -#define MCPWM_TZ2_A_CBC_D_V 0x3 -#define MCPWM_TZ2_A_CBC_D_S 8 -/* MCPWM_TZ2_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F0_OST (BIT(7)) -#define MCPWM_TZ2_F0_OST_M (BIT(7)) -#define MCPWM_TZ2_F0_OST_V 0x1 -#define MCPWM_TZ2_F0_OST_S 7 -/* MCPWM_TZ2_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F1_OST (BIT(6)) -#define MCPWM_TZ2_F1_OST_M (BIT(6)) -#define MCPWM_TZ2_F1_OST_V 0x1 -#define MCPWM_TZ2_F1_OST_S 6 -/* MCPWM_TZ2_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F2_OST (BIT(5)) -#define MCPWM_TZ2_F2_OST_M (BIT(5)) -#define MCPWM_TZ2_F2_OST_V 0x1 -#define MCPWM_TZ2_F2_OST_S 5 -/* MCPWM_TZ2_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_SW_OST (BIT(4)) -#define MCPWM_TZ2_SW_OST_M (BIT(4)) -#define MCPWM_TZ2_SW_OST_V 0x1 -#define MCPWM_TZ2_SW_OST_S 4 -/* MCPWM_TZ2_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F0_CBC (BIT(3)) -#define MCPWM_TZ2_F0_CBC_M (BIT(3)) -#define MCPWM_TZ2_F0_CBC_V 0x1 -#define MCPWM_TZ2_F0_CBC_S 3 -/* MCPWM_TZ2_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F1_CBC (BIT(2)) -#define MCPWM_TZ2_F1_CBC_M (BIT(2)) -#define MCPWM_TZ2_F1_CBC_V 0x1 -#define MCPWM_TZ2_F1_CBC_S 2 -/* MCPWM_TZ2_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F2_CBC (BIT(1)) -#define MCPWM_TZ2_F2_CBC_M (BIT(1)) -#define MCPWM_TZ2_F2_CBC_V 0x1 -#define MCPWM_TZ2_F2_CBC_S 1 -/* MCPWM_TZ2_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_SW_CBC (BIT(0)) -#define MCPWM_TZ2_SW_CBC_M (BIT(0)) -#define MCPWM_TZ2_SW_CBC_V 0x1 -#define MCPWM_TZ2_SW_CBC_S 0 +/** MCPWM_FH2_CFG0_REG register + * Actions on PWM2A and PWM2B trip events + */ +#define MCPWM_FH2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd8) +/** MCPWM_FH2_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_CBC (BIT(0)) +#define MCPWM_FH2_SW_CBC_M (MCPWM_FH2_SW_CBC_V << MCPWM_FH2_SW_CBC_S) +#define MCPWM_FH2_SW_CBC_V 0x00000001U +#define MCPWM_FH2_SW_CBC_S 0 +/** MCPWM_FH2_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_CBC (BIT(1)) +#define MCPWM_FH2_F2_CBC_M (MCPWM_FH2_F2_CBC_V << MCPWM_FH2_F2_CBC_S) +#define MCPWM_FH2_F2_CBC_V 0x00000001U +#define MCPWM_FH2_F2_CBC_S 1 +/** MCPWM_FH2_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_CBC (BIT(2)) +#define MCPWM_FH2_F1_CBC_M (MCPWM_FH2_F1_CBC_V << MCPWM_FH2_F1_CBC_S) +#define MCPWM_FH2_F1_CBC_V 0x00000001U +#define MCPWM_FH2_F1_CBC_S 2 +/** MCPWM_FH2_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_CBC (BIT(3)) +#define MCPWM_FH2_F0_CBC_M (MCPWM_FH2_F0_CBC_V << MCPWM_FH2_F0_CBC_S) +#define MCPWM_FH2_F0_CBC_V 0x00000001U +#define MCPWM_FH2_F0_CBC_S 3 +/** MCPWM_FH2_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_OST (BIT(4)) +#define MCPWM_FH2_SW_OST_M (MCPWM_FH2_SW_OST_V << MCPWM_FH2_SW_OST_S) +#define MCPWM_FH2_SW_OST_V 0x00000001U +#define MCPWM_FH2_SW_OST_S 4 +/** MCPWM_FH2_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_OST (BIT(5)) +#define MCPWM_FH2_F2_OST_M (MCPWM_FH2_F2_OST_V << MCPWM_FH2_F2_OST_S) +#define MCPWM_FH2_F2_OST_V 0x00000001U +#define MCPWM_FH2_F2_OST_S 5 +/** MCPWM_FH2_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_OST (BIT(6)) +#define MCPWM_FH2_F1_OST_M (MCPWM_FH2_F1_OST_V << MCPWM_FH2_F1_OST_S) +#define MCPWM_FH2_F1_OST_V 0x00000001U +#define MCPWM_FH2_F1_OST_S 6 +/** MCPWM_FH2_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_OST (BIT(7)) +#define MCPWM_FH2_F0_OST_M (MCPWM_FH2_F0_OST_V << MCPWM_FH2_F0_OST_S) +#define MCPWM_FH2_F0_OST_V 0x00000001U +#define MCPWM_FH2_F0_OST_S 7 +/** MCPWM_FH2_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_D 0x00000003U +#define MCPWM_FH2_A_CBC_D_M (MCPWM_FH2_A_CBC_D_V << MCPWM_FH2_A_CBC_D_S) +#define MCPWM_FH2_A_CBC_D_V 0x00000003U +#define MCPWM_FH2_A_CBC_D_S 8 +/** MCPWM_FH2_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_U 0x00000003U +#define MCPWM_FH2_A_CBC_U_M (MCPWM_FH2_A_CBC_U_V << MCPWM_FH2_A_CBC_U_S) +#define MCPWM_FH2_A_CBC_U_V 0x00000003U +#define MCPWM_FH2_A_CBC_U_S 10 +/** MCPWM_FH2_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_D 0x00000003U +#define MCPWM_FH2_A_OST_D_M (MCPWM_FH2_A_OST_D_V << MCPWM_FH2_A_OST_D_S) +#define MCPWM_FH2_A_OST_D_V 0x00000003U +#define MCPWM_FH2_A_OST_D_S 12 +/** MCPWM_FH2_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_U 0x00000003U +#define MCPWM_FH2_A_OST_U_M (MCPWM_FH2_A_OST_U_V << MCPWM_FH2_A_OST_U_S) +#define MCPWM_FH2_A_OST_U_V 0x00000003U +#define MCPWM_FH2_A_OST_U_S 14 +/** MCPWM_FH2_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_D 0x00000003U +#define MCPWM_FH2_B_CBC_D_M (MCPWM_FH2_B_CBC_D_V << MCPWM_FH2_B_CBC_D_S) +#define MCPWM_FH2_B_CBC_D_V 0x00000003U +#define MCPWM_FH2_B_CBC_D_S 16 +/** MCPWM_FH2_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_U 0x00000003U +#define MCPWM_FH2_B_CBC_U_M (MCPWM_FH2_B_CBC_U_V << MCPWM_FH2_B_CBC_U_S) +#define MCPWM_FH2_B_CBC_U_V 0x00000003U +#define MCPWM_FH2_B_CBC_U_S 18 +/** MCPWM_FH2_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_D 0x00000003U +#define MCPWM_FH2_B_OST_D_M (MCPWM_FH2_B_OST_D_V << MCPWM_FH2_B_OST_D_S) +#define MCPWM_FH2_B_OST_D_V 0x00000003U +#define MCPWM_FH2_B_OST_D_S 20 +/** MCPWM_FH2_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_U 0x00000003U +#define MCPWM_FH2_B_OST_U_M (MCPWM_FH2_B_OST_U_V << MCPWM_FH2_B_OST_U_S) +#define MCPWM_FH2_B_OST_U_V 0x00000003U +#define MCPWM_FH2_B_OST_U_S 22 -#define MCPWM_TZ2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0xDC) -/* MCPWM_TZ2_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: a toggle trigger a oneshot tripping.*/ -#define MCPWM_TZ2_FORCE_OST (BIT(4)) -#define MCPWM_TZ2_FORCE_OST_M (BIT(4)) -#define MCPWM_TZ2_FORCE_OST_V 0x1 -#define MCPWM_TZ2_FORCE_OST_S 4 -/* MCPWM_TZ2_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle trigger a cycle-by-cycle tripping.*/ -#define MCPWM_TZ2_FORCE_CBC (BIT(3)) -#define MCPWM_TZ2_FORCE_CBC_M (BIT(3)) -#define MCPWM_TZ2_FORCE_CBC_V 0x1 -#define MCPWM_TZ2_FORCE_CBC_S 3 -/* MCPWM_TZ2_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: tez, bit1: tep.*/ -#define MCPWM_TZ2_CBCPULSE 0x00000003 -#define MCPWM_TZ2_CBCPULSE_M ((MCPWM_TZ2_CBCPULSE_V)<<(MCPWM_TZ2_CBCPULSE_S)) -#define MCPWM_TZ2_CBCPULSE_V 0x3 -#define MCPWM_TZ2_CBCPULSE_S 1 -/* MCPWM_TZ2_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: a toggle will clear oneshot tripping.*/ -#define MCPWM_TZ2_CLR_OST (BIT(0)) -#define MCPWM_TZ2_CLR_OST_M (BIT(0)) -#define MCPWM_TZ2_CLR_OST_V 0x1 -#define MCPWM_TZ2_CLR_OST_S 0 +/** MCPWM_FH2_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xdc) +/** MCPWM_FH2_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH2_CLR_OST (BIT(0)) +#define MCPWM_FH2_CLR_OST_M (MCPWM_FH2_CLR_OST_V << MCPWM_FH2_CLR_OST_S) +#define MCPWM_FH2_CLR_OST_V 0x00000001U +#define MCPWM_FH2_CLR_OST_S 0 +/** MCPWM_FH2_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH2_CBCPULSE 0x00000003U +#define MCPWM_FH2_CBCPULSE_M (MCPWM_FH2_CBCPULSE_V << MCPWM_FH2_CBCPULSE_S) +#define MCPWM_FH2_CBCPULSE_V 0x00000003U +#define MCPWM_FH2_CBCPULSE_S 1 +/** MCPWM_FH2_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH2_FORCE_CBC (BIT(3)) +#define MCPWM_FH2_FORCE_CBC_M (MCPWM_FH2_FORCE_CBC_V << MCPWM_FH2_FORCE_CBC_S) +#define MCPWM_FH2_FORCE_CBC_V 0x00000001U +#define MCPWM_FH2_FORCE_CBC_S 3 +/** MCPWM_FH2_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH2_FORCE_OST (BIT(4)) +#define MCPWM_FH2_FORCE_OST_M (MCPWM_FH2_FORCE_OST_V << MCPWM_FH2_FORCE_OST_S) +#define MCPWM_FH2_FORCE_OST_V 0x00000001U +#define MCPWM_FH2_FORCE_OST_S 4 -#define MCPWM_TZ2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0xE0) -/* MCPWM_TZ2_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_ON (BIT(1)) -#define MCPWM_TZ2_OST_ON_M (BIT(1)) -#define MCPWM_TZ2_OST_ON_V 0x1 -#define MCPWM_TZ2_OST_ON_S 1 -/* MCPWM_TZ2_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_ON (BIT(0)) -#define MCPWM_TZ2_CBC_ON_M (BIT(0)) -#define MCPWM_TZ2_CBC_ON_V 0x1 -#define MCPWM_TZ2_CBC_ON_S 0 +/** MCPWM_FH2_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe0) +/** MCPWM_FH2_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH2_CBC_ON (BIT(0)) +#define MCPWM_FH2_CBC_ON_M (MCPWM_FH2_CBC_ON_V << MCPWM_FH2_CBC_ON_S) +#define MCPWM_FH2_CBC_ON_V 0x00000001U +#define MCPWM_FH2_CBC_ON_S 0 +/** MCPWM_FH2_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH2_OST_ON (BIT(1)) +#define MCPWM_FH2_OST_ON_M (MCPWM_FH2_OST_ON_V << MCPWM_FH2_OST_ON_S) +#define MCPWM_FH2_OST_ON_V 0x00000001U +#define MCPWM_FH2_OST_ON_S 1 -#define MCPWM_FAULT_DETECT_REG(i) (REG_MCPWM_BASE(i) + 0xE4) -/* MCPWM_EVENT_F2 : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EVENT_F2 (BIT(8)) -#define MCPWM_EVENT_F2_M (BIT(8)) -#define MCPWM_EVENT_F2_V 0x1 -#define MCPWM_EVENT_F2_S 8 -/* MCPWM_EVENT_F1 : RO ;bitpos:[7] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EVENT_F1 (BIT(7)) -#define MCPWM_EVENT_F1_M (BIT(7)) -#define MCPWM_EVENT_F1_V 0x1 -#define MCPWM_EVENT_F1_S 7 -/* MCPWM_EVENT_F0 : RO ;bitpos:[6] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EVENT_F0 (BIT(6)) -#define MCPWM_EVENT_F0_M (BIT(6)) -#define MCPWM_EVENT_F0_V 0x1 -#define MCPWM_EVENT_F0_S 6 -/* MCPWM_F2_POLE : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F2_POLE (BIT(5)) -#define MCPWM_F2_POLE_M (BIT(5)) -#define MCPWM_F2_POLE_V 0x1 -#define MCPWM_F2_POLE_S 5 -/* MCPWM_F1_POLE : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F1_POLE (BIT(4)) -#define MCPWM_F1_POLE_M (BIT(4)) -#define MCPWM_F1_POLE_V 0x1 -#define MCPWM_F1_POLE_S 4 -/* MCPWM_F0_POLE : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F0_POLE (BIT(3)) -#define MCPWM_F0_POLE_M (BIT(3)) -#define MCPWM_F0_POLE_V 0x1 -#define MCPWM_F0_POLE_S 3 -/* MCPWM_F2_EN : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F2_EN (BIT(2)) -#define MCPWM_F2_EN_M (BIT(2)) -#define MCPWM_F2_EN_V 0x1 -#define MCPWM_F2_EN_S 2 -/* MCPWM_F1_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F1_EN (BIT(1)) -#define MCPWM_F1_EN_M (BIT(1)) -#define MCPWM_F1_EN_V 0x1 -#define MCPWM_F1_EN_S 1 -/* MCPWM_F0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_FAULT_DETECT_REG register + * Fault detection configuration and status + */ +#define MCPWM_FAULT_DETECT_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe4) +/** MCPWM_F0_EN : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ #define MCPWM_F0_EN (BIT(0)) -#define MCPWM_F0_EN_M (BIT(0)) -#define MCPWM_F0_EN_V 0x1 +#define MCPWM_F0_EN_M (MCPWM_F0_EN_V << MCPWM_F0_EN_S) +#define MCPWM_F0_EN_V 0x00000001U #define MCPWM_F0_EN_S 0 +/** MCPWM_F1_EN : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ +#define MCPWM_F1_EN (BIT(1)) +#define MCPWM_F1_EN_M (MCPWM_F1_EN_V << MCPWM_F1_EN_S) +#define MCPWM_F1_EN_V 0x00000001U +#define MCPWM_F1_EN_S 1 +/** MCPWM_F2_EN : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ +#define MCPWM_F2_EN (BIT(2)) +#define MCPWM_F2_EN_M (MCPWM_F2_EN_V << MCPWM_F2_EN_S) +#define MCPWM_F2_EN_V 0x00000001U +#define MCPWM_F2_EN_S 2 +/** MCPWM_F0_POLE : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F0_POLE (BIT(3)) +#define MCPWM_F0_POLE_M (MCPWM_F0_POLE_V << MCPWM_F0_POLE_S) +#define MCPWM_F0_POLE_V 0x00000001U +#define MCPWM_F0_POLE_S 3 +/** MCPWM_F1_POLE : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F1_POLE (BIT(4)) +#define MCPWM_F1_POLE_M (MCPWM_F1_POLE_V << MCPWM_F1_POLE_S) +#define MCPWM_F1_POLE_V 0x00000001U +#define MCPWM_F1_POLE_S 4 +/** MCPWM_F2_POLE : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F2_POLE (BIT(5)) +#define MCPWM_F2_POLE_M (MCPWM_F2_POLE_V << MCPWM_F2_POLE_S) +#define MCPWM_F2_POLE_V 0x00000001U +#define MCPWM_F2_POLE_S 5 +/** MCPWM_EVENT_F0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ +#define MCPWM_EVENT_F0 (BIT(6)) +#define MCPWM_EVENT_F0_M (MCPWM_EVENT_F0_V << MCPWM_EVENT_F0_S) +#define MCPWM_EVENT_F0_V 0x00000001U +#define MCPWM_EVENT_F0_S 6 +/** MCPWM_EVENT_F1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ +#define MCPWM_EVENT_F1 (BIT(7)) +#define MCPWM_EVENT_F1_M (MCPWM_EVENT_F1_V << MCPWM_EVENT_F1_S) +#define MCPWM_EVENT_F1_V 0x00000001U +#define MCPWM_EVENT_F1_S 7 +/** MCPWM_EVENT_F2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ +#define MCPWM_EVENT_F2 (BIT(8)) +#define MCPWM_EVENT_F2_M (MCPWM_EVENT_F2_V << MCPWM_EVENT_F2_S) +#define MCPWM_EVENT_F2_V 0x00000001U +#define MCPWM_EVENT_F2_S 8 -#define MCPWM_CAP_TIMER_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xE8) -/* MCPWM_CAP_SYNC_SW : WO ;bitpos:[5] ;default: 1'd0 ; */ -/*description: Write 1 will force a timer sync.*/ -#define MCPWM_CAP_SYNC_SW (BIT(5)) -#define MCPWM_CAP_SYNC_SW_M (BIT(5)) -#define MCPWM_CAP_SYNC_SW_V 0x1 -#define MCPWM_CAP_SYNC_SW_S 5 -/* MCPWM_CAP_SYNCI_SEL : R/W ;bitpos:[4:2] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CAP_SYNCI_SEL 0x00000007 -#define MCPWM_CAP_SYNCI_SEL_M ((MCPWM_CAP_SYNCI_SEL_V)<<(MCPWM_CAP_SYNCI_SEL_S)) -#define MCPWM_CAP_SYNCI_SEL_V 0x7 -#define MCPWM_CAP_SYNCI_SEL_S 2 -/* MCPWM_CAP_SYNCI_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP_SYNCI_EN (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_M (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_V 0x1 -#define MCPWM_CAP_SYNCI_EN_S 1 -/* MCPWM_CAP_TIMER_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_TIMER_CFG_REG register + * Configure capture timer + */ +#define MCPWM_CAP_TIMER_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe8) +/** MCPWM_CAP_TIMER_EN : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ #define MCPWM_CAP_TIMER_EN (BIT(0)) -#define MCPWM_CAP_TIMER_EN_M (BIT(0)) -#define MCPWM_CAP_TIMER_EN_V 0x1 +#define MCPWM_CAP_TIMER_EN_M (MCPWM_CAP_TIMER_EN_V << MCPWM_CAP_TIMER_EN_S) +#define MCPWM_CAP_TIMER_EN_V 0x00000001U #define MCPWM_CAP_TIMER_EN_S 0 +/** MCPWM_CAP_SYNCI_EN : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ +#define MCPWM_CAP_SYNCI_EN (BIT(1)) +#define MCPWM_CAP_SYNCI_EN_M (MCPWM_CAP_SYNCI_EN_V << MCPWM_CAP_SYNCI_EN_S) +#define MCPWM_CAP_SYNCI_EN_V 0x00000001U +#define MCPWM_CAP_SYNCI_EN_S 1 +/** MCPWM_CAP_SYNCI_SEL : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ +#define MCPWM_CAP_SYNCI_SEL 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_M (MCPWM_CAP_SYNCI_SEL_V << MCPWM_CAP_SYNCI_SEL_S) +#define MCPWM_CAP_SYNCI_SEL_V 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_S 2 +/** MCPWM_CAP_SYNC_SW : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ +#define MCPWM_CAP_SYNC_SW (BIT(5)) +#define MCPWM_CAP_SYNC_SW_M (MCPWM_CAP_SYNC_SW_V << MCPWM_CAP_SYNC_SW_S) +#define MCPWM_CAP_SYNC_SW_V 0x00000001U +#define MCPWM_CAP_SYNC_SW_S 5 -#define MCPWM_CAP_TIMER_PHASE_REG(i) (REG_MCPWM_BASE(i) + 0xEC) -/* MCPWM_CAP_PHASE : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP_PHASE 0xFFFFFFFF -#define MCPWM_CAP_PHASE_M ((MCPWM_CAP_PHASE_V)<<(MCPWM_CAP_PHASE_S)) -#define MCPWM_CAP_PHASE_V 0xFFFFFFFF -#define MCPWM_CAP_PHASE_S 0 +/** MCPWM_CAP_TIMER_PHASE_REG register + * Phase for capture timer sync + */ +#define MCPWM_CAP_TIMER_PHASE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xec) +/** MCPWM_CAP_TIMER_PHASE : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ +#define MCPWM_CAP_TIMER_PHASE 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_M (MCPWM_CAP_TIMER_PHASE_V << MCPWM_CAP_TIMER_PHASE_S) +#define MCPWM_CAP_TIMER_PHASE_V 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_S 0 -#define MCPWM_CAP_CH0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xF0) -/* MCPWM_CAP0_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a sw capture.*/ -#define MCPWM_CAP0_SW (BIT(12)) -#define MCPWM_CAP0_SW_M (BIT(12)) -#define MCPWM_CAP0_SW_V 0x1 -#define MCPWM_CAP0_SW_S 12 -/* MCPWM_CAP0_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_IN_INVERT (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_V 0x1 -#define MCPWM_CAP0_IN_INVERT_S 11 -/* MCPWM_CAP0_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_PRESCALE 0x000000FF -#define MCPWM_CAP0_PRESCALE_M ((MCPWM_CAP0_PRESCALE_V)<<(MCPWM_CAP0_PRESCALE_S)) -#define MCPWM_CAP0_PRESCALE_V 0xFF -#define MCPWM_CAP0_PRESCALE_S 3 -/* MCPWM_CAP0_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: negedge cap en, bit1: posedge cap en.*/ -#define MCPWM_CAP0_MODE 0x00000003 -#define MCPWM_CAP0_MODE_M ((MCPWM_CAP0_MODE_V)<<(MCPWM_CAP0_MODE_S)) -#define MCPWM_CAP0_MODE_V 0x3 -#define MCPWM_CAP0_MODE_S 1 -/* MCPWM_CAP0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_CH0_CFG_REG register + * Capture channel 0 configuration and enable + */ +#define MCPWM_CAP_CH0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf0) +/** MCPWM_CAP0_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ #define MCPWM_CAP0_EN (BIT(0)) -#define MCPWM_CAP0_EN_M (BIT(0)) -#define MCPWM_CAP0_EN_V 0x1 +#define MCPWM_CAP0_EN_M (MCPWM_CAP0_EN_V << MCPWM_CAP0_EN_S) +#define MCPWM_CAP0_EN_V 0x00000001U #define MCPWM_CAP0_EN_S 0 +/** MCPWM_CAP0_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP0_MODE 0x00000003U +#define MCPWM_CAP0_MODE_M (MCPWM_CAP0_MODE_V << MCPWM_CAP0_MODE_S) +#define MCPWM_CAP0_MODE_V 0x00000003U +#define MCPWM_CAP0_MODE_S 1 +/** MCPWM_CAP0_PRESCALE : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + + * 1 + */ +#define MCPWM_CAP0_PRESCALE 0x000000FFU +#define MCPWM_CAP0_PRESCALE_M (MCPWM_CAP0_PRESCALE_V << MCPWM_CAP0_PRESCALE_S) +#define MCPWM_CAP0_PRESCALE_V 0x000000FFU +#define MCPWM_CAP0_PRESCALE_S 3 +/** MCPWM_CAP0_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP0 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP0_IN_INVERT (BIT(11)) +#define MCPWM_CAP0_IN_INVERT_M (MCPWM_CAP0_IN_INVERT_V << MCPWM_CAP0_IN_INVERT_S) +#define MCPWM_CAP0_IN_INVERT_V 0x00000001U +#define MCPWM_CAP0_IN_INVERT_S 11 +/** MCPWM_CAP0_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ +#define MCPWM_CAP0_SW (BIT(12)) +#define MCPWM_CAP0_SW_M (MCPWM_CAP0_SW_V << MCPWM_CAP0_SW_S) +#define MCPWM_CAP0_SW_V 0x00000001U +#define MCPWM_CAP0_SW_S 12 -#define MCPWM_CAP_CH1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xF4) -/* MCPWM_CAP1_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a sw capture.*/ -#define MCPWM_CAP1_SW (BIT(12)) -#define MCPWM_CAP1_SW_M (BIT(12)) -#define MCPWM_CAP1_SW_V 0x1 -#define MCPWM_CAP1_SW_S 12 -/* MCPWM_CAP1_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_IN_INVERT (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_V 0x1 -#define MCPWM_CAP1_IN_INVERT_S 11 -/* MCPWM_CAP1_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_PRESCALE 0x000000FF -#define MCPWM_CAP1_PRESCALE_M ((MCPWM_CAP1_PRESCALE_V)<<(MCPWM_CAP1_PRESCALE_S)) -#define MCPWM_CAP1_PRESCALE_V 0xFF -#define MCPWM_CAP1_PRESCALE_S 3 -/* MCPWM_CAP1_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_MODE 0x00000003 -#define MCPWM_CAP1_MODE_M ((MCPWM_CAP1_MODE_V)<<(MCPWM_CAP1_MODE_S)) -#define MCPWM_CAP1_MODE_V 0x3 -#define MCPWM_CAP1_MODE_S 1 -/* MCPWM_CAP1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_CH1_CFG_REG register + * Capture channel 1 configuration and enable + */ +#define MCPWM_CAP_CH1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf4) +/** MCPWM_CAP1_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ #define MCPWM_CAP1_EN (BIT(0)) -#define MCPWM_CAP1_EN_M (BIT(0)) -#define MCPWM_CAP1_EN_V 0x1 +#define MCPWM_CAP1_EN_M (MCPWM_CAP1_EN_V << MCPWM_CAP1_EN_S) +#define MCPWM_CAP1_EN_V 0x00000001U #define MCPWM_CAP1_EN_S 0 +/** MCPWM_CAP1_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 1 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP1_MODE 0x00000003U +#define MCPWM_CAP1_MODE_M (MCPWM_CAP1_MODE_V << MCPWM_CAP1_MODE_S) +#define MCPWM_CAP1_MODE_V 0x00000003U +#define MCPWM_CAP1_MODE_S 1 +/** MCPWM_CAP1_PRESCALE : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + + * 1 + */ +#define MCPWM_CAP1_PRESCALE 0x000000FFU +#define MCPWM_CAP1_PRESCALE_M (MCPWM_CAP1_PRESCALE_V << MCPWM_CAP1_PRESCALE_S) +#define MCPWM_CAP1_PRESCALE_V 0x000000FFU +#define MCPWM_CAP1_PRESCALE_S 3 +/** MCPWM_CAP1_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP1 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP1_IN_INVERT (BIT(11)) +#define MCPWM_CAP1_IN_INVERT_M (MCPWM_CAP1_IN_INVERT_V << MCPWM_CAP1_IN_INVERT_S) +#define MCPWM_CAP1_IN_INVERT_V 0x00000001U +#define MCPWM_CAP1_IN_INVERT_S 11 +/** MCPWM_CAP1_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 1 + */ +#define MCPWM_CAP1_SW (BIT(12)) +#define MCPWM_CAP1_SW_M (MCPWM_CAP1_SW_V << MCPWM_CAP1_SW_S) +#define MCPWM_CAP1_SW_V 0x00000001U +#define MCPWM_CAP1_SW_S 12 -#define MCPWM_CAP_CH2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xF8) -/* MCPWM_CAP2_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a sw capture.*/ -#define MCPWM_CAP2_SW (BIT(12)) -#define MCPWM_CAP2_SW_M (BIT(12)) -#define MCPWM_CAP2_SW_V 0x1 -#define MCPWM_CAP2_SW_S 12 -/* MCPWM_CAP2_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_IN_INVERT (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_V 0x1 -#define MCPWM_CAP2_IN_INVERT_S 11 -/* MCPWM_CAP2_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_PRESCALE 0x000000FF -#define MCPWM_CAP2_PRESCALE_M ((MCPWM_CAP2_PRESCALE_V)<<(MCPWM_CAP2_PRESCALE_S)) -#define MCPWM_CAP2_PRESCALE_V 0xFF -#define MCPWM_CAP2_PRESCALE_S 3 -/* MCPWM_CAP2_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_MODE 0x00000003 -#define MCPWM_CAP2_MODE_M ((MCPWM_CAP2_MODE_V)<<(MCPWM_CAP2_MODE_S)) -#define MCPWM_CAP2_MODE_V 0x3 -#define MCPWM_CAP2_MODE_S 1 -/* MCPWM_CAP2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_CH2_CFG_REG register + * Capture channel 2 configuration and enable + */ +#define MCPWM_CAP_CH2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf8) +/** MCPWM_CAP2_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ #define MCPWM_CAP2_EN (BIT(0)) -#define MCPWM_CAP2_EN_M (BIT(0)) -#define MCPWM_CAP2_EN_V 0x1 +#define MCPWM_CAP2_EN_M (MCPWM_CAP2_EN_V << MCPWM_CAP2_EN_S) +#define MCPWM_CAP2_EN_V 0x00000001U #define MCPWM_CAP2_EN_S 0 +/** MCPWM_CAP2_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 2 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP2_MODE 0x00000003U +#define MCPWM_CAP2_MODE_M (MCPWM_CAP2_MODE_V << MCPWM_CAP2_MODE_S) +#define MCPWM_CAP2_MODE_V 0x00000003U +#define MCPWM_CAP2_MODE_S 1 +/** MCPWM_CAP2_PRESCALE : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + + * 1 + */ +#define MCPWM_CAP2_PRESCALE 0x000000FFU +#define MCPWM_CAP2_PRESCALE_M (MCPWM_CAP2_PRESCALE_V << MCPWM_CAP2_PRESCALE_S) +#define MCPWM_CAP2_PRESCALE_V 0x000000FFU +#define MCPWM_CAP2_PRESCALE_S 3 +/** MCPWM_CAP2_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP2 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP2_IN_INVERT (BIT(11)) +#define MCPWM_CAP2_IN_INVERT_M (MCPWM_CAP2_IN_INVERT_V << MCPWM_CAP2_IN_INVERT_S) +#define MCPWM_CAP2_IN_INVERT_V 0x00000001U +#define MCPWM_CAP2_IN_INVERT_S 11 +/** MCPWM_CAP2_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 2 + */ +#define MCPWM_CAP2_SW (BIT(12)) +#define MCPWM_CAP2_SW_M (MCPWM_CAP2_SW_V << MCPWM_CAP2_SW_S) +#define MCPWM_CAP2_SW_V 0x00000001U +#define MCPWM_CAP2_SW_S 12 -#define MCPWM_CAP_CH0_REG(i) (REG_MCPWM_BASE(i) + 0xFC) -/* MCPWM_CAP0_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_VALUE 0xFFFFFFFF -#define MCPWM_CAP0_VALUE_M ((MCPWM_CAP0_VALUE_V)<<(MCPWM_CAP0_VALUE_S)) -#define MCPWM_CAP0_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH0_REG register + * ch0 capture value status register + */ +#define MCPWM_CAP_CH0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xfc) +/** MCPWM_CAP0_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 0 + */ +#define MCPWM_CAP0_VALUE 0xFFFFFFFFU +#define MCPWM_CAP0_VALUE_M (MCPWM_CAP0_VALUE_V << MCPWM_CAP0_VALUE_S) +#define MCPWM_CAP0_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP0_VALUE_S 0 -#define MCPWM_CAP_CH1_REG(i) (REG_MCPWM_BASE(i) + 0x100) -/* MCPWM_CAP1_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_VALUE 0xFFFFFFFF -#define MCPWM_CAP1_VALUE_M ((MCPWM_CAP1_VALUE_V)<<(MCPWM_CAP1_VALUE_S)) -#define MCPWM_CAP1_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH1_REG register + * ch1 capture value status register + */ +#define MCPWM_CAP_CH1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x100) +/** MCPWM_CAP1_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 1 + */ +#define MCPWM_CAP1_VALUE 0xFFFFFFFFU +#define MCPWM_CAP1_VALUE_M (MCPWM_CAP1_VALUE_V << MCPWM_CAP1_VALUE_S) +#define MCPWM_CAP1_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP1_VALUE_S 0 -#define MCPWM_CAP_CH2_REG(i) (REG_MCPWM_BASE(i) + 0x104) -/* MCPWM_CAP2_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_VALUE 0xFFFFFFFF -#define MCPWM_CAP2_VALUE_M ((MCPWM_CAP2_VALUE_V)<<(MCPWM_CAP2_VALUE_S)) -#define MCPWM_CAP2_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH2_REG register + * ch2 capture value status register + */ +#define MCPWM_CAP_CH2_REG(i) (DR_REG_MCPWM_BASE(i) + 0x104) +/** MCPWM_CAP2_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 2 + */ +#define MCPWM_CAP2_VALUE 0xFFFFFFFFU +#define MCPWM_CAP2_VALUE_M (MCPWM_CAP2_VALUE_V << MCPWM_CAP2_VALUE_S) +#define MCPWM_CAP2_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP2_VALUE_S 0 -#define MCPWM_CAP_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x108) -/* MCPWM_CAP2_EDGE : RO ;bitpos:[2] ;default: 1'd0 ; */ -/*description: cap trigger's edge, 0: posedge, 1: negedge.*/ -#define MCPWM_CAP2_EDGE (BIT(2)) -#define MCPWM_CAP2_EDGE_M (BIT(2)) -#define MCPWM_CAP2_EDGE_V 0x1 -#define MCPWM_CAP2_EDGE_S 2 -/* MCPWM_CAP1_EDGE : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_EDGE (BIT(1)) -#define MCPWM_CAP1_EDGE_M (BIT(1)) -#define MCPWM_CAP1_EDGE_V 0x1 -#define MCPWM_CAP1_EDGE_S 1 -/* MCPWM_CAP0_EDGE : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_STATUS_REG register + * Edge of last capture trigger + */ +#define MCPWM_CAP_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x108) +/** MCPWM_CAP0_EDGE : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ #define MCPWM_CAP0_EDGE (BIT(0)) -#define MCPWM_CAP0_EDGE_M (BIT(0)) -#define MCPWM_CAP0_EDGE_V 0x1 +#define MCPWM_CAP0_EDGE_M (MCPWM_CAP0_EDGE_V << MCPWM_CAP0_EDGE_S) +#define MCPWM_CAP0_EDGE_V 0x00000001U #define MCPWM_CAP0_EDGE_S 0 +/** MCPWM_CAP1_EDGE : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ +#define MCPWM_CAP1_EDGE (BIT(1)) +#define MCPWM_CAP1_EDGE_M (MCPWM_CAP1_EDGE_V << MCPWM_CAP1_EDGE_S) +#define MCPWM_CAP1_EDGE_V 0x00000001U +#define MCPWM_CAP1_EDGE_S 1 +/** MCPWM_CAP2_EDGE : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ +#define MCPWM_CAP2_EDGE (BIT(2)) +#define MCPWM_CAP2_EDGE_M (MCPWM_CAP2_EDGE_V << MCPWM_CAP2_EDGE_S) +#define MCPWM_CAP2_EDGE_V 0x00000001U +#define MCPWM_CAP2_EDGE_S 2 -#define MCPWM_UPDATE_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x10C) -/* MCPWM_OP2_FORCE_UP : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update.*/ -#define MCPWM_OP2_FORCE_UP (BIT(7)) -#define MCPWM_OP2_FORCE_UP_M (BIT(7)) -#define MCPWM_OP2_FORCE_UP_V 0x1 -#define MCPWM_OP2_FORCE_UP_S 7 -/* MCPWM_OP2_UP_EN : R/W ;bitpos:[6] ;default: 1'd1 ; */ -/*description: reg update local enable.*/ -#define MCPWM_OP2_UP_EN (BIT(6)) -#define MCPWM_OP2_UP_EN_M (BIT(6)) -#define MCPWM_OP2_UP_EN_V 0x1 -#define MCPWM_OP2_UP_EN_S 6 -/* MCPWM_OP1_FORCE_UP : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update.*/ -#define MCPWM_OP1_FORCE_UP (BIT(5)) -#define MCPWM_OP1_FORCE_UP_M (BIT(5)) -#define MCPWM_OP1_FORCE_UP_V 0x1 -#define MCPWM_OP1_FORCE_UP_S 5 -/* MCPWM_OP1_UP_EN : R/W ;bitpos:[4] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_OP1_UP_EN (BIT(4)) -#define MCPWM_OP1_UP_EN_M (BIT(4)) -#define MCPWM_OP1_UP_EN_V 0x1 -#define MCPWM_OP1_UP_EN_S 4 -/* MCPWM_OP0_FORCE_UP : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update.*/ -#define MCPWM_OP0_FORCE_UP (BIT(3)) -#define MCPWM_OP0_FORCE_UP_M (BIT(3)) -#define MCPWM_OP0_FORCE_UP_V 0x1 -#define MCPWM_OP0_FORCE_UP_S 3 -/* MCPWM_OP0_UP_EN : R/W ;bitpos:[2] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_OP0_UP_EN (BIT(2)) -#define MCPWM_OP0_UP_EN_M (BIT(2)) -#define MCPWM_OP0_UP_EN_V 0x1 -#define MCPWM_OP0_UP_EN_S 2 -/* MCPWM_GLOBAL_FORCE_UP : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update, all timers and operators will update their - active regs.*/ -#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_M (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_V 0x1 -#define MCPWM_GLOBAL_FORCE_UP_S 1 -/* MCPWM_GLOBAL_UP_EN : R/W ;bitpos:[0] ;default: 1'd1 ; */ -/*description: .*/ +/** MCPWM_UPDATE_CFG_REG register + * Enable update. + */ +#define MCPWM_UPDATE_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10c) +/** MCPWM_GLOBAL_UP_EN : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ #define MCPWM_GLOBAL_UP_EN (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_M (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_V 0x1 +#define MCPWM_GLOBAL_UP_EN_M (MCPWM_GLOBAL_UP_EN_V << MCPWM_GLOBAL_UP_EN_S) +#define MCPWM_GLOBAL_UP_EN_V 0x00000001U #define MCPWM_GLOBAL_UP_EN_S 0 +/** MCPWM_GLOBAL_FORCE_UP : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ +#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) +#define MCPWM_GLOBAL_FORCE_UP_M (MCPWM_GLOBAL_FORCE_UP_V << MCPWM_GLOBAL_FORCE_UP_S) +#define MCPWM_GLOBAL_FORCE_UP_V 0x00000001U +#define MCPWM_GLOBAL_FORCE_UP_S 1 +/** MCPWM_OP0_UP_EN : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ +#define MCPWM_OP0_UP_EN (BIT(2)) +#define MCPWM_OP0_UP_EN_M (MCPWM_OP0_UP_EN_V << MCPWM_OP0_UP_EN_S) +#define MCPWM_OP0_UP_EN_V 0x00000001U +#define MCPWM_OP0_UP_EN_S 2 +/** MCPWM_OP0_FORCE_UP : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ +#define MCPWM_OP0_FORCE_UP (BIT(3)) +#define MCPWM_OP0_FORCE_UP_M (MCPWM_OP0_FORCE_UP_V << MCPWM_OP0_FORCE_UP_S) +#define MCPWM_OP0_FORCE_UP_V 0x00000001U +#define MCPWM_OP0_FORCE_UP_S 3 +/** MCPWM_OP1_UP_EN : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ +#define MCPWM_OP1_UP_EN (BIT(4)) +#define MCPWM_OP1_UP_EN_M (MCPWM_OP1_UP_EN_V << MCPWM_OP1_UP_EN_S) +#define MCPWM_OP1_UP_EN_V 0x00000001U +#define MCPWM_OP1_UP_EN_S 4 +/** MCPWM_OP1_FORCE_UP : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ +#define MCPWM_OP1_FORCE_UP (BIT(5)) +#define MCPWM_OP1_FORCE_UP_M (MCPWM_OP1_FORCE_UP_V << MCPWM_OP1_FORCE_UP_S) +#define MCPWM_OP1_FORCE_UP_V 0x00000001U +#define MCPWM_OP1_FORCE_UP_S 5 +/** MCPWM_OP2_UP_EN : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ +#define MCPWM_OP2_UP_EN (BIT(6)) +#define MCPWM_OP2_UP_EN_M (MCPWM_OP2_UP_EN_V << MCPWM_OP2_UP_EN_S) +#define MCPWM_OP2_UP_EN_V 0x00000001U +#define MCPWM_OP2_UP_EN_S 6 +/** MCPWM_OP2_FORCE_UP : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ +#define MCPWM_OP2_FORCE_UP (BIT(7)) +#define MCPWM_OP2_FORCE_UP_M (MCPWM_OP2_FORCE_UP_V << MCPWM_OP2_FORCE_UP_S) +#define MCPWM_OP2_FORCE_UP_V 0x00000001U +#define MCPWM_OP2_FORCE_UP_S 7 -#define MCPWM_INT_ENA_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x110) -/* MCPWM_CAP2_INT_ENA : R/W ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_ENA (BIT(29)) -#define MCPWM_CAP2_INT_ENA_M (BIT(29)) -#define MCPWM_CAP2_INT_ENA_V 0x1 -#define MCPWM_CAP2_INT_ENA_S 29 -/* MCPWM_CAP1_INT_ENA : R/W ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_ENA (BIT(28)) -#define MCPWM_CAP1_INT_ENA_M (BIT(28)) -#define MCPWM_CAP1_INT_ENA_V 0x1 -#define MCPWM_CAP1_INT_ENA_S 28 -/* MCPWM_CAP0_INT_ENA : R/W ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_ENA (BIT(27)) -#define MCPWM_CAP0_INT_ENA_M (BIT(27)) -#define MCPWM_CAP0_INT_ENA_V 0x1 -#define MCPWM_CAP0_INT_ENA_S 27 -/* MCPWM_TZ2_OST_INT_ENA : R/W ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_ENA (BIT(26)) -#define MCPWM_TZ2_OST_INT_ENA_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_ENA_V 0x1 -#define MCPWM_TZ2_OST_INT_ENA_S 26 -/* MCPWM_TZ1_OST_INT_ENA : R/W ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_ENA (BIT(25)) -#define MCPWM_TZ1_OST_INT_ENA_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_ENA_V 0x1 -#define MCPWM_TZ1_OST_INT_ENA_S 25 -/* MCPWM_TZ0_OST_INT_ENA : R/W ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_ENA (BIT(24)) -#define MCPWM_TZ0_OST_INT_ENA_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_ENA_V 0x1 -#define MCPWM_TZ0_OST_INT_ENA_S 24 -/* MCPWM_TZ2_CBC_INT_ENA : R/W ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_ENA (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ENA_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ENA_V 0x1 -#define MCPWM_TZ2_CBC_INT_ENA_S 23 -/* MCPWM_TZ1_CBC_INT_ENA : R/W ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_ENA (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ENA_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ENA_V 0x1 -#define MCPWM_TZ1_CBC_INT_ENA_S 22 -/* MCPWM_TZ0_CBC_INT_ENA : R/W ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_ENA (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ENA_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ENA_V 0x1 -#define MCPWM_TZ0_CBC_INT_ENA_S 21 -/* MCPWM_CMPR2_TEB_INT_ENA : R/W ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_ENA (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ENA_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ENA_V 0x1 -#define MCPWM_CMPR2_TEB_INT_ENA_S 20 -/* MCPWM_CMPR1_TEB_INT_ENA : R/W ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_ENA (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ENA_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ENA_V 0x1 -#define MCPWM_CMPR1_TEB_INT_ENA_S 19 -/* MCPWM_CMPR0_TEB_INT_ENA : R/W ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_ENA (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ENA_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ENA_V 0x1 -#define MCPWM_CMPR0_TEB_INT_ENA_S 18 -/* MCPWM_CMPR2_TEA_INT_ENA : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_ENA (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ENA_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ENA_V 0x1 -#define MCPWM_CMPR2_TEA_INT_ENA_S 17 -/* MCPWM_CMPR1_TEA_INT_ENA : R/W ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_ENA (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ENA_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ENA_V 0x1 -#define MCPWM_CMPR1_TEA_INT_ENA_S 16 -/* MCPWM_CMPR0_TEA_INT_ENA : R/W ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_ENA (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ENA_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ENA_V 0x1 -#define MCPWM_CMPR0_TEA_INT_ENA_S 15 -/* MCPWM_FAULT2_CLR_INT_ENA : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ENA_S 14 -/* MCPWM_FAULT1_CLR_INT_ENA : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ENA_S 13 -/* MCPWM_FAULT0_CLR_INT_ENA : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ENA_S 12 -/* MCPWM_FAULT2_INT_ENA : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_ENA (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_M (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_V 0x1 -#define MCPWM_FAULT2_INT_ENA_S 11 -/* MCPWM_FAULT1_INT_ENA : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_ENA (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_M (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_V 0x1 -#define MCPWM_FAULT1_INT_ENA_S 10 -/* MCPWM_FAULT0_INT_ENA : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_ENA (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_M (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_V 0x1 -#define MCPWM_FAULT0_INT_ENA_S 9 -/* MCPWM_TIMER2_TEP_INT_ENA : R/W ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ENA_S 8 -/* MCPWM_TIMER1_TEP_INT_ENA : R/W ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ENA_S 7 -/* MCPWM_TIMER0_TEP_INT_ENA : R/W ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ENA_S 6 -/* MCPWM_TIMER2_TEZ_INT_ENA : R/W ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 -/* MCPWM_TIMER1_TEZ_INT_ENA : R/W ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 -/* MCPWM_TIMER0_TEZ_INT_ENA : R/W ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 -/* MCPWM_TIMER2_STOP_INT_ENA : R/W ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ENA_S 2 -/* MCPWM_TIMER1_STOP_INT_ENA : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ENA_S 1 -/* MCPWM_TIMER0_STOP_INT_ENA : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_ENA_REG register + * Interrupt enable bits + */ +#define MCPWM_INT_ENA_REG(i) (DR_REG_MCPWM_BASE(i) + 0x110) +/** MCPWM_TIMER0_STOP_INT_ENA : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_ENA (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_V 0x1 +#define MCPWM_TIMER0_STOP_INT_ENA_M (MCPWM_TIMER0_STOP_INT_ENA_V << MCPWM_TIMER0_STOP_INT_ENA_S) +#define MCPWM_TIMER0_STOP_INT_ENA_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ENA_S 0 +/** MCPWM_TIMER1_STOP_INT_ENA : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ENA_M (MCPWM_TIMER1_STOP_INT_ENA_V << MCPWM_TIMER1_STOP_INT_ENA_S) +#define MCPWM_TIMER1_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ENA_S 1 +/** MCPWM_TIMER2_STOP_INT_ENA : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ENA_M (MCPWM_TIMER2_STOP_INT_ENA_V << MCPWM_TIMER2_STOP_INT_ENA_S) +#define MCPWM_TIMER2_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ENA_S 2 +/** MCPWM_TIMER0_TEZ_INT_ENA : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ENA_M (MCPWM_TIMER0_TEZ_INT_ENA_V << MCPWM_TIMER0_TEZ_INT_ENA_S) +#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 +/** MCPWM_TIMER1_TEZ_INT_ENA : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ENA_M (MCPWM_TIMER1_TEZ_INT_ENA_V << MCPWM_TIMER1_TEZ_INT_ENA_S) +#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 +/** MCPWM_TIMER2_TEZ_INT_ENA : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ENA_M (MCPWM_TIMER2_TEZ_INT_ENA_V << MCPWM_TIMER2_TEZ_INT_ENA_S) +#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 +/** MCPWM_TIMER0_TEP_INT_ENA : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ENA_M (MCPWM_TIMER0_TEP_INT_ENA_V << MCPWM_TIMER0_TEP_INT_ENA_S) +#define MCPWM_TIMER0_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ENA_S 6 +/** MCPWM_TIMER1_TEP_INT_ENA : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ENA_M (MCPWM_TIMER1_TEP_INT_ENA_V << MCPWM_TIMER1_TEP_INT_ENA_S) +#define MCPWM_TIMER1_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ENA_S 7 +/** MCPWM_TIMER2_TEP_INT_ENA : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ENA_M (MCPWM_TIMER2_TEP_INT_ENA_V << MCPWM_TIMER2_TEP_INT_ENA_S) +#define MCPWM_TIMER2_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ENA_S 8 +/** MCPWM_FAULT0_INT_ENA : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ENA (BIT(9)) +#define MCPWM_FAULT0_INT_ENA_M (MCPWM_FAULT0_INT_ENA_V << MCPWM_FAULT0_INT_ENA_S) +#define MCPWM_FAULT0_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_INT_ENA_S 9 +/** MCPWM_FAULT1_INT_ENA : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ENA (BIT(10)) +#define MCPWM_FAULT1_INT_ENA_M (MCPWM_FAULT1_INT_ENA_V << MCPWM_FAULT1_INT_ENA_S) +#define MCPWM_FAULT1_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_INT_ENA_S 10 +/** MCPWM_FAULT2_INT_ENA : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ENA (BIT(11)) +#define MCPWM_FAULT2_INT_ENA_M (MCPWM_FAULT2_INT_ENA_V << MCPWM_FAULT2_INT_ENA_S) +#define MCPWM_FAULT2_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_INT_ENA_S 11 +/** MCPWM_FAULT0_CLR_INT_ENA : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ENA_M (MCPWM_FAULT0_CLR_INT_ENA_V << MCPWM_FAULT0_CLR_INT_ENA_S) +#define MCPWM_FAULT0_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ENA_S 12 +/** MCPWM_FAULT1_CLR_INT_ENA : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ENA_M (MCPWM_FAULT1_CLR_INT_ENA_V << MCPWM_FAULT1_CLR_INT_ENA_S) +#define MCPWM_FAULT1_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ENA_S 13 +/** MCPWM_FAULT2_CLR_INT_ENA : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ENA_M (MCPWM_FAULT2_CLR_INT_ENA_V << MCPWM_FAULT2_CLR_INT_ENA_S) +#define MCPWM_FAULT2_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ENA_S 14 +/** MCPWM_OP0_TEA_INT_ENA : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ENA (BIT(15)) +#define MCPWM_OP0_TEA_INT_ENA_M (MCPWM_OP0_TEA_INT_ENA_V << MCPWM_OP0_TEA_INT_ENA_S) +#define MCPWM_OP0_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ENA_S 15 +/** MCPWM_OP1_TEA_INT_ENA : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ENA (BIT(16)) +#define MCPWM_OP1_TEA_INT_ENA_M (MCPWM_OP1_TEA_INT_ENA_V << MCPWM_OP1_TEA_INT_ENA_S) +#define MCPWM_OP1_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ENA_S 16 +/** MCPWM_OP2_TEA_INT_ENA : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ENA (BIT(17)) +#define MCPWM_OP2_TEA_INT_ENA_M (MCPWM_OP2_TEA_INT_ENA_V << MCPWM_OP2_TEA_INT_ENA_S) +#define MCPWM_OP2_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ENA_S 17 +/** MCPWM_OP0_TEB_INT_ENA : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ENA (BIT(18)) +#define MCPWM_OP0_TEB_INT_ENA_M (MCPWM_OP0_TEB_INT_ENA_V << MCPWM_OP0_TEB_INT_ENA_S) +#define MCPWM_OP0_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ENA_S 18 +/** MCPWM_OP1_TEB_INT_ENA : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ENA (BIT(19)) +#define MCPWM_OP1_TEB_INT_ENA_M (MCPWM_OP1_TEB_INT_ENA_V << MCPWM_OP1_TEB_INT_ENA_S) +#define MCPWM_OP1_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ENA_S 19 +/** MCPWM_OP2_TEB_INT_ENA : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ENA (BIT(20)) +#define MCPWM_OP2_TEB_INT_ENA_M (MCPWM_OP2_TEB_INT_ENA_V << MCPWM_OP2_TEB_INT_ENA_S) +#define MCPWM_OP2_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ENA_S 20 +/** MCPWM_FH0_CBC_INT_ENA : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ENA (BIT(21)) +#define MCPWM_FH0_CBC_INT_ENA_M (MCPWM_FH0_CBC_INT_ENA_V << MCPWM_FH0_CBC_INT_ENA_S) +#define MCPWM_FH0_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ENA_S 21 +/** MCPWM_FH1_CBC_INT_ENA : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ENA (BIT(22)) +#define MCPWM_FH1_CBC_INT_ENA_M (MCPWM_FH1_CBC_INT_ENA_V << MCPWM_FH1_CBC_INT_ENA_S) +#define MCPWM_FH1_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ENA_S 22 +/** MCPWM_FH2_CBC_INT_ENA : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ENA (BIT(23)) +#define MCPWM_FH2_CBC_INT_ENA_M (MCPWM_FH2_CBC_INT_ENA_V << MCPWM_FH2_CBC_INT_ENA_S) +#define MCPWM_FH2_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ENA_S 23 +/** MCPWM_FH0_OST_INT_ENA : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ENA (BIT(24)) +#define MCPWM_FH0_OST_INT_ENA_M (MCPWM_FH0_OST_INT_ENA_V << MCPWM_FH0_OST_INT_ENA_S) +#define MCPWM_FH0_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH0_OST_INT_ENA_S 24 +/** MCPWM_FH1_OST_INT_ENA : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ENA (BIT(25)) +#define MCPWM_FH1_OST_INT_ENA_M (MCPWM_FH1_OST_INT_ENA_V << MCPWM_FH1_OST_INT_ENA_S) +#define MCPWM_FH1_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH1_OST_INT_ENA_S 25 +/** MCPWM_FH2_OST_INT_ENA : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ENA (BIT(26)) +#define MCPWM_FH2_OST_INT_ENA_M (MCPWM_FH2_OST_INT_ENA_V << MCPWM_FH2_OST_INT_ENA_S) +#define MCPWM_FH2_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH2_OST_INT_ENA_S 26 +/** MCPWM_CAP0_INT_ENA : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ENA (BIT(27)) +#define MCPWM_CAP0_INT_ENA_M (MCPWM_CAP0_INT_ENA_V << MCPWM_CAP0_INT_ENA_S) +#define MCPWM_CAP0_INT_ENA_V 0x00000001U +#define MCPWM_CAP0_INT_ENA_S 27 +/** MCPWM_CAP1_INT_ENA : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ENA (BIT(28)) +#define MCPWM_CAP1_INT_ENA_M (MCPWM_CAP1_INT_ENA_V << MCPWM_CAP1_INT_ENA_S) +#define MCPWM_CAP1_INT_ENA_V 0x00000001U +#define MCPWM_CAP1_INT_ENA_S 28 +/** MCPWM_CAP2_INT_ENA : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ENA (BIT(29)) +#define MCPWM_CAP2_INT_ENA_M (MCPWM_CAP2_INT_ENA_V << MCPWM_CAP2_INT_ENA_S) +#define MCPWM_CAP2_INT_ENA_V 0x00000001U +#define MCPWM_CAP2_INT_ENA_S 29 -#define MCPWM_INT_RAW_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x114) -/* MCPWM_CAP2_INT_RAW : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_RAW (BIT(29)) -#define MCPWM_CAP2_INT_RAW_M (BIT(29)) -#define MCPWM_CAP2_INT_RAW_V 0x1 -#define MCPWM_CAP2_INT_RAW_S 29 -/* MCPWM_CAP1_INT_RAW : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_RAW (BIT(28)) -#define MCPWM_CAP1_INT_RAW_M (BIT(28)) -#define MCPWM_CAP1_INT_RAW_V 0x1 -#define MCPWM_CAP1_INT_RAW_S 28 -/* MCPWM_CAP0_INT_RAW : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_RAW (BIT(27)) -#define MCPWM_CAP0_INT_RAW_M (BIT(27)) -#define MCPWM_CAP0_INT_RAW_V 0x1 -#define MCPWM_CAP0_INT_RAW_S 27 -/* MCPWM_TZ2_OST_INT_RAW : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_RAW (BIT(26)) -#define MCPWM_TZ2_OST_INT_RAW_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_RAW_V 0x1 -#define MCPWM_TZ2_OST_INT_RAW_S 26 -/* MCPWM_TZ1_OST_INT_RAW : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_RAW (BIT(25)) -#define MCPWM_TZ1_OST_INT_RAW_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_RAW_V 0x1 -#define MCPWM_TZ1_OST_INT_RAW_S 25 -/* MCPWM_TZ0_OST_INT_RAW : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_RAW (BIT(24)) -#define MCPWM_TZ0_OST_INT_RAW_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_RAW_V 0x1 -#define MCPWM_TZ0_OST_INT_RAW_S 24 -/* MCPWM_TZ2_CBC_INT_RAW : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_RAW (BIT(23)) -#define MCPWM_TZ2_CBC_INT_RAW_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_RAW_V 0x1 -#define MCPWM_TZ2_CBC_INT_RAW_S 23 -/* MCPWM_TZ1_CBC_INT_RAW : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_RAW (BIT(22)) -#define MCPWM_TZ1_CBC_INT_RAW_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_RAW_V 0x1 -#define MCPWM_TZ1_CBC_INT_RAW_S 22 -/* MCPWM_TZ0_CBC_INT_RAW : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_RAW (BIT(21)) -#define MCPWM_TZ0_CBC_INT_RAW_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_RAW_V 0x1 -#define MCPWM_TZ0_CBC_INT_RAW_S 21 -/* MCPWM_CMPR2_TEB_INT_RAW : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_RAW (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_RAW_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_RAW_V 0x1 -#define MCPWM_CMPR2_TEB_INT_RAW_S 20 -/* MCPWM_CMPR1_TEB_INT_RAW : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_RAW (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_RAW_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_RAW_V 0x1 -#define MCPWM_CMPR1_TEB_INT_RAW_S 19 -/* MCPWM_CMPR0_TEB_INT_RAW : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_RAW (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_RAW_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_RAW_V 0x1 -#define MCPWM_CMPR0_TEB_INT_RAW_S 18 -/* MCPWM_CMPR2_TEA_INT_RAW : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_RAW (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_RAW_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_RAW_V 0x1 -#define MCPWM_CMPR2_TEA_INT_RAW_S 17 -/* MCPWM_CMPR1_TEA_INT_RAW : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_RAW (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_RAW_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_RAW_V 0x1 -#define MCPWM_CMPR1_TEA_INT_RAW_S 16 -/* MCPWM_CMPR0_TEA_INT_RAW : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_RAW (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_RAW_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_RAW_V 0x1 -#define MCPWM_CMPR0_TEA_INT_RAW_S 15 -/* MCPWM_FAULT2_CLR_INT_RAW : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT2_CLR_INT_RAW_S 14 -/* MCPWM_FAULT1_CLR_INT_RAW : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT1_CLR_INT_RAW_S 13 -/* MCPWM_FAULT0_CLR_INT_RAW : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT0_CLR_INT_RAW_S 12 -/* MCPWM_FAULT2_INT_RAW : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_RAW (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_M (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_V 0x1 -#define MCPWM_FAULT2_INT_RAW_S 11 -/* MCPWM_FAULT1_INT_RAW : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_RAW (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_M (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_V 0x1 -#define MCPWM_FAULT1_INT_RAW_S 10 -/* MCPWM_FAULT0_INT_RAW : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_RAW (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_M (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_V 0x1 -#define MCPWM_FAULT0_INT_RAW_S 9 -/* MCPWM_TIMER2_TEP_INT_RAW : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEP_INT_RAW_S 8 -/* MCPWM_TIMER1_TEP_INT_RAW : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEP_INT_RAW_S 7 -/* MCPWM_TIMER0_TEP_INT_RAW : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEP_INT_RAW_S 6 -/* MCPWM_TIMER2_TEZ_INT_RAW : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 -/* MCPWM_TIMER1_TEZ_INT_RAW : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 -/* MCPWM_TIMER0_TEZ_INT_RAW : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 -/* MCPWM_TIMER2_STOP_INT_RAW : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_STOP_INT_RAW_S 2 -/* MCPWM_TIMER1_STOP_INT_RAW : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_STOP_INT_RAW_S 1 -/* MCPWM_TIMER0_STOP_INT_RAW : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_RAW_REG register + * Raw interrupt status + */ +#define MCPWM_INT_RAW_REG(i) (DR_REG_MCPWM_BASE(i) + 0x114) +/** MCPWM_TIMER0_STOP_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_RAW (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_V 0x1 +#define MCPWM_TIMER0_STOP_INT_RAW_M (MCPWM_TIMER0_STOP_INT_RAW_V << MCPWM_TIMER0_STOP_INT_RAW_S) +#define MCPWM_TIMER0_STOP_INT_RAW_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_RAW_S 0 +/** MCPWM_TIMER1_STOP_INT_RAW : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_RAW_M (MCPWM_TIMER1_STOP_INT_RAW_V << MCPWM_TIMER1_STOP_INT_RAW_S) +#define MCPWM_TIMER1_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_RAW_S 1 +/** MCPWM_TIMER2_STOP_INT_RAW : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_RAW_M (MCPWM_TIMER2_STOP_INT_RAW_V << MCPWM_TIMER2_STOP_INT_RAW_S) +#define MCPWM_TIMER2_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_RAW_S 2 +/** MCPWM_TIMER0_TEZ_INT_RAW : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_RAW_M (MCPWM_TIMER0_TEZ_INT_RAW_V << MCPWM_TIMER0_TEZ_INT_RAW_S) +#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 +/** MCPWM_TIMER1_TEZ_INT_RAW : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_RAW_M (MCPWM_TIMER1_TEZ_INT_RAW_V << MCPWM_TIMER1_TEZ_INT_RAW_S) +#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 +/** MCPWM_TIMER2_TEZ_INT_RAW : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_RAW_M (MCPWM_TIMER2_TEZ_INT_RAW_V << MCPWM_TIMER2_TEZ_INT_RAW_S) +#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 +/** MCPWM_TIMER0_TEP_INT_RAW : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_RAW_M (MCPWM_TIMER0_TEP_INT_RAW_V << MCPWM_TIMER0_TEP_INT_RAW_S) +#define MCPWM_TIMER0_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_RAW_S 6 +/** MCPWM_TIMER1_TEP_INT_RAW : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_RAW_M (MCPWM_TIMER1_TEP_INT_RAW_V << MCPWM_TIMER1_TEP_INT_RAW_S) +#define MCPWM_TIMER1_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_RAW_S 7 +/** MCPWM_TIMER2_TEP_INT_RAW : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_RAW_M (MCPWM_TIMER2_TEP_INT_RAW_V << MCPWM_TIMER2_TEP_INT_RAW_S) +#define MCPWM_TIMER2_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_RAW_S 8 +/** MCPWM_FAULT0_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_RAW (BIT(9)) +#define MCPWM_FAULT0_INT_RAW_M (MCPWM_FAULT0_INT_RAW_V << MCPWM_FAULT0_INT_RAW_S) +#define MCPWM_FAULT0_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_INT_RAW_S 9 +/** MCPWM_FAULT1_INT_RAW : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_RAW (BIT(10)) +#define MCPWM_FAULT1_INT_RAW_M (MCPWM_FAULT1_INT_RAW_V << MCPWM_FAULT1_INT_RAW_S) +#define MCPWM_FAULT1_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_INT_RAW_S 10 +/** MCPWM_FAULT2_INT_RAW : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_RAW (BIT(11)) +#define MCPWM_FAULT2_INT_RAW_M (MCPWM_FAULT2_INT_RAW_V << MCPWM_FAULT2_INT_RAW_S) +#define MCPWM_FAULT2_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_INT_RAW_S 11 +/** MCPWM_FAULT0_CLR_INT_RAW : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_RAW_M (MCPWM_FAULT0_CLR_INT_RAW_V << MCPWM_FAULT0_CLR_INT_RAW_S) +#define MCPWM_FAULT0_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_RAW_S 12 +/** MCPWM_FAULT1_CLR_INT_RAW : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_RAW_M (MCPWM_FAULT1_CLR_INT_RAW_V << MCPWM_FAULT1_CLR_INT_RAW_S) +#define MCPWM_FAULT1_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_RAW_S 13 +/** MCPWM_FAULT2_CLR_INT_RAW : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_RAW_M (MCPWM_FAULT2_CLR_INT_RAW_V << MCPWM_FAULT2_CLR_INT_RAW_S) +#define MCPWM_FAULT2_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_RAW_S 14 +/** MCPWM_OP0_TEA_INT_RAW : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_RAW (BIT(15)) +#define MCPWM_OP0_TEA_INT_RAW_M (MCPWM_OP0_TEA_INT_RAW_V << MCPWM_OP0_TEA_INT_RAW_S) +#define MCPWM_OP0_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEA_INT_RAW_S 15 +/** MCPWM_OP1_TEA_INT_RAW : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_RAW (BIT(16)) +#define MCPWM_OP1_TEA_INT_RAW_M (MCPWM_OP1_TEA_INT_RAW_V << MCPWM_OP1_TEA_INT_RAW_S) +#define MCPWM_OP1_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEA_INT_RAW_S 16 +/** MCPWM_OP2_TEA_INT_RAW : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_RAW (BIT(17)) +#define MCPWM_OP2_TEA_INT_RAW_M (MCPWM_OP2_TEA_INT_RAW_V << MCPWM_OP2_TEA_INT_RAW_S) +#define MCPWM_OP2_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEA_INT_RAW_S 17 +/** MCPWM_OP0_TEB_INT_RAW : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_RAW (BIT(18)) +#define MCPWM_OP0_TEB_INT_RAW_M (MCPWM_OP0_TEB_INT_RAW_V << MCPWM_OP0_TEB_INT_RAW_S) +#define MCPWM_OP0_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEB_INT_RAW_S 18 +/** MCPWM_OP1_TEB_INT_RAW : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_RAW (BIT(19)) +#define MCPWM_OP1_TEB_INT_RAW_M (MCPWM_OP1_TEB_INT_RAW_V << MCPWM_OP1_TEB_INT_RAW_S) +#define MCPWM_OP1_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEB_INT_RAW_S 19 +/** MCPWM_OP2_TEB_INT_RAW : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_RAW (BIT(20)) +#define MCPWM_OP2_TEB_INT_RAW_M (MCPWM_OP2_TEB_INT_RAW_V << MCPWM_OP2_TEB_INT_RAW_S) +#define MCPWM_OP2_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEB_INT_RAW_S 20 +/** MCPWM_FH0_CBC_INT_RAW : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_RAW (BIT(21)) +#define MCPWM_FH0_CBC_INT_RAW_M (MCPWM_FH0_CBC_INT_RAW_V << MCPWM_FH0_CBC_INT_RAW_S) +#define MCPWM_FH0_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH0_CBC_INT_RAW_S 21 +/** MCPWM_FH1_CBC_INT_RAW : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_RAW (BIT(22)) +#define MCPWM_FH1_CBC_INT_RAW_M (MCPWM_FH1_CBC_INT_RAW_V << MCPWM_FH1_CBC_INT_RAW_S) +#define MCPWM_FH1_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH1_CBC_INT_RAW_S 22 +/** MCPWM_FH2_CBC_INT_RAW : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_RAW (BIT(23)) +#define MCPWM_FH2_CBC_INT_RAW_M (MCPWM_FH2_CBC_INT_RAW_V << MCPWM_FH2_CBC_INT_RAW_S) +#define MCPWM_FH2_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH2_CBC_INT_RAW_S 23 +/** MCPWM_FH0_OST_INT_RAW : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_RAW (BIT(24)) +#define MCPWM_FH0_OST_INT_RAW_M (MCPWM_FH0_OST_INT_RAW_V << MCPWM_FH0_OST_INT_RAW_S) +#define MCPWM_FH0_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH0_OST_INT_RAW_S 24 +/** MCPWM_FH1_OST_INT_RAW : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_RAW (BIT(25)) +#define MCPWM_FH1_OST_INT_RAW_M (MCPWM_FH1_OST_INT_RAW_V << MCPWM_FH1_OST_INT_RAW_S) +#define MCPWM_FH1_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH1_OST_INT_RAW_S 25 +/** MCPWM_FH2_OST_INT_RAW : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_RAW (BIT(26)) +#define MCPWM_FH2_OST_INT_RAW_M (MCPWM_FH2_OST_INT_RAW_V << MCPWM_FH2_OST_INT_RAW_S) +#define MCPWM_FH2_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH2_OST_INT_RAW_S 26 +/** MCPWM_CAP0_INT_RAW : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_RAW (BIT(27)) +#define MCPWM_CAP0_INT_RAW_M (MCPWM_CAP0_INT_RAW_V << MCPWM_CAP0_INT_RAW_S) +#define MCPWM_CAP0_INT_RAW_V 0x00000001U +#define MCPWM_CAP0_INT_RAW_S 27 +/** MCPWM_CAP1_INT_RAW : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_RAW (BIT(28)) +#define MCPWM_CAP1_INT_RAW_M (MCPWM_CAP1_INT_RAW_V << MCPWM_CAP1_INT_RAW_S) +#define MCPWM_CAP1_INT_RAW_V 0x00000001U +#define MCPWM_CAP1_INT_RAW_S 28 +/** MCPWM_CAP2_INT_RAW : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_RAW (BIT(29)) +#define MCPWM_CAP2_INT_RAW_M (MCPWM_CAP2_INT_RAW_V << MCPWM_CAP2_INT_RAW_S) +#define MCPWM_CAP2_INT_RAW_V 0x00000001U +#define MCPWM_CAP2_INT_RAW_S 29 -#define MCPWM_INT_ST_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x118) -/* MCPWM_CAP2_INT_ST : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_ST (BIT(29)) -#define MCPWM_CAP2_INT_ST_M (BIT(29)) -#define MCPWM_CAP2_INT_ST_V 0x1 -#define MCPWM_CAP2_INT_ST_S 29 -/* MCPWM_CAP1_INT_ST : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_ST (BIT(28)) -#define MCPWM_CAP1_INT_ST_M (BIT(28)) -#define MCPWM_CAP1_INT_ST_V 0x1 -#define MCPWM_CAP1_INT_ST_S 28 -/* MCPWM_CAP0_INT_ST : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_ST (BIT(27)) -#define MCPWM_CAP0_INT_ST_M (BIT(27)) -#define MCPWM_CAP0_INT_ST_V 0x1 -#define MCPWM_CAP0_INT_ST_S 27 -/* MCPWM_TZ2_OST_INT_ST : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_ST (BIT(26)) -#define MCPWM_TZ2_OST_INT_ST_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_ST_V 0x1 -#define MCPWM_TZ2_OST_INT_ST_S 26 -/* MCPWM_TZ1_OST_INT_ST : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_ST (BIT(25)) -#define MCPWM_TZ1_OST_INT_ST_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_ST_V 0x1 -#define MCPWM_TZ1_OST_INT_ST_S 25 -/* MCPWM_TZ0_OST_INT_ST : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_ST (BIT(24)) -#define MCPWM_TZ0_OST_INT_ST_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_ST_V 0x1 -#define MCPWM_TZ0_OST_INT_ST_S 24 -/* MCPWM_TZ2_CBC_INT_ST : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_ST (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ST_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ST_V 0x1 -#define MCPWM_TZ2_CBC_INT_ST_S 23 -/* MCPWM_TZ1_CBC_INT_ST : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_ST (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ST_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ST_V 0x1 -#define MCPWM_TZ1_CBC_INT_ST_S 22 -/* MCPWM_TZ0_CBC_INT_ST : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_ST (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ST_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ST_V 0x1 -#define MCPWM_TZ0_CBC_INT_ST_S 21 -/* MCPWM_CMPR2_TEB_INT_ST : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_ST (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ST_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ST_V 0x1 -#define MCPWM_CMPR2_TEB_INT_ST_S 20 -/* MCPWM_CMPR1_TEB_INT_ST : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_ST (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ST_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ST_V 0x1 -#define MCPWM_CMPR1_TEB_INT_ST_S 19 -/* MCPWM_CMPR0_TEB_INT_ST : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_ST (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ST_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ST_V 0x1 -#define MCPWM_CMPR0_TEB_INT_ST_S 18 -/* MCPWM_CMPR2_TEA_INT_ST : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_ST (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ST_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ST_V 0x1 -#define MCPWM_CMPR2_TEA_INT_ST_S 17 -/* MCPWM_CMPR1_TEA_INT_ST : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_ST (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ST_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ST_V 0x1 -#define MCPWM_CMPR1_TEA_INT_ST_S 16 -/* MCPWM_CMPR0_TEA_INT_ST : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_ST (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ST_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ST_V 0x1 -#define MCPWM_CMPR0_TEA_INT_ST_S 15 -/* MCPWM_FAULT2_CLR_INT_ST : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ST_S 14 -/* MCPWM_FAULT1_CLR_INT_ST : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ST_S 13 -/* MCPWM_FAULT0_CLR_INT_ST : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ST_S 12 -/* MCPWM_FAULT2_INT_ST : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_ST (BIT(11)) -#define MCPWM_FAULT2_INT_ST_M (BIT(11)) -#define MCPWM_FAULT2_INT_ST_V 0x1 -#define MCPWM_FAULT2_INT_ST_S 11 -/* MCPWM_FAULT1_INT_ST : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_ST (BIT(10)) -#define MCPWM_FAULT1_INT_ST_M (BIT(10)) -#define MCPWM_FAULT1_INT_ST_V 0x1 -#define MCPWM_FAULT1_INT_ST_S 10 -/* MCPWM_FAULT0_INT_ST : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_ST (BIT(9)) -#define MCPWM_FAULT0_INT_ST_M (BIT(9)) -#define MCPWM_FAULT0_INT_ST_V 0x1 -#define MCPWM_FAULT0_INT_ST_S 9 -/* MCPWM_TIMER2_TEP_INT_ST : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ST_S 8 -/* MCPWM_TIMER1_TEP_INT_ST : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ST_S 7 -/* MCPWM_TIMER0_TEP_INT_ST : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ST_S 6 -/* MCPWM_TIMER2_TEZ_INT_ST : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ST_S 5 -/* MCPWM_TIMER1_TEZ_INT_ST : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ST_S 4 -/* MCPWM_TIMER0_TEZ_INT_ST : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ST_S 3 -/* MCPWM_TIMER2_STOP_INT_ST : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ST_S 2 -/* MCPWM_TIMER1_STOP_INT_ST : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ST_S 1 -/* MCPWM_TIMER0_STOP_INT_ST : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_ST_REG register + * Masked interrupt status + */ +#define MCPWM_INT_ST_REG(i) (DR_REG_MCPWM_BASE(i) + 0x118) +/** MCPWM_TIMER0_STOP_INT_ST : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_ST (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_V 0x1 +#define MCPWM_TIMER0_STOP_INT_ST_M (MCPWM_TIMER0_STOP_INT_ST_V << MCPWM_TIMER0_STOP_INT_ST_S) +#define MCPWM_TIMER0_STOP_INT_ST_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ST_S 0 +/** MCPWM_TIMER1_STOP_INT_ST : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ST_M (MCPWM_TIMER1_STOP_INT_ST_V << MCPWM_TIMER1_STOP_INT_ST_S) +#define MCPWM_TIMER1_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ST_S 1 +/** MCPWM_TIMER2_STOP_INT_ST : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ST_M (MCPWM_TIMER2_STOP_INT_ST_V << MCPWM_TIMER2_STOP_INT_ST_S) +#define MCPWM_TIMER2_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ST_S 2 +/** MCPWM_TIMER0_TEZ_INT_ST : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ST_M (MCPWM_TIMER0_TEZ_INT_ST_V << MCPWM_TIMER0_TEZ_INT_ST_S) +#define MCPWM_TIMER0_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ST_S 3 +/** MCPWM_TIMER1_TEZ_INT_ST : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ST_M (MCPWM_TIMER1_TEZ_INT_ST_V << MCPWM_TIMER1_TEZ_INT_ST_S) +#define MCPWM_TIMER1_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ST_S 4 +/** MCPWM_TIMER2_TEZ_INT_ST : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ST_M (MCPWM_TIMER2_TEZ_INT_ST_V << MCPWM_TIMER2_TEZ_INT_ST_S) +#define MCPWM_TIMER2_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ST_S 5 +/** MCPWM_TIMER0_TEP_INT_ST : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ST_M (MCPWM_TIMER0_TEP_INT_ST_V << MCPWM_TIMER0_TEP_INT_ST_S) +#define MCPWM_TIMER0_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ST_S 6 +/** MCPWM_TIMER1_TEP_INT_ST : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ST_M (MCPWM_TIMER1_TEP_INT_ST_V << MCPWM_TIMER1_TEP_INT_ST_S) +#define MCPWM_TIMER1_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ST_S 7 +/** MCPWM_TIMER2_TEP_INT_ST : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ST_M (MCPWM_TIMER2_TEP_INT_ST_V << MCPWM_TIMER2_TEP_INT_ST_S) +#define MCPWM_TIMER2_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ST_S 8 +/** MCPWM_FAULT0_INT_ST : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ST (BIT(9)) +#define MCPWM_FAULT0_INT_ST_M (MCPWM_FAULT0_INT_ST_V << MCPWM_FAULT0_INT_ST_S) +#define MCPWM_FAULT0_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_INT_ST_S 9 +/** MCPWM_FAULT1_INT_ST : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ST (BIT(10)) +#define MCPWM_FAULT1_INT_ST_M (MCPWM_FAULT1_INT_ST_V << MCPWM_FAULT1_INT_ST_S) +#define MCPWM_FAULT1_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_INT_ST_S 10 +/** MCPWM_FAULT2_INT_ST : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ST (BIT(11)) +#define MCPWM_FAULT2_INT_ST_M (MCPWM_FAULT2_INT_ST_V << MCPWM_FAULT2_INT_ST_S) +#define MCPWM_FAULT2_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_INT_ST_S 11 +/** MCPWM_FAULT0_CLR_INT_ST : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ST_M (MCPWM_FAULT0_CLR_INT_ST_V << MCPWM_FAULT0_CLR_INT_ST_S) +#define MCPWM_FAULT0_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ST_S 12 +/** MCPWM_FAULT1_CLR_INT_ST : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ST_M (MCPWM_FAULT1_CLR_INT_ST_V << MCPWM_FAULT1_CLR_INT_ST_S) +#define MCPWM_FAULT1_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ST_S 13 +/** MCPWM_FAULT2_CLR_INT_ST : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ST_M (MCPWM_FAULT2_CLR_INT_ST_V << MCPWM_FAULT2_CLR_INT_ST_S) +#define MCPWM_FAULT2_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ST_S 14 +/** MCPWM_OP0_TEA_INT_ST : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ST (BIT(15)) +#define MCPWM_OP0_TEA_INT_ST_M (MCPWM_OP0_TEA_INT_ST_V << MCPWM_OP0_TEA_INT_ST_S) +#define MCPWM_OP0_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ST_S 15 +/** MCPWM_OP1_TEA_INT_ST : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ST (BIT(16)) +#define MCPWM_OP1_TEA_INT_ST_M (MCPWM_OP1_TEA_INT_ST_V << MCPWM_OP1_TEA_INT_ST_S) +#define MCPWM_OP1_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ST_S 16 +/** MCPWM_OP2_TEA_INT_ST : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ST (BIT(17)) +#define MCPWM_OP2_TEA_INT_ST_M (MCPWM_OP2_TEA_INT_ST_V << MCPWM_OP2_TEA_INT_ST_S) +#define MCPWM_OP2_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ST_S 17 +/** MCPWM_OP0_TEB_INT_ST : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ST (BIT(18)) +#define MCPWM_OP0_TEB_INT_ST_M (MCPWM_OP0_TEB_INT_ST_V << MCPWM_OP0_TEB_INT_ST_S) +#define MCPWM_OP0_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ST_S 18 +/** MCPWM_OP1_TEB_INT_ST : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ST (BIT(19)) +#define MCPWM_OP1_TEB_INT_ST_M (MCPWM_OP1_TEB_INT_ST_V << MCPWM_OP1_TEB_INT_ST_S) +#define MCPWM_OP1_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ST_S 19 +/** MCPWM_OP2_TEB_INT_ST : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ST (BIT(20)) +#define MCPWM_OP2_TEB_INT_ST_M (MCPWM_OP2_TEB_INT_ST_V << MCPWM_OP2_TEB_INT_ST_S) +#define MCPWM_OP2_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ST_S 20 +/** MCPWM_FH0_CBC_INT_ST : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ST (BIT(21)) +#define MCPWM_FH0_CBC_INT_ST_M (MCPWM_FH0_CBC_INT_ST_V << MCPWM_FH0_CBC_INT_ST_S) +#define MCPWM_FH0_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ST_S 21 +/** MCPWM_FH1_CBC_INT_ST : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ST (BIT(22)) +#define MCPWM_FH1_CBC_INT_ST_M (MCPWM_FH1_CBC_INT_ST_V << MCPWM_FH1_CBC_INT_ST_S) +#define MCPWM_FH1_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ST_S 22 +/** MCPWM_FH2_CBC_INT_ST : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ST (BIT(23)) +#define MCPWM_FH2_CBC_INT_ST_M (MCPWM_FH2_CBC_INT_ST_V << MCPWM_FH2_CBC_INT_ST_S) +#define MCPWM_FH2_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ST_S 23 +/** MCPWM_FH0_OST_INT_ST : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ST (BIT(24)) +#define MCPWM_FH0_OST_INT_ST_M (MCPWM_FH0_OST_INT_ST_V << MCPWM_FH0_OST_INT_ST_S) +#define MCPWM_FH0_OST_INT_ST_V 0x00000001U +#define MCPWM_FH0_OST_INT_ST_S 24 +/** MCPWM_FH1_OST_INT_ST : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ST (BIT(25)) +#define MCPWM_FH1_OST_INT_ST_M (MCPWM_FH1_OST_INT_ST_V << MCPWM_FH1_OST_INT_ST_S) +#define MCPWM_FH1_OST_INT_ST_V 0x00000001U +#define MCPWM_FH1_OST_INT_ST_S 25 +/** MCPWM_FH2_OST_INT_ST : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ST (BIT(26)) +#define MCPWM_FH2_OST_INT_ST_M (MCPWM_FH2_OST_INT_ST_V << MCPWM_FH2_OST_INT_ST_S) +#define MCPWM_FH2_OST_INT_ST_V 0x00000001U +#define MCPWM_FH2_OST_INT_ST_S 26 +/** MCPWM_CAP0_INT_ST : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ST (BIT(27)) +#define MCPWM_CAP0_INT_ST_M (MCPWM_CAP0_INT_ST_V << MCPWM_CAP0_INT_ST_S) +#define MCPWM_CAP0_INT_ST_V 0x00000001U +#define MCPWM_CAP0_INT_ST_S 27 +/** MCPWM_CAP1_INT_ST : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ST (BIT(28)) +#define MCPWM_CAP1_INT_ST_M (MCPWM_CAP1_INT_ST_V << MCPWM_CAP1_INT_ST_S) +#define MCPWM_CAP1_INT_ST_V 0x00000001U +#define MCPWM_CAP1_INT_ST_S 28 +/** MCPWM_CAP2_INT_ST : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ST (BIT(29)) +#define MCPWM_CAP2_INT_ST_M (MCPWM_CAP2_INT_ST_V << MCPWM_CAP2_INT_ST_S) +#define MCPWM_CAP2_INT_ST_V 0x00000001U +#define MCPWM_CAP2_INT_ST_S 29 -#define MCPWM_INT_CLR_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x11C) -/* MCPWM_CAP2_INT_CLR : WO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_CLR (BIT(29)) -#define MCPWM_CAP2_INT_CLR_M (BIT(29)) -#define MCPWM_CAP2_INT_CLR_V 0x1 -#define MCPWM_CAP2_INT_CLR_S 29 -/* MCPWM_CAP1_INT_CLR : WO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_CLR (BIT(28)) -#define MCPWM_CAP1_INT_CLR_M (BIT(28)) -#define MCPWM_CAP1_INT_CLR_V 0x1 -#define MCPWM_CAP1_INT_CLR_S 28 -/* MCPWM_CAP0_INT_CLR : WO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_CLR (BIT(27)) -#define MCPWM_CAP0_INT_CLR_M (BIT(27)) -#define MCPWM_CAP0_INT_CLR_V 0x1 -#define MCPWM_CAP0_INT_CLR_S 27 -/* MCPWM_TZ2_OST_INT_CLR : WO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_CLR (BIT(26)) -#define MCPWM_TZ2_OST_INT_CLR_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_CLR_V 0x1 -#define MCPWM_TZ2_OST_INT_CLR_S 26 -/* MCPWM_TZ1_OST_INT_CLR : WO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_CLR (BIT(25)) -#define MCPWM_TZ1_OST_INT_CLR_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_CLR_V 0x1 -#define MCPWM_TZ1_OST_INT_CLR_S 25 -/* MCPWM_TZ0_OST_INT_CLR : WO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_CLR (BIT(24)) -#define MCPWM_TZ0_OST_INT_CLR_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_CLR_V 0x1 -#define MCPWM_TZ0_OST_INT_CLR_S 24 -/* MCPWM_TZ2_CBC_INT_CLR : WO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_CLR (BIT(23)) -#define MCPWM_TZ2_CBC_INT_CLR_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_CLR_V 0x1 -#define MCPWM_TZ2_CBC_INT_CLR_S 23 -/* MCPWM_TZ1_CBC_INT_CLR : WO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_CLR (BIT(22)) -#define MCPWM_TZ1_CBC_INT_CLR_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_CLR_V 0x1 -#define MCPWM_TZ1_CBC_INT_CLR_S 22 -/* MCPWM_TZ0_CBC_INT_CLR : WO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_CLR (BIT(21)) -#define MCPWM_TZ0_CBC_INT_CLR_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_CLR_V 0x1 -#define MCPWM_TZ0_CBC_INT_CLR_S 21 -/* MCPWM_CMPR2_TEB_INT_CLR : WO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_CLR (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_CLR_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_CLR_V 0x1 -#define MCPWM_CMPR2_TEB_INT_CLR_S 20 -/* MCPWM_CMPR1_TEB_INT_CLR : WO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_CLR (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_CLR_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_CLR_V 0x1 -#define MCPWM_CMPR1_TEB_INT_CLR_S 19 -/* MCPWM_CMPR0_TEB_INT_CLR : WO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_CLR (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_CLR_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_CLR_V 0x1 -#define MCPWM_CMPR0_TEB_INT_CLR_S 18 -/* MCPWM_CMPR2_TEA_INT_CLR : WO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_CLR (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_CLR_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_CLR_V 0x1 -#define MCPWM_CMPR2_TEA_INT_CLR_S 17 -/* MCPWM_CMPR1_TEA_INT_CLR : WO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_CLR (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_CLR_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_CLR_V 0x1 -#define MCPWM_CMPR1_TEA_INT_CLR_S 16 -/* MCPWM_CMPR0_TEA_INT_CLR : WO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_CLR (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_CLR_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_CLR_V 0x1 -#define MCPWM_CMPR0_TEA_INT_CLR_S 15 -/* MCPWM_FAULT2_CLR_INT_CLR : WO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT2_CLR_INT_CLR_S 14 -/* MCPWM_FAULT1_CLR_INT_CLR : WO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT1_CLR_INT_CLR_S 13 -/* MCPWM_FAULT0_CLR_INT_CLR : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT0_CLR_INT_CLR_S 12 -/* MCPWM_FAULT2_INT_CLR : WO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_CLR (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_M (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_V 0x1 -#define MCPWM_FAULT2_INT_CLR_S 11 -/* MCPWM_FAULT1_INT_CLR : WO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_CLR (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_M (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_V 0x1 -#define MCPWM_FAULT1_INT_CLR_S 10 -/* MCPWM_FAULT0_INT_CLR : WO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_CLR (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_M (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_V 0x1 -#define MCPWM_FAULT0_INT_CLR_S 9 -/* MCPWM_TIMER2_TEP_INT_CLR : WO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEP_INT_CLR_S 8 -/* MCPWM_TIMER1_TEP_INT_CLR : WO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEP_INT_CLR_S 7 -/* MCPWM_TIMER0_TEP_INT_CLR : WO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEP_INT_CLR_S 6 -/* MCPWM_TIMER2_TEZ_INT_CLR : WO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 -/* MCPWM_TIMER1_TEZ_INT_CLR : WO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 -/* MCPWM_TIMER0_TEZ_INT_CLR : WO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 -/* MCPWM_TIMER2_STOP_INT_CLR : WO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_STOP_INT_CLR_S 2 -/* MCPWM_TIMER1_STOP_INT_CLR : WO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_STOP_INT_CLR_S 1 -/* MCPWM_TIMER0_STOP_INT_CLR : WO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_CLR_REG register + * Interrupt clear bits + */ +#define MCPWM_INT_CLR_REG(i) (DR_REG_MCPWM_BASE(i) + 0x11c) +/** MCPWM_TIMER0_STOP_INT_CLR : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_CLR (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_V 0x1 +#define MCPWM_TIMER0_STOP_INT_CLR_M (MCPWM_TIMER0_STOP_INT_CLR_V << MCPWM_TIMER0_STOP_INT_CLR_S) +#define MCPWM_TIMER0_STOP_INT_CLR_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_CLR_S 0 +/** MCPWM_TIMER1_STOP_INT_CLR : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_CLR_M (MCPWM_TIMER1_STOP_INT_CLR_V << MCPWM_TIMER1_STOP_INT_CLR_S) +#define MCPWM_TIMER1_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_CLR_S 1 +/** MCPWM_TIMER2_STOP_INT_CLR : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_CLR_M (MCPWM_TIMER2_STOP_INT_CLR_V << MCPWM_TIMER2_STOP_INT_CLR_S) +#define MCPWM_TIMER2_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_CLR_S 2 +/** MCPWM_TIMER0_TEZ_INT_CLR : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_CLR_M (MCPWM_TIMER0_TEZ_INT_CLR_V << MCPWM_TIMER0_TEZ_INT_CLR_S) +#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 +/** MCPWM_TIMER1_TEZ_INT_CLR : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_CLR_M (MCPWM_TIMER1_TEZ_INT_CLR_V << MCPWM_TIMER1_TEZ_INT_CLR_S) +#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 +/** MCPWM_TIMER2_TEZ_INT_CLR : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_CLR_M (MCPWM_TIMER2_TEZ_INT_CLR_V << MCPWM_TIMER2_TEZ_INT_CLR_S) +#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 +/** MCPWM_TIMER0_TEP_INT_CLR : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_CLR_M (MCPWM_TIMER0_TEP_INT_CLR_V << MCPWM_TIMER0_TEP_INT_CLR_S) +#define MCPWM_TIMER0_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_CLR_S 6 +/** MCPWM_TIMER1_TEP_INT_CLR : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_CLR_M (MCPWM_TIMER1_TEP_INT_CLR_V << MCPWM_TIMER1_TEP_INT_CLR_S) +#define MCPWM_TIMER1_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_CLR_S 7 +/** MCPWM_TIMER2_TEP_INT_CLR : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_CLR_M (MCPWM_TIMER2_TEP_INT_CLR_V << MCPWM_TIMER2_TEP_INT_CLR_S) +#define MCPWM_TIMER2_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_CLR_S 8 +/** MCPWM_FAULT0_INT_CLR : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_CLR (BIT(9)) +#define MCPWM_FAULT0_INT_CLR_M (MCPWM_FAULT0_INT_CLR_V << MCPWM_FAULT0_INT_CLR_S) +#define MCPWM_FAULT0_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_INT_CLR_S 9 +/** MCPWM_FAULT1_INT_CLR : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_CLR (BIT(10)) +#define MCPWM_FAULT1_INT_CLR_M (MCPWM_FAULT1_INT_CLR_V << MCPWM_FAULT1_INT_CLR_S) +#define MCPWM_FAULT1_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_INT_CLR_S 10 +/** MCPWM_FAULT2_INT_CLR : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_CLR (BIT(11)) +#define MCPWM_FAULT2_INT_CLR_M (MCPWM_FAULT2_INT_CLR_V << MCPWM_FAULT2_INT_CLR_S) +#define MCPWM_FAULT2_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_INT_CLR_S 11 +/** MCPWM_FAULT0_CLR_INT_CLR : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_CLR_M (MCPWM_FAULT0_CLR_INT_CLR_V << MCPWM_FAULT0_CLR_INT_CLR_S) +#define MCPWM_FAULT0_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_CLR_S 12 +/** MCPWM_FAULT1_CLR_INT_CLR : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_CLR_M (MCPWM_FAULT1_CLR_INT_CLR_V << MCPWM_FAULT1_CLR_INT_CLR_S) +#define MCPWM_FAULT1_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_CLR_S 13 +/** MCPWM_FAULT2_CLR_INT_CLR : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_CLR_M (MCPWM_FAULT2_CLR_INT_CLR_V << MCPWM_FAULT2_CLR_INT_CLR_S) +#define MCPWM_FAULT2_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_CLR_S 14 +/** MCPWM_OP0_TEA_INT_CLR : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_CLR (BIT(15)) +#define MCPWM_OP0_TEA_INT_CLR_M (MCPWM_OP0_TEA_INT_CLR_V << MCPWM_OP0_TEA_INT_CLR_S) +#define MCPWM_OP0_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEA_INT_CLR_S 15 +/** MCPWM_OP1_TEA_INT_CLR : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_CLR (BIT(16)) +#define MCPWM_OP1_TEA_INT_CLR_M (MCPWM_OP1_TEA_INT_CLR_V << MCPWM_OP1_TEA_INT_CLR_S) +#define MCPWM_OP1_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEA_INT_CLR_S 16 +/** MCPWM_OP2_TEA_INT_CLR : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_CLR (BIT(17)) +#define MCPWM_OP2_TEA_INT_CLR_M (MCPWM_OP2_TEA_INT_CLR_V << MCPWM_OP2_TEA_INT_CLR_S) +#define MCPWM_OP2_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEA_INT_CLR_S 17 +/** MCPWM_OP0_TEB_INT_CLR : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_CLR (BIT(18)) +#define MCPWM_OP0_TEB_INT_CLR_M (MCPWM_OP0_TEB_INT_CLR_V << MCPWM_OP0_TEB_INT_CLR_S) +#define MCPWM_OP0_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEB_INT_CLR_S 18 +/** MCPWM_OP1_TEB_INT_CLR : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_CLR (BIT(19)) +#define MCPWM_OP1_TEB_INT_CLR_M (MCPWM_OP1_TEB_INT_CLR_V << MCPWM_OP1_TEB_INT_CLR_S) +#define MCPWM_OP1_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEB_INT_CLR_S 19 +/** MCPWM_OP2_TEB_INT_CLR : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_CLR (BIT(20)) +#define MCPWM_OP2_TEB_INT_CLR_M (MCPWM_OP2_TEB_INT_CLR_V << MCPWM_OP2_TEB_INT_CLR_S) +#define MCPWM_OP2_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEB_INT_CLR_S 20 +/** MCPWM_FH0_CBC_INT_CLR : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_CLR (BIT(21)) +#define MCPWM_FH0_CBC_INT_CLR_M (MCPWM_FH0_CBC_INT_CLR_V << MCPWM_FH0_CBC_INT_CLR_S) +#define MCPWM_FH0_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH0_CBC_INT_CLR_S 21 +/** MCPWM_FH1_CBC_INT_CLR : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_CLR (BIT(22)) +#define MCPWM_FH1_CBC_INT_CLR_M (MCPWM_FH1_CBC_INT_CLR_V << MCPWM_FH1_CBC_INT_CLR_S) +#define MCPWM_FH1_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH1_CBC_INT_CLR_S 22 +/** MCPWM_FH2_CBC_INT_CLR : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_CLR (BIT(23)) +#define MCPWM_FH2_CBC_INT_CLR_M (MCPWM_FH2_CBC_INT_CLR_V << MCPWM_FH2_CBC_INT_CLR_S) +#define MCPWM_FH2_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH2_CBC_INT_CLR_S 23 +/** MCPWM_FH0_OST_INT_CLR : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_CLR (BIT(24)) +#define MCPWM_FH0_OST_INT_CLR_M (MCPWM_FH0_OST_INT_CLR_V << MCPWM_FH0_OST_INT_CLR_S) +#define MCPWM_FH0_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH0_OST_INT_CLR_S 24 +/** MCPWM_FH1_OST_INT_CLR : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_CLR (BIT(25)) +#define MCPWM_FH1_OST_INT_CLR_M (MCPWM_FH1_OST_INT_CLR_V << MCPWM_FH1_OST_INT_CLR_S) +#define MCPWM_FH1_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH1_OST_INT_CLR_S 25 +/** MCPWM_FH2_OST_INT_CLR : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_CLR (BIT(26)) +#define MCPWM_FH2_OST_INT_CLR_M (MCPWM_FH2_OST_INT_CLR_V << MCPWM_FH2_OST_INT_CLR_S) +#define MCPWM_FH2_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH2_OST_INT_CLR_S 26 +/** MCPWM_CAP0_INT_CLR : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_CLR (BIT(27)) +#define MCPWM_CAP0_INT_CLR_M (MCPWM_CAP0_INT_CLR_V << MCPWM_CAP0_INT_CLR_S) +#define MCPWM_CAP0_INT_CLR_V 0x00000001U +#define MCPWM_CAP0_INT_CLR_S 27 +/** MCPWM_CAP1_INT_CLR : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_CLR (BIT(28)) +#define MCPWM_CAP1_INT_CLR_M (MCPWM_CAP1_INT_CLR_V << MCPWM_CAP1_INT_CLR_S) +#define MCPWM_CAP1_INT_CLR_V 0x00000001U +#define MCPWM_CAP1_INT_CLR_S 28 +/** MCPWM_CAP2_INT_CLR : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_CLR (BIT(29)) +#define MCPWM_CAP2_INT_CLR_M (MCPWM_CAP2_INT_CLR_V << MCPWM_CAP2_INT_CLR_S) +#define MCPWM_CAP2_INT_CLR_V 0x00000001U +#define MCPWM_CAP2_INT_CLR_S 29 -#define MCPWM_CLK_REG(i) (REG_MCPWM_BASE(i) + 0x120) -/* MCPWM_CLK_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CLK_REG register + * MCPWM APB configuration register + */ +#define MCPWM_CLK_REG(i) (DR_REG_MCPWM_BASE(i) + 0x120) +/** MCPWM_CLK_EN : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ #define MCPWM_CLK_EN (BIT(0)) -#define MCPWM_CLK_EN_M (BIT(0)) -#define MCPWM_CLK_EN_V 0x1 +#define MCPWM_CLK_EN_M (MCPWM_CLK_EN_V << MCPWM_CLK_EN_S) +#define MCPWM_CLK_EN_V 0x00000001U #define MCPWM_CLK_EN_S 0 -#define MCPWM_VERSION_REG(i) (REG_MCPWM_BASE(i) + 0x124) -/* MCPWM_DATE : R/W ;bitpos:[27:0] ;default: 28'h1509110 ; */ -/*description: .*/ -#define MCPWM_DATE 0x0FFFFFFF -#define MCPWM_DATE_M ((MCPWM_DATE_V)<<(MCPWM_DATE_S)) -#define MCPWM_DATE_V 0xFFFFFFF +/** MCPWM_VERSION_REG register + * Version register. + */ +#define MCPWM_VERSION_REG(i) (DR_REG_MCPWM_BASE(i) + 0x124) +/** MCPWM_DATE : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ +#define MCPWM_DATE 0x0FFFFFFFU +#define MCPWM_DATE_M (MCPWM_DATE_V << MCPWM_DATE_S) +#define MCPWM_DATE_V 0x0FFFFFFFU #define MCPWM_DATE_S 0 - #ifdef __cplusplus } #endif - - - -#endif /*_SOC_MCPWM_REG_H_ */ diff --git a/components/soc/esp32s3/include/soc/mcpwm_struct.h b/components/soc/esp32s3/include/soc/mcpwm_struct.h index 565e0a9886..afd2a5633c 100644 --- a/components/soc/esp32s3/include/soc/mcpwm_struct.h +++ b/components/soc/esp32s3/include/soc/mcpwm_struct.h @@ -1,461 +1,1468 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _SOC_MCPWM_STRUCT_H_ -#define _SOC_MCPWM_STRUCT_H_ - +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once #include #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { - union { - struct { - uint32_t prescale : 8; - uint32_t reserved8 : 24; - }; - uint32_t val; - } clk_cfg; +/** Group: Prescaler configuration */ +/** Type of clk_cfg register + * PWM clock prescaler register. + */ +typedef union { struct { - union { - struct { - uint32_t prescale : 8; - uint32_t period : 16; - uint32_t upmethod : 2; /*0: immediate, 1: eqz, 2: sync, 3: eqz | sync*/ - uint32_t reserved26 : 6; - }; - uint32_t val; - } period; - union { - struct { - uint32_t start : 3; /*0: stop @ eqz, 1: stop @ eqp, 2: free run, 3: start and stop @ next eqz, 4: start and stop @ next eqp,*/ - uint32_t mode : 2; /* 0: freeze, 1: inc, 2: dec, 3: up-down*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } mode; - union { - struct { - uint32_t in_en : 1; - uint32_t sync_sw : 1; /*write the negate value will trigger a sw sync*/ - uint32_t out_sel : 2; - uint32_t timer_phase : 16; /*phase for timer reload on sync event*/ - uint32_t phase_direct : 1; /*counter direction to apply on sync event*/ - uint32_t reserved21 : 11; - }; - uint32_t val; - } sync; - union { - struct { - uint32_t value : 16; - uint32_t direction : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } status; - } timer[3]; - union { - struct { - uint32_t t0_in_sel : 3; - uint32_t t1_in_sel : 3; - uint32_t t2_in_sel : 3; - uint32_t ext_in0_inv : 1; - uint32_t ext_in1_inv : 1; - uint32_t ext_in2_inv : 1; - uint32_t reserved12 : 20; - }; - uint32_t val; - } timer_synci_cfg; - union { - struct { - uint32_t operator0_sel : 2; /*0: timer0, 1: timer1, 2: timer2*/ - uint32_t operator1_sel : 2; /*0: timer0, 1: timer1, 2: timer2*/ - uint32_t operator2_sel : 2; /*0: timer0, 1: timer1, 2: timer2*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } timer_sel; + /** clk_prescale : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ + uint32_t clk_prescale: 8; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_clk_cfg_reg_t; + + +/** Group: MCPWM Timer Configuration and status */ +/** Type of timer_cfg0 register + * PWM timer period and update method configuration register. + */ +typedef union { struct { - union { - struct { - uint32_t a_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t b_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t a_shdw_full : 1; - uint32_t b_shdw_full : 1; - uint32_t reserved10 : 22; - }; - uint32_t val; - } cmpr_cfg; - union { - struct { - uint32_t cmpr_val : 16; - uint32_t reserved16 : 16; - }; - uint32_t val; - } cmpr_value[2]; - union { - struct { - uint32_t upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze*/ - uint32_t t0_sel : 3; /*take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none*/ - uint32_t t1_sel : 3; /*take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none*/ - uint32_t reserved10 : 22; - }; - uint32_t val; - } gen_cfg0; - union { - struct { - uint32_t cntu_force_upmethod : 6; /*0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: freeze*/ - uint32_t a_cntuforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t b_cntuforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t a_nciforce : 1; /*non-continuous immediate sw force, a toggle will trigger a force event*/ - uint32_t a_nciforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t b_nciforce : 1; /*non-continuous immediate sw force, a toggle will trigger a force event*/ - uint32_t b_nciforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } gen_force; - union { - struct { - uint32_t utez : 2; - uint32_t utep : 2; - uint32_t utea : 2; - uint32_t uteb : 2; - uint32_t ut0 : 2; - uint32_t ut1 : 2; - uint32_t dtez : 2; - uint32_t dtep : 2; - uint32_t dtea : 2; - uint32_t dteb : 2; - uint32_t dt0 : 2; - uint32_t dt1 : 2; /*0: no change, 1: low, 2: high, 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } generator[2]; - union { - struct { - uint32_t fed_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t red_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t deb_mode : 1; /*immediate, dual-edge B mode, 0: fed/red take effect on different path separately, 1: fed/red take effect on B path, A out is in bypass or dulpB mode*/ - uint32_t a_outswap : 1; - uint32_t b_outswap : 1; - uint32_t red_insel : 1; - uint32_t fed_insel : 1; - uint32_t red_outinvert : 1; - uint32_t fed_outinvert : 1; - uint32_t a_outbypass : 1; - uint32_t b_outbypass : 1; - uint32_t clk_sel : 1; - uint32_t reserved18 : 14; - }; - uint32_t val; - } db_cfg; - union { - struct { - uint32_t fed : 16; - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_fed_cfg; - union { - struct { - uint32_t red : 16; - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_red_cfg; - union { - struct { - uint32_t en : 1; - uint32_t prescale : 4; - uint32_t duty : 3; - uint32_t oshtwth : 4; - uint32_t out_invert : 1; - uint32_t in_invert : 1; - uint32_t reserved14 : 18; - }; - uint32_t val; - } carrier_cfg; - union { - struct { - uint32_t sw_cbc : 1; /*0: disable, 1: enable*/ - uint32_t f2_cbc : 1; /*0: disable, 1: enable*/ - uint32_t f1_cbc : 1; /*0: disable, 1: enable*/ - uint32_t f0_cbc : 1; /*0: disable, 1: enable*/ - uint32_t sw_ost : 1; /*0: disable, 1: enable*/ - uint32_t f2_ost : 1; /*0: disable, 1: enable*/ - uint32_t f1_ost : 1; /*0: disable, 1: enable*/ - uint32_t f0_ost : 1; /*0: disable, 1: enable*/ - uint32_t a_cbc_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t a_cbc_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t a_ost_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t a_ost_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_cbc_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_cbc_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_ost_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_ost_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } tz_cfg0; - union { - struct { - uint32_t clr_ost : 1; /*a toggle will clear oneshot tripping*/ - uint32_t cbcpulse : 2; /*bit0: tez, bit1: tep*/ - uint32_t force_cbc : 1; /*a toggle trigger a cycle-by-cycle tripping*/ - uint32_t force_ost : 1; /*a toggle trigger a oneshot tripping*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } tz_cfg1; - union { - struct { - uint32_t cbc_on : 1; - uint32_t ost_on : 1; - uint32_t reserved2 : 30; - }; - uint32_t val; - } tz_status; - } channel[3]; - union { - struct { - uint32_t f0_en : 1; - uint32_t f1_en : 1; - uint32_t f2_en : 1; - uint32_t f0_pole : 1; - uint32_t f1_pole : 1; - uint32_t f2_pole : 1; - uint32_t event_f0 : 1; - uint32_t event_f1 : 1; - uint32_t event_f2 : 1; - uint32_t reserved9 : 23; - }; - uint32_t val; - } fault_detect; - union { - struct { - uint32_t timer_en : 1; - uint32_t synci_en : 1; - uint32_t synci_sel : 3; - uint32_t sync_sw : 1; /*Write 1 will force a timer sync*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } cap_timer_cfg; - uint32_t cap_timer_phase; - union { - struct { - uint32_t en : 1; - uint32_t mode : 2; /*bit0: negedge cap en, bit1: posedge cap en*/ - uint32_t prescale : 8; - uint32_t in_invert : 1; - uint32_t sw : 1; /*Write 1 will trigger a sw capture*/ - uint32_t reserved13 : 19; - }; - uint32_t val; - } cap_cfg_ch[3]; - uint32_t cap_val_ch[3]; - union { - struct { - uint32_t cap0_edge : 1; - uint32_t cap1_edge : 1; - uint32_t cap2_edge : 1; /*cap trigger's edge, 0: posedge, 1: negedge*/ - uint32_t reserved3 : 29; - }; - uint32_t val; - } cap_status; - union { - struct { - uint32_t global_up_en : 1; - uint32_t global_force_up : 1; /*a toggle will trigger a force update, all timers and operators will update their active regs*/ - uint32_t op0_up_en : 1; - uint32_t op0_force_up : 1; /*a toggle will trigger a force update*/ - uint32_t op1_up_en : 1; - uint32_t op1_force_up : 1; /*a toggle will trigger a force update*/ - uint32_t op2_up_en : 1; /*reg update local enable*/ - uint32_t op2_force_up : 1; /*a toggle will trigger a force update*/ - uint32_t reserved8 : 24; - }; - uint32_t val; - } update_cfg; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t en : 1; - uint32_t reserved1 : 31; - }; - uint32_t val; - } reg_clk; - union { - struct { - uint32_t date : 28; - uint32_t reserved28 : 4; - }; - uint32_t val; - } version; + /** timer_prescale : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER_PRESCALE + 1) + */ + uint32_t timer_prescale: 8; + /** timer_period : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer + */ + uint32_t timer_period: 16; + /** timer_period_upmethod : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ + uint32_t timer_period_upmethod: 2; + uint32_t reserved_26: 6; + }; + uint32_t val; +} mcpwm_timer_cfg0_reg_t; + +/** Type of timer_cfg1 register + * PWM timer working mode and start/stop control configuration register. + */ +typedef union { + struct { + /** timer_start : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer start and stop control. 0: if PWM timer starts, then stops at TEZ, 1: + * if timer starts, then stops at TEP, 2: PWM timer starts and runs on, 3: timer + * starts and stops at the next TEZ, 4: timer starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ + uint32_t timer_start: 3; + /** timer_mod : R/W; bitpos: [4:3]; default: 0; + * PWM timer working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ + uint32_t timer_mod: 2; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_timer_cfg1_reg_t; + +/** Type of timer_sync register + * PWM timer sync function configuration register. + */ +typedef union { + struct { + /** timer_synci_en : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ + uint32_t timer_synci_en: 1; + /** timer_sync_sw : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ + uint32_t timer_sync_sw: 1; + /** timer_synco_sel : R/W; bitpos: [3:2]; default: 0; + * PWM timer sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer_sync_sw bit + */ + uint32_t timer_synco_sel: 2; + /** timer_phase : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ + uint32_t timer_phase: 16; + /** timer_phase_direction : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer's direction at the time sync event occurs when timer mode + * is up-down mode: 0-increase,1-decrease + */ + uint32_t timer_phase_direction: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} mcpwm_timer_sync_reg_t; + +/** Type of timer_status register + * PWM timer status register. + */ +typedef union { + struct { + /** timer_value : RO; bitpos: [15:0]; default: 0; + * current PWM timer counter value + */ + uint32_t timer_value: 16; + /** timer_direction : RO; bitpos: [16]; default: 0; + * current PWM timer counter direction, 0: increment 1: decrement + */ + uint32_t timer_direction: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} mcpwm_timer_status_reg_t; + + +/** Group: Common configuration for MCPWM timers */ +/** Type of timer_synci_cfg register + * Synchronization input selection for three PWM timers. + */ +typedef union { + struct { + /** timer0_syncisel : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer0_syncisel: 3; + /** timer1_syncisel : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer1_syncisel: 3; + /** timer2_syncisel : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer2_syncisel: 3; + /** external_synci0_invert : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ + uint32_t external_synci0_invert: 1; + /** external_synci1_invert : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ + uint32_t external_synci1_invert: 1; + /** external_synci2_invert : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ + uint32_t external_synci2_invert: 1; + uint32_t reserved_12: 20; + }; + uint32_t val; +} mcpwm_timer_synci_cfg_reg_t; + +/** Type of operator_timersel register + * Select specific timer for PWM operators. + */ +typedef union { + struct { + /** operator0_timersel : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator0_timersel: 2; + /** operator1_timersel : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator1_timersel: 2; + /** operator2_timersel : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator2_timersel: 2; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_operator_timersel_reg_t; + + +/** Group: MCPWM Operator Configuration and Status */ +/** Type of gen_stmp_cfg register + * Transfer status and update method for time stamp registers A and B + */ +typedef union { + struct { + /** gen_a_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_a_upmethod: 4; + /** gen_b_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_b_upmethod: 4; + /** gen_a_shdw_full : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_a_shdw_full: 1; + /** gen_b_shdw_full : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_b_shdw_full: 1; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_stmp_cfg_reg_t; + +/** Type of gen_tstmp register + * PWM generator shadow register for timer stamp + */ +typedef union { + struct { + /** gen : R/W; bitpos: [15:0]; default: 0; + * PWM generator time stamp's shadow register + */ + uint32_t gen: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_tstmp_reg_t; + +/** Type of gen_cfg0 register + * PWM generator event T0 and T1 handling + */ +typedef union { + struct { + /** gen_cfg_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ + uint32_t gen_cfg_upmethod: 4; + /** gen_t0_sel : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t0_sel: 3; + /** gen_t1_sel : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t1_sel: 3; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_cfg0_reg_t; + +/** Type of gen_force register + * Permissives to force PWM0A and PWM0B outputs by software + */ +typedef union { + struct { + /** gen_cntuforce_upmethod : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ + uint32_t gen_cntuforce_upmethod: 6; + /** gen_a_cntuforce_mode : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_a_cntuforce_mode: 2; + /** gen_b_cntuforce_mode : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_b_cntuforce_mode: 2; + /** gen_a_nciforce : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ + uint32_t gen_a_nciforce: 1; + /** gen_a_nciforce_mode : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_a_nciforce_mode: 2; + /** gen_b_nciforce : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ + uint32_t gen_b_nciforce: 1; + /** gen_b_nciforce_mode : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_b_nciforce_mode: 2; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_force_reg_t; + +/** Type of generator register + * Actions triggered by events on PWM0A + */ +typedef union { + struct { + /** gen_utez : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utez: 2; + /** gen_utep : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utep: 2; + /** gen_utea : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utea: 2; + /** gen_uteb : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_uteb: 2; + /** gen_ut0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut0: 2; + /** gen_ut1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut1: 2; + /** gen_dtez : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtez: 2; + /** gen_dtep : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtep: 2; + /** gen_dtea : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtea: 2; + /** gen_dteb : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dteb: 2; + /** gen_dt0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt0: 2; + /** gen_dt1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt1: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_gen_reg_t; + +/** Type of dt_cfg register + * PWM generator dead time type selection and configuration + */ +typedef union { + struct { + /** dt_fed_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_fed_upmethod: 4; + /** dt_red_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_red_upmethod: 4; + /** dt_deb_mode : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ + uint32_t dt_deb_mode: 1; + /** dt_a_outswap : R/W; bitpos: [9]; default: 0; + * S6 in table + */ + uint32_t dt_a_outswap: 1; + /** dt_b_outswap : R/W; bitpos: [10]; default: 0; + * S7 in table + */ + uint32_t dt_b_outswap: 1; + /** dt_red_insel : R/W; bitpos: [11]; default: 0; + * S4 in table + */ + uint32_t dt_red_insel: 1; + /** dt_fed_insel : R/W; bitpos: [12]; default: 0; + * S5 in table + */ + uint32_t dt_fed_insel: 1; + /** dt_red_outinvert : R/W; bitpos: [13]; default: 0; + * S2 in table + */ + uint32_t dt_red_outinvert: 1; + /** dt_fed_outinvert : R/W; bitpos: [14]; default: 0; + * S3 in table + */ + uint32_t dt_fed_outinvert: 1; + /** dt_a_outbypass : R/W; bitpos: [15]; default: 1; + * S1 in table + */ + uint32_t dt_a_outbypass: 1; + /** dt_b_outbypass : R/W; bitpos: [16]; default: 1; + * S0 in table + */ + uint32_t dt_b_outbypass: 1; + /** dt_clk_sel : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ + uint32_t dt_clk_sel: 1; + uint32_t reserved_18: 14; + }; + uint32_t val; +} mcpwm_dt_cfg_reg_t; + +/** Type of dt_fed_cfg register + * PWM generator shadow register for falling edge delay (FED). + */ +typedef union { + struct { + /** dt_fed : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ + uint32_t dt_fed: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_fed_cfg_reg_t; + +/** Type of dt_red_cfg register + * PWM generator shadow register for rising edge delay (RED). + */ +typedef union { + struct { + /** dt_red : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ + uint32_t dt_red: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_red_cfg_reg_t; + +/** Type of carrier_cfg register + * PWM generator carrier enable and configuratoin + */ +typedef union { + struct { + /** carrier_en : R/W; bitpos: [0]; default: 0; + * When set, carrier function is enabled. When cleared, carrier is bypassed + */ + uint32_t carrier_en: 1; + /** carrier_prescale : R/W; bitpos: [4:1]; default: 0; + * PWM carrier clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER_PRESCALE + 1) + */ + uint32_t carrier_prescale: 4; + /** carrier_duty : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER_DUTY / 8 + */ + uint32_t carrier_duty: 3; + /** carrier_oshtwth : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ + uint32_t carrier_oshtwth: 4; + /** carrier_out_invert : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_out_invert: 1; + /** carrier_in_invert : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_in_invert: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} mcpwm_carrier_cfg_reg_t; + +/** Type of fh_cfg0 register + * Actions on PWM0A and PWM0B trip events + */ +typedef union { + struct { + /** fh_sw_cbc : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_cbc: 1; + /** fh_f2_cbc : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_cbc: 1; + /** fh_f1_cbc : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_cbc: 1; + /** fh_f0_cbc : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_cbc: 1; + /** fh_sw_ost : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_ost: 1; + /** fh_f2_ost : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_ost: 1; + /** fh_f1_ost : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_ost: 1; + /** fh_f0_ost : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_ost: 1; + /** fh_a_cbc_d : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_d: 2; + /** fh_a_cbc_u : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_u: 2; + /** fh_a_ost_d : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_d: 2; + /** fh_a_ost_u : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_u: 2; + /** fh_b_cbc_d : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_d: 2; + /** fh_b_cbc_u : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_u: 2; + /** fh_b_ost_d : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_d: 2; + /** fh_b_ost_u : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_u: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_fh_cfg0_reg_t; + +/** Type of fh_cfg1 register + * Software triggers for fault handler actions + */ +typedef union { + struct { + /** fh_clr_ost : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ + uint32_t fh_clr_ost: 1; + /** fh_cbcpulse : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ + uint32_t fh_cbcpulse: 2; + /** fh_force_cbc : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ + uint32_t fh_force_cbc: 1; + /** fh_force_ost : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ + uint32_t fh_force_ost: 1; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_fh_cfg1_reg_t; + +/** Type of fh_status register + * Status of fault events. + */ +typedef union { + struct { + /** fh_cbc_on : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ + uint32_t fh_cbc_on: 1; + /** fh_ost_on : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ + uint32_t fh_ost_on: 1; + uint32_t reserved_2: 30; + }; + uint32_t val; +} mcpwm_fh_status_reg_t; + +/** Group: Fault Detection Configuration and Status */ +/** Type of fault_detect register + * Fault detection configuration and status + */ +typedef union { + struct { + /** f0_en : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ + uint32_t f0_en: 1; + /** f1_en : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ + uint32_t f1_en: 1; + /** f2_en : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ + uint32_t f2_en: 1; + /** f0_pole : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f0_pole: 1; + /** f1_pole : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f1_pole: 1; + /** f2_pole : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f2_pole: 1; + /** event_f0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ + uint32_t event_f0: 1; + /** event_f1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ + uint32_t event_f1: 1; + /** event_f2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ + uint32_t event_f2: 1; + uint32_t reserved_9: 23; + }; + uint32_t val; +} mcpwm_fault_detect_reg_t; + + +/** Group: Capture Configuration and Status */ +/** Type of cap_timer_cfg register + * Configure capture timer + */ +typedef union { + struct { + /** cap_timer_en : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ + uint32_t cap_timer_en: 1; + /** cap_synci_en : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ + uint32_t cap_synci_en: 1; + /** cap_synci_sel : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ + uint32_t cap_synci_sel: 3; + /** cap_sync_sw : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ + uint32_t cap_sync_sw: 1; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_cap_timer_cfg_reg_t; + +/** Type of cap_timer_phase register + * Phase for capture timer sync + */ +typedef union { + struct { + /** cap_timer_phase : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ + uint32_t cap_timer_phase: 32; + }; + uint32_t val; +} mcpwm_cap_timer_phase_reg_t; + +/** Type of cap_chn_cfg register + * Capture channel 0 configuration and enable + */ +typedef union { + struct { + /** capn_en : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ + uint32_t capn_en: 1; + /** capn_mode : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ + uint32_t capn_mode: 2; + /** capn_prescale : R/W; bitpos: [10:3]; default: 0; + * Value of prescaling on possitive edge of CAPn. Prescale value = PWM_CAPn_PRESCALE + + * 1 + */ + uint32_t capn_prescale: 8; + /** capn_in_invert : R/W; bitpos: [11]; default: 0; + * when set, CAPn form GPIO matrix is inverted before prescale + */ + uint32_t capn_in_invert: 1; + /** capn_sw : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ + uint32_t capn_sw: 1; + uint32_t reserved_13: 19; + }; + uint32_t val; +} mcpwm_cap_chn_cfg_reg_t; + +/** Type of cap_chn register + * chn capture value status register + */ +typedef union { + struct { + /** capn_value : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel n + */ + uint32_t capn_value: 32; + }; + uint32_t val; +} mcpwm_cap_chn_reg_t; + +/** Type of cap_status register + * Edge of last capture trigger + */ +typedef union { + struct { + /** cap0_edge : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ + uint32_t cap0_edge: 1; + /** cap1_edge : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ + uint32_t cap1_edge: 1; + /** cap2_edge : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ + uint32_t cap2_edge: 1; + uint32_t reserved_3: 29; + }; + uint32_t val; +} mcpwm_cap_status_reg_t; + + +/** Group: Enable update of active registers */ +/** Type of update_cfg register + * Enable update. + */ +typedef union { + struct { + /** global_up_en : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ + uint32_t global_up_en: 1; + /** global_force_up : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ + uint32_t global_force_up: 1; + /** op0_up_en : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ + uint32_t op0_up_en: 1; + /** op0_force_up : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ + uint32_t op0_force_up: 1; + /** op1_up_en : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ + uint32_t op1_up_en: 1; + /** op1_force_up : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ + uint32_t op1_force_up: 1; + /** op2_up_en : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ + uint32_t op2_up_en: 1; + /** op2_force_up : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ + uint32_t op2_force_up: 1; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_update_cfg_reg_t; + + +/** Group: Manage Interrupts */ +/** Type of int_ena register + * Interrupt enable bits + */ +typedef union { + struct { + /** timer0_stop_int_ena : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_ena: 1; + /** timer1_stop_int_ena : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_ena: 1; + /** timer2_stop_int_ena : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_ena: 1; + /** timer0_tez_int_ena : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_ena: 1; + /** timer1_tez_int_ena : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_ena: 1; + /** timer2_tez_int_ena : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_ena: 1; + /** timer0_tep_int_ena : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_ena: 1; + /** timer1_tep_int_ena : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_ena: 1; + /** timer2_tep_int_ena : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_ena: 1; + /** fault0_int_ena : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_ena: 1; + /** fault1_int_ena : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_ena: 1; + /** fault2_int_ena : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_ena: 1; + /** fault0_clr_int_ena : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_ena: 1; + /** fault1_clr_int_ena : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_ena: 1; + /** fault2_clr_int_ena : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_ena: 1; + /** op0_tea_int_ena : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_ena: 1; + /** op1_tea_int_ena : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_ena: 1; + /** op2_tea_int_ena : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_ena: 1; + /** op0_teb_int_ena : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_ena: 1; + /** op1_teb_int_ena : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_ena: 1; + /** op2_teb_int_ena : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_ena: 1; + /** fh0_cbc_int_ena : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ + uint32_t fh0_cbc_int_ena: 1; + /** fh1_cbc_int_ena : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ + uint32_t fh1_cbc_int_ena: 1; + /** fh2_cbc_int_ena : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ + uint32_t fh2_cbc_int_ena: 1; + /** fh0_ost_int_ena : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_ena: 1; + /** fh1_ost_int_ena : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_ena: 1; + /** fh2_ost_int_ena : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_ena: 1; + /** cap0_int_ena : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_ena: 1; + /** cap1_int_ena : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_ena: 1; + /** cap2_int_ena : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_ena: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_ena_reg_t; + +/** Type of int_raw register + * Raw interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_raw : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_raw: 1; + /** timer1_stop_int_raw : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_raw: 1; + /** timer2_stop_int_raw : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_raw: 1; + /** timer0_tez_int_raw : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_raw: 1; + /** timer1_tez_int_raw : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_raw: 1; + /** timer2_tez_int_raw : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_raw: 1; + /** timer0_tep_int_raw : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_raw: 1; + /** timer1_tep_int_raw : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_raw: 1; + /** timer2_tep_int_raw : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_raw: 1; + /** fault0_int_raw : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_raw: 1; + /** fault1_int_raw : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_raw: 1; + /** fault2_int_raw : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_raw: 1; + /** fault0_clr_int_raw : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_raw: 1; + /** fault1_clr_int_raw : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_raw: 1; + /** fault2_clr_int_raw : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_raw: 1; + /** op0_tea_int_raw : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_raw: 1; + /** op1_tea_int_raw : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_raw: 1; + /** op2_tea_int_raw : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_raw: 1; + /** op0_teb_int_raw : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_raw: 1; + /** op1_teb_int_raw : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_raw: 1; + /** op2_teb_int_raw : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_raw: 1; + /** fh0_cbc_int_raw : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_raw: 1; + /** fh1_cbc_int_raw : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_raw: 1; + /** fh2_cbc_int_raw : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_raw: 1; + /** fh0_ost_int_raw : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_raw: 1; + /** fh1_ost_int_raw : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_raw: 1; + /** fh2_ost_int_raw : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_raw: 1; + /** cap0_int_raw : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_raw: 1; + /** cap1_int_raw : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_raw: 1; + /** cap2_int_raw : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_raw: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_raw_reg_t; + +/** Type of int_st register + * Masked interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_st : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_st: 1; + /** timer1_stop_int_st : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_st: 1; + /** timer2_stop_int_st : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_st: 1; + /** timer0_tez_int_st : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_st: 1; + /** timer1_tez_int_st : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_st: 1; + /** timer2_tez_int_st : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_st: 1; + /** timer0_tep_int_st : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_st: 1; + /** timer1_tep_int_st : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_st: 1; + /** timer2_tep_int_st : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_st: 1; + /** fault0_int_st : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_st: 1; + /** fault1_int_st : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_st: 1; + /** fault2_int_st : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_st: 1; + /** fault0_clr_int_st : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_st: 1; + /** fault1_clr_int_st : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_st: 1; + /** fault2_clr_int_st : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_st: 1; + /** op0_tea_int_st : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_st: 1; + /** op1_tea_int_st : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_st: 1; + /** op2_tea_int_st : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_st: 1; + /** op0_teb_int_st : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_st: 1; + /** op1_teb_int_st : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_st: 1; + /** op2_teb_int_st : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_st: 1; + /** fh0_cbc_int_st : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ + uint32_t fh0_cbc_int_st: 1; + /** fh1_cbc_int_st : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ + uint32_t fh1_cbc_int_st: 1; + /** fh2_cbc_int_st : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ + uint32_t fh2_cbc_int_st: 1; + /** fh0_ost_int_st : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_st: 1; + /** fh1_ost_int_st : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_st: 1; + /** fh2_ost_int_st : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_st: 1; + /** cap0_int_st : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_st: 1; + /** cap1_int_st : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_st: 1; + /** cap2_int_st : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_st: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_st_reg_t; + +/** Type of int_clr register + * Interrupt clear bits + */ +typedef union { + struct { + /** timer0_stop_int_clr : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_clr: 1; + /** timer1_stop_int_clr : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_clr: 1; + /** timer2_stop_int_clr : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_clr: 1; + /** timer0_tez_int_clr : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_clr: 1; + /** timer1_tez_int_clr : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_clr: 1; + /** timer2_tez_int_clr : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_clr: 1; + /** timer0_tep_int_clr : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_clr: 1; + /** timer1_tep_int_clr : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_clr: 1; + /** timer2_tep_int_clr : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_clr: 1; + /** fault0_int_clr : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_clr: 1; + /** fault1_int_clr : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_clr: 1; + /** fault2_int_clr : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_clr: 1; + /** fault0_clr_int_clr : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_clr: 1; + /** fault1_clr_int_clr : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_clr: 1; + /** fault2_clr_int_clr : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_clr: 1; + /** op0_tea_int_clr : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_clr: 1; + /** op1_tea_int_clr : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_clr: 1; + /** op2_tea_int_clr : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_clr: 1; + /** op0_teb_int_clr : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_clr: 1; + /** op1_teb_int_clr : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_clr: 1; + /** op2_teb_int_clr : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_clr: 1; + /** fh0_cbc_int_clr : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_clr: 1; + /** fh1_cbc_int_clr : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_clr: 1; + /** fh2_cbc_int_clr : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_clr: 1; + /** fh0_ost_int_clr : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_clr: 1; + /** fh1_ost_int_clr : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_clr: 1; + /** fh2_ost_int_clr : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_clr: 1; + /** cap0_int_clr : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_clr: 1; + /** cap1_int_clr : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_clr: 1; + /** cap2_int_clr : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_clr: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_clr_reg_t; + + +/** Group: MCMCPWM APB configuration register */ +/** Type of clk register + * MCPWM APB configuration register + */ +typedef union { + struct { + /** clk_en : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ + uint32_t clk_en: 1; + uint32_t reserved_1: 31; + }; + uint32_t val; +} mcpwm_clk_reg_t; + + +/** Group: Version Register */ +/** Type of version register + * Version register. + */ +typedef union { + struct { + /** date : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ + uint32_t date: 28; + uint32_t reserved_28: 4; + }; + uint32_t val; +} mcpwm_version_reg_t; + + +typedef struct { + mcpwm_timer_cfg0_reg_t timer_cfg0; + mcpwm_timer_cfg1_reg_t timer_cfg1; + mcpwm_timer_sync_reg_t timer_sync; + mcpwm_timer_status_reg_t timer_status; +} mcpwm_timer_regs_t; + +typedef struct { + mcpwm_gen_stmp_cfg_reg_t gen_stmp_cfg; + mcpwm_gen_tstmp_reg_t timestamp[2]; + mcpwm_gen_cfg0_reg_t gen_cfg0; + mcpwm_gen_force_reg_t gen_force; + mcpwm_gen_reg_t generator[2]; + mcpwm_dt_cfg_reg_t dt_cfg; + mcpwm_dt_fed_cfg_reg_t dt_fed_cfg; + mcpwm_dt_red_cfg_reg_t dt_red_cfg; + mcpwm_carrier_cfg_reg_t carrier_cfg; + mcpwm_fh_cfg0_reg_t fh_cfg0; + mcpwm_fh_cfg1_reg_t fh_cfg1; + mcpwm_fh_status_reg_t fh_status; +} mcpwm_operator_reg_t; + +typedef struct { + volatile mcpwm_clk_cfg_reg_t clk_cfg; + volatile mcpwm_timer_regs_t timer[3]; + volatile mcpwm_timer_synci_cfg_reg_t timer_synci_cfg; + volatile mcpwm_operator_timersel_reg_t operator_timersel; + volatile mcpwm_operator_reg_t operator[3]; + volatile mcpwm_fault_detect_reg_t fault_detect; + volatile mcpwm_cap_timer_cfg_reg_t cap_timer_cfg; + volatile mcpwm_cap_timer_phase_reg_t cap_timer_phase; + volatile mcpwm_cap_chn_cfg_reg_t cap_chn_cfg[3]; + volatile mcpwm_cap_chn_reg_t cap_chn[3]; + volatile mcpwm_cap_status_reg_t cap_status; + volatile mcpwm_update_cfg_reg_t update_cfg; + volatile mcpwm_int_ena_reg_t int_ena; + volatile mcpwm_int_raw_reg_t int_raw; + volatile mcpwm_int_st_reg_t int_st; + volatile mcpwm_int_clr_reg_t int_clr; + volatile mcpwm_clk_reg_t clk; + volatile mcpwm_version_reg_t version; } mcpwm_dev_t; + extern mcpwm_dev_t MCPWM0; extern mcpwm_dev_t MCPWM1; + +#ifndef __cplusplus +_Static_assert(sizeof(mcpwm_dev_t) == 0x128, "Invalid size of mcpwm_dev_t structure"); +#endif + #ifdef __cplusplus } #endif - - - -#endif /*_SOC_MCPWM_STRUCT_H_ */ From 0dbe8725425095f99ed2f1a27812c53f7a66eab6 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 29 Jul 2021 21:34:24 +0800 Subject: [PATCH 023/310] mcpwm: bldc hall example --- components/driver/include/driver/mcpwm.h | 2 +- docs/en/api-reference/peripherals/mcpwm.rst | 2 +- .../mcpwm/mcpwm_bldc_control/README.md | 46 --- .../mcpwm_bldc_control/main/CMakeLists.txt | 2 - .../mcpwm_bldc_control_hall_sensor_example.c | 319 ------------------ .../CMakeLists.txt | 2 +- .../Makefile | 2 +- .../mcpwm/mcpwm_bldc_hall_control/README.md | 81 +++++ .../main/CMakeLists.txt | 2 + .../main/component.mk | 0 .../mcpwm_bldc_hall_control_example_main.c | 255 ++++++++++++++ 11 files changed, 342 insertions(+), 371 deletions(-) delete mode 100644 examples/peripherals/mcpwm/mcpwm_bldc_control/README.md delete mode 100644 examples/peripherals/mcpwm/mcpwm_bldc_control/main/CMakeLists.txt delete mode 100644 examples/peripherals/mcpwm/mcpwm_bldc_control/main/mcpwm_bldc_control_hall_sensor_example.c rename examples/peripherals/mcpwm/{mcpwm_bldc_control => mcpwm_bldc_hall_control}/CMakeLists.txt (84%) rename examples/peripherals/mcpwm/{mcpwm_bldc_control => mcpwm_bldc_hall_control}/Makefile (76%) create mode 100644 examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md create mode 100644 examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/CMakeLists.txt rename examples/peripherals/mcpwm/{mcpwm_bldc_control => mcpwm_bldc_hall_control}/main/component.mk (100%) create mode 100644 examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c diff --git a/components/driver/include/driver/mcpwm.h b/components/driver/include/driver/mcpwm.h index db8816069d..20b41ffd32 100644 --- a/components/driver/include/driver/mcpwm.h +++ b/components/driver/include/driver/mcpwm.h @@ -139,7 +139,7 @@ typedef enum { * @brief MCPWM select triggering level of fault signal */ typedef enum { - MCPWM_LOW_LEVEL_TGR, /*!4-->5-->1-->3-->2-->6-->4--> and so on - -IR2136 3-ph bridge driver is used for testing this example code - -User needs to make changes according to the motor and gate driver ic used - - -## Step 1: Pin assignment -* The gpio init function initializes: - * GPIO15 is assigned as the MCPWM signal for 1H(UH) - * GPIO02 is assigned as the MCPWM signal for 1L(UL) - * GPIO00 is assigned as the MCPWM signal for 2H(VH) - * GPIO04 is assigned as the MCPWM signal for 2L(VL) - * GPIO16 is assigned as the MCPWM signal for 3H(WH) - * GPIO17 is assigned as the MCPWM signal for 3L(WL) - * GPIO25 is assigned as the MCPWM capture signal for Hall A - * GPIO26 is assigned as the MCPWM capture signal for HALL B - * GPIO27 is assigned as the MCPWM capture signal for HALL C - - -## Step 2: Connection -* Connect GPIO15 with 1H/UH of BLDC motor driver -* Connect GPIO02 with 1L/UL of BLDC motor driver -* Connect GPIO00 with 2H/VH of BLDC motor driver -* Connect GPIO04 with 2L/VL of BLDC motor driver -* Connect GPIO16 with 3H/WH of BLDC motor driver -* Connect GPIO17 with 3L/WL of BLDC motor driver -* Connect GPIO25 to hall sensor A output -* Connect GPIO26 to hall sensor B output -* Connect GPIO27 to hall sensor C output - - -## Step 3: Initialize MCPWM - * You need to set the frequency and duty cycle of MCPWM timer - * You need to set the MCPWM channel you want to use, and bind the channel with one of the timers - * You need to set the capture unit, for POS/NEG edge capture - * Also reversing the hall sensor BIT weight, will make bldc motor rotate CW or CCW diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_control/main/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_bldc_control/main/CMakeLists.txt deleted file mode 100644 index 61d8388b1b..0000000000 --- a/examples/peripherals/mcpwm/mcpwm_bldc_control/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "mcpwm_bldc_control_hall_sensor_example.c" - INCLUDE_DIRS ".") diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_control/main/mcpwm_bldc_control_hall_sensor_example.c b/examples/peripherals/mcpwm/mcpwm_bldc_control/main/mcpwm_bldc_control_hall_sensor_example.c deleted file mode 100644 index 290b1fb2fa..0000000000 --- a/examples/peripherals/mcpwm/mcpwm_bldc_control/main/mcpwm_bldc_control_hall_sensor_example.c +++ /dev/null @@ -1,319 +0,0 @@ - -/* MCPWM BLDC control Test code - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -/* - * The following examples uses mcpwm module to control bldc motor vary its speed continiously - * The BLDC motor used for testing this code had sequence of 6-->4-->5-->1-->3-->2-->6-->4--> and so on - * IR2136 3-ph bridge driver is used for testing this example code - * User needs to make changes according to the motor and gate driver ic used - */ - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "soc/rtc.h" -#include "driver/mcpwm.h" - -#define INITIAL_DUTY 10.0 //initial duty cycle is 10.0% -#define MCPWM_GPIO_INIT 0 //select which function to use to initialize gpio signals - -#define GPIO_HALL_TEST_SIGNAL 0 //Make this 1 to enable generation of hall sensors test signal on GPIO13, 12, 14 -#define CHANGE_DUTY_CONTINUOUSLY 0 //Make this 1 to change duty continuously - -#define CAP_SIG_NUM 3 //three capture signals from HALL-A, HALL-B, HALL-C -#define CAP0_INT_EN BIT(27) //Capture 0 interrupt bit -#define CAP1_INT_EN BIT(28) //Capture 1 interrupt bit -#define CAP2_INT_EN BIT(29) //Capture 2 interrupt bit - -#define GPIO_PWM0A_OUT 15 //Set GPIO 15 as PWM0A -#define GPIO_PWM0B_OUT 02 //Set GPIO 02 as PWM0B -#define GPIO_PWM1A_OUT 00 //Set GPIO 00 as PWM1A -#define GPIO_PWM1B_OUT 04 //Set GPIO 04 as PWM1B -#define GPIO_PWM2A_OUT 16 //Set GPIO 16 as PWM2A -#define GPIO_PWM2B_OUT 17 //Set GPIO 17 as PWM2B -#define GPIO_CAP0_IN 25 //Set GPIO 25 as CAP0 -#define GPIO_CAP1_IN 26 //Set GPIO 26 as CAP1 -#define GPIO_CAP2_IN 27 //Set GPIO 27 as CAP2 - -typedef struct { - uint32_t capture_signal; - mcpwm_capture_signal_t sel_cap_signal; -} capture; - -static uint32_t hall_sensor_value = 0; -static uint32_t hall_sensor_previous = 0; - -xQueueHandle cap_queue; - -static void mcpwm_example_gpio_initialize(void) -{ - printf("initializing mcpwm bldc control gpio...\n"); -#if MCPWM_GPIO_INIT - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, GPIO_PWM1A_OUT); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1B, GPIO_PWM1B_OUT); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM2A, GPIO_PWM2A_OUT); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM2B, GPIO_PWM2B_OUT); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, GPIO_CAP0_IN); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_1, GPIO_CAP1_IN); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_2, GPIO_CAP2_IN); -#else - mcpwm_pin_config_t pin_config = { - .mcpwm0a_out_num = GPIO_PWM0A_OUT, - .mcpwm0b_out_num = GPIO_PWM0B_OUT, - .mcpwm1a_out_num = GPIO_PWM1A_OUT, - .mcpwm1b_out_num = GPIO_PWM1B_OUT, - .mcpwm2a_out_num = GPIO_PWM2A_OUT, - .mcpwm2b_out_num = GPIO_PWM2B_OUT, - .mcpwm_cap0_in_num = GPIO_CAP0_IN, - .mcpwm_cap1_in_num = GPIO_CAP1_IN, - .mcpwm_cap2_in_num = GPIO_CAP2_IN, - .mcpwm_sync0_in_num = -1, //Not used - .mcpwm_sync1_in_num = -1, //Not used - .mcpwm_sync2_in_num = -1, //Not used - .mcpwm_fault0_in_num = -1, //Not used - .mcpwm_fault1_in_num = -1, //Not used - .mcpwm_fault2_in_num = -1 //Not used - }; - mcpwm_set_pin(MCPWM_UNIT_0, &pin_config); -#endif - gpio_pulldown_en(GPIO_CAP0_IN); //Enable pull down on CAP0 signal - gpio_pulldown_en(GPIO_CAP1_IN); //Enable pull down on CAP1 signal - gpio_pulldown_en(GPIO_CAP2_IN); //Enable pull down on CAP2 signal -} - -#if GPIO_HALL_TEST_SIGNAL -/** - * @brief Set gpio 13, 12, 14 as our test signal of hall sensors, that generates high-low waveform continuously - * Attach this pins to GPIO 27, 26, 25 respectively for capture unit - */ -static void gpio_test_signal(void *arg) -{ - printf("intializing test signal...\n"); - gpio_config_t gp; - gp.intr_type = GPIO_INTR_DISABLE; - gp.mode = GPIO_MODE_OUTPUT; - gp.pin_bit_mask = GPIO_SEL_13 | GPIO_SEL_12 | GPIO_SEL_14; - gpio_config(&gp); - while (1) { - gpio_set_level(GPIO_NUM_13, 1); //Set H1 high - gpio_set_level(GPIO_NUM_12, 0); //Set H2 low - gpio_set_level(GPIO_NUM_14, 1); //Set H3 high - vTaskDelay(1); - gpio_set_level(GPIO_NUM_14, 0); //Set H3 low - vTaskDelay(1); - gpio_set_level(GPIO_NUM_12, 1); //Set H2 high - vTaskDelay(1); - gpio_set_level(GPIO_NUM_13, 0); //Set H1 low - vTaskDelay(1); - gpio_set_level(GPIO_NUM_14, 1); //Set H3 high - vTaskDelay(1); - gpio_set_level(GPIO_NUM_12, 0); //Set H2 high - vTaskDelay(1); - } -} -#endif - -/** - * @brief When interrupt occurs, we receive the counter value and display the time between two rising edge - */ -static void disp_captured_signal(void *arg) -{ - uint32_t *current_cap_value = (uint32_t *)malloc(sizeof(CAP_SIG_NUM)); - uint32_t *previous_cap_value = (uint32_t *)malloc(sizeof(CAP_SIG_NUM)); - capture evt; - while (1) { - xQueueReceive(cap_queue, &evt, portMAX_DELAY); - if (evt.sel_cap_signal == MCPWM_SELECT_CAP0) { - current_cap_value[0] = evt.capture_signal - previous_cap_value[0]; - previous_cap_value[0] = evt.capture_signal; - current_cap_value[0] = (current_cap_value[0] / 10000) * (10000000000 / rtc_clk_apb_freq_get()); - //printf("CAP0 : %d us\n", current_cap_value[0]); - } - if (evt.sel_cap_signal == MCPWM_SELECT_CAP1) { - current_cap_value[1] = evt.capture_signal - previous_cap_value[1]; - previous_cap_value[1] = evt.capture_signal; - current_cap_value[1] = (current_cap_value[1] / 10000) * (10000000000 / rtc_clk_apb_freq_get()); - //printf("CAP1 : %d us\n", current_cap_value[1]); - } - if (evt.sel_cap_signal == MCPWM_SELECT_CAP2) { - current_cap_value[2] = evt.capture_signal - previous_cap_value[2]; - previous_cap_value[2] = evt.capture_signal; - current_cap_value[2] = (current_cap_value[2] / 10000) * (10000000000 / rtc_clk_apb_freq_get()); - //printf("CAP2 : %d us\n", current_cap_value[2]); - } - } -} - -/** - * @brief this is ISR handler function, here we check for interrupt that triggers rising edge on CAP0 signal and according take action - */ -static bool isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, void *arg) -{ - capture evt; - if (cap_sig == MCPWM_SELECT_CAP0) { //Check for interrupt on rising edge on CAP0 signal - evt.capture_signal = edata->cap_value; //get capture signal counter value - evt.sel_cap_signal = MCPWM_SELECT_CAP0; - xQueueSendFromISR(cap_queue, &evt, NULL); - } - if (cap_sig == MCPWM_SELECT_CAP1) { //Check for interrupt on rising edge on CAP1 signal - evt.capture_signal = edata->cap_value; //get capture signal counter value - evt.sel_cap_signal = MCPWM_SELECT_CAP1; - xQueueSendFromISR(cap_queue, &evt, NULL); - } - if (cap_sig == MCPWM_SELECT_CAP2) { //Check for interrupt on rising edge on CAP2 signal - evt.capture_signal = edata->cap_value; //get capture signal counter value - evt.sel_cap_signal = MCPWM_SELECT_CAP2; - xQueueSendFromISR(cap_queue, &evt, NULL); - } - return false; -} - -#if CHANGE_DUTY_CONTINUOUSLY -static void change_duty(void *arg) -{ - int j; - while (1) { - for (j = 0; j < 18; j++) { - //printf("duty cycle: %d\n", (0 +j*50)); - mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, (INITIAL_DUTY + j * 5.0)); - mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B, (INITIAL_DUTY + j * 5.0)); - mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A, (INITIAL_DUTY + j * 5.0)); - mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B, (INITIAL_DUTY + j * 5.0)); - mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A, (INITIAL_DUTY + j * 5.0)); - mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B, (INITIAL_DUTY + j * 5.0)); - vTaskDelay(500 / portTICK_RATE_MS); - } - } -} -#endif - -/** - * @brief Configure whole MCPWM module for bldc motor control - */ -static void mcpwm_example_bldc_control(void *arg) -{ - //1. mcpwm gpio initialization - mcpwm_example_gpio_initialize(); - - //2. initial mcpwm configuration - printf("Configuring Initial Parameters of mcpwm bldc control...\n"); - mcpwm_config_t pwm_config; - pwm_config.frequency = 14400; //frequency = 1000Hz - pwm_config.cmpr_a = 50.0; //duty cycle of PWMxA = 50.0% - pwm_config.cmpr_b = 50.0; //duty cycle of PWMxb = 50.0% - pwm_config.counter_mode = MCPWM_UP_COUNTER; - pwm_config.duty_mode = MCPWM_DUTY_MODE_1; - mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //Configure PWM0A & PWM0B with above settings - mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_config); //Configure PWM1A & PWM1B with above settings - mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_2, &pwm_config); //Configure PWM2A & PWM2B with above settings - - //3. Capture configuration - //configure CAP0, CAP1 and CAP2 signal to start capture counter on rising edge - //we generate a gpio_test_signal of 20ms on GPIO 12 and connect it to one of the capture signal, the disp_captured_function displays the time between rising edge - //In general practice you can connect Capture to external signal, measure time between rising edge or falling edge and take action accordingly - mcpwm_capture_config_t conf = { - .cap_edge = MCPWM_POS_EDGE, - .cap_prescale = 1, - .capture_cb = isr_handler, - .user_data = NULL, - }; - mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, &conf); //capture signal on rising edge, pulse num = 0 i.e. 800,000,000 counts is equal to one second - mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP1, &conf); //capture signal on rising edge, pulse num = 0 i.e. 800,000,000 counts is equal to one second - mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP2, &conf); //capture signal on rising edge, pulse num = 0 i.e. 800,000,000 counts is equal to one second - //According to the hall sensor input value take action on PWM0A/0B/1A/1B/2A/2B - while (1) { - hall_sensor_value = (gpio_get_level(GPIO_NUM_27) * 1) + (gpio_get_level(GPIO_NUM_26) * 2) + (gpio_get_level(GPIO_NUM_25) * 4); - if (hall_sensor_value != hall_sensor_previous) { - //printf("hall_sen val: %d\n", hall_sensor_value); - if (hall_sensor_value == 2) { - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A); - mcpwm_set_signal_high(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B); - //MCPWMXA to duty mode 1 and MCPWMXB to duty mode 0 or vice versa will generate MCPWM compliment signal of each other, there are also other ways to do it - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, MCPWM_DUTY_MODE_1); //Set PWM0A to duty mode one - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //Set PWM0B back to duty mode zero - mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_BYPASS_FED, 100, 100); //Deadtime of 10us - } - if (hall_sensor_value == 6) { - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B); - mcpwm_deadtime_disable(MCPWM_UNIT_0, MCPWM_TIMER_0); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A); - mcpwm_set_signal_high(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B); - //MCPWMXA to duty mode 1 and MCPWMXB to duty mode 0 or vice versa will generate MCPWM compliment signal of each other, there are also other ways to do it - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A, MCPWM_DUTY_MODE_1); //Set PWM2A to duty mode one - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //Set PWM2B back to duty mode zero - mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_BYPASS_FED, 100, 100); //Deadtime of 10us - } - if (hall_sensor_value == 4) { - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A); - mcpwm_set_signal_high(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B); - //MCPWMXA to duty mode 1 and MCPWMXB to duty mode 0 or vice versa will generate MCPWM compliment signal of each other, there are also other ways to do it - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A, MCPWM_DUTY_MODE_1); //Set PWM2A to duty mode one - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //Set PWM2B back to duty mode zero - mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_BYPASS_FED, 100, 100); //Deadtime of 10us - } - if (hall_sensor_value == 5) { - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B); - mcpwm_deadtime_disable(MCPWM_UNIT_0, MCPWM_TIMER_2); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A); - mcpwm_set_signal_high(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B); - //MCPWMXA to duty mode 1 and MCPWMXB to duty mode 0 or vice versa will generate MCPWM compliment signal of each other, there are also other ways to do it - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A, MCPWM_DUTY_MODE_1); //Set PWM1A to duty mode one - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //Set PWM1B back to duty mode zero - mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_BYPASS_FED, 100, 100); //Deadtime of 10uss - } - if (hall_sensor_value == 1) { - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A); - mcpwm_set_signal_high(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B); - //MCPWMXA to duty mode 1 and MCPWMXB to duty mode 0 or vice versa will generate MCPWM compliment signal of each other, there are also other ways to do it - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A, MCPWM_DUTY_MODE_1); //Set PWM1A to duty mode one - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //Set PWM1B back to duty mode zero - mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_BYPASS_FED, 100, 100); //Deadtime of 10uss - } - if (hall_sensor_value == 3) { - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B); - mcpwm_deadtime_disable(MCPWM_UNIT_0, MCPWM_TIMER_1); - mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A); - mcpwm_set_signal_high(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B); - //MCPWMXA to duty mode 1 and MCPWMXB to duty mode 0 or vice versa will generate MCPWM compliment signal of each other, there are also other ways to do it - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, MCPWM_DUTY_MODE_1); //Set PWM0A to duty mode one - mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //Set PWM0B back to duty mode zero - mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_BYPASS_FED, 100, 100); //Deadtime of 10us - } - hall_sensor_previous = hall_sensor_value; - } - } -} - -void app_main(void) -{ - printf("Testing MCPWM BLDC Control...\n"); -#if CHANGE_DUTY_CONTINUOUSLY - xTaskCreate(change_duty, "change_duty", 2048, NULL, 2, NULL); -#endif - cap_queue = xQueueCreate(1, sizeof(capture)); //comment if you don't want to use capture module -#if GPIO_HALL_TEST_SIGNAL - xTaskCreate(gpio_test_signal, "gpio_test_signal", 2048, NULL, 2, NULL); -#endif - xTaskCreate(disp_captured_signal, "mcpwm_config", 4096, NULL, 2, NULL); //comment if you don't want to use capture module - xTaskCreate(mcpwm_example_bldc_control, "mcpwm_example_bldc_control", 4096, NULL, 2, NULL); -} diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_control/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/CMakeLists.txt similarity index 84% rename from examples/peripherals/mcpwm/mcpwm_bldc_control/CMakeLists.txt rename to examples/peripherals/mcpwm/mcpwm_bldc_hall_control/CMakeLists.txt index 10ed869e1b..6fbfed3cee 100644 --- a/examples/peripherals/mcpwm/mcpwm_bldc_control/CMakeLists.txt +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(mcpwm_bldc_control_hall_sensor) +project(mcpwm_bldc_hall_control) diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_control/Makefile b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/Makefile similarity index 76% rename from examples/peripherals/mcpwm/mcpwm_bldc_control/Makefile rename to examples/peripherals/mcpwm/mcpwm_bldc_hall_control/Makefile index eb1842cc7b..5e6eca0206 100644 --- a/examples/peripherals/mcpwm/mcpwm_bldc_control/Makefile +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/Makefile @@ -3,6 +3,6 @@ # project subdirectory. # -PROJECT_NAME := mcpwm_bldc_control_hall_sensor +PROJECT_NAME := mcpwm_bldc_hall_control include $(IDF_PATH)/make/project.mk diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md new file mode 100644 index 0000000000..5fa70fe40d --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md @@ -0,0 +1,81 @@ +| Supported Targets | ESP32 | ESP32-S3 | +| ----------------- | ----- | -------- | + +# MCPWM BLDC Hall motor control Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example will illustrate how to use MCPWM driver to control BLDC motor with hall sensor feedback. In the example, a timer is running at the background to update the motor speed periodically. + +With the hardware fault detection feature of MCPWM, the example will shut down the MOSFETs when over current happens. + +## How to Use Example + +### Hardware Required + +1. The BLDC motor used in this example has a hall sensor capture sequence of `6-->4-->5-->1-->3-->2-->6-->4-->` and so on. +2. A three-phase gate driver, this example uses [IR2136](https://www.infineon.com/cms/en/product/power/gate-driver-ics/ir2136s/). +3. Six N-MOSFETs, this example uses [IRF540NS](https://www.infineon.com/cms/en/product/power/mosfet/12v-300v-n-channel-power-mosfet/irf540ns/). +4. A development board with any Espressif SoC which features MCPWM peripheral (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +5. A USB cable for Power supply and programming. + +Connection : + +``` + ┌─────────────────────────────────────────────┐ + │ │ + │ ┌───────────────────────────┐ │ + │ │ │ │ +┌─────────┴─────────┴───────────┐ ┌────────┴───────┴──────────┐ +│ GPIO19 GPIO18 │ │ EN FAULT │ +│ GPIO21├──────┤PWM_UH │ ┌────────────┐ +│ GPIO22├──────┤PWM_UL U├────────┤ │ +│ │ │ │ │ │ +│ GPIO23├──────┤PWM_VH V├────────┤ BLDC │ +│ ESP Board GPIO25├──────┤PWM_VL 3-Phase Bridge │ │ │ +│ │ │ + W├────────┤ │ +│ GPIO26├──────┤PWM_WH MOSFET │ └─┬───┬───┬──┘ +│ GPIO27├──────┤PWM_WL │ │ │ │ +│ GPIO5 GPIO4 GPIO2 │ │ │ │ │ │ +└─────┬──────┬──────┬───────────┘ └───────────────────────────┘ │ │ │ + │ │ │ Hall U │ │ │ + │ │ └─────────────────────────────────────────────────────────┘ │ │ + │ │ Hall V │ │ + │ └────────────────────────────────────────────────────────────────────┘ │ + │ Hall W │ + └───────────────────────────────────────────────────────────────────────────────┘ +``` + +### Build and Flash + +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](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + + +## Example Output + +Run the example, you will see the following output log: + +``` +... +I (0) cpu_start: Starting scheduler on APP CPU. +I (327) example: Disable gate driver +I (327) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 +I (337) example: Setup PWM and Hall GPIO (pull up internally) +I (347) example: Initialize PWM (default to turn off all MOSFET) +I (357) example: Initialize over current fault action +I (357) example: Initialize Hall sensor capture +I (367) example: Please turn on the motor power +I (5367) example: Enable gate driver +I (5367) example: Changing speed at background +... +``` + +## Dive into the example + +1. How to change the rotation direction? + + The rotation direction is controlled by how the hall sensor value is parsed. If you pass `false` to `bldc_get_hall_sensor_value`, the BLDC should rotate in clock wise. Likewise, passing `true` to that function will make tha BLDC rotate in counter clock wise. diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/CMakeLists.txt new file mode 100644 index 0000000000..1d97d04dc0 --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "mcpwm_bldc_hall_control_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_control/main/component.mk b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/component.mk similarity index 100% rename from examples/peripherals/mcpwm/mcpwm_bldc_control/main/component.mk rename to examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/component.mk diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c new file mode 100644 index 0000000000..6acbbdbd17 --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c @@ -0,0 +1,255 @@ + +/* MCPWM BLDC control with Hall sensor + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/mcpwm.h" +#include "esp_timer.h" +#include "esp_attr.h" +#include "esp_log.h" + +#define PWM_DEFAULT_FREQ 14400 +#define PWM_MIN_DUTY 40.0 +#define PWM_MAX_DUTY 80.0 +#define PWM_DUTY_STEP 5.0 +#define BLDC_MCPWM_GROUP 0 +#define BLDC_MCPWM_TIMER_U 0 +#define BLDC_MCPWM_TIMER_V 1 +#define BLDC_MCPWM_TIMER_W 2 +#define BLDC_MCPWM_GEN_HIGH MCPWM_GEN_A +#define BLDC_MCPWM_GEN_LOW MCPWM_GEN_B + + +#define BLDC_DRV_EN_GPIO 18 +#define BLDC_DRV_FAULT_GPIO 19 +#define BLDC_DRV_OVER_CURRENT_FAULT MCPWM_SELECT_F0 + +#define BLDC_PWM_UH_GPIO 21 +#define BLDC_PWM_UL_GPIO 22 +#define BLDC_PWM_VH_GPIO 23 +#define BLDC_PWM_VL_GPIO 25 +#define BLDC_PWM_WH_GPIO 26 +#define BLDC_PWM_WL_GPIO 27 +#define HALL_CAP_U_GPIO 2 +#define HALL_CAP_V_GPIO 4 +#define HALL_CAP_W_GPIO 5 + +static const char *TAG = "example"; + +static inline uint32_t bldc_get_hall_sensor_value(bool ccw) +{ + uint32_t hall_val = gpio_get_level(HALL_CAP_U_GPIO) * 4 + gpio_get_level(HALL_CAP_V_GPIO) * 2 + gpio_get_level(HALL_CAP_W_GPIO) * 1; + return ccw ? hall_val ^ (0x07) : hall_val; +} + +static bool IRAM_ATTR bldc_hall_updated(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_channel, const cap_event_data_t *edata, void *user_data) +{ + TaskHandle_t task_to_notify = (TaskHandle_t)user_data; + BaseType_t high_task_wakeup = pdFALSE; + vTaskNotifyGiveFromISR(task_to_notify, &high_task_wakeup); + return high_task_wakeup == pdTRUE; +} + +static void update_bldc_speed(void *arg) +{ + static float duty = PWM_MIN_DUTY; + static float duty_step = PWM_DUTY_STEP; + duty += duty_step; + if (duty > PWM_MAX_DUTY || duty < PWM_MIN_DUTY) { + duty_step *= -1; + } + mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH, duty); + mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW, duty); + mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH, duty); + mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW, duty); + mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH, duty); + mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW, duty); +} + +// U+V- / A+B- +static void bldc_set_phase_up_vm(void) +{ + mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // U+ = PWM + mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // U- = _PWM_ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0 + mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 1 + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0 + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 0 +} + +// W+U- / C+A- +static void bldc_set_phase_wp_um(void) +{ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0 + mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 1 + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0 + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 0 + mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // W+ = PWM + mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // W- = _PWM_ +} + +// W+V- / C+B- +static void bldc_set_phase_wp_vm(void) +{ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0 + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 0 + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0 + mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 1 + mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // W+ = PWM + mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // W- = _PWM_ +} + +// V+U- / B+A- +static void bldc_set_phase_vp_um(void) +{ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0 + mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 1 + mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // V+ = PWM + mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // V- = _PWM_ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0 + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 0 +} + +// V+W- / B+C- +static void bldc_set_phase_vp_wm(void) +{ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0 + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 0 + mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // V+ = PWM + mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // V- = _PWM_ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0 + mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 1 +} + +// U+W- / A+C- +static void bldc_set_phase_up_wm(void) +{ + mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // U+ = PWM + mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // U- = _PWM_ + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0 + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 0 + mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W); + mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0 + mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 1 +} + +typedef void (*bldc_hall_phase_action_t)(void); + +static const bldc_hall_phase_action_t s_hall_actions[] = { + [2] = bldc_set_phase_up_vm, + [6] = bldc_set_phase_wp_vm, + [4] = bldc_set_phase_wp_um, + [5] = bldc_set_phase_vp_um, + [1] = bldc_set_phase_vp_wm, + [3] = bldc_set_phase_up_wm, +}; + +void app_main(void) +{ + uint32_t hall_sensor_value = 0; + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + + ESP_LOGI(TAG, "Disable gate driver"); + gpio_config_t drv_en_config = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1 << BLDC_DRV_EN_GPIO, + }; + ESP_ERROR_CHECK(gpio_config(&drv_en_config)); + gpio_set_level(BLDC_DRV_EN_GPIO, 0); + + ESP_LOGI(TAG, "Setup PWM and Hall GPIO (pull up internally)"); + mcpwm_pin_config_t mcpwm_gpio_config = { + .mcpwm0a_out_num = BLDC_PWM_UH_GPIO, + .mcpwm0b_out_num = BLDC_PWM_UL_GPIO, + .mcpwm1a_out_num = BLDC_PWM_VH_GPIO, + .mcpwm1b_out_num = BLDC_PWM_VL_GPIO, + .mcpwm2a_out_num = BLDC_PWM_WH_GPIO, + .mcpwm2b_out_num = BLDC_PWM_WL_GPIO, + .mcpwm_cap0_in_num = HALL_CAP_U_GPIO, + .mcpwm_cap1_in_num = HALL_CAP_V_GPIO, + .mcpwm_cap2_in_num = HALL_CAP_W_GPIO, + .mcpwm_sync0_in_num = -1, //Not used + .mcpwm_sync1_in_num = -1, //Not used + .mcpwm_sync2_in_num = -1, //Not used + .mcpwm_fault0_in_num = BLDC_DRV_FAULT_GPIO, + .mcpwm_fault1_in_num = -1, //Not used + .mcpwm_fault2_in_num = -1 //Not used + }; + ESP_ERROR_CHECK(mcpwm_set_pin(BLDC_MCPWM_GROUP, &mcpwm_gpio_config)); + // In case there's no pull-up resister for hall sensor on board + gpio_pullup_en(HALL_CAP_U_GPIO); + gpio_pullup_en(HALL_CAP_V_GPIO); + gpio_pullup_en(HALL_CAP_W_GPIO); + gpio_pullup_en(BLDC_DRV_FAULT_GPIO); + + ESP_LOGI(TAG, "Initialize PWM (default to turn off all MOSFET)"); + mcpwm_config_t pwm_config = { + .frequency = PWM_DEFAULT_FREQ, + .cmpr_a = PWM_MIN_DUTY, + .cmpr_b = PWM_MIN_DUTY, + .counter_mode = MCPWM_UP_COUNTER, + .duty_mode = MCPWM_HAL_GENERATOR_MODE_FORCE_LOW, + }; + ESP_ERROR_CHECK(mcpwm_init(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, &pwm_config)); + ESP_ERROR_CHECK(mcpwm_init(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, &pwm_config)); + ESP_ERROR_CHECK(mcpwm_init(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, &pwm_config)); + + ESP_LOGI(TAG, "Initialize over current fault action"); + ESP_ERROR_CHECK(mcpwm_fault_init(BLDC_MCPWM_GROUP, MCPWM_LOW_LEVEL_TGR, BLDC_DRV_OVER_CURRENT_FAULT)); + ESP_ERROR_CHECK(mcpwm_fault_set_cyc_mode(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_DRV_OVER_CURRENT_FAULT, MCPWM_ACTION_FORCE_LOW, MCPWM_ACTION_FORCE_LOW)); + ESP_ERROR_CHECK(mcpwm_fault_set_cyc_mode(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_DRV_OVER_CURRENT_FAULT, MCPWM_ACTION_FORCE_LOW, MCPWM_ACTION_FORCE_LOW)); + ESP_ERROR_CHECK(mcpwm_fault_set_cyc_mode(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_DRV_OVER_CURRENT_FAULT, MCPWM_ACTION_FORCE_LOW, MCPWM_ACTION_FORCE_LOW)); + + ESP_LOGI(TAG, "Initialize Hall sensor capture"); + mcpwm_capture_config_t cap_config = { + .cap_edge = MCPWM_BOTH_EDGE, + .cap_prescale = 1, + .capture_cb = bldc_hall_updated, + .user_data = cur_task, + }; + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(BLDC_MCPWM_GROUP, 0, &cap_config)); + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(BLDC_MCPWM_GROUP, 1, &cap_config)); + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(BLDC_MCPWM_GROUP, 2, &cap_config)); + ESP_LOGI(TAG, "Please turn on the motor power"); + vTaskDelay(pdMS_TO_TICKS(5000)); + ESP_LOGI(TAG, "Enable gate driver"); + gpio_set_level(BLDC_DRV_EN_GPIO, 1); + ESP_LOGI(TAG, "Changing speed at background"); + const esp_timer_create_args_t bldc_timer_args = { + .callback = update_bldc_speed, + .name = "bldc_speed" + }; + esp_timer_handle_t bldc_speed_timer; + ESP_ERROR_CHECK(esp_timer_create(&bldc_timer_args, &bldc_speed_timer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(bldc_speed_timer, 2000000)); + + while (1) { + // The rotation direction is controlled by inverting the hall sensor value + hall_sensor_value = bldc_get_hall_sensor_value(false); + if (hall_sensor_value >= 1 && hall_sensor_value <= sizeof(s_hall_actions) / sizeof(s_hall_actions[0])) { + s_hall_actions[hall_sensor_value](); + } else { + ESP_LOGE(TAG, "invalid bldc phase, wrong hall sensor value:%d", hall_sensor_value); + } + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + } +} From 33e245491f5fa0242b8ece2b54fe747d44214839 Mon Sep 17 00:00:00 2001 From: daiziyan Date: Mon, 23 Aug 2021 12:03:48 +0800 Subject: [PATCH 024/310] docs: translate readme --- README_CN.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/README_CN.md b/README_CN.md index 5408040576..97b26ec620 100644 --- a/README_CN.md +++ b/README_CN.md @@ -2,7 +2,21 @@ * [English Version](./README.md) -ESP-IDF 是乐鑫官方推出的开发框架,适用于 2016 年之后发布的系列芯片[1](#fn1),支持 Windows、Linux 和 macOS 操作系统。 +ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux 和 macOS 操作系统。 + +# ESP-IDF 与乐鑫芯片 + +下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 :green_circle: 代表已支持,:yellow_circle: 代表目前处于预览支持状态。在预览支持阶段,因为新芯片尚未完全添加到构建系统目录,所以一些重要的内容(如文档和技术规格书等)可能会缺失。请确保使用与芯片相匹配的 ESP-IDF 版本。 + +| 芯片 | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | +|:----------- |:-------------: | :-------------:| :-------------:| :-------------:| :-------------:| :-------------:|:---------------------------------------------------------- | +|ESP32 | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | | +|ESP32-S2 | | | | :green_circle: | :green_circle: | :green_circle: | | +|ESP32-C3 | | | | | :green_circle: | :green_circle: | | +|ESP32-S3 | | | | | :yellow_circle:| :green_circle: | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) | +|ESP32-H2 | | | | | | :yellow_circle:| [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) | + +对于 2016 年之前发布的乐鑫芯片(包括 ESP8266 和 ESP8285),请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。 # 使用 ESP-IDF 进行开发 @@ -99,8 +113,3 @@ ESP-IDF 中的子模块采用相对路径([详见 .gitmodules 文件](.gitmodu * 如果你在使用中发现了错误或者需要新的功能,请先[查看 GitHub Issues](https://github.com/espressif/esp-idf/issues),确保该问题没有重复提交。 * 如果你有兴趣为 ESP-IDF 作贡献,请先阅读[贡献指南](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html)。 - - -__________ - -1: ESP-IDF 不支持 ESP8266 和 ESP8285。如有需要,请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。 From fdb9edd8c6fbdb9b0c0909ca718f515d4014ad19 Mon Sep 17 00:00:00 2001 From: Dmitry <> Date: Tue, 24 Aug 2021 12:19:21 +0300 Subject: [PATCH 025/310] Bugfix enable console RX UART for gdbstub for runtime mode only. --- components/driver/uart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index 3f06bc82eb..8bc55f25c9 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -1515,9 +1515,9 @@ err: esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int event_queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags) { esp_err_t r; -#ifdef CONFIG_ESP_GDBSTUB_ENABLED +#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME ESP_RETURN_ON_FALSE((uart_num != CONFIG_ESP_CONSOLE_UART_NUM), ESP_FAIL, UART_TAG, "UART used by GDB-stubs! Please disable GDB in menuconfig."); -#endif // CONFIG_ESP_GDBSTUB_ENABLED +#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((rx_buffer_size > SOC_UART_FIFO_LEN), ESP_FAIL, UART_TAG, "uart rx buffer length error"); ESP_RETURN_ON_FALSE((tx_buffer_size > SOC_UART_FIFO_LEN) || (tx_buffer_size == 0), ESP_FAIL, UART_TAG, "uart tx buffer length error"); From 8b38e9ecf57d3c274de30f5f99ac087c54c99bd1 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 24 Aug 2021 17:40:11 +0800 Subject: [PATCH 026/310] docs: fix edit on github link to point to esp-idf Also add check for IDF_PATH for better error feedback --- docs/conf_common.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/conf_common.py b/docs/conf_common.py index b657c81fb9..46dcddd920 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -15,6 +15,9 @@ import os.path from esp_docs.conf_docs import * # noqa: F403,F401 +if os.environ.get('IDF_PATH') is None: + raise RuntimeError('IDF_PATH should be set, run export.sh before building docs') + BT_DOCS = ['api-guides/blufi.rst', 'api-guides/esp-ble-mesh/**', 'api-reference/bluetooth/**'] @@ -131,7 +134,7 @@ github_repo = 'espressif/esp-idf' # context used by sphinx_idf_theme html_context['github_user'] = 'espressif' -html_context['github_repo'] = 'esp-docs' +html_context['github_repo'] = 'esp-idf' # Extra options required by sphinx_idf_theme project_slug = 'esp-idf' From ef3038490275d02dee46319f9c596d807163213f Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Tue, 3 Aug 2021 13:34:52 +0200 Subject: [PATCH 027/310] esp_eth: add support for multiple Ethernets modules at a time Ethernet driver events properly bounded with ESP NETIF actions to support multiple Ethernet modules used at a time. Components using Ethernet updated to conform with new API. Closes https://github.com/espressif/esp-idf/issues/7318 --- .../esp_eth/include/esp_eth_netif_glue.h | 22 +- components/esp_eth/src/esp_eth_netif_glue.c | 209 +++++++++++++--- components/esp_eth/test/test_emac.c | 48 ++-- .../tcpip_adapter/tcpip_adapter_compat.c | 4 +- docs/en/api-reference/network/esp_eth.rst | 48 ++-- .../protocol_examples_common/connect.c | 22 +- examples/ethernet/README.md | 24 +- examples/ethernet/basic/README.md | 9 +- .../ethernet/basic/main/Kconfig.projbuild | 228 +++++++++++------- .../basic/main/ethernet_example_main.c | 193 +++++++++++---- .../enc28j60/main/enc28j60_example_main.c | 8 +- examples/ethernet/iperf/main/cmd_ethernet.c | 5 +- 12 files changed, 564 insertions(+), 256 deletions(-) diff --git a/components/esp_eth/include/esp_eth_netif_glue.h b/components/esp_eth/include/esp_eth_netif_glue.h index 5e88b5ba5e..d577fc00b7 100644 --- a/components/esp_eth/include/esp_eth_netif_glue.h +++ b/components/esp_eth/include/esp_eth_netif_glue.h @@ -19,6 +19,12 @@ extern "C" { #endif +/** + * @brief Handle of netif glue - an intermediate layer between netif and Ethernet driver + * + */ +typedef struct esp_eth_netif_glue_t* esp_eth_netif_glue_handle_t; + /** * @brief Create a netif glue for Ethernet driver * @note netif glue is used to attach io driver to TCP/IP netif @@ -26,20 +32,23 @@ extern "C" { * @param eth_hdl Ethernet driver handle * @return glue object, which inherits esp_netif_driver_base_t */ -void *esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl); +esp_eth_netif_glue_handle_t esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl); /** * @brief Delete netif glue of Ethernet driver * - * @param glue netif glue + * @param eth_netif_glue netif glue * @return -ESP_OK: delete netif glue successfully */ -esp_err_t esp_eth_del_netif_glue(void *glue); +esp_err_t esp_eth_del_netif_glue(esp_eth_netif_glue_handle_t eth_netif_glue); /** * @brief Register default IP layer handlers for Ethernet * * @note: Ethernet handle might not yet properly initialized when setting up these default handlers + * @warning: This function is deprecated and is kept here only for compatibility reasons. Registration + * of default IP layer handlers for Ethernet is now handled automatically. Do not call this + * function if you want to use multiple Ethernet instances at a time. * * @param[in] esp_netif esp network interface handle created for Ethernet driver * @return @@ -47,12 +56,15 @@ esp_err_t esp_eth_del_netif_glue(void *glue); * - ESP_OK: set default IP layer handlers successfully * - others: other failure occurred during register esp_event handler */ - -esp_err_t esp_eth_set_default_handlers(void *esp_netif); +esp_err_t esp_eth_set_default_handlers(void *esp_netif) __attribute__ ((deprecated)); /** * @brief Unregister default IP layer handlers for Ethernet * + * @warning: This function is deprecated and is kept here only for compatibility reasons. Unregistration + * of default IP layer handlers for Ethernet is now handled automatically if not registered + * by calling esp_eth_set_default_handlers. + * * @param[in] esp_netif esp network interface handle created for Ethernet driver * @return * - ESP_ERR_INVALID_ARG: invalid parameter (esp_netif is NULL) diff --git a/components/esp_eth/src/esp_eth_netif_glue.c b/components/esp_eth/src/esp_eth_netif_glue.c index 7a4e5e1a7d..a1ac4c5594 100644 --- a/components/esp_eth/src/esp_eth_netif_glue.c +++ b/components/esp_eth/src/esp_eth_netif_glue.c @@ -17,13 +17,23 @@ #include "esp_eth_netif_glue.h" #include "esp_event.h" #include "esp_log.h" +#include "esp_check.h" -const static char *TAG = "esp_eth.netif.glue"; +const static char *TAG = "esp_eth.netif.netif_glue"; -typedef struct { +typedef struct esp_eth_netif_glue_t esp_eth_netif_glue_t; + +struct esp_eth_netif_glue_t { esp_netif_driver_base_t base; esp_eth_handle_t eth_driver; -} esp_eth_netif_glue_t; + esp_event_handler_instance_t start_ctx_handler; + esp_event_handler_instance_t stop_ctx_handler; + esp_event_handler_instance_t connect_ctx_handler; + esp_event_handler_instance_t disconnect_ctx_handler; + esp_event_handler_instance_t get_ip_ctx_handler; +}; + +bool s_netif_glue_legacy_events_registered = false; static esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv) { @@ -33,20 +43,20 @@ static esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args) { uint8_t eth_mac[6]; - esp_eth_netif_glue_t *glue = (esp_eth_netif_glue_t *)args; - glue->base.netif = esp_netif; + esp_eth_netif_glue_t *netif_glue = (esp_eth_netif_glue_t *)args; + netif_glue->base.netif = esp_netif; - esp_eth_update_input_path(glue->eth_driver, eth_input_to_netif, esp_netif); + esp_eth_update_input_path(netif_glue->eth_driver, eth_input_to_netif, esp_netif); // set driver related config to esp-netif esp_netif_driver_ifconfig_t driver_ifconfig = { - .handle = glue->eth_driver, + .handle = netif_glue->eth_driver, .transmit = esp_eth_transmit, .driver_free_rx_buffer = NULL }; ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig)); - esp_eth_ioctl(glue->eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac); + esp_eth_ioctl(netif_glue->eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac); ESP_LOGI(TAG, "%02x:%02x:%02x:%02x:%02x:%02x", eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); @@ -56,39 +66,18 @@ static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args) return ESP_OK; } -void *esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl) -{ - esp_eth_netif_glue_t *glue = calloc(1, sizeof(esp_eth_netif_glue_t)); - if (!glue) { - ESP_LOGE(TAG, "create netif glue failed"); - return NULL; - } - glue->eth_driver = eth_hdl; - glue->base.post_attach = esp_eth_post_attach; - esp_eth_increase_reference(eth_hdl); - return &glue->base; -} - -esp_err_t esp_eth_del_netif_glue(void *g) -{ - esp_eth_netif_glue_t *glue = (esp_eth_netif_glue_t *)g; - esp_eth_decrease_reference(glue->eth_driver); - free(glue); - return ESP_OK; -} - esp_err_t esp_eth_clear_default_handlers(void *esp_netif) { - if (!esp_netif) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } + ESP_RETURN_ON_FALSE(esp_netif, ESP_ERR_INVALID_ARG, TAG, "esp_netif handle can't be null"); + esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start); esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop); esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, esp_netif_action_connected); esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, esp_netif_action_disconnected); esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, esp_netif_action_got_ip); + s_netif_glue_legacy_events_registered = false; + return ESP_OK; } @@ -96,10 +85,7 @@ esp_err_t esp_eth_set_default_handlers(void *esp_netif) { esp_err_t ret; - if (!esp_netif) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } + ESP_RETURN_ON_FALSE(esp_netif, ESP_ERR_INVALID_ARG, TAG, "esp_netif handle can't be null"); ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start, esp_netif); if (ret != ESP_OK) { @@ -126,9 +112,158 @@ esp_err_t esp_eth_set_default_handlers(void *esp_netif) goto fail; } + s_netif_glue_legacy_events_registered = true; + return ESP_OK; fail: esp_eth_clear_default_handlers(esp_netif); return ret; } + +static void eth_action_start(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_start: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_start(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_stop(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_stop: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_stop(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_connected(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_connected: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_connected(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_disconnected(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_disconnected: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_disconnected(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_got_ip(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + ip_event_got_ip_t *ip_event = (ip_event_got_ip_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_got_ip: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->base.netif == ip_event->esp_netif) { + esp_netif_action_got_ip(ip_event->esp_netif, base, event_id, event_data); + } +} + +static esp_err_t esp_eth_clear_glue_instance_handlers(esp_eth_netif_glue_handle_t eth_netif_glue) +{ + ESP_RETURN_ON_FALSE(eth_netif_glue, ESP_ERR_INVALID_ARG, TAG, "eth_netif_glue handle can't be null"); + + if (eth_netif_glue->start_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_START, eth_netif_glue->start_ctx_handler); + eth_netif_glue->start_ctx_handler = NULL; + } + + if (eth_netif_glue->stop_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, eth_netif_glue->stop_ctx_handler); + eth_netif_glue->stop_ctx_handler = NULL; + } + + if (eth_netif_glue->connect_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, eth_netif_glue->connect_ctx_handler); + eth_netif_glue->connect_ctx_handler = NULL; + } + + if (eth_netif_glue->disconnect_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, eth_netif_glue->disconnect_ctx_handler); + eth_netif_glue->disconnect_ctx_handler = NULL; + } + + if (eth_netif_glue->get_ip_ctx_handler) { + esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_netif_glue->get_ip_ctx_handler); + eth_netif_glue->get_ip_ctx_handler = NULL; + } + + return ESP_OK; +} + +static esp_err_t esp_eth_set_glue_instance_handlers(esp_eth_netif_glue_handle_t eth_netif_glue) +{ + ESP_RETURN_ON_FALSE(eth_netif_glue, ESP_ERR_INVALID_ARG, TAG, "eth_netif_glue handle can't be null"); + + esp_err_t ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_START, eth_action_start, eth_netif_glue, ð_netif_glue->start_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_STOP, eth_action_stop, eth_netif_glue, ð_netif_glue->stop_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, eth_action_connected, eth_netif_glue, ð_netif_glue->connect_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, eth_action_disconnected, eth_netif_glue, ð_netif_glue->disconnect_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_action_got_ip, eth_netif_glue, ð_netif_glue->get_ip_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + return ESP_OK; + +fail: + esp_eth_clear_glue_instance_handlers(eth_netif_glue); + return ret; +} + +esp_err_t esp_eth_del_netif_glue(esp_eth_netif_glue_handle_t eth_netif_glue) +{ + esp_eth_clear_glue_instance_handlers(eth_netif_glue); + + esp_eth_decrease_reference(eth_netif_glue->eth_driver); + free(eth_netif_glue); + return ESP_OK; +} + +esp_eth_netif_glue_handle_t esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl) +{ + esp_eth_netif_glue_t *netif_glue = calloc(1, sizeof(esp_eth_netif_glue_t)); + if (!netif_glue) { + ESP_LOGE(TAG, "create netif glue failed"); + return NULL; + } + netif_glue->eth_driver = eth_hdl; + netif_glue->base.post_attach = esp_eth_post_attach; + esp_eth_increase_reference(eth_hdl); + + if (s_netif_glue_legacy_events_registered == false) { + if (esp_eth_set_glue_instance_handlers(netif_glue) != ESP_OK) { + esp_eth_del_netif_glue(netif_glue); + return NULL; + } + } + return netif_glue; +} diff --git a/components/esp_eth/test/test_emac.c b/components/esp_eth/test/test_emac.c index 51b20917e7..b5a5f35762 100644 --- a/components/esp_eth/test/test_emac.c +++ b/components/esp_eth/test/test_emac.c @@ -218,11 +218,7 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") // create TCP/IP netif esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -232,8 +228,11 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") // install Ethernet driver TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); // start Ethernet driver TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ @@ -251,7 +250,6 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); esp_netif_destroy(eth_netif); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); @@ -267,11 +265,7 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et // create TCP/IP netif esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -281,8 +275,11 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et // install Ethernet driver TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); for (int i = 0; i < 10; i++) { // start Ethernet driver @@ -304,7 +301,6 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); esp_netif_destroy(eth_netif); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); @@ -320,11 +316,7 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") // create TCP/IP netif esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -333,8 +325,11 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") esp_eth_handle_t eth_handle = NULL; TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); // start Ethernet driver TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ @@ -395,7 +390,6 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") TEST_ESP_OK(phy->del(phy)); TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); esp_netif_destroy(eth_netif); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); @@ -458,11 +452,7 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t // create TCP/IP netif esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -472,8 +462,11 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t // install Ethernet driver TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); // start Ethernet driver TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ @@ -506,7 +499,6 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); esp_netif_destroy(eth_netif); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); diff --git a/components/tcpip_adapter/tcpip_adapter_compat.c b/components/tcpip_adapter/tcpip_adapter_compat.c index b3955020ac..bcd798fe7a 100644 --- a/components/tcpip_adapter/tcpip_adapter_compat.c +++ b/components/tcpip_adapter/tcpip_adapter_compat.c @@ -109,7 +109,7 @@ void tcpip_adapter_init(void) esp_err_t tcpip_adapter_clear_default_eth_handlers(void) { - return esp_eth_clear_default_handlers(netif_from_if(TCPIP_ADAPTER_IF_ETH)); + return ESP_OK; } esp_err_t tcpip_adapter_set_default_eth_handlers(void) @@ -119,8 +119,6 @@ esp_err_t tcpip_adapter_set_default_eth_handlers(void) esp_netif_t *eth_netif = esp_netif_new(&cfg); s_esp_netifs[TCPIP_ADAPTER_IF_ETH] = eth_netif; - - return esp_eth_set_default_handlers(eth_netif); } return ESP_OK; diff --git a/docs/en/api-reference/network/esp_eth.rst b/docs/en/api-reference/network/esp_eth.rst index 07b51867b3..3a8ebd21b5 100644 --- a/docs/en/api-reference/network/esp_eth.rst +++ b/docs/en/api-reference/network/esp_eth.rst @@ -225,6 +225,24 @@ EMAC ``REF_CLK`` can be optionally configured from user application code. Install Driver -------------- +To install the Ethernet driver, we need to combine the instance of MAC and PHY and set some additional high-level configurations (i.e. not specific to either MAC or PHY) in :cpp:class:`esp_eth_config_t`: + +* :cpp:member:`mac`: instance that created from MAC generator (e.g. :cpp:func:`esp_eth_mac_new_esp32`). +* :cpp:member:`phy`: instance that created from PHY generator (e.g. :cpp:func:`esp_eth_phy_new_ip101`). +* :cpp:member:`check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds. +* :cpp:member:`stack_input`: In most of Ethernet IoT applications, any Ethernet frame that received by driver should be passed to upper layer (e.g. TCP/IP stack). This field is set to a function which is responsible to deal with the incoming frames. You can even update this field at runtime via function :cpp:func:`esp_eth_update_input_path` after driver installation. +* :cpp:member:`on_lowlevel_init_done` and :cpp:member:`on_lowlevel_deinit_done`: These two fields are used to specify the hooks which get invoked when low level hardware has been initialized or de-initialized. + +ESP-IDF provides a default configuration for driver installation in macro :c:macro:`ETH_DEFAULT_CONFIG`. + +.. highlight:: c + +:: + + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration + esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver + esp_eth_driver_install(&config, ð_handle); // install driver + Ethernet driver also includes event-driven model, which will send useful and important event to user space. We need to initialize the event loop before installing the Ethernet driver. For more information about event-driven programming, please refer to :doc:`ESP Event <../system/esp_event>`. .. highlight:: c @@ -244,7 +262,7 @@ Ethernet driver also includes event-driven model, which will send useful and imp esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr); ESP_LOGI(TAG, "Ethernet Link Up"); ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x", - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); break; case ETHERNET_EVENT_DISCONNECTED: ESP_LOGI(TAG, "Ethernet Link Down"); @@ -263,24 +281,6 @@ Ethernet driver also includes event-driven model, which will send useful and imp esp_event_loop_create_default(); // create a default event loop that running in background esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL); // register Ethernet event handler (to deal with user specific stuffs when event like link up/down happened) -To install the Ethernet driver, we need to combine the instance of MAC and PHY and set some additional high-level configurations (i.e. not specific to either MAC or PHY) in :cpp:class:`esp_eth_config_t`: - -* :cpp:member:`mac`: instance that created from MAC generator (e.g. :cpp:func:`esp_eth_mac_new_esp32`). -* :cpp:member:`phy`: instance that created from PHY generator (e.g. :cpp:func:`esp_eth_phy_new_ip101`). -* :cpp:member:`check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds. -* :cpp:member:`stack_input`: In most of Ethernet IoT applications, any Ethernet frame that received by driver should be passed to upper layer (e.g. TCP/IP stack). This field is set to a function which is responsible to deal with the incoming frames. You can even update this field at runtime via function :cpp:func:`esp_eth_update_input_path` after driver installation. -* :cpp:member:`on_lowlevel_init_done` and :cpp:member:`on_lowlevel_deinit_done`: These two fields are used to specify the hooks which get invoked when low level hardware has been initialized or de-initialized. - -ESP-IDF provides a default configuration for driver installation in macro :c:macro:`ETH_DEFAULT_CONFIG`. - -.. highlight:: c - -:: - - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - esp_eth_driver_install(&config, ð_handle); // install driver - Start Ethernet Driver --------------------- @@ -303,8 +303,8 @@ The TCP/IP stack used in ESP-IDF is called LwIP, for more information about it, To connect Ethernet driver to TCP/IP stack, these three steps need to follow: 1. Create network interface for Ethernet driver -2. Register IP event handlers -3. Attach the network interface to Ethernet driver +2. Attach the network interface to Ethernet driver +3. Register IP event handlers More information about network interface, please refer to :doc:`Network Interface `. @@ -330,12 +330,14 @@ More information about network interface, please refer to :doc:`Network Interfac esp_netif_init()); // Initialize TCP/IP network interface (should be called only once in application) esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); // apply default network interface configuration for Ethernet esp_netif_t *eth_netif = esp_netif_new(&cfg); // create network interface for Ethernet driver - esp_eth_set_default_handlers(eth_netif); // set default handlers to process TCP/IP stuffs - esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // register user defined IP event handlers esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)); // attach Ethernet driver to TCP/IP stack + esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // register user defined IP event handlers esp_eth_start(eth_handle); // start Ethernet driver state machine +.. warning:: + It is recommended to fully initialize the Ethernet driver and network interface prior registering user's Ethernet/IP event handlers, i.e. register the event handlers as the last thing prior starting the Ethernet driver. Such approach ensures that Ethernet/IP events get executed first by the Ethernet driver or network interface and so the system is in expected state when executing user's handlers. + .. _misc-operation-of-driver: Misc control of Ethernet driver diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index d1063b43a0..a62f67f7f9 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -343,7 +343,7 @@ static void on_eth_event(void *esp_netif, esp_event_base_t event_base, switch (event_id) { case ETHERNET_EVENT_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); - esp_netif_create_ip6_linklocal(esp_netif); + ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif)); break; default: break; @@ -355,7 +355,7 @@ static void on_eth_event(void *esp_netif, esp_event_base_t event_base, static esp_eth_handle_t s_eth_handle = NULL; static esp_eth_mac_t *s_mac = NULL; static esp_eth_phy_t *s_phy = NULL; -static void *s_eth_glue = NULL; +static esp_eth_netif_glue_handle_t s_eth_glue = NULL; static esp_netif_t *eth_start(void) { @@ -373,14 +373,7 @@ static esp_netif_t *eth_start(void) esp_netif_t *netif = esp_netif_new(&netif_config); assert(netif); free(desc); - // Set default handlers to process TCP/IP stuffs - ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif)); - // Register user defined event handers - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); -#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 - ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); -#endif + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; @@ -460,6 +453,14 @@ static esp_netif_t *eth_start(void) // combine driver with netif s_eth_glue = esp_eth_new_netif_glue(s_eth_handle); esp_netif_attach(netif, s_eth_glue); + + // Register user defined event handers + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); +#endif + esp_eth_start(s_eth_handle); return netif; } @@ -474,7 +475,6 @@ static void eth_stop(void) #endif ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle)); ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue)); - ESP_ERROR_CHECK(esp_eth_clear_default_handlers(eth_netif)); ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle)); ESP_ERROR_CHECK(s_phy->del(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); diff --git a/examples/ethernet/README.md b/examples/ethernet/README.md index c12fe4ca16..ed6e524a94 100644 --- a/examples/ethernet/README.md +++ b/examples/ethernet/README.md @@ -28,29 +28,29 @@ See the [README.md](../README.md) file in the upper level [examples](../) direct ### Using SPI ethernet modules -* SPI Ethernet modules (DM9051, W5500, ...) typically consume one SPI interface plus an interrupt and reset GPIO. By default they're connected as follows: +* SPI Ethernet modules (DM9051, W5500, ...) typically consume one SPI interface plus an interrupt and reset GPIO. They can be connected as follows for ESP32 as an example. However, they can be remapped to any pin using the GPIO Matrix. | GPIO | DM9051 | | ------ | ----------- | -| GPIO19 | SPI_CLK | -| GPIO23 | SPI_MOSI | -| GPIO25 | SPI_MISO | -| GPIO22 | SPI_CS | +| GPIO14 | SPI_CLK | +| GPIO13 | SPI_MOSI | +| GPIO12 | SPI_MISO | +| GPIO15 | SPI_CS | | GPIO4 | Interrupt | -| GPIO5 | Reset | +| NC | Reset | -Please consult Espressif Technical reference manual for assigning any other pins, especially when choosing from system configuration menu for the ethernet examples, -some pins cannot be used. +Please consult Espressif Technical reference manual along with datasheet for specific ESP Module you use when assigning any other pins, especially when choosing from system configuration menu for the ethernet examples, some pins cannot be used (they may already be utilized for different purpose like SPI Flash/RAM, etc.). ## Common Configurations 1. In the `Example Configuration` menu: - * Choose the kind of Ethernet under `Ethernet Type`. + * Choose the kind of Ethernet. * If `Internal EMAC` is selected: * Choose PHY device under `Ethernet PHY Device`, by default, the **ESP32-Ethernet-Kit** has an `IP101` on board. * Set GPIO number used by SMI signal under `SMI MDC GPIO number` and `SMI MDIO GPIO number` respectively. - * If `DM9051 Module` is selected: - * Set SPI specific configuration, including SPI host number, GPIO number and clock rate. + * If `SPI Ethernet` is selected: + * Set SPI specific configuration, including SPI host number, GPIO numbers and clock rate. + * Multiple Ethernet SPI modules of the same type can be connected to single SPI interface at a time. The modules then share data and CLK signals. The CS, interrupt and reset pins need to be specifically configured for each module separately. * Set GPIO number used by PHY chip reset under `PHY Reset GPIO number`, you may have to change the default value according to your board schematic. **PHY hardware reset can be disabled by set this value to -1**. * Set PHY address under `PHY Address`, you may have to change the default value according to your board schematic. @@ -61,7 +61,7 @@ some pins cannot be used. * If `Output RMII clock from internal` is enabled, you also have to set the GPIO number that used to output the RMII clock, under `RMII clock GPIO number`. In this case, you can set the GPIO number to 16 or 17. * If `Output RMII clock from GPIO0 (Experimental!)` is also enabled, then you have no choice but GPIO0 to output the RMII clock. * In `Amount of Ethernet DMA Rx buffers` and `Amount of Ethernet DMA Tx buffers`, you can set the amount of DMA buffers used for Tx and Rx. - * Under `Support SPI to Ethernet Module` sub-menu, select the SPI module that you used for this example. Currently ESP-IDF only supports `DM9051`. + * Under `Support SPI to Ethernet Module` sub-menu, select the SPI module that you used for this example. Currently ESP-IDF only supports `DM9051`, `W5500` and `KSZ8851SNL`. ## Common Troubleshooting diff --git a/examples/ethernet/basic/README.md b/examples/ethernet/basic/README.md index a2f49723a4..49961a0266 100644 --- a/examples/ethernet/basic/README.md +++ b/examples/ethernet/basic/README.md @@ -17,12 +17,19 @@ If you have a new Ethernet application to go (for example, connect to IoT cloud To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. Up until now, ESP-IDF supports up to four Ethernet PHY: `LAN8720`, `IP101`, `DP83848` and `RTL8201`, additional PHY drivers should be implemented by users themselves. -Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). This example will take the **DM9051** as an example, illustrating how to install the Ethernet driver in the same manner. +Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). This example will take the `DM9051`, `W5500` or `KSZ8851SNL` SPI modules as an example, illustrating how to install the Ethernet driver in the same manner. + +The ESP-IDF supports the usage of multiple Ethernet interfaces at a time when external modules are utilized which is also demonstrated by this example. There are several options you can combine: + * Internal EMAC and one SPI Ethernet module. + * Two SPI Ethernet modules of the same type connected to single SPI interface and accessed by switching appropriate CS. + * Internal EMAC and two SPI Ethernet modules of the same type. #### Pin Assignment See common pin assignments for Ethernet examples from [upper level](../README.md#common-pin-assignments). +When using two Ethernet SPI modules at a time, they are to be connected to single SPI interface. Both modules then share data (MOSI/MISO) and CLK signals. However, the CS, interrupt and reset pins need to be connected to separate GPIO for each Ethernet SPI module. + ### Configure the project ``` diff --git a/examples/ethernet/basic/main/Kconfig.projbuild b/examples/ethernet/basic/main/Kconfig.projbuild index 71239ebdf0..671f673193 100644 --- a/examples/ethernet/basic/main/Kconfig.projbuild +++ b/examples/ethernet/basic/main/Kconfig.projbuild @@ -1,46 +1,21 @@ menu "Example Configuration" - config EXAMPLE_USE_SPI_ETHERNET - bool + config EXAMPLE_GPIO_RANGE_MIN + int + default 0 - choice EXAMPLE_ETHERNET_TYPE - prompt "Ethernet Type" - default EXAMPLE_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32 - default EXAMPLE_USE_W5500 + config EXAMPLE_GPIO_RANGE_MAX + int + default 33 if IDF_TARGET_ESP32 + default 46 if IDF_TARGET_ESP32S2 + default 19 if IDF_TARGET_ESP32C3 + + config EXAMPLE_USE_INTERNAL_ETHERNET + depends on IDF_TARGET_ESP32 + select ETH_USE_ESP32_EMAC + bool "Internal EMAC" help - Select which kind of Ethernet will be used in the example. - - config EXAMPLE_USE_INTERNAL_ETHERNET - depends on IDF_TARGET_ESP32 - select ETH_USE_ESP32_EMAC - bool "Internal EMAC" - help - Select internal Ethernet MAC controller. - - config EXAMPLE_USE_DM9051 - bool "DM9051 Module" - select EXAMPLE_USE_SPI_ETHERNET - select ETH_USE_SPI_ETHERNET - select ETH_SPI_ETHERNET_DM9051 - help - Select external SPI-Ethernet module (DM9051). - - config EXAMPLE_USE_W5500 - bool "W5500 Module" - select EXAMPLE_USE_SPI_ETHERNET - select ETH_USE_SPI_ETHERNET - select ETH_SPI_ETHERNET_W5500 - help - Select external SPI-Ethernet module (W5500). - - config EXAMPLE_USE_KSZ8851SNL - bool "KSZ8851SNL Module" - select EXAMPLE_USE_SPI_ETHERNET - select ETH_USE_SPI_ETHERNET - select ETH_SPI_ETHERNET_KSZ8851SNL - help - Select external SPI-Ethernet module (KSZ8851SNL). - endchoice # EXAMPLE_ETHERNET_TYPE + Use internal Ethernet MAC controller. if EXAMPLE_USE_INTERNAL_ETHERNET choice EXAMPLE_ETH_PHY_MODEL @@ -95,18 +70,75 @@ menu "Example Configuration" config EXAMPLE_ETH_MDC_GPIO int "SMI MDC GPIO number" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX default 23 help Set the GPIO number used by SMI MDC. config EXAMPLE_ETH_MDIO_GPIO int "SMI MDIO GPIO number" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX default 18 help Set the GPIO number used by SMI MDIO. + + config EXAMPLE_ETH_PHY_RST_GPIO + int "PHY Reset GPIO number" + range -1 EXAMPLE_GPIO_RANGE_MAX + default 5 + help + Set the GPIO number used to reset PHY chip. + Set to -1 to disable PHY chip hardware reset. + + config EXAMPLE_ETH_PHY_ADDR + int "PHY Address" + range 0 31 + default 1 + help + Set PHY address according your board schematic. endif # EXAMPLE_USE_INTERNAL_ETHERNET + config EXAMPLE_USE_SPI_ETHERNET + bool "SPI Ethernet" + default y + select ETH_USE_SPI_ETHERNET + help + Use external SPI-Ethernet module(s). + if EXAMPLE_USE_SPI_ETHERNET + config EXAMPLE_SPI_ETHERNETS_NUM + int "Number of SPI Ethernet modules to use at a time" + range 1 2 + default 1 + help + Set the number of SPI Ethernet modules you want to use at a time. Multiple SPI modules can be connected + to one SPI interface and can be separately accessed based on state of associated Chip Select (CS). + + choice EXAMPLE_ETHERNET_TYPE_SPI + prompt "Ethernet SPI" + default EXAMPLE_USE_W5500 + help + Select which kind of Ethernet will be used in the example. + + config EXAMPLE_USE_DM9051 + bool "DM9051 Module" + select ETH_SPI_ETHERNET_DM9051 + help + Select external SPI-Ethernet module (DM9051). + + config EXAMPLE_USE_KSZ8851SNL + bool "KSZ8851SNL Module" + select ETH_SPI_ETHERNET_KSZ8851SNL + help + Select external SPI-Ethernet module (KSZ8851SNL). + + config EXAMPLE_USE_W5500 + bool "W5500 Module" + select ETH_SPI_ETHERNET_W5500 + help + Select external SPI-Ethernet module (W5500). + endchoice + config EXAMPLE_ETH_SPI_HOST int "SPI Host Number" range 0 2 @@ -116,48 +148,31 @@ menu "Example Configuration" config EXAMPLE_ETH_SPI_SCLK_GPIO int "SPI SCLK GPIO number" - range 0 34 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 19 if IDF_TARGET_ESP32C3 - default 18 if IDF_TARGET_ESP32 - default 20 if IDF_TARGET_ESP32S2 + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 14 if IDF_TARGET_ESP32 + default 12 if IDF_TARGET_ESP32S2 default 6 if IDF_TARGET_ESP32C3 help Set the GPIO number used by SPI SCLK. config EXAMPLE_ETH_SPI_MOSI_GPIO int "SPI MOSI GPIO number" - range 0 34 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 19 if IDF_TARGET_ESP32C3 - default 23 if IDF_TARGET_ESP32 - default 19 if IDF_TARGET_ESP32S2 + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 13 if IDF_TARGET_ESP32 + default 11 if IDF_TARGET_ESP32S2 default 7 if IDF_TARGET_ESP32C3 help Set the GPIO number used by SPI MOSI. config EXAMPLE_ETH_SPI_MISO_GPIO int "SPI MISO GPIO number" - range 0 34 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 19 if IDF_TARGET_ESP32C3 - default 19 if IDF_TARGET_ESP32 - default 18 if IDF_TARGET_ESP32S2 + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 12 if IDF_TARGET_ESP32 + default 13 if IDF_TARGET_ESP32S2 default 2 if IDF_TARGET_ESP32C3 help Set the GPIO number used by SPI MISO. - config EXAMPLE_ETH_SPI_CS_GPIO - int "SPI CS GPIO number" - range 0 34 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 19 if IDF_TARGET_ESP32C3 - default 16 if IDF_TARGET_ESP32 - default 21 if IDF_TARGET_ESP32S2 - default 10 if IDF_TARGET_ESP32C3 - help - Set the GPIO number used by SPI CS. - config EXAMPLE_ETH_SPI_CLOCK_MHZ int "SPI clock speed (MHz)" range 5 80 @@ -166,25 +181,70 @@ menu "Example Configuration" help Set the clock speed (MHz) of SPI interface. - config EXAMPLE_ETH_SPI_INT_GPIO - int "Interrupt GPIO number" - default 17 if IDF_TARGET_ESP32 - default 4 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 + config EXAMPLE_ETH_SPI_CS0_GPIO + int "SPI CS0 GPIO number for SPI Ethernet module #1" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 15 if IDF_TARGET_ESP32 + default 10 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 help - Set the GPIO number used by the SPI Ethernet module interrupt line. + Set the GPIO number used by SPI CS0, i.e. Chip Select associated with the first SPI Eth module). + + config EXAMPLE_ETH_SPI_CS1_GPIO + depends on EXAMPLE_SPI_ETHERNETS_NUM > 1 + int "SPI CS1 GPIO number for SPI Ethernet module #2" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 32 if IDF_TARGET_ESP32 + default 7 if IDF_TARGET_ESP32S2 + default 8 if IDF_TARGET_ESP32C3 + help + Set the GPIO number used by SPI CS1, i.e. Chip Select associated with the second SPI Eth module. + + config EXAMPLE_ETH_SPI_INT0_GPIO + int "Interrupt GPIO number SPI Ethernet module #1" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 4 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 + help + Set the GPIO number used by the first SPI Ethernet module interrupt line. + + config EXAMPLE_ETH_SPI_INT1_GPIO + depends on EXAMPLE_SPI_ETHERNETS_NUM > 1 + int "Interrupt GPIO number SPI Ethernet module #2" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 33 if IDF_TARGET_ESP32 + default 5 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 + help + Set the GPIO number used by the second SPI Ethernet module interrupt line. + + config EXAMPLE_ETH_SPI_PHY_RST0_GPIO + int "PHY Reset GPIO number of SPI Ethernet Module #1" + range -1 EXAMPLE_GPIO_RANGE_MAX + default -1 + help + Set the GPIO number used to reset PHY chip on the first SPI Ethernet module. + Set to -1 to disable PHY chip hardware reset. + + config EXAMPLE_ETH_SPI_PHY_RST1_GPIO + depends on EXAMPLE_SPI_ETHERNETS_NUM > 1 + int "PHY Reset GPIO number of SPI Ethernet Module #2" + range -1 EXAMPLE_GPIO_RANGE_MAX + default -1 + help + Set the GPIO number used to reset PHY chip on the second SPI Ethernet module. + Set to -1 to disable PHY chip hardware reset. + + config EXAMPLE_ETH_SPI_PHY_ADDR0 + int "PHY Address of SPI Ethernet Module #1" + range 0 31 + default 1 + help + Set the first SPI Ethernet module PHY address according your board schematic. + + config EXAMPLE_ETH_SPI_PHY_ADDR1 + depends on EXAMPLE_SPI_ETHERNETS_NUM > 1 + int "PHY Address of SPI Ethernet Module #2" + range 0 31 + default 1 + help + Set the second SPI Ethernet module PHY address according your board schematic. endif # EXAMPLE_USE_SPI_ETHERNET - - config EXAMPLE_ETH_PHY_RST_GPIO - int "PHY Reset GPIO number" - default 5 - help - Set the GPIO number used to reset PHY chip. - Set to -1 to disable PHY chip hardware reset. - - config EXAMPLE_ETH_PHY_ADDR - int "PHY Address" - range 0 31 - default 1 - help - Set PHY address according your board schematic. endmenu diff --git a/examples/ethernet/basic/main/ethernet_example_main.c b/examples/ethernet/basic/main/ethernet_example_main.c index d68f523419..263b29d875 100644 --- a/examples/ethernet/basic/main/ethernet_example_main.c +++ b/examples/ethernet/basic/main/ethernet_example_main.c @@ -22,6 +22,23 @@ static const char *TAG = "eth_example"; +#if CONFIG_EXAMPLE_USE_SPI_ETHERNET +#define INIT_SPI_ETH_MODULE_CONFIG(eth_module_config, num) \ + do { \ + eth_module_config[num].spi_cs_gpio = CONFIG_EXAMPLE_ETH_SPI_CS ##num## _GPIO; \ + eth_module_config[num].int_gpio = CONFIG_EXAMPLE_ETH_SPI_INT ##num## _GPIO; \ + eth_module_config[num].phy_reset_gpio = CONFIG_EXAMPLE_ETH_SPI_PHY_RST ##num## _GPIO; \ + eth_module_config[num].phy_addr = CONFIG_EXAMPLE_ETH_SPI_PHY_ADDR ##num; \ + } while(0) + +typedef struct { + uint8_t spi_cs_gpio; + uint8_t int_gpio; + int8_t phy_reset_gpio; + uint8_t phy_addr; +}spi_eth_module_config_t; +#endif + /** Event handler for Ethernet events */ static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) @@ -72,19 +89,18 @@ void app_main(void) ESP_ERROR_CHECK(esp_netif_init()); // Create default event loop that running in background ESP_ERROR_CHECK(esp_event_loop_create_default()); + +#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET + // Create new default instance of esp-netif for Ethernet esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&cfg); - // Set default handlers to process TCP/IP stuffs - ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif)); - // Register user defined event handers - ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); + // Init MAC and PHY configs to default eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; -#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); @@ -101,9 +117,43 @@ void app_main(void) #elif CONFIG_EXAMPLE_ETH_PHY_KSZ8081 esp_eth_phy_t *phy = esp_eth_phy_new_ksz8081(&phy_config); #endif -#elif CONFIG_ETH_USE_SPI_ETHERNET + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); + esp_eth_handle_t eth_handle = NULL; + ESP_ERROR_CHECK(esp_eth_driver_install(&config, ð_handle)); + /* attach Ethernet driver to TCP/IP stack */ + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); +#endif //CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET + +#if CONFIG_EXAMPLE_USE_SPI_ETHERNET + // Create instance(s) of esp-netif for SPI Ethernet(s) + esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); + esp_netif_config_t cfg_spi = { + .base = &esp_netif_config, + .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH + }; + esp_netif_t *eth_netif_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { NULL }; + char if_key_str[10]; + char if_desc_str[10]; + char num_str[3]; + for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) { + itoa(i, num_str, 10); + strcat(strcpy(if_key_str, "ETH_SPI_"), num_str); + strcat(strcpy(if_desc_str, "eth"), num_str); + esp_netif_config.if_key = if_key_str; + esp_netif_config.if_desc = if_desc_str; + esp_netif_config.route_prio = 30 - i; + eth_netif_spi[i] = esp_netif_new(&cfg_spi); + } + + // Init MAC and PHY configs to default + eth_mac_config_t mac_config_spi = ETH_MAC_DEFAULT_CONFIG(); + eth_phy_config_t phy_config_spi = ETH_PHY_DEFAULT_CONFIG(); + + // Install GPIO ISR handler to be able to service SPI Eth modlues interrupts gpio_install_isr_service(0); - spi_device_handle_t spi_handle = NULL; + + // Init SPI bus + spi_device_handle_t spi_handle[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { NULL }; spi_bus_config_t buscfg = { .miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO, .mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO, @@ -111,66 +161,121 @@ void app_main(void) .quadwp_io_num = -1, .quadhd_io_num = -1, }; - ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1)); + ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); + // Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.) + spi_eth_module_config_t spi_eth_module_config[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM]; + INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 0); +#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM > 1 + INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 1); +#endif + + // Configure SPI interface and Ethernet driver for specific SPI module + esp_eth_mac_t *mac_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM]; + esp_eth_phy_t *phy_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM]; + esp_eth_handle_t eth_handle_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { NULL }; #if CONFIG_EXAMPLE_USE_KSZ8851SNL spi_device_interface_config_t devcfg = { .mode = 0, .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000, - .spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO, .queue_size = 20 }; - ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle)); - /* KSZ8851SNL ethernet driver is based on spi driver */ - eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle); - ksz8851snl_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO; - esp_eth_mac_t *mac = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config); - esp_eth_phy_t *phy = esp_eth_phy_new_ksz8851snl(&phy_config); + + for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) { + // Set SPI module Chip Select GPIO + devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio; + + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle[i])); + // KSZ8851SNL ethernet driver is based on spi driver + eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle[i]); + + // Set remaining GPIO numbers and configuration used by the SPI module + ksz8851snl_config.int_gpio_num = spi_eth_module_config[i].int_gpio; + phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr; + phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio; + + mac_spi[i] = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config_spi); + phy_spi[i] = esp_eth_phy_new_ksz8851snl(&phy_config_spi); + } #elif CONFIG_EXAMPLE_USE_DM9051 spi_device_interface_config_t devcfg = { .command_bits = 1, .address_bits = 7, .mode = 0, .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000, - .spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO, .queue_size = 20 }; - ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle)); - /* dm9051 ethernet driver is based on spi driver */ - eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); - dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO; - esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); - esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config); + + for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) { + // Set SPI module Chip Select GPIO + devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio; + + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle[i])); + // dm9051 ethernet driver is based on spi driver + eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle[i]); + + // Set remaining GPIO numbers and configuration used by the SPI module + dm9051_config.int_gpio_num = spi_eth_module_config[i].int_gpio; + phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr; + phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio; + + mac_spi[i] = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config_spi); + phy_spi[i] = esp_eth_phy_new_dm9051(&phy_config_spi); + } #elif CONFIG_EXAMPLE_USE_W5500 spi_device_interface_config_t devcfg = { .command_bits = 16, // Actually it's the address phase in W5500 SPI frame .address_bits = 8, // Actually it's the control phase in W5500 SPI frame .mode = 0, .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000, - .spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO, .queue_size = 20 }; - ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle)); - /* w5500 ethernet driver is based on spi driver */ - eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); - w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO; - esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); - esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config); -#endif -#endif // CONFIG_ETH_USE_SPI_ETHERNET - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); - esp_eth_handle_t eth_handle = NULL; - ESP_ERROR_CHECK(esp_eth_driver_install(&config, ð_handle)); -#if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET - /* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually. + + for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) { + // Set SPI module Chip Select GPIO + devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio; + + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle[i])); + // w5500 ethernet driver is based on spi driver + eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle[i]); + + // Set remaining GPIO numbers and configuration used by the SPI module + w5500_config.int_gpio_num = spi_eth_module_config[i].int_gpio; + phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr; + phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio; + + mac_spi[i] = esp_eth_mac_new_w5500(&w5500_config, &mac_config_spi); + phy_spi[i] = esp_eth_phy_new_w5500(&phy_config_spi); + } +#endif //CONFIG_EXAMPLE_USE_W5500 + + for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) { + esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac_spi[i], phy_spi[i]); + ESP_ERROR_CHECK(esp_eth_driver_install(ð_config_spi, ð_handle_spi[i])); + + /* The SPI Ethernet module might not have a burned factory MAC address, we cat to set it manually. 02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control. - */ - ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) { - 0x02, 0x00, 0x00, 0x12, 0x34, 0x56 - })); -#endif - /* attach Ethernet driver to TCP/IP stack */ - ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); + */ + ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle_spi[i], ETH_CMD_S_MAC_ADDR, (uint8_t[]) { + 0x02, 0x00, 0x00, 0x12, 0x34, 0x56 + i + })); + + // attach Ethernet driver to TCP/IP stack + ESP_ERROR_CHECK(esp_netif_attach(eth_netif_spi[i], esp_eth_new_netif_glue(eth_handle_spi[i]))); + } +#endif // CONFIG_ETH_USE_SPI_ETHERNET + + // Register user defined event handers + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); + /* start Ethernet driver state machine */ +#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET ESP_ERROR_CHECK(esp_eth_start(eth_handle)); +#endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET +#if CONFIG_EXAMPLE_USE_SPI_ETHERNET + for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) { + ESP_ERROR_CHECK(esp_eth_start(eth_handle_spi[i])); + } +#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET } diff --git a/examples/ethernet/enc28j60/main/enc28j60_example_main.c b/examples/ethernet/enc28j60/main/enc28j60_example_main.c index f267c96032..70a10c44dd 100644 --- a/examples/ethernet/enc28j60/main/enc28j60_example_main.c +++ b/examples/ethernet/enc28j60/main/enc28j60_example_main.c @@ -74,11 +74,6 @@ void app_main(void) ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // Set default handlers to process TCP/IP stuffs - ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif)); - // Register user defined event handers - ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); spi_bus_config_t buscfg = { .miso_io_num = CONFIG_EXAMPLE_ENC28J60_MISO_GPIO, @@ -134,6 +129,9 @@ void app_main(void) /* attach Ethernet driver to TCP/IP stack */ ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); + // Register user defined event handers + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); /* start Ethernet driver state machine */ ESP_ERROR_CHECK(esp_eth_start(eth_handle)); diff --git a/examples/ethernet/iperf/main/cmd_ethernet.c b/examples/ethernet/iperf/main/cmd_ethernet.c index 2afe66042b..719e20d772 100644 --- a/examples/ethernet/iperf/main/cmd_ethernet.c +++ b/examples/ethernet/iperf/main/cmd_ethernet.c @@ -188,9 +188,6 @@ void register_ethernet(void) ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); eth_netif = esp_netif_new(&cfg); - ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif)); - ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler, NULL)); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -304,6 +301,8 @@ void register_ethernet(void) })); #endif ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler, NULL)); ESP_ERROR_CHECK(esp_eth_start(eth_handle)); #if CONFIG_EXAMPLE_USE_ENC28J60 && CONFIG_EXAMPLE_ENC28J60_DUPLEX_FULL From accbaee57ceca241ca117a53f486b7f79ed528b9 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 24 Aug 2021 23:20:50 +0800 Subject: [PATCH 028/310] Add USB Host Library This commit adds the preliminary version of the USB Host Library. This commit contains: - USBH (USB Host Driver) - Hub Driver that only supports a single device and device enumeration - USB Host Library (asychronous API) - Test cases for USB Host Library asychronous API The following changes were made to the existing HCD: - Removed HCD_PIPE_STATE_INVALID. Pipes are no longer invalidated - Changed pipe commands to halt, flush, and clear. Pipes need to be manually halted, flush, and cleared. - Halting and flushing a pipe will execute the pipe callback if it causes a HCD_PIPE_EVENT_URB_DONE event --- .../hal/include/hal/usb_types_private.h | 2 +- components/hal/include/hal/usbh_hal.h | 4 +- components/hal/usbh_hal.c | 25 +- components/usb/CMakeLists.txt | 8 +- components/usb/Kconfig | 49 +- components/usb/hcd.c | 1309 ++++++++--------- components/usb/hub.c | 668 +++++++++ components/usb/include/usb/usb_host.h | 408 +++++ components/usb/include/usb/usb_host_misc.h | 130 ++ components/usb/include/usb/usb_types_ch9.h | 464 ++++++ components/usb/include/usb/usb_types_stack.h | 137 ++ components/usb/maintainers.md | 58 +- components/usb/private_include/hcd.h | 92 +- components/usb/private_include/hub.h | 88 ++ components/usb/private_include/usb.h | 561 ------- components/usb/private_include/usb_private.h | 68 +- components/usb/private_include/usbh.h | 383 +++++ components/usb/test/CMakeLists.txt | 5 +- .../usb/test/common/test_usb_mock_classes.c | 2 +- .../usb/test/common/test_usb_mock_classes.h | 104 +- components/usb/test/hcd/test_hcd_bulk.c | 26 +- components/usb/test/hcd/test_hcd_common.c | 43 +- components/usb/test/hcd/test_hcd_common.h | 22 +- components/usb/test/hcd/test_hcd_ctrl.c | 81 +- components/usb/test/hcd/test_hcd_intr.c | 18 +- components/usb/test/hcd/test_hcd_isoc.c | 20 +- components/usb/test/hcd/test_hcd_port.c | 155 +- components/usb/test/usb_host/ctrl_client.h | 15 + .../usb/test/usb_host/ctrl_client_async_seq.c | 185 +++ components/usb/test/usb_host/msc_client.h | 17 + .../usb/test/usb_host/msc_client_async_seq.c | 242 +++ .../usb/test/usb_host/test_usb_host_async.c | 157 ++ .../usb/test/usb_host/test_usb_host_misc.c | 439 ++++++ components/usb/usb_host.c | 1270 ++++++++++++++++ components/usb/usb_host_misc.c | 168 +++ components/usb/usb_private.c | 38 + components/usb/usbh.c | 909 ++++++++++++ 37 files changed, 6795 insertions(+), 1575 deletions(-) create mode 100644 components/usb/hub.c create mode 100644 components/usb/include/usb/usb_host.h create mode 100644 components/usb/include/usb/usb_host_misc.h create mode 100644 components/usb/include/usb/usb_types_ch9.h create mode 100644 components/usb/include/usb/usb_types_stack.h create mode 100644 components/usb/private_include/hub.h delete mode 100644 components/usb/private_include/usb.h create mode 100644 components/usb/private_include/usbh.h create mode 100644 components/usb/test/usb_host/ctrl_client.h create mode 100644 components/usb/test/usb_host/ctrl_client_async_seq.c create mode 100644 components/usb/test/usb_host/msc_client.h create mode 100644 components/usb/test/usb_host/msc_client_async_seq.c create mode 100644 components/usb/test/usb_host/test_usb_host_async.c create mode 100644 components/usb/test/usb_host/test_usb_host_misc.c create mode 100644 components/usb/usb_host.c create mode 100644 components/usb/usb_host_misc.c create mode 100644 components/usb/usb_private.c create mode 100644 components/usb/usbh.c diff --git a/components/hal/include/hal/usb_types_private.h b/components/hal/include/hal/usb_types_private.h index 868fdee589..5cce6b66af 100644 --- a/components/hal/include/hal/usb_types_private.h +++ b/components/hal/include/hal/usb_types_private.h @@ -16,7 +16,7 @@ Note: This header file contains USB2.0 related types and macros that can be used by code specific to the DWC_OTG controller (i.e., the HW specific layers of the USB host stack). Thus, this header is only meant to be used below (and including) the HAL layer. For types and macros that are HW implementation agnostic (i.e., HCD layer and above), add them -to the "usb.h" header instead. +to the "usb/usb_types_ch9.h" header instead. */ #pragma once diff --git a/components/hal/include/hal/usbh_hal.h b/components/hal/include/hal/usbh_hal.h index 1ff721c373..b315f6c0b1 100644 --- a/components/hal/include/hal/usbh_hal.h +++ b/components/hal/include/hal/usbh_hal.h @@ -151,7 +151,7 @@ typedef struct { //Channel control, status, and information union { struct { - uint32_t active: 1; /**< The channel is enabled */ + uint32_t active: 1; /**< Debugging bit to indicate whether channel is enabled */ uint32_t halt_requested: 1; /**< A halt has been requested */ uint32_t error_pending: 1; /**< The channel is waiting for the error to be handled */ uint32_t reserved: 1; @@ -811,6 +811,8 @@ usbh_hal_chan_t *usbh_hal_get_chan_pending_intr(usbh_hal_context_t *hal); * - Returns the corresponding event for that channel * * @param chan_obj Channel object + * @note If the host port has an error (e.g., a sudden disconnect or an port error), any active channels will not + * receive an interrupt. Each active channel must be manually halted. * @return usbh_hal_chan_event_t Channel event */ usbh_hal_chan_event_t usbh_hal_chan_decode_intr(usbh_hal_chan_t *chan_obj); diff --git a/components/hal/usbh_hal.c b/components/hal/usbh_hal.c index c85438c61b..5091952de8 100644 --- a/components/hal/usbh_hal.c +++ b/components/hal/usbh_hal.c @@ -291,27 +291,19 @@ void usbh_hal_chan_activate(usbh_hal_chan_t *chan_obj, void *xfer_desc_list, int bool usbh_hal_chan_request_halt(usbh_hal_chan_t *chan_obj) { //Cannot request halt on a channel that is pending error handling - HAL_ASSERT(!chan_obj->flags.error_pending); - if (usbh_ll_chan_is_active(chan_obj->regs) || chan_obj->flags.active) { + HAL_ASSERT(chan_obj->flags.active && !chan_obj->flags.error_pending); + if (usbh_ll_chan_is_active(chan_obj->regs)) { usbh_ll_chan_halt(chan_obj->regs); chan_obj->flags.halt_requested = 1; return false; + } else { + chan_obj->flags.active = 0; + return true; } - return true; } // ------------------------------------------------- Event Handling ---------------------------------------------------- -//When a device on the port is no longer valid (e.g., disconnect, port error). All channels are no longer valid -static void chan_all_halt(usbh_hal_context_t *hal) -{ - for (int i = 0; i < USBH_HAL_NUM_CHAN; i++) { - if (hal->channels.hdls[i] != NULL) { - hal->channels.hdls[i]->flags.active = 0; - } - } -} - usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) { uint32_t intrs_core = usb_ll_intr_read_and_clear(hal->dev); //Read and clear core interrupts @@ -321,7 +313,7 @@ usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) intrs_port = usbh_ll_hprt_intr_read_and_clear(hal->dev); } //Note: Do not change order of checks. Regressing events (e.g. enable -> disabled, connected -> connected) - //always take precendance. ENABLED < DISABLED < CONN < DISCONN < OVRCUR + //always take precedence. ENABLED < DISABLED < CONN < DISCONN < OVRCUR usbh_hal_port_event_t event = USBH_HAL_PORT_EVENT_NONE; //Check if this is a core or port event @@ -330,13 +322,11 @@ usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) if (intrs_core & USB_LL_INTR_CORE_DISCONNINT) { event = USBH_HAL_PORT_EVENT_DISCONN; debounce_lock_enable(hal); - chan_all_halt(hal); //All channels are halted on a disconnect //Mask the port connection and disconnection interrupts to prevent repeated triggering } else if (intrs_port & USBH_LL_INTR_HPRT_PRTOVRCURRCHNG) { //Check if this is an overcurrent or an overcurrent cleared if (usbh_ll_hprt_get_port_overcur(hal->dev)) { event = USBH_HAL_PORT_EVENT_OVRCUR; - chan_all_halt(hal); //All channels are halted on an overcurrent } else { event = USBH_HAL_PORT_EVENT_OVRCUR_CLR; } @@ -345,14 +335,13 @@ usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) event = USBH_HAL_PORT_EVENT_ENABLED; } else { //Host port has been disabled event = USBH_HAL_PORT_EVENT_DISABLED; - chan_all_halt(hal); //All channels are halted when the port is disabled } } else if (intrs_port & USBH_LL_INTR_HPRT_PRTCONNDET && !hal->flags.dbnc_lock_enabled) { event = USBH_HAL_PORT_EVENT_CONN; debounce_lock_enable(hal); } } - //Port events always take precendance over channel events + //Port events always take precedence over channel events if (event == USBH_HAL_PORT_EVENT_NONE && (intrs_core & USB_LL_INTR_CORE_HCHINT)) { //One or more channels have pending interrupts. Store the mask of those channels hal->channels.chan_pend_intrs_msk = usbh_ll_get_chan_intrs_msk(hal->dev); diff --git a/components/usb/CMakeLists.txt b/components/usb/CMakeLists.txt index 20d143ea6e..50c5deb399 100644 --- a/components/usb/CMakeLists.txt +++ b/components/usb/CMakeLists.txt @@ -4,7 +4,13 @@ set(priv_include) set(priv_require) if(CONFIG_USB_OTG_SUPPORTED) - list(APPEND srcs "hcd.c") + list(APPEND srcs "hcd.c" + "hub.c" + "usb_host_misc.c" + "usb_host.c" + "usb_private.c" + "usbh.c") + list(APPEND include "include") list(APPEND priv_include "private_include") list(APPEND priv_require "hal" "driver") endif() diff --git a/components/usb/Kconfig b/components/usb/Kconfig index 2be5c9da6b..939a2b1d14 100644 --- a/components/usb/Kconfig +++ b/components/usb/Kconfig @@ -6,4 +6,51 @@ menu "USB-OTG" bool default y if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 -endmenu + config USB_HOST_CONTROL_TRANSFER_MAX_SIZE + depends on USB_OTG_SUPPORTED + int "Largest size (in bytes) of transfers to/from default endpoints" + default 256 + help + Each USB device attached is allocated a dedicated buffer for its OUT/IN transfers to/from the device's + control endpoint. The maximum size of that buffer is determined by this option. The limited size of the + transfer buffer have the following implications: + - The maximum length of control transfers is limited + - Device's with configuration descriptors larger than this limit cannot be supported + + choice USB_HOST_HW_BUFFER_BIAS + depends on USB_OTG_SUPPORTED + prompt "Hardware FIFO size biasing" + default USB_HOST_HW_BUFFER_BIAS_BALANCED + help + The underlying hardware has size adjustable FIFOs to cache USB packets on reception (IN) or for + transmission (OUT). The size of these FIFOs will affect the largest MPS (maximum packet size) and the + maximum number of packets that can be cached at any one time. The hardware contains the following + FIFOS: RX (for all IN packets), Non-periodic TX (for Bulk and Control OUT packets), and Periodic TX + (for Interrupt and Isochronous OUT packets). This configuration option allows biasing the FIFO sizes + towards a particular use case, which may be necessary for devices that have endpoints with large MPS. + The MPS limits for each biasing are listed below: + + Balanced: + - IN (all transfer types), 408 bytes + - OUT non-periodic (Bulk/Control), 192 bytes (i.e., 3 x 64 byte packets) + - OUT periodic (Interrupt/Isochronous), 192 bytes + + Bias IN: + - IN (all transfer types), 600 bytes + - OUT non-periodic (Bulk/Control), 64 bytes (i.e., 1 x 64 byte packets) + - OUT periodic (Interrupt/Isochronous), 128 bytes + + Bias Periodic OUT: + - IN (all transfer types), 128 bytes + - OUT non-periodic (Bulk/Control), 64 bytes (i.e., 1 x 64 byte packets) + - OUT periodic (Interrupt/Isochronous), 600 bytes + + config USB_HOST_HW_BUFFER_BIAS_BALANCED + bool "Balanced" + config USB_HOST_HW_BUFFER_BIAS_IN + bool "Bias IN" + config USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT + bool "Periodic OUT" + endchoice + +endmenu #USB-OTG diff --git a/components/usb/hcd.c b/components/usb/hcd.c index 5e94b5921b..87be3a350a 100644 --- a/components/usb/hcd.c +++ b/components/usb/hcd.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -30,7 +22,9 @@ #include "driver/periph_ctrl.h" #include "hcd.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" + +#include "esp_rom_sys.h" // ----------------------------------------------------- Macros -------------------------------------------------------- @@ -219,13 +213,11 @@ typedef struct { } flags; union { struct { - uint32_t stop_idx: 8; //The descriptor index when the channel was halted uint32_t executing: 1; //The buffer is currently executing - uint32_t error_occurred: 1; //An error occurred - uint32_t cancelled: 1; //The buffer was actively cancelled - uint32_t reserved5: 5; - hcd_pipe_state_t pipe_state: 8; //The pipe's state when the error occurred - hcd_pipe_event_t pipe_event: 8; //The pipe event when the error occurred + uint32_t reserved7: 7; + uint32_t stop_idx: 8; //The descriptor index when the channel was halted + hcd_pipe_event_t pipe_event: 8; //The pipe event when the buffer was done + uint32_t reserved8: 8; }; uint32_t val; } status_flags; //Status flags for the buffer @@ -236,8 +228,8 @@ typedef struct { */ struct pipe_obj { //URB queueing related - TAILQ_HEAD(tailhead_urb_pending, urb_obj) pending_urb_tailq; - TAILQ_HEAD(tailhead_urb_done, urb_obj) done_urb_tailq; + TAILQ_HEAD(tailhead_urb_pending, urb_s) pending_urb_tailq; + TAILQ_HEAD(tailhead_urb_done, urb_s) done_urb_tailq; int num_urb_pending; int num_urb_done; //Multi-buffer control @@ -268,13 +260,12 @@ struct pipe_obj { TaskHandle_t task_waiting_pipe_notif; //Task handle used for internal pipe events union { struct { - uint32_t waiting_xfer_done: 1; - uint32_t paused: 1; + uint32_t waiting_halt: 1; uint32_t pipe_cmd_processing: 1; - uint32_t is_active: 1; + uint32_t has_urb: 1; //Indicates there is at least one URB either pending, inflight, or done uint32_t persist: 1; //indicates that this pipe should persist through a run-time port reset uint32_t reset_lock: 1; //Indicates that this pipe is undergoing a run-time reset - uint32_t reserved26: 26; + uint32_t reserved27: 27; }; uint32_t val; } cs_flags; @@ -305,17 +296,17 @@ struct port_obj { uint32_t event_pending: 1; //The port has an event that needs to be handled uint32_t event_processing: 1; //The port is current processing (handling) an event uint32_t cmd_processing: 1; //Used to indicate command handling is ongoing - uint32_t waiting_all_pipes_pause: 1; //Waiting for all pipes routed through this port to be paused uint32_t disable_requested: 1; uint32_t conn_dev_ena: 1; //Used to indicate the port is connected to a device that has been reset uint32_t periodic_scheduling_enabled: 1; - uint32_t reserved9:9; - uint32_t num_pipes_waiting_pause: 16; + uint32_t reserved26: 26; }; uint32_t val; } flags; bool initialized; - hcd_port_fifo_bias_t fifo_bias; + //FIFO biasing related + const usbh_hal_fifo_config_t *fifo_config; + const fifo_mps_limits_t *fifo_mps_limits; //Port callback and context hcd_port_callback_t callback; void *callback_arg; @@ -400,13 +391,30 @@ static void _buffer_exec(pipe_t *pipe); * @brief Check if a buffer as completed execution * * This should only be called after receiving a USBH_HAL_CHAN_EVENT_CPLT event to check if a buffer is actually - * done. Buffers that aren't complete (such as Control transfers) will be continued automatically. + * done. * * @param pipe Pipe object * @return true Buffer complete * @return false Buffer not complete */ -static bool _buffer_check_done(pipe_t *pipe); +static inline bool _buffer_check_done(pipe_t *pipe) +{ + if (pipe->ep_char.type != USB_PRIV_XFER_TYPE_CTRL) { + return true; + } + //Only control transfers need to be continued + dma_buffer_block_t *buffer_inflight = pipe->buffers[pipe->multi_buffer_control.rd_idx]; + return (buffer_inflight->flags.ctrl.cur_stg == 2); +} + +/** + * @brief Continue execution of a buffer + * + * This should only be called after checking if a buffer has completed execution using _buffer_check_done() + * + * @param pipe Pipe object + */ +static void _buffer_exec_cont(pipe_t *pipe); /** * @brief Marks the last executed buffer as complete @@ -415,40 +423,14 @@ static bool _buffer_check_done(pipe_t *pipe); * * @param pipe Pipe object * @param stop_idx Descriptor index when the buffer stopped execution + * @param pipe_event Pipe event that caused the buffer to be complete */ -static inline void _buffer_done(pipe_t *pipe, int stop_idx) +static inline void _buffer_done(pipe_t *pipe, int stop_idx, hcd_pipe_event_t pipe_event) { - //Store the stop_idx for later parsing + //Store the stop_idx and pipe_event for later parsing dma_buffer_block_t *buffer_done = pipe->buffers[pipe->multi_buffer_control.rd_idx]; buffer_done->status_flags.executing = 0; - buffer_done->status_flags.error_occurred = 0; buffer_done->status_flags.stop_idx = stop_idx; - pipe->multi_buffer_control.rd_idx++; - pipe->multi_buffer_control.buffer_num_to_exec--; - pipe->multi_buffer_control.buffer_num_to_parse++; - pipe->multi_buffer_control.buffer_is_executing = 0; -} - -/** - * @brief Marks the last executed buffer as complete due to an error - * - * This should be called on a pipe that has received a USBH_HAL_CHAN_EVENT_ERROR event - * - * @param pipe Pipe object - * @param stop_idx Descriptor index when the buffer stopped execution - * @param pipe_state State of the pipe after the error - * @param pipe_event Error event - * @param cancelled Whether the pipe stopped due to cancellation - */ -static inline void _buffer_done_error(pipe_t *pipe, int stop_idx, hcd_pipe_state_t pipe_state, hcd_pipe_event_t pipe_event, bool cancelled) -{ - //Mark the buffer as erroneous for later parsing - dma_buffer_block_t *buffer_done = pipe->buffers[pipe->multi_buffer_control.rd_idx]; - buffer_done->status_flags.executing = 0; - buffer_done->status_flags.error_occurred = 1; - buffer_done->status_flags.cancelled = cancelled; - buffer_done->status_flags.stop_idx = stop_idx; - buffer_done->status_flags.pipe_state = pipe_state; buffer_done->status_flags.pipe_event = pipe_event; pipe->multi_buffer_control.rd_idx++; pipe->multi_buffer_control.buffer_num_to_exec--; @@ -493,50 +475,13 @@ static void _buffer_parse(pipe_t *pipe); * * @param pipe Pipe object * @param cancelled Whether this flush is due to cancellation + * @return true One or more buffers were flushed + * @return false There were no buffers that needed to be flushed */ -static void _buffer_flush_all(pipe_t *pipe, bool cancelled); +static bool _buffer_flush_all(pipe_t *pipe, bool cancelled); // ------------------------ Pipe --------------------------- -/** - * @brief Wait until a pipe's in-flight URB is done - * - * If the pipe has an in-flight URB, this function will block until it is done (via a internal pipe event). - * If the pipe has no in-flight URB, this function do nothing and return immediately. - * If the pipe's state changes unexpectedly, this function will return false. - * - * Also parses all buffers on exit - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param pipe Pipe object - * @return true Pipes in-flight URB is done - * @return false Pipes state unexpectedly changed - */ -static bool _pipe_wait_done(pipe_t *pipe); - -/** - * @brief Retires all URBs (those that were previously in-flight or pending) - * - * Retiring all URBs will result in any pending URB being moved to the done tailq. This function will update the IPR - * status of each URB. - * - If the retiring is self-initiated (i.e., due to a pipe command), the URB status will be set to USB_TRANSFER_STATUS_CANCELED. - * - If the retiring is NOT self-initiated (i.e., the pipe is no longer valid), the URB status will be set to USB_TRANSFER_STATUS_NO_DEVICE - * - * Entry: - * - There can be no in-flight URB (must already be parsed and returned to done queue) - * - All buffers must be parsed - * Exit: - * - If there was an in-flight URB, it is parsed and returned to the done queue - * - If there are any pending URBs: - * - They are moved to the done tailq - * - * @param pipe Pipe object - * @param cancelled Are we actively Pipe retire is initialized by the user due to a command, thus URB are - * actively cancelled. - */ -static void _pipe_retire(pipe_t *pipe, bool self_initiated); - /** * @brief Decode a HAL channel error to the corresponding pipe event * @@ -545,59 +490,47 @@ static void _pipe_retire(pipe_t *pipe, bool self_initiated); */ static inline hcd_pipe_event_t pipe_decode_error_event(usbh_hal_chan_error_t chan_error); +/** + * @brief Halt a pipe + * + * - Attempts to halt a pipe. Pipe must be active in order to be halted + * - If the underlying channel has an ongoing transfer, a halt will be requested, then the function will block until the + * channel indicates it is halted + * - If the channel is no on-going transfer, the pipe will simply be marked has halted (thus preventing any further URBs + * from being enqueued) + * + * @note This function can block + * @param pipe Pipe object + * @return esp_err_t + */ +static esp_err_t _pipe_cmd_halt(pipe_t *pipe); + +/** + * @brief Flush a pipe + * + * - Flushing a pipe causes all of its pending URBs to be become done, thus allowing them to be dequeued + * - The pipe must be halted in order to be flushed + * - The pipe callback will be run if one or more URBs become done + * + * @param pipe Pipe object + * @return esp_err_t + */ +static esp_err_t _pipe_cmd_flush(pipe_t *pipe); + +/** + * @brief Clear a pipe from its halt + * + * - Pipe must be halted in order to be cleared + * - Clearing a pipe makes it active again + * - If there are any enqueued URBs, they will executed + * + * @param pipe Pipe object + * @return esp_err_t + */ +static esp_err_t _pipe_cmd_clear(pipe_t *pipe); + // ------------------------ Port --------------------------- -/** - * @brief Invalidates all the pipes routed through a port - * - * This should be called when port or its connected device is no longer valid (e.g., the port is suddenly reset/disabled - * or the device suddenly disconnects) - * - * @note This function may run one or more callbacks, and will exit and enter the critical section to do so - * - * Entry: - * - The port or its connected device is no longer valid. This guarantees that none of the pipes will be transferring - * Exit: - * - Each pipe will have any pending URBs moved to their respective done tailq - * - Each pipe will be put into the invalid state - * - Generate a HCD_PIPE_EVENT_INVALID event on each pipe and run their respective callbacks - * - * @param port Port object - */ -static void _port_invalidate_all_pipes(port_t *port); - -/** - * @brief Pause all pipes routed through a port - * - * Call this before attempting to reset or suspend a port - * - * Entry: - * - The port is in the HCD_PORT_STATE_ENABLED state (i.e., there is a connected device which has been reset) - * Exit: - * - All pipes routed through the port have either paused, or are waiting to complete their in-flight URBs before pausing - * - If waiting for one or more pipes to pause, _internal_port_event_wait() must be called after this function returns - * - * @param port Port object - * @return true All pipes have been paused - * @return false Need to wait for one or more pipes to pause. Call _internal_port_event_wait() afterwards - */ -static bool _port_pause_all_pipes(port_t *port); - -/** - * @brief Un-pause all pipes routed through a port - * - * Call this before after coming out of a port reset or resume. - * - * Entry: - * - The port is in the HCD_PORT_STATE_ENABLED state - * - All pipes are paused - * Exit: - * - All pipes un-paused. If those pipes have pending URBs, they will be started. - * - * @param port Port object - */ -static void _port_unpause_all_pipes(port_t *port); - /** * @brief Prepare persistent pipes for reset * @@ -621,72 +554,13 @@ static bool _port_persist_all_pipes(port_t *port); static void _port_recover_all_pipes(port_t *port); /** - * @brief Send a reset condition on a port's bus - * - * Entry: - * - The port must be in the HCD_PORT_STATE_ENABLED or HCD_PORT_STATE_DISABLED state - * Exit: - * - Reset condition sent on the port's bus - * - * @note This function is blocking (will exit and re-enter the critical section to do so) + * @brief Checks if all pipes are in the halted state * * @param port Port object - * @return true Reset condition successfully sent - * @return false Failed to send reset condition due to unexpected port state + * @return true All pipes are halted + * @return false Not all pipes are halted */ -static bool _port_bus_reset(port_t *port); - -/** - * @brief Send a suspend condition on a port's bus - * - * This function will first pause pipes routed through a port, and then send a suspend condition. - * - * Entry: - * - The port must be in the HCD_PORT_STATE_ENABLED state - * Exit: - * - All pipes paused and the port is put into the suspended state - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param port Port object - * @return true Suspend condition successfully sent. Port is now in the HCD_PORT_STATE_SUSPENDED state - * @return false Failed to send a suspend condition due to unexpected port state - */ -static bool _port_bus_suspend(port_t *port); - -/** - * @brief Send a resume condition on a port's bus - * - * This function will send a resume condition, and then un-pause all the pipes routed through a port - * - * Entry: - * - The port must be in the HCD_PORT_STATE_SUSPENDED state - * Exit: - * - The port is put into the enabled state and all pipes un-paused - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param port Port object - * @return true Resume condition successfully sent. Port is now in the HCD_PORT_STATE_ENABLED state - * @return false Failed to send a resume condition due to unexpected port state. - */ -static bool _port_bus_resume(port_t *port); - -/** - * @brief Disable a port - * - * Entry: - * - The port must be in the HCD_PORT_STATE_ENABLED or HCD_PORT_STATE_SUSPENDED state - * Exit: - * - All pipes paused (should already be paused if port was suspended), and the port is put into the disabled state. - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param port Port object - * @return true Port successfully disabled - * @return false Port to disable port due to unexpected port state - */ -static bool _port_disable(port_t *port); +static bool _port_check_all_pipes_halted(port_t *port); /** * @brief Debounce port after a connection or disconnection event @@ -694,12 +568,77 @@ static bool _port_disable(port_t *port); * This function should be called after a port connection or disconnect event. This function will execute a debounce * delay then check the actual connection/disconnections state. * + * @note This function can block * @param port Port object * @return true A device is connected * @return false No device connected */ static bool _port_debounce(port_t *port); +/** + * @brief Power ON the port + * + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_power_on(port_t *port); + +/** + * @brief Power OFF the port + * + * - If a device is currently connected, this function will cause a disconnect event + * + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_power_off(port_t *port); + +/** + * @brief Reset the port + * + * - This function issues a reset signal using the timings specified by the USB2.0 spec + * + * @note This function can block + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_reset(port_t *port); + +/** + * @brief Suspend the port + * + * - Port must be enabled in order to to be suspended + * - All pipes must be halted for the port to be suspended + * - Suspending the port stops Keep Alive/SOF from being sent to the connected device + * + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_bus_suspend(port_t *port); + +/** + * @brief Resume the port + * + * - Port must be suspended in order to be resumed + * + * @note This function can block + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_bus_resume(port_t *port); + +/** + * @brief Disable the port + * + * - All pipes must be halted for the port to be disabled + * - The port must be enabled or suspended in order to be disabled + * + * @note This function can block + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_disable(port_t *port); + // ----------------------- Events -------------------------- /** @@ -822,14 +761,8 @@ static hcd_port_event_t _intr_hdlr_hprt(port_t *port, usbh_hal_port_event_t hal_ break; } case USBH_HAL_PORT_EVENT_DISCONN: { - if (port->flags.conn_dev_ena) { - //The port was previously enabled, so this is a sudden disconnection - port->state = HCD_PORT_STATE_RECOVERY; - port_event = HCD_PORT_EVENT_SUDDEN_DISCONN; - } else { - //For normal disconnections, don't update state immediately as we still need to debounce. - port_event = HCD_PORT_EVENT_DISCONNECTION; - } + port->state = HCD_PORT_STATE_RECOVERY; + port_event = HCD_PORT_EVENT_DISCONNECTION; port->flags.conn_dev_ena = 0; break; } @@ -892,31 +825,27 @@ static hcd_pipe_event_t _intr_hdlr_chan(pipe_t *pipe, usbh_hal_chan_t *chan_obj, { usbh_hal_chan_event_t chan_event = usbh_hal_chan_decode_intr(chan_obj); hcd_pipe_event_t event = HCD_PIPE_EVENT_NONE; - //Check the the pipe's port still has a connected and enabled device before processing the interrupt - if (!pipe->port->flags.conn_dev_ena) { - return event; //Treat as a no event. - } - bool handle_waiting_xfer_done = false; + switch (chan_event) { case USBH_HAL_CHAN_EVENT_CPLT: { if (!_buffer_check_done(pipe)) { + _buffer_exec_cont(pipe); break; } pipe->last_event = HCD_PIPE_EVENT_URB_DONE; event = pipe->last_event; //Mark the buffer as done int stop_idx = usbh_hal_chan_get_qtd_idx(chan_obj); - _buffer_done(pipe, stop_idx); - //First check if there is another buffer we can execute - if (_buffer_can_exec(pipe) && !pipe->cs_flags.waiting_xfer_done) { + _buffer_done(pipe, stop_idx, pipe->last_event); + //First check if there is another buffer we can execute. But we only want to execute if there's still a valid device + if (_buffer_can_exec(pipe) && pipe->port->flags.conn_dev_ena) { //If the next buffer is filled and ready to execute, execute it _buffer_exec(pipe); } //Handle the previously done buffer _buffer_parse(pipe); - if (pipe->cs_flags.waiting_xfer_done) { - handle_waiting_xfer_done = true; - } else if (_buffer_can_fill(pipe)) { + //Check to see if we can fill another buffer. But we only want to fill if there is still a valid device + if (_buffer_can_fill(pipe) && pipe->port->flags.conn_dev_ena) { //Now that we've parsed a buffer, see if another URB can be filled in its place _buffer_fill(pipe); } @@ -931,39 +860,33 @@ static hcd_pipe_event_t _intr_hdlr_chan(pipe_t *pipe, usbh_hal_chan_t *chan_obj, pipe->state = HCD_PIPE_STATE_HALTED; //Mark the buffer as done with an error int stop_idx = usbh_hal_chan_get_qtd_idx(chan_obj); - _buffer_done_error(pipe, stop_idx, pipe->state, pipe->last_event, false); + _buffer_done(pipe, stop_idx, pipe->last_event); //Parse the buffer _buffer_parse(pipe); - if (pipe->cs_flags.waiting_xfer_done) { - handle_waiting_xfer_done = true; - } + break; + } + case USBH_HAL_CHAN_EVENT_HALT_REQ: { + assert(pipe->cs_flags.waiting_halt); + //We've halted a transfer, so we need to trigger the pipe callback + pipe->last_event = HCD_PIPE_EVENT_URB_DONE; + event = pipe->last_event; + //Halt request event is triggered when packet is successful completed. But just treat all halted transfers as errors + pipe->state = HCD_PIPE_STATE_HALTED; + int stop_idx = usbh_hal_chan_get_qtd_idx(chan_obj); + _buffer_done(pipe, stop_idx, HCD_PIPE_EVENT_NONE); + //Parse the buffer + _buffer_parse(pipe); + //Notify the task waiting for the pipe halt + *yield |= _internal_pipe_event_notify(pipe, true); break; } case USBH_HAL_CHAN_EVENT_NONE: { break; //Nothing to do } - case USBH_HAL_CHAN_EVENT_HALT_REQ: //We currently don't halt request so this event should never occur default: abort(); break; } - if (handle_waiting_xfer_done) { - //A port/pipe command is waiting for this pipe to complete its transfer. So don't load the next transfer - pipe->cs_flags.waiting_xfer_done = 0; - if (pipe->port->flags.waiting_all_pipes_pause) { - //Port command is waiting for all pipes to be paused - pipe->cs_flags.paused = 1; - pipe->port->flags.num_pipes_waiting_pause--; - if (pipe->port->flags.num_pipes_waiting_pause == 0) { - //All pipes have finished pausing, Notify the blocked port command - pipe->port->flags.waiting_all_pipes_pause = 0; - *yield |= _internal_port_event_notify_from_isr(pipe->port); - } - } else { - //Pipe command is waiting for transfer to complete - *yield |= _internal_pipe_event_notify(pipe, true); - } - } return event; } @@ -1138,94 +1061,7 @@ esp_err_t hcd_uninstall(void) // ------------------------------------------------------ Port --------------------------------------------------------- -// ----------------------- Private ------------------------- - -static void _port_invalidate_all_pipes(port_t *port) -{ - //This function should only be called when the port is invalid - assert(!port->flags.conn_dev_ena); - pipe_t *pipe; - //Process all pipes that have queued URBs - TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { - //Mark the pipe as invalid and set an invalid event - pipe->state = HCD_PIPE_STATE_INVALID; - pipe->last_event = HCD_PIPE_EVENT_INVALID; - //Flush all buffers that are still awaiting exec - _buffer_flush_all(pipe, false); - //Retire any remaining URBs in the pending tailq - _pipe_retire(pipe, false); - if (pipe->task_waiting_pipe_notif != NULL) { - //Unblock the thread/task waiting for a notification from the pipe as the pipe is no longer valid. - _internal_pipe_event_notify(pipe, false); - } - if (pipe->callback != NULL) { - HCD_EXIT_CRITICAL(); - (void) pipe->callback((hcd_pipe_handle_t)pipe, HCD_PIPE_EVENT_INVALID, pipe->callback_arg, false); - HCD_ENTER_CRITICAL(); - } - } - //Process all idle pipes - TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { - //Mark pipe as invalid and call its callback - pipe->state = HCD_PIPE_STATE_INVALID; - pipe->last_event = HCD_PIPE_EVENT_INVALID; - if (pipe->callback != NULL) { - HCD_EXIT_CRITICAL(); - (void) pipe->callback((hcd_pipe_handle_t)pipe, HCD_PIPE_EVENT_INVALID, pipe->callback_arg, false); - HCD_ENTER_CRITICAL(); - } - } -} - -static bool _port_pause_all_pipes(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED); - pipe_t *pipe; - int num_pipes_waiting_done = 0; - //Process all pipes that have queued URBs - TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { - //Check if pipe is currently executing - if (pipe->multi_buffer_control.buffer_is_executing) { - //Pipe is executing a buffer. Indicate to the pipe we are waiting the buffer's transfer to complete - pipe->cs_flags.waiting_xfer_done = 1; - num_pipes_waiting_done++; - } else { - //No buffer is being executed so need to wait - pipe->cs_flags.paused = 1; - } - } - //Process all idle pipes. They don't have queue transfer so just mark them as paused - TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { - pipe->cs_flags.paused = 1; - } - if (num_pipes_waiting_done > 0) { - //Indicate we need to wait for one or more pipes to complete their transfers - port->flags.num_pipes_waiting_pause = num_pipes_waiting_done; - port->flags.waiting_all_pipes_pause = 1; - return false; - } - return true; -} - -static void _port_unpause_all_pipes(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED); - pipe_t *pipe; - //Process all idle pipes. They don't have queue transfer so just mark them as un-paused - TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { - pipe->cs_flags.paused = 0; - } - //Process all pipes that have queued URBs - TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { - pipe->cs_flags.paused = 0; - if (_buffer_can_fill(pipe)) { - _buffer_fill(pipe); - } - if (_buffer_can_exec(pipe)) { - _buffer_exec(pipe); - } - } -} +// ----------------------- Helpers ------------------------- static bool _port_persist_all_pipes(port_t *port) { @@ -1264,108 +1100,23 @@ static void _port_recover_all_pipes(port_t *port) } } -static bool _port_bus_reset(port_t *port) +static bool _port_check_all_pipes_halted(port_t *port) { - assert(port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_DISABLED); - //Put and hold the bus in the reset state. If the port was previously enabled, a disabled event will occur after this - port->state = HCD_PORT_STATE_RESETTING; - usbh_hal_port_toggle_reset(port->hal, true); - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESET_HOLD_MS)); - HCD_ENTER_CRITICAL(); - if (port->state != HCD_PORT_STATE_RESETTING) { - //The port state has unexpectedly changed - goto bailout; - } - //Return the bus to the idle state and hold it for the required reset recovery time. Port enabled event should occur - usbh_hal_port_toggle_reset(port->hal, false); - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESET_RECOVERY_MS)); - HCD_ENTER_CRITICAL(); - if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { - //The port state has unexpectedly changed - goto bailout; - } - return true; -bailout: - return false; -} - -static bool _port_bus_suspend(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED); - //Pause all pipes before suspending the bus - if (!_port_pause_all_pipes(port)) { - //Need to wait for some pipes to pause. Wait for notification from ISR - _internal_port_event_wait(port); - if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; + bool all_halted = true; + pipe_t *pipe; + TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { + if (pipe->state != HCD_PIPE_STATE_HALTED) { + all_halted = false; + break; } } - //All pipes are guaranteed paused at this point. Proceed to suspend the port - usbh_hal_port_suspend(port->hal); - port->state = HCD_PORT_STATE_SUSPENDED; - return true; -bailout: - return false; -} - -static bool _port_bus_resume(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_SUSPENDED); - //Put and hold the bus in the K state. - usbh_hal_port_toggle_resume(port->hal, true); - port->state = HCD_PORT_STATE_RESUMING; - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESUME_HOLD_MS)); - HCD_ENTER_CRITICAL(); - //Return and hold the bus to the J state (as port of the LS EOP) - usbh_hal_port_toggle_resume(port->hal, false); - if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; - } - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESUME_RECOVERY_MS)); - HCD_ENTER_CRITICAL(); - if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; - } - port->state = HCD_PORT_STATE_ENABLED; - _port_unpause_all_pipes(port); - return true; -bailout: - return false; -} - -static bool _port_disable(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_SUSPENDED); - if (port->state == HCD_PORT_STATE_ENABLED) { - //There may be pipes that are still transferring, so pause them. - if (!_port_pause_all_pipes(port)) { - //Need to wait for some pipes to pause. Wait for notification from ISR - _internal_port_event_wait(port); - if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; - } + TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { + if (pipe->state != HCD_PIPE_STATE_HALTED) { + all_halted = false; + break; } } - //All pipes are guaranteed paused at this point. Proceed to suspend the port. This should trigger an internal event - port->flags.disable_requested = 1; - usbh_hal_port_disable(port->hal); - _internal_port_event_wait(port); - if (port->state != HCD_PORT_STATE_DISABLED) { - //Port state unexpectedly changed - goto bailout; - } - _port_invalidate_all_pipes(port); - return true; -bailout: - return false; + return all_halted; } static bool _port_debounce(port_t *port) @@ -1389,6 +1140,166 @@ static bool _port_debounce(port_t *port) return is_connected; } +// ---------------------- Commands ------------------------- + +static esp_err_t _port_cmd_power_on(port_t *port) +{ + esp_err_t ret; + //Port can only be powered on if it's currently unpowered + if (port->state == HCD_PORT_STATE_NOT_POWERED) { + port->state = HCD_PORT_STATE_DISCONNECTED; + usbh_hal_port_init(port->hal); + usbh_hal_port_toggle_power(port->hal, true); + ret = ESP_OK; + } else { + ret = ESP_ERR_INVALID_STATE; + } + return ret; +} + +static esp_err_t _port_cmd_power_off(port_t *port) +{ + esp_err_t ret; + //Port can only be unpowered if already powered + if (port->state != HCD_PORT_STATE_NOT_POWERED) { + port->state = HCD_PORT_STATE_NOT_POWERED; + usbh_hal_port_deinit(port->hal); + usbh_hal_port_toggle_power(port->hal, false); + //If a device is currently connected, this should trigger a disconnect event + ret = ESP_OK; + } else { + ret = ESP_ERR_INVALID_STATE; + } + return ret; +} + +static esp_err_t _port_cmd_reset(port_t *port) +{ + esp_err_t ret; + //Port can only a reset when it is in the enabled or disabled states (in case of new connection) + if (port->state != HCD_PORT_STATE_ENABLED && port->state != HCD_PORT_STATE_DISABLED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + bool is_runtime_reset = (port->state == HCD_PORT_STATE_ENABLED) ? true : false; + if (is_runtime_reset && !_port_persist_all_pipes(port)) { + //If this is a run time reset, check all pipes that are still allocated can persist the reset + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes (if any_) are guaranteed to be persistent at this point. Proceed to resetting the bus + port->state = HCD_PORT_STATE_RESETTING; + //Put and hold the bus in the reset state. If the port was previously enabled, a disabled event will occur after this + usbh_hal_port_toggle_reset(port->hal, true); + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESET_HOLD_MS)); + HCD_ENTER_CRITICAL(); + if (port->state != HCD_PORT_STATE_RESETTING) { + //The port state has unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto bailout; + } + //Return the bus to the idle state and hold it for the required reset recovery time. Port enabled event should occur + usbh_hal_port_toggle_reset(port->hal, false); + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESET_RECOVERY_MS)); + HCD_ENTER_CRITICAL(); + if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { + //The port state has unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto bailout; + } + //Set FIFO sizes based on the selected biasing + usbh_hal_set_fifo_size(port->hal, port->fifo_config); + //We start periodic scheduling only after a RESET command since SOFs only start after a reset + usbh_hal_port_set_frame_list(port->hal, port->frame_list, FRAME_LIST_LEN); + usbh_hal_port_periodic_enable(port->hal); + ret = ESP_OK; +bailout: + if (is_runtime_reset) { + _port_recover_all_pipes(port); + } +exit: + return ret; +} + +static esp_err_t _port_cmd_bus_suspend(port_t *port) +{ + esp_err_t ret; + //Port must have been previously enabled, and all pipes must already be halted + if (port->state == HCD_PORT_STATE_ENABLED && !_port_check_all_pipes_halted(port)) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes are guaranteed halted at this point. Proceed to suspend the port + usbh_hal_port_suspend(port->hal); + port->state = HCD_PORT_STATE_SUSPENDED; + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _port_cmd_bus_resume(port_t *port) +{ + esp_err_t ret; + //Port can only be resumed if it was previously suspended + if (port->state != HCD_PORT_STATE_SUSPENDED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Put and hold the bus in the K state. + usbh_hal_port_toggle_resume(port->hal, true); + port->state = HCD_PORT_STATE_RESUMING; + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESUME_HOLD_MS)); + HCD_ENTER_CRITICAL(); + //Return and hold the bus to the J state (as port of the LS EOP) + usbh_hal_port_toggle_resume(port->hal, false); + if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { + //Port state unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto exit; + } + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESUME_RECOVERY_MS)); + HCD_ENTER_CRITICAL(); + if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { + //Port state unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto exit; + } + port->state = HCD_PORT_STATE_ENABLED; + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _port_cmd_disable(port_t *port) +{ + esp_err_t ret; + if (port->state != HCD_PORT_STATE_ENABLED && port->state != HCD_PORT_STATE_SUSPENDED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes must be halted before disabling the port + if (!_port_check_all_pipes_halted(port)){ + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes are guaranteed to be halted or freed at this point. Proceed to disable the port + port->flags.disable_requested = 1; + usbh_hal_port_disable(port->hal); + _internal_port_event_wait(port); + if (port->state != HCD_PORT_STATE_DISABLED) { + //Port state unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto exit; + } + ret = ESP_OK; +exit: + return ret; +} + // ----------------------- Public -------------------------- esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, hcd_port_handle_t *port_hdl) @@ -1396,6 +1307,29 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h HCD_CHECK(port_number > 0 && port_config != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG); HCD_CHECK(port_number <= NUM_PORTS, ESP_ERR_NOT_FOUND); + //Get a pointer to the correct FIFO bias constant values + const usbh_hal_fifo_config_t *fifo_config; + const fifo_mps_limits_t *mps_limits; + switch (port_config->fifo_bias) { + case HCD_PORT_FIFO_BIAS_BALANCED: + fifo_config = &fifo_config_default; + mps_limits = &mps_limits_default; + break; + case HCD_PORT_FIFO_BIAS_RX: + fifo_config = &fifo_config_bias_rx; + mps_limits = &mps_limits_bias_rx; + break; + case HCD_PORT_FIFO_BIAS_PTX: + fifo_config = &fifo_config_bias_ptx; + mps_limits = &mps_limits_bias_ptx; + break; + default: + fifo_config = NULL; + mps_limits = NULL; + abort(); + break; + } + HCD_ENTER_CRITICAL(); HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && !s_hcd_obj->port_obj->initialized, ESP_ERR_INVALID_STATE); //Port object memory and resources (such as the mutex) already be allocated. Just need to initialize necessary fields only @@ -1404,6 +1338,8 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h TAILQ_INIT(&port_obj->pipes_active_tailq); port_obj->state = HCD_PORT_STATE_NOT_POWERED; port_obj->last_event = HCD_PORT_EVENT_NONE; + port_obj->fifo_config = fifo_config; + port_obj->fifo_mps_limits = mps_limits; port_obj->callback = port_config->callback; port_obj->callback_arg = port_config->callback_arg; port_obj->context = port_config->context; @@ -1427,7 +1363,7 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl) HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && port->initialized && port->num_pipes_idle == 0 && port->num_pipes_queued == 0 && (port->state == HCD_PORT_STATE_NOT_POWERED || port->state == HCD_PORT_STATE_RECOVERY) - && port->flags.val == 0 && port->task_waiting_port_notif == NULL, + && port->task_waiting_port_notif == NULL, ESP_ERR_INVALID_STATE); port->initialized = false; esp_intr_disable(s_hcd_obj->isr_hdl); @@ -1447,74 +1383,27 @@ esp_err_t hcd_port_command(hcd_port_handle_t port_hdl, hcd_port_cmd_t command) port->flags.cmd_processing = 1; switch (command) { case HCD_PORT_CMD_POWER_ON: { - //Port can only be powered on if currently unpowered - if (port->state == HCD_PORT_STATE_NOT_POWERED) { - port->state = HCD_PORT_STATE_DISCONNECTED; - usbh_hal_port_init(port->hal); - usbh_hal_port_toggle_power(port->hal, true); - ret = ESP_OK; - } + ret = _port_cmd_power_on(port); break; } case HCD_PORT_CMD_POWER_OFF: { - //Port can only be unpowered if already powered - if (port->state != HCD_PORT_STATE_NOT_POWERED) { - port->state = HCD_PORT_STATE_NOT_POWERED; - usbh_hal_port_deinit(port->hal); - usbh_hal_port_toggle_power(port->hal, false); - //If a device is currently connected, this should trigger a disconnect event - ret = ESP_OK; - } + ret = _port_cmd_power_off(port); break; } case HCD_PORT_CMD_RESET: { - //Port can only a reset when it is in the enabled or disabled states (in case of new connection) - if (port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_DISABLED) { - bool is_runtime_reset = (port->state == HCD_PORT_STATE_ENABLED) ? true : false; - if (is_runtime_reset) { - //Check all pipes that are still allocated are persistent before we execute the reset - if (!_port_persist_all_pipes(port)) { - ret = ESP_ERR_INVALID_STATE; - break; - } - } - if (_port_bus_reset(port)) { - //Set FIFO sizes to default - usbh_hal_set_fifo_size(port->hal, &fifo_config_default); - port->fifo_bias = HCD_PORT_FIFO_BIAS_BALANCED; - //We start periodic scheduling only after a RESET command since SOFs only start after a reset - usbh_hal_port_set_frame_list(port->hal, port->frame_list, FRAME_LIST_LEN); - usbh_hal_port_periodic_enable(port->hal); - ret = ESP_OK; - } else { - ret = ESP_ERR_INVALID_RESPONSE; - } - if (is_runtime_reset) { - _port_recover_all_pipes(port); - } - - } + ret = _port_cmd_reset(port); break; } case HCD_PORT_CMD_SUSPEND: { - //Port can only be suspended if already in the enabled state - if (port->state == HCD_PORT_STATE_ENABLED) { - ret = (_port_bus_suspend(port)) ? ESP_OK : ESP_ERR_INVALID_RESPONSE; - } + ret = _port_cmd_bus_suspend(port); break; } case HCD_PORT_CMD_RESUME: { - //Port can only be resumed if already suspended - if (port->state == HCD_PORT_STATE_SUSPENDED) { - ret = (_port_bus_resume(port)) ? ESP_OK : ESP_ERR_INVALID_RESPONSE; - } + ret = _port_cmd_bus_resume(port); break; } case HCD_PORT_CMD_DISABLE: { - //Can only disable the port when already enabled or suspended - if (port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_SUSPENDED) { - ret = (_port_disable(port)) ? ESP_OK : ESP_ERR_INVALID_RESPONSE; - } + ret = _port_cmd_disable(port); break; } } @@ -1570,22 +1459,8 @@ hcd_port_event_t hcd_port_handle_event(hcd_port_handle_t port_hdl) break; } case HCD_PORT_EVENT_DISCONNECTION: - if (_port_debounce(port)) { - //A device is still connected, so it was just a debounce - port->state = HCD_PORT_STATE_DISABLED; - ret = HCD_PORT_EVENT_NONE; - } else { - //No device connected after debounce delay. This is an actual disconnection - if (port->state != HCD_PORT_STATE_NOT_POWERED) { //Don't update state if disconnect was due to power-off - port->state = HCD_PORT_STATE_DISCONNECTED; - } - ret = HCD_PORT_EVENT_DISCONNECTION; - } - break; case HCD_PORT_EVENT_ERROR: - case HCD_PORT_EVENT_OVERCURRENT: - case HCD_PORT_EVENT_SUDDEN_DISCONN: { - _port_invalidate_all_pipes(port); + case HCD_PORT_EVENT_OVERCURRENT: { break; } default: { @@ -1637,28 +1512,37 @@ void *hcd_port_get_context(hcd_port_handle_t port_hdl) esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_t bias) { esp_err_t ret; + //Get a pointer to the correct FIFO bias constant values + const usbh_hal_fifo_config_t *fifo_config; + const fifo_mps_limits_t *mps_limits; + switch (bias) { + case HCD_PORT_FIFO_BIAS_BALANCED: + fifo_config = &fifo_config_default; + mps_limits = &mps_limits_default; + break; + case HCD_PORT_FIFO_BIAS_RX: + fifo_config = &fifo_config_bias_rx; + mps_limits = &mps_limits_bias_rx; + break; + case HCD_PORT_FIFO_BIAS_PTX: + fifo_config = &fifo_config_bias_ptx; + mps_limits = &mps_limits_bias_ptx; + break; + default: + fifo_config = NULL; + mps_limits = NULL; + abort(); + break; + } + //Configure the new FIFO sizes and store the pointers port_t *port = (port_t *)port_hdl; xSemaphoreTake(port->port_mux, portMAX_DELAY); HCD_ENTER_CRITICAL(); //Check that port is in the correct state to update FIFO sizes if (port->initialized && !port->flags.event_pending && port->num_pipes_idle == 0 && port->num_pipes_queued == 0) { - const usbh_hal_fifo_config_t *fifo_config; - switch (bias) { - case HCD_PORT_FIFO_BIAS_BALANCED: - fifo_config = &fifo_config_default; - break; - case HCD_PORT_FIFO_BIAS_RX: - fifo_config = &fifo_config_bias_rx; - break; - case HCD_PORT_FIFO_BIAS_PTX: - fifo_config = &fifo_config_bias_ptx; - break; - default: - fifo_config = NULL; - abort(); - } usbh_hal_set_fifo_size(port->hal, fifo_config); - port->fifo_bias = bias; + port->fifo_config = fifo_config; + port->fifo_mps_limits = mps_limits; ret = ESP_OK; } else { ret = ESP_ERR_INVALID_STATE; @@ -1672,45 +1556,6 @@ esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_ // ----------------------- Private ------------------------- -static bool _pipe_wait_done(pipe_t *pipe) -{ - //Check if the pipe has a currently executing buffer - if (pipe->multi_buffer_control.buffer_is_executing) { - //Wait for pipe to complete its transfer - pipe->cs_flags.waiting_xfer_done = 1; - _internal_pipe_event_wait(pipe); - if (pipe->state == HCD_PIPE_STATE_INVALID) { - //The pipe become invalid whilst waiting for its internal event - pipe->cs_flags.waiting_xfer_done = 0; //Need to manually reset this bit in this case - return false; - } - bool chan_halted = usbh_hal_chan_request_halt(pipe->chan_obj); - assert(chan_halted); - (void) chan_halted; - } - return true; -} - -static void _pipe_retire(pipe_t *pipe, bool self_initiated) -{ - //Cannot have a currently executing buffer - assert(!pipe->multi_buffer_control.buffer_is_executing); - if (pipe->num_urb_pending > 0) { - //Process all remaining pending URBs - urb_t *urb; - TAILQ_FOREACH(urb, &pipe->pending_urb_tailq, tailq_entry) { - //Update the URB's current state - urb->hcd_var = URB_HCD_STATE_DONE; - //If we are initiating the retire, mark the URB as canceled - urb->transfer.status = (self_initiated) ? USB_TRANSFER_STATUS_CANCELED : USB_TRANSFER_STATUS_NO_DEVICE; - } - //Concatenated pending tailq to the done tailq - TAILQ_CONCAT(&pipe->done_urb_tailq, &pipe->pending_urb_tailq, tailq_entry); - pipe->num_urb_done += pipe->num_urb_pending; - pipe->num_urb_pending = 0; - } -} - static inline hcd_pipe_event_t pipe_decode_error_event(usbh_hal_chan_error_t chan_error) { hcd_pipe_event_t event = HCD_PIPE_EVENT_NONE; @@ -1768,7 +1613,7 @@ static void buffer_block_free(dma_buffer_block_t *buffer) free(buffer); } -static bool pipe_alloc_check_args(const hcd_pipe_config_t *pipe_config, usb_speed_t port_speed, hcd_port_fifo_bias_t fifo_bias, usb_transfer_type_t type, bool is_default_pipe) +static bool pipe_alloc_check_args(const hcd_pipe_config_t *pipe_config, usb_speed_t port_speed, const fifo_mps_limits_t *mps_limits, usb_transfer_type_t type, bool is_default_pipe) { //Check if pipe can be supported if (port_speed == USB_SPEED_LOW && pipe_config->dev_speed == USB_SPEED_FULL) { @@ -1790,25 +1635,12 @@ static bool pipe_alloc_check_args(const hcd_pipe_config_t *pipe_config, usb_spee //Interval not supported for isochronous pipe (where 0 < 2^(bInterval - 1) <= 32) return false; } - if (is_default_pipe) { return true; } - //Check if MPS is within FIFO limits - const fifo_mps_limits_t *mps_limits; - switch (fifo_bias) { - case HCD_PORT_FIFO_BIAS_BALANCED: - mps_limits = &mps_limits_default; - break; - case HCD_PORT_FIFO_BIAS_RX: - mps_limits = &mps_limits_bias_rx; - break; - default: //HCD_PORT_FIFO_BIAS_PTX - mps_limits = &mps_limits_bias_ptx; - break; - } + int limit; - if (USB_DESC_EP_GET_EP_DIR(pipe_config->ep_desc)) { //IN + if (USB_EP_DESC_GET_EP_DIR(pipe_config->ep_desc)) { //IN limit = mps_limits->in_mps; } else { //OUT if (type == USB_TRANSFER_TYPE_CTRL || type == USB_TRANSFER_TYPE_BULK) { @@ -1880,6 +1712,102 @@ static void pipe_set_ep_char(const hcd_pipe_config_t *pipe_config, usb_transfer_ } } +// ---------------------- Commands ------------------------- + +static esp_err_t _pipe_cmd_halt(pipe_t *pipe) +{ + esp_err_t ret; + //Pipe must be in the active state in order to be halted + if (pipe->state != HCD_PIPE_STATE_ACTIVE) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Request that the channel halts + if (!usbh_hal_chan_request_halt(pipe->chan_obj)) { + //We need to wait for channel to be halted. State will be updated in the ISR + pipe->cs_flags.waiting_halt = 1; + _internal_pipe_event_wait(pipe); + } else { + pipe->state = HCD_PIPE_STATE_HALTED; + } + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _pipe_cmd_flush(pipe_t *pipe) +{ + esp_err_t ret; + //The pipe must be halted in order to be flushed + if (pipe->state != HCD_PIPE_STATE_HALTED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Cannot have a currently executing buffer + assert(!pipe->multi_buffer_control.buffer_is_executing); + bool call_pipe_cb; + //Flush any filled buffers + call_pipe_cb = _buffer_flush_all(pipe, true); + //Move all URBs from the pending tailq to the done tailq + if (pipe->num_urb_pending > 0) { + //Process all remaining pending URBs + urb_t *urb; + TAILQ_FOREACH(urb, &pipe->pending_urb_tailq, tailq_entry) { + //Update the URB's current state + urb->hcd_var = URB_HCD_STATE_DONE; + //We are canceling the URB. Update its actual_num_bytes and status + urb->transfer.actual_num_bytes = 0; + urb->transfer.status = USB_TRANSFER_STATUS_CANCELED; + if (pipe->ep_char.type == USB_PRIV_XFER_TYPE_ISOCHRONOUS) { + //Update the URB's isoc packet descriptors as well + for (int pkt_idx = 0; pkt_idx < urb->transfer.num_isoc_packets; pkt_idx++) { + urb->transfer.isoc_packet_desc[pkt_idx].actual_num_bytes = 0; + urb->transfer.isoc_packet_desc[pkt_idx].status = USB_TRANSFER_STATUS_CANCELED; + } + } + } + //Concatenated pending tailq to the done tailq + TAILQ_CONCAT(&pipe->done_urb_tailq, &pipe->pending_urb_tailq, tailq_entry); + pipe->num_urb_done += pipe->num_urb_pending; + pipe->num_urb_pending = 0; + call_pipe_cb = true; + } + if (call_pipe_cb) { + //One or more URBs can be dequeued as a result of the flush. We need to call the callback + HCD_EXIT_CRITICAL(); + pipe->callback((hcd_pipe_handle_t)pipe, HCD_PIPE_EVENT_URB_DONE, pipe->callback_arg, false); + HCD_ENTER_CRITICAL(); + } + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _pipe_cmd_clear(pipe_t *pipe) +{ + esp_err_t ret; + //Pipe must be in the halted state in order to be made active, and there must be an enabled device on the port + if (pipe->state != HCD_PIPE_STATE_HALTED || !pipe->port->flags.conn_dev_ena) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Update the pipe's state + pipe->state = HCD_PIPE_STATE_ACTIVE; + if (pipe->num_urb_pending > 0) { + //Fill as many buffers as possible + while (_buffer_can_fill(pipe)) { + _buffer_fill(pipe); + } + } + //Execute any filled buffers + if (_buffer_can_exec(pipe)) { + _buffer_exec(pipe); + } + ret = ESP_OK; +exit: + return ret; +} + // ----------------------- Public -------------------------- esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pipe_config, hcd_pipe_handle_t *pipe_hdl) @@ -1890,7 +1818,7 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi //Can only allocate a pipe if the target port is initialized and connected to an enabled device HCD_CHECK_FROM_CRIT(port->initialized && port->flags.conn_dev_ena, ESP_ERR_INVALID_STATE); usb_speed_t port_speed = port->speed; - hcd_port_fifo_bias_t port_fifo_bias = port->fifo_bias; + const fifo_mps_limits_t *mps_limits = port->fifo_mps_limits; int pipe_idx = port->num_pipes_idle + port->num_pipes_queued; HCD_EXIT_CRITICAL(); @@ -1900,11 +1828,11 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi type = USB_TRANSFER_TYPE_CTRL; is_default = true; } else { - type = USB_DESC_EP_GET_XFERTYPE(pipe_config->ep_desc); + type = USB_EP_DESC_GET_XFERTYPE(pipe_config->ep_desc); is_default = false; } //Check if pipe configuration can be supported - if (!pipe_alloc_check_args(pipe_config, port_speed, port_fifo_bias, type, is_default)) { + if (!pipe_alloc_check_args(pipe_config, port_speed, mps_limits, type, is_default)) { return ESP_ERR_NOT_SUPPORTED; } @@ -1979,10 +1907,7 @@ esp_err_t hcd_pipe_free(hcd_pipe_handle_t pipe_hdl) HCD_ENTER_CRITICAL(); //Check that all URBs have been removed and pipe has no pending events HCD_CHECK_FROM_CRIT(!pipe->multi_buffer_control.buffer_is_executing - && pipe->multi_buffer_control.buffer_num_to_parse == 0 - && pipe->multi_buffer_control.buffer_num_to_exec == 0 - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 + && !pipe->cs_flags.has_urb && !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); //Remove pipe from the list of idle pipes (it must be in the idle list because it should have no queued URBs) @@ -2005,11 +1930,9 @@ esp_err_t hcd_pipe_update_mps(hcd_pipe_handle_t pipe_hdl, int mps) pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); //Check if pipe is in the correct state to be updated - HCD_CHECK_FROM_CRIT(pipe->state != HCD_PIPE_STATE_INVALID - && !pipe->cs_flags.pipe_cmd_processing - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 - && !pipe->cs_flags.reset_lock, + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); pipe->ep_char.mps = mps; //Update the underlying channel's registers @@ -2023,11 +1946,9 @@ esp_err_t hcd_pipe_update_dev_addr(hcd_pipe_handle_t pipe_hdl, uint8_t dev_addr) pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); //Check if pipe is in the correct state to be updated - HCD_CHECK_FROM_CRIT(pipe->state != HCD_PIPE_STATE_INVALID - && !pipe->cs_flags.pipe_cmd_processing - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 - && !pipe->cs_flags.reset_lock, + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); pipe->ep_char.dev_addr = dev_addr; //Update the underlying channel's registers @@ -2036,16 +1957,29 @@ esp_err_t hcd_pipe_update_dev_addr(hcd_pipe_handle_t pipe_hdl, uint8_t dev_addr) return ESP_OK; } -esp_err_t hcd_pipe_persist_reset(hcd_pipe_handle_t pipe_hdl) +esp_err_t hcd_pipe_update_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_callback_t callback, void *user_arg) { pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); //Check if pipe is in the correct state to be updated - HCD_CHECK_FROM_CRIT(pipe->state != HCD_PIPE_STATE_INVALID - && !pipe->cs_flags.pipe_cmd_processing - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 - && !pipe->cs_flags.reset_lock, + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, + ESP_ERR_INVALID_STATE); + pipe->callback = callback; + pipe->callback_arg = user_arg; + HCD_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t hcd_pipe_set_persist_reset(hcd_pipe_handle_t pipe_hdl) +{ + pipe_t *pipe = (pipe_t *)pipe_hdl; + HCD_ENTER_CRITICAL(); + //Check if pipe is in the correct state to be updated + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); pipe->cs_flags.persist = 1; HCD_EXIT_CRITICAL(); @@ -2067,14 +2001,7 @@ hcd_pipe_state_t hcd_pipe_get_state(hcd_pipe_handle_t pipe_hdl) hcd_pipe_state_t ret; pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); - //If there is no enabled device, all existing pipes are invalid. - if (pipe->port->state != HCD_PORT_STATE_ENABLED - && pipe->port->state != HCD_PORT_STATE_SUSPENDED - && pipe->port->state != HCD_PORT_STATE_RESUMING) { - ret = HCD_PIPE_STATE_INVALID; - } else { - ret = pipe->state; - } + ret = pipe->state; HCD_EXIT_CRITICAL(); return ret; } @@ -2084,60 +2011,31 @@ esp_err_t hcd_pipe_command(hcd_pipe_handle_t pipe_hdl, hcd_pipe_cmd_t command) pipe_t *pipe = (pipe_t *)pipe_hdl; esp_err_t ret = ESP_OK; + xSemaphoreTake(pipe->port->port_mux, portMAX_DELAY); HCD_ENTER_CRITICAL(); //Cannot execute pipe commands the pipe is already executing a command, or if the pipe or its port are no longer valid - if (pipe->cs_flags.pipe_cmd_processing || pipe->cs_flags.reset_lock || !pipe->port->flags.conn_dev_ena || pipe->state == HCD_PIPE_STATE_INVALID) { + if (pipe->cs_flags.reset_lock) { ret = ESP_ERR_INVALID_STATE; } else { pipe->cs_flags.pipe_cmd_processing = 1; switch (command) { - case HCD_PIPE_CMD_ABORT: { - //Retire all scheduled URBs. Pipe's state remains unchanged - if (!_pipe_wait_done(pipe)) { //Stop any on going transfers - ret = ESP_ERR_INVALID_RESPONSE; - } - _buffer_flush_all(pipe, true); //Some buffers might still be filled. Flush them - _pipe_retire(pipe, true); //Retire any pending transfers - break; - } - case HCD_PIPE_CMD_RESET: { - //Retire all scheduled URBs. Pipe's state moves to active - if (!_pipe_wait_done(pipe)) { //Stop any on going transfers - ret = ESP_ERR_INVALID_RESPONSE; - break; - } - _buffer_flush_all(pipe, true); //Some buffers might still be filled. Flush them - _pipe_retire(pipe, true); //Retire any pending transfers - pipe->state = HCD_PIPE_STATE_ACTIVE; - break; - } - case HCD_PIPE_CMD_CLEAR: { //Can only do this if port is still active - //Pipe's state moves from halted to active - if (pipe->state == HCD_PIPE_STATE_HALTED) { - pipe->state = HCD_PIPE_STATE_ACTIVE; - //Start the next pending transfer if it exists - if (_buffer_can_fill(pipe)) { - _buffer_fill(pipe); - } - if (_buffer_can_exec(pipe)) { - _buffer_exec(pipe); - } - } - break; - } case HCD_PIPE_CMD_HALT: { - //Pipe's state moves to halted - if (!_pipe_wait_done(pipe)) { //Stop any on going transfers - ret = ESP_ERR_INVALID_RESPONSE; - break; - } - pipe->state = HCD_PIPE_STATE_HALTED; + ret = _pipe_cmd_halt(pipe); + break; + } + case HCD_PIPE_CMD_FLUSH: { + ret = _pipe_cmd_flush(pipe); + break; + } + case HCD_PIPE_CMD_CLEAR: { + ret = _pipe_cmd_clear(pipe); break; } } pipe->cs_flags.pipe_cmd_processing = 0; } HCD_EXIT_CRITICAL(); + xSemaphoreGive(pipe->port->port_mux); return ret; } @@ -2157,11 +2055,11 @@ hcd_pipe_event_t hcd_pipe_get_event(hcd_pipe_handle_t pipe_hdl) static inline void _buffer_fill_ctrl(dma_buffer_block_t *buffer, usb_transfer_t *transfer) { //Get information about the control transfer by analyzing the setup packet (the first 8 bytes of the URB's data) - usb_ctrl_req_t *ctrl_req = (usb_ctrl_req_t *)transfer->data_buffer; - bool data_stg_in = (ctrl_req->bRequestType & USB_B_REQUEST_TYPE_DIR_IN); - bool data_stg_skip = (transfer->num_bytes == 0); + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)transfer->data_buffer; + bool data_stg_in = (setup_pkt->bmRequestType & USB_BM_REQUEST_TYPE_DIR_IN); + bool data_stg_skip = (setup_pkt->wLength == 0); //Fill setup stage - usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 0, transfer->data_buffer, sizeof(usb_ctrl_req_t), + usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 0, transfer->data_buffer, sizeof(usb_setup_packet_t), USBH_HAL_XFER_DESC_FLAG_SETUP | USBH_HAL_XFER_DESC_FLAG_HOC); //Fill data stage if (data_stg_skip) { @@ -2169,7 +2067,7 @@ static inline void _buffer_fill_ctrl(dma_buffer_block_t *buffer, usb_transfer_t usbh_hal_xfer_desc_clear(buffer->xfer_desc_list, 1); } else { //Fill data stage - usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 1, transfer->data_buffer + sizeof(usb_ctrl_req_t), transfer->num_bytes, + usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 1, transfer->data_buffer + sizeof(usb_setup_packet_t), setup_pkt->wLength, ((data_stg_in) ? USBH_HAL_XFER_DESC_FLAG_IN : 0) | USBH_HAL_XFER_DESC_FLAG_HOC); } //Fill status stage (i.e., a zero length packet). If data stage is skipped, the status stage is always IN. @@ -2370,15 +2268,14 @@ static void _buffer_exec(pipe_t *pipe) usbh_hal_chan_activate(pipe->chan_obj, buffer_to_exec->xfer_desc_list, desc_list_len, start_idx); } -static bool _buffer_check_done(pipe_t *pipe) +static void _buffer_exec_cont(pipe_t *pipe) { - if (pipe->ep_char.type != USB_PRIV_XFER_TYPE_CTRL) { - return true; - } - //Only control transfers need to be continued + //This should only ever be called on control transfers + assert(pipe->ep_char.type == USB_PRIV_XFER_TYPE_CTRL); dma_buffer_block_t *buffer_inflight = pipe->buffers[pipe->multi_buffer_control.rd_idx]; bool next_dir_is_in; int next_pid; + assert(buffer_inflight->flags.ctrl.cur_stg != 2); if (buffer_inflight->flags.ctrl.cur_stg == 0) { //Just finished control stage if (buffer_inflight->flags.ctrl.data_stg_skip) { //Skipping data stage. Go straight to status stage @@ -2391,18 +2288,15 @@ static bool _buffer_check_done(pipe_t *pipe) next_pid = 1; //Data stage always starts with a PID of DATA1 buffer_inflight->flags.ctrl.cur_stg = 1; } - } else if (buffer_inflight->flags.ctrl.cur_stg == 1) { //Just finished data stage. Go to status stage + } else { //cur_stg == 1. //Just finished data stage. Go to status stage next_dir_is_in = !buffer_inflight->flags.ctrl.data_stg_in; //Status stage is always the opposite direction of data stage next_pid = 1; //Status stage always has a PID of DATA1 buffer_inflight->flags.ctrl.cur_stg = 2; - } else { //Just finished status stage. Transfer is complete - return true; } //Continue the control transfer usbh_hal_chan_set_dir(pipe->chan_obj, next_dir_is_in); usbh_hal_chan_set_pid(pipe->chan_obj, next_pid); usbh_hal_chan_activate(pipe->chan_obj, buffer_inflight->xfer_desc_list, XFER_LIST_LEN_CTRL, buffer_inflight->flags.ctrl.cur_stg); - return false; } static inline void _buffer_parse_ctrl(dma_buffer_block_t *buffer) @@ -2410,15 +2304,15 @@ static inline void _buffer_parse_ctrl(dma_buffer_block_t *buffer) usb_transfer_t *transfer = &buffer->urb->transfer; //Update URB's actual number of bytes if (buffer->flags.ctrl.data_stg_skip) { - //There was no data stage. Just set the actual length to zero - transfer->actual_num_bytes = 0; + //There was no data stage. Just set the actual length to the size of the setup packet + transfer->actual_num_bytes = sizeof(usb_setup_packet_t); } else { //Parse the data stage for the remaining length int rem_len; int desc_status; usbh_hal_xfer_desc_parse(buffer->xfer_desc_list, 1, &rem_len, &desc_status); assert(desc_status == USBH_HAL_XFER_DESC_STS_SUCCESS); - assert(rem_len <= transfer->num_bytes); + assert(rem_len <= (transfer->num_bytes - sizeof(usb_setup_packet_t))); transfer->actual_num_bytes = transfer->num_bytes - rem_len; } //Update URB status @@ -2497,6 +2391,7 @@ static inline void _buffer_parse_isoc(dma_buffer_block_t *buffer, bool is_in) { usb_transfer_t *transfer = &buffer->urb->transfer; int desc_idx = buffer->flags.isoc.start_idx; //Descriptor index tracks which descriptor in the QTD list + int total_actual_num_bytes = 0; for (int pkt_idx = 0; pkt_idx < transfer->num_isoc_packets; pkt_idx++) { //Clear the filled descriptor int rem_len; @@ -2508,6 +2403,7 @@ static inline void _buffer_parse_isoc(dma_buffer_block_t *buffer, bool is_in) assert(rem_len <= transfer->isoc_packet_desc[pkt_idx].num_bytes); //Check for DMA errata //Update ISO packet actual length and status transfer->isoc_packet_desc[pkt_idx].actual_num_bytes = transfer->isoc_packet_desc[pkt_idx].num_bytes - rem_len; + total_actual_num_bytes += transfer->isoc_packet_desc[pkt_idx].actual_num_bytes; transfer->isoc_packet_desc[pkt_idx].status = (desc_status == USBH_HAL_XFER_DESC_STS_NOT_EXECUTED) ? USB_TRANSFER_STATUS_SKIPPED : USB_TRANSFER_STATUS_COMPLETED; //A descriptor is also allocated for unscheduled frames. We need to skip over them desc_idx += buffer->flags.isoc.interval; @@ -2515,43 +2411,39 @@ static inline void _buffer_parse_isoc(dma_buffer_block_t *buffer, bool is_in) desc_idx -= XFER_LIST_LEN_INTR; } } + //Write back the actual_num_bytes and statue of entire transfer + assert(total_actual_num_bytes <= transfer->num_bytes); + transfer->actual_num_bytes = total_actual_num_bytes; + transfer->status = USB_TRANSFER_STATUS_COMPLETED; } static inline void _buffer_parse_error(dma_buffer_block_t *buffer) { - //The URB had an error, so we consider that NO bytes were transferred + //The URB had an error, so we consider that NO bytes were transferred. Set actual_num_bytes to zero usb_transfer_t *transfer = &buffer->urb->transfer; transfer->actual_num_bytes = 0; for (int i = 0; i < transfer->num_isoc_packets; i++) { transfer->isoc_packet_desc[i].actual_num_bytes = 0; } - //Update status of URB - if (buffer->status_flags.cancelled) { - transfer->status = USB_TRANSFER_STATUS_CANCELED; - } else if (buffer->status_flags.pipe_state == HCD_PIPE_STATE_INVALID) { - transfer->status = USB_TRANSFER_STATUS_NO_DEVICE; - } else { - switch (buffer->status_flags.pipe_event) { - case HCD_PIPE_EVENT_ERROR_XFER: //Excessive transaction error - transfer->status = USB_TRANSFER_STATUS_ERROR; - break; - case HCD_PIPE_EVENT_ERROR_OVERFLOW: - transfer->status = USB_TRANSFER_STATUS_OVERFLOW; - break; - case HCD_PIPE_EVENT_ERROR_STALL: - transfer->status = USB_TRANSFER_STATUS_STALL; - break; - case HCD_PIPE_EVENT_URB_DONE: //Special case where we are cancelling an URB due to pipe_retire - transfer->status = USB_TRANSFER_STATUS_CANCELED; - break; - default: - //HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL should never occur - abort(); - break; - } + //Update status of URB. Status will depend on the pipe_event + switch (buffer->status_flags.pipe_event) { + case HCD_PIPE_EVENT_NONE: + transfer->status = USB_TRANSFER_STATUS_CANCELED; + break; + case HCD_PIPE_EVENT_ERROR_XFER: + transfer->status = USB_TRANSFER_STATUS_ERROR; + break; + case HCD_PIPE_EVENT_ERROR_OVERFLOW: + transfer->status = USB_TRANSFER_STATUS_OVERFLOW; + break; + case HCD_PIPE_EVENT_ERROR_STALL: + transfer->status = USB_TRANSFER_STATUS_STALL; + break; + default: + //HCD_PIPE_EVENT_URB_DONE and HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL should not occur here + abort(); + break; } - //Clear error flags - buffer->status_flags.val = 0; } static void _buffer_parse(pipe_t *pipe) @@ -2563,9 +2455,8 @@ static void _buffer_parse(pipe_t *pipe) int mps = pipe->ep_char.mps; //Parsing the buffer will update the buffer's corresponding URB - if (buffer_to_parse->status_flags.error_occurred) { - _buffer_parse_error(buffer_to_parse); - } else { + if (buffer_to_parse->status_flags.pipe_event == HCD_PIPE_EVENT_URB_DONE) { + //URB was successful switch (pipe->ep_char.type) { case USB_PRIV_XFER_TYPE_CTRL: { _buffer_parse_ctrl(buffer_to_parse); @@ -2588,6 +2479,9 @@ static void _buffer_parse(pipe_t *pipe) break; } } + } else { + //URB failed + _buffer_parse_error(buffer_to_parse); } urb_t *urb = buffer_to_parse->urb; urb->hcd_var = URB_HCD_STATE_DONE; @@ -2602,18 +2496,19 @@ static void _buffer_parse(pipe_t *pipe) pipe->multi_buffer_control.buffer_num_to_fill++; } -static void _buffer_flush_all(pipe_t *pipe, bool cancelled) +static bool _buffer_flush_all(pipe_t *pipe, bool cancelled) { - int cur_num_to_mark_done = pipe->multi_buffer_control.buffer_num_to_exec; + int cur_num_to_mark_done = pipe->multi_buffer_control.buffer_num_to_exec; for (int i = 0; i < cur_num_to_mark_done; i++) { //Mark any filled buffers as done - _buffer_done_error(pipe, 0, pipe->state, pipe->last_event, cancelled); + _buffer_done(pipe, 0, HCD_PIPE_EVENT_NONE); } int cur_num_to_parse = pipe->multi_buffer_control.buffer_num_to_parse; for (int i = 0; i < cur_num_to_parse; i++) { _buffer_parse(pipe); } //At this point, there should be no more filled buffers. Only URBs in the pending or done tailq + return (cur_num_to_parse > 0); } // ---------------------------------------------- HCD Transfer Descriptors --------------------------------------------- @@ -2646,13 +2541,13 @@ esp_err_t hcd_urb_enqueue(hcd_pipe_handle_t pipe_hdl, urb_t *urb) if (_buffer_can_exec(pipe)) { _buffer_exec(pipe); } - if (!pipe->cs_flags.is_active) { + if (!pipe->cs_flags.has_urb) { //This is the first URB to be enqueued into the pipe. Move the pipe to the list of active pipes TAILQ_REMOVE(&pipe->port->pipes_idle_tailq, pipe, tailq_entry); TAILQ_INSERT_TAIL(&pipe->port->pipes_active_tailq, pipe, tailq_entry); pipe->port->num_pipes_idle--; pipe->port->num_pipes_queued++; - pipe->cs_flags.is_active = 1; + pipe->cs_flags.has_urb = 1; } HCD_EXIT_CRITICAL(); return ESP_OK; @@ -2672,7 +2567,7 @@ urb_t *hcd_urb_dequeue(hcd_pipe_handle_t pipe_hdl) assert(urb->hcd_ptr == (void *)pipe && urb->hcd_var == URB_HCD_STATE_DONE); //The URB's reserved field should have been set to this pipe urb->hcd_ptr = NULL; urb->hcd_var = URB_HCD_STATE_IDLE; - if (pipe->cs_flags.is_active + if (pipe->cs_flags.has_urb && pipe->num_urb_pending == 0 && pipe->num_urb_done == 0 && pipe->multi_buffer_control.buffer_num_to_exec == 0 && pipe->multi_buffer_control.buffer_num_to_parse == 0) { //This pipe has no more enqueued URBs. Move the pipe to the list of idle pipes @@ -2680,7 +2575,7 @@ urb_t *hcd_urb_dequeue(hcd_pipe_handle_t pipe_hdl) TAILQ_INSERT_TAIL(&pipe->port->pipes_idle_tailq, pipe, tailq_entry); pipe->port->num_pipes_idle++; pipe->port->num_pipes_queued--; - pipe->cs_flags.is_active = 0; + pipe->cs_flags.has_urb = 0; } } else { //No more URBs to dequeue from this pipe diff --git a/components/usb/hub.c b/components/usb/hub.c new file mode 100644 index 0000000000..f970c41b3f --- /dev/null +++ b/components/usb/hub.c @@ -0,0 +1,668 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "esp_err.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "usb_private.h" +#include "hcd.h" +#include "hub.h" + +/* +Implementation of the HUB driver that only supports the root hub with a single port. Therefore, we currently don't +implement the bare minimum to control the root HCD port. +*/ + +#define HUB_ROOT_PORT_NUM 1 //HCD only supports one port +#ifdef CONFIG_USB_HOST_HW_BUFFER_BIAS_IN +#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_RX +#elif CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT +#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_PTX +#else //CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED +#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_BALANCED +#endif + +#define ENUM_CTRL_TRANSFER_MAX_LEN CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE +#define ENUM_DEV_ADDR 1 //Device address used in enumeration +#define ENUM_CONFIG_INDEX 0 //Index of the first configuration of the device +#define ENUM_DEV_DESC_REQ_SIZE 64 //Worst case size for device descriptor request +#define ENUM_LOW_SPEED_MPS 8 //Worst case MPS for the default endpoint of a low-speed device +#define ENUM_FULL_SPEED_MPS 64 //Worst case MPS for the default endpoint of a full-speed device + +#define HUB_DRIVER_FLAG_ACTION_ROOT_EVENT 0x01 +#define HUB_DRIVER_FLAG_ACTION_ENUM_EVENT 0x02 +#define HUB_DRIVER_FLAG_ACTION_PORT_RECOVER 0x04 + +typedef enum { + HUB_DRIVER_STATE_INSTALLED, + HUB_DRIVER_STATE_ROOT_POWERD, + HUB_DRIVER_STATE_ROOT_ENUMERATING, + HUB_DRIVER_STATE_ROOT_ACTIVE, + HUB_DRIVER_STATE_ROOT_RECOVERY, +} hub_driver_state_t; + +typedef enum { + ENUM_STAGE_NONE, /**< There is no device awaiting enumeration */ + ENUM_STAGE_START, /**< Start of enumeration. Allocates device object */ + ENUM_STAGE_GET_SHORT_DEV_DESC, /**< Getting short device descriptor */ + ENUM_STAGE_GET_SHORT_DEV_DESC_CHECK, /**< Check that short device descriptor was obtained */ + ENUM_STAGE_SECOND_RESET, /**< Doing second reset */ + ENUM_STAGE_SET_ADDR, /**< Setting address */ + ENUM_STAGE_SET_ADDR_CHECK, /**< Check that address was set successful */ + ENUM_STAGE_GET_FULL_DEV_DESC, /**< Getting full device descriptor */ + ENUM_STAGE_GET_FULL_DEV_DESC_CHECK, /**< Check that full device descriptor was obtained */ + ENUM_STAGE_GET_CONFIG_DESC, /**< Getting full configuration descriptor */ + ENUM_STAGE_GET_CONFIG_DESC_CHECK, /**< Check that full configuration descriptor was obtained */ + ENUM_STAGE_SET_CONFIG, /**< Set configuration number */ + ENUM_STAGE_SET_CONFIG_CHECK, /**< Check that configuration number was set */ + ENUM_STAGE_CLEANUP, /**< Clean up successful enumeration. Adds enumerated device to USBH */ + ENUM_STAGE_CLEANUP_FAILED, /**< Cleanup failed enumeration. Free device resources */ +} enum_stage_t; + +typedef struct { + //Dynamic members require a critical section + struct { + union { + struct { + uint32_t actions: 8; + uint32_t reserved24: 24; + }; + uint32_t val; + } flags; + hub_driver_state_t driver_state; + usb_device_handle_t root_dev_hdl; //Indicates if an enumerated device is connected to the root port + } dynamic; + //Single thread members don't require a critical section so long as they are never accessed from multiple threads + struct { + enum_stage_t enum_stage; + urb_t *enum_urb; + usb_device_handle_t enum_dev_hdl; //Handle of the device being enumerated. Moves to root_dev_hdl on enumeration completion + hcd_pipe_handle_t enum_dflt_pipe_hdl; + } single_thread; + //Constant members do no change after installation thus do not require a critical section + struct { + hcd_port_handle_t root_port_hdl; + usb_notif_cb_t notif_cb; + void *notif_cb_arg; + } constant; +} hub_driver_t; + +static hub_driver_t *p_hub_driver_obj = NULL; +static portMUX_TYPE hub_driver_lock = portMUX_INITIALIZER_UNLOCKED; + +const char *HUB_DRIVER_TAG = "HUB"; + +#define HUB_DRIVER_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&hub_driver_lock) +#define HUB_DRIVER_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&hub_driver_lock) +#define HUB_DRIVER_ENTER_CRITICAL() portENTER_CRITICAL(&hub_driver_lock) +#define HUB_DRIVER_EXIT_CRITICAL() portEXIT_CRITICAL(&hub_driver_lock) +#define HUB_DRIVER_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&hub_driver_lock) +#define HUB_DRIVER_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&hub_driver_lock) + +#define HUB_DRIVER_CHECK(cond, ret_val) ({ \ + if (!(cond)) { \ + return (ret_val); \ + } \ +}) +#define HUB_DRIVER_CHECK_FROM_CRIT(cond, ret_val) ({ \ + if (!(cond)) { \ + HUB_DRIVER_EXIT_CRITICAL(); \ + return ret_val; \ + } \ +}) + +// ------------------------------------------------- Event Handling ---------------------------------------------------- + +// ---------------------- Callbacks ------------------------ + +static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port_event, void *user_arg, bool in_isr) +{ + HUB_DRIVER_ENTER_CRITICAL_SAFE(); + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ROOT_EVENT; + HUB_DRIVER_EXIT_CRITICAL_SAFE(); + bool yield; + if (in_isr) { + p_hub_driver_obj->constant.notif_cb(USB_NOTIF_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.notif_cb_arg); + } else { + yield = false; + } + return yield; +} + +static bool enum_dflt_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr) +{ + //Note: This callback may have triggered when a failed enumeration is already cleaned up (e.g., due to a failed port reset) + HUB_DRIVER_ENTER_CRITICAL_SAFE(); + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + HUB_DRIVER_EXIT_CRITICAL_SAFE(); + return p_hub_driver_obj->constant.notif_cb(USB_NOTIF_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.notif_cb_arg); +} + +static void usbh_hub_callback(hcd_port_handle_t port_hdl, usbh_hub_event_t hub_event, void *arg) +{ + //We currently only support the root port + assert(port_hdl == p_hub_driver_obj->constant.root_port_hdl); + HUB_DRIVER_ENTER_CRITICAL(); + //Any hub_event results in whatever device connected to the root port to no longer be valid. We clear root_dev_hdl here. + usb_device_handle_t dev_hdl = p_hub_driver_obj->dynamic.root_dev_hdl; + p_hub_driver_obj->dynamic.root_dev_hdl = NULL; + assert(dev_hdl); + bool call_port_disable = false; + switch (hub_event) { + case USBH_HUB_EVENT_CLEANUP_PORT: + //After USBH has cleaned up gone device. The port can be recovered. + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER; + break; + case USBH_HUB_EVENT_DISABLE_PORT: + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERD; + call_port_disable = true; + break; + default: + abort(); //Should never occur + break; + } + HUB_DRIVER_EXIT_CRITICAL(); + if (call_port_disable) { + ESP_LOGD(HUB_DRIVER_TAG, "Disabling root port"); + hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE); + ESP_ERROR_CHECK(usbh_hub_dev_port_disabled(dev_hdl)); + } +} + +// ---------------------- Handlers ------------------------- + +static void root_port_handle_events(hcd_port_handle_t root_port_hdl) +{ + hcd_port_event_t port_event = hcd_port_handle_event(root_port_hdl); + switch (port_event) { + case HCD_PORT_EVENT_NONE: + //Nothing to do + break; + case HCD_PORT_EVENT_CONNECTION: { + if (hcd_port_command(root_port_hdl, HCD_PORT_CMD_RESET) == ESP_OK) { + ESP_LOGD(HUB_DRIVER_TAG, "Root port reset"); + //Start enumeration + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ENUMERATING; + HUB_DRIVER_EXIT_CRITICAL(); + p_hub_driver_obj->single_thread.enum_stage = ENUM_STAGE_START; + } else { + ESP_LOGE(HUB_DRIVER_TAG, "Root port reset failed"); + } + break; + } + case HCD_PORT_EVENT_DISCONNECTION: + case HCD_PORT_EVENT_ERROR: + case HCD_PORT_EVENT_OVERCURRENT: { + usb_device_handle_t dev_hdl = NULL; + HUB_DRIVER_ENTER_CRITICAL(); + switch (p_hub_driver_obj->dynamic.driver_state) { + case HUB_DRIVER_STATE_ROOT_POWERD: + //This occurred before enumeration. Therefore, there's no device and we can go straight to port recovery + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + break; + case HUB_DRIVER_STATE_ROOT_ENUMERATING: + //This occurred during enumeration. Therefore, we need to recover the failed enumeration + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + p_hub_driver_obj->single_thread.enum_stage = ENUM_STAGE_CLEANUP_FAILED; + break; + case HUB_DRIVER_STATE_ROOT_ACTIVE: + //There was an enumerated device. We need to indicate to USBH that the device is gone + dev_hdl = p_hub_driver_obj->dynamic.root_dev_hdl; + break; + default: + abort(); //Should never occur + break; + } + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_RECOVERY; + HUB_DRIVER_EXIT_CRITICAL(); + if (dev_hdl) { + ESP_ERROR_CHECK(usbh_hub_mark_dev_gone(dev_hdl)); + } + break; + } + default: + abort(); //Should never occur + break; + } +} + +// ------------------------------------------------- Enum Functions ---------------------------------------------------- + +static enum_stage_t enum_stage_start(void) +{ + usb_speed_t speed; + if (hcd_port_get_speed(p_hub_driver_obj->constant.root_port_hdl, &speed) != ESP_OK) { + return ENUM_STAGE_NONE; + } + usb_device_handle_t enum_dev_hdl; + hcd_pipe_handle_t enum_dflt_pipe_hdl; + //We use NULL as the parent device to indicate the root hub port 1. We currently only support a single device + if (usbh_hub_add_dev(p_hub_driver_obj->constant.root_port_hdl, speed, &enum_dev_hdl, &enum_dflt_pipe_hdl) != ESP_OK) { + return ENUM_STAGE_NONE; + } + //Set our own default pipe callback + ESP_ERROR_CHECK(hcd_pipe_update_callback(enum_dflt_pipe_hdl, enum_dflt_pipe_callback, NULL)); + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->single_thread.enum_dev_hdl = enum_dev_hdl; + p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl = enum_dflt_pipe_hdl; + HUB_DRIVER_EXIT_CRITICAL(); + ESP_LOGD(HUB_DRIVER_TAG, "Enumeration starting"); + return ENUM_STAGE_GET_SHORT_DEV_DESC; +} + +static enum_stage_t enum_stage_get_short_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)enum_urb->transfer.data_buffer); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + ENUM_DEV_DESC_REQ_SIZE; + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to get short device descriptor"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Getting short device descriptor"); + return ENUM_STAGE_GET_SHORT_DEV_DESC_CHECK; +} + +static enum_stage_t enum_stage_check_short_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Short device descriptor transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + usb_device_desc_t *device_desc = (usb_device_desc_t *)(enum_urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + if (enum_urb->transfer.actual_num_bytes < sizeof(usb_setup_packet_t) + 8) { //Device must return at least 8 bytes in its data stage + ESP_LOGE(HUB_DRIVER_TAG, "Short device descriptor too short"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Update the MPS of the default pipe + if (hcd_pipe_update_mps(pipe_hdl, device_desc->bMaxPacketSize0) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to update default pipe MPS"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Short device descriptor obtained"); + return ENUM_STAGE_SECOND_RESET; +} + +static enum_stage_t enum_stage_second_reset(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + ESP_ERROR_CHECK(hcd_pipe_set_persist_reset(pipe_hdl)); //Persist the default pipe through the reset + if (hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_RESET) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to issue second reset"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Second reset done"); + return ENUM_STAGE_SET_ADDR; +} + +static enum_stage_t enum_stage_set_addr(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_SET_ADDR((usb_setup_packet_t *)enum_urb->transfer.data_buffer, ENUM_DEV_ADDR); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t); //No data stage + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to set address"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Setting address %d", ENUM_DEV_ADDR); + return ENUM_STAGE_SET_ADDR_CHECK; +} + +static enum_stage_t enum_stage_check_set_addr(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb, usb_device_handle_t dev_hdl) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Set address transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Update the pipe and device's address, and fill the address into the device object + ESP_ERROR_CHECK(hcd_pipe_update_dev_addr(pipe_hdl, ENUM_DEV_ADDR)); + ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_addr(dev_hdl, ENUM_DEV_ADDR)); + ESP_LOGD(HUB_DRIVER_TAG, "Address set successfully"); + return ENUM_STAGE_GET_FULL_DEV_DESC; +} + +static enum_stage_t enum_stage_get_full_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)enum_urb->transfer.data_buffer); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + ENUM_DEV_DESC_REQ_SIZE; + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to get full device descriptor"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Getting full device descriptor"); + return ENUM_STAGE_GET_FULL_DEV_DESC_CHECK; +} + +static enum_stage_t enum_stage_check_full_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb, usb_device_handle_t dev_hdl) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Full device descriptor transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + if (enum_urb->transfer.actual_num_bytes < sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t)) { + ESP_LOGE(HUB_DRIVER_TAG, "Full device descriptor too short"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Fill device descriptor into device + const usb_device_desc_t *device_desc = (const usb_device_desc_t *)(enum_urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_desc(dev_hdl, device_desc)); + ESP_LOGD(HUB_DRIVER_TAG, "Full device descriptor obtained"); + return ENUM_STAGE_GET_CONFIG_DESC; +} + +static enum_stage_t enum_stage_get_config_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + //Get the configuration descriptor at index 0 + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)enum_urb->transfer.data_buffer, ENUM_CONFIG_INDEX, ENUM_CTRL_TRANSFER_MAX_LEN); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_LEN; + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to get configuration descriptor"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Getting configuration descriptor"); + return ENUM_STAGE_GET_CONFIG_DESC_CHECK; +} + +static enum_stage_t enum_stage_check_config_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb, usb_device_handle_t dev_hdl) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + usb_config_desc_t *config_desc = (usb_config_desc_t *)(enum_urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + if (enum_urb->transfer.actual_num_bytes < sizeof(usb_setup_packet_t) + sizeof(usb_config_desc_t)) { + ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor too small"); + return ENUM_STAGE_CLEANUP_FAILED; + } + if (config_desc->wTotalLength > ENUM_CTRL_TRANSFER_MAX_LEN) { + ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor larger than control transfer max length"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Fill configuration descriptor into device + ESP_ERROR_CHECK(usbh_hub_enum_fill_config_desc(dev_hdl, config_desc)); + return ENUM_STAGE_SET_CONFIG; +} + +static enum_stage_t enum_stage_set_config(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_SET_CONFIG((usb_setup_packet_t *)enum_urb->transfer.data_buffer, ENUM_CONFIG_INDEX + 1); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t); //No data stage + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to set configuration"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Setting configuration"); + return ENUM_STAGE_SET_CONFIG_CHECK; +} + +static enum_stage_t enum_stage_check_config(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Set configuration transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Configuration set successfully"); + return ENUM_STAGE_CLEANUP; +} + +static enum_stage_t enum_stage_cleanup(void) +{ + //We currently only support a single device connected to the root port. Move the device handle from enum to root + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.root_dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ACTIVE; + HUB_DRIVER_EXIT_CRITICAL(); + usb_device_handle_t dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + p_hub_driver_obj->single_thread.enum_dev_hdl = NULL; + p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl = NULL; + //Update device object after enumeration is done + ESP_ERROR_CHECK(usbh_hub_enum_done(dev_hdl)); + return ENUM_STAGE_NONE; +} + +static enum_stage_t enum_stage_cleanup_failed(void) +{ + //Enumeration failed. Clear the enum device handle and pipe + usb_device_handle_t dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + if (p_hub_driver_obj->single_thread.enum_dev_hdl) { + //Halt, flush, and dequeue enum default pipe + ESP_ERROR_CHECK(hcd_pipe_command(p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl, HCD_PIPE_CMD_HALT)); + ESP_ERROR_CHECK(hcd_pipe_command(p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl, HCD_PIPE_CMD_FLUSH)); + urb_t *dequeued_enum_urb = hcd_urb_dequeue(p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl); + assert(dequeued_enum_urb == p_hub_driver_obj->single_thread.enum_urb); + ESP_ERROR_CHECK(usbh_hub_enum_failed(dev_hdl)); //Free the underlying device object first before recovering the port + } + p_hub_driver_obj->single_thread.enum_dev_hdl = NULL; + p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl = NULL; + HUB_DRIVER_ENTER_CRITICAL(); + //Enum could have failed due to a port error. If so, we need to trigger a port recovery + if (p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_ROOT_RECOVERY) { + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER; + } + HUB_DRIVER_EXIT_CRITICAL(); + return ENUM_STAGE_NONE; +} + +static void enum_handle_events(void) +{ + enum_stage_t cur_stage = p_hub_driver_obj->single_thread.enum_stage; + hcd_pipe_handle_t enum_dflt_pipe_hdl = p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl; + urb_t *enum_urb = p_hub_driver_obj->single_thread.enum_urb; + usb_device_handle_t dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + enum_stage_t next_stage; + switch (cur_stage) { + case ENUM_STAGE_START: + next_stage = enum_stage_start(); + break; + case ENUM_STAGE_GET_SHORT_DEV_DESC: + next_stage = enum_stage_get_short_dev_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_GET_SHORT_DEV_DESC_CHECK: + next_stage = enum_stage_check_short_dev_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SECOND_RESET: + next_stage = enum_stage_second_reset(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SET_ADDR: + next_stage = enum_stage_set_addr(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SET_ADDR_CHECK: + next_stage = enum_stage_check_set_addr(enum_dflt_pipe_hdl, enum_urb, dev_hdl); + break; + case ENUM_STAGE_GET_FULL_DEV_DESC: + next_stage = enum_stage_get_full_dev_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_GET_FULL_DEV_DESC_CHECK: + next_stage = enum_stage_check_full_dev_desc(enum_dflt_pipe_hdl, enum_urb, dev_hdl); + break; + case ENUM_STAGE_GET_CONFIG_DESC: + next_stage = enum_stage_get_config_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_GET_CONFIG_DESC_CHECK: + next_stage = enum_stage_check_config_desc(enum_dflt_pipe_hdl, enum_urb, dev_hdl); + break; + case ENUM_STAGE_SET_CONFIG: + next_stage = enum_stage_set_config(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SET_CONFIG_CHECK: + next_stage = enum_stage_check_config(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_CLEANUP: + next_stage = enum_stage_cleanup(); + break; + case ENUM_STAGE_CLEANUP_FAILED: + next_stage = enum_stage_cleanup_failed(); + break; + default: + //Note: Don't abort here. The enum_dflt_pipe_callback() can trigger a HUB_DRIVER_FLAG_ACTION_ENUM_EVENT after a cleanup + next_stage = ENUM_STAGE_NONE; + break; + } + p_hub_driver_obj->single_thread.enum_stage = next_stage; + HUB_DRIVER_ENTER_CRITICAL(); + if (next_stage == ENUM_STAGE_GET_SHORT_DEV_DESC || + next_stage == ENUM_STAGE_SECOND_RESET || + next_stage == ENUM_STAGE_SET_ADDR || + next_stage == ENUM_STAGE_GET_FULL_DEV_DESC || + next_stage == ENUM_STAGE_GET_CONFIG_DESC || + next_stage == ENUM_STAGE_SET_CONFIG || + next_stage == ENUM_STAGE_CLEANUP || + next_stage == ENUM_STAGE_CLEANUP_FAILED) { + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + } + HUB_DRIVER_EXIT_CRITICAL(); +} + +// ---------------------------------------------- Hub Driver Functions ------------------------------------------------- + +esp_err_t hub_install(hub_config_t *hub_config) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj == NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_EXIT_CRITICAL(); + //Allocate Hub driver object + hub_driver_t *hub_driver_obj = heap_caps_calloc(1, sizeof(hub_driver_t), MALLOC_CAP_DEFAULT); + urb_t *enum_urb = urb_alloc(sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_LEN, 0, 0); + if (hub_driver_obj == NULL || enum_urb == NULL) { + return ESP_ERR_NO_MEM; + } + esp_err_t ret; + //Install HCD port + hcd_port_config_t port_config = { + .fifo_bias = HUB_ROOT_HCD_PORT_FIFO_BIAS, + .callback = root_port_callback, + .callback_arg = NULL, + .context = NULL, + }; + hcd_port_handle_t port_hdl; + ret = hcd_port_init(HUB_ROOT_PORT_NUM, &port_config, &port_hdl); + if (ret != ESP_OK) { + goto err; + } + //Initialize hub driver object + hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED; + hub_driver_obj->single_thread.enum_stage = ENUM_STAGE_NONE; + hub_driver_obj->single_thread.enum_urb = enum_urb; + hub_driver_obj->constant.root_port_hdl = port_hdl; + hub_driver_obj->constant.notif_cb = hub_config->notif_cb; + hub_driver_obj->constant.notif_cb_arg = hub_config->notif_cb_arg; + HUB_DRIVER_ENTER_CRITICAL(); + if (p_hub_driver_obj != NULL) { + HUB_DRIVER_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + p_hub_driver_obj = hub_driver_obj; + HUB_DRIVER_EXIT_CRITICAL(); + //Indicate to USBH that the hub is installed + ESP_ERROR_CHECK(usbh_hub_is_installed(usbh_hub_callback, NULL)); + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hcd_port_deinit(port_hdl)); +err: + urb_free(enum_urb); + heap_caps_free(hub_driver_obj); + return ret; +} + +esp_err_t hub_uninstall(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE); + hub_driver_t *hub_driver_obj = p_hub_driver_obj; + p_hub_driver_obj = NULL; + HUB_DRIVER_EXIT_CRITICAL(); + + ESP_ERROR_CHECK(hcd_port_deinit(hub_driver_obj->constant.root_port_hdl)); + //Free Hub driver resources + urb_free(hub_driver_obj->single_thread.enum_urb); + heap_caps_free(hub_driver_obj); + return ESP_OK; +} + +esp_err_t hub_root_start(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE); + HUB_DRIVER_EXIT_CRITICAL(); + //Power ON the root port + esp_err_t ret; + ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON); + if (ret == ESP_OK) { + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERD; + HUB_DRIVER_EXIT_CRITICAL(); + } + return ret; +} + +esp_err_t hub_root_stop(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state != HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE); + HUB_DRIVER_EXIT_CRITICAL(); + esp_err_t ret; + ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_OFF); + if (ret == ESP_OK) { + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED; + HUB_DRIVER_EXIT_CRITICAL(); + } + return ret; +} + +esp_err_t hub_process(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + uint32_t action_flags = p_hub_driver_obj->dynamic.flags.actions; + p_hub_driver_obj->dynamic.flags.actions = 0; + HUB_DRIVER_EXIT_CRITICAL(); + + while (action_flags) { + if (action_flags & HUB_DRIVER_FLAG_ACTION_ROOT_EVENT) { + root_port_handle_events(p_hub_driver_obj->constant.root_port_hdl); + } + if (action_flags & HUB_DRIVER_FLAG_ACTION_ENUM_EVENT) { + enum_handle_events(); + } + if (action_flags & HUB_DRIVER_FLAG_ACTION_PORT_RECOVER) { + ESP_LOGD(HUB_DRIVER_TAG, "Recovering root port"); + ESP_ERROR_CHECK(hcd_port_recover(p_hub_driver_obj->constant.root_port_hdl)); + ESP_ERROR_CHECK(hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON)); + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERD; + HUB_DRIVER_EXIT_CRITICAL(); + } + HUB_DRIVER_ENTER_CRITICAL(); + action_flags = p_hub_driver_obj->dynamic.flags.actions; + p_hub_driver_obj->dynamic.flags.actions = 0; + HUB_DRIVER_EXIT_CRITICAL(); + } + return ESP_OK; +} diff --git a/components/usb/include/usb/usb_host.h b/components/usb/include/usb/usb_host.h new file mode 100644 index 0000000000..dbc38bd385 --- /dev/null +++ b/components/usb/include/usb/usb_host.h @@ -0,0 +1,408 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "freertos/FreeRTOS.h" +#include "esp_err.h" +#include "esp_intr_alloc.h" +//Include the other USB Host Library headers as well +#include "usb/usb_host_misc.h" +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------- Macros and Types -------------------------------------------------- + +// ----------------------- Handles ------------------------- + +typedef void * usb_host_client_handle_t; /**< Handle to a client using the USB Host Library */ + +// ----------------------- Events -------------------------- + +#define USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS 0x01 /**< All clients have been deregistered from the USB Host Library */ +#define USB_HOST_LIB_EVENT_FLAGS_ALL_FREE 0x02 /**< The USB Host Library has freed all devices */ + +/** + * @brief The type event in a client event message + */ +typedef enum { + USB_HOST_CLIENT_EVENT_NEW_DEV, /**< A new device has been enumerated and added to the USB Host Library */ + USB_HOST_CLIENT_EVENT_DEV_GONE, /**< A device opened by the client is now gone */ +} usb_host_client_event_t; + +/** + * @brief Client event message + * + * Client event messages are sent to each client of the USB Host Library in order to notify them of various + * USB Host Library events such as: + * - Addition of new devices + * - Removal of existing devices + * + * @note The event message structure has a union with members corresponding to each particular event. Based on the event + * type, only the relevant member field should be accessed. + */ +typedef struct { + usb_host_client_event_t event; /**< Type of event */ + union { + struct { + uint8_t address; /**< New device's address */ + } new_dev; + struct { + usb_device_handle_t dev_hdl; /**< The handle of the device that was gone */ + } dev_gone; + }; +} usb_host_client_event_msg_t; + +// ---------------------- Callbacks ------------------------ + +/** + * @brief Client event callback + * + * - Each client of the USB Host Library must register an event callback to receive event messages from the USB Host + * Library. + * - The client event callback is run from the context of the clients usb_host_client_handle_events() function + */ +typedef void (*usb_host_client_event_cb_t)(const usb_host_client_event_msg_t *event_msg, void *arg); + +// -------------------- Configurations --------------------- + +/** + * @brief USB Host Library configuration + * + * Configuration structure of the USB Host Library. Provided in the usb_host_install() function + */ +typedef struct { + int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */ +} usb_host_config_t; + +/** + * @brief USB Host Library Client configuration + * + * Configuration structure for a USB Host Library client. Provided in usb_host_client_register() + */ +typedef struct { + usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */ + void *callback_arg; /**< Event callback function argument */ + int max_num_event_msg; /**< Maximum number of event messages that can be stored (e.g., 3) */ +} usb_host_client_config_t; + +// ------------------------------------------------ Library Functions -------------------------------------------------- + +/** + * @brief Install the USB Host Library + * + * - This function should only once to install the USB Host Library + * - This function should be called before any other USB Host Library functions are called + * + * @param[in] config USB Host Library configuration + * @return esp_err_t + */ +esp_err_t usb_host_install(const usb_host_config_t *config); + +/** + * @brief Uninstall the USB Host Library + * + * - This function should be called to uninstall the USB Host Library, thereby freeing its resources + * - All clients must have been deregistered before calling this function + * - All devices must have been freed by calling usb_host_device_free_all() and receiving the + * USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event flag + * + * @return esp_err_t + */ +esp_err_t usb_host_uninstall(void); + +/** + * @brief Handle USB Host Library events + * + * - This function handles all of the USB Host Library's processing and should be called repeatedly in a loop + * - Check event_flags_ret to see if an flags are set indicating particular USB Host Library events + * + * @param[in] timeout_ticks Timeout in ticks to wait for an event to occur + * @param[out] event_flags_ret Event flags that indicate what USB Host Library event occurred + * @return esp_err_t + */ +esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret); + +// ------------------------------------------------ Client Functions --------------------------------------------------- + +/** + * @brief Register a client of the USB Host Library + * + * - This function registers a client of the USB Host Library + * - Once a client is registered, its processing function usb_host_client_handle_events() should be called repeatedly + * + * @param[in] client_config Client configuration + * @param[out] client_hdl_ret Client handle + * @return esp_err_t + */ +esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret); + +/** + * @brief Deregister a USB Host Library client + * + * - This function deregisters a client of the USB Host Library + * - The client must have closed all previously opened devices before attempting to deregister + * + * @param[in] client_hdl Client handle + * @return esp_err_t + */ +esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl); + +/** + * @brief USB Host Library client processing function + * + * - This function handles all of a client's processing and should be called repeatedly in a loop + * + * @param[in] client_hdl Client handle + * @param[in] timeout_ticks Timeout in ticks to wait for an event to occur + * @return esp_err_t + */ +esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks); + +/** + * @brief Unblock a client + * + * - This function simply unblocks a client if it is blocked on the usb_host_client_handle_events() function. + * - This function is useful when need to unblock a client in order to deregister it. + * + * @param[in] client_hdl Client handle + * @return esp_err_t + */ +esp_err_t usb_host_client_unblock(usb_host_client_handle_t client_hdl); + +// ------------------------------------------------- Device Handling --------------------------------------------------- + +/** + * @brief Open a device + * + * - This function allows a client to open a device + * - A client must open a device first before attempting to use it (e.g., sending transfers, device requests etc.) + * + * @param[in] client_hdl Client handle + * @param[in] dev_addr Device's address + * @param[out] dev_hdl_ret Device's handle + * @return esp_err_t + */ +esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_addr, usb_device_handle_t *dev_hdl_ret); + +/** + * @brief Close a device + * + * - This function allows a client to close a device + * - A client must close a device after it has finished using the device + * - A client must close all devices it has opened before deregistering + * + * @param[in] client_hdl Client handle + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl); + +/** + * @brief Indicate that all devices can be freed when possible + * + * - This function marks all devices as waiting to be freed + * - If a device is not opened by any clients, it will be freed immediately + * - If a device is opened by at least one client, the device will be free when the last client closes that device. + * - Wait for the USB_HOST_LIB_EVENT_FLAGS_ALL_FREE flag to be set by usb_host_lib_handle_events() in order to know + * when all devices have been freed + * - This function is useful when cleaning up devices before uninstalling the USB Host Library + * + * @return esp_err_t + */ +esp_err_t usb_host_device_free_all(void); + +// ------------------------------------------------- Device Requests --------------------------------------------------- + +// ------------------- Cached Requests --------------------- + +/** + * @brief Get a device's information + * + * - This function gets some basic information of a device + * - The device must be opened first before attempting to get its information + * + * @param[in] dev_hdl Device handle + * @param[out] dev_info Device information + * @return esp_err_t + */ +esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info); + +// ----------------------------------------------- Descriptor Requests ------------------------------------------------- + +// ----------------- Cached Descriptors -------------------- + +/** + * @brief Get a device's device descriptor + * + * - A client must call usb_host_device_open() first + * - No control transfer is sent. The device's descriptor is cached on enumeration + * - This function simple returns a pointer to the cached descriptor + * + * @note No control transfer is sent. The device's descriptor is cached on enumeration + * @param[in] dev_hdl Device handle + * @param[out] device_desc Device descriptor + * @return esp_err_t + */ +esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc); + +/** + * @brief Get a device's active configuration descriptor + * + * - A client must call usb_host_device_open() first + * - No control transfer is sent. The device's active configuration descriptor is cached on enumeration + * - This function simple returns a pointer to the cached descriptor + * + * @note No control transfer is sent. A device's active configuration descriptor is cached on enumeration + * @param[in] dev_hdl Device handle + * @param[out] config_desc Configuration descriptor + * @return esp_err_t + */ +esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc); + +// ----------------------------------------------- Interface Functions ------------------------------------------------- + +/** + * @brief Function for a client to claim an device's interface + * + * - A client must claim a device's interface before attempting to communicate with any of its endpoints + * - Once an interface is claimed by a client, it cannot be claimed by any other client. + * + * @param[in] client_hdl Client handle + * @param[in] dev_hdl Device handle + * @param[in] bInterfaceNumber Interface number + * @param[in] bAlternateSetting Interface alternate setting number + * @return esp_err_t + */ +esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting); + +/** + * @brief Function for a client to release a device's interface + * + * - A client should release a device's interface after it no longer needs to communicate with the interface + * - A client must release all of its interfaces of a device it has claimed before being able to close the device + * + * @param[in] client_hdl Client handle + * @param[in] dev_hdl Device handle + * @param[in] bInterfaceNumber Interface number + * @return esp_err_t + */ +esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber); + +/** + * @brief Halt a particular endpoint + * + * - The device must have been opened by a client + * - The endpoint must be part of an interface claimed by a client + * - Once halted, the endpoint must be cleared using usb_host_endpoint_clear() before it can communicate again + * + * @param dev_hdl Device handle + * @param bEndpointAddress Endpoint address + * @return esp_err_t + */ +esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +/** + * @brief Flush a particular endpoint + * + * - The device must have been opened by a client + * - The endpoint must be part of an interface claimed by a client + * - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt()) + * - Flushing an endpoint will caused an queued up transfers to be canceled + * + * @param dev_hdl Device handle + * @param bEndpointAddress Endpoint address + * @return esp_err_t + */ +esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +/** + * @brief Clear a halt on a particular endpoint + * + * - The device must have been opened by a client + * - The endpoint must be part of an interface claimed by a client + * - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt()) + * - If the endpoint has any queued up transfers, clearing a halt will resume their execution + * + * @param dev_hdl Device handle + * @param bEndpointAddress Endpoint address + * @return esp_err_t + */ +esp_err_t usb_host_endpoint_clear(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +// ------------------------------------------------ Asynchronous I/O --------------------------------------------------- + +/** + * @brief Allocate a transfer object + * + * - This function allocates a transfer object + * - Each transfer object has a fixed sized buffer specified on allocation + * - A transfer object can be re-used indefinitely + * - A transfer can be submitted using usb_host_transfer_submit() or usb_host_transfer_submit_control() + * + * @param[in] data_buffer_size Size of the transfer's data buffer + * @param[in] num_isoc_packets Number of isochronous packets in transfer (set to 0 for non-isochronous transfers) + * @param[out] transfer Transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer); + +/** + * @brief Free a transfer object + * + * - Free a transfer object previously allocated using usb_host_transfer_alloc() + * - The transfer must not be in-flight when attempting to free it + * + * @param[in] transfer Transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_free(usb_transfer_t *transfer); + +/** + * @brief Submit a non-control transfer + * + * - Submit a transfer to a particular endpoint. The device and endpoint number is specified inside the transfer + * - The transfer must be properly initialized before submitting + * - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function. + * + * @param[in] transfer Initialized transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer); + +/** + * @brief Submit a control transfer + * + * - Submit a control transfer to a particular device. The client must have opened the device first + * - The transfer must be properly initialized before submitting. The first 8 bytes of the transfer's data buffer should + * contain the control transfer setup packet + * - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function. + * + * @param[in] client_hdl Client handle + * @param[in] transfer Initialized transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer); + +/** + * @brief Cancel a submitted transfer + * + * - Cancel a previously submitted transfer + * - In its current implementation, any transfer that is already in-flight will not be canceled + * + * @param transfer Transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_cancel(usb_transfer_t *transfer); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/include/usb/usb_host_misc.h b/components/usb/include/usb/usb_host_misc.h new file mode 100644 index 0000000000..ab04b471e2 --- /dev/null +++ b/components/usb/include/usb/usb_host_misc.h @@ -0,0 +1,130 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "usb/usb_types_ch9.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ---------------------------------------- Configuration Descriptor Parsing ------------------------------------------- + +/** + * @brief Get the next descriptor + * + * Given a particular descriptor within a full configuration descriptor, get the next descriptor within the + * configuration descriptor. This is a convenience function that can be used to walk each individual descriptor within + * a full configuration descriptor. + * + * @param[in] cur_desc Current descriptor + * @param[in] wTotalLength Total length of the configuration descriptor + * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of + * the current descriptor. On output, it is the offset of the returned descriptor. + * @return usb_standard_desc_t* Next descriptor, NULL if end of configuration descriptor reached + */ +const usb_standard_desc_t *usb_host_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset); + +/** + * @brief Get the next descriptor of a particular type + * + * Given a particular descriptor within a full configuration descriptor, get the next descriptor of a particular type + * (i.e., using the bDescriptorType value) within the configuration descriptor. + * + * @param[in] cur_desc Current descriptor + * @param[in] wTotalLength Total length of the configuration descriptor + * @param[in] bDescriptorType Type of the next descriptor to get + * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of + * the current descriptor. On output, it is the offset of the returned descriptor. + * @return usb_standard_desc_t* Next descriptor, NULL if end descriptor is not found or configuration descriptor reached + */ +const usb_standard_desc_t *usb_host_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset); + +/** + * @brief Get the number of alternate settings for a bInterfaceNumber + * + * Given a particular configuration descriptor, for a particular bInterfaceNumber, get the number of alternate settings + * available for that interface (i.e., the max possible value of bAlternateSetting for that bInterfaceNumber). + * + * @param[in] config_desc Pointer to the start of a full configuration descriptor + * @param[in] bInterfaceNumber Interface number + * @return int The number of alternate settings that the interface has, -1 if bInterfaceNumber not found + */ +int usb_host_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber); + +/** + * @brief Get a particular interface descriptor (using bInterfaceNumber and bAlternateSetting) + * + * Given a full configuration descriptor, get a particular interface descriptor. + * + * @note To get the number of alternate settings for a particular bInterfaceNumber, call + * usb_host_parse_interface_number_of_alternate() + * + * @param[in] config_desc Pointer to the start of a full configuration descriptor + * @param[in] bInterfaceNumber Interface number + * @param[in] bAlternateSetting Alternate setting number + * @param[out] offset Byte offset of the interface descriptor relative to the start of the configuration descriptor. Can be NULL. + * @return const usb_intf_desc_t* Pointer to interface descriptor, NULL if not found. + */ +const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset); + +/** + * @brief Get an endpoint descriptor within an interface descriptor + * + * Given an interface descriptor, get the Nth endpoint descriptor of the interface. The number of endpoints in an + * interface is indicated by the bNumEndpoints field of the interface descriptor. + * + * @note If bNumEndpoints is 0, it means the interface uses the default endpoint only + * + * @param[in] intf_desc Pointer to thee start of an interface descriptor + * @param[in] index Endpoint index + * @param[in] wTotalLength Total length of the containing configuration descriptor + * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset + * of the interface descriptor. On output, it is the offset of the endpoint descriptor. + * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found. + */ +const usb_ep_desc_t *usb_host_parse_endpoint_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset); + +/** + * @brief Get an endpoint descriptor based on the endpoint's address + * + * Given a configuration descriptor, get an endpoint descriptor based on it's bEndpointAddress, bAlternateSetting, and + * bInterfaceNumber. + * + * @param[in] config_desc Pointer to the start of a full configuration descriptor + * @param[in] bInterfaceNumber Interface number + * @param[in] bAlternateSetting Alternate setting number + * @param[in] bEndpointAddress Endpoint address + * @param[out] offset Byte offset of the endpoint descriptor relative to the start of the configuration descriptor. Can be NULL + * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found. + */ +const usb_ep_desc_t *usb_host_parse_endpoint_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset); + +// ------------------------------------------------------ Misc --------------------------------------------------------- + +/** + * @brief Round up to an integer multiple of an endpoint's MPS + * + * This is a convenience function to round up a size/length to an endpoint's MPS (Maximum packet size). This is useful + * when calculating transfer or buffer lengths of IN endpoints. + * + * @param[in] num_bytes Number of bytes + * @param[in] mps MPS + * @return int Round up integer multiple of MPS + */ +static inline int usb_host_round_up_to_mps(int num_bytes, int mps) +{ + if (num_bytes < 0 || mps < 0) { + return 0; + } + return ((num_bytes + mps - 1) / mps) * mps; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/include/usb/usb_types_ch9.h b/components/usb/include/usb/usb_types_ch9.h new file mode 100644 index 0000000000..4fe31b342f --- /dev/null +++ b/components/usb/include/usb/usb_types_ch9.h @@ -0,0 +1,464 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* +Note: This header file contains the types and macros belong/relate to the USB2.0 protocol and are HW implementation +and mode (i.e., Host or Device) agnostic. + +- On the USB Host Stack, this header is only meant to be used on the HCD layer and above. For types and macros on the + Host stack that are HW implementation specific (i.e., HAL layer and below), add them to the "hal/usb_types_private.h" + header instead. +*/ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define USB_DESC_ATTR __attribute__((packed)) + +// ---------------------------------------------------- Chapter 9 ------------------------------------------------------ + +/** + * @brief USB2.0 device states + */ +typedef enum { + USB_DEVICE_STATE_NOT_ATTACHED, //Not in the USB spec, but is a catch all state for devices that need to be cleaned up after a sudden disconnection or port error + USB_DEVICE_STATE_ATTACHED, + USB_DEVICE_STATE_POWERED, + USB_DEVICE_STATE_DEFAULT, + USB_DEVICE_STATE_ADDRESS, + USB_DEVICE_STATE_CONFIGURED, + USB_DEVICE_STATE_SUSPENDED, +} usb_device_state_t; + +/** + * @brief Descriptor types from USB2.0 specification table 9.5 + */ +#define USB_B_DESCRIPTOR_TYPE_DEVICE 0x01 +#define USB_B_DESCRIPTOR_TYPE_CONFIGURATION 0x02 +#define USB_B_DESCRIPTOR_TYPE_STRING 0x03 +#define USB_B_DESCRIPTOR_TYPE_INTERFACE 0x04 +#define USB_B_DESCRIPTOR_TYPE_ENDPOINT 0x05 +#define USB_B_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06 +#define USB_B_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07 +#define USB_B_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08 + +/** + * @brief Descriptor types from USB 2.0 ECN + */ +#define USB_B_DESCRIPTOR_TYPE_OTG 0x09 +#define USB_B_DESCRIPTOR_TYPE_DEBUG 0x0a +#define USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b + +/** + * @brief Descriptor types from Wireless USB spec + */ +#define USB_B_DESCRIPTOR_TYPE_SECURITY 0x0c +#define USB_B_DESCRIPTOR_TYPE_KEY 0x0d +#define USB_B_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 0x0e +#define USB_B_DESCRIPTOR_TYPE_BOS 0x0f +#define USB_B_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10 +#define USB_B_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMP 0x11 +#define USB_B_DESCRIPTOR_TYPE_WIRE_ADAPTER 0x21 +#define USB_B_DESCRIPTOR_TYPE_RPIPE 0x22 +#define USB_B_DESCRIPTOR_TYPE_CS_RADIO_CONTROL 0x23 + +/** + * @brief Descriptor types from UAS specification + */ +#define USB_B_DESCRIPTOR_TYPE_PIPE_USAGE 0x24 + +// -------------------- Setup Packet ----------------------- + +/** + * @brief Size of a USB control transfer setup packet in bytes + */ +#define USB_SETUP_PACKET_SIZE 8 + +/** + * @brief Structure representing a USB control transfer setup packet + */ +typedef union { + struct { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + } __attribute__((packed)); + uint8_t val[USB_SETUP_PACKET_SIZE]; +} usb_setup_packet_t; +_Static_assert(sizeof(usb_setup_packet_t) == USB_SETUP_PACKET_SIZE, "Size of usb_setup_packet_t incorrect"); + +/** + * @brief Bit masks belonging to the bmRequestType field of a setup packet + */ +#define USB_BM_REQUEST_TYPE_DIR_OUT (0X00 << 7) +#define USB_BM_REQUEST_TYPE_DIR_IN (0x01 << 7) +#define USB_BM_REQUEST_TYPE_TYPE_STANDARD (0x00 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_CLASS (0x01 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_VENDOR (0x02 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_RESERVED (0x03 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_MASK (0x03 << 5) +#define USB_BM_REQUEST_TYPE_RECIP_DEVICE (0x00 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_INTERFACE (0x01 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_ENDPOINT (0x02 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_OTHER (0x03 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_MASK (0x1f << 0) + +/** + * @brief Bit masks belonging to the bRequest field of a setup packet + */ +#define USB_B_REQUEST_GET_STATUS 0x00 +#define USB_B_REQUEST_CLEAR_FEATURE 0x01 +#define USB_B_REQUEST_SET_FEATURE 0x03 +#define USB_B_REQUEST_SET_ADDRESS 0x05 +#define USB_B_REQUEST_GET_DESCRIPTOR 0x06 +#define USB_B_REQUEST_SET_DESCRIPTOR 0x07 +#define USB_B_REQUEST_GET_CONFIGURATION 0x08 +#define USB_B_REQUEST_SET_CONFIGURATION 0x09 +#define USB_B_REQUEST_GET_INTERFACE 0x0A +#define USB_B_REQUEST_SET_INTERFACE 0x0B +#define USB_B_REQUEST_SYNCH_FRAME 0x0C + +/** + * @brief Bit masks belonging to the wValue field of a setup packet + */ +#define USB_W_VALUE_DT_DEVICE 0x01 +#define USB_W_VALUE_DT_CONFIG 0x02 +#define USB_W_VALUE_DT_STRING 0x03 +#define USB_W_VALUE_DT_INTERFACE 0x04 +#define USB_W_VALUE_DT_ENDPOINT 0x05 +#define USB_W_VALUE_DT_DEVICE_QUALIFIER 0x06 +#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_W_VALUE_DT_INTERFACE_POWER 0x08 + +/** + * @brief Initializer for a SET_ADDRESS request + * + * Sets the address of a connected device + */ +#define USB_SETUP_PACKET_INIT_SET_ADDR(setup_pkt_ptr, addr) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD |USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS; \ + (setup_pkt_ptr)->wValue = (addr); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 0; \ +}) + +/** + * @brief Initializer for a request to get a device's device descriptor + */ +#define USB_SETUP_PACKET_INIT_GET_DEVICE_DESC(setup_pkt_ptr) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ + (setup_pkt_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 18; \ +}) + +/** + * @brief Initializer for a request to get a device's current configuration number + */ +#define USB_SETUP_PACKET_INIT_GET_CONFIG(setup_pkt_ptr) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION; \ + (setup_pkt_ptr)->wValue = 0; \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 1; \ +}) + +/** + * @brief Initializer for a request to get one of the device's current configuration descriptor + * + * - desc_index indicates the configuration's index number + * - Number of bytes of the configuration descriptor to get + */ +#define USB_SETUP_PACKET_INIT_GET_CONFIG_DESC(setup_pkt_ptr, desc_index, desc_len) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ + (setup_pkt_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = (desc_len); \ +}) + +/** + * @brief Initializer for a request to set a device's current configuration number + */ +#define USB_SETUP_PACKET_INIT_SET_CONFIG(setup_pkt_ptr, config_num) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION; \ + (setup_pkt_ptr)->wValue = (config_num); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 0; \ +}) + +/** + * @brief Initializer for a request to set an interface's alternate setting + */ +#define USB_SETUP_PACKET_INIT_SET_INTERFACE(setup_pkt_ptr, intf_num, alt_setting_num) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_INTERFACE; \ + (setup_pkt_ptr)->wValue = (alt_setting_num); \ + (setup_pkt_ptr)->wIndex = (intf_num); \ + (setup_pkt_ptr)->wLength = 0; \ +}) + +// ---------------- Standard Descriptor -------------------- + +/** + * @brief Size of dummy USB standard descriptor + */ +#define USB_STANDARD_DESC_SIZE 2 + +/** + * @brief Dummy USB standard descriptor + * + * All USB standard descriptors start with these two bytes. Use this type traversing over descriptors + */ +typedef union { + struct { + uint8_t bLength; + uint8_t bDescriptorType; + } USB_DESC_ATTR; + uint8_t val[USB_STANDARD_DESC_SIZE]; +} usb_standard_desc_t; +_Static_assert(sizeof(usb_standard_desc_t) == USB_STANDARD_DESC_SIZE, "Size of usb_standard_desc_t incorrect"); + +// ------------------ Device Descriptor -------------------- + +/** + * @brief Size of a USB device descriptor in bytes + */ +#define USB_DEVICE_DESC_SIZE 18 + +/** + * @brief Structure representing a USB device descriptor + */ +typedef union { + struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; + } USB_DESC_ATTR; + uint8_t val[USB_DEVICE_DESC_SIZE]; +} usb_device_desc_t; +_Static_assert(sizeof(usb_device_desc_t) == USB_DEVICE_DESC_SIZE, "Size of usb_device_desc_t incorrect"); + +/** + * @brief Possible base class values of the bDeviceClass field of a USB device descriptor + */ +#define USB_CLASS_PER_INTERFACE 0x00 +#define USB_CLASS_AUDIO 0x01 +#define USB_CLASS_COMM 0x02 +#define USB_CLASS_HID 0x03 +#define USB_CLASS_PHYSICAL 0x05 +#define USB_CLASS_STILL_IMAGE 0x06 +#define USB_CLASS_PRINTER 0x07 +#define USB_CLASS_MASS_STORAGE 0x08 +#define USB_CLASS_HUB 0x09 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b +#define USB_CLASS_CONTENT_SEC 0x0d +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f +#define USB_CLASS_AUDIO_VIDEO 0x10 +#define USB_CLASS_BILLBOARD 0x11 +#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff + +/** + * @brief Vendor specific subclass code + */ +#define USB_SUBCLASS_VENDOR_SPEC 0xff + +// -------------- Configuration Descriptor ----------------- + +/** + * @brief Size of a short USB configuration descriptor in bytes + * + * @note The size of a full USB configuration includes all the interface and endpoint + * descriptors of that configuration. + */ +#define USB_CONFIG_DESC_SIZE 9 + +/** + * @brief Structure representing a short USB configuration descriptor + * + * @note The full USB configuration includes all the interface and endpoint + * descriptors of that configuration. + */ +typedef union { + struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; + } USB_DESC_ATTR; + uint8_t val[USB_CONFIG_DESC_SIZE]; +} usb_config_desc_t; +_Static_assert(sizeof(usb_config_desc_t) == USB_CONFIG_DESC_SIZE, "Size of usb_config_desc_t incorrect"); + +/** + * @brief Bit masks belonging to the bmAttributes field of a configuration descriptor + */ +#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set +#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered +#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wake-up +#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered + +// ---------- Interface Association Descriptor ------------- + +/** + * @brief Size of a USB interface association descriptor in bytes + */ +#define USB_IAD_DESC_SIZE 9 + +/** + * @brief Structure representing a USB interface association descriptor + */ +typedef union { + struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; + } USB_DESC_ATTR; + uint8_t val[USB_IAD_DESC_SIZE]; +} usb_iad_desc_t; +_Static_assert(sizeof(usb_iad_desc_t) == USB_IAD_DESC_SIZE, "Size of usb_iad_desc_t incorrect"); + +// ---------------- Interface Descriptor ------------------- + +/** + * @brief Size of a USB interface descriptor in bytes + */ +#define USB_INTF_DESC_SIZE 9 + +/** + * @brief Structure representing a USB interface descriptor + */ +typedef union { + struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; + } USB_DESC_ATTR; + uint8_t val[USB_INTF_DESC_SIZE]; +} usb_intf_desc_t; +_Static_assert(sizeof(usb_intf_desc_t) == USB_INTF_DESC_SIZE, "Size of usb_intf_desc_t incorrect"); + +// ----------------- Endpoint Descriptor ------------------- + +/** + * @brief Size of a USB endpoint descriptor in bytes + */ +#define USB_EP_DESC_SIZE 7 + +/** + * @brief Structure representing a USB endpoint descriptor + */ +typedef union { + struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + } USB_DESC_ATTR; + uint8_t val[USB_EP_DESC_SIZE]; +} usb_ep_desc_t; +_Static_assert(sizeof(usb_ep_desc_t) == USB_EP_DESC_SIZE, "Size of usb_ep_desc_t incorrect"); + +/** + * @brief Bit masks belonging to the bEndpointAddress field of an endpoint descriptor + */ +#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f +#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80 + +/** + * @brief Bit masks belonging to the bmAttributes field of an endpoint descriptor + */ +#define USB_BM_ATTRIBUTES_XFERTYPE_MASK 0x03 +#define USB_BM_ATTRIBUTES_XFER_CONTROL (0 << 0) +#define USB_BM_ATTRIBUTES_XFER_ISOC (1 << 0) +#define USB_BM_ATTRIBUTES_XFER_BULK (2 << 0) +#define USB_BM_ATTRIBUTES_XFER_INT (3 << 0) +#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK 0x0C /* in bmAttributes */ +#define USB_BM_ATTRIBUTES_SYNC_NONE (0 << 2) +#define USB_BM_ATTRIBUTES_SYNC_ASYNC (1 << 2) +#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE (2 << 2) +#define USB_BM_ATTRIBUTES_SYNC_SYNC (3 << 2) +#define USB_BM_ATTRIBUTES_USAGETYPE_MASK 0x30 +#define USB_BM_ATTRIBUTES_USAGE_DATA (0 << 4) +#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK (1 << 4) +#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB (2 << 4) + +/** + * @brief Macro helpers to get information about an endpoint from its descriptor + */ +#define USB_EP_DESC_GET_XFERTYPE(desc_ptr) ((usb_transfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK)) +#define USB_EP_DESC_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) +#define USB_EP_DESC_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0) +#define USB_EP_DESC_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF) + +// ------------------ String Descriptor -------------------- + +/** + * @brief Size of a short USB string descriptor in bytes + */ +#define USB_STR_DESC_SIZE 4 + +/** + * @brief Structure representing a USB string descriptor + */ +typedef union { + struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wData[1]; /* UTF-16LE encoded */ + } USB_DESC_ATTR; + uint8_t val[USB_STR_DESC_SIZE]; +} usb_str_desc_t; +_Static_assert(sizeof(usb_str_desc_t) == USB_STR_DESC_SIZE, "Size of usb_str_desc_t incorrect"); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/include/usb/usb_types_stack.h b/components/usb/include/usb/usb_types_stack.h new file mode 100644 index 0000000000..0db75d3788 --- /dev/null +++ b/components/usb/include/usb/usb_types_stack.h @@ -0,0 +1,137 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "usb/usb_types_ch9.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------ Protocol Standard -------------------------------------------------- + +/** + * @brief USB Standard Speeds + */ +typedef enum { + USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */ + USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ +} usb_speed_t; + +/** + * @brief The type of USB transfer + * + * @note The enum values need to match the bmAttributes field of an EP descriptor + */ +typedef enum { + USB_TRANSFER_TYPE_CTRL = 0, + USB_TRANSFER_TYPE_ISOCHRONOUS, + USB_TRANSFER_TYPE_BULK, + USB_TRANSFER_TYPE_INTR, +} usb_transfer_type_t; + +// ------------------------------------------------- Device Related ---------------------------------------------------- + +/** + * @brief Handle of a USB Device connected to a USB Host + */ +typedef void * usb_device_handle_t; + +/** + * @brief Basic information of an enumerated device + */ +typedef struct { + usb_speed_t speed; /**< Device's speed */ + uint8_t dev_addr; /**< Device's address */ + uint8_t bMaxPacketSize0; /**< The maximum packet size of the device's default endpoint */ + uint8_t bConfigurationValue; /**< Device's current configuration number */ +} usb_device_info_t; + +// ------------------------------------------------ Transfer Related --------------------------------------------------- + +/** + * @brief The status of a particular transfer + */ +typedef enum { + USB_TRANSFER_STATUS_COMPLETED, /**< The transfer was successful (but may be short) */ + USB_TRANSFER_STATUS_ERROR, /**< The transfer failed because due to excessive errors (e.g. no response or CRC error) */ + USB_TRANSFER_STATUS_TIMED_OUT, /**< The transfer failed due to a time out */ + USB_TRANSFER_STATUS_CANCELED, /**< The transfer was canceled */ + USB_TRANSFER_STATUS_STALL, /**< The transfer was stalled */ + USB_TRANSFER_STATUS_OVERFLOW, /**< The transfer as more data was sent than was requested */ + USB_TRANSFER_STATUS_SKIPPED, /**< ISOC packets only. The packet was skipped due to system latency or bus overload */ +} usb_transfer_status_t; + +/** + * @brief Isochronous packet descriptor + * + * If the number of bytes in an Isochronous transfer is larger than the MPS of the endpoint, the transfer is split + * into multiple packets transmitted at the endpoint's specified interval. An array of Isochronous packet descriptors + * describes how an Isochronous transfer should be split into multiple packets. + */ +typedef struct { + int num_bytes; /**< Number of bytes to transmit/receive in the packet. IN packets should be integer multiple of MPS */ + int actual_num_bytes; /**< Actual number of bytes transmitted/received in the packet */ + usb_transfer_status_t status; /**< Status of the packet */ +} usb_isoc_packet_desc_t; + +/** + * @brief USB transfer structure + * + * This structure is used to represent a transfer from a software client to an endpoint over the USB bus. Some of the + * fields are made const on purpose as they are fixed on allocation. Users should call the appropriate USB Host Library + * function to allocate a USB transfer structure instead of allocating this structure themselves. + * + * The transfer type is inferred from the endpoint this transfer is sent to. Depending on the transfer type, users + * should note the following: + * + * - Bulk: This structure represents a single bulk transfer. If the number of bytes exceeds the endpoint's MPS, the + * transfer will be split into multiple MPS sized packets followed by a short packet. + * - Control: This structure represents a single control transfer. This first 8 bytes of the data_buffer must be filled + * with the setup packet (see usb_setup_packet_t). The num_bytes field should be the total size of the + * transfer (i.e., size of setup packet + wLength). + * - Interrupt: Represents an interrupt transfer. If num_bytes exceeds the MPS of the endpoint, the transfer will be + * split into multiple packets, and each packet is transferred at the endpoint's specified interval. + * - Isochronous: Represents a stream of bytes that should be transferred to an endpoint at a fixed rate. The transfer + * is split into packets according to the each isoc_packet_desc. A packet is transferred at each interval + * of the endpoint. + * + * @note For Bulk/Control/Interrupt IN transfers, the num_bytes must be a integer multiple of the endpoint's MPS + * @note This structure should be allocated via __insert_func_name__() + * @note Once the transfer has be submitted, users should not modify the structure until the transfer has completed + */ +typedef struct usb_transfer_s usb_transfer_t; + +/** + * @brief USB transfer completion callback + */ +typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer); + +struct usb_transfer_s{ + uint8_t *const data_buffer; /**< Pointer to data buffer */ + const size_t data_buffer_size; /**< Size of the data buffer in bytes */ + int num_bytes; /**< Number of bytes to transfer. + Control transfers should include the size of the setup packet. + Isochronous transfer should be the total transfer size of all packets. + For non-control IN transfers, num_bytes should be an integer multiple of MPS. */ + int actual_num_bytes; /**< Actual number of bytes transferred */ + uint32_t flags; /**< Transfer flags */ + usb_device_handle_t device_handle; /**< Device handle */ + uint8_t bEndpointAddress; /**< Endpoint Address */ + usb_transfer_status_t status; /**< Status of the transfer */ + uint32_t timeout; /**< Timeout (in milliseconds) of the packet (currently not supported yet) */ + usb_transfer_cb_t callback; /**< Transfer callback */ + void *context; /**< Context variable for transfer to associate transfer with something */ + const int num_isoc_packets; /**< Only relevant to Isochronous. Number of service periods (i.e., intervals) to transfer data buffer over. */ + usb_isoc_packet_desc_t isoc_packet_desc[0]; /**< Descriptors for each Isochronous packet */ +}; + +#define USB_TRANSFER_FLAG_ZERO_PACK 0x01 /**< (For bulk OUT only). Indicates that a bulk OUT transfers should always terminate with a short packet, even if it means adding an extra zero length packet */ + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/maintainers.md b/components/usb/maintainers.md index d31fb84d25..81e2d00dec 100644 --- a/components/usb/maintainers.md +++ b/components/usb/maintainers.md @@ -1,18 +1,41 @@ # USB Host Stack Maintainers Notes -This document is intended future maintainers of the ESP-IDF USB Host stack. +This document is intended for future maintainers of the ESP-IDF USB Host stack. Note: The underlying DWC_OTG controller will sometimes be referred to as the Host Controller in this document. +Note: Some static functions within the stack need to be called within critical sections. Therefore, the USB Host stack will prefix all such function names with an underscore (e.g., `_some_static_func()`) will need to be called in critical sections) + The host driver is currently split into the following layers, ordered from the lowest (furthest away from the user) to the highest layer (closest to the user). * USB Host lower layer in `usbh_ll.h` * USB HAL in `usbh_hal.h` and `usbh_hal.c` * Host Controller Driver in `hcd.c` and `hcd.h` +* USB Host Driver in `usb_host.h` and `usb_host.c` + +# DWC_OTG + +Details regarding the DWC_OTG peripheral are covered in the data book and programming guide. However, this section adds some extra notes regarding the hardware's behavior that are not specified / cannot be easily found in the data book or programming guide. + +## Implicit interrupt on short packet on INTERRUPT transfer. + +- An interrupt channel will trigger an interrupt one of its QTDs is a short packet (event if the QTD did not set the interrupt on complete bit). This implicit interrupt is used to notify the software that it should halt the channel to +stop the remainder of the interrupt transfer. + +## Channel interrupt on port errors + +- If there are one or more channels active, and a port error interrupt occurs (such as disconnection, over-current), the active channels will not have an interrupt. Each need to be manually disabled to obtain an interrupt. + +## Reset + +- When resetting, if a disconnect occurs while a reset condition is being held. The disconnect is not detected until the reset condition is released. Once released, a `USBH_HAL_PORT_EVENT_DISCONN` is generated. +- During a second reset (i.e., there is already an enabled device). + - Once the reset condition is asserted, a `USBH_HAL_PORT_EVENT_DISABLED` is generated + - Once released, a `USBH_HAL_PORT_EVENT_ENABLED` is generated again. # USB Host Lower Layer -* `usbh_ll.h` abstracts away the basic register operation of the **DWC** OTG controller +* `usbh_ll.h` abstracts away the basic register operation of the DWC_OTG controller * The LL provides register operations of the DWC OTG controller operating under Host Mode using scatter/gather internal DMA. * For non-host mode specific register operations (i.e. global registers), the functions are prefixed with `usb_ll_...()` * For host mode specific register operations, the functions are prefixed with `usbh_ll_...()` @@ -47,49 +70,52 @@ The HAL layer abstracts the DWC_OTG operating in Host Mode using Internal Scatte # Host Controller Driver (HCD) -The HCD (Host Controller Driver) abstracts the DWC_OTG as N number of ports and an arbitrary number of pipes that can be routed through one of the ports to a device. However note that **the underlying hardware controller only has a single port, so technically only one port can ever be enabled**. +The HCD (Host Controller Driver) abstracts the DWC_OTG as N number of ports and an arbitrary number of pipes that can be routed through one of the ports to a device. However, note that **the underlying hardware controller only has a single port, so technically only one port can ever be enabled**. - In other words, the HCD essentially implements a root hub (not fully behavioral compliant) that contains a single port. - Pipes are "an association between an endpoint on a device and software on the host". URBs (USB Request Block) represent a USB transfer that can be enqueued into a pipe for transmission, and dequeued from a pipe when completed. The HCD currently has the following limitations: -- HCD **does not** "present the root hub and its behavior according to the hub class definition". We currently don't have a hub driver yet, so the port commands in the driver do not fully represent an interface of a USB hub as described in 10.4 of the USB2.0 spec. +- HCD **does not "present the root hub and its behavior according to the hub class definition"**. We currently don't have a hub driver yet, so the port commands in the driver do not fully represent an interface of a USB hub as described in 10.4 of the USB2.0 spec. - No more than 8 pipes can be allocated at any one time due to underlying Host Controllers 8 channel limit. In the future, we could make particular pipes share a single Host Controller channel. -- The HCD currently only supports Control and Bulk transfer types. -- If you are connecting to a device with a large MPS requirements (e.g., Isochronous transfers), you may need to call `hcd_port_set_fifo_bias()` to adjust the size of the internal FIFO ## HCD Port -- An HCD port can be as a simplified version of a port on the Root Hub of the host controller. However, the complexity of parsing Hub Requests is discarded in favor of port commands (`hcd_port_cmd_t`) as the current USB Host Stack does not support hubs yet. +- An HCD port can be thought of as a simplified version of a port on the Root Hub of the host controller. However, the complexity of parsing Hub Requests is discarded in favor of port commands (`hcd_port_cmd_t`) as the current USB Host Stack does not support hubs yet. - A port must first initialized before it can be used. A port is identified by its handled of type `hcd_port_handle_t` - The port can be manipulated using commands such as: - Powering the port ON/OFF - Issuing reset/resume signals - The various host port events are represented in the `hcd_port_event_t` enumeration -- When a fatal error (such as a sudden disconnection or a port over current), the port will be put into the HCD_PORT_STATE_RECOVERY state. The port can be deinitialized from there, or recovered using `hcd_port_recover()`. All the pipes routed through the port will be made invalid. -- The FIFO bias of a port can be set using `hcd_port_set_fifo_bias()`. Biasing the FIFO will affect the permissible MPS sizes of pipes. For example, if the connected device has an IN endpoint with large MPS (e.g., 512 bytes), the FIFO should be biased as `HCD_PORT_FIFO_BIAS_RX`. +- When the following port events occur, the port will be put into the HCD_PORT_STATE_RECOVERY state. The port can be deinitialized from there, or recovered using `hcd_port_recover()`. All the pipes routed through the port must be freed before the port can be recovered. + - `HCD_PORT_EVENT_DISCONNECTION` + - `HCD_PORT_EVENT_ERROR` + - `HCD_PORT_EVENT_OVERCURRENT` +- The port's internal FIFOs (RX, Periodic TX, Non-periodic TX) must be after each port reset (a port reset seems to clear the FIFO sizing registers). The sizing of these FIFOs will affect the largest supported MPS of endpoints using that FIFO. For convenience, the HCD provides the `hcd_port_fifo_bias_t` enum that will set the FIFO sizes for you but biased towards a particular use case. For example, if the connected device has an IN endpoint with large MPS (e.g., 512 bytes), the FIFO should be biased as `HCD_PORT_FIFO_BIAS_RX`. + - The FIFO sizes will be set on port initialization (supplied in `hcd_port_config_t`) + - FIFOs can be resized after port reset using `hcd_port_set_fifo_bias()` but some restrictions apply (see API description). ## HCD Pipes -- URBs can be enqueued into a pipe. Pipes use a linked list internally, so there is in-theory no limit to the number of URBs that can be enqueued. +- Pipes can be opened to a particular endpoint based on a descriptor provided on allocation. If opening a default pipe, a `NULL` descriptor can be provided. +- URBs can be enqueued into a pipe. Pipes use a linked list internally, so there is (in theory) no limit to the number of URBs that can be enqueued. - URBs need to be dequeued once they are completed. - URBs need to have the transfer information (such as data buffer, transfer length in bytes) filled before they should be enqueued. -- URBs will be owned by the HCD until they are dequeued. Thus, users should not attempt to modify an URB object (and the URB's data buffer) until the URB is dequeued. +- URBs will be owned by the HCD until they are dequeued. Thus, users should not attempt to modify a URB object (and the URB's data buffer) until the URB is dequeued. - The URB is defined in `usb_private.h` instead of `hcd.h` so that the same structure can shared throughout the entire Host stack. Each layer simply needs to pass the pointer of the URB to the next layer thus minimizing the amount of copying required. ## HCD SW Arch The software arch for the HCD has the following properties and intentions: -- Some static functions need to be called in critical sections whilst others need not. Therefore, static functions prefixed by an underscore ((e.g., `_some_static_func()`) will need to be called in critical sections. - Some static functions may be blocking. Those functions will have a note in their descriptions. - The HCD communicates events entirely through callbacks and polling/handling functions. The client can choose what type of data structure they want to use in the callbacks to keep track of port and pipe events. Callbacks don't even need to be used, and the HCD should be able to operate entirely on a polling basis. -- The port and each pipe have to be treated as completely separate entities (wither their own handles and events). This allows client to group these entities however it sees fit. For example, the client can: +- The port and each pipe have to be treated as completely separate entities (with their own handles and events). This allows clients to group these entities however it sees fit. For example, the client can: - Let a hub driver manage the port, and manipulate the port via its port handle - Group pipes into interfaces and expose the interface as a single entity -- The HCD will not internally allocate any tasks. It is up to the client to decide how distribute workload (e.g., a single while loop polling a port and all its pipes vs or each pipe having its own task). -- The HCD uses an interrupt process things that require low latency such as processing pipe transfer requests. Where possible, processing is deferred to the `hcd_port_handle_event()` to reduce ISR workload. +- The HCD will not internally allocate any tasks. It is up to the client to decide how to distribute workload (e.g., a single while loop polling a port and all its pipes vs or each pipe having its own task). +- The HCD uses an interrupt to process things that require low latency such as processing pipe transfer requests. Where possible, processing is deferred to the `hcd_port_handle_event()` to reduce ISR workload. ### Events @@ -112,4 +138,4 @@ The HCD API is thread safe however the following limitations should be noted: - Likewise, it is the client's responsibility to ensure that events and pipes are cleared before calling `hcd_port_deinit()`. - `hcd_port_command()` is thread safe, but only one port command can be executed at any one time. Therefore HCD internally used a mutex to protect against concurrent commands. - If multiple threads attempt to execute a command on the sample one, all but one of those threads will return with an invalid state error. -- HCD functions should not be called from critical sections and interrupts, as some functions (e.g., `hcd_port_command()` and `hcd_pipe_command()`) may be blocking. \ No newline at end of file +- Blocking HCD functions should not be called from critical sections and interrupts (e.g., `hcd_port_command()` and `hcd_pipe_command()`). \ No newline at end of file diff --git a/components/usb/private_include/hcd.h b/components/usb/private_include/hcd.h index d5f25c0e92..b1e24ae530 100644 --- a/components/usb/private_include/hcd.h +++ b/components/usb/private_include/hcd.h @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -23,7 +15,7 @@ extern "C" { #include #include "esp_err.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" // ------------------------------------------------- Macros & Types ---------------------------------------------------- @@ -53,18 +45,14 @@ typedef enum { * * Active: * - Pipe is able to transmit data. URBs can be enqueued. - * - Event if pipe has no URBs enqueued, it can still be in the active state. + * - Even if pipe has no URBs enqueued, it can still be in the active state. * Halted: * - An error has occurred on the pipe. URBs will no longer be executed. - * - Halt should be cleared using the clear command - * Invalid: - * - The underlying device that the pipe connects is not longer valid, thus making the pipe invalid. - * - Pending URBs should be dequeued and the pipe should be freed. + * - Halt should be cleared using the HCD_PIPE_CMD_CLEAR command */ typedef enum { HCD_PIPE_STATE_ACTIVE, /**< The pipe is active */ HCD_PIPE_STATE_HALTED, /**< The pipe is halted */ - HCD_PIPE_STATE_INVALID, /**< The pipe no longer exists and should be freed */ } hcd_pipe_state_t; // ----------------------- Events -------------------------- @@ -80,20 +68,16 @@ typedef enum { HCD_PORT_EVENT_DISCONNECTION, /**< A device disconnection has been detected */ HCD_PORT_EVENT_ERROR, /**< A port error has been detected. Port is now HCD_PORT_STATE_RECOVERY */ HCD_PORT_EVENT_OVERCURRENT, /**< Overcurrent detected on the port. Port is now HCD_PORT_STATE_RECOVERY */ - HCD_PORT_EVENT_SUDDEN_DISCONN, /**< The port has suddenly disconnected (i.e., there was an enabled device connected - to the port when the disconnection occurred. Port is now HCD_PORT_STATE_RECOVERY. */ } hcd_port_event_t; /** * @brief HCD pipe events * * @note Pipe error events will put the pipe into the HCD_PIPE_STATE_HALTED state - * @note The HCD_PIPE_EVENT_INVALID will put the pipe in the HCD_PIPE_STATE_INVALID state */ typedef enum { HCD_PIPE_EVENT_NONE, /**< The pipe has no events (used to indicate no events when polling) */ HCD_PIPE_EVENT_URB_DONE, /**< The pipe has completed an URB. The URB can be dequeued */ - HCD_PIPE_EVENT_INVALID, /**< The pipe is invalid because the underlying device is no longer valid */ HCD_PIPE_EVENT_ERROR_XFER, /**< Excessive (three consecutive) transaction errors (e.g., no ACK, bad CRC etc) */ HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL, /**< URB was not available */ HCD_PIPE_EVENT_ERROR_OVERFLOW, /**< Received more data than requested. Usually a Packet babble error @@ -111,9 +95,9 @@ typedef enum { HCD_PORT_CMD_POWER_OFF, /**< Power OFF the port. If the port is enabled, this will cause a HCD_PORT_EVENT_SUDDEN_DISCONN event. If the port is disabled, this will cause a HCD_PORT_EVENT_DISCONNECTION event. */ HCD_PORT_CMD_RESET, /**< Issue a reset on the port */ - HCD_PORT_CMD_SUSPEND, /**< Suspend the port */ + HCD_PORT_CMD_SUSPEND, /**< Suspend the port. All pipes must be halted */ HCD_PORT_CMD_RESUME, /**< Resume the port */ - HCD_PORT_CMD_DISABLE, /**< Disable the port (stops the SOFs or keep alive). Any created pipes will receive a HCD_PIPE_EVENT_INVALID event */ + HCD_PORT_CMD_DISABLE, /**< Disable the port (stops the SOFs or keep alive). All pipes must be halted. */ } hcd_port_cmd_t; /** @@ -122,10 +106,9 @@ typedef enum { * The pipe commands represent the list of pipe manipulations outlined in 10.5.2.2. of USB2.0 specification. */ typedef enum { - HCD_PIPE_CMD_ABORT, /**< Retire all scheduled URBs. Pipe's state remains unchanged */ - HCD_PIPE_CMD_RESET, /**< Retire all scheduled URBs. Pipe's state moves to active */ - HCD_PIPE_CMD_CLEAR, /**< Pipe's state moves from halted to active */ - HCD_PIPE_CMD_HALT /**< Pipe's state moves to halted */ + HCD_PIPE_CMD_HALT, /**< Halt an active pipe. The currently executing URB will be canceled. Enqueued URBs are left untouched */ + HCD_PIPE_CMD_FLUSH, /**< Can only be called when halted. Will cause all enqueued URBs to be canceled */ + HCD_PIPE_CMD_CLEAR, /**< Causes a halted pipe to become active again. Any enqueued URBs will being executing.*/ } hcd_pipe_cmd_t; // -------------------- Object Types ----------------------- @@ -171,6 +154,7 @@ typedef struct { * @brief Port configuration structure */ typedef struct { + hcd_port_fifo_bias_t fifo_bias; /**< HCD port internal FIFO biasing */ hcd_port_callback_t callback; /**< HCD port event callback */ void *callback_arg; /**< User argument for HCD port callback */ void *context; /**< Context variable used to associate the port with upper layer object */ @@ -185,7 +169,7 @@ typedef struct { hcd_pipe_callback_t callback; /**< HCD pipe event ISR callback */ void *callback_arg; /**< User argument for HCD pipe callback */ void *context; /**< Context variable used to associate the pipe with upper layer object */ - const usb_desc_ep_t *ep_desc; /**< Pointer to endpoint descriptor of the pipe */ + const usb_ep_desc_t *ep_desc; /**< Pointer to endpoint descriptor of the pipe */ usb_speed_t dev_speed; /**< Speed of the device */ uint8_t dev_addr; /**< Device address of the pipe */ } hcd_pipe_config_t; @@ -257,11 +241,12 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl); * * Call this function to manipulate a port (e.g., powering it ON, sending a reset etc). The following conditions * must be met when calling this function: - * - The port is in the correct state for the command (e.g., port must be suspend in order to use the resume command) + * - The port is in the correct state for the command (e.g., port must be suspended in order to use the resume command) * - The port does not have any pending events * * @note This function is internally protected by a mutex. If multiple threads call this function, this function will * can block. + * @note The function can block * @note For some of the commands that involve a blocking delay (e.g., reset and resume), if the port's state changes * unexpectedly (e.g., a disconnect during a resume), this function will return ESP_ERR_INVALID_RESPONSE. * @@ -358,8 +343,7 @@ esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_ * When allocating a pipe, the HCD will assess whether there are sufficient resources (i.e., bus time, and controller * channels). If sufficient, the pipe will be allocated. * - * @note Currently, Interrupt and Isochronous pipes are not supported yet - * @note The host port must be in the enabled state before a pipe can be allcoated + * @note The host port must be in the enabled state before a pipe can be allocated * * @param[in] port_hdl Handle of the port this pipe will be routed through * @param[in] pipe_config Pipe configuration @@ -392,9 +376,9 @@ esp_err_t hcd_pipe_free(hcd_pipe_handle_t pipe_hdl); * * This function is intended to be called on default pipes during enumeration in order to update the pipe's maximum * packet size. This function can only be called on a pipe that has met the following conditions: - * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID state) - * - Pipe is not currently processing a command - * - All URBs have been dequeued from the pipe + * - Pipe is not current processing a command + * - Pipe does not have any enqueued URBs + * - Port cannot be resetting * * @param pipe_hdl Pipe handle * @param mps New Maximum Packet Size @@ -409,9 +393,9 @@ esp_err_t hcd_pipe_update_mps(hcd_pipe_handle_t pipe_hdl, int mps); * * This function is intended to be called on default pipes during enumeration in order to update the pipe's device * address. This function can only be called on a pipe that has met the following conditions: - * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID state) - * - Pipe is not currently processing a command - * - All URBs have been dequeued from the pipe + * - Pipe is not current processing a command + * - Pipe does not have any enqueued URBs + * - Port cannot be resetting * * @param pipe_hdl Pipe handle * @param dev_addr New device address @@ -421,6 +405,22 @@ esp_err_t hcd_pipe_update_mps(hcd_pipe_handle_t pipe_hdl, int mps); */ esp_err_t hcd_pipe_update_dev_addr(hcd_pipe_handle_t pipe_hdl, uint8_t dev_addr); +/** + * @brief Update a pipe's callback + * + * This function is intended to be called on default pipes at the end of enumeration to switch to a callback that + * handles the completion of regular control transfer. + * - Pipe is not current processing a command + * - Pipe does not have any enqueued URBs + * - Port cannot be resetting + * + * @param pipe_hdl Pipe handle + * @param callback Callback + * @param user_arg Callback argument + * @return esp_err_t + */ +esp_err_t hcd_pipe_update_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_callback_t callback, void *user_arg); + /** * @brief Make a pipe persist through a run time reset * @@ -454,19 +454,14 @@ hcd_pipe_state_t hcd_pipe_get_state(hcd_pipe_handle_t pipe_hdl); /** * @brief Execute a command on a particular pipe * - * Pipe commands allow a pipe to be manipulated (such as clearing a halt, retiring all URBs etc). The following - * conditions must for a pipe command to be issued: - * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID) - * - No other thread/task processing a command on the pipe concurrently (will return) + * Pipe commands allow a pipe to be manipulated (such as clearing a halt, retiring all URBs etc) * - * @note Some pipe commands will block until the pipe's current in-flight URB is complete. If the pipe's state - * changes unexpectedly, this function will return ESP_ERR_INVALID_RESPONSE + * @note This function can block * * @param pipe_hdl Pipe handle * @param command Pipe command * @retval ESP_OK: Command executed successfully * @retval ESP_ERR_INVALID_STATE: The pipe is not in the correct state/condition too execute the command - * @retval ESP_ERR_INVALID_RESPONSE: The pipe's state changed unexpectedly */ esp_err_t hcd_pipe_command(hcd_pipe_handle_t pipe_hdl, hcd_pipe_cmd_t command); @@ -490,6 +485,7 @@ hcd_pipe_event_t hcd_pipe_get_event(hcd_pipe_handle_t pipe_hdl); * - The URB is properly initialized (data buffer and transfer length are set) * - The URB must not already be enqueued * - The pipe must be in the HCD_PIPE_STATE_ACTIVE state + * - The pipe cannot be executing a command * * @param pipe_hdl Pipe handle * @param urb URB to enqueue @@ -514,7 +510,7 @@ urb_t *hcd_urb_dequeue(hcd_pipe_handle_t pipe_hdl); * @brief Abort an enqueued URB * * This function will attempt to abort an URB that is already enqueued. If the URB has yet to be executed, it will be - * "cancelled" and can then be dequeued. If the URB is currenty in-flight or has already completed, the URB will not be + * "canceled" and can then be dequeued. If the URB is currently in-flight or has already completed, the URB will not be * affected by this function. * * @param urb URB to abort diff --git a/components/usb/private_include/hub.h b/components/usb/private_include/hub.h new file mode 100644 index 0000000000..fad62817b8 --- /dev/null +++ b/components/usb/private_include/hub.h @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_err.h" +#include "usb_private.h" +#include "usbh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ Types -------------------------------------------------------- + +/** + * @brief Hub driver configuration + */ +typedef struct { + usb_notif_cb_t notif_cb; /**< Notification callback */ + void *notif_cb_arg; /**< Notification callback argument */ +} hub_config_t; + +// ---------------------------------------------- Hub Driver Functions ------------------------------------------------- + +/** + * @brief Install Hub driver + * + * Entry: + * - USBH must already be installed + * Exit: + * - Install Hub driver memory resources + * - Initializes the HCD root port + * + * @param[in] hub_config Hub driver configuration + * @return esp_err_t + */ +esp_err_t hub_install(hub_config_t *hub_config); + +/** + * @brief Uninstall Hub driver + * + * This must be called before uninstalling the USBH + * Entry: + * - Must have stopped the root port + * Exit: + * - HCD root port deinitialized + * + * @return esp_err_t + */ +esp_err_t hub_uninstall(void); + +/** + * @brief Start the Hub driver's root port + * + * This will power the root port ON + * + * @return esp_err_t + */ +esp_err_t hub_root_start(void); + +/** + * @brief Stops the Hub driver's root port + * + * This will power OFF the root port + * + * @return esp_err_t + */ +esp_err_t hub_root_stop(void); + +/** + * @brief Hub driver's processing function + * + * Hub driver handling function that must be called repeatdly to process the Hub driver's events. If blocking, the + * caller can block on the notification callback of source USB_NOTIF_SOURCE_HUB to run this function. + * + * @return esp_err_t + */ +esp_err_t hub_process(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/private_include/usb.h b/components/usb/private_include/usb.h deleted file mode 100644 index 7c4287ec6e..0000000000 --- a/components/usb/private_include/usb.h +++ /dev/null @@ -1,561 +0,0 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/* -Note: This header file contains the types and macros belong/relate to the USB2.0 protocol and are HW implementation -agnostic. In other words, this header is only meant to be used in the HCD layer and above of the USB Host stack. For -types and macros that are HW implementation specific (i.e., HAL layer and below), add them to the -"hal/usb_types_private.h" header instead. -*/ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define USB_CTRL_REQ_ATTR __attribute__((packed)) -#define USB_DESC_ATTR __attribute__((packed)) - -// ------------------------------------------------ Common USB Types --------------------------------------------------- - -// --------------------- Bus Related ----------------------- - -/** - * @brief USB Standard Speeds - */ -typedef enum { - USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */ - USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ -} usb_speed_t; - -// ------------------ Transfer Related --------------------- - -/** - * @brief The type of USB transfer - * - * @note The enum values need to match the bmAttributes field of an EP descriptor - */ -typedef enum { - USB_TRANSFER_TYPE_CTRL = 0, - USB_TRANSFER_TYPE_ISOCHRONOUS, - USB_TRANSFER_TYPE_BULK, - USB_TRANSFER_TYPE_INTR, -} usb_transfer_type_t; - -/** - * @brief The status of a particular transfer - */ -typedef enum { - USB_TRANSFER_STATUS_COMPLETED, /**< The transfer was successful (but may be short) */ - USB_TRANSFER_STATUS_ERROR, /**< The transfer failed because due to excessive errors (e.g. no response or CRC error) */ - USB_TRANSFER_STATUS_TIMED_OUT, /**< The transfer failed due to a time out */ - USB_TRANSFER_STATUS_CANCELED, /**< The transfer was canceled */ - USB_TRANSFER_STATUS_STALL, /**< The transfer was stalled */ - USB_TRANSFER_STATUS_NO_DEVICE, /**< The transfer failed because the device is no longer valid (e.g., disconnected */ - USB_TRANSFER_STATUS_OVERFLOW, /**< The transfer as more data was sent than was requested */ - USB_TRANSFER_STATUS_SKIPPED, /**< ISOC packets only. The packet was skipped due to system latency or bus overload */ -} usb_transfer_status_t; - - -#define USB_TRANSFER_FLAG_ZERO_PACK 0x01 /**< (For bulk OUT only). Indicates that a bulk OUT transfers should always terminate with a short packet, even if it means adding an extra zero length packet */ - -/** - * @brief Isochronous packet descriptor - * - * If the number of bytes in an Isochronous transfer is larger than the MPS of the endpoint, the transfer is split - * into multiple packets transmitted at the endpoint's specified interval. An array of Isochronous packet descriptors - * describes how an Isochronous transfer should be split into multiple packets. - */ -typedef struct { - int num_bytes; /**< Number of bytes to transmit/receive in the packet */ - int actual_num_bytes; /**< Actual number of bytes transmitted/received in the packet */ - usb_transfer_status_t status; /**< Status of the packet */ -} usb_isoc_packet_desc_t; - -/** - * @brief USB transfer structure - * - * This structure is used to represent a transfer from a software client to an endopint over the USB bus. Some of the - * fields are made const on purpose as they are fixed on allocation. Users should call the appropriate USB Host Driver - * function to allocate a USB transfer structure instead of allocating this structure themselves. - * - * The transfer type is inferred from the endpoint this transfer is sent to. Depending on the transfer type, users - * should note the following: - * - * - Bulk: This structure represents a single bulk transfer. If the number of bytes exceeds the endpoint's MPS, the - * transfer will be split into multiple MPS sized packets followed by a short packet. - * - Control: This structure represents a single control transfer. This first 8 bytes of the data_buffer must be filled - * with the setup packet. The num_bytes field should exclude the size of the setup packet (i.e., set to 0 if - * the control transfer has no data stage). - * - Interrupt: Represents an interrupt transfer. If num_bytes exceeds the MPS of the endpoint, the transfer will be - * split into multiple packets, and each packet is transferred at the endpoint's specified interval. - * - Isochronous: Represents a stream of bytes that should be transferred to an endpoint at a fixed rate. The transfer - * is split into packets according to the each isoc_packet_desc. A packet is transferred at each interval - * of the endpoint. - * - * @note For Bulk/Control/Interrupt IN transfers, the num_bytes must be a integer multiple of the endpoint's MPS - * @note This structure should be allocated via __insert_func_name__() - * @note Once the transfer has be submitted, users should not modify the structure until the transfer has completed - */ -typedef struct usb_transfer_obj usb_transfer_t; - -/** - * @brief USB transfer completion callback - */ -typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer); - -struct usb_transfer_obj{ - uint8_t *const data_buffer; /**< Pointer to data buffer */ - const size_t data_buffer_size; /**< Size of the data buffer in bytes */ - int num_bytes; /**< Number of bytes to transfer. Control transfers should exclude size of setup packet. IN transfers should be integer multiple of MPS */ - int actual_num_bytes; /**< Actual number of bytes transferred */ - uint32_t flags; /**< Transfer flags */ - usb_transfer_status_t status; /**< Status of the transfer */ - uint32_t timeout; /**< Timeout (in milliseconds) of the packet (currently not supported yet) */ - usb_transfer_cb_t callback; /**< Transfer callback */ - void *context; /**< Context variable for transfer to associate transfer with something */ - const int num_isoc_packets; /**< Only relevant to Isochronous. Number of service periods (i.e., intervals) to transfer data buffer over. */ - usb_isoc_packet_desc_t isoc_packet_desc[0]; /**< Descriptors for each Isochronous packet */ -}; - - -// ---------------------------------------------------- Chapter 9 ------------------------------------------------------ - -/** - * @brief Descriptor types from USB2.0 specification table 9.5 - */ -#define USB_B_DESCRIPTOR_TYPE_DEVICE 0x01 -#define USB_B_DESCRIPTOR_TYPE_CONFIGURATION 0x02 -#define USB_B_DESCRIPTOR_TYPE_STRING 0x03 -#define USB_B_DESCRIPTOR_TYPE_INTERFACE 0x04 -#define USB_B_DESCRIPTOR_TYPE_ENDPOINT 0x05 -#define USB_B_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06 -#define USB_B_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07 -#define USB_B_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08 - -/** - * @brief Descriptor types from USB 2.0 ECN - */ -#define USB_B_DESCRIPTOR_TYPE_OTG 0x09 -#define USB_B_DESCRIPTOR_TYPE_DEBUG 0x0a -#define USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b - -/** - * @brief Descriptor types from Wireless USB spec - */ -#define USB_B_DESCRIPTOR_TYPE_SECURITY 0x0c -#define USB_B_DESCRIPTOR_TYPE_KEY 0x0d -#define USB_B_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 0x0e -#define USB_B_DESCRIPTOR_TYPE_BOS 0x0f -#define USB_B_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10 -#define USB_B_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMP 0x11 -#define USB_B_DESCRIPTOR_TYPE_WIRE_ADAPTER 0x21 -#define USB_B_DESCRIPTOR_TYPE_RPIPE 0x22 -#define USB_B_DESCRIPTOR_TYPE_CS_RADIO_CONTROL 0x23 - -/** - * @brief Descriptor types from UAS specification - */ -#define USB_B_DESCRIPTOR_TYPE_PIPE_USAGE 0x24 - -// ------------------- Control Request --------------------- - -/** - * @brief Size of a USB control transfer setup packet in bytes - */ -#define USB_CTRL_REQ_SIZE 8 - -/** - * @brief Structure representing a USB control transfer setup packet - */ -typedef union { - struct { - uint8_t bRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; - } USB_CTRL_REQ_ATTR; - uint8_t val[USB_CTRL_REQ_SIZE]; -} usb_ctrl_req_t; -_Static_assert(sizeof(usb_ctrl_req_t) == USB_CTRL_REQ_SIZE, "Size of usb_ctrl_req_t incorrect"); - -/** - * @brief Bit masks belonging to the bRequestType field of a setup packet - */ -#define USB_B_REQUEST_TYPE_DIR_OUT (0X00 << 7) -#define USB_B_REQUEST_TYPE_DIR_IN (0x01 << 7) -#define USB_B_REQUEST_TYPE_TYPE_STANDARD (0x00 << 5) -#define USB_B_REQUEST_TYPE_TYPE_CLASS (0x01 << 5) -#define USB_B_REQUEST_TYPE_TYPE_VENDOR (0x02 << 5) -#define USB_B_REQUEST_TYPE_TYPE_RESERVED (0x03 << 5) -#define USB_B_REQUEST_TYPE_TYPE_MASK (0x03 << 5) -#define USB_B_REQUEST_TYPE_RECIP_DEVICE (0x00 << 0) -#define USB_B_REQUEST_TYPE_RECIP_INTERFACE (0x01 << 0) -#define USB_B_REQUEST_TYPE_RECIP_ENDPOINT (0x02 << 0) -#define USB_B_REQUEST_TYPE_RECIP_OTHER (0x03 << 0) -#define USB_B_REQUEST_TYPE_RECIP_MASK (0x1f << 0) - -/** - * @brief Bit masks belonging to the bRequest field of a setup packet - */ -#define USB_B_REQUEST_GET_STATUS 0x00 -#define USB_B_REQUEST_CLEAR_FEATURE 0x01 -#define USB_B_REQUEST_SET_FEATURE 0x03 -#define USB_B_REQUEST_SET_ADDRESS 0x05 -#define USB_B_REQUEST_GET_DESCRIPTOR 0x06 -#define USB_B_REQUEST_SET_DESCRIPTOR 0x07 -#define USB_B_REQUEST_GET_CONFIGURATION 0x08 -#define USB_B_REQUEST_SET_CONFIGURATION 0x09 -#define USB_B_REQUEST_GET_INTERFACE 0x0A -#define USB_B_REQUEST_SET_INTERFACE 0x0B -#define USB_B_REQUEST_SYNCH_FRAME 0x0C - -/** - * @brief Bit masks belonging to the wValue field of a setup packet - */ -#define USB_W_VALUE_DT_DEVICE 0x01 -#define USB_W_VALUE_DT_CONFIG 0x02 -#define USB_W_VALUE_DT_STRING 0x03 -#define USB_W_VALUE_DT_INTERFACE 0x04 -#define USB_W_VALUE_DT_ENDPOINT 0x05 -#define USB_W_VALUE_DT_DEVICE_QUALIFIER 0x06 -#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07 -#define USB_W_VALUE_DT_INTERFACE_POWER 0x08 - -/** - * @brief Initializer for a SET_ADDRESS request - * - * Sets the address of a connected device - */ -#define USB_CTRL_REQ_INIT_SET_ADDR(ctrl_req_ptr, addr) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD |USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS; \ - (ctrl_req_ptr)->wValue = (addr); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 0; \ -}) - -/** - * @brief Initializer for a request to get a device's device descriptor - */ -#define USB_CTRL_REQ_INIT_GET_DEVICE_DESC(ctrl_req_ptr) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ - (ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 18; \ -}) - -/** - * @brief Initializer for a request to get a device's current configuration number - */ -#define USB_CTRL_REQ_INIT_GET_CONFIG(ctrl_req_ptr) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION; \ - (ctrl_req_ptr)->wValue = 0; \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 1; \ -}) - -/** - * @brief Initializer for a request to get one of the device's current configuration descriptor - * - * - desc_index indicates the configuration's index number - * - Number of bytes of the configuration descriptor to get - */ -#define USB_CTRL_REQ_INIT_GET_CONFIG_DESC(ctrl_req_ptr, desc_index, desc_len) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ - (ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = (desc_len); \ -}) - -/** - * @brief Initializer for a request to set a device's current configuration number - */ -#define USB_CTRL_REQ_INIT_SET_CONFIG(ctrl_req_ptr, config_num) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION; \ - (ctrl_req_ptr)->wValue = (config_num); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 0; \ -}) - -/** - * @brief Initializer for a request to set an interface's alternate setting - */ -#define USB_CTRL_REQ_INIT_SET_INTERFACE(ctrl_req_ptr, intf_num, alt_setting_num) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_INTERFACE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_INTERFACE; \ - (ctrl_req_ptr)->wValue = (alt_setting_num); \ - (ctrl_req_ptr)->wIndex = (intf_num); \ - (ctrl_req_ptr)->wLength = 0; \ -}) - -// ---------------- Standard Descriptor -------------------- - -/** - * @brief Size of dummy USB standard descriptor - */ -#define USB_DESC_STANDARD_SIZE 2 - -/** - * @brief Dummy USB standard descriptor - * - * All USB standard descriptors start with these two bytes. Use this type traversing over descriptors - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_STANDARD_SIZE]; -} usb_desc_standard_t; -_Static_assert(sizeof(usb_desc_standard_t) == USB_DESC_STANDARD_SIZE, "Size of usb_desc_standard_t incorrect"); - -// ------------------ Device Descriptor -------------------- - -/** - * @brief Size of a USB device descriptor in bytes - */ -#define USB_DESC_DEVICE_SIZE 18 - -/** - * @brief Structure representing a USB device descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_DEVICE_SIZE]; -} usb_desc_device_t; -_Static_assert(sizeof(usb_desc_device_t) == USB_DESC_DEVICE_SIZE, "Size of usb_desc_device_t incorrect"); - -/** - * @brief Possible base class values of the bDeviceClass field of a USB device descriptor - */ -#define USB_CLASS_PER_INTERFACE 0x00 -#define USB_CLASS_AUDIO 0x01 -#define USB_CLASS_COMM 0x02 -#define USB_CLASS_HID 0x03 -#define USB_CLASS_PHYSICAL 0x05 -#define USB_CLASS_STILL_IMAGE 0x06 -#define USB_CLASS_PRINTER 0x07 -#define USB_CLASS_MASS_STORAGE 0x08 -#define USB_CLASS_HUB 0x09 -#define USB_CLASS_CDC_DATA 0x0a -#define USB_CLASS_CSCID 0x0b -#define USB_CLASS_CONTENT_SEC 0x0d -#define USB_CLASS_VIDEO 0x0e -#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 -#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f -#define USB_CLASS_AUDIO_VIDEO 0x10 -#define USB_CLASS_BILLBOARD 0x11 -#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12 -#define USB_CLASS_MISC 0xef -#define USB_CLASS_APP_SPEC 0xfe -#define USB_CLASS_VENDOR_SPEC 0xff - -/** - * @brief Vendor specific subclass code - */ -#define USB_SUBCLASS_VENDOR_SPEC 0xff - -// -------------- Configuration Descriptor ----------------- - -/** - * @brief Size of a short USB configuration descriptor in bytes - * - * @note The size of a full USB configuration includes all the interface and endpoint - * descriptors of that configuration. - */ -#define USB_DESC_CONFIG_SIZE 9 - -/** - * @brief Structure representing a short USB configuration descriptor - * - * @note The full USB configuration includes all the interface and endpoint - * descriptors of that configuration. - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_CONFIG_SIZE]; -} usb_desc_config_t; -_Static_assert(sizeof(usb_desc_config_t) == USB_DESC_CONFIG_SIZE, "Size of usb_desc_config_t incorrect"); - -/** - * @brief Bit masks belonging to the bmAttributes field of a configuration descriptor - */ -#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set -#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered -#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wake-up -#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered - -// ---------- Interface Association Descriptor ------------- - -/** - * @brief Size of a USB interface association descriptor in bytes - */ -#define USB_DESC_INTF_ASSOC_SIZE 9 - -/** - * @brief Structure representing a USB interface association descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bFirstInterface; - uint8_t bInterfaceCount; - uint8_t bFunctionClass; - uint8_t bFunctionSubClass; - uint8_t bFunctionProtocol; - uint8_t iFunction; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_INTF_ASSOC_SIZE]; -} usb_desc_iad_t; -_Static_assert(sizeof(usb_desc_iad_t) == USB_DESC_INTF_ASSOC_SIZE, "Size of usb_desc_iad_t incorrect"); - -// ---------------- Interface Descriptor ------------------- - -/** - * @brief Size of a USB interface descriptor in bytes - */ -#define USB_DESC_INTF_SIZE 9 - -/** - * @brief Structure representing a USB interface descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_INTF_SIZE]; -} usb_desc_intf_t; -_Static_assert(sizeof(usb_desc_intf_t) == USB_DESC_INTF_SIZE, "Size of usb_desc_intf_t incorrect"); - -// ----------------- Endpoint Descriptor ------------------- - -/** - * @brief Size of a USB endpoint descriptor in bytes - */ -#define USB_DESC_EP_SIZE 7 - -/** - * @brief Structure representing a USB endpoint descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_EP_SIZE]; -} usb_desc_ep_t; -_Static_assert(sizeof(usb_desc_ep_t) == USB_DESC_EP_SIZE, "Size of usb_desc_ep_t incorrect"); - -/** - * @brief Bit masks belonging to the bEndpointAddress field of an endpoint descriptor - */ -#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f -#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80 - -/** - * @brief Bit masks belonging to the bmAttributes field of an endpoint descriptor - */ -#define USB_BM_ATTRIBUTES_XFERTYPE_MASK 0x03 -#define USB_BM_ATTRIBUTES_XFER_CONTROL (0 << 0) -#define USB_BM_ATTRIBUTES_XFER_ISOC (1 << 0) -#define USB_BM_ATTRIBUTES_XFER_BULK (2 << 0) -#define USB_BM_ATTRIBUTES_XFER_INT (3 << 0) -#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK 0x0C /* in bmAttributes */ -#define USB_BM_ATTRIBUTES_SYNC_NONE (0 << 2) -#define USB_BM_ATTRIBUTES_SYNC_ASYNC (1 << 2) -#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE (2 << 2) -#define USB_BM_ATTRIBUTES_SYNC_SYNC (3 << 2) -#define USB_BM_ATTRIBUTES_USAGETYPE_MASK 0x30 -#define USB_BM_ATTRIBUTES_USAGE_DATA (0 << 4) -#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK (1 << 4) -#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB (2 << 4) - -/** - * @brief Macro helpers to get information about an endpoint from its descriptor - */ -#define USB_DESC_EP_GET_XFERTYPE(desc_ptr) ((usb_transfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK)) -#define USB_DESC_EP_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) -#define USB_DESC_EP_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0) -#define USB_DESC_EP_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF) - -// ------------------ String Descriptor -------------------- - -/** - * @brief Size of a short USB string descriptor in bytes - */ -#define USB_DESC_STR_SIZE 4 - -/** - * @brief Structure representing a USB string descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wData[1]; /* UTF-16LE encoded */ - } USB_DESC_ATTR; - uint8_t val[USB_DESC_STR_SIZE]; -} usb_desc_str_t; -_Static_assert(sizeof(usb_desc_str_t) == USB_DESC_STR_SIZE, "Size of usb_desc_str_t incorrect"); - -#ifdef __cplusplus -} -#endif diff --git a/components/usb/private_include/usb_private.h b/components/usb/private_include/usb_private.h index f3b0eaac38..b245970b54 100644 --- a/components/usb/private_include/usb_private.h +++ b/components/usb/private_include/usb_private.h @@ -1,34 +1,32 @@ -// Copyright 2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include +#include #include #include -#include "usb.h" +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" #ifdef __cplusplus extern "C" { #endif +// ------------------------------------------------------ Types -------------------------------------------------------- + typedef struct { uint8_t *data_buffer; size_t data_buffer_size; int num_bytes; int actual_num_bytes; uint32_t flags; + usb_device_handle_t device_handle; + uint8_t bEndpointAddress; usb_transfer_status_t status; uint32_t timeout; usb_transfer_cb_t callback; @@ -38,17 +36,49 @@ typedef struct { } usb_transfer_dummy_t; _Static_assert(sizeof(usb_transfer_dummy_t) == sizeof(usb_transfer_t), "usb_transfer_dummy_t does not match usb_transfer_t"); -struct urb_obj{ - TAILQ_ENTRY(urb_obj) tailq_entry; - //HCD context pointer and variables. Must be initialized to NULL and 0 respectively +struct urb_s{ + TAILQ_ENTRY(urb_s) tailq_entry; + //HCD handler pointer and variables. Must be initialized to NULL and 0 respectively void *hcd_ptr; uint32_t hcd_var; - //Host Driver layer will add its fields here. + //Host Driver layer handler + void *usb_host_client; //Currently only used when submitted to shared pipes (i.e., Device default pipes) + size_t usb_host_header_size; //USB Host may need the data buffer to have a transparent header //Public transfer structure. Must be last due to variable length array usb_transfer_t transfer; }; +typedef struct urb_s urb_t; -typedef struct urb_obj urb_t; +typedef enum { + USB_NOTIF_SOURCE_USBH = 0x01, + USB_NOTIF_SOURCE_HUB = 0x02, +} usb_notif_source_t; + +typedef bool (*usb_notif_cb_t)(usb_notif_source_t source, bool in_isr, void *context); + +// --------------------------------------------------- Allocation ------------------------------------------------------ + +/** + * @brief Allocate a URB + * + * - Data buffer is allocated in DMA capable memory + * - The constant fields of the URB are also set + * - The data_buffer field of the URB is set to point to start of the allocated data buffer AFTER the header. To access + * the header, users need a negative offset from data_buffer. + * + * @param data_buffer_size Size of the URB's data buffer + * @param header_size Size of header to put in front of URB's data buffer + * @param num_isoc_packets Number of isochronous packet descriptors + * @return urb_t* URB object + */ +urb_t *urb_alloc(size_t data_buffer_size, size_t header_size, int num_isoc_packets); + +/** + * @brief Free a URB + * + * @param urb URB object + */ +void urb_free(urb_t *urb); #ifdef __cplusplus } diff --git a/components/usb/private_include/usbh.h b/components/usb/private_include/usbh.h new file mode 100644 index 0000000000..924646fc48 --- /dev/null +++ b/components/usb/private_include/usbh.h @@ -0,0 +1,383 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "hcd.h" +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ Types -------------------------------------------------------- + +// ----------------------- Events -------------------------- + +typedef enum { + USBH_EVENT_DEV_NEW, /**< A new device has been enumerated and added to the device pool */ + USBH_EVENT_DEV_GONE, /**< A device is gone. Clients should close the device */ + USBH_EVENT_DEV_ALL_FREE, /**< All devices have been freed */ +} usbh_event_t; + +typedef enum { + USBH_HUB_EVENT_CLEANUP_PORT, /**< Indicate to the Hub driver that it should clean up the port of a device (occurs after a gone device has been freed) */ + USBH_HUB_EVENT_DISABLE_PORT, /**< Indicate to the Hub driver that it should disable the port of a device (occurs after a device has been freed) */ +} usbh_hub_event_t; + +// ---------------------- Callbacks ------------------------ + +/** + * @brief Callback used to indicate completion of control transfers submitted usbh_dev_submit_ctrl_urb() + * @note This callback is called from within usbh_process() + */ +typedef void (*usbh_ctrl_xfer_cb_t)(usb_device_handle_t dev_hdl, urb_t *urb, void *arg); + +/** + * @brief Callback used to indicate that the USBH has an event + * + * @note This callback is called from within usbh_process() + * @note On a USBH_EVENT_DEV_ALL_FREE event, the dev_hdl argument is set to NULL + */ +typedef void (*usbh_event_cb_t)(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg); + +/** + * @brief Callback used by the USBH to request actions from the Hub driver + * @note This callback is called from within usbh_process() + */ +typedef void (*usbh_hub_cb_t)(hcd_port_handle_t port_hdl, usbh_hub_event_t hub_event, void *arg); + +// ----------------------- Objects ------------------------- + +/** + * @brief Configuration for an endpoint being allocated using usbh_ep_alloc() + */ +typedef struct { + const usb_ep_desc_t *ep_desc; /**< Endpoint descriptor */ + hcd_pipe_callback_t pipe_cb; /**< Endpoint's pipe callback */ + void *pipe_cb_arg; /**< Pipe callback argument */ + void *context; /**< Pipe context */ +} usbh_ep_config_t; + +/** + * @brief USBH configuration used in usbh_install() + */ +typedef struct { + usb_notif_cb_t notif_cb; /**< Notification callback */ + void *notif_cb_arg; /**< Notification callback argument */ + usbh_ctrl_xfer_cb_t ctrl_xfer_cb; /**< Control transfer callback */ + void *ctrl_xfer_cb_arg; /**< Control transfer callback argument */ + usbh_event_cb_t event_cb; /**< USBH event callback */ + void *event_cb_arg; /**< USBH event callback argument */ + hcd_config_t hcd_config; /**< HCD configuration */ +} usbh_config_t; + +// ------------------------------------------------- USBH Functions ---------------------------------------------------- + +/** + * @brief Installs the USBH driver + * + * - This function will internally install the HCD + * - This must be called before calling any Hub driver functions + * + * @param usbh_config USBH driver configuration + * @return esp_err_t + */ +esp_err_t usbh_install(const usbh_config_t *usbh_config); + +/** + * @brief Uninstall the USBH driver + * + * - This function will uninstall the HCD + * - The Hub driver must be uninstalled before calling this function + * + * @return esp_err_t + */ +esp_err_t usbh_uninstall(void); + +/** + * @brief USBH processing function + * + * - USBH processing function that must be called repeatedly to process USBH events + * - If blocking, the caller can block until a USB_NOTIF_SOURCE_USBH notification is received before running this + * function + * + * @return esp_err_t + */ +esp_err_t usbh_process(void); + +// ------------------------------------------------ Device Functions --------------------------------------------------- + +// --------------------- Device Pool ----------------------- + +/** + * @brief Open a device by address + * + * A device must be opened before it can be used + * + * @param[in] dev_addr Device address + * @param[out] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl); + +/** + * @brief CLose a device + * + * Device can be opened by calling usbh_dev_open() + * + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl); + +/** + * @brief Mark that all devices should be freed at the next possible opportunity + * + * A device marked as free will not be freed until the last client using the device has called usbh_dev_close() + * + * @return esp_err_t + */ +esp_err_t usbh_dev_mark_all_free(void); + +// ------------------- Single Device ---------------------- + +/** + * @brief Get a device's address + * + * @note Can be called without opening the device + * + * @param[in] dev_hdl Device handle + * @param[out] dev_addr Device's address + * @return esp_err_t + */ +esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr); + +/** + * @brief Get a device's information + * + * @param[in] dev_hdl Device handle + * @param[out] dev_info Device information + * @return esp_err_t + */ +esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info); + +/** + * @brief Get a device's device descriptor + * + * - The device descriptor is cached when the device is created by the Hub driver + * + * @param[in] dev_hdl Device handle + * @param[out] dev_desc_ret Device descriptor + * @return esp_err_t + */ +esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t **dev_desc_ret); + +/** + * @brief Get a device's active configuration descriptor + * + * Simply returns a reference to the internally cached configuration descriptor + * + * @param[in] dev_hdl Device handle + * @param config_desc_ret + * @return esp_err_t + */ +esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc_ret); + +/** + * @brief Submit a control transfer (URB) to a device + * + * @param[in] dev_hdl Device handle + * @param[in] urb URB + * @return esp_err_t + */ +esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb); + +// ----------------------------------------------- Endpoint Functions ------------------------------------------------- + +/** + * @brief Allocate an endpoint on a device + * + * Clients that have opened a device must call this function to allocate all endpoints in an interface that is claimed. + * The pipe handle of the endpoint is returned so that clients can use and control the pipe directly. + * + * @note Default pipes are owned by the USBH. For control transfers, use usbh_dev_submit_ctrl_urb() instead + * @note Device must be opened by the client first + * + * @param[in] dev_hdl Device handle + * @param[in] ep_config + * @param[out] pipe_hdl_ret Pipe handle + * @return esp_err_t + */ +esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config, hcd_pipe_handle_t *pipe_hdl_ret); + +/** + * @brief Free and endpoint on a device + * + * Free an endpoint previously opened by usbh_ep_alloc() + * + * @param[in] dev_hdl Device handle + * @param[in] bEndpointAddress Endpoint's address + * @return esp_err_t + */ +esp_err_t usbh_ep_free(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +/** + * @brief Get the context of an endpoint + * + * Get the context variable assigned to and endpoint on allocation. + * + * @param[in] dev_hdl Device handle + * @param[in] bEndpointAddress Endpoint's address + * @param[out] context_ret Context variable + * @return esp_err_t + */ +esp_err_t usbh_ep_get_context(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, void **context_ret); + +// -------------------------------------------------- Hub Functions ---------------------------------------------------- + +// ------------------- Device Related ---------------------- + +/** + * @brief Indicates to USBH that the Hub driver is installed + * + * - The Hub driver must call this function in its installation to indicate the the USBH that it has been installed. + * - This should only be called after the USBH has already be installed + * + * @note Hub Driver only + * @param[in] hub_callback Hub callback + * @param[in] callback_arg Callback argument + * @return esp_err_t + */ +esp_err_t usbh_hub_is_installed(usbh_hub_cb_t hub_callback, void *callback_arg); + +/** + * @brief Indicates to USBH the start of enumeration for a device + * + * - The Hub driver calls this function before it starts enumerating a new device. + * - The USBH will allocate a new device that will be initialized by the Hub driver using the remaining hub enumeration + * functions. + * - The new device's default pipe handle is returned to all the Hub driver to be used during enumeration. + * + * @note Hub Driver only + * @param[in] port_hdl Handle of the port that the device is connected to + * @param[in] dev_speed Device's speed + * @param[out] new_dev_hdl Device's handle + * @param[out] default_pipe_hdl Device's default pipe handle + * @return esp_err_t + */ +esp_err_t usbh_hub_add_dev(hcd_port_handle_t port_hdl, usb_speed_t dev_speed, usb_device_handle_t *new_dev_hdl, hcd_pipe_handle_t *default_pipe_hdl); + +/** + * @brief Indicate that a device is gone + * + * This Hub driver must call this function to indicate that a device is gone. A device is gone when: + * - It suddenly disconnects + * - Its upstream port or device has an error or is also gone. + * Marking a device as gone will: + * - Trigger a USBH_EVENT_DEV_GONE + * - Prevent further transfers to the device + * - Trigger the device's cleanup if it is already closed + * - When the last client closes the device via usbh_dev_close(), the device's resources will be cleaned up + * + * @note Hub Driver only + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_mark_dev_gone(usb_device_handle_t dev_hdl); + +/** + * @brief Indicate that a device's port has been disabled + * + * - The Hub driver must call this function once it has disabled the port of a particular device + * - The Hub driver disables a device's port when requested by the USBH via the USBH_HUB_EVENT_DISABLE_PORT + * - This function will trigger the device's cleanup. + * + * @note Hub Driver only + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_dev_port_disabled(usb_device_handle_t dev_hdl); + +// ----------------- Enumeration Related ------------------- + +/** + * @brief Fill the enumerating device's descriptor + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param device_desc + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_dev_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t *device_desc); + +/** + * @brief Assign the enumerating device's address + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param dev_addr + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_dev_addr(usb_device_handle_t dev_hdl, uint8_t dev_addr); + +/** + * @brief Fill the enumerating device's active configuration descriptor + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param config_desc_full + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc_full); + +/** + * @brief Assign the enumerating device's active configuration number + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param bConfigurationValue + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_config_num(usb_device_handle_t dev_hdl, uint8_t bConfigurationValue); + +/** + * @brief Indicate the device enumeration is completed + * + * This will all the device to be opened by clients, and also trigger a USBH_EVENT_DEV_NEW event. + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_done(usb_device_handle_t dev_hdl); + +/** + * @brief Indicate that device enumeration has failed + * + * This will cause the enumerating device's resources to be cleaned up + * The Hub Driver must guarantee that the enumerating device's default pipe is already halted, flushed, and dequeued. + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_failed(usb_device_handle_t dev_hdl); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/test/CMakeLists.txt b/components/usb/test/CMakeLists.txt index b2b31a2bec..7857c7ee66 100644 --- a/components/usb/test/CMakeLists.txt +++ b/components/usb/test/CMakeLists.txt @@ -5,7 +5,8 @@ if(NOT "${target}" MATCHES "^esp32s[2-3]") return() endif() -idf_component_register(SRC_DIRS "common" "hcd" - PRIV_INCLUDE_DIRS "../private_include" "common" "hcd" +idf_component_register( + SRC_DIRS "common" "hcd" "usb_host" + PRIV_INCLUDE_DIRS "../private_include" "common" "hcd" "usb_host" PRIV_REQUIRES cmock usb test_utils ) diff --git a/components/usb/test/common/test_usb_mock_classes.c b/components/usb/test/common/test_usb_mock_classes.c index cadf33d9a8..f3d7d42d8e 100644 --- a/components/usb/test/common/test_usb_mock_classes.c +++ b/components/usb/test/common/test_usb_mock_classes.c @@ -15,7 +15,7 @@ #include #include #include -#include "usb.h" +#include "usb/usb_types_ch9.h" #include "test_usb_mock_classes.h" // ---------------------------------------------------- MSC SCSI ------------------------------------------------------- diff --git a/components/usb/test/common/test_usb_mock_classes.h b/components/usb/test/common/test_usb_mock_classes.h index 77352b3bcf..6c80b076c1 100644 --- a/components/usb/test/common/test_usb_mock_classes.h +++ b/components/usb/test/common/test_usb_mock_classes.h @@ -21,7 +21,7 @@ Host stack. #include #include -#include "usb.h" +#include "usb/usb_types_ch9.h" #ifdef __cplusplus extern "C" { @@ -94,8 +94,8 @@ Configuration Descriptor: If you're using a flash driver with different endpoints, modify the endpoint descriptors below. */ -static const usb_desc_ep_t mock_msc_scsi_bulk_out_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = 0x01, //EP 1 OUT .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, @@ -103,8 +103,8 @@ static const usb_desc_ep_t mock_msc_scsi_bulk_out_ep_desc = { .bInterval = 1, }; -static const usb_desc_ep_t mock_msc_scsi_bulk_in_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = 0x82, //EP 2 IN .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, @@ -123,12 +123,12 @@ static const usb_desc_ep_t mock_msc_scsi_bulk_in_ep_desc = { #define MOCK_MSC_SCSI_BULK_IN_EP_ADDR 0x82 #define MOCK_MSC_SCSI_BULK_EP_MPS 64 -#define MOCK_MSC_SCSI_REQ_INIT_RESET(ctrl_req_ptr, intf_num) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_CLASS | USB_B_REQUEST_TYPE_RECIP_INTERFACE; \ - (ctrl_req_ptr)->bRequest = 0xFF; \ - (ctrl_req_ptr)->wValue = 0; \ - (ctrl_req_ptr)->wIndex = (intf_num); \ - (ctrl_req_ptr)->wLength = 0; \ +#define MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt_ptr, intf_num) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_CLASS | USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \ + (setup_pkt_ptr)->bRequest = 0xFF; \ + (setup_pkt_ptr)->wValue = 0; \ + (setup_pkt_ptr)->wIndex = (intf_num); \ + (setup_pkt_ptr)->wLength = 0; \ }) typedef struct __attribute__((packed)) { @@ -193,21 +193,67 @@ Note: The mock HID mouse tests require that USB low speed mouse be connected. Th - Be implement the HID with standard report format used by mice - It's configuration 1 should have the following endpoint -Endpoint Descriptor: - bLength 7 - bDescriptorType 5 - bEndpointAddress 0x81 EP 1 IN - bmAttributes 3 - Transfer Type Interrupt - Synch Type None - Usage Type Data - wMaxPacketSize 0x0004 1x 4 bytes - bInterval 10 +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x413c Dell Computer Corp. + idProduct 0x301a + bcdDevice 1.00 + iManufacturer 1 + iProduct 2 + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0022 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xa0 + (Bus Powered) + Remote Wakeup + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 3 Human Interface Device + bInterfaceSubClass 1 Boot Interface Subclass + bInterfaceProtocol 2 Mouse + iInterface 0 + HID Device Descriptor: + bLength 9 + bDescriptorType 33 + bcdHID 1.11 + bCountryCode 0 Not supported + bNumDescriptors 1 + bDescriptorType 34 Report + wDescriptorLength 46 + Report Descriptors: + ** UNAVAILABLE ** + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0004 1x 4 bytes + bInterval 10 If you're using another mice with different endpoints, modify the endpoint descriptor below */ -static const usb_desc_ep_t mock_hid_mouse_in_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_hid_mouse_in_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = 0x81, //EP 1 IN .bmAttributes = USB_BM_ATTRIBUTES_XFER_INT, @@ -215,6 +261,14 @@ static const usb_desc_ep_t mock_hid_mouse_in_ep_desc = { .bInterval = 10, //Interval of 10ms }; +#define MOCK_HID_MOUSE_DEV_ID_VENDOR 0x413C +#define MOCK_HID_MOUSE_DEV_ID_PRODUCT 0x301A +#define MOCK_HID_MOUSE_DEV_DFLT_EP_MPS 8 +#define MOCK_HID_MOUSE_INTF_NUMBER 0 +#define MOCK_HID_MOUSE_INTF_ALT_SETTING 0 +#define MOCK_HID_MOUSE_INTR_IN_EP_ADDR 0x81 +#define MOCK_HID_MOUSE_INTR_IN_MPS 0x04 + typedef union { struct { uint32_t left_button: 1; @@ -241,8 +295,8 @@ ISOC, transferring to a non-existent endpoint should work. The non-existent endp #define MOCK_ISOC_EP_MPS 512 -static const usb_desc_ep_t mock_isoc_out_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_isoc_out_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = MOCK_ISOC_EP_NUM, .bmAttributes = USB_BM_ATTRIBUTES_XFER_ISOC, diff --git a/components/usb/test/hcd/test_hcd_bulk.c b/components/usb/test/hcd/test_hcd_bulk.c index aef531a046..e1bd189c27 100644 --- a/components/usb/test/hcd/test_hcd_bulk.c +++ b/components/usb/test/hcd/test_hcd_bulk.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -26,10 +18,10 @@ static void mock_msc_reset_req(hcd_pipe_handle_t default_pipe) { //Create URB - urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_ctrl_req_t)); - usb_ctrl_req_t *ctrl_req = (usb_ctrl_req_t *)urb->transfer.data_buffer; - MOCK_MSC_SCSI_REQ_INIT_RESET(ctrl_req, MOCK_MSC_SCSI_INTF_NUMBER); - urb->transfer.num_bytes = 0; + urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_setup_packet_t)); + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)urb->transfer.data_buffer; + MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt, MOCK_MSC_SCSI_INTF_NUMBER); + urb->transfer.num_bytes = sizeof(usb_setup_packet_t); //Enqueue, wait, dequeue, and check URB TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); diff --git a/components/usb/test/hcd/test_hcd_common.c b/components/usb/test/hcd/test_hcd_common.c index 2bf815b47b..93a22d8fd9 100644 --- a/components/usb/test/hcd/test_hcd_common.c +++ b/components/usb/test/hcd/test_hcd_common.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -26,7 +18,7 @@ #include "soc/usb_wrap_struct.h" #include "hcd.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" #include "test_hcd_common.h" #define PORT_NUM 1 @@ -174,6 +166,7 @@ hcd_port_handle_t test_hcd_setup(void) TEST_ASSERT_EQUAL(ESP_OK, hcd_install(&hcd_config)); //Initialize a port hcd_port_config_t port_config = { + .fifo_bias = HCD_PORT_FIFO_BIAS_BALANCED, .callback = port_callback, .callback_arg = (void *)port_evt_queue, .context = (void *)port_evt_queue, @@ -237,7 +230,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled test_hcd_force_conn_state(false, pdMS_TO_TICKS(100)); //Force disconnected state on PHY test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); - TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl)); + TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); //Power down the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl)); @@ -245,7 +238,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled // ---------------------------------------------- Pipe Setup/Tear-down ------------------------------------------------- -hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_desc_ep_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed) +hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_desc_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed) { //Create a queue for pipe callback to queue up pipe events QueueHandle_t pipe_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(pipe_event_msg_t)); @@ -300,24 +293,24 @@ void test_hcd_free_urb(urb_t *urb) uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe) { //We need to create a URB for the enumeration control transfers - urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_ctrl_req_t) + 256); - usb_ctrl_req_t *ctrl_req = (usb_ctrl_req_t *)urb->transfer.data_buffer; + urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_setup_packet_t) + 256); + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)urb->transfer.data_buffer; //Get the device descriptor (note that device might only return 8 bytes) - USB_CTRL_REQ_INIT_GET_DEVICE_DESC(ctrl_req); - urb->transfer.num_bytes = sizeof(usb_desc_device_t); + USB_SETUP_PACKET_INIT_GET_DEVICE_DESC(setup_pkt); + urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); //Update the MPS of the default pipe - usb_desc_device_t *device_desc = (usb_desc_device_t *)(urb->transfer.data_buffer + sizeof(usb_ctrl_req_t)); + usb_device_desc_t *device_desc = (usb_device_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_update_mps(default_pipe, device_desc->bMaxPacketSize0)); //Send a set address request - USB_CTRL_REQ_INIT_SET_ADDR(ctrl_req, ENUM_ADDR); //We only support one device for now so use address 1 - urb->transfer.num_bytes = 0; + USB_SETUP_PACKET_INIT_SET_ADDR(setup_pkt, ENUM_ADDR); //We only support one device for now so use address 1 + urb->transfer.num_bytes = sizeof(usb_setup_packet_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); @@ -327,8 +320,8 @@ uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe) TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_update_dev_addr(default_pipe, ENUM_ADDR)); //Send a set configuration request - USB_CTRL_REQ_INIT_SET_CONFIG(ctrl_req, ENUM_CONFIG); - urb->transfer.num_bytes = 0; + USB_SETUP_PACKET_INIT_SET_CONFIG(setup_pkt, ENUM_CONFIG); + urb->transfer.num_bytes = sizeof(usb_setup_packet_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); diff --git a/components/usb/test/hcd/test_hcd_common.h b/components/usb/test/hcd/test_hcd_common.h index 1d9dac14a2..493b95dc24 100644 --- a/components/usb/test/hcd/test_hcd_common.h +++ b/components/usb/test/hcd/test_hcd_common.h @@ -1,22 +1,14 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "hcd.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" #define URB_CONTEXT_VAL ((void *)0xDEADBEEF) @@ -109,7 +101,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled * @param dev_speed Device speed of the pipe * @return hcd_pipe_handle_t Pipe handle */ -hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_desc_ep_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed); +hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_desc_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed); /** * @brief Test the freeing of a pipe diff --git a/components/usb/test/hcd/test_hcd_ctrl.c b/components/usb/test/hcd/test_hcd_ctrl.c index fe29db4374..678de453ca 100644 --- a/components/usb/test/hcd/test_hcd_ctrl.c +++ b/components/usb/test/hcd/test_hcd_ctrl.c @@ -22,7 +22,7 @@ #define TEST_DEV_ADDR 0 #define NUM_URBS 3 #define TRANSFER_MAX_BYTES 256 -#define URB_DATA_BUFF_SIZE (sizeof(usb_ctrl_req_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors /* Test HCD control pipe URBs (normal completion and early abort) @@ -54,8 +54,8 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } @@ -68,20 +68,20 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); } - //Dequeue URBs + //Dequeue URBs, check, and print for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType); + printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); } - //Print config desc - for (int i = 0; i < urb_list[0]->transfer.actual_num_bytes; i++) { - printf("%d\t0x%x\n", i, urb_list[0]->transfer.data_buffer[sizeof(usb_ctrl_req_t) + i]); - } - - //Enqueue URBs again but abort them short after for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); @@ -98,8 +98,11 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") //No need to check for URB pointer address as they may be out of order TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(urb->transfer.context, URB_CONTEXT_VAL); @@ -119,8 +122,8 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") Test HCD control pipe STALL condition, abort, and clear Purpose: - - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_HALTED event) - - The HCD_PIPE_CMD_ABORT can retire all URBs + - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_ERROR_STALL event) + - The HCD_PIPE_CMD_FLUSH can retire all URBs - Pipe clear command can return the pipe to being active Procedure: @@ -128,7 +131,7 @@ Procedure: - Setup default pipe and allocate URBs - Corrupt the first URB so that it will trigger a STALL, then enqueue all the URBs - Check that a HCD_PIPE_EVENT_ERROR_STALL event is triggered - - Check that all URBs can be retired using HCD_PIPE_CMD_ABORT + - Check that all URBs can be retired using HCD_PIPE_CMD_FLUSH, a HCD_PIPE_EVENT_URB_DONE event should be generated - Check that the STALL can be cleared by using HCD_PIPE_CMD_CLEAR - Fix the corrupt first URB and retry the URBs - Dequeue URBs @@ -146,12 +149,12 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } //Corrupt the first URB so that it triggers a STALL - ((usb_ctrl_req_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA; + ((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA; //Enqueue URBs. A STALL should occur int num_enqueued = 0; @@ -168,14 +171,18 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); //Call the pipe abort command to retire all URBs then dequeue them all - TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_ABORT)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); for (int i = 0; i < num_enqueued; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_STALL || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); @@ -187,7 +194,7 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") printf("Retrying\n"); //Correct first URB then requeue - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } @@ -199,8 +206,13 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType); + printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); } //Free URB list and pipe @@ -224,9 +236,10 @@ Purpose: Procedure: - Setup HCD and wait for connection - Setup default pipe and allocate URBs - - Enqqueue URBs but execute a HCD_PIPE_CMD_HALT command immediately after. Halt command should let on - the current going URB finish before actually halting the pipe. - - Un-halt the pipe a HCD_PIPE_CMD_HALT command. Enqueued URBs will be resumed + - Enqqueue URBs but execute a HCD_PIPE_CMD_HALT command immediately after. + - Halt command should immediately halt the current URB and generate a HCD_PIPE_EVENT_URB_DONE + - Other pending URBs should be untouched. + - Un-halt the pipe using a HCD_PIPE_CMD_CLEAR command. Enqueued URBs will be resumed - Check that all URBs have completed successfully - Dequeue URBs and teardown */ @@ -242,8 +255,8 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } @@ -253,6 +266,7 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]") TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); printf("Pipe halted\n"); @@ -264,11 +278,20 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]") //Wait for each URB to be done, dequeue, and check results for (int i = 0; i < NUM_URBS; i++) { - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); + if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType); + printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); + } else { + //A failed transfer should 0 actual number of bytes transmitted + TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); + } TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); } diff --git a/components/usb/test/hcd/test_hcd_intr.c b/components/usb/test/hcd/test_hcd_intr.c index b4de2042c5..1e6f01cbd4 100644 --- a/components/usb/test/hcd/test_hcd_intr.c +++ b/components/usb/test/hcd/test_hcd_intr.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "freertos/FreeRTOS.h" diff --git a/components/usb/test/hcd/test_hcd_isoc.c b/components/usb/test/hcd/test_hcd_isoc.c index d421d926ee..cb9dbec971 100644 --- a/components/usb/test/hcd/test_hcd_isoc.c +++ b/components/usb/test/hcd/test_hcd_isoc.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -65,7 +57,7 @@ TEST_CASE("Test HCD isochronous pipe URBs", "[hcd][ignore]") //Initialize URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { urb_list[urb_idx] = test_hcd_alloc_urb(NUM_PACKETS_PER_URB, URB_DATA_BUFF_SIZE); - urb_list[urb_idx]->transfer.num_bytes = 0; //num_bytes is not used for ISOC + urb_list[urb_idx]->transfer.num_bytes = URB_DATA_BUFF_SIZE; urb_list[urb_idx]->transfer.context = URB_CONTEXT_VAL; for (int pkt_idx = 0; pkt_idx < NUM_PACKETS_PER_URB; pkt_idx++) { urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = ISOC_PACKET_SIZE; diff --git a/components/usb/test/hcd/test_hcd_port.c b/components/usb/test/hcd/test_hcd_port.c index 5d2c56f8ab..e7267de5f1 100644 --- a/components/usb/test/hcd/test_hcd_port.c +++ b/components/usb/test/hcd/test_hcd_port.c @@ -1,43 +1,40 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "unity.h" +#include "esp_rom_sys.h" #include "test_utils.h" #include "test_hcd_common.h" #define TEST_DEV_ADDR 0 #define NUM_URBS 3 #define TRANSFER_MAX_BYTES 256 -#define URB_DATA_BUFF_SIZE (sizeof(usb_ctrl_req_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define POST_ENQUEUE_DELAY_US 10 /* Test a port sudden disconnect and port recovery Purpose: Test that when sudden disconnection happens on an HCD port, the port will - Generate the HCD_PORT_EVENT_SUDDEN_DISCONN and be put into the HCD_PORT_STATE_RECOVERY state - - Ongoing URBs and pipes are handled correctly + - Pipes can be halted and flushed after a port error Procedure: - Setup the HCD and a port - Trigger a port connection - Create a default pipe - - Start transfers but immediately trigger a disconnect - - Check that HCD_PORT_EVENT_SUDDEN_DISCONN event is generated. Handle the event. - - Check that default pipe received a HCD_PIPE_EVENT_INVALID event. Pipe state should be invalid. Dequeue URBs + - Start transfers but trigger a disconnect after a short delay + - Check that HCD_PORT_EVENT_SUDDEN_DISCONN event is generated. Handle that port event. + - Check that the default pipe remains in the HCD_PIPE_STATE_ACTIVE after the port error. + - Check that the default pipe can be halted, a HCD_PIPE_EVENT_URB_DONE event should be generated + - Check that the default pipe can be flushed, a HCD_PIPE_EVENT_URB_DONE event should be generated + - Check that all URBs can be dequeued. - Free default pipe - Recover the port - Trigger connection and disconnection again (to make sure the port works post recovery) @@ -56,8 +53,8 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } @@ -66,29 +63,35 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } + //Add a short delay to let the transfers run for a bit + esp_rom_delay_us(POST_ENQUEUE_DELAY_US); test_hcd_force_conn_state(false, 0); //Disconnect event should have occurred. Handle the event - test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_SUDDEN_DISCONN); - TEST_ASSERT_EQUAL(HCD_PORT_EVENT_SUDDEN_DISCONN, hcd_port_handle_event(port_hdl)); + test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); + TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); printf("Sudden disconnect\n"); - //Pipe should have received (zero or more HCD_PIPE_EVENT_URB_DONE) followed by a HCD_PIPE_EVENT_INVALID (MUST OCCUR) - int num_pipe_events = test_hcd_get_num_pipe_events(default_pipe); - for (int i = 0; i < num_pipe_events - 1; i++) { - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); - } - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_INVALID); - TEST_ASSERT_EQUAL(hcd_pipe_get_state(default_pipe), HCD_PIPE_STATE_INVALID); + //We should be able to halt then flush the pipe + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); + printf("Pipe halted and flushed\n"); //Dequeue URBs for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); @@ -113,17 +116,20 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]") Test port suspend and resume with active pipes Purpose: - - Test port suspend and resume commands work correctly whilst there are active pipes with ongoing transfers - - When suspending, the pipes should be allowed to finish their current ongoing transfer before the bus is suspended. - - When resuming, pipes with pending transfer should be started after the bus is resumed. + - Test port suspend and resume procedure + - When suspending, the pipes should be halted before suspending the port. Any pending transfers should remain pending + - When resuming, the pipes should remain in the halted state + - Pipes on being cleared of the halt should resume transferring the pending transfers Procedure: - Setup the HCD and a port - Trigger a port connection - Create a default pipe - - Start transfers but suspend the port immediately + - Start transfers + - Halt the default pipe after a short delay + - Suspend the port - Resume the port - - Check that all the URBs have completed successfully + - Check that all the URBs have either completed successfully or been canceled by the pipe halt - Cleanup URBs and default pipe - Trigger disconnection and teardown */ @@ -139,8 +145,8 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } @@ -149,6 +155,13 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } + //Add a short delay to let the transfers run for a bit + esp_rom_delay_us(POST_ENQUEUE_DELAY_US); + //Halt the default pipe before suspending + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); + //Suspend the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_SUSPEND)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_SUSPENDED, hcd_port_get_state(port_hdl)); printf("Suspended\n"); @@ -158,13 +171,23 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_ENABLED, hcd_port_get_state(port_hdl)); printf("Resumed\n"); + //Clear the default pipe's halt + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR)); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for resumed URBs to complete //Dequeue URBs for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT_EQUAL(urb->transfer.status, USB_TRANSFER_STATUS_COMPLETED); - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); + if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + } else { + //A failed transfer should 0 actual number of bytes transmitted + TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); + } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); } @@ -179,18 +202,20 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") } /* -Test HCD port disable with active pipes +Test HCD port disable and disconnection Purpose: - - Test that the port disable command works correctly with active pipes - - Pipes should be to finish their current ongoing transfer before port is disabled - - After disabling the port, all pipes should become invalid. + - Test that the port disable command works correctly + - Check that port can only be disabled when pipes have been halted + - Check that a disconnection after port disable still triggers a HCD_PORT_EVENT_DISCONNECTION event Procedure: - Setup HCD, a default pipe, and multiple URBs - - Start transfers but immediately disable the port - - Check pipe received invalid event - - Check that transfer are either done or not executed + - Start transfers + - Halt the default pipe after a short delay + - Check that port can be disabled + - Flush the default pipe and cleanup the default pipe + - Check that a disconnection still works after disable - Teardown */ TEST_CASE("Test HCD port disable", "[hcd][ignore]") @@ -205,8 +230,8 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } @@ -215,25 +240,32 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } + //Add a short delay to let the transfers run for a bit + esp_rom_delay_us(POST_ENQUEUE_DELAY_US); + //Halt the default pipe before suspending + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); + + + //Check that port can be disabled TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl)); printf("Disabled\n"); - //Pipe should have received (zero or more HCD_PIPE_EVENT_URB_DONE) followed by a HCD_PIPE_EVENT_INVALID (MUST OCCUR) - int num_pipe_events = test_hcd_get_num_pipe_events(default_pipe); - for (int i = 0; i < num_pipe_events - 1; i++) { - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); - } - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_INVALID); - + //Flush pipe + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); //Dequeue URBs for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); @@ -244,7 +276,8 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]") test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(default_pipe); - //Cleanup + + //Trigger a disconnection and cleanup test_hcd_wait_for_disconn(port_hdl, true); test_hcd_teardown(port_hdl); } @@ -296,8 +329,8 @@ TEST_CASE("Test HCD port command bailout", "[hcd][ignore]") TEST_ASSERT_EQUAL(ESP_ERR_INVALID_RESPONSE, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME)); //Check that concurrent task triggered a sudden disconnection - test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_SUDDEN_DISCONN); - TEST_ASSERT_EQUAL(HCD_PORT_EVENT_SUDDEN_DISCONN, hcd_port_handle_event(port_hdl)); + test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); + TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); //Cleanup task and semaphore diff --git a/components/usb/test/usb_host/ctrl_client.h b/components/usb/test/usb_host/ctrl_client.h new file mode 100644 index 0000000000..4cfeccc53d --- /dev/null +++ b/components/usb/test/usb_host/ctrl_client.h @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +typedef struct { + int num_ctrl_xfer_to_send; + uint16_t idVendor; + uint16_t idProduct; +} ctrl_client_test_param_t; + +void ctrl_client_async_seq_task(void *arg); diff --git a/components/usb/test/usb_host/ctrl_client_async_seq.c b/components/usb/test/usb_host/ctrl_client_async_seq.c new file mode 100644 index 0000000000..85751adeb6 --- /dev/null +++ b/components/usb/test/usb_host/ctrl_client_async_seq.c @@ -0,0 +1,185 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_err.h" +#include "esp_log.h" +#include "ctrl_client.h" +#include "usb/usb_host.h" +#include "unity.h" +#include "test_utils.h" + +/* +Implementation of a control transfer client used for USB Host Tests. + +- Implemented using sequential call patterns, meaning: + - The entire client is contained within a single task + - All API calls and callbacks are run sequentially + - No critical sections required since everything is sequential +- The control transfer client will: + - Register itself as a client + - Receive USB_HOST_CLIENT_EVENT_NEW_DEV event message, and open the device + - Allocate multiple transfer objects + - Submit a number of control transfers (get configuration descriptor requests) + - Free transfer objects + - Close the device + - Deregister control client +*/ + +#define MAX(x,y) (((x) >= (y)) ? (x) : (y)) +#define CTRL_CLIENT_MAX_EVENT_MSGS 5 +#define NUM_TRANSFER_OBJ 3 +#define MAX_TRANSFER_BYTES 256 + +const char *CTRL_CLIENT_TAG = "Ctrl Client"; + +typedef enum { + TEST_STAGE_WAIT_CONN, + TEST_STAGE_DEV_OPEN, + TEST_STAGE_CTRL_XFER, + TEST_STAGE_CTRL_XFER_WAIT, + TEST_STAGE_DEV_CLOSE, +} test_stage_t; + +typedef struct { + ctrl_client_test_param_t test_param; + test_stage_t cur_stage; + test_stage_t next_stage; + uint8_t num_xfer_done; + uint8_t num_xfer_sent; + uint8_t dev_addr_to_open; + usb_host_client_handle_t client_hdl; + usb_device_handle_t dev_hdl; + const usb_config_desc_t *config_desc_cached; +} ctrl_client_obj_t; + +static void ctrl_transfer_cb(usb_transfer_t *transfer) +{ + ctrl_client_obj_t *ctrl_obj = (ctrl_client_obj_t *)transfer->context; + //Check the completed control transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(ctrl_obj->config_desc_cached->wTotalLength, transfer->actual_num_bytes - sizeof(usb_setup_packet_t)); + ctrl_obj->num_xfer_done++; + if (ctrl_obj->num_xfer_sent < ctrl_obj->test_param.num_ctrl_xfer_to_send) { + ctrl_obj->next_stage = TEST_STAGE_CTRL_XFER; + } else if (ctrl_obj->num_xfer_done == ctrl_obj->test_param.num_ctrl_xfer_to_send) { + ctrl_obj->next_stage = TEST_STAGE_DEV_CLOSE; + } +} + +static void ctrl_client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg) +{ + ctrl_client_obj_t *ctrl_obj = (ctrl_client_obj_t *)arg; + switch (event_msg->event) { + case USB_HOST_CLIENT_EVENT_NEW_DEV: + TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, ctrl_obj->cur_stage); + ctrl_obj->next_stage = TEST_STAGE_DEV_OPEN; + ctrl_obj->dev_addr_to_open = event_msg->new_dev.address; + break; + default: + abort(); //Should never occur in this test + break; + } +} + +void ctrl_client_async_seq_task(void *arg) +{ + ctrl_client_obj_t ctrl_obj = {0}; + memcpy(&ctrl_obj.test_param, arg, sizeof(ctrl_client_test_param_t)); + ctrl_obj.cur_stage = TEST_STAGE_WAIT_CONN; + ctrl_obj.next_stage = TEST_STAGE_WAIT_CONN; + + //Register client + usb_host_client_config_t client_config = { + .client_event_callback = ctrl_client_event_cb, + .callback_arg = (void *)&ctrl_obj, + .max_num_event_msg = CTRL_CLIENT_MAX_EVENT_MSGS, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &ctrl_obj.client_hdl)); + + //Allocate transfers + usb_transfer_t *ctrl_xfer[NUM_TRANSFER_OBJ] = {NULL}; + for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(sizeof(usb_setup_packet_t) + MAX_TRANSFER_BYTES, 0, &ctrl_xfer[i])); + ctrl_xfer[i]->callback = ctrl_transfer_cb; + ctrl_xfer[i]->context = (void *)&ctrl_obj; + } + + //Wait to be started by main thread + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + ESP_LOGD(CTRL_CLIENT_TAG, "Starting"); + + bool exit_loop = false; + bool skip_event_handling = false; + while (!exit_loop) { + if (!skip_event_handling) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_handle_events(ctrl_obj.client_hdl, portMAX_DELAY)); + } + skip_event_handling = false; + if (ctrl_obj.cur_stage == ctrl_obj.next_stage) { + continue; + } + ctrl_obj.cur_stage = ctrl_obj.next_stage; + + switch (ctrl_obj.next_stage) { + case TEST_STAGE_DEV_OPEN: { + ESP_LOGD(CTRL_CLIENT_TAG, "Open"); + //Open the device + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(ctrl_obj.client_hdl, ctrl_obj.dev_addr_to_open, &ctrl_obj.dev_hdl)); + //Target our transfers to the device + for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { + ctrl_xfer[i]->device_handle = ctrl_obj.dev_hdl; + } + //Check the VID/PID of the opened device + const usb_device_desc_t *device_desc; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(ctrl_obj.dev_hdl, &device_desc)); + TEST_ASSERT_EQUAL(ctrl_obj.test_param.idVendor, device_desc->idVendor); + TEST_ASSERT_EQUAL(ctrl_obj.test_param.idProduct, device_desc->idProduct); + //Cache the active configuration descriptor for later comparison + TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_active_config_descriptor(ctrl_obj.dev_hdl, &ctrl_obj.config_desc_cached)); + ctrl_obj.next_stage = TEST_STAGE_CTRL_XFER; + skip_event_handling = true; + break; + } + case TEST_STAGE_CTRL_XFER: { + ESP_LOGD(CTRL_CLIENT_TAG, "Transfer"); + //Send a control transfer to get the device's configuration descriptor + usb_transfer_t *transfer = ctrl_xfer[ctrl_obj.num_xfer_sent % NUM_TRANSFER_OBJ]; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, 0, MAX_TRANSFER_BYTES); + transfer->num_bytes = sizeof(usb_setup_packet_t) + MAX_TRANSFER_BYTES; + transfer->bEndpointAddress = 0; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit_control(ctrl_obj.client_hdl, transfer)); + ctrl_obj.num_xfer_sent++; + ctrl_obj.next_stage = TEST_STAGE_CTRL_XFER_WAIT; + skip_event_handling = true; + break; + } + case TEST_STAGE_CTRL_XFER_WAIT: { + //Nothing to do but wait + break; + } + case TEST_STAGE_DEV_CLOSE: { + ESP_LOGD(CTRL_CLIENT_TAG, "Close"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(ctrl_obj.client_hdl, ctrl_obj.dev_hdl)); + exit_loop = true; + break; + } + default: + abort(); + break; + } + } + //Free transfers and deregister client + for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(ctrl_xfer[i])); + } + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(ctrl_obj.client_hdl)); + ESP_LOGD(CTRL_CLIENT_TAG, "Done"); + vTaskDelete(NULL); +} diff --git a/components/usb/test/usb_host/msc_client.h b/components/usb/test/usb_host/msc_client.h new file mode 100644 index 0000000000..b1809b949c --- /dev/null +++ b/components/usb/test/usb_host/msc_client.h @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +typedef struct { + int num_sectors_to_read; + int num_sectors_per_xfer; + uint32_t msc_scsi_xfer_tag; + uint16_t idVendor; + uint16_t idProduct; +} msc_client_test_param_t; + +void msc_client_async_seq_task(void *arg); diff --git a/components/usb/test/usb_host/msc_client_async_seq.c b/components/usb/test/usb_host/msc_client_async_seq.c new file mode 100644 index 0000000000..6880e96ec7 --- /dev/null +++ b/components/usb/test/usb_host/msc_client_async_seq.c @@ -0,0 +1,242 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "test_usb_mock_classes.h" +#include "msc_client.h" +#include "usb/usb_host.h" +#include "unity.h" +#include "test_utils.h" + +/* +Implementation of an MSC client used for USB Host Tests + +- Implemented using sequential call patterns, meaning: + - The entire client is contained within a single task + - All API calls and callbacks are run sequentially + - No critical sections required since everything is sequential +- The MSC client will: + - Register itself as a client + - Receive USB_HOST_CLIENT_EVENT_NEW_DEV event message, and open the device + - Allocate IN and OUT transfer objects for MSC SCSI transfers + - Iterate through multiple MSC SCSI block reads + - Free transfer objects + - Close device + - Deregister MSC client +*/ + +#define MAX(x,y) (((x) >= (y)) ? (x) : (y)) +#define MSC_CLIENT_MAX_EVENT_MSGS 5 + +const char *MSC_CLIENT_TAG = "MSC Client"; + +typedef enum { + TEST_STAGE_WAIT_CONN, + TEST_STAGE_DEV_OPEN, + TEST_STAGE_MSC_RESET, + TEST_STAGE_MSC_CBW, + TEST_STAGE_MSC_DATA, + TEST_STAGE_MSC_CSW, + TEST_STAGE_DEV_CLOSE, +} test_stage_t; + +typedef struct { + msc_client_test_param_t test_param; + test_stage_t cur_stage; + test_stage_t next_stage; + uint8_t dev_addr_to_open; + usb_host_client_handle_t client_hdl; + usb_device_handle_t dev_hdl; + int num_sectors_read; +} msc_client_obj_t; + +static void msc_transfer_cb(usb_transfer_t *transfer) +{ + msc_client_obj_t *msc_obj = (msc_client_obj_t *)transfer->context; + switch (msc_obj->cur_stage) { + case TEST_STAGE_MSC_RESET: { + //Check MSC SCSI interface reset + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(transfer->num_bytes, transfer->actual_num_bytes); + msc_obj->next_stage = TEST_STAGE_MSC_CBW; + break; + } + case TEST_STAGE_MSC_CBW: { + //Check MSC SCSI CBW transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(sizeof(mock_msc_bulk_cbw_t), transfer->actual_num_bytes); + msc_obj->next_stage = TEST_STAGE_MSC_DATA; + break; + } + case TEST_STAGE_MSC_DATA: { + //Check MSC SCSI data IN transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj->test_param.num_sectors_per_xfer, transfer->actual_num_bytes); + msc_obj->next_stage = TEST_STAGE_MSC_CSW; + break; + } + case TEST_STAGE_MSC_CSW: { + //Check MSC SCSI CSW transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(true, mock_msc_scsi_check_csw((mock_msc_bulk_csw_t *)transfer->data_buffer, msc_obj->test_param.msc_scsi_xfer_tag)); + msc_obj->num_sectors_read += msc_obj->test_param.num_sectors_per_xfer; + if (msc_obj->num_sectors_read < msc_obj->test_param.num_sectors_to_read) { + msc_obj->next_stage = TEST_STAGE_MSC_CBW; + } else { + msc_obj->next_stage = TEST_STAGE_DEV_CLOSE; + } + break; + } + default: { + abort(); + break; + } + } +} + +static void msc_client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg) +{ + msc_client_obj_t *msc_obj = (msc_client_obj_t *)arg; + switch (event_msg->event) { + case USB_HOST_CLIENT_EVENT_NEW_DEV: + TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, msc_obj->cur_stage); + msc_obj->next_stage = TEST_STAGE_DEV_OPEN; + msc_obj->dev_addr_to_open = event_msg->new_dev.address; + break; + default: + abort(); //Should never occur in this test + break; + + } +} + +void msc_client_async_seq_task(void *arg) +{ + msc_client_obj_t msc_obj; + memcpy(&msc_obj.test_param, arg, sizeof(msc_client_test_param_t)); + msc_obj.cur_stage = TEST_STAGE_WAIT_CONN; + msc_obj.next_stage = TEST_STAGE_WAIT_CONN; + msc_obj.client_hdl = NULL; + msc_obj.dev_addr_to_open = 0; + msc_obj.dev_hdl = NULL; + msc_obj.num_sectors_read = 0; + + //Register client + usb_host_client_config_t client_config = { + .client_event_callback = msc_client_event_cb, + .callback_arg = (void *)&msc_obj, + .max_num_event_msg = MSC_CLIENT_MAX_EVENT_MSGS, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &msc_obj.client_hdl)); + + //Allocate transfers + usb_transfer_t *xfer_out = NULL; //Must be large enough to contain CBW and MSC reset control transfer + usb_transfer_t *xfer_in = NULL; //Must be large enough to contain CSW and Data + size_t out_worst_case_size = MAX(sizeof(mock_msc_bulk_cbw_t), sizeof(usb_setup_packet_t)); + size_t in_worst_case_size = usb_host_round_up_to_mps(MAX(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, sizeof(mock_msc_bulk_csw_t)), MOCK_MSC_SCSI_BULK_EP_MPS); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(out_worst_case_size, 0, &xfer_out)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(in_worst_case_size, 0, &xfer_in)); + xfer_out->callback = msc_transfer_cb; + xfer_in->callback = msc_transfer_cb; + xfer_out->context = (void *)&msc_obj; + xfer_in->context = (void *)&msc_obj; + + //Wait to be started by main thread + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + ESP_LOGD(MSC_CLIENT_TAG, "Starting"); + + bool exit_loop = false; + bool skip_event_handling = false; + while (!exit_loop) { + if (!skip_event_handling) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_handle_events(msc_obj.client_hdl, portMAX_DELAY)); + } + skip_event_handling = false; + if (msc_obj.cur_stage == msc_obj.next_stage) { + continue; + } + msc_obj.cur_stage = msc_obj.next_stage; + + switch (msc_obj.cur_stage) { + case TEST_STAGE_DEV_OPEN: { + ESP_LOGD(MSC_CLIENT_TAG, "Open"); + //Open the device + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(msc_obj.client_hdl, msc_obj.dev_addr_to_open, &msc_obj.dev_hdl)); + //Target our transfers to the device + xfer_out->device_handle = msc_obj.dev_hdl; + xfer_in->device_handle = msc_obj.dev_hdl; + //Check the VID/PID of the opened device + const usb_device_desc_t *device_desc; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(msc_obj.dev_hdl, &device_desc)); + TEST_ASSERT_EQUAL(msc_obj.test_param.idVendor, device_desc->idVendor); + TEST_ASSERT_EQUAL(msc_obj.test_param.idProduct, device_desc->idProduct); + //Claim the MSC interface + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER, MOCK_MSC_SCSI_INTF_ALT_SETTING)); + msc_obj.next_stage = TEST_STAGE_MSC_RESET; + skip_event_handling = true; //Need to execute TEST_STAGE_MSC_RESET + break; + } + case TEST_STAGE_MSC_RESET: { + ESP_LOGD(MSC_CLIENT_TAG, "MSC Reset"); + //Send an MSC SCSI interface reset + MOCK_MSC_SCSI_REQ_INIT_RESET((usb_setup_packet_t *)xfer_out->data_buffer, MOCK_MSC_SCSI_INTF_NUMBER); + xfer_out->num_bytes = sizeof(usb_setup_packet_t); + xfer_out->bEndpointAddress = 0; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit_control(msc_obj.client_hdl, xfer_out)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_MSC_CBW: { + ESP_LOGD(MSC_CLIENT_TAG, "CBW"); + mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)xfer_out->data_buffer, true, msc_obj.next_stage, msc_obj.test_param.num_sectors_per_xfer, msc_obj.test_param.msc_scsi_xfer_tag); + xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t); + xfer_out->bEndpointAddress = MOCK_MSC_SCSI_BULK_OUT_EP_ADDR; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_MSC_DATA: { + ESP_LOGD(MSC_CLIENT_TAG, "Data"); + xfer_in->num_bytes = usb_host_round_up_to_mps(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, MOCK_MSC_SCSI_BULK_EP_MPS); + xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_MSC_CSW: { + ESP_LOGD(MSC_CLIENT_TAG, "CSW"); + xfer_in->num_bytes = usb_host_round_up_to_mps(sizeof(mock_msc_bulk_csw_t), MOCK_MSC_SCSI_BULK_EP_MPS); + xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_DEV_CLOSE: { + ESP_LOGD(MSC_CLIENT_TAG, "Close"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(msc_obj.client_hdl, msc_obj.dev_hdl)); + exit_loop = true; + break; + } + default: + abort(); + break; + } + } + //Free transfers and deregister the client + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_out)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_in)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(msc_obj.client_hdl)); + ESP_LOGD(MSC_CLIENT_TAG, "Done"); + vTaskDelete(NULL); +} diff --git a/components/usb/test/usb_host/test_usb_host_async.c b/components/usb/test/usb_host/test_usb_host_async.c new file mode 100644 index 0000000000..4c7f792e7c --- /dev/null +++ b/components/usb/test/usb_host/test_usb_host_async.c @@ -0,0 +1,157 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_intr_alloc.h" +#include "test_usb_mock_classes.h" +#include "msc_client.h" +#include "ctrl_client.h" +#include "usb/usb_host.h" +#include "unity.h" +#include "test_utils.h" + +#define TEST_MSC_NUM_SECTORS_TOTAL 10 +#define TEST_MSC_NUM_SECTORS_PER_XFER 2 +#define TEST_MSC_SCSI_TAG 0xDEADBEEF +#define TEST_CTRL_NUM_TRANSFERS 30 + +// --------------------------------------------------- Test Cases ------------------------------------------------------ + +/* +Test USB Host Asynchronous API single client + +Requires: This test requires an MSC SCSI device to be attached (see the MSC mock class) + +Purpose: + - Test that USB Host Asynchronous API works correctly with a single client + - Test that a client can be created + - Test that client can operate concurrently in a separate thread + - Test that the main thread is able to detect library events (such as USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) + +Procedure: + - Install USB Host Library + - Create a task to run an MSC client + - Start the MSC client task. It will execute a bunch of MSC SCSI sector reads + - Wait for the host library event handler to report a USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS event + - Free all devices + - Uninstall USB Host Library +*/ + +TEST_CASE("Test USB Host async (single client)", "[usb_host][ignore]") +{ + //Install USB Host + usb_host_config_t host_config = { + .intr_flags = ESP_INTR_FLAG_LEVEL1, + }; + ESP_ERROR_CHECK(usb_host_install(&host_config)); + printf("Installed\n"); + + //Create task to run client that communicates with MSC SCSI interface + msc_client_test_param_t params = { + .num_sectors_to_read = TEST_MSC_NUM_SECTORS_TOTAL, + .num_sectors_per_xfer = TEST_MSC_NUM_SECTORS_PER_XFER, + .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG, + .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, + .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, + }; + TaskHandle_t task_hdl; + xTaskCreatePinnedToCore(msc_client_async_seq_task, "async", 4096, (void *)¶ms, 2, &task_hdl, 0); + //Start the task + xTaskNotifyGive(task_hdl); + + while (1) { + //Start handling system events + uint32_t event_flags; + usb_host_lib_handle_events(portMAX_DELAY, &event_flags); + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { + printf("No more clients\n"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_free_all()); + } + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { + break; + } + } + + //Short delay to allow task to be cleaned up + vTaskDelay(10); + //Clean up USB Host + ESP_ERROR_CHECK(usb_host_uninstall()); +} + +/* +Test USB Host Asynchronous API with multiple clients + +Requires: This test requires an MSC SCSI device to be attached (see the MSC mock class) + +Purpose: + - Test the USB Host Asynchronous API works correctly with multiple clients + - Test that multiple clients can be created + - Test that multiple clients can operate concurrently in separate threads + - Test that the main thread is able to detect library events (such as USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) + +Procedure: + - Install USB Host Library + - Create separate tasks to run an MSC client and Ctrl Client + - MSC Client will execute a bunch of MSC SCSI sector reads + - Ctrl Client will execute a bunch of control transfers + - Wait for the host library event handler to report a USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS event + - Free all devices + - Uninstall USB Host Library +*/ +TEST_CASE("Test USB Host async (multi client)", "[usb_host][ignore]") +{ + //Install USB Host + usb_host_config_t host_config = { + .intr_flags = ESP_INTR_FLAG_LEVEL1, + }; + ESP_ERROR_CHECK(usb_host_install(&host_config)); + printf("Installed\n"); + + //Create task to run the MSC client + msc_client_test_param_t msc_params = { + .num_sectors_to_read = TEST_MSC_NUM_SECTORS_TOTAL, + .num_sectors_per_xfer = TEST_MSC_NUM_SECTORS_PER_XFER, + .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG, + .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, + .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, + }; + TaskHandle_t msc_task_hdl; + xTaskCreatePinnedToCore(msc_client_async_seq_task, "msc", 4096, (void *)&msc_params, 2, &msc_task_hdl, 0); + + //Create task a control transfer client + ctrl_client_test_param_t ctrl_params = { + .num_ctrl_xfer_to_send = TEST_CTRL_NUM_TRANSFERS, + .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, + .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, + }; + TaskHandle_t ctrl_task_hdl; + xTaskCreatePinnedToCore(ctrl_client_async_seq_task, "ctrl", 4096, (void *)&ctrl_params, 2, &ctrl_task_hdl, 0); + + //Start both tasks + xTaskNotifyGive(msc_task_hdl); + xTaskNotifyGive(ctrl_task_hdl); + + while (1) { + //Start handling system events + uint32_t event_flags; + usb_host_lib_handle_events(portMAX_DELAY, &event_flags); + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { + printf("No more clients\n"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_free_all()); + } + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { + break; + } + } + + //Short delay to allow task to be cleaned up + vTaskDelay(10); + //Clean up USB Host + ESP_ERROR_CHECK(usb_host_uninstall()); +} diff --git a/components/usb/test/usb_host/test_usb_host_misc.c b/components/usb/test/usb_host/test_usb_host_misc.c new file mode 100644 index 0000000000..465e7ca915 --- /dev/null +++ b/components/usb/test/usb_host/test_usb_host_misc.c @@ -0,0 +1,439 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "unity.h" +#include "test_utils.h" +#include "usb/usb_host.h" + +/* +Tests that check the configuration descriptor parsing functions provided in usb_host.h work by parsing a fixed +configuration descriptor. The fixed configuration descriptor used in this test is provided below (both in textual and +byte format), and is of a UVC device. Thus the configuration descriptor has a good set of scenarios that can be tested +(such as multiple interfaces, alternate settings, class specific descriptors, default endpoint only interfaces etc). +*/ + +/* +Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0185 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 0 + bInterfaceCount 2 + bFunctionClass 14 Video + bFunctionSubClass 3 Video Interface Collection + bFunctionProtocol 0 + iFunction 5 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 1 Video Control + bInterfaceProtocol 0 + iInterface 5 + VideoControl Interface Descriptor: + bLength 13 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdUVC 1.00 + wTotalLength 0x004f + dwClockFrequency 15.000000MHz + bInCollection 1 + baInterfaceNr( 0) 1 + VideoControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 4 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 3 + iTerminal 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 3 + guidExtensionCode {4cf18db6-abd0-495c-9876-1fa3942ff9fa} + bNumControl 24 + bNrPins 1 + baSourceID( 0) 2 + bControlSize 3 + bmControls( 0) 0xff + bmControls( 1) 0xff + bmControls( 2) 0xff + iExtension 0 + VideoControl Interface Descriptor: + bLength 18 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Camera Sensor + bAssocTerminal 0 + iTerminal 0 + wObjectiveFocalLengthMin 0 + wObjectiveFocalLengthMax 0 + wOcularFocalLength 0 + bControlSize 3 + bmControls 0x0000000e + Auto-Exposure Mode + Auto-Exposure Priority + Exposure Time (Absolute) + VideoControl Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 5 (PROCESSING_UNIT) + Warning: Descriptor too short + bUnitID 2 + bSourceID 1 + wMaxMultiplier 0 + bControlSize 2 + bmControls 0x0000177f + Brightness + Contrast + Hue + Saturation + Sharpness + Gamma + White Balance Temperature + Backlight Compensation + Gain + Power Line Frequency + White Balance Temperature, Auto + iProcessing 0 + bmVideoStandards 0x62 + NTSC - 525/60 + PAL - 525/60 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 6 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + VideoStreaming Interface Descriptor: + bLength 15 + bDescriptorType 36 + bDescriptorSubtype 1 (INPUT_HEADER) + bNumFormats 2 + wTotalLength 0x00f7 + bEndPointAddress 129 + bmInfo 0 + bTerminalLink 4 + bStillCaptureMethod 0 + bTriggerSupport 0 + bTriggerUsage 0 + bControlSize 1 + bmaControls( 0) 0 + bmaControls( 1) 0 + VideoStreaming Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) + bFormatIndex 1 + bNumFrameDescriptors 2 + guidFormat {85f6cc1d-0c9f-44f5-9ce0-97c7dd8c98ab} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 2 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 480 + wHeight 320 + dwMinBitRate 12288000 + dwMaxBitRate 12288000 + dwMaxVideoFrameBufferSize 307200 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 1 + dwFrameInterval( 0) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 73728000 + dwMaxBitRate 73728000 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 6 (FORMAT_MJPEG) + bFormatIndex 2 + bNumFrameDescriptors 4 + bFlags 0 + Fixed-size samples: No + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 36864000 + dwMaxBitRate 36864000 + dwMaxVideoFrameBufferSize 307789 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 480 + wHeight 320 + dwMinBitRate 6144000 + dwMaxBitRate 18432000 + dwMaxVideoFrameBufferSize 154189 + dwDefaultFrameInterval 666666 + bFrameIntervalType 3 + dwFrameInterval( 0) 666666 + dwFrameInterval( 1) 1000000 + dwFrameInterval( 2) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 12165120 + dwMaxBitRate 12165120 + dwMaxVideoFrameBufferSize 101965 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 9216000 + dwMaxBitRate 9216000 + dwMaxVideoFrameBufferSize 77389 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 1 (BT.709,sRGB) + bTransferCharacteristics 1 (BT.709) + bMatrixCoefficients 4 (SMPTE 170M (BT.601)) + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x03bc 1x 956 bytes + bInterval 1 +*/ + +static uint8_t config_desc_bytes [] = { + 0x09, 0x02, 0x85, 0x01, 0x02, 0x01, 0x00, 0x80, 0xFA, 0x08, 0x0B, 0x00, 0x02, 0x0E, 0x03, 0x00, 0x05, 0x09, 0x04, + 0x00, 0x00, 0x01, 0x0E, 0x01, 0x00, 0x05, 0x0D, 0x24, 0x01, 0x00, 0x01, 0x4F, 0x00, 0xC0, 0xE1, 0xE4, 0x00, 0x01, + 0x01, 0x09, 0x24, 0x03, 0x04, 0x01, 0x01, 0x00, 0x03, 0x00, 0x1C, 0x24, 0x06, 0x03, 0xB6, 0x8D, 0xF1, 0x4C, 0xD0, + 0xAB, 0x5C, 0x49, 0x76, 0x98, 0xFA, 0xF9, 0x2F, 0x94, 0xA3, 0x1F, 0x18, 0x01, 0x02, 0x03, 0xFF, 0xFF, 0xFF, 0x00, + 0x12, 0x24, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x00, 0x00, 0x0B, + 0x24, 0x05, 0x02, 0x01, 0x00, 0x00, 0x02, 0x7F, 0x17, 0x00, 0x07, 0x05, 0x83, 0x03, 0x10, 0x00, 0x06, 0x05, 0x25, + 0x03, 0x80, 0x00, 0x09, 0x04, 0x01, 0x00, 0x00, 0x0E, 0x02, 0x00, 0x00, 0x0F, 0x24, 0x01, 0x02, 0xF7, 0x00, 0x81, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1B, 0x24, 0x04, 0x01, 0x02, 0x1D, 0xCC, 0xF6, 0x85, 0x9F, 0x0C, + 0xF5, 0x44, 0xE0, 0x9C, 0xAB, 0x98, 0x8C, 0xDD, 0xC7, 0x97, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x24, 0x05, + 0x01, 0x00, 0xE0, 0x01, 0x40, 0x01, 0x00, 0x80, 0xBB, 0x00, 0x00, 0x80, 0xBB, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x80, + 0x84, 0x1E, 0x00, 0x01, 0x80, 0x84, 0x1E, 0x00, 0x1E, 0x24, 0x05, 0x02, 0x00, 0x80, 0x02, 0xE0, 0x01, 0x00, 0x00, + 0x65, 0x04, 0x00, 0x00, 0x65, 0x04, 0x00, 0x60, 0x09, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x01, 0x2A, 0x2C, 0x0A, 0x00, + 0x0B, 0x24, 0x06, 0x02, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x24, 0x07, 0x01, 0x00, 0x80, 0x02, 0xE0, + 0x01, 0x00, 0x80, 0x32, 0x02, 0x00, 0x80, 0x32, 0x02, 0x4D, 0xB2, 0x04, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x01, 0x2A, + 0x2C, 0x0A, 0x00, 0x26, 0x24, 0x07, 0x02, 0x00, 0xE0, 0x01, 0x40, 0x01, 0x00, 0xC0, 0x5D, 0x00, 0x00, 0x40, 0x19, + 0x01, 0x4D, 0x5A, 0x02, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x03, 0x2A, 0x2C, 0x0A, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x80, + 0x84, 0x1E, 0x00, 0x1E, 0x24, 0x07, 0x03, 0x00, 0x60, 0x01, 0x20, 0x01, 0x00, 0xA0, 0xB9, 0x00, 0x00, 0xA0, 0xB9, + 0x00, 0x4D, 0x8E, 0x01, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x01, 0x2A, 0x2C, 0x0A, 0x00, 0x1E, 0x24, 0x07, 0x04, 0x00, + 0x40, 0x01, 0xF0, 0x00, 0x00, 0xA0, 0x8C, 0x00, 0x00, 0xA0, 0x8C, 0x00, 0x4D, 0x2E, 0x01, 0x00, 0x2A, 0x2C, 0x0A, + 0x00, 0x01, 0x2A, 0x2C, 0x0A, 0x00, 0x06, 0x24, 0x0D, 0x01, 0x01, 0x04, 0x09, 0x04, 0x01, 0x01, 0x01, 0x0E, 0x02, + 0x00, 0x00, 0x07, 0x05, 0x81, 0x05, 0xBC, 0x03, 0x01, +}; +_Static_assert(sizeof(config_desc_bytes) == 0x0185, "Configuration Descriptor size does not match"); + +#define TEST_NUM_INTF_DESC 3 //Total number of interface descriptors (including alternate) + +// --------------------- Sub-Test 1 ------------------------ + +/* +Test if we can walk the configuration descriptor to find each interface descriptor +*/ +static void test_walk_desc(const usb_config_desc_t *config_desc) +{ + int offset = 0; + const usb_standard_desc_t *cur_desc = (usb_standard_desc_t *)config_desc; + for (int i = 0; i < TEST_NUM_INTF_DESC; i++) { + cur_desc = usb_host_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + TEST_ASSERT_NOT_EQUAL(NULL, cur_desc); + } + //Attempting to look for another interface descriptor should result in NULL + cur_desc = usb_host_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + TEST_ASSERT_EQUAL(NULL, cur_desc); +} + +/* +Test if the count of number of alternate descriptors is correct +*/ +static void test_alt_intf_desc_count(const usb_config_desc_t *config_desc) +{ + //bInterface 0 has no alternate interfaces + TEST_ASSERT_EQUAL(0, usb_host_parse_interface_number_of_alternate(config_desc, 0)); + //bInterface 1 has 1 alternate interface + TEST_ASSERT_EQUAL(1, usb_host_parse_interface_number_of_alternate(config_desc, 1)); + //Non existent bInterface 2 should return -1 + TEST_ASSERT_EQUAL(-1, usb_host_parse_interface_number_of_alternate(config_desc, 2)); +} + +static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc) +{ + int offset_intf = 0; + + //Get bInterfaceNumber 0 (index 0) + const usb_intf_desc_t *intf_desc = usb_host_parse_interface(config_desc, 0, 0, &offset_intf); + TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); + //Should only have one endpoint + int offset_ep = offset_intf; + const usb_ep_desc_t *ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress); + offset_ep = offset_intf; + ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); + + //Get bInterfaceNumber 1 alternate setting 0 + offset_intf = 0; + intf_desc = usb_host_parse_interface(config_desc, 1, 0, &offset_intf); + TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); + //Should have no endpoints + offset_ep = offset_intf; + ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); + + //Get bInterfaceNumber 1 alternate setting 1 + offset_intf = 0; + intf_desc = usb_host_parse_interface(config_desc, 1, 1, &offset_intf); + TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); + //Should only have one endpoint + offset_ep = offset_intf; + ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress); + offset_ep = offset_intf; + ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); +} + +static void test_parse_ep_by_address(const usb_config_desc_t *config_desc) +{ + int offset_ep = 0; + //Get bInterface 0 bAlternateSetting 0 EP 0x83 + const usb_ep_desc_t *ep_desc = usb_host_parse_endpoint_by_address(config_desc, 0, 0, 0x83, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress); + //Getting same EP address under different interface should return NULL + offset_ep = 0; + ep_desc = usb_host_parse_endpoint_by_address(config_desc, 1, 0, 0x83, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); + + //Get bInterface 1 bAlternateSetting 1 EP 0x81 + offset_ep = 0; + ep_desc = usb_host_parse_endpoint_by_address(config_desc, 1, 1, 0x81, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress); + //Getting same EP address under different interface should return NULL + offset_ep = 0; + ep_desc = usb_host_parse_endpoint_by_address(config_desc, 1, 0, 0x81, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); +} + +TEST_CASE("Test USB Host descriptor parsing", "[usb_host][ignore]") +{ + const usb_config_desc_t *config_desc = (const usb_config_desc_t *)config_desc_bytes; + test_walk_desc(config_desc); + test_alt_intf_desc_count(config_desc); + test_parse_intf_and_ep(config_desc); + test_parse_ep_by_address(config_desc); +} diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c new file mode 100644 index 0000000000..f745001b22 --- /dev/null +++ b/components/usb/usb_host.c @@ -0,0 +1,1270 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "hub.h" +#include "usbh.h" +#include "usb/usb_host.h" + +static portMUX_TYPE host_lock = portMUX_INITIALIZER_UNLOCKED; + +#define HOST_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&host_lock) +#define HOST_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&host_lock) +#define HOST_ENTER_CRITICAL() portENTER_CRITICAL(&host_lock) +#define HOST_EXIT_CRITICAL() portEXIT_CRITICAL(&host_lock) +#define HOST_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&host_lock) +#define HOST_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&host_lock) + +#define HOST_CHECK(cond, ret_val) ({ \ + if (!(cond)) { \ + return (ret_val); \ + } \ +}) +#define HOST_CHECK_FROM_CRIT(cond, ret_val) ({ \ + if (!(cond)) { \ + HOST_EXIT_CRITICAL(); \ + return ret_val; \ + } \ +}) + +#define PROCESS_PENDING_FLAG_USBH 0x01 +#define PROCESS_PENDING_FLAG_HUB 0x02 +#define PROCESS_PENDING_FLAG_EVENT 0x04 + +typedef struct endpoint_s endpoint_t; +typedef struct interface_s interface_t; +typedef struct client_s client_t; + +struct endpoint_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(endpoint_s) tailq_entry; + union { + struct { + uint32_t pending: 1; + uint32_t reserved31:31; + }; + } flags; + uint32_t num_urb_inflight; + hcd_pipe_event_t last_event; + } dynamic; + //Constant members do no change after claiming the interface thus do not require a critical section + struct { + hcd_pipe_handle_t pipe_hdl; + const usb_ep_desc_t *ep_desc; + interface_t *intf_obj; + } constant; +}; + +struct interface_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(interface_s) tailq_entry; + } mux_protected; + //Constant members do no change after claiming the interface thus do not require a critical section + struct { + const usb_intf_desc_t *intf_desc; + usb_device_handle_t dev_hdl; + client_t *client_obj; + endpoint_t *endpoints[0]; + } constant; +}; + +struct client_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(client_s) tailq_entry; + TAILQ_HEAD(tailhead_pending_ep, endpoint_s) pending_ep_tailq; + TAILQ_HEAD(tailhead_idle_ep, endpoint_s) idle_ep_tailq; + TAILQ_HEAD(tailhead_done_ctrl_xfers, urb_s) done_ctrl_xfer_tailq; + union { + struct { + uint32_t events_pending: 1; + uint32_t handling_events: 1; + uint32_t blocked: 1; + uint32_t taking_mux: 1; + uint32_t reserved4: 4; + uint32_t num_intf_claimed: 8; + uint32_t reserved16: 16; + }; + uint32_t val; + } flags; + uint32_t num_done_ctrl_xfer; + uint32_t opened_dev_addr_map; + } dynamic; + //Mux protected members must be protected by host library the mux_lock when accessed + struct { + TAILQ_HEAD(tailhead_interfaces, interface_s) interface_tailq; + } mux_protected; + //Constant members do no change after registration thus do not require a critical section + struct { + SemaphoreHandle_t event_sem; + usb_host_client_event_cb_t event_callback; + void *callback_arg; + QueueHandle_t event_msg_queue; + } constant; +}; + +typedef struct { + //Dynamic members require a critical section + struct { + //Access to these should be done in a critical section + uint32_t process_pending_flags; + uint32_t lib_event_flags; + union { + struct { + uint32_t process_pending: 1; + uint32_t handling_events: 1; + uint32_t blocked: 1; + uint32_t reserved5: 5; + uint32_t num_clients: 8; + uint32_t reserved16: 16; + }; + uint32_t val; + } flags; + } dynamic; + //Mux protected members must be protected by host library the mux_lock when accessed + struct { + TAILQ_HEAD(tailhead_clients, client_s) client_tailq; //List of all clients registered + } mux_protected; + //Constant members do no change after installation thus do not require a critical section + struct { + SemaphoreHandle_t event_sem; + SemaphoreHandle_t mux_lock; + } constant; +} host_lib_t; + +static host_lib_t *p_host_lib_obj = NULL; + +const char *USB_HOST_TAG = "USB HOST"; + +// ----------------------------------------------------- Helpers ------------------------------------------------------- + +static inline void _record_client_opened_device(client_t *client_obj, uint8_t dev_addr) +{ + assert(dev_addr != 0); + client_obj->dynamic.opened_dev_addr_map |= (1 << (dev_addr - 1)); +} + +static inline void _clear_client_opened_device(client_t *client_obj, uint8_t dev_addr) +{ + assert(dev_addr != 0); + client_obj->dynamic.opened_dev_addr_map &= ~(1 << (dev_addr - 1)); +} + +static inline bool _check_client_opened_device(client_t *client_obj, uint8_t dev_addr) +{ + assert(dev_addr != 0); + return (client_obj->dynamic.opened_dev_addr_map & (1 << (dev_addr - 1))); +} + +static bool _unblock_client(client_t *client_obj, bool in_isr) +{ + bool send_sem; + if (!client_obj->dynamic.flags.events_pending && !client_obj->dynamic.flags.handling_events) { + client_obj->dynamic.flags.events_pending = 1; + send_sem = true; + } else { + send_sem = false; + } + + HOST_EXIT_CRITICAL_SAFE(); + bool yield = false; + if (send_sem) { + if (in_isr) { + BaseType_t xTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(client_obj->constant.event_sem, &xTaskWoken); + yield = (xTaskWoken == pdTRUE); + } else { + xSemaphoreGive(client_obj->constant.event_sem); + } + } + HOST_ENTER_CRITICAL_SAFE(); + + return yield; +} + +static bool _unblock_lib(bool in_isr) +{ + bool send_sem; + if (!p_host_lib_obj->dynamic.flags.process_pending && !p_host_lib_obj->dynamic.flags.handling_events) { + p_host_lib_obj->dynamic.flags.process_pending = 1; + send_sem = true; + } else { + send_sem = false; + } + + HOST_EXIT_CRITICAL_SAFE(); + bool yield = false; + if (send_sem) { + if (in_isr) { + BaseType_t xTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(p_host_lib_obj->constant.event_sem, &xTaskWoken); + yield = (xTaskWoken == pdTRUE); + } else { + xSemaphoreGive(p_host_lib_obj->constant.event_sem); + } + } + HOST_ENTER_CRITICAL_SAFE(); + + return yield; +} + +static void send_event_msg_to_clients(const usb_host_client_event_msg_t *event_msg, bool send_to_all, uint8_t opened_dev_addr) +{ + //Lock client list + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + //Send event message to relevant or all clients + client_t *client_obj; + TAILQ_FOREACH(client_obj, &p_host_lib_obj->mux_protected.client_tailq, dynamic.tailq_entry) { + if (!send_to_all) { + //Check if client opened the device + HOST_ENTER_CRITICAL(); + bool send = _check_client_opened_device(client_obj, opened_dev_addr); + HOST_EXIT_CRITICAL(); + if (!send) { + continue; + } + } + //Send the event message + if (xQueueSend(client_obj->constant.event_msg_queue, event_msg, 0) == pdTRUE) { + HOST_ENTER_CRITICAL(); + _unblock_client(client_obj, false); + HOST_EXIT_CRITICAL(); + } else { + ESP_LOGE(USB_HOST_TAG, "Client event message queue full"); + } + } + //Unlock client list + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); +} + +// ---------------------------------------------------- Callbacks ------------------------------------------------------ + +// ------------------- Library Related --------------------- + +static bool notif_callback(usb_notif_source_t source, bool in_isr, void *arg) +{ + HOST_ENTER_CRITICAL_SAFE(); + //Store notification source + switch (source) { + case USB_NOTIF_SOURCE_USBH: + p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_PENDING_FLAG_USBH; + break; + case USB_NOTIF_SOURCE_HUB: + p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_PENDING_FLAG_HUB; + break; + } + bool yield = _unblock_lib(in_isr); + HOST_EXIT_CRITICAL_SAFE(); + + return yield; +} + +static void ctrl_xfer_callback(usb_device_handle_t dev_hdl, urb_t *urb, void *arg) +{ + assert(urb->usb_host_client != NULL); + //Redistribute done control transfer to the clients that submitted them + client_t *client_obj = (client_t *)urb->usb_host_client; + + HOST_ENTER_CRITICAL(); + TAILQ_INSERT_TAIL(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry); + client_obj->dynamic.num_done_ctrl_xfer++; + _unblock_client(client_obj, false); + HOST_EXIT_CRITICAL(); +} + +static void dev_event_callback(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg) +{ + //Check usbh_event. The data type of event_arg depends on the type of event + switch (usbh_event) { + case USBH_EVENT_DEV_NEW: { + //Prepare a NEW_DEV client event message, the send it to all clients + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + usb_host_client_event_msg_t event_msg = { + .event = USB_HOST_CLIENT_EVENT_NEW_DEV, + .new_dev.address = dev_addr, + }; + send_event_msg_to_clients(&event_msg, true, 0); + break; + } + case USBH_EVENT_DEV_GONE: { + //Prepare event msg, send only to clients that have opened the device + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + usb_host_client_event_msg_t event_msg = { + .event = USB_HOST_CLIENT_EVENT_DEV_GONE, + .dev_gone.dev_hdl = dev_hdl, + }; + send_event_msg_to_clients(&event_msg, false, dev_addr); + break; + } + case USBH_EVENT_DEV_ALL_FREE: { + //Notify the lib handler that all devices are free + HOST_ENTER_CRITICAL(); + p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_ALL_FREE; + _unblock_lib(false); + HOST_EXIT_CRITICAL(); + break; + } + default: + abort(); //Should never occur + break; + } +} + +// ------------------- Client Related ---------------------- + +static bool pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr) +{ + endpoint_t *ep_obj = (endpoint_t *)user_arg; + client_t *client_obj = (client_t *)ep_obj->constant.intf_obj->constant.client_obj; + + HOST_ENTER_CRITICAL_SAFE(); + //Store the event to be handled later. Note that we allow overwriting of events because more severe will halt the pipe prevent any further events. + ep_obj->dynamic.last_event = pipe_event; + //Add the EP to the client's pending list if it's not in the list already + if (!ep_obj->dynamic.flags.pending) { + ep_obj->dynamic.flags.pending = 1; + TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, ep_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&client_obj->dynamic.pending_ep_tailq, ep_obj, dynamic.tailq_entry); + } + bool yield = _unblock_client(client_obj, in_isr); + HOST_EXIT_CRITICAL_SAFE(); + + return yield; +} + +// ------------------------------------------------ Library Functions -------------------------------------------------- + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_install(const usb_host_config_t *config) +{ + HOST_CHECK(config != NULL, ESP_ERR_INVALID_ARG); + HOST_ENTER_CRITICAL(); + HOST_CHECK_FROM_CRIT(p_host_lib_obj == NULL, ESP_ERR_INVALID_STATE); + HOST_EXIT_CRITICAL(); + + esp_err_t ret; + host_lib_t *host_lib_obj = heap_caps_calloc(1, sizeof(host_lib_t), MALLOC_CAP_DEFAULT); + SemaphoreHandle_t event_sem = xSemaphoreCreateBinary(); + SemaphoreHandle_t mux_lock = xSemaphoreCreateMutex(); + if (host_lib_obj == NULL || event_sem == NULL || mux_lock == NULL) { + ret = ESP_ERR_NO_MEM; + goto alloc_err; + } + //Initialize host library object + TAILQ_INIT(&host_lib_obj->mux_protected.client_tailq); + host_lib_obj->constant.event_sem = event_sem; + host_lib_obj->constant.mux_lock = mux_lock; + //Install USBH + usbh_config_t usbh_config = { + .notif_cb = notif_callback, + .notif_cb_arg = NULL, + .ctrl_xfer_cb = ctrl_xfer_callback, + .ctrl_xfer_cb_arg = NULL, + .event_cb = dev_event_callback, + .event_cb_arg = NULL, + .hcd_config = { + .intr_flags = config->intr_flags, + }, + }; + ret = usbh_install(&usbh_config); + if (ret != ESP_OK) { + goto usbh_err; + } + //Install Hub + hub_config_t hub_config = { + .notif_cb = notif_callback, + .notif_cb_arg = NULL, + }; + ret = hub_install(&hub_config); + if (ret != ESP_OK) { + goto hub_err; + } + + //Assign host library object + HOST_ENTER_CRITICAL(); + if (p_host_lib_obj != NULL) { + HOST_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + p_host_lib_obj = host_lib_obj; + HOST_EXIT_CRITICAL(); + + //Start the root hub + ESP_ERROR_CHECK(hub_root_start()); + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hub_uninstall()); +hub_err: + ESP_ERROR_CHECK(usbh_uninstall()); +usbh_err: +alloc_err: + if (mux_lock) { + vSemaphoreDelete(mux_lock); + } + if (event_sem) { + vSemaphoreDelete(event_sem); + } + heap_caps_free(host_lib_obj); + return ret; +} + +esp_err_t usb_host_uninstall(void) +{ + //All devices must have been freed at this point + HOST_ENTER_CRITICAL(); + HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE); + HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.process_pending_flags == 0 && + p_host_lib_obj->dynamic.lib_event_flags == 0 && + p_host_lib_obj->dynamic.flags.val == 0, + ESP_ERR_INVALID_STATE); + HOST_EXIT_CRITICAL(); + + //Stop the root hub + ESP_ERROR_CHECK(hub_root_stop()); + + //Uninstall Hub and USBH + ESP_ERROR_CHECK(hub_uninstall()); + ESP_ERROR_CHECK(usbh_uninstall()); + + HOST_ENTER_CRITICAL(); + host_lib_t *host_lib_obj = p_host_lib_obj; + p_host_lib_obj = NULL; + HOST_EXIT_CRITICAL(); + + //Free memory objects + vSemaphoreDelete(host_lib_obj->constant.mux_lock); + vSemaphoreDelete(host_lib_obj->constant.event_sem); + heap_caps_free(host_lib_obj); + return ESP_OK; +} + +esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret) +{ + esp_err_t ret; + uint32_t event_flags = 0; + + HOST_ENTER_CRITICAL(); + if (!p_host_lib_obj->dynamic.flags.process_pending) { + //There is currently processing that needs to be done. Wait for some processing + HOST_EXIT_CRITICAL(); + BaseType_t sem_ret = xSemaphoreTake(p_host_lib_obj->constant.event_sem, timeout_ticks); + if (sem_ret == pdFALSE) { + ret = ESP_ERR_TIMEOUT; + goto exit; + } + HOST_ENTER_CRITICAL(); + } + //Read and clear process pending flags + uint32_t process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags; + p_host_lib_obj->dynamic.process_pending_flags = 0; + p_host_lib_obj->dynamic.flags.handling_events = 1; + while (process_pending_flags) { + HOST_EXIT_CRITICAL(); + if (process_pending_flags & PROCESS_PENDING_FLAG_USBH) { + ESP_ERROR_CHECK(usbh_process()); + } + if (process_pending_flags & PROCESS_PENDING_FLAG_HUB) { + ESP_ERROR_CHECK(hub_process()); + } + HOST_ENTER_CRITICAL(); + //Read and clear process pending flags again, and loop back if there is more to process + process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags; + p_host_lib_obj->dynamic.process_pending_flags = 0; + } + p_host_lib_obj->dynamic.flags.process_pending = 0; + p_host_lib_obj->dynamic.flags.handling_events = 0; + event_flags = p_host_lib_obj->dynamic.lib_event_flags; + p_host_lib_obj->dynamic.lib_event_flags = 0; + HOST_EXIT_CRITICAL(); + + ret = ESP_OK; +exit: + if (event_flags_ret != NULL) { + *event_flags_ret = event_flags; + } + return ret; +} + +// ------------------------------------------------ Client Functions --------------------------------------------------- + +// ----------------------- Private ------------------------- + +static void _handle_pending_ep(client_t *client_obj) +{ + //Handle each EP on the pending list + while (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) { + //Get the next pending EP. + endpoint_t *ep_obj = TAILQ_FIRST(&client_obj->dynamic.pending_ep_tailq); + TAILQ_REMOVE(&client_obj->dynamic.pending_ep_tailq, ep_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, ep_obj, dynamic.tailq_entry); + ep_obj->dynamic.flags.pending = 0; + hcd_pipe_event_t last_event = ep_obj->dynamic.last_event; + uint32_t num_urb_dequeued = 0; + + HOST_EXIT_CRITICAL(); + //Handle pipe event + switch (last_event) { + case HCD_PIPE_EVENT_ERROR_XFER: + case HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL: + case HCD_PIPE_EVENT_ERROR_OVERFLOW: + case HCD_PIPE_EVENT_ERROR_STALL: + //The pipe is now stalled. Flush all pending URBs + ESP_ERROR_CHECK(hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_FLUSH)); + //All URBs in this pipe are now retired waiting to be dequeued. Fall through to dequeue them + __attribute__((fallthrough)); + case HCD_PIPE_EVENT_URB_DONE: { + //Dequeue all URBs and run their transfer callback + urb_t *urb = hcd_urb_dequeue(ep_obj->constant.pipe_hdl); + while (urb != NULL) { + urb->transfer.callback(&urb->transfer); + num_urb_dequeued++; + urb = hcd_urb_dequeue(ep_obj->constant.pipe_hdl); + } + break; + } + default: + abort(); //Should never occur + break; + } + HOST_ENTER_CRITICAL(); + + //Update the endpoint's number of URB's inflight + assert(num_urb_dequeued <= ep_obj->dynamic.num_urb_inflight); + ep_obj->dynamic.num_urb_inflight -= num_urb_dequeued; + } +} + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret) +{ + HOST_CHECK(client_config != NULL && client_hdl_ret != NULL, ESP_ERR_INVALID_ARG); + HOST_CHECK(client_config->client_event_callback != NULL && client_config->max_num_event_msg > 0, ESP_ERR_INVALID_ARG); + + esp_err_t ret; + //Create client object + client_t *client_obj = heap_caps_calloc(1, sizeof(client_t), MALLOC_CAP_DEFAULT); + SemaphoreHandle_t event_sem = xSemaphoreCreateBinary(); + QueueHandle_t event_msg_queue = xQueueCreate(client_config->max_num_event_msg, sizeof(usb_host_client_event_msg_t)); + if (client_obj == NULL || event_sem == NULL || event_msg_queue == NULL) { + ret = ESP_ERR_NO_MEM; + goto alloc_err; + } + //Initialize client object + TAILQ_INIT(&client_obj->dynamic.pending_ep_tailq); + TAILQ_INIT(&client_obj->dynamic.idle_ep_tailq); + TAILQ_INIT(&client_obj->mux_protected.interface_tailq); + TAILQ_INIT(&client_obj->dynamic.done_ctrl_xfer_tailq); + client_obj->constant.event_sem = event_sem; + client_obj->constant.event_callback = client_config->client_event_callback; + client_obj->constant.callback_arg = client_config->callback_arg; + client_obj->constant.event_msg_queue = event_msg_queue; + + //Add client to the host library's list of clients + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + HOST_ENTER_CRITICAL(); + p_host_lib_obj->dynamic.flags.num_clients++; + HOST_EXIT_CRITICAL(); + TAILQ_INSERT_TAIL(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry); + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + + //Write back client handle + *client_hdl_ret = (usb_host_client_handle_t)client_obj; + ret = ESP_OK; + return ret; + +alloc_err: + if (event_msg_queue) { + vQueueDelete(event_msg_queue); + } + if (event_sem) { + vSemaphoreDelete(event_sem); + } + heap_caps_free(client_obj); + return ESP_OK; +} + +esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl) +{ + HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + esp_err_t ret; + + //We take the mux_lock because we need to access the host library's client_tailq + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + HOST_ENTER_CRITICAL(); + //Check that client can currently deregistered + bool can_deregister; + if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) || + !TAILQ_EMPTY(&client_obj->dynamic.idle_ep_tailq) || + !TAILQ_EMPTY(&client_obj->dynamic.done_ctrl_xfer_tailq) || + client_obj->dynamic.flags.handling_events || + client_obj->dynamic.flags.blocked || + client_obj->dynamic.flags.taking_mux || + client_obj->dynamic.flags.num_intf_claimed != 0 || + client_obj->dynamic.num_done_ctrl_xfer != 0 || + client_obj->dynamic.opened_dev_addr_map != 0) { + can_deregister = false; + } else { + can_deregister = true; + } + HOST_EXIT_CRITICAL(); + if (!can_deregister) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + + //Remove client object from the library's list of clients + TAILQ_REMOVE(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry); + HOST_ENTER_CRITICAL(); + p_host_lib_obj->dynamic.flags.num_clients--; + if (p_host_lib_obj->dynamic.flags.num_clients == 0) { + //This is the last client being deregistered. Notify the lib handler + p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS; + _unblock_lib(false); + } + HOST_EXIT_CRITICAL(); + //Free client object + vQueueDelete(client_obj->constant.event_msg_queue); + vSemaphoreDelete(client_obj->constant.event_sem); + heap_caps_free(client_obj); + ret = ESP_OK; +exit: + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + return ret; +} + +esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks) +{ + HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG); + esp_err_t ret; + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + if (!client_obj->dynamic.flags.events_pending) { + //There are currently no events, wait for one to occur + client_obj->dynamic.flags.blocked = 1; + HOST_EXIT_CRITICAL(); + BaseType_t sem_ret = xSemaphoreTake(client_obj->constant.event_sem, timeout_ticks); + HOST_ENTER_CRITICAL(); + client_obj->dynamic.flags.blocked = 0; + if (sem_ret == pdFALSE) { + HOST_EXIT_CRITICAL(); + //Timed out waiting for semaphore + ret = ESP_ERR_TIMEOUT; + goto exit; + } + } + //Mark that we're processing events + client_obj->dynamic.flags.handling_events = 1; + while (client_obj->dynamic.flags.handling_events) { + //Handle pending endpoints + if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) { + _handle_pending_ep(client_obj); + } + //Handle any done control transfers + while (client_obj->dynamic.num_done_ctrl_xfer > 0) { + urb_t *urb = TAILQ_FIRST(&client_obj->dynamic.done_ctrl_xfer_tailq); + TAILQ_REMOVE(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry); + client_obj->dynamic.num_done_ctrl_xfer--; + HOST_EXIT_CRITICAL(); + //Call the transfer's callback + urb->transfer.callback(&urb->transfer); + HOST_ENTER_CRITICAL(); + } + //Handle event messages + while (uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) > 0) { + HOST_EXIT_CRITICAL(); + //Dequeue the event message and call the client event callback + usb_host_client_event_msg_t event_msg; + BaseType_t queue_ret = xQueueReceive(client_obj->constant.event_msg_queue, &event_msg, 0); + assert(queue_ret == pdTRUE); + client_obj->constant.event_callback(&event_msg, client_obj->constant.callback_arg); + HOST_ENTER_CRITICAL(); + } + //Check each event again to see any new events occurred + if (TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) && + client_obj->dynamic.num_done_ctrl_xfer == 0 && + uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) == 0) { + //All pending endpoints and event messages handled + client_obj->dynamic.flags.events_pending = 0; + client_obj->dynamic.flags.handling_events = 0; + } + } + HOST_EXIT_CRITICAL(); + + ret = ESP_OK; +exit: + return ret; +} + +esp_err_t usb_host_client_unblock(usb_host_client_handle_t client_hdl) +{ + HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + _unblock_client(client_obj, false); + HOST_EXIT_CRITICAL(); + + return ESP_OK; +} + +// ------------------------------------------------- Device Handling --------------------------------------------------- + +esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_addr, usb_device_handle_t *dev_hdl_ret) +{ + HOST_CHECK(dev_addr > 0 && client_hdl != NULL && dev_hdl_ret != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + esp_err_t ret; + usb_device_handle_t dev_hdl; + ret = usbh_dev_open(dev_addr, &dev_hdl); + if (ret != ESP_OK) { + goto exit; + } + + HOST_ENTER_CRITICAL(); + if (_check_client_opened_device(client_obj, dev_addr)) { + //Client has already opened the device. Close it and return an error + ret = ESP_ERR_INVALID_STATE; + HOST_EXIT_CRITICAL(); + goto already_opened; + } + //Record in client object that we have opened the device of this address + _record_client_opened_device(client_obj, dev_addr); + HOST_EXIT_CRITICAL(); + + *dev_hdl_ret = dev_hdl; + ret = ESP_OK; + return ret; + +already_opened: + ESP_ERROR_CHECK(usbh_dev_close(dev_hdl)); +exit: + return ret; +} + +esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl) +{ + HOST_CHECK(dev_hdl != NULL && client_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + //We take the lock because we need to walk the interface list + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + esp_err_t ret; + //Check that all interfaces claimed by this client do not belong to this device + bool all_released = true; + interface_t *intf_obj; + TAILQ_FOREACH(intf_obj, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) { + if (intf_obj->constant.dev_hdl == dev_hdl) { + all_released = false; + break; + } + } + if (!all_released) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + + //Check that client actually opened the device in the first place + HOST_ENTER_CRITICAL(); + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_NOT_FOUND); + if (!_check_client_opened_device(client_obj, dev_addr)) { + //Client never opened this device + ret = ESP_ERR_INVALID_STATE; + HOST_EXIT_CRITICAL(); + goto exit; + } + //Proceed to clear the record of the device form the client + _clear_client_opened_device(client_obj, dev_addr); + HOST_EXIT_CRITICAL(); + + ESP_ERROR_CHECK(usbh_dev_close(dev_hdl)); + ret = ESP_OK; +exit: + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + return ret; +} + +esp_err_t usb_host_device_free_all(void) +{ + HOST_ENTER_CRITICAL(); + HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.flags.num_clients == 0, ESP_ERR_INVALID_STATE); //All clients must have been deregistered + HOST_EXIT_CRITICAL(); + esp_err_t ret; + ret = usbh_dev_mark_all_free(); + //Wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices free + return ret; +} + +// ------------------------------------------------- Device Requests --------------------------------------------------- + +// ------------------- Cached Requests --------------------- + +esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info) +{ + HOST_CHECK(dev_hdl != NULL && dev_info != NULL, ESP_ERR_INVALID_ARG); + return usbh_dev_get_info(dev_hdl, dev_info); +} + +// ----------------------------------------------- Descriptor Requests ------------------------------------------------- + +// ----------------- Cached Descriptors -------------------- + +esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc) +{ + HOST_CHECK(dev_hdl != NULL && device_desc != NULL, ESP_ERR_INVALID_ARG); + return usbh_dev_get_desc(dev_hdl, device_desc); +} + +esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc) +{ + HOST_CHECK(dev_hdl != NULL && config_desc != NULL, ESP_ERR_INVALID_ARG); + return usbh_dev_get_config_desc(dev_hdl, config_desc); +} + +// ----------------------------------------------- Interface Functions ------------------------------------------------- + +// ----------------------- Private ------------------------- + +static esp_err_t endpoint_alloc(usb_device_handle_t dev_hdl, const usb_ep_desc_t *ep_desc, interface_t *intf_obj, endpoint_t **ep_obj_ret) +{ + endpoint_t *ep_obj = heap_caps_calloc(1, sizeof(endpoint_t), MALLOC_CAP_DEFAULT); + if (ep_obj == NULL) { + return ESP_ERR_NO_MEM; + } + esp_err_t ret; + usbh_ep_config_t ep_config = { + .ep_desc = ep_desc, + .pipe_cb = pipe_callback, + .pipe_cb_arg = (void *)ep_obj, + .context = (void *)ep_obj, + }; + hcd_pipe_handle_t pipe_hdl; + ret = usbh_ep_alloc(dev_hdl, &ep_config, &pipe_hdl); + if (ret != ESP_OK) { + goto ep_alloc_err; + } + //Initialize endpoint object + ep_obj->constant.pipe_hdl = pipe_hdl; + ep_obj->constant.ep_desc = ep_desc; + ep_obj->constant.intf_obj = intf_obj; + //Write back result + *ep_obj_ret = ep_obj; + ret = ESP_OK; + return ret; + +ep_alloc_err: + heap_caps_free(ep_obj); + return ret; +} + +static void endpoint_free(usb_device_handle_t dev_hdl, endpoint_t *ep_obj) +{ + if (ep_obj == NULL) { + return; + } + //Free the underlying endpoint + ESP_ERROR_CHECK(usbh_ep_free(dev_hdl, ep_obj->constant.ep_desc->bEndpointAddress)); + //Free the endpoint object + heap_caps_free(ep_obj); +} + +static interface_t *interface_alloc(client_t *client_obj, usb_device_handle_t dev_hdl, const usb_intf_desc_t *intf_desc) +{ + interface_t *intf_obj = heap_caps_calloc(1, sizeof(interface_t) + (sizeof(endpoint_t *) * intf_desc->bNumEndpoints), MALLOC_CAP_DEFAULT); + if (intf_obj == NULL) { + return NULL; + } + intf_obj->constant.intf_desc = intf_desc; + intf_obj->constant.client_obj = client_obj; + intf_obj->constant.dev_hdl = dev_hdl; + return intf_obj; +} + +static void interface_free(interface_t *intf_obj) +{ + if (intf_obj == NULL) { + return; + } + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + assert(intf_obj->constant.endpoints[i] == NULL); + } + heap_caps_free(intf_obj); +} + +static esp_err_t interface_claim(client_t *client_obj, usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, interface_t **intf_obj_ret) +{ + esp_err_t ret; + //We need to walk to configuration descriptor to find the correct interface descriptor, and each of its constituent endpoint descriptors + //Find the interface descriptor and allocate the interface object + int offset_intf; + const usb_intf_desc_t *intf_desc = usb_host_parse_interface(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); + if (intf_desc == NULL) { + ret = ESP_ERR_NOT_FOUND; + goto exit; + } + //Allocate interface object + interface_t *intf_obj = interface_alloc(client_obj, dev_hdl, intf_desc); + if (intf_obj == NULL) { + ret = ESP_ERR_NO_MEM; + goto exit; + } + //Find each endpoint descriptor in the interface by index, and allocate those endpoints + for (int i = 0; i < intf_desc->bNumEndpoints; i++) { + int offset_ep = offset_intf; + const usb_ep_desc_t *ep_desc = usb_host_parse_endpoint_by_index(intf_desc, i, config_desc->wTotalLength, &offset_ep); + if (ep_desc == NULL) { + ret = ESP_ERR_NOT_FOUND; + goto ep_alloc_err; + } + //Allocate the endpoint + endpoint_t *ep_obj; + ret = endpoint_alloc(dev_hdl, ep_desc, intf_obj, &ep_obj); + if (ret != ESP_OK) { + goto ep_alloc_err; + } + //Store endpoint object into interface object + intf_obj->constant.endpoints[i] = ep_obj; + } + //Add interface object to client (safe because we have already taken the mutex) + TAILQ_INSERT_TAIL(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry); + //Add each endpoint to the client's endpoint list + HOST_ENTER_CRITICAL(); + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry); + } + HOST_EXIT_CRITICAL(); + //Write back result + *intf_obj_ret = intf_obj; + ret = ESP_OK; + return ret; + +ep_alloc_err: + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + endpoint_free(dev_hdl, intf_obj->constant.endpoints[i]); + intf_obj->constant.endpoints[i] = NULL; + } + interface_free(intf_obj); +exit: + return ret; +} + +static esp_err_t interface_release(client_t *client_obj, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber) +{ + esp_err_t ret; + //Find the interface object + interface_t *intf_obj_iter; + interface_t *intf_obj = NULL; + TAILQ_FOREACH(intf_obj_iter, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) { + if (intf_obj_iter->constant.dev_hdl == dev_hdl && intf_obj_iter->constant.intf_desc->bInterfaceNumber == bInterfaceNumber) { + intf_obj = intf_obj_iter; + break; + } + } + if (intf_obj == NULL) { + ret = ESP_ERR_NOT_FOUND; + goto exit; + } + + //Check that all endpoints in the interface are in a state to be freed + HOST_ENTER_CRITICAL(); + bool can_free = true; + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + endpoint_t *ep_obj = intf_obj->constant.endpoints[i]; + //Endpoint must not be on the pending list and must not have inflight URBs + if (ep_obj->dynamic.num_urb_inflight != 0 || ep_obj->dynamic.flags.pending) { + can_free = false; + break; + } + } + if (!can_free) { + HOST_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Proceed to remove all endpoint objects from list + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry); + } + HOST_EXIT_CRITICAL(); + + //Remove the interface object from the list (safe because we have already taken the mutex) + TAILQ_REMOVE(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry); + + //Free each endpoint in the interface + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + endpoint_free(dev_hdl, intf_obj->constant.endpoints[i]); + intf_obj->constant.endpoints[i] = NULL; + } + //Free the interface object itself + interface_free(intf_obj); + ret = ESP_OK; +exit: + return ret; +} + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting) +{ + HOST_CHECK(client_hdl != NULL && dev_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + //Check if client actually opened device + HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE); + client_obj->dynamic.flags.taking_mux = 1; + HOST_EXIT_CRITICAL(); + + //Take mux lock. This protects the client being released or other clients from claiming interfaces + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + esp_err_t ret; + const usb_config_desc_t *config_desc; + ESP_ERROR_CHECK(usbh_dev_get_config_desc(dev_hdl, &config_desc)); + interface_t *intf_obj; + //Claim interface + ret = interface_claim(client_obj, dev_hdl, config_desc, bInterfaceNumber, bAlternateSetting, &intf_obj); + if (ret != ESP_OK) { + goto exit; + } + ret = ESP_OK; +exit: + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + + HOST_ENTER_CRITICAL(); + if (ret == ESP_OK) { + client_obj->dynamic.flags.num_intf_claimed++; + } + client_obj->dynamic.flags.taking_mux = 0; + HOST_EXIT_CRITICAL(); + return ret; +} + +esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber) +{ + HOST_CHECK(client_hdl != NULL && dev_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + //Check if client actually opened device + HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE); + client_obj->dynamic.flags.taking_mux = 1; + HOST_EXIT_CRITICAL(); + + //Take mux lock. This protects the client being released or other clients from claiming interfaces + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + esp_err_t ret = interface_release(client_obj, dev_hdl, bInterfaceNumber); + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + + HOST_ENTER_CRITICAL(); + if (ret == ESP_OK) { + client_obj->dynamic.flags.num_intf_claimed--; + } + client_obj->dynamic.flags.taking_mux = 0; + HOST_EXIT_CRITICAL(); + + return ret; +} + +esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + esp_err_t ret; + endpoint_t *ep_obj = NULL; + ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto exit; + } + assert(ep_obj != NULL); + ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_HALT); +exit: + return ret; +} + +esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + esp_err_t ret; + endpoint_t *ep_obj = NULL; + ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto exit; + } + assert(ep_obj != NULL); + ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_FLUSH); +exit: + return ret; +} + +esp_err_t usb_host_endpoint_clear(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + esp_err_t ret; + endpoint_t *ep_obj = NULL; + ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto exit; + } + assert(ep_obj != NULL); + ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_CLEAR); +exit: + return ret; +} + +// ------------------------------------------------ Asynchronous I/O --------------------------------------------------- + +// ----------------------- Private ------------------------- + +static bool transfer_check(usb_transfer_t *transfer, usb_transfer_type_t type, int mps, bool is_in) +{ + if (transfer->callback == NULL) { + ESP_LOGE(USB_HOST_TAG, "Transfer callback is NULL"); + return false; + } + //Check that the total transfer length does not exceed data buffer size + if (transfer->num_bytes > transfer->data_buffer_size) { + ESP_LOGE(USB_HOST_TAG, "Transfer num_bytes > data_buffer_size"); + return false; + } + if (type == USB_TRANSFER_TYPE_CTRL) { + //Check that num_bytes and wLength are set correctly + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)transfer->data_buffer; + if (transfer->num_bytes != sizeof(usb_setup_packet_t) + setup_pkt->wLength) { + ESP_LOGE(USB_HOST_TAG, "Control transfer num_bytes wLength mismatch"); + return false; + } + } else if (type == USB_TRANSFER_TYPE_ISOCHRONOUS) { + //Check that there is at least one isochronous packet descriptor + if (transfer->num_isoc_packets <= 0) { + ESP_LOGE(USB_HOST_TAG, "ISOC transfer has 0 packet descriptors"); + return false; + } + //Check that sum of all packet lengths add up to transfer length + //If IN, check that each packet length is integer multiple of MPS + int total_num_bytes = 0; + bool mod_mps_all_zero = true; + for (int i = 0; i < transfer->num_isoc_packets; i++) { + total_num_bytes += transfer->isoc_packet_desc[i].num_bytes; + if (transfer->isoc_packet_desc[i].num_bytes % mps != 0) { + mod_mps_all_zero = false; + } + } + if (transfer->num_bytes != total_num_bytes) { + ESP_LOGE(USB_HOST_TAG, "ISOC transfer num_bytes not equal to total num_bytes of all packets"); + return false; + } + if (is_in && !mod_mps_all_zero) { + ESP_LOGE(USB_HOST_TAG, "ISOC IN transfer all packets num_bytes must be integer multiple of MPS"); + return false; + } + } else { + //Check that IN transfers are integer multiple of MPS + if (is_in && (transfer->num_bytes % mps != 0)) { + ESP_LOGE(USB_HOST_TAG, "IN transfer num_bytes must be integer multiple of MPS"); + return false; + } + } + return true; +} + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer) +{ + urb_t *urb = urb_alloc(data_buffer_size, 0, num_isoc_packets); + if (urb == NULL) { + return ESP_ERR_NO_MEM; + } + *transfer = &urb->transfer; + return ESP_OK; +} + +esp_err_t usb_host_transfer_free(usb_transfer_t *transfer) +{ + HOST_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG); + urb_t *urb = __containerof(transfer, urb_t, transfer); + urb_free(urb); + return ESP_OK; +} + +esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer) +{ + HOST_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG); + //Check that transfer and target endpoint are valid + HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set + HOST_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) != 0, ESP_ERR_INVALID_ARG); + endpoint_t *ep_obj = NULL; + urb_t *urb_obj = __containerof(transfer, urb_t, transfer); + esp_err_t ret; + ret = usbh_ep_get_context(transfer->device_handle, transfer->bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto err; + } + assert(ep_obj != NULL); + HOST_CHECK(transfer_check(transfer, + USB_EP_DESC_GET_XFERTYPE(ep_obj->constant.ep_desc), + USB_EP_DESC_GET_MPS(ep_obj->constant.ep_desc), + transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK), ESP_ERR_INVALID_ARG); + HOST_ENTER_CRITICAL(); + ep_obj->dynamic.num_urb_inflight++; + HOST_EXIT_CRITICAL(); + //Check if pipe is in a state to enqueue URBs + if (hcd_pipe_get_state(ep_obj->constant.pipe_hdl) != HCD_PIPE_STATE_ACTIVE) { + ret = ESP_ERR_INVALID_STATE; + goto hcd_err; + } + ret = hcd_urb_enqueue(ep_obj->constant.pipe_hdl, urb_obj); + if (ret != ESP_OK) { + goto hcd_err; + } + ret = ESP_OK; + return ret; + +hcd_err: + HOST_ENTER_CRITICAL(); + ep_obj->dynamic.num_urb_inflight--; + HOST_EXIT_CRITICAL(); +err: + return ret; +} + +esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer) +{ + HOST_CHECK(client_hdl != NULL && transfer != NULL, ESP_ERR_INVALID_ARG); + //Check that control transfer is valid + HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set + usb_device_handle_t dev_hdl = transfer->device_handle; + bool xfer_is_in = ((usb_setup_packet_t *)transfer->data_buffer)->bmRequestType & USB_BM_REQUEST_TYPE_DIR_OUT; + usb_device_info_t dev_info; + ESP_ERROR_CHECK(usbh_dev_get_info(dev_hdl, &dev_info)); + HOST_CHECK(transfer_check(transfer, USB_TRANSFER_TYPE_CTRL, dev_info.bMaxPacketSize0, xfer_is_in), ESP_ERR_INVALID_ARG); + HOST_CHECK(transfer->bEndpointAddress == 0, ESP_ERR_INVALID_ARG); + //Save client handle into URB + urb_t *urb_obj = __containerof(transfer, urb_t, transfer); + urb_obj->usb_host_client = (void *)client_hdl; + return usbh_dev_submit_ctrl_urb(dev_hdl, urb_obj); +} diff --git a/components/usb/usb_host_misc.c b/components/usb/usb_host_misc.c new file mode 100644 index 0000000000..072b547e31 --- /dev/null +++ b/components/usb/usb_host_misc.c @@ -0,0 +1,168 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "usb/usb_host_misc.h" +#include "usb/usb_types_ch9.h" + +// ---------------------------------------- Configuration Descriptor Parsing ------------------------------------------- + +const usb_standard_desc_t *usb_host_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset) +{ + assert(cur_desc != NULL && offset != NULL); + if (*offset >= wTotalLength) { + return NULL; //We have traversed the entire configuration descriptor + } + if (*offset + cur_desc->bLength >= wTotalLength) { + return NULL; //Next descriptor is out of bounds + } + //Return the next descriptor, update offset + const usb_standard_desc_t *ret_desc = (const usb_standard_desc_t *)(((uint32_t)cur_desc) + cur_desc->bLength); + *offset += cur_desc->bLength; + return ret_desc; +} + +const usb_standard_desc_t *usb_host_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset) +{ + assert(cur_desc != NULL && offset != NULL); + int offset_temp = *offset; //We only want to update offset if we've actually found a descriptor + //Keep stepping over descriptors until we find one of bDescriptorType or until we go out of bounds + const usb_standard_desc_t *ret_desc = usb_host_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp); + while (ret_desc != NULL) { + if (ret_desc->bDescriptorType == bDescriptorType) { + break; + } + ret_desc = usb_host_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp); + } + if (ret_desc != NULL) { + //We've found a descriptor. Update the offset + *offset = offset_temp; + } + return ret_desc; +} + +int usb_host_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber) +{ + assert(config_desc != NULL); + int offset = 0; + //Find the first interface descriptor of bInterfaceNumber + const usb_intf_desc_t *first_intf_desc = usb_host_parse_interface(config_desc, bInterfaceNumber, 0, &offset); + if (first_intf_desc == NULL) { + return -1; //bInterfaceNumber not found + } + + int num_alt_setting = 0; + const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)first_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + while (next_intf_desc != NULL) { + if (next_intf_desc->bInterfaceNumber != bInterfaceNumber) { + break; + } + num_alt_setting++; + next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + } + return num_alt_setting; +} + +const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset) +{ + assert(config_desc != NULL); + if (bInterfaceNumber >= config_desc->bNumInterfaces) { + return NULL; //bInterfaceNumber is out of range + } + + //Walk to first interface descriptor of bInterfaceNumber + int offset_temp = 0; + const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + while (next_intf_desc != NULL) { + if (next_intf_desc->bInterfaceNumber == bInterfaceNumber) { + break; //We found the first interface descriptor with matching bInterfaceNumber + } + next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + } + if (next_intf_desc == NULL) { + return NULL; //Couldn't find a interface with bInterfaceNumber + } + + //Keep walking until an interface descriptor matching bInterfaceNumber and bAlternateSetting is found + while (next_intf_desc != NULL) { + if (next_intf_desc->bInterfaceNumber == bInterfaceNumber + 1) { + //We've walked past our target bInterfaceNumber + next_intf_desc = NULL; + break; + } + if (next_intf_desc->bAlternateSetting == bAlternateSetting) { + //We've found our target interface descriptor + break; + } + //Get the next interface descriptor + next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + } + if (next_intf_desc != NULL && offset != NULL) { + *offset = offset_temp; + } + return next_intf_desc; +} + +const usb_ep_desc_t *usb_host_parse_endpoint_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset) +{ + assert(intf_desc != NULL && offset != NULL); + if (index >= intf_desc->bNumEndpoints) { + return NULL; //Index is out of range + } + //Walk to the Nth endpoint descriptor we find + int offset_temp = *offset; + bool ep_found = true; + const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)intf_desc; + for (int i = 0; i <= index; i++) { + next_desc = usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_desc, wTotalLength, USB_B_DESCRIPTOR_TYPE_ENDPOINT, &offset_temp); + if (next_desc == NULL) { + ep_found = false; + break; + } + } + if (ep_found) { + *offset = offset_temp; + return (const usb_ep_desc_t *)next_desc; + } + return NULL; +} + +const usb_ep_desc_t *usb_host_parse_endpoint_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset) +{ + assert(config_desc != NULL); + + //Find the interface descriptor + int offset_intf; + const usb_intf_desc_t *intf_desc = usb_host_parse_interface(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); + if (intf_desc == NULL) { + return NULL; + } + + //Walk endpoint descriptors until one matching bEndpointAddress is found + int offset_ep; + bool ep_found = false; + const usb_ep_desc_t *ep_desc = NULL; + for (int index = 0; index < intf_desc->bNumEndpoints; index++) { + offset_ep = offset_intf; + ep_desc = usb_host_parse_endpoint_by_index(intf_desc, index, config_desc->wTotalLength, &offset_ep); + if (ep_desc == NULL) { + break; + } + if (ep_desc->bEndpointAddress == bEndpointAddress) { + ep_found = true; + break; + } + } + if (ep_found && offset != NULL) { + *offset = offset_ep; + } + return ep_desc; +} + +// ------------------------------------------------------ Misc --------------------------------------------------------- diff --git a/components/usb/usb_private.c b/components/usb/usb_private.c new file mode 100644 index 0000000000..1ab0448a6f --- /dev/null +++ b/components/usb/usb_private.c @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_heap_caps.h" +#include "usb_private.h" +#include "usb/usb_types_ch9.h" + +urb_t *urb_alloc(size_t data_buffer_size, size_t header_size, int num_isoc_packets) +{ + urb_t *urb = heap_caps_calloc(1, sizeof(urb_t) + (sizeof(usb_isoc_packet_desc_t) * num_isoc_packets), MALLOC_CAP_DEFAULT); + uint8_t *data_buffer = heap_caps_malloc(data_buffer_size + header_size, MALLOC_CAP_DMA); + if (urb == NULL || data_buffer == NULL) { + goto err; + } + urb->usb_host_header_size = header_size; //Indicate that this URB's data_buffer has a header in front of it. + //Case as dummy transfer to write to initialize const fields + usb_transfer_dummy_t *dummy_transfer = (usb_transfer_dummy_t *)&urb->transfer; + dummy_transfer->data_buffer = (uint8_t *)(data_buffer + header_size); + dummy_transfer->data_buffer_size = data_buffer_size; + dummy_transfer->num_isoc_packets = num_isoc_packets; + return urb; +err: + heap_caps_free(urb); + heap_caps_free(data_buffer); + return NULL; +} + +void urb_free(urb_t *urb) +{ + if (urb == NULL) { + return; + } + heap_caps_free((uint8_t *)(urb->transfer.data_buffer - urb->usb_host_header_size)); + heap_caps_free(urb); +} diff --git a/components/usb/usbh.c b/components/usb/usbh.c new file mode 100644 index 0000000000..d05cf6a000 --- /dev/null +++ b/components/usb/usbh.c @@ -0,0 +1,909 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/task.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "hcd.h" +#include "usbh.h" +#include "usb/usb_host_misc.h" +#include "usb/usb_types_ch9.h" + +//Device action flags. Listed in the order they should handled in. Some actions are mutually exclusive +#define DEV_FLAG_ACTION_SEND_GONE_EVENT 0x01 //Send a USB_HOST_CLIENT_EVENT_DEV_GONE event +#define DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH 0x02 //Retire all URBS in the default pipe +#define DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE 0x04 //Dequeue all URBs from default pipe +#define DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR 0x08 //Move the default pipe to the active state +#define DEV_FLAG_ACTION_FREE 0x10 //Free the device object +#define DEV_FLAG_ACTION_PORT_DISABLE 0x20 +#define DEV_FLAG_ACTION_SEND_NEW 0x40 //Send a new device event + +#define DEV_ENUM_TODO_FLAG_DEV_ADDR 0x01 +#define DEV_ENUM_TODO_FLAG_DEV_DESC 0x02 +#define DEV_ENUM_TODO_FLAG_CONFIG_DESC 0x04 + +#define EP_NUM_MIN 1 +#define EP_NUM_MAX 16 + +typedef struct device_s device_t; +struct device_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(device_s) tailq_entry; + union { + struct { + uint32_t actions: 8; + uint32_t in_pending_list: 1; + uint32_t is_gone: 1; + uint32_t waiting_close: 1; + uint32_t waiting_port_disable: 1; + uint32_t waiting_free: 1; + uint32_t reserved19: 19; + }; + uint32_t val; + } flags; + int num_ctrl_xfers_inflight; + usb_device_state_t state; + uint32_t ref_count; + usb_config_desc_t *config_desc; + hcd_pipe_handle_t ep_in[EP_NUM_MAX - 1]; //IN EP owner contexts. -1 to exclude the default endpoint + hcd_pipe_handle_t ep_out[EP_NUM_MAX - 1]; //OUT EP owner contexts. -1 to exclude the default endpoint + } dynamic; + //Constant members do no change after device allocation and enumeration thus do not require a critical section + struct { + hcd_pipe_handle_t default_pipe; + hcd_port_handle_t port_hdl; + uint8_t address; + usb_speed_t speed; + const usb_device_desc_t *desc; + uint32_t enum_todo_flags; + } constant; +}; + +typedef struct { + //Dynamic members require a critical section + struct { + TAILQ_HEAD(tailhead_devs, device_s) devs_idle_tailq; //Tailq of all enum and configured devices + TAILQ_HEAD(tailhead_devs_cb, device_s) devs_pending_tailq; //Tailq of devices that need to have their cb called + uint8_t num_device; //Number of enumerated devices + } dynamic; + //Constant members do no change after installation thus do not require a critical section + struct { + usb_notif_cb_t notif_cb; + void *notif_cb_arg; + usbh_hub_cb_t hub_cb; + void *hub_cb_arg; + usbh_event_cb_t event_cb; + void *event_cb_arg; + usbh_ctrl_xfer_cb_t ctrl_xfer_cb; + void *ctrl_xfer_cb_arg; + } constant; +} usbh_t; + +static usbh_t *p_usbh_obj = NULL; + +static portMUX_TYPE usbh_lock = portMUX_INITIALIZER_UNLOCKED; + +const char *USBH_TAG = "USBH"; + +#define USBH_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&usbh_lock) +#define USBH_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&usbh_lock) +#define USBH_ENTER_CRITICAL() portENTER_CRITICAL(&usbh_lock) +#define USBH_EXIT_CRITICAL() portEXIT_CRITICAL(&usbh_lock) +#define USBH_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&usbh_lock) +#define USBH_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&usbh_lock) + +#define USBH_CHECK(cond, ret_val) ({ \ + if (!(cond)) { \ + return (ret_val); \ + } \ +}) +#define USBH_CHECK_FROM_CRIT(cond, ret_val) ({ \ + if (!(cond)) { \ + USBH_EXIT_CRITICAL(); \ + return ret_val; \ + } \ +}) + +// --------------------------------------------------- Allocation ------------------------------------------------------ + +static esp_err_t device_alloc(hcd_port_handle_t port_hdl, usb_speed_t speed, device_t **dev_obj_ret) +{ + esp_err_t ret; + device_t *dev_obj = heap_caps_calloc(1, sizeof(device_t), MALLOC_CAP_DEFAULT); + usb_device_desc_t *dev_desc = heap_caps_calloc(1, sizeof(usb_device_desc_t), MALLOC_CAP_DEFAULT); + if (dev_obj == NULL || dev_desc == NULL) { + ret = ESP_ERR_NO_MEM; + goto err; + } + //Allocate default pipe. We set the pipe callback to NULL for now + hcd_pipe_config_t pipe_config = { + .callback = NULL, + .callback_arg = NULL, + .context = (void *)dev_obj, + .ep_desc = NULL, //No endpoint descriptor means we're allocating a default pipe + .dev_speed = speed, + .dev_addr = 0, + }; + hcd_pipe_handle_t default_pipe_hdl; + ret = hcd_pipe_alloc(port_hdl, &pipe_config, &default_pipe_hdl); + if (ret != ESP_OK) { + goto err; + } + //Initialize device object + dev_obj->dynamic.state = USB_DEVICE_STATE_DEFAULT; + dev_obj->constant.default_pipe = default_pipe_hdl; + dev_obj->constant.port_hdl = port_hdl; + //Note: dev_obj->constant.address is assigned later during enumeration + dev_obj->constant.speed = speed; + dev_obj->constant.desc = dev_desc; + dev_obj->constant.enum_todo_flags = (DEV_ENUM_TODO_FLAG_DEV_ADDR | DEV_ENUM_TODO_FLAG_DEV_DESC | DEV_ENUM_TODO_FLAG_CONFIG_DESC); + *dev_obj_ret = dev_obj; + ret = ESP_OK; + return ret; + +err: + heap_caps_free(dev_desc); + heap_caps_free(dev_obj); + return ret; +} + +static void device_free(device_t *dev_obj) +{ + if (dev_obj == NULL) { + return; + } + //Configuration must be freed + assert(dev_obj->dynamic.config_desc == NULL); + ESP_ERROR_CHECK(hcd_pipe_free(dev_obj->constant.default_pipe)); + heap_caps_free((usb_device_desc_t *)dev_obj->constant.desc); + heap_caps_free(dev_obj); +} + +// -------------------------------------------------- Event Related ---------------------------------------------------- + +static bool _dev_set_actions(device_t *dev_obj, uint32_t action_flags) +{ + if (action_flags == 0) { + return false; + } + bool call_notif_cb; + //Check if device is already on the callback list + if (!dev_obj->dynamic.flags.in_pending_list) { + //Move device form idle device list to callback device list + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry); + dev_obj->dynamic.flags.actions |= action_flags; + dev_obj->dynamic.flags.in_pending_list = 1; + call_notif_cb = true; + } else { + call_notif_cb = false; + } + return call_notif_cb; +} + +static bool default_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr) +{ + uint32_t action_flags; + device_t *dev_obj = (device_t *)user_arg; + switch (pipe_event) { + case HCD_PIPE_EVENT_URB_DONE: + //A control transfer completed on the default pipe. We need to dequeue it + action_flags = DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE; + break; + case HCD_PIPE_EVENT_ERROR_XFER: + case HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL: + case HCD_PIPE_EVENT_ERROR_OVERFLOW: + //The default pipe has encountered an error. We need to retire all URBs, dequeue them, then make the pipe active again + action_flags = DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH | + DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE | + DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR; + if (in_isr) { + ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address); + } else { + ESP_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address); + } + break; + case HCD_PIPE_EVENT_ERROR_STALL: + //The default pipe encountered a "protocol stall". We just need to dequeue URBs then make the pipe active again + action_flags = DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE | DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR; + if (in_isr) { + ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address); + } else { + ESP_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address); + } + break; + default: + action_flags = 0; + break; + } + + USBH_ENTER_CRITICAL_SAFE(); + bool call_notif_cb = _dev_set_actions(dev_obj, action_flags); + USBH_EXIT_CRITICAL_SAFE(); + + bool yield = false; + if (call_notif_cb) { + yield = p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, in_isr, p_usbh_obj->constant.notif_cb_arg); + } + return yield; +} + +static bool handle_dev_free(device_t *dev_obj) +{ + USBH_ENTER_CRITICAL(); + //Remove the device object for it's containing list + if (dev_obj->dynamic.flags.in_pending_list) { + dev_obj->dynamic.flags.in_pending_list = 0; + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry); + } else { + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); + } + p_usbh_obj->dynamic.num_device--; + bool all_free = (p_usbh_obj->dynamic.num_device == 0); + USBH_EXIT_CRITICAL(); + + heap_caps_free(dev_obj->dynamic.config_desc); + dev_obj->dynamic.config_desc = NULL; + device_free(dev_obj); + return all_free; +} + +// ------------------------------------------------- USBH Functions ---------------------------------------------------- + +esp_err_t usbh_install(const usbh_config_t *usbh_config) +{ + USBH_CHECK(usbh_config != NULL, ESP_ERR_INVALID_ARG); + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(p_usbh_obj == NULL, ESP_ERR_INVALID_STATE); + USBH_EXIT_CRITICAL(); + + usbh_t *usbh_obj = heap_caps_calloc(1, sizeof(usbh_t), MALLOC_CAP_DEFAULT); + if (usbh_obj == NULL) { + return ESP_ERR_NO_MEM; + } + esp_err_t ret; + //Install HCD + ret = hcd_install(&usbh_config->hcd_config); + if (ret != ESP_OK) { + goto hcd_install_err; + } + //Initialize usbh object + TAILQ_INIT(&usbh_obj->dynamic.devs_idle_tailq); + TAILQ_INIT(&usbh_obj->dynamic.devs_pending_tailq); + usbh_obj->constant.notif_cb = usbh_config->notif_cb; + usbh_obj->constant.notif_cb_arg = usbh_config->notif_cb_arg; + usbh_obj->constant.event_cb = usbh_config->event_cb; + usbh_obj->constant.event_cb_arg = usbh_config->event_cb_arg; + usbh_obj->constant.ctrl_xfer_cb = usbh_config->ctrl_xfer_cb; + usbh_obj->constant.ctrl_xfer_cb_arg = usbh_config->ctrl_xfer_cb_arg; + + //Assign usbh object pointer + USBH_ENTER_CRITICAL(); + if (p_usbh_obj != NULL) { + USBH_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + p_usbh_obj = usbh_obj; + USBH_EXIT_CRITICAL(); + + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hcd_uninstall()); +hcd_install_err: + heap_caps_free(usbh_obj); + return ret; +} + +esp_err_t usbh_uninstall(void) +{ + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE); + //Check that USBH is in a state to be uninstalled + USBH_CHECK_FROM_CRIT(p_usbh_obj->dynamic.num_device == 0, ESP_ERR_INVALID_STATE); + usbh_t *usbh_obj = p_usbh_obj; + p_usbh_obj = NULL; + USBH_EXIT_CRITICAL(); + + //Uninstall HCD + ESP_ERROR_CHECK(hcd_uninstall()); + heap_caps_free(usbh_obj); + return ESP_OK; +} + +esp_err_t usbh_process(void) +{ + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE); + //Keep clearing devices with events + while (!TAILQ_EMPTY(&p_usbh_obj->dynamic.devs_pending_tailq)){ + //Move the device back into the idle device list, + device_t *dev_obj = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq); + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); + //Clear the device's flags + uint32_t action_flags = dev_obj->dynamic.flags.actions; + dev_obj->dynamic.flags.actions = 0; + dev_obj->dynamic.flags.in_pending_list = 0; + + USBH_EXIT_CRITICAL(); + ESP_LOGD(USBH_TAG, "Processing actions 0x%x", action_flags); + //Sanity check. If the device is being freed, there must not be any other action flags set + assert(!(action_flags & DEV_FLAG_ACTION_FREE) || action_flags == DEV_FLAG_ACTION_FREE); + if (action_flags & DEV_FLAG_ACTION_SEND_GONE_EVENT) { + //Flush the default pipe. Then do an event gone + ESP_LOGE(USBH_TAG, "Device %d gone", dev_obj->constant.address); + p_usbh_obj->constant.event_cb((usb_device_handle_t)dev_obj, USBH_EVENT_DEV_GONE, p_usbh_obj->constant.event_cb_arg); + } + if (action_flags & DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH) { + ESP_ERROR_CHECK(hcd_pipe_command(dev_obj->constant.default_pipe, HCD_PIPE_CMD_HALT)); + ESP_ERROR_CHECK(hcd_pipe_command(dev_obj->constant.default_pipe, HCD_PIPE_CMD_FLUSH)); + } + if (action_flags & DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE) { + //Empty URBs from default pipe and trigger a control transfer callback + ESP_LOGD(USBH_TAG, "Default pipe device %d", dev_obj->constant.address); + int num_urbs = 0; + urb_t *urb = hcd_urb_dequeue(dev_obj->constant.default_pipe); + while (urb != NULL) { + num_urbs++; + p_usbh_obj->constant.ctrl_xfer_cb((usb_device_handle_t)dev_obj, urb, p_usbh_obj->constant.ctrl_xfer_cb_arg); + urb = hcd_urb_dequeue(dev_obj->constant.default_pipe); + } + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.num_ctrl_xfers_inflight -= num_urbs; + USBH_EXIT_CRITICAL(); + } + if (action_flags & DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR) { + //We allow the pipe command to fail just in case the pipe becomes invalid mid command + hcd_pipe_command(dev_obj->constant.default_pipe, HCD_PIPE_CMD_CLEAR); + } + /* + Note: We make these action flags mutually exclusive in case they happen in rapid succession. They are handled + in the order of precedence + For example + - New device event is requested followed immediately by a disconnection + - Port disable requested followed immediately by a disconnection + */ + if (action_flags & DEV_FLAG_ACTION_FREE) { + ESP_LOGD(USBH_TAG, "Freeing device %d", dev_obj->constant.address); + if (handle_dev_free(dev_obj)) { + ESP_LOGD(USBH_TAG, "Device all free"); + p_usbh_obj->constant.event_cb((usb_device_handle_t)NULL, USBH_EVENT_DEV_ALL_FREE, p_usbh_obj->constant.event_cb_arg); + } + } else if (action_flags & DEV_FLAG_ACTION_PORT_DISABLE) { + //Request that the HUB disables this device's port + ESP_LOGD(USBH_TAG, "Disable device port %d", dev_obj->constant.address); + p_usbh_obj->constant.hub_cb(dev_obj->constant.port_hdl, USBH_HUB_EVENT_DISABLE_PORT, p_usbh_obj->constant.hub_cb_arg); + } else if (action_flags & DEV_FLAG_ACTION_SEND_NEW) { + ESP_LOGD(USBH_TAG, "New device %d", dev_obj->constant.address); + p_usbh_obj->constant.event_cb((usb_device_handle_t)dev_obj, USBH_EVENT_DEV_NEW, p_usbh_obj->constant.event_cb_arg); + } + USBH_ENTER_CRITICAL(); + + } + USBH_EXIT_CRITICAL(); + return ESP_OK; +} + +// ------------------------------------------------ Device Functions --------------------------------------------------- + +// --------------------- Device Pool ----------------------- + +esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + esp_err_t ret; + + USBH_ENTER_CRITICAL(); + //Go through the device lists to find the device with the specified address + device_t *found_dev_obj = NULL; + device_t *dev_obj; + TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_idle_tailq, dynamic.tailq_entry) { + if (dev_obj->constant.address == dev_addr) { + found_dev_obj = dev_obj; + goto exit; + } + } + TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_idle_tailq, dynamic.tailq_entry) { + if (dev_obj->constant.address == dev_addr) { + found_dev_obj = dev_obj; + goto exit; + } + } +exit: + if (found_dev_obj != NULL) { + //The device is not in a state to be referenced + if (dev_obj->dynamic.flags.is_gone || dev_obj->dynamic.flags.waiting_port_disable || dev_obj->dynamic.flags.waiting_free) { + ret = ESP_ERR_INVALID_STATE; + } else { + dev_obj->dynamic.ref_count++; + *dev_hdl = (usb_device_handle_t)found_dev_obj; + ret = ESP_OK; + } + } else { + ret = ESP_ERR_NOT_FOUND; + } + USBH_EXIT_CRITICAL(); + + return ret; +} + +esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.num_ctrl_xfers_inflight == 0, ESP_ERR_INVALID_STATE); + dev_obj->dynamic.ref_count--; + bool call_notif_cb = false; + if (dev_obj->dynamic.ref_count == 0) { + //Sanity check. This can only be set when ref count reaches 0 + assert(!dev_obj->dynamic.flags.waiting_free); + if (dev_obj->dynamic.flags.is_gone) { + //Device is already gone so it's port is already disabled. Trigger the USBH process to free the device + dev_obj->dynamic.flags.waiting_free = 1; + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_FREE); + } else if (dev_obj->dynamic.flags.waiting_close) { + //Device is still connected but is no longer needed. Trigger the USBH process to request device's port be disabled + dev_obj->dynamic.flags.waiting_port_disable = 1; + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_PORT_DISABLE); + } + //Else, there's nothing to do. Leave the device allocated + } + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +esp_err_t usbh_dev_mark_all_free(void) +{ + USBH_ENTER_CRITICAL(); + /* + Go through the device list and mark each device as waiting to be closed. If the device is not opened at all, we can + disable it immediately. + Note: We manually traverse the list because we need to add/remove items while traversing + */ + bool call_notif_cb = false; + for (int i = 0; i < 2; i++) { + device_t *dev_obj_cur; + device_t *dev_obj_next; + //Go through pending list first as it's more efficient + if (i == 0) { + dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq); + } else { + dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_idle_tailq); + } + while (dev_obj_cur != NULL) { + assert(!dev_obj_cur->dynamic.flags.waiting_close); //Sanity check + //Keep a copy of the next item first in case we remove the current item + dev_obj_next = TAILQ_NEXT(dev_obj_cur, dynamic.tailq_entry); + if (dev_obj_cur->dynamic.ref_count == 0 && !dev_obj_cur->dynamic.flags.is_gone) { + //Device is not opened as is not gone, so we can disable it now + dev_obj_cur->dynamic.flags.waiting_port_disable = 1; + call_notif_cb |= _dev_set_actions(dev_obj_cur, DEV_FLAG_ACTION_PORT_DISABLE); + } else { + //Device is still opened. Just mark it as waiting to be closed + dev_obj_cur->dynamic.flags.waiting_close = 1; + } + dev_obj_cur = dev_obj_next; + } + } + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +// ------------------- Single Device ---------------------- + +esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr) +{ + USBH_CHECK(dev_hdl != NULL && dev_addr != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->constant.address > 0, ESP_ERR_INVALID_STATE); + *dev_addr = dev_obj->constant.address; + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info) +{ + USBH_CHECK(dev_hdl != NULL && dev_info != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED || dev_obj->dynamic.state == USB_DEVICE_STATE_NOT_ATTACHED, ESP_ERR_INVALID_STATE); + dev_info->speed = dev_obj->constant.speed; + dev_info->dev_addr = dev_obj->constant.address; + dev_info->bMaxPacketSize0 = dev_obj->constant.desc->bMaxPacketSize0; + if (dev_obj->dynamic.config_desc == NULL) { + dev_info->bConfigurationValue = 0; + } else { + dev_info->bConfigurationValue = dev_obj->dynamic.config_desc->bConfigurationValue; + } + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t **dev_desc_ret) +{ + USBH_CHECK(dev_hdl != NULL && dev_desc_ret != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + USBH_EXIT_CRITICAL(); + + *dev_desc_ret = dev_obj->constant.desc; + return ESP_OK; +} + +esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc_ret) +{ + USBH_CHECK(dev_hdl != NULL && config_desc_ret != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + *config_desc_ret = dev_obj->dynamic.config_desc; + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb) +{ + USBH_CHECK(dev_hdl != NULL && urb != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + //Increment the control transfer count first + dev_obj->dynamic.num_ctrl_xfers_inflight++; + USBH_EXIT_CRITICAL(); + + esp_err_t ret; + if (hcd_pipe_get_state(dev_obj->constant.default_pipe) != HCD_PIPE_STATE_ACTIVE) { + ret = ESP_ERR_INVALID_STATE; + goto hcd_err; + } + ret = hcd_urb_enqueue(dev_obj->constant.default_pipe, urb); + if (ret != ESP_OK) { + goto hcd_err; + } + ret = ESP_OK; + return ret; + +hcd_err: + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.num_ctrl_xfers_inflight--; + USBH_EXIT_CRITICAL(); + return ret; +} + +// ----------------------------------------------- Interface Functions ------------------------------------------------- + +esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config, hcd_pipe_handle_t *pipe_hdl_ret) +{ + USBH_CHECK(dev_hdl != NULL && ep_config != NULL && pipe_hdl_ret != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + dev_obj->dynamic.ref_count++; //Increase the ref_count to keep the device alive while allocating the endpoint + USBH_EXIT_CRITICAL(); + + esp_err_t ret; + //Allocate HCD pipe + hcd_pipe_config_t pipe_config = { + .callback = ep_config->pipe_cb, + .callback_arg = ep_config->pipe_cb_arg, + .context = ep_config->context, + .ep_desc = ep_config->ep_desc, + .dev_speed = dev_obj->constant.speed, + .dev_addr = dev_obj->constant.address, + }; + hcd_pipe_handle_t pipe_hdl; + ret = hcd_pipe_alloc(dev_obj->constant.port_hdl, &pipe_config, &pipe_hdl); + if (ret != ESP_OK) { + goto pipe_alloc_err; + } + + USBH_ENTER_CRITICAL(); + //Check that endpoint has not be allocated yet + bool is_in = ep_config->ep_desc->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK; + uint8_t addr = ep_config->ep_desc->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK; + //Assign the pipe handle + bool assigned = false; + if (is_in && dev_obj->dynamic.ep_in[addr - 1] == NULL) { //Is an IN EP + dev_obj->dynamic.ep_in[addr - 1] = pipe_hdl; + assigned = true; + } else { + dev_obj->dynamic.ep_out[addr - 1] = pipe_hdl; + assigned = true; + } + dev_obj->dynamic.ref_count--; //Restore ref_count + USBH_EXIT_CRITICAL(); + + if (!assigned) { + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + //Write back output + *pipe_hdl_ret = pipe_hdl; + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hcd_pipe_free(pipe_hdl)); +pipe_alloc_err: + return ret; +} + +esp_err_t usbh_ep_free(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + //Un-assign the pipe handle from the endpoint + bool is_in = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK; + uint8_t addr = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK; + hcd_pipe_handle_t pipe_hdl; + if (is_in) { + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.ep_in[addr - 1] != NULL, ESP_ERR_INVALID_STATE); + pipe_hdl = dev_obj->dynamic.ep_in[addr - 1]; + dev_obj->dynamic.ep_in[addr - 1] = NULL; + } else { + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.ep_out[addr - 1] != NULL, ESP_ERR_INVALID_STATE); + pipe_hdl = dev_obj->dynamic.ep_out[addr - 1]; + dev_obj->dynamic.ep_out[addr - 1] = NULL; + } + USBH_EXIT_CRITICAL(); + + ESP_ERROR_CHECK(hcd_pipe_free(pipe_hdl)); + return ESP_OK; +} + +esp_err_t usbh_ep_get_context(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, void **context_ret) +{ + bool is_in = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK; + uint8_t addr = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK; + USBH_CHECK(dev_hdl != NULL && + addr >= EP_NUM_MIN && //Control endpoints are owned by the USBH + addr <= EP_NUM_MAX && + context_ret != NULL, + ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + //Get the endpoint's corresponding pipe + hcd_pipe_handle_t pipe_hdl; + if (is_in) { + pipe_hdl = dev_obj->dynamic.ep_in[addr - 1]; + } else { + pipe_hdl = dev_obj->dynamic.ep_out[addr - 1]; + } + esp_err_t ret; + if (pipe_hdl == NULL) { + USBH_EXIT_CRITICAL(); + ret = ESP_ERR_NOT_FOUND; + goto exit; + } + //Return the context of the pipe + void *context = hcd_pipe_get_context(pipe_hdl); + *context_ret = context; + USBH_EXIT_CRITICAL(); + + ret = ESP_OK; +exit: + return ret; +} + +// -------------------------------------------------- Hub Functions ---------------------------------------------------- + +// ------------------- Device Related ---------------------- + +esp_err_t usbh_hub_is_installed(usbh_hub_cb_t hub_callback, void *callback_arg) +{ + USBH_CHECK(hub_callback != NULL, ESP_ERR_INVALID_ARG); + + USBH_ENTER_CRITICAL(); + //Check that USBH is already installed + USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE); + //Check that Hub has not be installed yet + USBH_CHECK_FROM_CRIT(p_usbh_obj->constant.hub_cb == NULL, ESP_ERR_INVALID_STATE); + p_usbh_obj->constant.hub_cb = hub_callback; + p_usbh_obj->constant.hub_cb_arg = callback_arg; + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_hub_add_dev(hcd_port_handle_t port_hdl, usb_speed_t dev_speed, usb_device_handle_t *new_dev_hdl, hcd_pipe_handle_t *default_pipe_hdl) +{ + //Note: Parent device handle can be NULL if it's connected to the root hub + USBH_CHECK(new_dev_hdl != NULL, ESP_ERR_INVALID_ARG); + esp_err_t ret; + device_t *dev_obj; + ret = device_alloc(port_hdl, dev_speed, &dev_obj); + if (ret != ESP_OK) { + return ret; + } + //Write-back device handle + *new_dev_hdl = (usb_device_handle_t)dev_obj; + *default_pipe_hdl = dev_obj->constant.default_pipe; + ret = ESP_OK; + return ret; +} + +esp_err_t usbh_hub_mark_dev_gone(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.flags.is_gone = 1; + bool call_notif_cb; + //Check if the device can be freed now + if (dev_obj->dynamic.ref_count == 0) { + dev_obj->dynamic.flags.waiting_free = 1; + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_FREE); + } else { + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_SEND_GONE_EVENT | + DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH | + DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE); + } + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +esp_err_t usbh_hub_dev_port_disabled(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + assert(dev_obj->dynamic.ref_count == 0); //At this stage, the device should have been closed by all users + dev_obj->dynamic.flags.waiting_free = 1; + bool call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_FREE); + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + ESP_LOGD(USBH_TAG, "Notif free"); + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +// ----------------- Enumeration Related ------------------- + +esp_err_t usbh_hub_enum_fill_dev_addr(usb_device_handle_t dev_hdl, uint8_t dev_addr) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->constant.enum_todo_flags & DEV_ENUM_TODO_FLAG_DEV_ADDR, ESP_ERR_INVALID_STATE); + dev_obj->dynamic.state = USB_DEVICE_STATE_ADDRESS; + USBH_EXIT_CRITICAL(); + + //We can modify the info members outside the critical section + dev_obj->constant.enum_todo_flags &= ~DEV_ENUM_TODO_FLAG_DEV_ADDR; + dev_obj->constant.address = dev_addr; + return ESP_OK; +} + +esp_err_t usbh_hub_enum_fill_dev_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t *device_desc) +{ + USBH_CHECK(dev_hdl != NULL && device_desc != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + //We can modify the info members outside the critical section + USBH_CHECK(dev_obj->constant.enum_todo_flags & DEV_ENUM_TODO_FLAG_DEV_DESC, ESP_ERR_INVALID_STATE); + dev_obj->constant.enum_todo_flags &= ~DEV_ENUM_TODO_FLAG_DEV_DESC; + memcpy((usb_device_desc_t *)dev_obj->constant.desc, device_desc, sizeof(usb_device_desc_t)); + return ESP_OK; +} + +esp_err_t usbh_hub_enum_fill_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc_full) +{ + USBH_CHECK(dev_hdl != NULL && config_desc_full != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + esp_err_t ret; + //Allocate memory to store the configuration descriptor + usb_config_desc_t *config_desc = heap_caps_malloc(config_desc_full->wTotalLength, MALLOC_CAP_DEFAULT); //Buffer to copy over full configuration descriptor (wTotalLength) + if (config_desc == NULL) { + ret = ESP_ERR_NO_MEM; + goto err; + } + //Copy the configuration descriptor + memcpy(config_desc, config_desc_full, config_desc_full->wTotalLength); + //Assign the config object to the device object + if (!(dev_obj->constant.enum_todo_flags & DEV_ENUM_TODO_FLAG_CONFIG_DESC)) { + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + + USBH_ENTER_CRITICAL(); + assert(dev_obj->dynamic.config_desc == NULL); + dev_obj->dynamic.config_desc = config_desc; + USBH_EXIT_CRITICAL(); + + //We can modify the info members outside the critical section + dev_obj->constant.enum_todo_flags &= ~DEV_ENUM_TODO_FLAG_CONFIG_DESC; + ret = ESP_OK; + return ret; + +assign_err: + heap_caps_free(config_desc); +err: + return ret; +} + +esp_err_t usbh_hub_enum_done(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + USBH_CHECK(dev_obj->constant.enum_todo_flags == 0, ESP_ERR_INVALID_STATE); //All enumeration stages to be done + + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.state = USB_DEVICE_STATE_CONFIGURED; + //Add the device to list of devices, then trigger a device event + TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); //Add it to the idle device list first + p_usbh_obj->dynamic.num_device++; + bool call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_SEND_NEW); + USBH_EXIT_CRITICAL(); + + //Update the default pipe callback + ESP_ERROR_CHECK(hcd_pipe_update_callback(dev_obj->constant.default_pipe, default_pipe_callback, (void *)dev_obj)); + //Call the notification callback + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +esp_err_t usbh_hub_enum_failed(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + usb_config_desc_t *config_desc = dev_obj->dynamic.config_desc; + dev_obj->dynamic.config_desc = NULL; + USBH_EXIT_CRITICAL(); + + if (config_desc) { + heap_caps_free(config_desc); + } + device_free(dev_obj); + return ESP_OK; +} From 3907634d208347370e0e6f5abb51cb58a70fd1b4 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 20 Jul 2021 18:59:24 +0800 Subject: [PATCH 029/310] aes: fix potential unaligned access of buffers https://github.com/espressif/esp-idf/issues/7236 --- components/hal/esp32/include/hal/aes_ll.h | 10 ++- components/hal/esp32c3/include/hal/aes_ll.h | 50 ++++++++------- components/hal/esp32h2/include/hal/aes_ll.h | 50 ++++++++------- components/hal/esp32s2/include/hal/aes_ll.h | 67 +++++++++++---------- components/hal/esp32s3/include/hal/aes_ll.h | 50 ++++++++------- 5 files changed, 114 insertions(+), 113 deletions(-) diff --git a/components/hal/esp32/include/hal/aes_ll.h b/components/hal/esp32/include/hal/aes_ll.h index 8283397dde..b0142cbe68 100644 --- a/components/hal/esp32/include/hal/aes_ll.h +++ b/components/hal/esp32/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-2021 Espressif Systems (Shanghai) CO LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ #include "soc/hwcrypto_reg.h" #include "soc/dport_access.h" #include "hal/aes_types.h" +#include #ifdef __cplusplus extern "C" { @@ -46,10 +47,13 @@ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_bytes_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; + + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + DPORT_REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_bytes_in_hardware += 4; } return key_bytes_in_hardware; diff --git a/components/hal/esp32c3/include/hal/aes_ll.h b/components/hal/esp32c3/include/hal/aes_ll.h index 0eb7fabc64..e18c44e58e 100644 --- a/components/hal/esp32c3/include/hal/aes_ll.h +++ b/components/hal/esp32c3/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-2021 Espressif Systems (Shanghai) CO LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -39,16 +40,17 @@ typedef enum { * @param key Key to be written to the AES hardware * @param key_word_len Number of words in the key * - * @return volatile number of bytes written to hardware, used for fault injection check + * @return Number of bytes written to hardware, used for fault injection check */ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -76,22 +78,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers, not in an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -101,11 +93,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -179,11 +173,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -192,11 +188,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } diff --git a/components/hal/esp32h2/include/hal/aes_ll.h b/components/hal/esp32h2/include/hal/aes_ll.h index 0eb7fabc64..e18c44e58e 100644 --- a/components/hal/esp32h2/include/hal/aes_ll.h +++ b/components/hal/esp32h2/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-2021 Espressif Systems (Shanghai) CO LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -39,16 +40,17 @@ typedef enum { * @param key Key to be written to the AES hardware * @param key_word_len Number of words in the key * - * @return volatile number of bytes written to hardware, used for fault injection check + * @return Number of bytes written to hardware, used for fault injection check */ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -76,22 +78,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers, not in an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -101,11 +93,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -179,11 +173,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -192,11 +188,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } diff --git a/components/hal/esp32s2/include/hal/aes_ll.h b/components/hal/esp32s2/include/hal/aes_ll.h index 9056216517..653253d06d 100644 --- a/components/hal/esp32s2/include/hal/aes_ll.h +++ b/components/hal/esp32s2/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-2021 Espressif Systems (Shanghai) CO LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -46,10 +47,11 @@ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -77,22 +79,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers not an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -102,11 +94,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -190,11 +184,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -203,11 +199,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } @@ -247,13 +245,14 @@ static inline void aes_ll_interrupt_clear(void) */ static inline void aes_ll_gcm_read_hash(uint8_t *gcm_hash) { - uint32_t *hash_words = (uint32_t *)gcm_hash; const size_t REG_WIDTH = sizeof(uint32_t); + uint32_t hash_word; for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - hash_words[i] = REG_READ(AES_H_BASE + (i * REG_WIDTH)); + hash_word = REG_READ(AES_H_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(gcm_hash + i * 4, &hash_word, sizeof(hash_word)); } - } /** @@ -277,11 +276,13 @@ static inline void aes_ll_gcm_set_aad_num_blocks(size_t aad_num_blocks) */ static inline void aes_ll_gcm_set_j0(const uint8_t *j0) { - uint32_t *j0_words = (uint32_t *)j0; uint32_t *reg_addr_buf = (uint32_t *)(AES_J_BASE); + uint32_t j0_word; for (int i = 0; i < AES_BLOCK_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], j0_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&j0_word, j0 + 4 * i, sizeof(j0_word)); + REG_WRITE(®_addr_buf[i], j0_word); } } @@ -304,11 +305,13 @@ static inline void aes_ll_gcm_set_num_valid_bit(size_t num_valid_bits) */ static inline void aes_ll_gcm_read_tag(uint8_t *tag) { - uint32_t *tag_words = (uint32_t *)tag; + uint32_t tag_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < TAG_WORDS; i++) { - tag_words[i] = REG_READ(AES_T_BASE + (i * REG_WIDTH)); + tag_word = REG_READ(AES_T_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(tag + i * 4, &tag_word, sizeof(tag_word)); } } diff --git a/components/hal/esp32s3/include/hal/aes_ll.h b/components/hal/esp32s3/include/hal/aes_ll.h index dbc831f038..e18c44e58e 100644 --- a/components/hal/esp32s3/include/hal/aes_ll.h +++ b/components/hal/esp32s3/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-2021 Espressif Systems (Shanghai) CO LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -39,16 +40,17 @@ typedef enum { * @param key Key to be written to the AES hardware * @param key_word_len Number of words in the key * - * @return volatile number of bytes written to hardware, used for fault injection check + * @return Number of bytes written to hardware, used for fault injection check */ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -76,22 +78,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers not an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -101,11 +93,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -179,11 +173,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -192,11 +188,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } From 6ab495b4dc4621ece201c55c02219b3d1bc4e753 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 8 Jul 2021 14:37:24 +0800 Subject: [PATCH 030/310] esp32h2: chip env support brownout init fixed --- Kconfig | 1 - .../bootloader_support/src/esp32h2/bootloader_esp32h2.c | 7 +------ .../port/esp32h2/private_include/regi2c_bias.h | 4 ++-- .../port/esp32h2/private_include/regi2c_lp_bias.h | 2 ++ components/esp_hw_support/port/esp32h2/rtc_sleep.c | 1 + components/esp_system/port/soc/esp32h2/clk.c | 4 ++-- components/esp_system/startup.c | 1 + components/soc/esp32h2/include/soc/soc.h | 4 ++-- 8 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Kconfig b/Kconfig index 942837a0ea..65d03788c9 100644 --- a/Kconfig +++ b/Kconfig @@ -11,7 +11,6 @@ mainmenu "Espressif IoT Development Framework Configuration" config IDF_ENV_FPGA # This option is for internal use only bool - default "y" if IDF_TARGET="esp32h2" # ESP32H2-TODO: IDF-3378 option env="IDF_ENV_FPGA" config IDF_TARGET_ARCH_RISCV diff --git a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c index 075bd6a8c4..a483b34ceb 100644 --- a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c +++ b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c @@ -254,12 +254,7 @@ static void bootloader_super_wdt_auto_feed(void) static inline void bootloader_hardware_init(void) { - // This check is always included in the bootloader so it can - // print the minimum revision error message later in the boot - if (bootloader_common_get_chip_revision() < 3) { - REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1); - REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12); - } + } static inline void bootloader_glitch_reset_disable(void) diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h index e359ef0a69..c1e540bf7a 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h @@ -14,8 +14,8 @@ * bootloader_hardware_init function in bootloader_esp32c3.c. */ -#define I2C_BIAS 0X6A -#define I2C_BIAS_HOSTID 0 +#define I2C_BIAS 0x6a +#define I2C_BIAS_HOSTID 0 #define I2C_BIAS_DREG_1P1_PVT 1 #define I2C_BIAS_DREG_1P1_PVT_MSB 3 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h index c50c1a941a..6a8c996fd5 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h @@ -14,6 +14,8 @@ * bus. These definitions are used via macros defined in regi2c_ctrl.h, by * rtc_init function in rtc_init.c. */ +#define I2C_ULP 0x61 +#define I2C_ULP_HOSTID 0 #define I2C_ULP 0x61 #define I2C_ULP_HOSTID 0 diff --git a/components/esp_hw_support/port/esp32h2/rtc_sleep.c b/components/esp_hw_support/port/esp32h2/rtc_sleep.c index 6323613194..4ef41d5725 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32h2/rtc_sleep.c @@ -85,6 +85,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, RTC_CNTL_BIASSLP_SLEEP_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, RTC_CNTL_PD_CUR_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, RTC_CNTL_PD_CUR_SLEEP_DEFAULT); + // ESP32-H2 TO-DO: IDF-3693 if (cfg.deep_slp) { REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0); CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); diff --git a/components/esp_system/port/soc/esp32h2/clk.c b/components/esp_system/port/soc/esp32h2/clk.c index 64aeab1f04..81cdd5e1d7 100644 --- a/components/esp_system/port/soc/esp32h2/clk.c +++ b/components/esp_system/port/soc/esp32h2/clk.c @@ -82,7 +82,7 @@ static const char *TAG = "clk"; } rtc_init(cfg); - assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M); + assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_32M); rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M); #endif @@ -177,7 +177,7 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk) } } } else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) { - rtc_clk_8m_enable(true, true); + // rtc_clk_8m_enable(true, true); } rtc_clk_slow_freq_set(rtc_slow_freq); diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 8afc43087f..ebe31b73cf 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -268,6 +268,7 @@ static void do_core_init(void) CONFIG_ESP32S3_BROWNOUT_DET || \ CONFIG_ESP32C3_BROWNOUT_DET || \ CONFIG_ESP32H2_BROWNOUT_DET + // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) -> // malloc (newlib) -> heap_caps_malloc (heap), so heap must be at least initialized esp_brownout_init(); diff --git a/components/soc/esp32h2/include/soc/soc.h b/components/soc/esp32h2/include/soc/soc.h index 1e88295771..bca83126d5 100644 --- a/components/soc/esp32h2/include/soc/soc.h +++ b/components/soc/esp32h2/include/soc/soc.h @@ -228,10 +228,10 @@ #if CONFIG_IDF_ENV_FPGA #define APB_CLK_FREQ ( 32*1000000 ) #else -#define APB_CLK_FREQ ( 80*1000000 ) +#define APB_CLK_FREQ ( 96*1000000 ) #endif #define REF_CLK_FREQ ( 1000000 ) -#define RTC_CLK_FREQ (20*1000000) +#define RTC_CLK_FREQ (17.5*1000000) #define XTAL_CLK_FREQ (32*1000000) #define UART_CLK_FREQ APB_CLK_FREQ #define WDT_CLK_FREQ APB_CLK_FREQ From be36c9ae36441d1b948b2c9515bc61b59fd7efb9 Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 25 Aug 2021 14:43:15 +0800 Subject: [PATCH 031/310] tinyusb: const in_buf of tinyusb_cdcacm_write_queue --- components/tinyusb/additions/include/tusb_cdc_acm.h | 2 +- components/tinyusb/additions/src/tusb_cdc_acm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/tinyusb/additions/include/tusb_cdc_acm.h b/components/tinyusb/additions/include/tusb_cdc_acm.h index af7985e6c4..fb837a5f31 100644 --- a/components/tinyusb/additions/include/tusb_cdc_acm.h +++ b/components/tinyusb/additions/include/tusb_cdc_acm.h @@ -157,7 +157,7 @@ size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch); * @param in_size - size to write from arr_src * @return size_t - amount of queued bytes */ -size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, uint8_t *in_buf, size_t in_size); +size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size); /** * @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer. diff --git a/components/tinyusb/additions/src/tusb_cdc_acm.c b/components/tinyusb/additions/src/tusb_cdc_acm.c index f2e536c64b..4dad2bc062 100644 --- a/components/tinyusb/additions/src/tusb_cdc_acm.c +++ b/components/tinyusb/additions/src/tusb_cdc_acm.c @@ -290,7 +290,7 @@ size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch) } -size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, uint8_t *in_buf, size_t in_size) +size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size) { if (!get_acm(itf)) { // non-initialized return 0; From c860b3ead6757c3ee1d395aa4d5433760b6552b8 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Wed, 25 Aug 2021 15:09:23 +0800 Subject: [PATCH 032/310] gpio: fix issue that gpio cannot hold during deep-sleep on c3, Closes https://github.com/espressif/esp-idf/issues/7455 --- components/hal/esp32c3/include/hal/gpio_ll.h | 1 + components/soc/esp32c3/gpio_periph.c | 44 ++++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index 6ba4d601b9..da61aa198c 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -334,6 +334,7 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_ */ static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } diff --git a/components/soc/esp32c3/gpio_periph.c b/components/soc/esp32c3/gpio_periph.c index e72f7e20a7..1bdf359819 100644 --- a/components/soc/esp32c3/gpio_periph.c +++ b/components/soc/esp32c3/gpio_periph.c @@ -40,26 +40,26 @@ const uint32_t GPIO_PIN_MUX_REG[SOC_GPIO_PIN_COUNT] = { }; const uint32_t GPIO_HOLD_MASK[SOC_GPIO_PIN_COUNT] = { - BIT(0), //GPIO0 - BIT(1), //GPIO1 - BIT(2), //GPIO2 - BIT(3), //GPIO3 - BIT(4), //GPIO4 - BIT(5), //GPIO5 - BIT(5), //GPIO6 - BIT(6), //GPIO7 - BIT(3), //GPIO8 - BIT(4), //GPIO9 - BIT(0), //GPIO10 - BIT(15), //GPIO11 - BIT(10), //GPIO12 - BIT(12), //GPIO13 - BIT(8), //GPIO14 - BIT(7), //GPIO15 - BIT(9), //GPIO16 - BIT(11), //GPIO17 - BIT(1), //GPIO18 - BIT(2), //GPIO19 - BIT(13), //GPIO20 - BIT(14), //GPIO21 + BIT(0), //GPIO0 + BIT(1), //GPIO1 + BIT(2), //GPIO2 + BIT(3), //GPIO3 + BIT(4), //GPIO4 + BIT(5), //GPIO5 + BIT(6), //GPIO6 + BIT(7), //GPIO7 + BIT(8), //GPIO8 + BIT(9), //GPIO9 + BIT(10), //GPIO10 + BIT(11), //GPIO11 + BIT(12), //GPIO12 + BIT(13), //GPIO13 + BIT(14), //GPIO14 + BIT(15), //GPIO15 + BIT(16), //GPIO16 + BIT(17), //GPIO17 + BIT(18), //GPIO18 + BIT(19), //GPIO19 + BIT(20), //GPIO20 + BIT(21), //GPIO21 }; From 12bf160f3d90b1d1ed85acd12d2ae5db5e27a0aa Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Wed, 25 Aug 2021 15:59:00 +0800 Subject: [PATCH 033/310] vCoRoutineScheduleFix (cherry picked from commit 1edbd44db107225b7bc6342a7da5680cc12ad22f) --- components/freertos/croutine.c | 47 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/components/freertos/croutine.c b/components/freertos/croutine.c index a4628f4ddb..8be115f78c 100644 --- a/components/freertos/croutine.c +++ b/components/freertos/croutine.c @@ -281,31 +281,36 @@ void vCoRoutineSchedule( void ) { - /* See if any co-routines readied by events need moving to the ready lists. */ - prvCheckPendingReadyList(); - - /* See if any delayed co-routines have timed out. */ - prvCheckDelayedList(); - - /* Find the highest priority queue that contains ready co-routines. */ - while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) + /* Only run a co-routine after prvInitialiseCoRoutineLists() has been + * called. prvInitialiseCoRoutineLists() is called automatically when a + * co-routine is created. */ + if( pxDelayedCoRoutineList != NULL ) { - if( uxTopCoRoutineReadyPriority == 0 ) + /* See if any co-routines readied by events need moving to the ready lists. */ + prvCheckPendingReadyList(); + + /* See if any delayed co-routines have timed out. */ + prvCheckDelayedList(); + + /* Find the highest priority queue that contains ready co-routines. */ + while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) { - /* No more co-routines to check. */ - return; + if( uxTopCoRoutineReadyPriority == 0 ) + { + /* No more co-routines to check. */ + return; + } + + --uxTopCoRoutineReadyPriority; } - --uxTopCoRoutineReadyPriority; + + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines + * of the same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); + + /* Call the co-routine. */ + ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); } - - /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines - * of the same priority get an equal share of the processor time. */ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); - - /* Call the co-routine. */ - ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); - - return; } /*-----------------------------------------------------------*/ From 3128a2544b92d61b840a7c0dca65bf8cafcf4de1 Mon Sep 17 00:00:00 2001 From: Wu Zheng Hui Date: Wed, 25 Aug 2021 16:06:28 +0800 Subject: [PATCH 034/310] Adjust the variable name & Add mapping support for different sizes of spi ram --- .gitlab/ci/target-test.yml | 4 +- .../esp_hw_support/Kconfig.spiram.common | 2 +- .../esp_hw_support/port/esp32s2/spiram.c | 275 ++++++++++-------- .../esp_hw_support/port/esp32s3/spiram.c | 6 +- components/esp_system/ld/esp32/memory.ld.in | 2 +- components/esp_system/ld/esp32s2/memory.ld.in | 4 + .../esp_system/ld/esp32s2/sections.ld.in | 11 + components/esp_system/port/cpu_start.c | 5 +- .../soc/esp32s2/include/soc/cache_memory.h | 2 +- .../configs/spi_flash_config_2_s2 | 3 +- .../configs/spi_flash_config_3_s2 | 1 + .../configs/spi_flash_config_4_s2 | 6 + 12 files changed, 190 insertions(+), 131 deletions(-) create mode 100644 tools/unit-test-app/configs/spi_flash_config_4_s2 diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 6f420768d4..5be1958303 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -482,7 +482,7 @@ UT_006: UT_007: extends: .unit_test_esp32_template - parallel: 3 + parallel: 4 tags: - ESP32_IDF - UT_T1_1 @@ -633,7 +633,7 @@ UT_046: UT_047: extends: .unit_test_esp32s2_template - parallel: 3 + parallel: 4 tags: - ESP32S2_IDF - UT_T1_1 diff --git a/components/esp_hw_support/Kconfig.spiram.common b/components/esp_hw_support/Kconfig.spiram.common index a0616bf444..ae9b298b4a 100644 --- a/components/esp_hw_support/Kconfig.spiram.common +++ b/components/esp_hw_support/Kconfig.spiram.common @@ -92,7 +92,7 @@ config SPIRAM_MALLOC_RESERVE_INTERNAL config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY bool "Allow .bss segment placed in external memory" default n - depends on SPIRAM && IDF_TARGET_ESP32 # TODO ESP32-S2 IDFGH-4320, ESP32-S3 IDF-1974 + depends on SPIRAM && (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2) # ESP32-S3 IDF-1974 select ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY help If enabled, variables with EXT_RAM_ATTR attribute will be placed in SPIRAM instead of internal DRAM. diff --git a/components/esp_hw_support/port/esp32s2/spiram.c b/components/esp_hw_support/port/esp32s2/spiram.c index e9a6e70184..38eb9ea8c6 100644 --- a/components/esp_hw_support/port/esp32s2/spiram.c +++ b/components/esp_hw_support/port/esp32s2/spiram.c @@ -44,99 +44,36 @@ static const char* TAG = "spiram"; static bool spiram_inited=false; -/* - Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns - true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been - initialized (in a two-core system) or after the heap allocator has taken ownership of the memory. -*/ -bool esp_spiram_test(void) -{ - size_t spiram_size = esp_spiram_get_size(); - volatile int *spiram=(volatile int*)(SOC_EXTRAM_DATA_HIGH - spiram_size); - size_t p; - size_t s = spiram_size; - int errct=0; - int initial_err=-1; - - if (SOC_EXTRAM_DATA_SIZE < spiram_size) { - ESP_EARLY_LOGW(TAG, "Only test spiram from %08x to %08x\n", SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH); - spiram=(volatile int*)SOC_EXTRAM_DATA_LOW; - s = SOC_EXTRAM_DATA_SIZE; - } - for (p=0; p<(s/sizeof(int)); p+=8) { - spiram[p]=p^0xAAAAAAAA; - } - for (p=0; p<(s/sizeof(int)); p+=8) { - if (spiram[p]!=(p^0xAAAAAAAA)) { - errct++; - if (errct==1) initial_err=p*4; - if (errct < 4) { - ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p^0xAAAAAAAA); - } - } - } - if (errct) { - ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err+SOC_EXTRAM_DATA_LOW); - return false; - } else { - ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK"); - return true; - } -} - #define DRAM0_ONLY_CACHE_SIZE BUS_IRAM0_CACHE_SIZE -#define DRAM0_DRAM1_CACHE_SIZE (BUS_IRAM0_CACHE_SIZE + BUS_IRAM1_CACHE_SIZE) +#define DRAM0_DRAM1_CACHE_SIZE (BUS_IRAM0_CACHE_SIZE + BUS_IRAM1_CACHE_SIZE) #define DRAM0_DRAM1_DPORT_CACHE_SIZE (BUS_IRAM0_CACHE_SIZE + BUS_IRAM1_CACHE_SIZE + BUS_DPORT_CACHE_SIZE) -#define DBUS3_ONLY_CACHE_SIZE BUS_AHB_DBUS3_CACHE_SIZE -#define DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE (DRAM0_DRAM1_DPORT_CACHE_SIZE + DBUS3_ONLY_CACHE_SIZE) +#define SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT (spiram_size - DRAM0_DRAM1_DPORT_CACHE_SIZE) -#define SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT (spiram_size - DRAM0_DRAM1_DPORT_CACHE_SIZE) -#define SPIRAM_SIZE_EXC_DATA_CACHE (spiram_size - DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE) +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +extern uint8_t _ext_ram_bss_start, _ext_ram_bss_end; +#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#define EXT_BSS_SIZE ((uint32_t)(&_ext_ram_bss_end - &_ext_ram_bss_start)) +#define EXT_BSS_PAGE_ALIGN_SIZE (ALIGN_UP_BY(EXT_BSS_SIZE, 0x10000)) +#endif -#define SPIRAM_SMALL_SIZE_MAP_VADDR (DRAM0_CACHE_ADDRESS_HIGH - spiram_size) -#define SPIRAM_SMALL_SIZE_MAP_PADDR 0 -#define SPIRAM_SMALL_SIZE_MAP_SIZE spiram_size +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +#define SPIRAM_MAP_PADDR_START EXT_BSS_PAGE_ALIGN_SIZE +#define FREE_DRAM0_DRAM1_DPORT_CACHE_START (DPORT_CACHE_ADDRESS_LOW + EXT_BSS_PAGE_ALIGN_SIZE) +#define FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE (DRAM0_DRAM1_DPORT_CACHE_SIZE - EXT_BSS_PAGE_ALIGN_SIZE) +#else +#define SPIRAM_MAP_PADDR_START 0 +#define FREE_DRAM0_DRAM1_DPORT_CACHE_START (DPORT_CACHE_ADDRESS_LOW) +#define FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE (DRAM0_DRAM1_DPORT_CACHE_SIZE) +#endif // if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY -#define SPIRAM_MID_SIZE_MAP_VADDR (AHB_DBUS3_ADDRESS_HIGH - SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) -#define SPIRAM_MID_SIZE_MAP_PADDR 0 -#define SPIRAM_MID_SIZE_MAP_SIZE (SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) +#define SPIRAM_MAP_VADDR_START (DRAM0_CACHE_ADDRESS_HIGH - spiram_map_size) +#define SPIRAM_MAP_SIZE spiram_map_size -#define SPIRAM_BIG_SIZE_MAP_VADDR AHB_DBUS3_ADDRESS_LOW -#define SPIRAM_BIG_SIZE_MAP_PADDR (AHB_DBUS3_ADDRESS_HIGH - DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE) -#define SPIRAM_BIG_SIZE_MAP_SIZE DBUS3_ONLY_CACHE_SIZE - -#define SPIRAM_MID_BIG_SIZE_MAP_VADDR DPORT_CACHE_ADDRESS_LOW -#define SPIRAM_MID_BIG_SIZE_MAP_PADDR SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT -#define SPIRAM_MID_BIG_SIZE_MAP_SIZE DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE - -void IRAM_ATTR esp_spiram_init_cache(void) -{ - size_t spiram_size = esp_spiram_get_size(); - Cache_Suspend_DCache(); - /* map the address from SPIRAM end to the start, map the address in order: DRAM1, DRAM1, DPORT, DBUS3 */ - if (spiram_size <= DRAM0_ONLY_CACHE_SIZE) { - /* cache size <= 3MB + 512 KB, only map DRAM0 bus */ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_SMALL_SIZE_MAP_VADDR, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, SPIRAM_SMALL_SIZE_MAP_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0); - } else if (spiram_size <= DRAM0_DRAM1_CACHE_SIZE) { - /* cache size <= 7MB + 512KB, only map DRAM0 and DRAM1 bus */ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_SMALL_SIZE_MAP_VADDR, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, SPIRAM_SMALL_SIZE_MAP_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0); - } else if (spiram_size <= DRAM0_DRAM1_DPORT_CACHE_SIZE) { - /* cache size <= 10MB + 512KB, map DRAM0, DRAM1, DPORT bus */ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_SMALL_SIZE_MAP_VADDR, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, SPIRAM_SMALL_SIZE_MAP_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); - } else { - /* cache size > 10MB + 512KB, map DRAM0, DRAM1, DPORT bus , only remap 0x3f500000 ~ 0x3ff90000*/ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, DPORT_CACHE_ADDRESS_LOW, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, DRAM0_DRAM1_DPORT_CACHE_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); - } - Cache_Resume_DCache(0); -} - -static uint32_t pages_for_flash = 0; -static uint32_t instrcution_in_spiram = 0; +static uint32_t next_map_page_num = 0; +static uint32_t instruction_in_spiram = 0; static uint32_t rodata_in_spiram = 0; +static size_t spiram_size = 0; +static size_t spiram_map_size = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS static int instr_flash2spiram_offs = 0; @@ -155,9 +92,44 @@ static uint32_t page0_mapped = 0; static uint32_t page0_page = INVALID_PHY_PAGE; #endif +void IRAM_ATTR esp_spiram_init_cache(void) +{ + spiram_map_size = spiram_size; + Cache_Suspend_DCache(); + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + /*if instruction or rodata in flash will be load to spiram, some subsequent operations require the start + address to be aligned by page, so allocate N pages address space for spiram's bss*/ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, DPORT_CACHE_ADDRESS_LOW, 0, 64, EXT_BSS_PAGE_ALIGN_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DPORT); + next_map_page_num += (EXT_BSS_PAGE_ALIGN_SIZE >> 16); + spiram_map_size -= EXT_BSS_PAGE_ALIGN_SIZE; +#endif + + /* map the address from SPIRAM end to the start, map the address in order: DRAM0, DRAM1, DPORT */ + if (spiram_map_size <= DRAM0_ONLY_CACHE_SIZE) { + /* psram need to be mapped vaddr size <= 3MB + 512 KB, only map DRAM0 bus */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_MAP_VADDR_START, SPIRAM_MAP_PADDR_START, 64, SPIRAM_MAP_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0); + } else if (spiram_map_size <= DRAM0_DRAM1_CACHE_SIZE) { + /* psram need to be mapped vaddr size <= 7MB + 512KB, only map DRAM0 and DRAM1 bus */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_MAP_VADDR_START, SPIRAM_MAP_PADDR_START, 64, SPIRAM_MAP_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0); + } else if (spiram_size <= DRAM0_DRAM1_DPORT_CACHE_SIZE) { // Equivalent to {spiram_map_size < DRAM0_DRAM1_DPORT_CACHE_SIZE - (spiram_size - spiram_map_size)/*bss size*/} + /* psram need to be mapped vaddr size <= 10MB + 512KB - bss_page_align_size, map DRAM0, DRAM1, DPORT bus */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_MAP_VADDR_START, SPIRAM_MAP_PADDR_START, 64, SPIRAM_MAP_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); + } else { + /* psram need to be mapped vaddr size > 10MB + 512KB - bss_page_align_size, map DRAM0, DRAM1, DPORT bus ,discard the memory in the end of spiram */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, FREE_DRAM0_DRAM1_DPORT_CACHE_START, SPIRAM_MAP_PADDR_START, 64, FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); + } + Cache_Resume_DCache(0); +} + uint32_t esp_spiram_instruction_access_enabled(void) { - return instrcution_in_spiram; + return instruction_in_spiram; } uint32_t esp_spiram_rodata_access_enabled(void) @@ -168,23 +140,22 @@ uint32_t esp_spiram_rodata_access_enabled(void) #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS esp_err_t esp_spiram_enable_instruction_access(void) { - size_t spiram_size = esp_spiram_get_size(); uint32_t pages_in_flash = 0; pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_IBUS0, &page0_mapped); pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_IBUS1, &page0_mapped); - if ((pages_in_flash + pages_for_flash) > (spiram_size >> 16)) { - ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, has %d pages, need %d pages.", (spiram_size >> 16), (pages_in_flash + pages_for_flash)); + if ((pages_in_flash + next_map_page_num) > (spiram_size >> 16)) { + ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, has %d pages, need %d pages.", (spiram_size >> 16), (pages_in_flash + next_map_page_num)); return ESP_FAIL; } ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM"); uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START + instr_mmu_offset*sizeof(uint32_t)); mmu_value &= MMU_ADDRESS_MASK; - instr_flash2spiram_offs = mmu_value - pages_for_flash; - ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, instr_flash2spiram_offs); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, pages_for_flash, &page0_page); - instrcution_in_spiram = 1; + instr_flash2spiram_offs = mmu_value - next_map_page_num; + ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, next_map_page_num, instr_flash2spiram_offs); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, next_map_page_num, &page0_page); + instruction_in_spiram = 1; return ESP_OK; } #endif @@ -198,7 +169,7 @@ esp_err_t esp_spiram_enable_rodata_access(void) pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_DBUS1, &page0_mapped); pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_DBUS2, &page0_mapped); - if ((pages_in_flash + pages_for_flash) > (esp_spiram_get_size() >> 16)) { + if ((pages_in_flash + next_map_page_num) > (spiram_size >> 16)) { ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the read only data."); return ESP_FAIL; } @@ -207,12 +178,12 @@ esp_err_t esp_spiram_enable_rodata_access(void) uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START + rodata_mmu_offset*sizeof(uint32_t)); mmu_value &= MMU_ADDRESS_MASK; - rodata_flash2spiram_offs = mmu_value - pages_for_flash; - ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, rodata_flash2spiram_offs); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, pages_for_flash, &page0_page); + rodata_flash2spiram_offs = mmu_value - next_map_page_num; + ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, next_map_page_num, rodata_flash2spiram_offs); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, next_map_page_num, &page0_page); rodata_in_spiram = 1; return ESP_OK; } @@ -285,7 +256,7 @@ esp_err_t esp_spiram_init(void) spiram_inited = true; - size_t spiram_size = esp_spiram_get_size(); + spiram_size = esp_spiram_get_size(); #if (CONFIG_SPIRAM_SIZE != -1) if (spiram_size != CONFIG_SPIRAM_SIZE) { @@ -308,30 +279,58 @@ esp_err_t esp_spiram_init(void) esp_err_t esp_spiram_add_to_heapalloc(void) { - size_t spiram_size = esp_spiram_get_size(); - uint32_t size_for_flash = (pages_for_flash << 16); - intptr_t vaddr; - ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (spiram_size - (pages_for_flash << 16))/1024); - //Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's - //no need to explicitly specify them. + size_t recycle_pages_size = 0; + size_t map_size = 0; + intptr_t map_vaddr, map_paddr; + ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (spiram_size - (next_map_page_num << 16))/1024); +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + if(EXT_BSS_SIZE){ + ESP_EARLY_LOGI(TAG, "Adding pool of %d Byte(spiram .bss page unused area) of external SPI memory to heap allocator", EXT_BSS_PAGE_ALIGN_SIZE - EXT_BSS_SIZE); + esp_err_t err_status = heap_caps_add_region(DPORT_CACHE_ADDRESS_LOW + EXT_BSS_SIZE, FREE_DRAM0_DRAM1_DPORT_CACHE_START - 1); + if (err_status != ESP_OK){ + return err_status; + } + } +#endif + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA + /* Part of the physical address space in spiram is mapped by IRAM0/DROM0, + so the DPORT_DRAM0_DRAM1 address space of the same size can be released */ + uint32_t occupied_pages_size = (next_map_page_num << 16); + recycle_pages_size = occupied_pages_size - SPIRAM_MAP_PADDR_START; +#endif + + // Small size: means DPORT_DRAM0_DRAM1 bus virtrual address space larger than the spiram size if (spiram_size <= DRAM0_DRAM1_DPORT_CACHE_SIZE) { - /* cache size <= 10MB + 512KB, map DRAM0, DRAM1, DPORT bus */ - vaddr = SPIRAM_SMALL_SIZE_MAP_VADDR; - return heap_caps_add_region(vaddr + size_for_flash, vaddr + spiram_size - 1); + map_vaddr = SPIRAM_MAP_VADDR_START; + return heap_caps_add_region(map_vaddr + recycle_pages_size, map_vaddr + spiram_map_size - 1); // pass rodata & instruction section } - vaddr = DPORT_CACHE_ADDRESS_LOW; - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, vaddr, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, DRAM0_DRAM1_DPORT_CACHE_SIZE >> 16, 0); - if (size_for_flash <= SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) { - return heap_caps_add_region(vaddr, vaddr + DRAM0_DRAM1_DPORT_CACHE_SIZE - 1); + // Middle size: means DPORT_DRAM0_DRAM1 bus virtrual address space less than the + // spiram size, but after releasing the virtual address space mapped + // from the rodata or instruction copied from the flash, the released + // virtual address space is enough to map the abandoned physical address + // space in spiram + if (recycle_pages_size >= SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) { + map_vaddr = SPIRAM_MAP_VADDR_START + recycle_pages_size; + map_paddr = SPIRAM_MAP_PADDR_START + recycle_pages_size; + map_size = SPIRAM_MAP_SIZE - recycle_pages_size; + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, map_vaddr, map_paddr, 64, map_size >> 16, 0); + return heap_caps_add_region(map_vaddr , map_vaddr + map_size - 1); } - // Largest size - return heap_caps_add_region(vaddr + size_for_flash, vaddr + DRAM0_DRAM1_DPORT_CACHE_SIZE -1); + // Large size: means after releasing the virtual address space mapped from the rodata + // or instruction copied from the flash, the released virtual address space + // still not enough to map the abandoned physical address space in spiram, + // so use all the virtual address space as much as possible + map_vaddr = FREE_DRAM0_DRAM1_DPORT_CACHE_START; + map_paddr = SPIRAM_MAP_PADDR_START + recycle_pages_size; + map_size = FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE; + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, map_vaddr, map_paddr, 64, map_size >> 16, 0); + return heap_caps_add_region(map_vaddr, map_vaddr + FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE -1); } - static uint8_t *dma_heap; esp_err_t esp_spiram_reserve_dma_pool(size_t size) { @@ -378,4 +377,42 @@ bool esp_spiram_is_initialized(void) return spiram_inited; } +/* + Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns + true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been + initialized (in a two-core system) or after the heap allocator has taken ownership of the memory. +*/ +bool esp_spiram_test(void) +{ + volatile int *spiram = (volatile int*)(SOC_EXTRAM_DATA_HIGH - spiram_map_size); + size_t p; + size_t s = spiram_map_size; + int errct=0; + int initial_err=-1; + + if (SOC_EXTRAM_DATA_SIZE < spiram_map_size) { + ESP_EARLY_LOGW(TAG, "Only test spiram from %08x to %08x\n", SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH); + spiram=(volatile int*)SOC_EXTRAM_DATA_LOW; + s = SOC_EXTRAM_DATA_SIZE; + } + for (p=0; p<(s/sizeof(int)); p+=8) { + spiram[p]=p^0xAAAAAAAA; + } + for (p=0; p<(s/sizeof(int)); p+=8) { + if (spiram[p]!=(p^0xAAAAAAAA)) { + errct++; + if (errct==1) initial_err=p*4; + if (errct < 4) { + ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p^0xAAAAAAAA); + } + } + } + if (errct) { + ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err+SOC_EXTRAM_DATA_LOW); + return false; + } else { + ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK"); + return true; + } +} #endif diff --git a/components/esp_hw_support/port/esp32s3/spiram.c b/components/esp_hw_support/port/esp32s3/spiram.c index 37a7d28e89..f554cb096c 100644 --- a/components/esp_hw_support/port/esp32s3/spiram.c +++ b/components/esp_hw_support/port/esp32s3/spiram.c @@ -104,7 +104,7 @@ void IRAM_ATTR esp_spiram_init_cache(void) } static uint32_t pages_for_flash = 0; -static uint32_t instrcution_in_spiram = 0; +static uint32_t instruction_in_spiram = 0; static uint32_t rodata_in_spiram = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS @@ -126,7 +126,7 @@ static uint32_t page0_page = INVALID_PHY_PAGE; uint32_t esp_spiram_instruction_access_enabled(void) { - return instrcution_in_spiram; + return instruction_in_spiram; } uint32_t esp_spiram_rodata_access_enabled(void) @@ -149,7 +149,7 @@ esp_err_t esp_spiram_enable_instruction_access(void) instr_flash2spiram_offs = mmu_value - pages_for_flash; ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, instr_flash2spiram_offs); pages_for_flash = Cache_Flash_To_SPIRAM_Copy(CACHE_IBUS, IRAM0_CACHE_ADDRESS_LOW, pages_for_flash, &page0_page); - instrcution_in_spiram = 1; + instruction_in_spiram = 1; return ESP_OK; } #endif diff --git a/components/esp_system/ld/esp32/memory.ld.in b/components/esp_system/ld/esp32/memory.ld.in index 49b2bc3be5..9a8af9e096 100644 --- a/components/esp_system/ld/esp32/memory.ld.in +++ b/components/esp_system/ld/esp32/memory.ld.in @@ -102,7 +102,7 @@ MEMORY rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ESP32_ULP_COPROC_RESERVE_MEM, len = 0x2000 - CONFIG_ESP32_ULP_COPROC_RESERVE_MEM - /* external memory ,including data and text */ + /* external memory */ extern_ram_seg(RWX) : org = 0x3F800000, len = 0x400000 } diff --git a/components/esp_system/ld/esp32s2/memory.ld.in b/components/esp_system/ld/esp32s2/memory.ld.in index ffe08e5333..d4c50f4253 100644 --- a/components/esp_system/ld/esp32s2/memory.ld.in +++ b/components/esp_system/ld/esp32s2/memory.ld.in @@ -107,6 +107,10 @@ MEMORY /* RTC fast memory (same block as above), viewed from data bus */ rtc_data_seg(RW) : org = 0x3ff9e000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + + /* external memory, covers the dport, dram0, dram1 cacheable address space */ + extern_ram_seg(RWX) : org = 0x3F500000, + len = 0xA80000 } #if defined(CONFIG_ESP32S2_USE_FIXED_STATIC_RAM_SIZE) diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index e4cd142753..3c6bbe87ed 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -226,6 +226,17 @@ SECTIONS _noinit_end = ABSOLUTE(.); } > dram0_0_seg + /* external memory bss, from any global variable with EXT_RAM_ATTR attribute*/ + .ext_ram.bss (NOLOAD) : + { + _ext_ram_bss_start = ABSOLUTE(.); + + mapping[extern_ram] + + . = ALIGN(4); + _ext_ram_bss_end = ABSOLUTE(.); + } > extern_ram_seg + /* Shared RAM */ .dram0.bss (NOLOAD) : { diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 220daa0d23..9c91e94440 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -125,16 +125,15 @@ extern int _vector_table; static const char *TAG = "cpu_start"; -#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY extern int _ext_ram_bss_start; extern int _ext_ram_bss_end; #endif + #ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY extern int _iram_bss_start; extern int _iram_bss_end; #endif -#endif // CONFIG_IDF_TARGET_ESP32 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE static volatile bool s_cpu_up[SOC_CPU_CORES_NUM] = { false }; @@ -380,7 +379,7 @@ void IRAM_ATTR call_start_cpu0(void) bootloader_init_mem(); #if CONFIG_SPIRAM_BOOT_INIT if (esp_spiram_init() != ESP_OK) { -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY ESP_EARLY_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment"); abort(); diff --git a/components/soc/esp32s2/include/soc/cache_memory.h b/components/soc/esp32s2/include/soc/cache_memory.h index 06de5a4323..5c182bd6c4 100644 --- a/components/soc/esp32s2/include/soc/cache_memory.h +++ b/components/soc/esp32s2/include/soc/cache_memory.h @@ -67,7 +67,7 @@ extern "C" { #define BUS_DROM0_CACHE_SIZE BUS_SIZE(DROM0) #define BUS_DRAM0_CACHE_SIZE BUS_SIZE(DRAM0_CACHE) #define BUS_DRAM1_CACHE_SIZE BUS_SIZE(DRAM1) -#define BUS_DPORT_CACHE_SIZE BUS_SIZE(DPORT) +#define BUS_DPORT_CACHE_SIZE BUS_SIZE(DPORT_CACHE) #define PRO_CACHE_IBUS0 0 #define PRO_CACHE_IBUS0_MMU_START 0 diff --git a/tools/unit-test-app/configs/spi_flash_config_2_s2 b/tools/unit-test-app/configs/spi_flash_config_2_s2 index dff40d8377..b1badb9aac 100644 --- a/tools/unit-test-app/configs/spi_flash_config_2_s2 +++ b/tools/unit-test-app/configs/spi_flash_config_2_s2 @@ -1,5 +1,6 @@ TEST_COMPONENTS=spi_flash CONFIG_ESP32S2_SPIRAM_SUPPORT=y CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y -CONFIG_SPIRAM_RODATA=y +CONFIG_SPIRAM_RODATA=n +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_IDF_TARGET="esp32s2" diff --git a/tools/unit-test-app/configs/spi_flash_config_3_s2 b/tools/unit-test-app/configs/spi_flash_config_3_s2 index 7d79b240f0..a457c0efbc 100644 --- a/tools/unit-test-app/configs/spi_flash_config_3_s2 +++ b/tools/unit-test-app/configs/spi_flash_config_3_s2 @@ -2,4 +2,5 @@ TEST_COMPONENTS=spi_flash CONFIG_ESP32S2_SPIRAM_SUPPORT=y CONFIG_SPIRAM_FETCH_INSTRUCTIONS=n CONFIG_SPIRAM_RODATA=y +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_IDF_TARGET="esp32s2" diff --git a/tools/unit-test-app/configs/spi_flash_config_4_s2 b/tools/unit-test-app/configs/spi_flash_config_4_s2 new file mode 100644 index 0000000000..48efd202f0 --- /dev/null +++ b/tools/unit-test-app/configs/spi_flash_config_4_s2 @@ -0,0 +1,6 @@ +TEST_COMPONENTS=spi_flash +CONFIG_ESP32S2_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y +CONFIG_SPIRAM_RODATA=y +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_IDF_TARGET="esp32s2" From 6c272d651581b18dcc88038f61480636566f3c5a Mon Sep 17 00:00:00 2001 From: SalimTerryLi Date: Wed, 25 Aug 2021 15:59:51 +0800 Subject: [PATCH 035/310] bugfix: hc-sr04 example: init queue before setup ISR Closes https://github.com/espressif/esp-idf/issues/7419 --- .../main/mcpwm_capture_hc_sr04.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c index 44363ee0ad..f3a4cfb566 100644 --- a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c +++ b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c @@ -79,6 +79,13 @@ static bool sr04_echo_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t void app_main(void) { ESP_LOGI(TAG, "HC-SR04 example based on capture function from MCPWM"); + // the queue where we read data + cap_queue = xQueueCreate(1, sizeof(uint32_t)); + if (cap_queue == NULL) { + ESP_LOGE(TAG, "failed to alloc cap_queue"); + return; + } + /* configure Echo pin */ // set CAP_0 on GPIO ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, HC_SR04_PIN_ECHO)); @@ -106,12 +113,6 @@ void app_main(void) { ESP_ERROR_CHECK(gpio_set_level(HC_SR04_PIN_TRIG, 0)); // drive low by default ESP_LOGI(TAG, "Trig pin configured"); - // the queue where we read data - cap_queue = xQueueCreate(1, sizeof(uint32_t)); - if (cap_queue == 0) { - ESP_LOGE(TAG, "failed to alloc cap_queue"); - } - // start generating trig signal xTaskCreate(gen_trig_output, "gen_trig_output", TRIGGER_THREAD_STACK_SIZE, NULL, TRIGGER_THREAD_PRIORITY, NULL); ESP_LOGI(TAG, "trig task started"); From 0b3476fdd0c792b260276684305224bc6135ae1b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 26 Jul 2021 09:53:26 +0200 Subject: [PATCH 036/310] CI: mqtt test apps: removed unnecessary env.yml --- .gitlab/ci/target-test.yml | 2 +- tools/test_apps/protocols/mqtt/publish_connect_test/env.yml | 0 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/env.yml diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 5be1958303..8b4ecfaba9 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -60,7 +60,7 @@ test_weekend_mqtt: - export MQTT_PUBLISH_TEST=1 - export TEST_PATH=$CI_PROJECT_DIR/tools/test_apps/protocols/mqtt/publish_connect_test - cd $IDF_PATH/tools/ci/python_packages/tiny_test_fw/bin - - run_cmd python Runner.py $TEST_PATH -c $TEST_PATH/publish_connect_mqtt_.yml -e $TEST_PATH/env.yml + - run_cmd python Runner.py $TEST_PATH -c $TEST_PATH/publish_connect_mqtt_.yml .example_test_esp32_template: extends: diff --git a/tools/test_apps/protocols/mqtt/publish_connect_test/env.yml b/tools/test_apps/protocols/mqtt/publish_connect_test/env.yml deleted file mode 100644 index e69de29bb2..0000000000 From b342b498231cf011c01be9c26c48c5431cfe0f2f Mon Sep 17 00:00:00 2001 From: sly Date: Tue, 10 Aug 2021 15:51:23 +0800 Subject: [PATCH 037/310] fix esp32c3 auto adjust voltage bug --- components/esp_hw_support/port/esp32c3/rtc_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_hw_support/port/esp32c3/rtc_init.c b/components/esp_hw_support/port/esp32c3/rtc_init.c index 7a33720bea..1458eae2b8 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_init.c @@ -296,7 +296,7 @@ uint32_t get_rtc_dbias_by_efuse(uint8_t chip_version, uint32_t dig_dbias) signed int k_dig_ldo_real_mul10000 = K_DIG_MID_MUL10000 + k_dig_ldo; uint32_t v_dig_nearest_1v15_mul10000 = v_dig_dbias20_real_mul10000 + k_dig_ldo_real_mul10000 * (dig_dbias - 20); uint32_t v_rtc_nearest_1v15_mul10000 = 0; - for (rtc_dbias = 15; rtc_dbias < 32; rtc_dbias++) { + for (rtc_dbias = 15; rtc_dbias < 31; rtc_dbias++) { v_rtc_nearest_1v15_mul10000 = v_rtc_dbias20_real_mul10000 + k_rtc_ldo_real_mul10000 * (rtc_dbias - 20); if (v_rtc_nearest_1v15_mul10000 >= v_dig_nearest_1v15_mul10000 - 250) break; From 4175aa0892b948356f63a4f4b0f350e590d28829 Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Wed, 28 Jul 2021 15:32:59 +0800 Subject: [PATCH 038/310] openthread: add ot_rcp example --- components/esp_phy/lib | 2 +- .../ieee802154/include/esp_ieee802154_types.h | 2 + components/ieee802154/lib | 2 +- components/openthread/CMakeLists.txt | 59 +--- components/openthread/component.mk | 2 +- components/openthread/ftd.cmake | 52 ++++ .../openthread/include/esp_openthread_types.h | 5 +- ....h => openthread-core-esp32x-ftd-config.h} | 0 .../openthread-core-esp32x-radio-config.h | 292 ++++++++++++++++++ components/openthread/lib | 2 +- components/openthread/radio.cmake | 77 +++++ docs/doxygen/Doxyfile | 3 +- .../api-reference/network/esp_openthread.rst | 5 +- .../openthread/ot_br/main/esp_ot_config.h | 36 +-- .../openthread/ot_cli/main/esp_ot_config.h | 36 +-- examples/openthread/ot_rcp/CMakeLists.txt | 6 + examples/openthread/ot_rcp/Makefile | 8 + examples/openthread/ot_rcp/README.md | 69 +++++ .../openthread/ot_rcp/main/CMakeLists.txt | 2 + .../openthread/ot_rcp/main/esp_ot_config.h | 48 +++ examples/openthread/ot_rcp/main/esp_ot_rcp.c | 66 ++++ examples/openthread/ot_rcp/partitions.csv | 6 + examples/openthread/ot_rcp/sdkconfig.defaults | 48 +++ 23 files changed, 736 insertions(+), 92 deletions(-) create mode 100644 components/openthread/ftd.cmake rename components/openthread/include/{openthread-core-esp32x-config.h => openthread-core-esp32x-ftd-config.h} (100%) create mode 100644 components/openthread/include/openthread-core-esp32x-radio-config.h create mode 100644 components/openthread/radio.cmake create mode 100644 examples/openthread/ot_rcp/CMakeLists.txt create mode 100644 examples/openthread/ot_rcp/Makefile create mode 100644 examples/openthread/ot_rcp/README.md create mode 100644 examples/openthread/ot_rcp/main/CMakeLists.txt create mode 100644 examples/openthread/ot_rcp/main/esp_ot_config.h create mode 100644 examples/openthread/ot_rcp/main/esp_ot_rcp.c create mode 100644 examples/openthread/ot_rcp/partitions.csv create mode 100644 examples/openthread/ot_rcp/sdkconfig.defaults diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 8b1137c35c..1174878441 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 8b1137c35cc3d2b1085e7f857c2530efb115d3a3 +Subproject commit 1174878441c77b467503b1b7a1b24e00bea2839e diff --git a/components/ieee802154/include/esp_ieee802154_types.h b/components/ieee802154/include/esp_ieee802154_types.h index 6979991cc3..1407563171 100644 --- a/components/ieee802154/include/esp_ieee802154_types.h +++ b/components/ieee802154/include/esp_ieee802154_types.h @@ -41,6 +41,8 @@ typedef enum { ESP_IEEE802154_TX_ERR_NO_ACK, /*!< No Ack frame received until timeout */ ESP_IEEE802154_TX_ERR_INVALID_ACK, /*!< Invalid Ack frame */ ESP_IEEE802154_TX_ERR_COEXIST, /*!< Rejected by coexist system */ + ESP_IEEE802154_TX_ERR_COEXIST_REJ, /*!< Rejected by coexist system before transmitting frame */ + ESP_IEEE802154_TX_ERR_COEXIST_ACK, /*!< Rejected by coexist system when receiving ack */ } esp_ieee802154_tx_error_t; /** diff --git a/components/ieee802154/lib b/components/ieee802154/lib index efbc05d641..dd7afcc9f6 160000 --- a/components/ieee802154/lib +++ b/components/ieee802154/lib @@ -1 +1 @@ -Subproject commit efbc05d641040253567e825dae53731da595c7b5 +Subproject commit dd7afcc9f6d4bbd923f601e0d59b0e59b0170a91 diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index c32211eadc..993432260d 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -1,51 +1,10 @@ if(CONFIG_OPENTHREAD_ENABLED) - set(public_include_dirs - "include" - "openthread/include") - - set(private_include_dirs - "openthread/src" - "openthread/src/core" - "openthread/src/lib/hdlc" - "openthread/src/lib/spinel" - "openthread/src/ncp" - "openthread/examples/platforms/") - - set(src_dirs - "openthread/examples/apps/cli" - "openthread/examples/platforms/utils" - "openthread/src/cli" - "openthread/src/core/api" - "openthread/src/core/backbone_router" - "openthread/src/core/coap" - "openthread/src/core/common" - "openthread/src/core/crypto" - "openthread/src/core/diags" - "openthread/src/core/mac" - "openthread/src/core/meshcop" - "openthread/src/core/net" - "openthread/src/core/radio" - "openthread/src/core/thread" - "openthread/src/core/utils" - "openthread/src/lib/platform" - "openthread/src/lib/hdlc" - "openthread/src/lib/spinel") - - if(CONFIG_OPENTHREAD_BORDER_ROUTER) - list(APPEND src_dirs - "openthread/src/core/border_router") + if(CONFIG_OPENTHREAD_FTD) + include(ftd.cmake) + else() + include(radio.cmake) endif() - set(exclude_srcs - "openthread/examples/apps/cli/main.c" - "openthread/examples/platforms/utils/logging_rtt.c" - "openthread/examples/platforms/utils/soft_source_match_table.c" - "openthread/src/core/common/extension_example.cpp") - - set_source_files_properties("openthread/src/core/net/srp_server.cpp" - PROPERTIES COMPILE_FLAGS - -Wno-maybe-uninitialized) - if(CONFIG_OPENTHREAD_FTD) set(device_type "OPENTHREAD_FTD=1") elseif(CONFIG_OPENTHREAD_MTD) @@ -75,13 +34,19 @@ idf_component_register(SRC_DIRS "${src_dirs}" REQUIRES mbedtls ieee802154) if(CONFIG_OPENTHREAD_ENABLED) + if(CONFIG_OPENTHREAD_RADIO) + set(CONFIG_FILE_TYPE "radio") + else() + set(CONFIG_FILE_TYPE "ftd") + endif() + target_compile_definitions( ${COMPONENT_LIB} PUBLIC - "OPENTHREAD_CONFIG_FILE=\"openthread-core-esp32x-config.h\"" + "OPENTHREAD_CONFIG_FILE=\"openthread-core-esp32x-${CONFIG_FILE_TYPE}-config.h\"" "${device_type}" PRIVATE - "PACKAGE_VERSION=\"${IDF_VERSION_FOR_OPENTHREAD_PACKAGE}-${OPENTHREAD_VERSION}\"") + "PACKAGE_VERSION=\"${IDF_VERSION_FOR_OPENTHREAD_PACKAGE}-${OPENTHREAD_VERSION}\"") if(CONFIG_OPENTHREAD_ESP_LIB_FROM_INTERNAL_SRC) idf_component_get_property(openthread_port_lib openthread_port COMPONENT_LIB) diff --git a/components/openthread/component.mk b/components/openthread/component.mk index c49b004d42..b404e35c21 100644 --- a/components/openthread/component.mk +++ b/components/openthread/component.mk @@ -57,7 +57,7 @@ OPENTHREAD_VERSION := $(shell git -C $(COMPONENT_PATH)/openthread rev-parse --sh OPENTHREAD_PACKAGE_VERSION := $(IDF_VERSION_FOR_OPENTHREAD_PACKAGE)-$(OPENTHREAD_VERSION) COMMON_FLAGS := \ - -DOPENTHREAD_CONFIG_FILE=\ \ + -DOPENTHREAD_CONFIG_FILE=\ \ -DPACKAGE_VERSION=\"OPENTHREAD_PACKAGE_VERSION\" \ -Wno-maybe-uninitialized diff --git a/components/openthread/ftd.cmake b/components/openthread/ftd.cmake new file mode 100644 index 0000000000..89ef3e1735 --- /dev/null +++ b/components/openthread/ftd.cmake @@ -0,0 +1,52 @@ +set(public_include_dirs + "include" + "openthread/include") + +set(private_include_dirs + "openthread/examples/platforms" + "openthread/include/openthread" + "openthread/src" + "openthread/src/core" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/ncp" + ) + +set(src_dirs + "openthread/examples/apps/cli" + "openthread/examples/platforms/utils" + "openthread/src/core/api" + "openthread/src/core/backbone_router" + "openthread/src/core/coap" + "openthread/src/core/common" + "openthread/src/core/crypto" + "openthread/src/core/diags" + "openthread/src/core/mac" + "openthread/src/core/meshcop" + "openthread/src/core/net" + "openthread/src/core/radio" + "openthread/src/core/thread" + "openthread/src/core/utils" + "openthread/src/cli" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/lib/platform") + +set(exclude_srcs + "openthread/examples/apps/cli/main.c" + "openthread/examples/platforms/utils/logging_rtt.c" + "openthread/examples/platforms/utils/soft_source_match_table.c" + "openthread/src/core/common/extension_example.cpp") + +if(CONFIG_OPENTHREAD_BORDER_ROUTER) + list(APPEND src_dirs + "openthread/src/core/border_router") +endif() + +set_source_files_properties("openthread/src/core/net/srp_server.cpp" + PROPERTIES COMPILE_FLAGS + -Wno-maybe-uninitialized) + +if(CONFIG_OPENTHREAD_FTD) + set(device_type "OPENTHREAD_FTD=1") +endif() diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index a3fb31ed41..1b1234ddcd 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -82,8 +82,9 @@ typedef enum { * */ typedef enum { - HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection*/ - HOST_CONNECTION_MODE_UART = 0x1, /*!< UART connection to the host*/ + HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection*/ + HOST_CONNECTION_MODE_CLI_UART = 0x1, /*!< CLI UART connection to the host*/ + HOST_CONNECTION_MODE_RCP_UART = 0x2, /*!< RCP UART connection to the host*/ } esp_openthread_host_connection_mode_t; /** diff --git a/components/openthread/include/openthread-core-esp32x-config.h b/components/openthread/include/openthread-core-esp32x-ftd-config.h similarity index 100% rename from components/openthread/include/openthread-core-esp32x-config.h rename to components/openthread/include/openthread-core-esp32x-ftd-config.h diff --git a/components/openthread/include/openthread-core-esp32x-radio-config.h b/components/openthread/include/openthread-core-esp32x-radio-config.h new file mode 100644 index 0000000000..ace9c05e74 --- /dev/null +++ b/components/openthread/include/openthread-core-esp32x-radio-config.h @@ -0,0 +1,292 @@ +// Copyright 2021 Espressif Systems (Shanghai) CO LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License + +#pragma once + +#include "sdkconfig.h" +/** + * @def OPENTHREAD_CONFIG_PLATFORM_INFO + * + * The platform-specific string to insert into the OpenThread version string. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_INFO CONFIG_IDF_TARGET + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT + * + * The assert is managed by platform defined logic when this flag is set. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT 1 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE + * + * Define to 1 to enable otPlatFlash* APIs to support non-volatile storage. + * + * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_LOG_OUTPUT + * + * The ESP-IDF platform provides an otPlatLog() function. + */ +#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED + +/** + * @def OPENTHREAD_CONFIG_LOG_LEVEL + * + * The log level (used at compile time). If `OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE` is set, this defines the most + * verbose log level possible. See `OPENTHREAD_CONFIG_LOG_LEVEL_INIT` to set the initial log level. + * + */ +#ifndef OPENTHREAD_CONFIG_LOG_LEVEL +#if CONFIG_LOG_DEFAULT_LEVEL_NONE +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_NONE +#elif CONFIG_LOG_DEFAULT_LEVEL_ERROR +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_CRIT +#elif CONFIG_LOG_DEFAULT_LEVEL_WARN +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_WARN +#elif CONFIG_LOG_DEFAULT_LEVEL_INFO +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_INFO +#elif CONFIG_LOG_DEFAULT_LEVEL_DEBUG +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_DEBG +#elif CONFIG_LOG_DEFAULT_LEVEL_VERBOSE +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_DEBG +#endif +#endif + +#define OPENTHREAD_CONFIG_LOG_API 1 +#define OPENTHREAD_CONFIG_LOG_ARP 1 +#define OPENTHREAD_CONFIG_LOG_BBR 1 +#define OPENTHREAD_CONFIG_LOG_CLI 1 +#define OPENTHREAD_CONFIG_LOG_COAP 1 +#define OPENTHREAD_CONFIG_LOG_DUA 1 +#define OPENTHREAD_CONFIG_LOG_ICMP 1 +#define OPENTHREAD_CONFIG_LOG_IP6 1 +#define OPENTHREAD_CONFIG_LOG_MAC 1 +#define OPENTHREAD_CONFIG_LOG_MEM 1 +#define OPENTHREAD_CONFIG_LOG_MESHCOP 1 +#define OPENTHREAD_CONFIG_LOG_MLE 1 +#define OPENTHREAD_CONFIG_LOG_MLR 1 +#define OPENTHREAD_CONFIG_LOG_NETDATA 1 +#define OPENTHREAD_CONFIG_LOG_NETDIAG 1 +#define OPENTHREAD_CONFIG_LOG_PKT_DUMP 1 +#define OPENTHREAD_CONFIG_LOG_PLATFORM 1 + +/** + * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS + * + * The number of message buffers in buffer pool + */ +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 50 + +/** + * @def OPENTHREAD_CONFIG_COAP_API_ENABLE + * + * Define to 1 to enable the CoAP API. + * + */ +#define OPENTHREAD_CONFIG_COAP_API_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE + * + * Define to 1 to enable Border Router support. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + * + * Define to 1 to enable Thread Test Harness reference device support. + * + */ +#define OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE + * + * Define to 1 to enable Child Supervision support. + * + */ +#ifndef OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE +#define OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE + * + * Define to 1 to enable DHCPv6 Client support. + * + */ +#ifndef OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE + * + * Define to 1 to enable DHCPv6 Server support. + * + */ +#ifndef OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE +#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE + * + * Define to 1 to enable DNS Client support. + * + */ +#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_NCP_SPI_ENABLE + * + * Define to 1 to enable NCP SPI support. + * + */ +#define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0 + +/** + * @def OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER + * + * Define to 1 to enable NCP Spinel Encrypter. + * + */ +#define OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 0 + +/** + * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE + * + * Define to 1 to enable NCP HDLC support. + * + */ +#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1 + +/** + * @def OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE + * + * Define 1 to enable feeding an OpenThread message to encoder/decoder. + * + */ +#define OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + * + * Define to 1 to support injecting Service entries into the Thread Network Data. + * + */ +#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 0 + +/** + * @def PACKAGE_NAME + * + * Define to the full name of this package. + * + */ +#define PACKAGE_NAME "openthread-esp32" + +/** + * @def PACKAGE_STRING + * + * Define to the full name and version of this package. + * + */ +#define PACKAGE_STRING (PACKAGE_NAME " - " PACKAGE_VERSION) + +/** + * @def OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS + * + * Define as 1 to enable bultin-mbedtls. + * + * Note that the OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS determines whether to use bultin-mbedtls as well as + * whether to manage mbedTLS internally, such as memory allocation and debug. + * + */ +#define OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS 0 + +/** + * @def OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE + * + * Define as 1 to enable support for adding of auto-configured SLAAC addresses by OpenThread. + * + */ +#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS + * + * The maximum number of state-changed callback handlers (set using `otSetStateChangedCallback()`). + * + */ +#define OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS 3 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_RADIO_SPINEL_RX_FRAME_BUFFER_SIZE + * + * Specifies the rx frame buffer size used by `SpinelInterface` in RCP host code. This is applicable/used when + * `RadioSpinel` platform is used. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_SPINEL_RX_FRAME_BUFFER_SIZE 1024 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE + * + * Define as 1 to enable microsecond timer. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1 + +/** + * The configurable definitions via Kconfig + */ +#if CONFIG_OPENTHREAD_COMMISSIONER +#error "Commissioner shouldn't be enabled for RCP" +#endif + +#if CONFIG_OPENTHREAD_JOINER +#error "Joiner shouldn't be enabled for RCP" +#endif + +#if CONFIG_OPENTHREAD_DIAG +#define OPENTHREAD_CONFIG_DIAG_ENABLE 1 +#endif + +#if CONFIG_OPENTHREAD_FTD +#error "Only OPENTHREAD_RADIO is used for RCP" +#elif CONFIG_OPENTHREAD_MTD +#error "Only OPENTHREAD_RADIO is used for RCP" +#elif CONFIG_OPENTHREAD_RADIO +#define OPENTHREAD_RADIO 1 +#endif + + +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 1 +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE 1 +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 1 +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE 1 diff --git a/components/openthread/lib b/components/openthread/lib index 105f3610d2..5e09d71ee4 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 105f3610d2258d7a7dd1c72f5f1adea89077c6cc +Subproject commit 5e09d71ee4a6a8165ae4cdbabc46b79a88a95c11 diff --git a/components/openthread/radio.cmake b/components/openthread/radio.cmake new file mode 100644 index 0000000000..3c5510c497 --- /dev/null +++ b/components/openthread/radio.cmake @@ -0,0 +1,77 @@ +set(public_include_dirs + "include" + "openthread/include") + +set(private_include_dirs + "openthread/examples/platforms" + "openthread/include/openthread" + "openthread/src" + "openthread/src/core" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/ncp" + ) + +set(src_dirs + "openthread/examples/platforms/utils" + "openthread/src/core/api" + "openthread/src/core/common" + "openthread/src/core/crypto" + "openthread/src/core/diags" + "openthread/src/core/mac" + "openthread/src/core/radio" + "openthread/src/core/thread" + "openthread/src/core/utils" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/ncp" + "openthread/examples/apps/ncp") + +set(exclude_srcs + "openthread/examples/platforms/utils/logging_rtt.c" + "openthread/examples/platforms/utils/soft_source_match_table.c" + "openthread/examples/apps/ncp/main.c" + "openthread/src/core/api/backbone_router_api.cpp" + "openthread/src/core/api/entropy_api.cpp" + "openthread/src/core/api/netdata_api.cpp" + "openthread/src/core/api/link_api.cpp" + "openthread/src/core/api/icmp6_api.cpp" + "openthread/src/core/api/ip6_api.cpp" + "openthread/src/core/api/udp_api.cpp" + "openthread/src/core/common/settings.cpp" + "openthread/src/core/api/dataset_api.cpp" + "openthread/src/core/api/random_crypto_api.cpp" + "openthread/src/core/common/extension_example.cpp" + "openthread/src/core/common/heap_string.cpp" + "openthread/src/core/common/time_ticker.cpp" + "openthread/src/core/common/notifier.cpp" + "openthread/src/core/api/message_api.cpp" + "openthread/src/core/thread/energy_scan_server.cpp" + "openthread/src/core/thread/mesh_forwarder.cpp" + "openthread/src/core/thread/mle.cpp" + "openthread/src/core/thread/neighbor_table.cpp" + "openthread/src/core/thread/tmf.cpp" + "openthread/src/core/thread/network_data_leader_ftd.cpp" + "openthread/src/core/thread/discover_scanner.cpp" + "openthread/src/core/thread/lowpan.cpp" + "openthread/src/core/thread/network_data_leader.cpp" + "openthread/src/core/thread/mesh_forwarder_mtd.cpp" + "openthread/src/core/thread/key_manager.cpp" + "openthread/src/core/thread/network_data_types.cpp" + "openthread/src/core/thread/mesh_forwarder_ftd.cpp" + "openthread/src/core/thread/network_data.cpp" + "openthread/src/core/thread/network_data_service.cpp" + "openthread/src/core/thread/announce_begin_server.cpp" + "openthread/src/core/thread/announce_sender.cpp" + "openthread/src/core/thread/thread_netif.cpp" + "openthread/src/core/thread/topology.cpp" + "openthread/src/core/thread/panid_query_server.cpp" + "openthread/src/core/mac/channel_mask.cpp" + "openthread/src/core/mac/data_poll_handler.cpp" + "openthread/src/core/mac/data_poll_sender.cpp" + "openthread/src/core/mac/mac.cpp" + "openthread/src/core/mac/mac_filter.cpp" + "openthread/src/core/mac/mac_links.cpp" + "openthread/src/core/utils/child_supervision.cpp") + +set(device_type "OPENTHREAD_RADIO=1") diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index e513ed65a7..7424a473b3 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -158,7 +158,8 @@ INPUT = \ $(PROJECT_PATH)/components/openthread/include/esp_openthread_lock.h \ $(PROJECT_PATH)/components/openthread/include/esp_openthread_netif_glue.h \ $(PROJECT_PATH)/components/openthread/include/esp_openthread_types.h \ - $(PROJECT_PATH)/components/openthread/include/openthread-core-esp32x-config.h \ + $(PROJECT_PATH)/components/openthread/include/openthread-core-esp32x-ftd-config.h \ + $(PROJECT_PATH)/components/openthread/include/openthread-core-esp32x-radio-config.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs_dev.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs_eventfd.h \ diff --git a/docs/en/api-reference/network/esp_openthread.rst b/docs/en/api-reference/network/esp_openthread.rst index 8771b8b5dc..21f3933191 100644 --- a/docs/en/api-reference/network/esp_openthread.rst +++ b/docs/en/api-reference/network/esp_openthread.rst @@ -12,7 +12,8 @@ Application Examples The :example:`openthread` directory of ESP-IDF examples contains the following applications: - The OpenThread interactive shell :example:`openthread/ot_cli`. -- The Thread border router :example:`openthread/ot_cli`. +- The Thread border router :example:`openthread/ot_br`. +- The Thread radio co-processor :example:`openthread/ot_rcp`. API Reference @@ -28,5 +29,5 @@ ESP-IDF provides extra apis for launching and managing the OpenThread stack, bin .. include-build-file:: inc/esp_openthread_lock.inc .. include-build-file:: inc/esp_openthread_netif_glue.inc .. include-build-file:: inc/esp_openthread_border_router.inc - +.. include-build-file:: inc/openthread-core-esp32x-ftd-config.inc diff --git a/examples/openthread/ot_br/main/esp_ot_config.h b/examples/openthread/ot_br/main/esp_ot_config.h index e2ed326eac..70af02ca11 100644 --- a/examples/openthread/ot_br/main/esp_ot_config.h +++ b/examples/openthread/ot_br/main/esp_ot_config.h @@ -36,24 +36,24 @@ }, \ } -#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = HOST_CONNECTION_MODE_UART, \ - .host_uart_config = { \ - .port = 0, \ - .uart_config = \ - { \ - .baud_rate = 115200, \ - .data_bits = UART_DATA_8_BITS, \ - .parity = UART_PARITY_DISABLE, \ - .stop_bits = UART_STOP_BITS_1, \ - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ - .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_APB, \ - }, \ - .rx_pin = UART_PIN_NO_CHANGE, \ - .tx_pin = UART_PIN_NO_CHANGE, \ - }, \ +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ + .host_uart_config = { \ + .port = 0, \ + .uart_config = \ + { \ + .baud_rate = 115200, \ + .data_bits = UART_DATA_8_BITS, \ + .parity = UART_PARITY_DISABLE, \ + .stop_bits = UART_STOP_BITS_1, \ + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ + .rx_flow_ctrl_thresh = 0, \ + .source_clk = UART_SCLK_APB, \ + }, \ + .rx_pin = UART_PIN_NO_CHANGE, \ + .tx_pin = UART_PIN_NO_CHANGE, \ + }, \ } #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ diff --git a/examples/openthread/ot_cli/main/esp_ot_config.h b/examples/openthread/ot_cli/main/esp_ot_config.h index bd6371728b..edd8a34bc3 100644 --- a/examples/openthread/ot_cli/main/esp_ot_config.h +++ b/examples/openthread/ot_cli/main/esp_ot_config.h @@ -44,24 +44,24 @@ } #endif -#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = HOST_CONNECTION_MODE_UART, \ - .host_uart_config = { \ - .port = 0, \ - .uart_config = \ - { \ - .baud_rate = 115200, \ - .data_bits = UART_DATA_8_BITS, \ - .parity = UART_PARITY_DISABLE, \ - .stop_bits = UART_STOP_BITS_1, \ - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ - .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_APB, \ - }, \ - .rx_pin = UART_PIN_NO_CHANGE, \ - .tx_pin = UART_PIN_NO_CHANGE, \ - }, \ +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ + .host_uart_config = { \ + .port = 0, \ + .uart_config = \ + { \ + .baud_rate = 115200, \ + .data_bits = UART_DATA_8_BITS, \ + .parity = UART_PARITY_DISABLE, \ + .stop_bits = UART_STOP_BITS_1, \ + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ + .rx_flow_ctrl_thresh = 0, \ + .source_clk = UART_SCLK_APB, \ + }, \ + .rx_pin = UART_PIN_NO_CHANGE, \ + .tx_pin = UART_PIN_NO_CHANGE, \ + }, \ } #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ diff --git a/examples/openthread/ot_rcp/CMakeLists.txt b/examples/openthread/ot_rcp/CMakeLists.txt new file mode 100644 index 0000000000..d377b2ce87 --- /dev/null +++ b/examples/openthread/ot_rcp/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following 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(esp_ot_rcp) diff --git a/examples/openthread/ot_rcp/Makefile b/examples/openthread/ot_rcp/Makefile new file mode 100644 index 0000000000..e167f2d2f8 --- /dev/null +++ b/examples/openthread/ot_rcp/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := ot_esp_rcp + +include $(IDF_PATH)/make/project.mk diff --git a/examples/openthread/ot_rcp/README.md b/examples/openthread/ot_rcp/README.md new file mode 100644 index 0000000000..ac3c8ae58a --- /dev/null +++ b/examples/openthread/ot_rcp/README.md @@ -0,0 +1,69 @@ +| Supported Targets | ESP32-H2 | +| ----------------- | -------- | + +# OpenThread radio co-processor (RCP) example + +## Overview + +This example demonstrates an openthread radio co-processor. +The RCP can receive/transmit 15.4-type packets, encode and send the packet to the host device. +You can use the RCP to implement an Openthread sniffer. You cani also connect the RCP to the host device which do not have a 15.4-radio to join in an Openthread network. + +To run this example, an ESP32-H2 board is required. + +### Config ESP32-H2 uart + +Modify the file `esp_ot_config.h`. + +In the file `esp_ot_config.h`, there are three parameters. +As for `ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG` and `ESP_OPENTHREAD_DEFAULT_PORT_CONFIG`, modification is not recommended. +As for the parameters in `ESP_OPENTHREAD_DEFAULT_HOST_CONFIG`, you can refer to ESP uart example `example/peripherals/uart/uart_echo/README.md` + +### Build, Flash, and Run + +Build the project and flash it to the board + +``` +idf.py -p build flash +``` + +Now you'll get an ot-rcp (for this example, there is no output in console). + +# OpenThread sniffer example (Linux or macOS based) + +## Overview + +This example is about how to run a sniffer to capture Thread packet, which refers to [openthread.io](https://openthread.io/guides/pyspinel/sniffer). +Openthread group just supports Linux and macOS. + +## How to use example + +### Hardware connection + +To run this example, you need an ESP32-H2 borad flashed with ot-rcp application. + +### Set up the sniffer environment + +The sniffer tool connects to an openthread RCP device and converts it into a promiscuous packet sniffer. RCP +will encode and send the packet to host after capturing a 15.4-type packet. On the host, Pyspinel should be run for +decoding the packet and generating a pcap (packet capture) stream to be saved or piped directly into Wireshark. + +Clone and install Pyspinel and dependencies, refer to [openthread.io](https://openthread.io/guides/pyspinel/sniffer#installation). + +### Install and config Wireshark + +For installing the Wireshark, refer to [Espressif Wireshark User Guide]( +https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wireshark-user-guide.html). + +You need to config Wireshark with some properties for the Thread network. +For Wireshark configuration, refer to [openthread.io](https://openthread.io/guides/pyspinel/sniffer#thread_network_properties). + +### Run the sniffer + +For example, to sniff on Channel 15 using a device mounted at /dev/ttyUSB0 with the baudrate 115200 in the Wireshark output: + +``` +cd ~/pyspinel +python sniffer.py -c 15 -u /dev/ttyUSB0 --crc -b 115200 | wireshark -k -i - +``` + diff --git a/examples/openthread/ot_rcp/main/CMakeLists.txt b/examples/openthread/ot_rcp/main/CMakeLists.txt new file mode 100644 index 0000000000..83b084e909 --- /dev/null +++ b/examples/openthread/ot_rcp/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "esp_ot_rcp.c" + INCLUDE_DIRS ".") diff --git a/examples/openthread/ot_rcp/main/esp_ot_config.h b/examples/openthread/ot_rcp/main/esp_ot_config.h new file mode 100644 index 0000000000..012f31d5ce --- /dev/null +++ b/examples/openthread/ot_rcp/main/esp_ot_config.h @@ -0,0 +1,48 @@ +// Copyright 2021 Espressif Systems (Shanghai) CO LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License + +#pragma once + +#include "esp_openthread_types.h" +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_NATIVE, \ + } + +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_RCP_UART, \ + .host_uart_config = { \ + .port = 0, \ + .uart_config = \ + { \ + .baud_rate = 92160, \ + .data_bits = UART_DATA_8_BITS, \ + .parity = UART_PARITY_DISABLE, \ + .stop_bits = UART_STOP_BITS_1, \ + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ + .rx_flow_ctrl_thresh = 0, \ + .source_clk = UART_SCLK_APB, \ + }, \ + .rx_pin = UART_PIN_NO_CHANGE, \ + .tx_pin = UART_PIN_NO_CHANGE, \ + }, \ + } + +#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ + { \ + .storage_partition_name = "ot_storage", \ + .netif_queue_size = 10, \ + .task_queue_size = 10, \ + } diff --git a/examples/openthread/ot_rcp/main/esp_ot_rcp.c b/examples/openthread/ot_rcp/main/esp_ot_rcp.c new file mode 100644 index 0000000000..433f630294 --- /dev/null +++ b/examples/openthread/ot_rcp/main/esp_ot_rcp.c @@ -0,0 +1,66 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "esp_event.h" +#include "esp_openthread.h" +#include "esp_ot_config.h" +#include "esp_vfs_eventfd.h" +#include "driver/uart.h" + +#if !CONFIG_IDF_TARGET_ESP32H2 +#error "RCP is only supported for esp32h2" +#endif + +#define TAG "ot_esp_rcp" + +extern void otAppNcpInit(otInstance *instance); + +static void ot_task_worker(void *aContext) +{ + esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + + // Initialize the OpenThread stack + ESP_ERROR_CHECK(esp_openthread_init(&config)); + + // Initialize the OpenThread ncp + otAppNcpInit(esp_openthread_get_instance()); + + // Run the main loop + esp_openthread_launch_mainloop(); + + // Clean up + esp_vfs_eventfd_unregister(); + vTaskDelete(NULL); +} + +void app_main(void) +{ + // Used eventfds: + // * ot task queue + // * radio driver + esp_vfs_eventfd_config_t eventfd_config = { + .max_fds = 2, + }; + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); + xTaskCreate(ot_task_worker, "ot_rcp_main", 10240, xTaskGetCurrentTaskHandle(), 5, NULL); +} diff --git a/examples/openthread/ot_rcp/partitions.csv b/examples/openthread/ot_rcp/partitions.csv new file mode 100644 index 0000000000..dad8b3ef5e --- /dev/null +++ b/examples/openthread/ot_rcp/partitions.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +ot_storage, data, 0x3a, , 0x2000, diff --git a/examples/openthread/ot_rcp/sdkconfig.defaults b/examples/openthread/ot_rcp/sdkconfig.defaults new file mode 100644 index 0000000000..fe3a8c762b --- /dev/null +++ b/examples/openthread/ot_rcp/sdkconfig.defaults @@ -0,0 +1,48 @@ +CONFIG_IDF_TARGET="esp32h2" +# +# libsodium +# +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y +# end of libsodium + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# mbedTLS +# + +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_ECJPAKE_C=y +# end of mbedTLS + +# +# OpenThread +# +CONFIG_OPENTHREAD_ENABLED=y +CONFIG_OPENTHREAD_RADIO=y +CONFIG_OPENTHREAD_DIAG=y +CONFIG_OPENTHREAD_COMMISSIONER=n +CONFIG_OPENTHREAD_JOINER=n +CONFIG_OPENTHREAD_BORDER_ROUTER=n +CONFIG_OPENTHREAD_ESP_LIB_FROM_INTERNAL_SRC=n +# end of OpenThread + + +# +# Deprecated options for backward compatibility +# +CONFIG_LOG_BOOTLOADER_LEVEL_ERROR=y +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=n +# End of deprecated options From 4a6cc1d2a4ad5948b6a2d987e508eea8c7a9f6f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Mon, 23 Aug 2021 09:27:46 +0200 Subject: [PATCH 039/310] vfs/fatfs: fix failed tests by increasing timeout Default 30s timeout is too low for a case when SD card formatting is triggered, which could lead to tests failure. Timeout of tests is now set to 60s. JIRA IDFCI-742 --- components/fatfs/test/test_fatfs_sdmmc.c | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/components/fatfs/test/test_fatfs_sdmmc.c b/components/fatfs/test/test_fatfs_sdmmc.c index d4d0e8b77c..8cfb446199 100644 --- a/components/fatfs/test/test_fatfs_sdmmc.c +++ b/components/fatfs/test/test_fatfs_sdmmc.c @@ -83,14 +83,14 @@ TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][sd][ignore]") HEAP_SIZE_CHECK(heap_size, 0); } -TEST_CASE("(SD) can create and write file", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can create and write file", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); test_teardown(); } -TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); @@ -98,7 +98,7 @@ TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE]") test_teardown(); } -TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); @@ -106,84 +106,84 @@ TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE]") test_teardown(); } -TEST_CASE("(SD) pwrite() works well", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) pwrite() works well", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_pwrite_file(test_filename); test_teardown(); } -TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_overwrite_append(test_filename); test_teardown(); } -TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_lseek("/sdcard/seek.txt"); test_teardown(); } -TEST_CASE("(SD) can truncate", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can truncate", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_truncate_file("/sdcard/truncate.txt"); test_teardown(); } -TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_stat("/sdcard/stat.txt", "/sdcard"); test_teardown(); } -TEST_CASE("(SD) utime sets modification time", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) utime sets modification time", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_utime("/sdcard/utime.txt", "/sdcard"); test_teardown(); } -TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_unlink("/sdcard/unlink.txt"); test_teardown(); } -TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_link_rename("/sdcard/link"); test_teardown(); } -TEST_CASE("(SD) can create and remove directories", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can create and remove directories", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_mkdir_rmdir("/sdcard/dir"); test_teardown(); } -TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_can_opendir("/sdcard"); test_teardown(); } -TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_opendir_readdir_rewinddir("/sdcard/dir"); test_teardown(); } -TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_concurrent("/sdcard/f"); @@ -232,7 +232,7 @@ static void sdmmc_speed_test(void *buf, size_t buf_size, size_t file_size, bool TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount()); } -TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = true, From 72ba1866fbd2f3eb91754c01d1f9aa23f69495cb Mon Sep 17 00:00:00 2001 From: Darian Date: Wed, 25 Aug 2021 19:57:10 +0800 Subject: [PATCH 040/310] twai: TWAI_ALERT_RX_DATA indicates that frames were received Signed-off-by: Darian Leung Closes https://github.com/espressif/esp-idf/pull/7386 Closes https://github.com/espressif/esp-idf/issues/7374 --- components/driver/include/driver/twai.h | 33 +++++++++++----------- components/driver/twai.c | 4 +-- docs/en/api-reference/peripherals/twai.rst | 2 ++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/components/driver/include/driver/twai.h b/components/driver/include/driver/twai.h index ce616fe125..70f88a4da1 100644 --- a/components/driver/include/driver/twai.h +++ b/components/driver/include/driver/twai.h @@ -47,23 +47,24 @@ extern "C" { */ #define TWAI_ALERT_TX_IDLE 0x00000001 /**< Alert(1): No more messages to transmit */ #define TWAI_ALERT_TX_SUCCESS 0x00000002 /**< Alert(2): The previous transmission was successful */ -#define TWAI_ALERT_BELOW_ERR_WARN 0x00000004 /**< Alert(4): Both error counters have dropped below error warning limit */ -#define TWAI_ALERT_ERR_ACTIVE 0x00000008 /**< Alert(8): TWAI controller has become error active */ -#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x00000010 /**< Alert(16): TWAI controller is undergoing bus recovery */ -#define TWAI_ALERT_BUS_RECOVERED 0x00000020 /**< Alert(32): TWAI controller has successfully completed bus recovery */ -#define TWAI_ALERT_ARB_LOST 0x00000040 /**< Alert(64): The previous transmission lost arbitration */ -#define TWAI_ALERT_ABOVE_ERR_WARN 0x00000080 /**< Alert(128): One of the error counters have exceeded the error warning limit */ -#define TWAI_ALERT_BUS_ERROR 0x00000100 /**< Alert(256): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */ -#define TWAI_ALERT_TX_FAILED 0x00000200 /**< Alert(512): The previous transmission has failed (for single shot transmission) */ -#define TWAI_ALERT_RX_QUEUE_FULL 0x00000400 /**< Alert(1024): The RX queue is full causing a frame to be lost */ -#define TWAI_ALERT_ERR_PASS 0x00000800 /**< Alert(2048): TWAI controller has become error passive */ -#define TWAI_ALERT_BUS_OFF 0x00001000 /**< Alert(4096): Bus-off condition occurred. TWAI controller can no longer influence bus */ -#define TWAI_ALERT_RX_FIFO_OVERRUN 0x00002000 /**< Alert(8192): An RX FIFO overrun has occurred */ -#define TWAI_ALERT_TX_RETRIED 0x00004000 /**< Alert(16384): An message transmission was cancelled and retried due to an errata workaround */ -#define TWAI_ALERT_PERIPH_RESET 0x00008000 /**< Alert(32768): The TWAI controller was reset */ -#define TWAI_ALERT_ALL 0x0000FFFF /**< Bit mask to enable all alerts during configuration */ +#define TWAI_ALERT_RX_DATA 0x00000004 /**< Alert(4): A frame has been received and added to the RX queue */ +#define TWAI_ALERT_BELOW_ERR_WARN 0x00000008 /**< Alert(8): Both error counters have dropped below error warning limit */ +#define TWAI_ALERT_ERR_ACTIVE 0x00000010 /**< Alert(16): TWAI controller has become error active */ +#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x00000020 /**< Alert(32): TWAI controller is undergoing bus recovery */ +#define TWAI_ALERT_BUS_RECOVERED 0x00000040 /**< Alert(64): TWAI controller has successfully completed bus recovery */ +#define TWAI_ALERT_ARB_LOST 0x00000080 /**< Alert(128): The previous transmission lost arbitration */ +#define TWAI_ALERT_ABOVE_ERR_WARN 0x00000100 /**< Alert(256): One of the error counters have exceeded the error warning limit */ +#define TWAI_ALERT_BUS_ERROR 0x00000200 /**< Alert(512): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */ +#define TWAI_ALERT_TX_FAILED 0x00000400 /**< Alert(1024): The previous transmission has failed (for single shot transmission) */ +#define TWAI_ALERT_RX_QUEUE_FULL 0x00000800 /**< Alert(2048): The RX queue is full causing a frame to be lost */ +#define TWAI_ALERT_ERR_PASS 0x00001000 /**< Alert(4096): TWAI controller has become error passive */ +#define TWAI_ALERT_BUS_OFF 0x00002000 /**< Alert(8192): Bus-off condition occurred. TWAI controller can no longer influence bus */ +#define TWAI_ALERT_RX_FIFO_OVERRUN 0x00004000 /**< Alert(16384): An RX FIFO overrun has occurred */ +#define TWAI_ALERT_TX_RETRIED 0x00008000 /**< Alert(32768): An message transmission was cancelled and retried due to an errata workaround */ +#define TWAI_ALERT_PERIPH_RESET 0x00010000 /**< Alert(65536): The TWAI controller was reset */ +#define TWAI_ALERT_ALL 0x0001FFFF /**< Bit mask to enable all alerts during configuration */ #define TWAI_ALERT_NONE 0x00000000 /**< Bit mask to disable all alerts during configuration */ -#define TWAI_ALERT_AND_LOG 0x00010000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */ +#define TWAI_ALERT_AND_LOG 0x00020000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */ /** @endcond */ diff --git a/components/driver/twai.c b/components/driver/twai.c index 08b8d048f0..17d34e9ccd 100644 --- a/components/driver/twai.c +++ b/components/driver/twai.c @@ -130,6 +130,7 @@ static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *ale //Valid frame copied from RX buffer if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) { p_twai_obj->rx_msg_count++; + twai_alert_handler(TWAI_ALERT_RX_DATA, alert_req); } else { //Failed to send to queue p_twai_obj->rx_missed_count++; twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req); @@ -149,6 +150,7 @@ static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *ale //Valid frame copied from RX buffer if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) { p_twai_obj->rx_msg_count++; + twai_alert_handler(TWAI_ALERT_RX_DATA, alert_req); } else { p_twai_obj->rx_missed_count++; twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req); @@ -391,8 +393,6 @@ cleanup: return NULL; } - - /* ---------------------------- Public Functions ---------------------------- */ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config) diff --git a/docs/en/api-reference/peripherals/twai.rst b/docs/en/api-reference/peripherals/twai.rst index 617cc06183..31aed19e2a 100644 --- a/docs/en/api-reference/peripherals/twai.rst +++ b/docs/en/api-reference/peripherals/twai.rst @@ -124,6 +124,8 @@ The TWAI driver contains an alert feature that is used to notify the application - No more messages queued for transmission * - ``TWAI_ALERT_TX_SUCCESS`` - The previous transmission was successful + * - ``TWAI_ALERT_RX_DATA`` + - A frame has been received and added to the RX queue * - ``TWAI_ALERT_BELOW_ERR_WARN`` - Both error counters have dropped below error warning limit * - ``TWAI_ALERT_ERR_ACTIVE`` From 5eee64bd16235d4c33003808b8557b16379b6045 Mon Sep 17 00:00:00 2001 From: muhaidong Date: Tue, 24 Aug 2021 16:05:38 +0800 Subject: [PATCH 041/310] esp_wifi: fix airkiss and esptouch find channel crash issue --- components/esp_wifi/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 492bb8b01b..045b526641 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 492bb8b01b6ccff1e830b52c7b15d8c3d90101c6 +Subproject commit 045b526641b7dbe7a6be3d9039be93a2c1b56f10 From c8b7f7a5d32a2b068fb2767eef1a4328a4f2281d Mon Sep 17 00:00:00 2001 From: Jon Maloney Date: Sat, 14 Aug 2021 21:02:02 +1000 Subject: [PATCH 042/310] esp_http_client: Support client key password for HTTPS connections. Closes https://github.com/espressif/esp-idf/pull/7420 Closes https://github.com/espressif/esp-idf/issues/7418 Signed-off-by: Aditya Patwardhan --- components/esp_http_client/esp_http_client.c | 4 ++++ components/esp_http_client/include/esp_http_client.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index d9c58c0c04..f5a05841f1 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -632,6 +632,10 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co } } + if (config->client_key_password && config->client_key_password_len > 0) { + esp_transport_ssl_set_client_key_password(ssl, config->client_key_password, config->client_key_password_len); + } + if (config->skip_cert_common_name_check) { esp_transport_ssl_skip_common_name_check(ssl); } diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index ab7e3c2e32..820c4168f6 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -113,6 +113,8 @@ typedef struct { size_t client_cert_len; /*!< Length of the buffer pointed to by client_cert_pem. May be 0 for null-terminated pem */ const char *client_key_pem; /*!< SSL client key, PEM format as string, if the server requires to verify client */ size_t client_key_len; /*!< Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem */ + const char *client_key_password; /*!< Client key decryption password string */ + size_t client_key_password_len; /*!< String length of the password pointed to by client_key_password */ const char *user_agent; /*!< The User Agent string to send with HTTP requests */ esp_http_client_method_t method; /*!< HTTP Method */ int timeout_ms; /*!< Network timeout in milliseconds */ From 376559d14cb4905255562814794e9fa119dfdb55 Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Thu, 19 Aug 2021 14:54:11 +0800 Subject: [PATCH 043/310] [cmake]: fixed FPGA setting during early build --- tools/cmake/idf.cmake | 7 +++++++ tools/cmake/targets.cmake | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/cmake/idf.cmake b/tools/cmake/idf.cmake index 547473f22b..ea096b96c1 100644 --- a/tools/cmake/idf.cmake +++ b/tools/cmake/idf.cmake @@ -49,5 +49,12 @@ if(NOT __idf_env_set) __build_init("${idf_path}") + # Check if IDF_ENV_FPGA environment is set + set(env_idf_env_fpga $ENV{IDF_ENV_FPGA}) + if(${env_idf_env_fpga}) + idf_build_set_property(__IDF_ENV_FPGA "y") + message(NOTICE "IDF_ENV_FPGA is set, building for FPGA environment") + endif() + set_property(GLOBAL PROPERTY __IDF_ENV_SET 1) endif() diff --git a/tools/cmake/targets.cmake b/tools/cmake/targets.cmake index 22df06abcd..ecaaaf1818 100644 --- a/tools/cmake/targets.cmake +++ b/tools/cmake/targets.cmake @@ -27,13 +27,6 @@ macro(__target_init) # Finally, set IDF_TARGET in cache set(IDF_TARGET ${env_idf_target} CACHE STRING "IDF Build Target") - - # Check if IDF_ENV_FPGA environment is set - set(env_idf_env_fpga $ENV{IDF_ENV_FPGA}) - if(${env_idf_env_fpga}) - idf_build_set_property(__IDF_ENV_FPGA "y") - message(NOTICE "IDF_ENV_FPGA is set, building for FPGA environment") - endif() endmacro() # From 11dfd802e04f97ea0029545ab325bc9aad6d5b97 Mon Sep 17 00:00:00 2001 From: sly Date: Wed, 7 Jul 2021 11:28:07 +0800 Subject: [PATCH 044/310] esp32h2: add rtc clock support --- components/esp_hw_support/clk_ctrl_os.c | 5 + .../esp32h2/private_include/regi2c_bbpll.h | 120 ++--- .../esp32h2/private_include/regi2c_bias.h | 106 ++++- .../esp32h2/private_include/regi2c_lp_bias.h | 119 +++-- .../port/esp32h2/private_include/regi2c_pmu.h | 280 ++++++++++++ .../port/esp32h2/private_include/regi2c_ulp.h | 108 +++++ .../esp_hw_support/port/esp32h2/rtc_clk.c | 411 ++++++++---------- .../port/esp32h2/rtc_clk_common.h | 1 + .../port/esp32h2/rtc_clk_init.c | 23 +- .../esp_hw_support/port/esp32h2/rtc_init.c | 121 +++++- .../esp_hw_support/port/esp32h2/rtc_pm.c | 2 +- .../esp_hw_support/port/esp32h2/rtc_sleep.c | 227 +++++++--- .../esp_hw_support/port/esp32h2/rtc_time.c | 27 +- components/esp_system/port/soc/esp32h2/clk.c | 14 +- components/esp_system/startup.c | 1 - components/esptool_py/Kconfig.projbuild | 1 - components/hal/esp32h2/brownout_hal.c | 3 +- components/soc/esp32h2/i2c_bbpll.h | 141 ++---- components/soc/esp32h2/i2c_bias.h | 112 +++++ components/soc/esp32h2/i2c_pmu.h | 280 ++++++++++++ components/soc/esp32h2/i2c_ulp.h | 108 +++++ components/soc/esp32h2/include/soc/rtc.h | 221 ++++++++-- components/soc/esp32h2/include/soc/soc_caps.h | 10 - 23 files changed, 1818 insertions(+), 623 deletions(-) create mode 100644 components/esp_hw_support/port/esp32h2/private_include/regi2c_pmu.h create mode 100644 components/esp_hw_support/port/esp32h2/private_include/regi2c_ulp.h create mode 100644 components/soc/esp32h2/i2c_bias.h create mode 100644 components/soc/esp32h2/i2c_pmu.h create mode 100644 components/soc/esp32h2/i2c_ulp.h diff --git a/components/esp_hw_support/clk_ctrl_os.c b/components/esp_hw_support/clk_ctrl_os.c index 9120c473d3..d3cc0d5248 100644 --- a/components/esp_hw_support/clk_ctrl_os.c +++ b/components/esp_hw_support/clk_ctrl_os.c @@ -6,6 +6,7 @@ #include #include "soc/clk_ctrl_os.h" +#include "sdkconfig.h" #define DELAY_RTC_CLK_SWITCH 5 @@ -19,7 +20,11 @@ bool periph_rtc_dig_clk8m_enable(void) portENTER_CRITICAL(&periph_spinlock); if (s_periph_ref_counts == 0) { rtc_dig_clk8m_enable(); +#if CONFIG_IDF_TARGET_ESP32H2 + s_rtc_clk_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_RC32K, 100)); +#else s_rtc_clk_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, 100)); +#endif if (s_rtc_clk_freq == 0) { portEXIT_CRITICAL(&periph_spinlock); return false; diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h index 8235741d58..56e31cd6b5 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h @@ -50,71 +50,39 @@ #define I2C_BBPLL_OC_REF_DIV_MSB 3 #define I2C_BBPLL_OC_REF_DIV_LSB 0 -#define I2C_BBPLL_OC_DCHGP 2 -#define I2C_BBPLL_OC_DCHGP_MSB 6 -#define I2C_BBPLL_OC_DCHGP_LSB 4 +#define I2C_BBPLL_OC_DIV 3 +#define I2C_BBPLL_OC_DIV_MSB 5 +#define I2C_BBPLL_OC_DIV_LSB 0 -#define I2C_BBPLL_OC_ENB_FCAL 2 +#define I2C_BBPLL_OC_CHGP_DCUR 4 +#define I2C_BBPLL_OC_CHGP_DCUR_MSB 2 +#define I2C_BBPLL_OC_CHGP_DCUR_LSB 0 + +#define I2C_BBPLL_OC_BUFF_DCUR 4 +#define I2C_BBPLL_OC_BUFF_DCUR_MSB 5 +#define I2C_BBPLL_OC_BUFF_DCUR_LSB 3 + +#define I2C_BBPLL_OC_TSCHGP 4 +#define I2C_BBPLL_OC_TSCHGP_MSB 6 +#define I2C_BBPLL_OC_TSCHGP_LSB 6 + +#define I2C_BBPLL_OC_ENB_FCAL 4 #define I2C_BBPLL_OC_ENB_FCAL_MSB 7 #define I2C_BBPLL_OC_ENB_FCAL_LSB 7 -#define I2C_BBPLL_OC_DIV_7_0 3 -#define I2C_BBPLL_OC_DIV_7_0_MSB 7 -#define I2C_BBPLL_OC_DIV_7_0_LSB 0 +#define I2C_BBPLL_OC_LPF_DR 5 +#define I2C_BBPLL_OC_LPF_DR_MSB 1 +#define I2C_BBPLL_OC_LPF_DR_LSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC 4 -#define I2C_BBPLL_RSTB_DIV_ADC_MSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC_LSB 0 +#define I2C_BBPLL_OC_VCO_DCUR 5 +#define I2C_BBPLL_OC_VCO_DCUR_MSB 3 +#define I2C_BBPLL_OC_VCO_DCUR_LSB 2 -#define I2C_BBPLL_MODE_HF 4 -#define I2C_BBPLL_MODE_HF_MSB 1 -#define I2C_BBPLL_MODE_HF_LSB 1 - -#define I2C_BBPLL_DIV_ADC 4 -#define I2C_BBPLL_DIV_ADC_MSB 3 -#define I2C_BBPLL_DIV_ADC_LSB 2 - -#define I2C_BBPLL_DIV_DAC 4 -#define I2C_BBPLL_DIV_DAC_MSB 4 -#define I2C_BBPLL_DIV_DAC_LSB 4 - -#define I2C_BBPLL_DIV_CPU 4 -#define I2C_BBPLL_DIV_CPU_MSB 5 -#define I2C_BBPLL_DIV_CPU_LSB 5 - -#define I2C_BBPLL_OC_ENB_VCON 4 -#define I2C_BBPLL_OC_ENB_VCON_MSB 6 -#define I2C_BBPLL_OC_ENB_VCON_LSB 6 - -#define I2C_BBPLL_OC_TSCHGP 4 -#define I2C_BBPLL_OC_TSCHGP_MSB 7 -#define I2C_BBPLL_OC_TSCHGP_LSB 7 - -#define I2C_BBPLL_OC_DR1 5 -#define I2C_BBPLL_OC_DR1_MSB 2 -#define I2C_BBPLL_OC_DR1_LSB 0 - -#define I2C_BBPLL_OC_DR3 5 -#define I2C_BBPLL_OC_DR3_MSB 6 -#define I2C_BBPLL_OC_DR3_LSB 4 - -#define I2C_BBPLL_EN_USB 5 -#define I2C_BBPLL_EN_USB_MSB 7 -#define I2C_BBPLL_EN_USB_LSB 7 - -#define I2C_BBPLL_OC_DCUR 6 -#define I2C_BBPLL_OC_DCUR_MSB 2 -#define I2C_BBPLL_OC_DCUR_LSB 0 - -#define I2C_BBPLL_INC_CUR 6 -#define I2C_BBPLL_INC_CUR_MSB 3 -#define I2C_BBPLL_INC_CUR_LSB 3 - -#define I2C_BBPLL_OC_DHREF_SEL 6 +#define I2C_BBPLL_OC_DHREF_SEL 5 #define I2C_BBPLL_OC_DHREF_SEL_MSB 5 #define I2C_BBPLL_OC_DHREF_SEL_LSB 4 -#define I2C_BBPLL_OC_DLREF_SEL 6 +#define I2C_BBPLL_OC_DLREF_SEL 5 #define I2C_BBPLL_OC_DLREF_SEL_MSB 7 #define I2C_BBPLL_OC_DLREF_SEL_LSB 6 @@ -138,38 +106,14 @@ #define I2C_BBPLL_OR_LOCK_MSB 7 #define I2C_BBPLL_OR_LOCK_LSB 7 -#define I2C_BBPLL_OC_VCO_DBIAS 9 -#define I2C_BBPLL_OC_VCO_DBIAS_MSB 1 -#define I2C_BBPLL_OC_VCO_DBIAS_LSB 0 - -#define I2C_BBPLL_BBADC_DELAY2 9 -#define I2C_BBPLL_BBADC_DELAY2_MSB 3 -#define I2C_BBPLL_BBADC_DELAY2_LSB 2 - -#define I2C_BBPLL_BBADC_DVDD 9 -#define I2C_BBPLL_BBADC_DVDD_MSB 5 -#define I2C_BBPLL_BBADC_DVDD_LSB 4 - -#define I2C_BBPLL_BBADC_DREF 9 -#define I2C_BBPLL_BBADC_DREF_MSB 7 -#define I2C_BBPLL_BBADC_DREF_LSB 6 - -#define I2C_BBPLL_BBADC_DCUR 10 -#define I2C_BBPLL_BBADC_DCUR_MSB 1 -#define I2C_BBPLL_BBADC_DCUR_LSB 0 - -#define I2C_BBPLL_BBADC_INPUT_SHORT 10 -#define I2C_BBPLL_BBADC_INPUT_SHORT_MSB 2 -#define I2C_BBPLL_BBADC_INPUT_SHORT_LSB 2 +#define I2C_BBPLL_DTEST 10 +#define I2C_BBPLL_DTEST_MSB 1 +#define I2C_BBPLL_DTEST_LSB 0 #define I2C_BBPLL_ENT_PLL 10 -#define I2C_BBPLL_ENT_PLL_MSB 3 -#define I2C_BBPLL_ENT_PLL_LSB 3 +#define I2C_BBPLL_ENT_PLL_MSB 2 +#define I2C_BBPLL_ENT_PLL_LSB 2 -#define I2C_BBPLL_DTEST 10 -#define I2C_BBPLL_DTEST_MSB 5 -#define I2C_BBPLL_DTEST_LSB 4 - -#define I2C_BBPLL_ENT_ADC 10 -#define I2C_BBPLL_ENT_ADC_MSB 7 -#define I2C_BBPLL_ENT_ADC_LSB 6 +#define I2C_BBPLL_DIV_CPU 10 +#define I2C_BBPLL_DIV_CPU_MSB 3 +#define I2C_BBPLL_DIV_CPU_LSB 3 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h index c1e540bf7a..2d6b73a45e 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h @@ -17,6 +17,106 @@ #define I2C_BIAS 0x6a #define I2C_BIAS_HOSTID 0 -#define I2C_BIAS_DREG_1P1_PVT 1 -#define I2C_BIAS_DREG_1P1_PVT_MSB 3 -#define I2C_BIAS_DREG_1P1_PVT_LSB 0 +#define I2C_BIAS_DREG_1P6 0 +#define I2C_BIAS_DREG_1P6_MSB 3 +#define I2C_BIAS_DREG_1P6_LSB 0 + +#define I2C_BIAS_DREG_0P8 0 +#define I2C_BIAS_DREG_0P8_MSB 7 +#define I2C_BIAS_DREG_0P8_LSB 4 + +#define I2C_BIAS_DREG_1P1_PVT 1 +#define I2C_BIAS_DREG_1P1_PVT_MSB 3 +#define I2C_BIAS_DREG_1P1_PVT_LSB 0 + +#define I2C_BIAS_DREG_1P2 1 +#define I2C_BIAS_DREG_1P2_MSB 7 +#define I2C_BIAS_DREG_1P2_LSB 4 + +#define I2C_BIAS_ENT_CPREG 2 +#define I2C_BIAS_ENT_CPREG_MSB 0 +#define I2C_BIAS_ENT_CPREG_LSB 0 + +#define I2C_BIAS_ENT_CGM 2 +#define I2C_BIAS_ENT_CGM_MSB 1 +#define I2C_BIAS_ENT_CGM_LSB 1 + +#define I2C_BIAS_CGM_BIAS 2 +#define I2C_BIAS_CGM_BIAS_MSB 3 +#define I2C_BIAS_CGM_BIAS_LSB 2 + +#define I2C_BIAS_DREF_IGM 2 +#define I2C_BIAS_DREF_IGM_MSB 4 +#define I2C_BIAS_DREF_IGM_LSB 4 + +#define I2C_BIAS_RC_DVREF 2 +#define I2C_BIAS_RC_DVREF_MSB 6 +#define I2C_BIAS_RC_DVREF_LSB 5 + +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP 2 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_MSB 7 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_LSB 7 + +#define I2C_BIAS_RC_ENX 3 +#define I2C_BIAS_RC_ENX_MSB 0 +#define I2C_BIAS_RC_ENX_LSB 0 + +#define I2C_BIAS_RC_START 3 +#define I2C_BIAS_RC_START_MSB 1 +#define I2C_BIAS_RC_START_LSB 1 + +#define I2C_BIAS_RC_DCAP_EXT 3 +#define I2C_BIAS_RC_DCAP_EXT_MSB 7 +#define I2C_BIAS_RC_DCAP_EXT_LSB 2 + +#define I2C_BIAS_XPD_RC 4 +#define I2C_BIAS_XPD_RC_MSB 0 +#define I2C_BIAS_XPD_RC_LSB 0 + +#define I2C_BIAS_ENT_CONSTI 4 +#define I2C_BIAS_ENT_CONSTI_MSB 1 +#define I2C_BIAS_ENT_CONSTI_LSB 1 + +#define I2C_BIAS_XPD_ICX 4 +#define I2C_BIAS_XPD_ICX_MSB 2 +#define I2C_BIAS_XPD_ICX_LSB 2 + +#define I2C_BIAS_RC_RSTB 4 +#define I2C_BIAS_RC_RSTB_MSB 3 +#define I2C_BIAS_RC_RSTB_LSB 3 + +#define I2C_BIAS_RC_DIV 4 +#define I2C_BIAS_RC_DIV_MSB 7 +#define I2C_BIAS_RC_DIV_LSB 4 + +#define I2C_BIAS_RC_CAP 5 +#define I2C_BIAS_RC_CAP_MSB 5 +#define I2C_BIAS_RC_CAP_LSB 0 + +#define I2C_BIAS_RC_UD 5 +#define I2C_BIAS_RC_UD_MSB 6 +#define I2C_BIAS_RC_UD_LSB 6 + +#define I2C_BIAS_RC_LOCKB 5 +#define I2C_BIAS_RC_LOCKB_MSB 7 +#define I2C_BIAS_RC_LOCKB_LSB 7 + +#define I2C_BIAS_RC_CHG_COUNT 6 +#define I2C_BIAS_RC_CHG_COUNT_MSB 4 +#define I2C_BIAS_RC_CHG_COUNT_LSB 0 + +#define I2C_BIAS_XPD_CPREG 7 +#define I2C_BIAS_XPD_CPREG_MSB 0 +#define I2C_BIAS_XPD_CPREG_LSB 0 + +#define I2C_BIAS_XPD_CGM 7 +#define I2C_BIAS_XPD_CGM_MSB 1 +#define I2C_BIAS_XPD_CGM_LSB 1 + +#define I2C_BIAS_DTEST 7 +#define I2C_BIAS_DTEST_MSB 3 +#define I2C_BIAS_DTEST_LSB 2 + +#define I2C_BIAS_DRES12K 7 +#define I2C_BIAS_DRES12K_MSB 7 +#define I2C_BIAS_DRES12K_LSB 4 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h index 6a8c996fd5..d10669d34a 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h @@ -17,41 +17,102 @@ #define I2C_ULP 0x61 #define I2C_ULP_HOSTID 0 -#define I2C_ULP 0x61 -#define I2C_ULP_HOSTID 0 +#define I2C_ULP_IR_RESETB 0 +#define I2C_ULP_IR_RESETB_MSB 0 +#define I2C_ULP_IR_RESETB_LSB 0 -#define I2C_ULP_IR_RESETB 0 -#define I2C_ULP_IR_RESETB_MSB 0 -#define I2C_ULP_IR_RESETB_LSB 0 +#define I2C_ULP_XPD_REG_SLP 0 +#define I2C_ULP_XPD_REG_SLP_MSB 1 +#define I2C_ULP_XPD_REG_SLP_LSB 1 -#define I2C_ULP_IR_FORCE_XPD_CK 0 -#define I2C_ULP_IR_FORCE_XPD_CK_MSB 2 -#define I2C_ULP_IR_FORCE_XPD_CK_LSB 2 +#define I2C_ULP_DBIAS_SLP 0 +#define I2C_ULP_DBIAS_SLP_MSB 7 +#define I2C_ULP_DBIAS_SLP_LSB 4 -#define I2C_ULP_IR_FORCE_XPD_IPH 0 -#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 4 -#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 4 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_MSB 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_LSB 1 -#define I2C_ULP_IR_DISABLE_WATCHDOG_CK 0 -#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_MSB 6 -#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_LSB 6 +#define I2C_ULP_IR_FORCE_XPD_IPH 1 +#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 2 +#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 2 -#define I2C_ULP_O_DONE_FLAG 3 -#define I2C_ULP_O_DONE_FLAG_MSB 0 -#define I2C_ULP_O_DONE_FLAG_LSB 0 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_MSB 3 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_LSB 3 -#define I2C_ULP_BG_O_DONE_FLAG 3 -#define I2C_ULP_BG_O_DONE_FLAG_MSB 3 -#define I2C_ULP_BG_O_DONE_FLAG_LSB 3 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP 1 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_MSB 4 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_LSB 4 -#define I2C_ULP_OCODE 4 -#define I2C_ULP_OCODE_MSB 7 -#define I2C_ULP_OCODE_LSB 0 +#define I2C_ULP_IR_ZOS_XPD 2 +#define I2C_ULP_IR_ZOS_XPD_MSB 0 +#define I2C_ULP_IR_ZOS_XPD_LSB 0 -#define I2C_ULP_IR_FORCE_CODE 5 -#define I2C_ULP_IR_FORCE_CODE_MSB 6 -#define I2C_ULP_IR_FORCE_CODE_LSB 6 +#define I2C_ULP_IR_ZOS_RSTB 2 +#define I2C_ULP_IR_ZOS_RSTB_MSB 1 +#define I2C_ULP_IR_ZOS_RSTB_LSB 1 -#define I2C_ULP_EXT_CODE 6 -#define I2C_ULP_EXT_CODE_MSB 7 -#define I2C_ULP_EXT_CODE_LSB 0 +#define I2C_ULP_IR_ZOS_RESTART 2 +#define I2C_ULP_IR_ZOS_RESTART_MSB 2 +#define I2C_ULP_IR_ZOS_RESTART_LSB 2 + +#define I2C_ULP_DTEST 3 +#define I2C_ULP_DTEST_MSB 1 +#define I2C_ULP_DTEST_LSB 0 + +#define I2C_ULP_ENT_BG 3 +#define I2C_ULP_ENT_BG_MSB 2 +#define I2C_ULP_ENT_BG_LSB 2 + +#define I2C_ULP_MODE_LVDET 3 +#define I2C_ULP_MODE_LVDET_MSB 3 +#define I2C_ULP_MODE_LVDET_LSB 3 + +#define I2C_ULP_DREF_LVDET 3 +#define I2C_ULP_DREF_LVDET_MSB 6 +#define I2C_ULP_DREF_LVDET_LSB 4 + +#define I2C_ULP_XPD_LVDET 3 +#define I2C_ULP_XPD_LVDET_MSB 7 +#define I2C_ULP_XPD_LVDET_LSB 7 + +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG 4 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_MSB 0 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_LSB 0 + +#define I2C_ULP_INT_XPD_XTAL_BUF 4 +#define I2C_ULP_INT_XPD_XTAL_BUF_MSB 1 +#define I2C_ULP_INT_XPD_XTAL_BUF_LSB 1 + +#define I2C_ULP_INT_XPD_RC_CK 4 +#define I2C_ULP_INT_XPD_RC_CK_MSB 2 +#define I2C_ULP_INT_XPD_RC_CK_LSB 2 + +#define I2C_ULP_XTAL_DPHASE 4 +#define I2C_ULP_XTAL_DPHASE_MSB 3 +#define I2C_ULP_XTAL_DPHASE_LSB 3 + +#define I2C_ULP_INT_XPD_XTAL_LIN_REG 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_MSB 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_LSB 4 + +#define I2C_ULP_XTAL_RESTART_DC_CAL 4 +#define I2C_ULP_XTAL_RESTART_DC_CAL_MSB 5 +#define I2C_ULP_XTAL_RESTART_DC_CAL_LSB 5 + +#define I2C_ULP_XTAL_DAC 5 +#define I2C_ULP_XTAL_DAC_MSB 3 +#define I2C_ULP_XTAL_DAC_LSB 0 + +#define I2C_ULP_XTAL_DBLEED 6 +#define I2C_ULP_XTAL_DBLEED_MSB 4 +#define I2C_ULP_XTAL_DBLEED_LSB 0 + +#define I2C_ULP_XTAL_CAL_DONE 6 +#define I2C_ULP_XTAL_CAL_DONE_MSB 5 +#define I2C_ULP_XTAL_CAL_DONE_LSB 5 + +#define I2C_ULP_ZOS_DONE 6 +#define I2C_ULP_ZOS_DONE_MSB 6 +#define I2C_ULP_ZOS_DONE_LSB 6 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_pmu.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_pmu.h new file mode 100644 index 0000000000..24ddd77826 --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_pmu.h @@ -0,0 +1,280 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_PMU 0x6d +#define I2C_PMU_HOSTID 0 + +#define I2C_PMU_THRES_HIGH_7_0 0 +#define I2C_PMU_THRES_HIGH_7_0_MSB 7 +#define I2C_PMU_THRES_HIGH_7_0_LSB 0 + +#define I2C_PMU_THRES_LOW_7_0 1 +#define I2C_PMU_THRES_LOW_7_0_MSB 7 +#define I2C_PMU_THRES_LOW_7_0_LSB 0 + +#define I2C_PMU_THRES_HIGH_11_8 2 +#define I2C_PMU_THRES_HIGH_11_8_MSB 3 +#define I2C_PMU_THRES_HIGH_11_8_LSB 0 + +#define I2C_PMU_THRES_LOW_11_8 2 +#define I2C_PMU_THRES_LOW_11_8_MSB 7 +#define I2C_PMU_THRES_LOW_11_8_LSB 4 + +#define I2C_PMU_PVT_DELAY_INIT 3 +#define I2C_PMU_PVT_DELAY_INIT_MSB 7 +#define I2C_PMU_PVT_DELAY_INIT_LSB 0 + +#define I2C_PMU_PVT_DELAY_COUNT 4 +#define I2C_PMU_PVT_DELAY_COUNT_MSB 5 +#define I2C_PMU_PVT_DELAY_COUNT_LSB 0 + +#define I2C_PMU_OR_EN_CONT_CAL 4 +#define I2C_PMU_OR_EN_CONT_CAL_MSB 7 +#define I2C_PMU_OR_EN_CONT_CAL_LSB 7 + +#define I2C_PMU_I2C_RTC_DREG 5 +#define I2C_PMU_I2C_RTC_DREG_MSB 4 +#define I2C_PMU_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG 6 +#define I2C_PMU_I2C_DIG_DREG_MSB 4 +#define I2C_PMU_I2C_DIG_DREG_LSB 0 + +#define I2C_PMU_I2C_RTC_DREG_SLP 7 +#define I2C_PMU_I2C_RTC_DREG_SLP_MSB 3 +#define I2C_PMU_I2C_RTC_DREG_SLP_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG_SLP 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_MSB 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_LSB 4 + +#define I2C_PMU_EN_I2C_RTC_DREG 10 +#define I2C_PMU_EN_I2C_RTC_DREG_MSB 0 +#define I2C_PMU_EN_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_EN_I2C_DIG_DREG 10 +#define I2C_PMU_EN_I2C_DIG_DREG_MSB 1 +#define I2C_PMU_EN_I2C_DIG_DREG_LSB 1 + +#define I2C_PMU_EN_I2C_RTC_DREG_SLP 10 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_MSB 2 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_LSB 2 + +#define I2C_PMU_EN_I2C_DIG_DREG_SLP 10 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_MSB 3 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_LSB 3 + +#define I2C_PMU_ENX_RTC_DREG 11 +#define I2C_PMU_ENX_RTC_DREG_MSB 0 +#define I2C_PMU_ENX_RTC_DREG_LSB 0 + +#define I2C_PMU_ENX_DIG_DREG 11 +#define I2C_PMU_ENX_DIG_DREG_MSB 1 +#define I2C_PMU_ENX_DIG_DREG_LSB 1 + +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3 11 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_MSB 2 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_LSB 2 + +#define I2C_PMU_OR_XPD_RTC_REG 11 +#define I2C_PMU_OR_XPD_RTC_REG_MSB 4 +#define I2C_PMU_OR_XPD_RTC_REG_LSB 4 + +#define I2C_PMU_OR_XPD_DIG_REG 11 +#define I2C_PMU_OR_XPD_DIG_REG_MSB 5 +#define I2C_PMU_OR_XPD_DIG_REG_LSB 5 + +#define I2C_PMU_OR_PD_RTC_REG_SLP 11 +#define I2C_PMU_OR_PD_RTC_REG_SLP_MSB 6 +#define I2C_PMU_OR_PD_RTC_REG_SLP_LSB 6 + +#define I2C_PMU_OR_PD_DIG_REG_SLP 11 +#define I2C_PMU_OR_PD_DIG_REG_SLP_MSB 7 +#define I2C_PMU_OR_PD_DIG_REG_SLP_LSB 7 + +#define I2C_PMU_INT_DREG 12 +#define I2C_PMU_INT_DREG_MSB 4 +#define I2C_PMU_INT_DREG_LSB 0 + +#define I2C_PMU_O_UDF 12 +#define I2C_PMU_O_UDF_MSB 5 +#define I2C_PMU_O_UDF_LSB 5 + +#define I2C_PMU_O_OVF 12 +#define I2C_PMU_O_OVF_MSB 6 +#define I2C_PMU_O_OVF_LSB 6 + +#define I2C_PMU_O_UPDATE 12 +#define I2C_PMU_O_UPDATE_MSB 7 +#define I2C_PMU_O_UPDATE_LSB 7 + +#define I2C_PMU_PVT_COUNT 13 +#define I2C_PMU_PVT_COUNT_MSB 7 +#define I2C_PMU_PVT_COUNT_LSB 0 + +#define I2C_PMU_PVT_COUNT 14 +#define I2C_PMU_PVT_COUNT_MSB 3 +#define I2C_PMU_PVT_COUNT_LSB 0 + +#define I2C_PMU_IC_VGOOD_LVDET 14 +#define I2C_PMU_IC_VGOOD_LVDET_MSB 4 +#define I2C_PMU_IC_VGOOD_LVDET_LSB 4 + +#define I2C_PMU_IC_POWER_GOOD_DCDC 14 +#define I2C_PMU_IC_POWER_GOOD_DCDC_MSB 5 +#define I2C_PMU_IC_POWER_GOOD_DCDC_LSB 5 + +#define I2C_PMU_IC_VGOOD_DIGDET 14 +#define I2C_PMU_IC_VGOOD_DIGDET_MSB 6 +#define I2C_PMU_IC_VGOOD_DIGDET_LSB 6 + +#define I2C_PMU_OR_XPD_DCDC 15 +#define I2C_PMU_OR_XPD_DCDC_MSB 0 +#define I2C_PMU_OR_XPD_DCDC_LSB 0 + +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_MSB 1 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_LSB 1 + +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_MSB 2 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_LSB 2 + +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC 15 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_MSB 3 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_LSB 3 + +#define I2C_PMU_OR_ENX_REG_DCDC 15 +#define I2C_PMU_OR_ENX_REG_DCDC_MSB 4 +#define I2C_PMU_OR_ENX_REG_DCDC_LSB 4 + +#define I2C_PMU_OR_UNLOCK_DCDC 15 +#define I2C_PMU_OR_UNLOCK_DCDC_MSB 5 +#define I2C_PMU_OR_UNLOCK_DCDC_LSB 5 + +#define I2C_PMU_OR_FORCE_LOCK_DCDC 15 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_MSB 6 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_LSB 6 + +#define I2C_PMU_OR_ENB_SLOW_CLK 15 +#define I2C_PMU_OR_ENB_SLOW_CLK_MSB 7 +#define I2C_PMU_OR_ENB_SLOW_CLK_LSB 7 + +#define I2C_PMU_OC_SCK_DCAP 16 +#define I2C_PMU_OC_SCK_DCAP_MSB 7 +#define I2C_PMU_OC_SCK_DCAP_LSB 0 + +#define I2C_PMU_OC_XPD_LVDET 17 +#define I2C_PMU_OC_XPD_LVDET_MSB 0 +#define I2C_PMU_OC_XPD_LVDET_LSB 0 + +#define I2C_PMU_OC_MODE_LVDET 17 +#define I2C_PMU_OC_MODE_LVDET_MSB 1 +#define I2C_PMU_OC_MODE_LVDET_LSB 1 + +#define I2C_PMU_OR_XPD_TRX 17 +#define I2C_PMU_OR_XPD_TRX_MSB 2 +#define I2C_PMU_OR_XPD_TRX_LSB 2 + +#define I2C_PMU_OR_EN_RESET_CHIP 17 +#define I2C_PMU_OR_EN_RESET_CHIP_MSB 3 +#define I2C_PMU_OR_EN_RESET_CHIP_LSB 3 + +#define I2C_PMU_OC_DREF_LVDET 17 +#define I2C_PMU_OC_DREF_LVDET_MSB 6 +#define I2C_PMU_OC_DREF_LVDET_LSB 4 + +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE 17 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_MSB 7 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_LSB 7 + +#define I2C_PMU_DTEST 18 +#define I2C_PMU_DTEST_MSB 1 +#define I2C_PMU_DTEST_LSB 0 + +#define I2C_PMU_ENT_BIAS 18 +#define I2C_PMU_ENT_BIAS_MSB 2 +#define I2C_PMU_ENT_BIAS_LSB 2 + +#define I2C_PMU_ENT_VDD 18 +#define I2C_PMU_ENT_VDD_MSB 5 +#define I2C_PMU_ENT_VDD_LSB 3 + +#define I2C_PMU_EN_DMUX 18 +#define I2C_PMU_EN_DMUX_MSB 6 +#define I2C_PMU_EN_DMUX_LSB 6 + +#define I2C_PMU_WD_DISABLE 18 +#define I2C_PMU_WD_DISABLE_MSB 7 +#define I2C_PMU_WD_DISABLE_LSB 7 + +#define I2C_PMU_DTEST_DCDC 19 +#define I2C_PMU_DTEST_DCDC_MSB 0 +#define I2C_PMU_DTEST_DCDC_LSB 0 + +#define I2C_PMU_TESTEN_DCDC 19 +#define I2C_PMU_TESTEN_DCDC_MSB 1 +#define I2C_PMU_TESTEN_DCDC_LSB 1 + +#define I2C_PMU_ADD_DCDC 19 +#define I2C_PMU_ADD_DCDC_MSB 6 +#define I2C_PMU_ADD_DCDC_LSB 4 + +#define I2C_PMU_OR_POCPENB_DCDC 20 +#define I2C_PMU_OR_POCPENB_DCDC_MSB 0 +#define I2C_PMU_OR_POCPENB_DCDC_LSB 0 + +#define I2C_PMU_OR_SSTIME_DCDC 20 +#define I2C_PMU_OR_SSTIME_DCDC_MSB 1 +#define I2C_PMU_OR_SSTIME_DCDC_LSB 1 + +#define I2C_PMU_OR_CCM_DCDC 20 +#define I2C_PMU_OR_CCM_DCDC_MSB 2 +#define I2C_PMU_OR_CCM_DCDC_LSB 2 + +#define I2C_PMU_OR_VSET_LOW_DCDC 20 +#define I2C_PMU_OR_VSET_LOW_DCDC_MSB 7 +#define I2C_PMU_OR_VSET_LOW_DCDC_LSB 3 + +#define I2C_PMU_OR_FSW_DCDC 21 +#define I2C_PMU_OR_FSW_DCDC_MSB 2 +#define I2C_PMU_OR_FSW_DCDC_LSB 0 + +#define I2C_PMU_OR_DCMLEVEL_DCDC 21 +#define I2C_PMU_OR_DCMLEVEL_DCDC_MSB 4 +#define I2C_PMU_OR_DCMLEVEL_DCDC_LSB 3 + +#define I2C_PMU_OR_DCM2ENB_DCDC 21 +#define I2C_PMU_OR_DCM2ENB_DCDC_MSB 5 +#define I2C_PMU_OR_DCM2ENB_DCDC_LSB 5 + +#define I2C_PMU_OR_RAMP_DCDC 21 +#define I2C_PMU_OR_RAMP_DCDC_MSB 6 +#define I2C_PMU_OR_RAMP_DCDC_LSB 6 + +#define I2C_PMU_OR_RAMPLEVEL_DCDC 21 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_MSB 7 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_LSB 7 + +#define I2C_PMU_OR_VSET_HIGH_DCDC 22 +#define I2C_PMU_OR_VSET_HIGH_DCDC_MSB 4 +#define I2C_PMU_OR_VSET_HIGH_DCDC_LSB 0 + +#define I2C_PMU_OC_DEL_SSEND 22 +#define I2C_PMU_OC_DEL_SSEND_MSB 7 +#define I2C_PMU_OC_DEL_SSEND_LSB 5 + +#define I2C_PMU_OC_XPD_DIGDET 23 +#define I2C_PMU_OC_XPD_DIGDET_MSB 0 +#define I2C_PMU_OC_XPD_DIGDET_LSB 0 + +#define I2C_PMU_OC_MODE_DIGDET 23 +#define I2C_PMU_OC_MODE_DIGDET_MSB 1 +#define I2C_PMU_OC_MODE_DIGDET_LSB 1 + +#define I2C_PMU_OC_DREF_DIGDET 23 +#define I2C_PMU_OC_DREF_DIGDET_MSB 6 +#define I2C_PMU_OC_DREF_DIGDET_LSB 4 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_ulp.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_ulp.h new file mode 100644 index 0000000000..5751f01936 --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_ulp.h @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_ULP 0x61 +#define I2C_ULP_HOSTID 0 + +#define I2C_ULP_IR_RESETB 0 +#define I2C_ULP_IR_RESETB_MSB 0 +#define I2C_ULP_IR_RESETB_LSB 0 + +#define I2C_ULP_XPD_REG_SLP 0 +#define I2C_ULP_XPD_REG_SLP_MSB 1 +#define I2C_ULP_XPD_REG_SLP_LSB 1 + +#define I2C_ULP_DBIAS_SLP 0 +#define I2C_ULP_DBIAS_SLP_MSB 7 +#define I2C_ULP_DBIAS_SLP_LSB 4 + +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_MSB 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_LSB 1 + +#define I2C_ULP_IR_FORCE_XPD_IPH 1 +#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 2 +#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 2 + +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_MSB 3 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_LSB 3 + +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP 1 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_MSB 4 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_LSB 4 + +#define I2C_ULP_IR_ZOS_XPD 2 +#define I2C_ULP_IR_ZOS_XPD_MSB 0 +#define I2C_ULP_IR_ZOS_XPD_LSB 0 + +#define I2C_ULP_IR_ZOS_RSTB 2 +#define I2C_ULP_IR_ZOS_RSTB_MSB 1 +#define I2C_ULP_IR_ZOS_RSTB_LSB 1 + +#define I2C_ULP_IR_ZOS_RESTART 2 +#define I2C_ULP_IR_ZOS_RESTART_MSB 2 +#define I2C_ULP_IR_ZOS_RESTART_LSB 2 + +#define I2C_ULP_DTEST 3 +#define I2C_ULP_DTEST_MSB 1 +#define I2C_ULP_DTEST_LSB 0 + +#define I2C_ULP_ENT_BG 3 +#define I2C_ULP_ENT_BG_MSB 2 +#define I2C_ULP_ENT_BG_LSB 2 + +#define I2C_ULP_MODE_LVDET 3 +#define I2C_ULP_MODE_LVDET_MSB 3 +#define I2C_ULP_MODE_LVDET_LSB 3 + +#define I2C_ULP_DREF_LVDET 3 +#define I2C_ULP_DREF_LVDET_MSB 6 +#define I2C_ULP_DREF_LVDET_LSB 4 + +#define I2C_ULP_XPD_LVDET 3 +#define I2C_ULP_XPD_LVDET_MSB 7 +#define I2C_ULP_XPD_LVDET_LSB 7 + +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG 4 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_MSB 0 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_LSB 0 + +#define I2C_ULP_INT_XPD_XTAL_BUF 4 +#define I2C_ULP_INT_XPD_XTAL_BUF_MSB 1 +#define I2C_ULP_INT_XPD_XTAL_BUF_LSB 1 + +#define I2C_ULP_INT_XPD_RC_CK 4 +#define I2C_ULP_INT_XPD_RC_CK_MSB 2 +#define I2C_ULP_INT_XPD_RC_CK_LSB 2 + +#define I2C_ULP_XTAL_DPHASE 4 +#define I2C_ULP_XTAL_DPHASE_MSB 3 +#define I2C_ULP_XTAL_DPHASE_LSB 3 + +#define I2C_ULP_INT_XPD_XTAL_LIN_REG 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_MSB 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_LSB 4 + +#define I2C_ULP_XTAL_RESTART_DC_CAL 4 +#define I2C_ULP_XTAL_RESTART_DC_CAL_MSB 5 +#define I2C_ULP_XTAL_RESTART_DC_CAL_LSB 5 + +#define I2C_ULP_XTAL_DAC 5 +#define I2C_ULP_XTAL_DAC_MSB 3 +#define I2C_ULP_XTAL_DAC_LSB 0 + +#define I2C_ULP_XTAL_DBLEED 6 +#define I2C_ULP_XTAL_DBLEED_MSB 4 +#define I2C_ULP_XTAL_DBLEED_LSB 0 + +#define I2C_ULP_XTAL_CAL_DONE 6 +#define I2C_ULP_XTAL_CAL_DONE_MSB 5 +#define I2C_ULP_XTAL_CAL_DONE_LSB 5 + +#define I2C_ULP_ZOS_DONE 6 +#define I2C_ULP_ZOS_DONE_MSB 6 +#define I2C_ULP_ZOS_DONE_LSB 6 diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index e78aa33c7e..550d84058a 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.c @@ -15,6 +15,7 @@ #include "esp32h2/rom/uart.h" #include "esp32h2/rom/gpio.h" #include "soc/rtc.h" +#include "i2c_bbpll.h" #include "soc/rtc_cntl_reg.h" #include "soc/efuse_reg.h" #include "soc/syscon_reg.h" @@ -26,14 +27,19 @@ static const char *TAG = "rtc_clk"; -#define RTC_PLL_FREQ_320M 320 -#define RTC_PLL_FREQ_480M 480 +#define RTC_PLL_FREQ_96M 96 +#define RTC_OSC_FREQ_RC8M 18 #define DELAY_RTC_CLK_SWITCH 5 +#define RTC_CNTL_ANA_CONF0_CAL_REG 0x6000e040 +#define RTC_CNTL_ANA_CONF0_CAL_START BIT(2) +#define RTC_CNTL_ANA_CONF0_CAL_STOP BIT(3) +#define RTC_CNTL_ANA_CONF0_CAL_DONE BIT(24) -// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. +// Current PLL frequency, in 96MHZ. Zero if PLL is not enabled. static int s_cur_pll_freq; -static void rtc_clk_cpu_freq_to_8m(void); +void rtc_clk_cpu_freq_to_8m(void); +static uint32_t rtc_clk_ahb_freq_set(uint32_t div); void rtc_clk_32k_enable_internal(x32k_config_t cfg) { @@ -47,6 +53,9 @@ void rtc_clk_32k_enable_internal(x32k_config_t cfg) void rtc_clk_32k_enable(bool enable) { if (enable) { + /* need to hangup gpio0 & 1 before enable xtal_32k */ + rtc_gpio_hangup(0); + rtc_gpio_hangup(1); x32k_config_t cfg = X32K_CONFIG_DEFAULT(); rtc_clk_32k_enable_internal(cfg); } else { @@ -55,16 +64,26 @@ void rtc_clk_32k_enable(bool enable) } } +void rtc_clk_rc32k_dfreq(uint32_t dfreq) +{ + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_DFREQ, dfreq); +} + +void rtc_clk_rc32k_enable(bool enable) +{ + rc32k_config_t cfg = RC32K_CONFIG_DEFAULT(); + rtc_clk_rc32k_dfreq(cfg.dfreq); + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_XPD, enable); +} + void rtc_clk_32k_enable_external(void) { - /* TODO ESP32-C3 IDF-2408: external 32k source may need different settings */ - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + rtc_clk_32k_enable(true); } void rtc_clk_32k_bootstrap(uint32_t cycle) { - /* No special bootstrapping needed for ESP32-C3, 'cycle' argument is to keep the signature + /* No special bootstrapping needed for ESP32-H2, 'cycle' argument is to keep the signature * same as for the ESP32. Just enable the XTAL here. */ (void) cycle; @@ -82,53 +101,11 @@ bool rtc_clk_32k_enabled(void) return !disabled; } -void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en) -{ - if (clk_8m_en) { - // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); // ESP32H2-TODO: IDF-3396 - /* no need to wait once enabled by software */ - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); - esp_rom_delay_us(DELAY_8M_ENABLE); - } else { - // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); - } - /* d256 should be independent configured with 8M - * Maybe we can split this function into 8m and dmd256 - */ - if (d256_en) { - // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); - } else { - // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); - } -} - -bool rtc_clk_8m_enabled(void) -{ - return false; - // return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; // ESP32H2-TODO: IDF-3396 -} - -bool rtc_clk_8md256_enabled(void) -{ - return false; - // return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; // ESP32H2-TODO: IDF-3396 -} - void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq) { REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); - - /* Why we need to connect this clock to digital? - * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? - */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, - (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0); - - /* The clk_8m_d256 will be closed when rtc_state in SLEEP, - so if the slow_clk is 8md256, clk_8m must be force power on - */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, (slow_freq == RTC_SLOW_FREQ_8MD256) ? 1 : 0); + rtc_clk_32k_enable((slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0); + rtc_clk_rc32k_enable((slow_freq == RTC_SLOW_FREQ_RC32K) ? 1 : 0); esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); } @@ -142,7 +119,7 @@ uint32_t rtc_clk_slow_freq_get_hz(void) switch (rtc_clk_slow_freq_get()) { case RTC_SLOW_FREQ_RTC: return RTC_SLOW_CLK_FREQ_150K; case RTC_SLOW_FREQ_32K_XTAL: return RTC_SLOW_CLK_FREQ_32K; - case RTC_SLOW_FREQ_8MD256: return RTC_SLOW_CLK_FREQ_8MD256; + case RTC_SLOW_FREQ_RC32K: return RTC_SLOW_CLK_FREQ_RC32; } return 0; } @@ -170,100 +147,32 @@ static void rtc_clk_bbpll_enable(void) CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); } +static void rtc_clk_bbpll_cali_stop(void) +{ + while (!REG_GET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_DONE)); + REG_CLR_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_STOP); + REG_SET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_START); + +} void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) { uint8_t div_ref; - uint8_t div7_0; - uint8_t dr1; - uint8_t dr3; - uint8_t dchgp; - uint8_t dcur; - uint8_t dbias; - - CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); - SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); - if (pll_freq == RTC_PLL_FREQ_480M) { - /* Set this register to let the digital part know 480M PLL is used */ - // SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396 - /* Configure 480M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 26; - dr1 = 1; - dr3 = 1; - dchgp = 4; - dcur = 0; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); + uint8_t div5_0; + if ((pll_freq == RTC_PLL_FREQ_96M) && (xtal_freq == RTC_XTAL_FREQ_32M)) { + /* Configure 96M PLL */ + div_ref = 0; + div5_0 = 1; } else { - /* Clear this register to let the digital part know 320M PLL is used */ - // CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396 - /* Configure 320M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 6; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); + div_ref = 0; + div5_0 = 1; + SOC_LOGE(TAG, "invalid pll frequency"); } - uint8_t i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref); - uint8_t i2c_bbpll_div_7_0 = div7_0; - uint8_t i2c_bbpll_dcur = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 2); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, div_ref); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DIV, div5_0); //I2C_BBPLL_OC_DIV_5_0 + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 3); // need update to 3 since s2 + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); s_cur_pll_freq = pll_freq; } @@ -274,19 +183,21 @@ void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { - // int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) { - /* nothing to do */ - } else if (cpu_freq_mhz == 160) { - // per_conf = DPORT_CPUPERIOD_SEL_160; + int div = 1; + if (RTC_PLL_FREQ_96M % cpu_freq_mhz == 0) { + div = RTC_PLL_FREQ_96M / cpu_freq_mhz; } else { SOC_LOGE(TAG, "invalid frequency"); abort(); } - // REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); // ESP32H2-TODO: IDF-3396 - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); - rtc_clk_apb_freq_update(80 * MHZ); + rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_PLL, div - 1); + if (cpu_freq_mhz > RTC_XTAL_FREQ_32M) { + rtc_clk_ahb_freq_set(2); + } else { + rtc_clk_ahb_freq_set(1); + } + + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); ets_update_cpu_frequency(cpu_freq_mhz); } @@ -295,62 +206,32 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou uint32_t source_freq_mhz; rtc_cpu_freq_src_t source; uint32_t divider; - uint32_t real_freq_mhz; - uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get(); - if (freq_mhz <= xtal_freq) { - divider = xtal_freq / freq_mhz; - real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */ - if (real_freq_mhz != freq_mhz) { - // no suitable divider - return false; - } - - source_freq_mhz = xtal_freq; - source = RTC_CPU_FREQ_SRC_XTAL; - } else if (freq_mhz == 80) { - real_freq_mhz = freq_mhz; + if (freq_mhz > xtal_freq) { source = RTC_CPU_FREQ_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; - divider = 6; - } else if (freq_mhz == 160) { - real_freq_mhz = freq_mhz; - source = RTC_CPU_FREQ_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; - divider = 3; + source_freq_mhz = RTC_PLL_FREQ_96M; + divider = RTC_PLL_FREQ_96M / freq_mhz; + rtc_clk_ahb_freq_set(2); } else { - // unsupported frequency - return false; + source = root_clk_get(); + source_freq_mhz = root_clk_slt(source); + divider = source_freq_mhz / freq_mhz; + rtc_clk_ahb_freq_set(1); } *out_config = (rtc_cpu_freq_config_t) { .source = source, .div = divider, .source_freq_mhz = source_freq_mhz, - .freq_mhz = real_freq_mhz + .freq_mhz = freq_mhz }; return true; } void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); - if (config->source == RTC_CPU_FREQ_SRC_XTAL) { - rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - rtc_clk_bbpll_disable(); - } - } else if (config->source == RTC_CPU_FREQ_SRC_PLL) { - if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) { - rtc_clk_bbpll_enable(); - rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); - } - rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); - } else if (config->source == RTC_CPU_FREQ_SRC_8M) { - rtc_clk_cpu_freq_to_8m(); - if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - rtc_clk_bbpll_disable(); - } - } + uint32_t src_freq_mhz = root_clk_slt(config->source); + uint32_t div = src_freq_mhz / (config->freq_mhz); + rtc_clk_cpu_freq_set(config->source, div); } void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) @@ -363,29 +244,37 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) switch (soc_clk_sel) { case DPORT_SOC_CLK_SEL_XTAL: { source = RTC_CPU_FREQ_SRC_XTAL; - div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; + break; } - break; case DPORT_SOC_CLK_SEL_PLL: { - // ESP32H2-TODO: IDF-3396 - source = 0; - div = 0; - source_freq_mhz = 0; - freq_mhz = 0; + source = RTC_CPU_FREQ_SRC_PLL; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + source_freq_mhz = RTC_PLL_FREQ_96M; + freq_mhz = source_freq_mhz / div; break; } - case DPORT_SOC_CLK_SEL_8M: + case DPORT_SOC_CLK_SEL_8M: { source = RTC_CPU_FREQ_SRC_8M; - source_freq_mhz = 8; - div = 1; - freq_mhz = source_freq_mhz; + source_freq_mhz = RTC_OSC_FREQ_RC8M; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + freq_mhz = source_freq_mhz / div; break; - default: + } + case DPORT_SOC_CLK_SEL_XTAL_D2: { + source = RTC_CPU_FREQ_SRC_XTAL_D2; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + freq_mhz = source_freq_mhz / div / 2; + break; + } + default: { SOC_LOGE(TAG, "unsupported frequency configuration"); abort(); } + } *out_config = (rtc_cpu_freq_config_t) { .source = source, .source_freq_mhz = source_freq_mhz, @@ -410,7 +299,6 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { int freq_mhz = (int) rtc_clk_xtal_freq_get(); - rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); rtc_clk_bbpll_disable(); } @@ -422,20 +310,17 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1); + rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_XTAL, div); /* no need to adjust the REF_TICK */ /* switch clock source */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); - rtc_clk_apb_freq_update(freq * MHZ); + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); } -static void rtc_clk_cpu_freq_to_8m(void) +void rtc_clk_cpu_freq_to_8m(void) { - ets_update_cpu_frequency(8); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M); - rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M); + ets_update_cpu_frequency(RTC_OSC_FREQ_RC8M); + root_clk_slt(DPORT_SOC_CLK_SEL_8M); + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) @@ -443,7 +328,7 @@ rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); if (!clk_val_is_valid(xtal_freq_reg)) { SOC_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg); - return RTC_XTAL_FREQ_40M; + return RTC_XTAL_FREQ_32M; } return reg_val_to_clk_val(xtal_freq_reg); } @@ -458,41 +343,121 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq) WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12)); } + uint32_t rtc_clk_apb_freq_get(void) { - uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12; - // round to the nearest MHz - freq_hz += MHZ / 2; - uint32_t remainder = freq_hz % MHZ; - return freq_hz - remainder; + uint32_t apb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM) + 1; + return rtc_clk_ahb_freq_get() / apb_div; +} + +uint32_t rtc_clk_ahb_freq_get() +{ + rtc_cpu_freq_config_t cpu_config; + uint32_t ahb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM) + 1; + rtc_clk_cpu_freq_get_config(&cpu_config) ; + return cpu_config.freq_mhz / ahb_div; +} + +uint32_t rtc_clk_ahb_freq_set(uint32_t div) +{ + REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM, div - 1); + return rtc_clk_ahb_freq_get(); +} + +uint32_t rtc_clk_apb_freq_set(uint32_t div) +{ + REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM, div - 1); + return rtc_clk_apb_freq_get(); +} + +void rtc_clk_cpu_freq_set(uint32_t source, uint32_t div) +{ + if (root_clk_get() != source) { + root_clk_slt(source); + } + REG_SET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_CPU_DIV_NUM, div - 1); } void rtc_clk_divider_set(uint32_t div) { CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); - REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div); + REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div - 1); SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); } void rtc_clk_8m_divider_set(uint32_t div) { CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div - 1); SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); } +uint32_t read_spll_freq(void) +{ + return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SPLL_FREQ); +} + +uint32_t read_xtal_freq(void) +{ + return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_CLK_XTAL_FREQ); +} + +/* Select clock root source for esp32h2. return source clk freq_mhz + */ +uint32_t root_clk_slt(uint32_t source) +{ + uint32_t root_clk_freq_mhz; + switch (source) { + case RTC_CPU_FREQ_SRC_XTAL: + root_clk_freq_mhz = RTC_XTAL_FREQ_32M; + rtc_clk_bbpll_disable(); + break; + case RTC_CPU_FREQ_SRC_PLL: + // SPLL_ENABLE + root_clk_freq_mhz = RTC_PLL_FREQ_96M; + rtc_clk_bbpll_enable(); + rtc_clk_bbpll_configure(RTC_XTAL_FREQ_32M, root_clk_freq_mhz); + rtc_clk_bbpll_cali_stop(); + break; + case RTC_CPU_FREQ_SRC_8M: + root_clk_freq_mhz = RTC_OSC_FREQ_RC8M; + rtc_dig_clk8m_enable(); + rtc_clk_8m_divider_set(1); + rtc_clk_bbpll_disable(); + break; + case RTC_CPU_FREQ_SRC_XTAL_D2: + root_clk_freq_mhz = RTC_XTAL_FREQ_32M / 2; + rtc_clk_bbpll_disable(); + break; + default: + SOC_LOGE(TAG, "unsupported source clk configuration"); + root_clk_freq_mhz = RTC_XTAL_FREQ_32M; + rtc_clk_bbpll_disable(); + source = 0; + break; + } + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, source); + return root_clk_freq_mhz; +} + +uint32_t root_clk_get() +{ + uint32_t src_slt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + return src_slt; +} + /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk_common.h b/components/esp_hw_support/port/esp32h2/rtc_clk_common.h index 07f8c1243c..76e3fd3208 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_common.h +++ b/components/esp_hw_support/port/esp32h2/rtc_clk_common.h @@ -14,6 +14,7 @@ #define DPORT_SOC_CLK_SEL_XTAL 0 #define DPORT_SOC_CLK_SEL_PLL 1 #define DPORT_SOC_CLK_SEL_8M 2 +#define DPORT_SOC_CLK_SEL_XTAL_D2 3 #define RTC_FAST_CLK_FREQ_8M 8500000 diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c index c3fabe521d..b19ea4aa2d 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c @@ -8,11 +8,14 @@ #include #include #include +#include "sdkconfig.h" #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/uart.h" +#include "esp32h2/rom/gpio.h" #include "soc/rtc.h" #include "soc/rtc_periph.h" +#include "soc/rtc_cntl_reg.h" #include "soc/efuse_periph.h" #include "soc/apb_ctrl_reg.h" #include "hal/cpu_hal.h" @@ -21,7 +24,11 @@ #include "sdkconfig.h" #include "rtc_clk_common.h" #include "esp_rom_uart.h" - +#include "soc/efuse_reg.h" +#include "soc/syscon_reg.h" +#include "soc/system_reg.h" +#include "rtc_clk_common.h" +#include "esp_rom_sys.h" static const char *TAG = "rtc_clk_init"; void rtc_clk_init(rtc_clk_config_t cfg) @@ -39,24 +46,25 @@ void rtc_clk_init(rtc_clk_config_t cfg) REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, cfg.slow_clk_dcap); REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq); + /* enable modem clk */ + REG_WRITE(SYSTEM_MODEM_CLK_EN_REG, UINT32_MAX); + /* Configure 150k clock division */ rtc_clk_divider_set(cfg.clk_rtc_clk_div); /* Configure 8M clock division */ rtc_clk_8m_divider_set(cfg.clk_8m_clk_div); - /* Enable the internal bus used to configure PLLs */ - SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_APLL_M | ANA_I2C_BBPLL_M); - rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_uart_tx_wait_idle(0); rtc_clk_xtal_freq_update(xtal_freq); - rtc_clk_apb_freq_update(xtal_freq * MHZ); + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get() * MHZ); /* Set CPU frequency */ rtc_clk_cpu_freq_get_config(&old_config); uint32_t freq_before = old_config.freq_mhz; + + root_clk_slt(cfg.root_clk_slt); bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config); if (!res) { SOC_LOGE(TAG, "invalid CPU frequency value"); @@ -72,8 +80,7 @@ void rtc_clk_init(rtc_clk_config_t cfg) rtc_clk_32k_enable(true); } if (cfg.fast_freq == RTC_FAST_FREQ_8M) { - bool need_8md256 = cfg.slow_freq == RTC_SLOW_FREQ_8MD256; - rtc_clk_8m_enable(true, need_8md256); + rtc_dig_clk8m_enable(); } rtc_clk_fast_freq_set(cfg.fast_freq); rtc_clk_slow_freq_set(cfg.slow_freq); diff --git a/components/esp_hw_support/port/esp32h2/rtc_init.c b/components/esp_hw_support/port/esp32h2/rtc_init.c index 6e3b85f640..7b684d3d3d 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_init.c @@ -9,23 +9,26 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "soc/io_mux_reg.h" #include "soc/efuse_periph.h" #include "soc/gpio_reg.h" #include "soc/spi_mem_reg.h" #include "soc/extmem_reg.h" #include "soc/system_reg.h" +#include "soc/syscon_reg.h" #include "regi2c_ctrl.h" #include "soc_log.h" #include "esp_efuse.h" #include "esp_efuse_table.h" +#include "i2c_pmu.h" +#include "soc/clkrst_reg.h" -// ESP32H2-TODO: IDF-3396 +void pmu_ctl(void); +void dcdc_ctl(uint32_t mode); +void regulator_slt(regulator_config_t regula_cfg); void rtc_init(rtc_config_t cfg) { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); - CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait); @@ -44,8 +47,6 @@ void rtc_init(rtc_config_t cfg) REG_SET_FIELD(RTC_CNTL_TIMER6_REG, RTC_CNTL_DG_PERI_POWERUP_TIMER, rtc_init_cfg.dg_peri_powerup_cycles); REG_SET_FIELD(RTC_CNTL_TIMER6_REG, RTC_CNTL_DG_PERI_WAIT_TIMER, rtc_init_cfg.dg_peri_wait_cycles); - // set_rtc_dig_dbias(); // ESP32H2-TODO: IDF-3396 - if (cfg.clkctl_init) { //clear CMMU clock force on CLEAR_PERI_REG_MASK(EXTMEM_CACHE_MMU_POWER_CTRL_REG, EXTMEM_CACHE_MMU_MEM_FORCE_ON); @@ -69,10 +70,6 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); - //open sar_i2c protect function to avoid sar_i2c reset when rtc_ldo is low. - CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_I2C_RESET_POR_FORCE_PD); - - //cancel bbpll force pu if setting no force power up if (!cfg.bbpll_fpu) { CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_I2C_FORCE_PU); @@ -86,14 +83,8 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PU); - if (cfg.rtc_dboost_fpd) { - SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD); - } else { - CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD); - } - - //clear i2c_reset_protect pd force, need tested in low temperature. - //CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,RTC_CNTL_I2C_RESET_POR_FORCE_PD); + // clear i2c_reset_protect pd force, need tested in low temperature. + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,RTC_CNTL_I2C_RESET_POR_FORCE_PD); /* If this mask is enabled, all soc memories cannot enter power down mode */ /* We should control soc memory power down mode from RTC, so we will not touch this register any more */ @@ -104,18 +95,25 @@ void rtc_init(rtc_config_t cfg) rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(0); rtc_sleep_pu(pu_cfg); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PU); + //cancel digital PADS force pu CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU); // CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_MEM_FORCE_PU); // + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU); // + //cancel digital PADS force no iso CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_WRAP_FORCE_NOISO); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CPU_TOP_FORCE_NOISO); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PERI_FORCE_NOISO); - //cancel digital PADS force no iso + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); // + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_MEM_FORCE_NOISO); // + if (cfg.cpu_waiti_clk_gate) { CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON); } else { @@ -125,10 +123,49 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } + REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); + if (cfg.pmu_ctl) { + /* pmu init*/ + pmu_ctl(); + } + /* config dcdc frequency */ + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL0_REG, RTC_CNTL_FSW_DCDC, RTC_CNTL_DCDC_FREQ_DEFAULT); } +void pmu_ctl(void) +{ + pmu_config_t pmu_cfg = PMU_CONFIG_DEFAULT(); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_EN_CONT_CAL, pmu_cfg.or_en_cont_cal); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_ENX_RTC_DREG, pmu_cfg.enx_rtc_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_ENX_DIG_DREG, pmu_cfg.enx_dig_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, pmu_cfg.en_i2c_rtc_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, pmu_cfg.en_i2c_dig_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG_SLP, pmu_cfg.en_i2c_rtc_dreg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG_SLP, pmu_cfg.en_i2c_dig_dreg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_SLAVE_3P3, pmu_cfg.or_xpd_rtc_slave_3p3); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_REG, pmu_cfg.or_xpd_rtc_reg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_DIG_REG, pmu_cfg.or_xpd_dig_reg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_PD_RTC_REG_SLP, pmu_cfg.or_pd_rtc_reg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_PD_DIG_REG_SLP, pmu_cfg.or_pd_dig_reg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_DCDC, pmu_cfg.or_xpd_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC, pmu_cfg.or_disalbe_deep_sleep_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC, pmu_cfg.or_disalbe_light_sleep_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_ENALBE_TRX_MODE_DCDC, pmu_cfg.or_enalbe_trx_mode_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_ENX_REG_DCDC, pmu_cfg.or_enx_reg_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_UNLOCK_DCDC, pmu_cfg.or_unlock_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_FORCE_LOCK_DCDC, pmu_cfg.or_force_lock_dcdc); + // REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_ENB_SLOW_CLK, pmu_cfg.or_enb_slow_clk); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_TRX, pmu_cfg.or_xpd_trx); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_EN_RESET_CHIP, pmu_cfg.or_en_reset_chip); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_FORCE_XPD_REG_SLAVE, pmu_cfg.or_force_xpd_reg_slave); +} + +void dslp_osc_pd(void){ + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG,RTC_CNTL_RC32K_XPD, 0); + REG_SET_FIELD(RTC_CNTL_PLL8M_REG, RTC_CNTL_XPD_PLL8M, 0); +} rtc_vddsdio_config_t rtc_vddsdio_get_config(void) { rtc_vddsdio_config_t result; @@ -166,3 +203,41 @@ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) val |= RTC_CNTL_SDIO_PD_EN; REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val); } + +void dig_gpio_setpd(uint32_t gpio_no, bool pd) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, pd, FUN_PD_S); +} + +void dig_gpio_setpu(uint32_t gpio_no, bool pu) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, pu, FUN_PU_S); +} + +void dig_gpio_in_en(uint32_t gpio_no, bool enable) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, enable, FUN_IE_S); +} + +void dig_gpio_out_en(uint32_t gpio_no, bool enable) +{ + if (enable) + SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, 1 << gpio_no); + else + SET_PERI_REG_MASK(GPIO_ENABLE_W1TC_REG, 1 << gpio_no); +} + +void dig_gpio_mcusel(uint32_t gpio_no, uint32_t mcu_sel) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, MCU_SEL, mcu_sel, MCU_SEL_S); +} + + +void rtc_gpio_hangup(uint32_t gpio_no) +{ + dig_gpio_setpd(gpio_no, 0); + dig_gpio_setpu(gpio_no, 0); + dig_gpio_out_en(gpio_no, 0); + dig_gpio_in_en(gpio_no, 0); + dig_gpio_mcusel(gpio_no, 1); +} diff --git a/components/esp_hw_support/port/esp32h2/rtc_pm.c b/components/esp_hw_support/port/esp32h2/rtc_pm.c index c73ae9edf3..28283bc4c4 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_pm.c +++ b/components/esp_hw_support/port/esp32h2/rtc_pm.c @@ -44,7 +44,7 @@ pm_sw_reject_t pm_set_sleep_mode(pm_sleep_mode_t sleep_mode, void(*pmac_save_par switch (sleep_mode) { case PM_LIGHT_SLEEP: - cfg.wifi_pd_en = 1; + // cfg.wifi_pd_en = 1; // ESP32-H2 TO-DO: IDF-3693 cfg.dig_dbias_wak = 4; cfg.dig_dbias_slp = 0; cfg.rtc_dbias_wak = 0; diff --git a/components/esp_hw_support/port/esp32h2/rtc_sleep.c b/components/esp_hw_support/port/esp32h2/rtc_sleep.c index 4ef41d5725..0b6bd454a2 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32h2/rtc_sleep.c @@ -10,23 +10,26 @@ #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" #include "soc/apb_ctrl_reg.h" -#include "soc/rtc.h" #include "soc/i2s_reg.h" #include "soc/bb_reg.h" #include "soc/nrx_reg.h" #include "soc/fe_reg.h" #include "soc/timer_group_reg.h" #include "soc/system_reg.h" -#include "soc/rtc.h" #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/rtc.h" #include "regi2c_ctrl.h" #include "esp_efuse.h" +#include "i2c_pmu.h" +#include "soc_log.h" +#include "esp_rom_uart.h" /** * Configure whether certain peripherals are powered down in deep sleep * @param cfg power down flags as rtc_sleep_pu_config_t structure */ +static const char *TAG = "rtc_sleep"; + void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) { REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu); @@ -53,17 +56,111 @@ void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) } } +void dcdc_ctl(uint32_t mode) +{ + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_IDLE, RTC_CNTL_DCDC_TRX_MODE); + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_MONITOR, RTC_CNTL_DCDC_TRX_MODE); + if ((mode & 0x10) == 0x10) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, mode); + } else if (mode == 0) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_TRX_MODE); + } else if (mode == 1) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_LSLP_MODE); + } else if (mode == 2) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_DSLP_MODE); + } else { + SOC_LOGE(TAG, "invalid dcdc mode!\n"); + } +} + +void regulator_set(regulator_cfg_t cfg) +{ + // DIG REGULATOR0 + if (cfg.dig_regul0_en) { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PD, 0); + } else { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PD, 1); + } + // DIG REGULATOR1 + if (cfg.dig_regul1_en) { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PD, 0); + } else { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PD, 1); + } + // RTC REGULATOR0 + if (cfg.rtc_regul0_en) { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PD, 0); + } else { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PD, 1); + } +} + +void regulator_slt(regulator_config_t regula_cfg) +{ + // dig regulator + if (regula_cfg.dig_source == 1) { + REG_SET_FIELD(RTC_CNTL_DIGULATOR1_DBIAS_REG, RTC_CNTL_DIG_REGULATOR1_DBIAS_SLP, regula_cfg.dig_slp_dbias); + REG_SET_FIELD(RTC_CNTL_DIGULATOR1_DBIAS_REG, RTC_CNTL_DIG_REGULATOR1_DBIAS_ACTIVE, regula_cfg.dig_active_dbias); + } else { + REG_SET_FIELD(RTC_CNTL_DIGULATOR0_DBIAS_REG, RTC_CNTL_DIG_REGULATOR0_DBIAS_SLP, regula_cfg.dig_slp_dbias); + REG_SET_FIELD(RTC_CNTL_DIGULATOR0_DBIAS_REG, RTC_CNTL_DIG_REGULATOR0_DBIAS_ACTIVE, regula_cfg.dig_active_dbias); + } + // rtc regulator + if (regula_cfg.rtc_source == 1) { + REG_SET_FIELD(RTC_CNTL_RTCULATOR1_DBIAS_REG, RTC_CNTL_REGULATOR1_DBIAS_SLP, regula_cfg.rtc_slp_dbias); + REG_SET_FIELD(RTC_CNTL_RTCULATOR1_DBIAS_REG, RTC_CNTL_REGULATOR1_DBIAS_ACTIVE, regula_cfg.rtc_active_dbias); + } else { + REG_SET_FIELD(RTC_CNTL_RTCULATOR0_DBIAS_REG, RTC_CNTL_REGULATOR0_DBIAS_SLP, regula_cfg.rtc_slp_dbias); + REG_SET_FIELD(RTC_CNTL_RTCULATOR0_DBIAS_REG, RTC_CNTL_REGULATOR0_DBIAS_ACTIVE, regula_cfg.rtc_active_dbias); + } +} + +void dbias_switch_set(dbias_swt_cfg_t cfg) +{ + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_IDLE, cfg.swt_idle); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_MONITOR, cfg.swt_monitor); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_SLP, cfg.swt_slp); +} + +void left_up_trx_fpu(bool fpu) +{ + if (fpu) { + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP, 0); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_BIAS_BUF, 0); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 0); + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_XPD_TRX_FORCE_PU); + } else { + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_XPD_TRX_FORCE_PU); + } +} + +void rtc_sleep_pmu_init(void) +{ + dcdc_ctl(DCDC_SLP_DSLP_MODE); + dbias_swt_cfg_t swt_cfg = DBIAS_SWITCH_CONFIG_DEFAULT(); + dbias_switch_set(swt_cfg); + regulator_config_t regula0_cfg = REGULATOR0_CONFIG_DEFAULT(); + regulator_slt(regula0_cfg); + regulator_config_t regula1_cfg = REGULATOR1_CONFIG_DEFAULT(); + regulator_slt(regula1_cfg); + regulator_cfg_t rg_set = REGULATOR_SET_DEFAULT(); + regulator_set(rg_set); + left_up_trx_fpu(0); +} + + void rtc_sleep_init(rtc_sleep_config_t cfg) { if (cfg.lslp_mem_inf_fpu) { rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1); rtc_sleep_pu(pu_cfg); } - if (cfg.wifi_pd_en) { - SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); - } else { - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); - } if (cfg.bt_pd_en) { SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN); } else { @@ -79,44 +176,43 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) } else { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN); } + if (cfg.dig_ret_pd_en) { + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_RET_PD_EN); + } else { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_RET_PD_EN); + } - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, RTC_CNTL_BIASSLP_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, RTC_CNTL_BIASSLP_SLEEP_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, RTC_CNTL_PD_CUR_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, RTC_CNTL_PD_CUR_SLEEP_DEFAULT); // ESP32-H2 TO-DO: IDF-3693 if (cfg.deep_slp) { - REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0); - CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); - unsigned atten_deep_sleep = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT; - - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, atten_deep_sleep); + // REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0); + // CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN); CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU | RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU); } else { - SET_PERI_REG_MASK(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP_EN); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT); - SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); + SET_PERI_REG_MASK(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_VDD_DRV_B_SLP_EN); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT); + // SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT); } /* enable VDDSDIO control by state machine */ REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE); REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, cfg.rtc_dbias_slp); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG_SLEEP, cfg.dig_dbias_slp); - REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); /* gating XTAL clock */ REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING); + esp_rom_uart_tx_wait_idle(0); + } void rtc_sleep_low_init(uint32_t slowclk_period) @@ -142,7 +238,6 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp /* Start entry into sleep mode */ SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN); - while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) { ; @@ -173,56 +268,56 @@ uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) const unsigned CRC_LEN = 0x7ff; asm volatile( - /* Start CRC calculation */ - "sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN - "or t0, %1, %2\n" - "sw t0, 0(%0)\n" // set RTC_MEM_CRC_START + /* Start CRC calculation */ + "sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN + "or t0, %1, %2\n" + "sw t0, 0(%0)\n" // set RTC_MEM_CRC_START - /* Wait for the CRC calculation to finish */ - ".Lwaitcrc:\n" - "fence\n" - "lw t0, 0(%0)\n" - "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n" - "and t0, t0, t1\n" - "beqz t0, .Lwaitcrc\n" - "not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START - "and t0, t0, %2\n" - "sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START - "fence\n" - "not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged + /* Wait for the CRC calculation to finish */ + ".Lwaitcrc:\n" + "fence\n" + "lw t0, 0(%0)\n" + "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n" + "and t0, t0, t1\n" + "beqz t0, .Lwaitcrc\n" + "not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START + "and t0, t0, %2\n" + "sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START + "fence\n" + "not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged - /* Store the calculated value in RTC_MEM_CRC_REG */ - "lw t0, 0(%3)\n" - "sw t0, 0(%4)\n" - "fence\n" + /* Store the calculated value in RTC_MEM_CRC_REG */ + "lw t0, 0(%3)\n" + "sw t0, 0(%4)\n" + "fence\n" - /* Set register bit to go into deep sleep */ - "lw t0, 0(%5)\n" - "or t0, t0, %6\n" - "sw t0, 0(%5)\n" - "fence\n" + /* Set register bit to go into deep sleep */ + "lw t0, 0(%5)\n" + "or t0, t0, %6\n" + "sw t0, 0(%5)\n" + "fence\n" - /* Wait for sleep reject interrupt (never finishes if successful) */ - ".Lwaitsleep:" - "fence\n" - "lw t0, 0(%7)\n" - "and t0, t0, %8\n" - "beqz t0, .Lwaitsleep\n" + /* Wait for sleep reject interrupt (never finishes if successful) */ + ".Lwaitsleep:" + "fence\n" + "lw t0, 0(%7)\n" + "and t0, t0, %8\n" + "beqz t0, .Lwaitsleep\n" - : - : - "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0 - "r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S) - | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1 - "r" (SYSTEM_RTC_MEM_CRC_START), // %2 - "r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3 - "r" (RTC_MEMORY_CRC_REG), // %4 - "r" (RTC_CNTL_STATE0_REG), // %5 - "r" (RTC_CNTL_SLEEP_EN), // %6 - "r" (RTC_CNTL_INT_RAW_REG), // %7 - "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8 - : "t0", "t1" // working registers - ); + : + : + "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0 + "r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S) + | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1 + "r" (SYSTEM_RTC_MEM_CRC_START), // %2 + "r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3 + "r" (RTC_MEMORY_CRC_REG), // %4 + "r" (RTC_CNTL_STATE0_REG), // %5 + "r" (RTC_CNTL_SLEEP_EN), // %6 + "r" (RTC_CNTL_INT_RAW_REG), // %7 + "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8 + : "t0", "t1" // working registers + ); return rtc_sleep_finish(0); } diff --git a/components/esp_hw_support/port/esp32h2/rtc_time.c b/components/esp_hw_support/port/esp32h2/rtc_time.c index 8e8f1bf4cd..3efad7ce3d 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_time.c +++ b/components/esp_hw_support/port/esp32h2/rtc_time.c @@ -40,18 +40,19 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) rtc_slow_freq_t slow_freq = rtc_clk_slow_freq_get(); if (slow_freq == RTC_SLOW_FREQ_32K_XTAL) { cal_clk = RTC_CAL_32K_XTAL; - } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { - cal_clk = RTC_CAL_8MD256; + } else if (slow_freq == RTC_SLOW_FREQ_RC32K) { + cal_clk = RTC_CAL_RC32K; } } /* Enable requested clock (150k clock is always on) */ - int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); + bool dig_32k_xtal_state = REG_GET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); - } - if (cal_clk == RTC_CAL_8MD256) { - // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); // ESP32H2-TODO: IDF-3396 + } + bool dig_rc32k_state = REG_GET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN); + if (cal_clk == RTC_CAL_RC32K && !dig_rc32k_state) { + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN, 1); } /* Prepare calibration */ REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk); @@ -72,9 +73,9 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) if (cal_clk == RTC_CAL_32K_XTAL) { REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles)); expected_freq = RTC_SLOW_CLK_FREQ_32K; - } else if (cal_clk == RTC_CAL_8MD256) { - REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles)); - expected_freq = RTC_SLOW_CLK_FREQ_8MD256; + } else if (cal_clk == RTC_CAL_RC32K) { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_RC32K_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = RTC_SLOW_CLK_FREQ_RC32; } else { REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles)); expected_freq = RTC_SLOW_CLK_FREQ_150K; @@ -85,7 +86,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); /* Wait for calibration to finish up to another us_time_estimate */ - esp_rom_delay_us(us_time_estimate); + esp_rom_delay_us(us_time_estimate * 3); uint32_t cal_val; while (true) { if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) { @@ -98,12 +99,8 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } } CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); - - if (cal_clk == RTC_CAL_8MD256) { - // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); // ESP32H2-TODO: IDF-3396 - } + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN, dig_rc32k_state); return cal_val; } diff --git a/components/esp_system/port/soc/esp32h2/clk.c b/components/esp_system/port/soc/esp32h2/clk.c index 81cdd5e1d7..52cb9e9c44 100644 --- a/components/esp_system/port/soc/esp32h2/clk.c +++ b/components/esp_system/port/soc/esp32h2/clk.c @@ -23,6 +23,7 @@ #include "esp_clk_internal.h" #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/uart.h" +#include "esp32h2/rom/rtc.h" #include "soc/system_reg.h" #include "soc/dport_access.h" #include "soc/soc.h" @@ -35,7 +36,6 @@ #include "bootloader_clock.h" #include "soc/syscon_reg.h" #include "esp_rom_uart.h" -#include "esp_rom_sys.h" /* Number of cycles to wait from the 32k XTAL oscillator to consider it running. * Larger values increase startup delay. Smaller values may cause false positive @@ -62,7 +62,7 @@ typedef enum { SLOW_CLK_RTC = RTC_SLOW_FREQ_RTC, //!< Internal 150 kHz RC oscillator SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, //!< External 32 kHz XTAL - SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256, //!< Internal 8 MHz RC oscillator, divided by 256 + SLOW_CLK_RC32K = RTC_SLOW_FREQ_RC32K, //!< Internal 32 KHz RC oscillator SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin } slow_clk_sel_t; @@ -73,7 +73,6 @@ static const char *TAG = "clk"; __attribute__((weak)) void esp_clk_init(void) { -#if !CONFIG_IDF_ENV_FPGA rtc_config_t cfg = RTC_CONFIG_DEFAULT(); soc_reset_reason_t rst_reas; rst_reas = esp_rom_get_reset_reason(0); @@ -85,7 +84,6 @@ static const char *TAG = "clk"; assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_32M); rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M); -#endif #ifdef CONFIG_BOOTLOADER_WDT_ENABLE // WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed. @@ -176,8 +174,7 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk) rtc_slow_freq = RTC_SLOW_FREQ_RTC; } } - } else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) { - // rtc_clk_8m_enable(true, true); + } rtc_clk_slow_freq_set(rtc_slow_freq); @@ -211,7 +208,8 @@ __attribute__((weak)) void esp_perip_clk_init(void) uint32_t common_perip_clk, hwcrypto_perip_clk = 0; uint32_t common_perip_clk1 = 0; -soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); + soc_reset_reason_t rst_reas[1]; + rst_reas[0] = esp_rom_get_reset_reason(0); /* For reason that only reset CPU, do not disable the clocks * that have been enabled before reset. @@ -219,7 +217,7 @@ soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); /* For reason that only reset CPU, do not disable the clocks * that have been enabled before reset. */ -if (rst_reason >= RESET_REASON_CPU0_MWDT0 && rst_reason <= RESET_REASON_CPU0_RTC_WDT && rst_reason != RESET_REASON_SYS_BROWN_OUT) { + if ((rst_reas[0] >= RESET_REASON_CPU0_MWDT0 && rst_reas[0] <= RESET_REASON_CPU0_RTC_WDT && rst_reas[0] != RESET_REASON_SYS_BROWN_OUT)) { common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG); hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG); } else { diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index ebe31b73cf..8afc43087f 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -268,7 +268,6 @@ static void do_core_init(void) CONFIG_ESP32S3_BROWNOUT_DET || \ CONFIG_ESP32C3_BROWNOUT_DET || \ CONFIG_ESP32H2_BROWNOUT_DET - // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) -> // malloc (newlib) -> heap_caps_malloc (heap), so heap must be at least initialized esp_brownout_init(); diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index 0b18e9e011..9c765aaac5 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -56,7 +56,6 @@ menu "Serial flasher config" config ESPTOOLPY_NO_STUB bool "Disable download stub" - default "y" if IDF_TARGET_ESP32H2 # ESP32H2-TODO: IDF-3378 default "n" help The flasher tool sends a precompiled download stub first by default. That stub allows things diff --git a/components/hal/esp32h2/brownout_hal.c b/components/hal/esp32h2/brownout_hal.c index 5dac36f067..f60410b490 100644 --- a/components/hal/esp32h2/brownout_hal.c +++ b/components/hal/esp32h2/brownout_hal.c @@ -17,12 +17,13 @@ #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" #include "regi2c_ctrl.h" +#include "i2c_pmu.h" #include "regi2c_brownout.h" void brownout_hal_config(const brownout_hal_config_t *cfg) { - REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD, cfg->threshold); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OC_DREF_LVDET, cfg->threshold); typeof(RTCCNTL.brown_out) brown_out_reg = { .close_flash_ena = cfg->flash_power_down, .pd_rf_ena = cfg->rf_power_down, diff --git a/components/soc/esp32h2/i2c_bbpll.h b/components/soc/esp32h2/i2c_bbpll.h index c9d4753f49..2efd12168b 100644 --- a/components/soc/esp32h2/i2c_bbpll.h +++ b/components/soc/esp32h2/i2c_bbpll.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -24,7 +16,8 @@ */ #define I2C_BBPLL 0x66 -#define I2C_BBPLL_HOSTID 1 +#define I2C_BBPLL_HOSTID 0 + #define I2C_BBPLL_IR_CAL_DELAY 0 #define I2C_BBPLL_IR_CAL_DELAY_MSB 3 @@ -58,71 +51,39 @@ #define I2C_BBPLL_OC_REF_DIV_MSB 3 #define I2C_BBPLL_OC_REF_DIV_LSB 0 -#define I2C_BBPLL_OC_DCHGP 2 -#define I2C_BBPLL_OC_DCHGP_MSB 6 -#define I2C_BBPLL_OC_DCHGP_LSB 4 +#define I2C_BBPLL_OC_DIV 3 +#define I2C_BBPLL_OC_DIV_MSB 5 +#define I2C_BBPLL_OC_DIV_LSB 0 -#define I2C_BBPLL_OC_ENB_FCAL 2 +#define I2C_BBPLL_OC_CHGP_DCUR 4 +#define I2C_BBPLL_OC_CHGP_DCUR_MSB 2 +#define I2C_BBPLL_OC_CHGP_DCUR_LSB 0 + +#define I2C_BBPLL_OC_BUFF_DCUR 4 +#define I2C_BBPLL_OC_BUFF_DCUR_MSB 5 +#define I2C_BBPLL_OC_BUFF_DCUR_LSB 3 + +#define I2C_BBPLL_OC_TSCHGP 4 +#define I2C_BBPLL_OC_TSCHGP_MSB 6 +#define I2C_BBPLL_OC_TSCHGP_LSB 6 + +#define I2C_BBPLL_OC_ENB_FCAL 4 #define I2C_BBPLL_OC_ENB_FCAL_MSB 7 #define I2C_BBPLL_OC_ENB_FCAL_LSB 7 -#define I2C_BBPLL_OC_DIV_7_0 3 -#define I2C_BBPLL_OC_DIV_7_0_MSB 7 -#define I2C_BBPLL_OC_DIV_7_0_LSB 0 +#define I2C_BBPLL_OC_LPF_DR 5 +#define I2C_BBPLL_OC_LPF_DR_MSB 1 +#define I2C_BBPLL_OC_LPF_DR_LSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC 4 -#define I2C_BBPLL_RSTB_DIV_ADC_MSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC_LSB 0 +#define I2C_BBPLL_OC_VCO_DCUR 5 +#define I2C_BBPLL_OC_VCO_DCUR_MSB 3 +#define I2C_BBPLL_OC_VCO_DCUR_LSB 2 -#define I2C_BBPLL_MODE_HF 4 -#define I2C_BBPLL_MODE_HF_MSB 1 -#define I2C_BBPLL_MODE_HF_LSB 1 - -#define I2C_BBPLL_DIV_ADC 4 -#define I2C_BBPLL_DIV_ADC_MSB 3 -#define I2C_BBPLL_DIV_ADC_LSB 2 - -#define I2C_BBPLL_DIV_DAC 4 -#define I2C_BBPLL_DIV_DAC_MSB 4 -#define I2C_BBPLL_DIV_DAC_LSB 4 - -#define I2C_BBPLL_DIV_CPU 4 -#define I2C_BBPLL_DIV_CPU_MSB 5 -#define I2C_BBPLL_DIV_CPU_LSB 5 - -#define I2C_BBPLL_OC_ENB_VCON 4 -#define I2C_BBPLL_OC_ENB_VCON_MSB 6 -#define I2C_BBPLL_OC_ENB_VCON_LSB 6 - -#define I2C_BBPLL_OC_TSCHGP 4 -#define I2C_BBPLL_OC_TSCHGP_MSB 7 -#define I2C_BBPLL_OC_TSCHGP_LSB 7 - -#define I2C_BBPLL_OC_DR1 5 -#define I2C_BBPLL_OC_DR1_MSB 2 -#define I2C_BBPLL_OC_DR1_LSB 0 - -#define I2C_BBPLL_OC_DR3 5 -#define I2C_BBPLL_OC_DR3_MSB 6 -#define I2C_BBPLL_OC_DR3_LSB 4 - -#define I2C_BBPLL_EN_USB 5 -#define I2C_BBPLL_EN_USB_MSB 7 -#define I2C_BBPLL_EN_USB_LSB 7 - -#define I2C_BBPLL_OC_DCUR 6 -#define I2C_BBPLL_OC_DCUR_MSB 2 -#define I2C_BBPLL_OC_DCUR_LSB 0 - -#define I2C_BBPLL_INC_CUR 6 -#define I2C_BBPLL_INC_CUR_MSB 3 -#define I2C_BBPLL_INC_CUR_LSB 3 - -#define I2C_BBPLL_OC_DHREF_SEL 6 +#define I2C_BBPLL_OC_DHREF_SEL 5 #define I2C_BBPLL_OC_DHREF_SEL_MSB 5 #define I2C_BBPLL_OC_DHREF_SEL_LSB 4 -#define I2C_BBPLL_OC_DLREF_SEL 6 +#define I2C_BBPLL_OC_DLREF_SEL 5 #define I2C_BBPLL_OC_DLREF_SEL_MSB 7 #define I2C_BBPLL_OC_DLREF_SEL_LSB 6 @@ -146,38 +107,14 @@ #define I2C_BBPLL_OR_LOCK_MSB 7 #define I2C_BBPLL_OR_LOCK_LSB 7 -#define I2C_BBPLL_BBADC_DELAY1 9 -#define I2C_BBPLL_BBADC_DELAY1_MSB 1 -#define I2C_BBPLL_BBADC_DELAY1_LSB 0 - -#define I2C_BBPLL_BBADC_DELAY2 9 -#define I2C_BBPLL_BBADC_DELAY2_MSB 3 -#define I2C_BBPLL_BBADC_DELAY2_LSB 2 - -#define I2C_BBPLL_BBADC_DVDD 9 -#define I2C_BBPLL_BBADC_DVDD_MSB 5 -#define I2C_BBPLL_BBADC_DVDD_LSB 4 - -#define I2C_BBPLL_BBADC_DREF 9 -#define I2C_BBPLL_BBADC_DREF_MSB 7 -#define I2C_BBPLL_BBADC_DREF_LSB 6 - -#define I2C_BBPLL_BBADC_DCUR 10 -#define I2C_BBPLL_BBADC_DCUR_MSB 1 -#define I2C_BBPLL_BBADC_DCUR_LSB 0 - -#define I2C_BBPLL_BBADC_INPUT_SHORT 10 -#define I2C_BBPLL_BBADC_INPUT_SHORT_MSB 2 -#define I2C_BBPLL_BBADC_INPUT_SHORT_LSB 2 +#define I2C_BBPLL_DTEST 10 +#define I2C_BBPLL_DTEST_MSB 1 +#define I2C_BBPLL_DTEST_LSB 0 #define I2C_BBPLL_ENT_PLL 10 -#define I2C_BBPLL_ENT_PLL_MSB 3 -#define I2C_BBPLL_ENT_PLL_LSB 3 +#define I2C_BBPLL_ENT_PLL_MSB 2 +#define I2C_BBPLL_ENT_PLL_LSB 2 -#define I2C_BBPLL_DTEST 10 -#define I2C_BBPLL_DTEST_MSB 5 -#define I2C_BBPLL_DTEST_LSB 4 - -#define I2C_BBPLL_ENT_ADC 10 -#define I2C_BBPLL_ENT_ADC_MSB 7 -#define I2C_BBPLL_ENT_ADC_LSB 6 +#define I2C_BBPLL_DIV_CPU 10 +#define I2C_BBPLL_DIV_CPU_MSB 3 +#define I2C_BBPLL_DIV_CPU_LSB 3 diff --git a/components/soc/esp32h2/i2c_bias.h b/components/soc/esp32h2/i2c_bias.h new file mode 100644 index 0000000000..a7ea588270 --- /dev/null +++ b/components/soc/esp32h2/i2c_bias.h @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_BIAS 0x6a +#define I2C_BIAS_HOSTID 0 + +#define I2C_BIAS_DREG_1P6 0 +#define I2C_BIAS_DREG_1P6_MSB 3 +#define I2C_BIAS_DREG_1P6_LSB 0 + +#define I2C_BIAS_DREG_0P8 0 +#define I2C_BIAS_DREG_0P8_MSB 7 +#define I2C_BIAS_DREG_0P8_LSB 4 + +#define I2C_BIAS_DREG_1P1_PVT 1 +#define I2C_BIAS_DREG_1P1_PVT_MSB 3 +#define I2C_BIAS_DREG_1P1_PVT_LSB 0 + +#define I2C_BIAS_DREG_1P2 1 +#define I2C_BIAS_DREG_1P2_MSB 7 +#define I2C_BIAS_DREG_1P2_LSB 4 + +#define I2C_BIAS_ENT_CPREG 2 +#define I2C_BIAS_ENT_CPREG_MSB 0 +#define I2C_BIAS_ENT_CPREG_LSB 0 + +#define I2C_BIAS_ENT_CGM 2 +#define I2C_BIAS_ENT_CGM_MSB 1 +#define I2C_BIAS_ENT_CGM_LSB 1 + +#define I2C_BIAS_CGM_BIAS 2 +#define I2C_BIAS_CGM_BIAS_MSB 3 +#define I2C_BIAS_CGM_BIAS_LSB 2 + +#define I2C_BIAS_DREF_IGM 2 +#define I2C_BIAS_DREF_IGM_MSB 4 +#define I2C_BIAS_DREF_IGM_LSB 4 + +#define I2C_BIAS_RC_DVREF 2 +#define I2C_BIAS_RC_DVREF_MSB 6 +#define I2C_BIAS_RC_DVREF_LSB 5 + +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP 2 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_MSB 7 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_LSB 7 + +#define I2C_BIAS_RC_ENX 3 +#define I2C_BIAS_RC_ENX_MSB 0 +#define I2C_BIAS_RC_ENX_LSB 0 + +#define I2C_BIAS_RC_START 3 +#define I2C_BIAS_RC_START_MSB 1 +#define I2C_BIAS_RC_START_LSB 1 + +#define I2C_BIAS_RC_DCAP_EXT 3 +#define I2C_BIAS_RC_DCAP_EXT_MSB 7 +#define I2C_BIAS_RC_DCAP_EXT_LSB 2 + +#define I2C_BIAS_XPD_RC 4 +#define I2C_BIAS_XPD_RC_MSB 0 +#define I2C_BIAS_XPD_RC_LSB 0 + +#define I2C_BIAS_ENT_CONSTI 4 +#define I2C_BIAS_ENT_CONSTI_MSB 1 +#define I2C_BIAS_ENT_CONSTI_LSB 1 + +#define I2C_BIAS_XPD_ICX 4 +#define I2C_BIAS_XPD_ICX_MSB 2 +#define I2C_BIAS_XPD_ICX_LSB 2 + +#define I2C_BIAS_RC_RSTB 4 +#define I2C_BIAS_RC_RSTB_MSB 3 +#define I2C_BIAS_RC_RSTB_LSB 3 + +#define I2C_BIAS_RC_DIV 4 +#define I2C_BIAS_RC_DIV_MSB 7 +#define I2C_BIAS_RC_DIV_LSB 4 + +#define I2C_BIAS_RC_CAP 5 +#define I2C_BIAS_RC_CAP_MSB 5 +#define I2C_BIAS_RC_CAP_LSB 0 + +#define I2C_BIAS_RC_UD 5 +#define I2C_BIAS_RC_UD_MSB 6 +#define I2C_BIAS_RC_UD_LSB 6 + +#define I2C_BIAS_RC_LOCKB 5 +#define I2C_BIAS_RC_LOCKB_MSB 7 +#define I2C_BIAS_RC_LOCKB_LSB 7 + +#define I2C_BIAS_RC_CHG_COUNT 6 +#define I2C_BIAS_RC_CHG_COUNT_MSB 4 +#define I2C_BIAS_RC_CHG_COUNT_LSB 0 + +#define I2C_BIAS_XPD_CPREG 7 +#define I2C_BIAS_XPD_CPREG_MSB 0 +#define I2C_BIAS_XPD_CPREG_LSB 0 + +#define I2C_BIAS_XPD_CGM 7 +#define I2C_BIAS_XPD_CGM_MSB 1 +#define I2C_BIAS_XPD_CGM_LSB 1 + +#define I2C_BIAS_DTEST 7 +#define I2C_BIAS_DTEST_MSB 3 +#define I2C_BIAS_DTEST_LSB 2 + +#define I2C_BIAS_DRES12K 7 +#define I2C_BIAS_DRES12K_MSB 7 +#define I2C_BIAS_DRES12K_LSB 4 diff --git a/components/soc/esp32h2/i2c_pmu.h b/components/soc/esp32h2/i2c_pmu.h new file mode 100644 index 0000000000..de1e7d6aea --- /dev/null +++ b/components/soc/esp32h2/i2c_pmu.h @@ -0,0 +1,280 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_PMU 0x6d +#define I2C_PMU_HOSTID 0 + +#define I2C_PMU_THRES_HIGH_7_0 0 +#define I2C_PMU_THRES_HIGH_7_0_MSB 7 +#define I2C_PMU_THRES_HIGH_7_0_LSB 0 + +#define I2C_PMU_THRES_LOW_7_0 1 +#define I2C_PMU_THRES_LOW_7_0_MSB 7 +#define I2C_PMU_THRES_LOW_7_0_LSB 0 + +#define I2C_PMU_THRES_HIGH_11_8 2 +#define I2C_PMU_THRES_HIGH_11_8_MSB 3 +#define I2C_PMU_THRES_HIGH_11_8_LSB 0 + +#define I2C_PMU_THRES_LOW_11_8 2 +#define I2C_PMU_THRES_LOW_11_8_MSB 7 +#define I2C_PMU_THRES_LOW_11_8_LSB 4 + +#define I2C_PMU_PVT_DELAY_INIT 3 +#define I2C_PMU_PVT_DELAY_INIT_MSB 7 +#define I2C_PMU_PVT_DELAY_INIT_LSB 0 + +#define I2C_PMU_PVT_DELAY_COUNT 4 +#define I2C_PMU_PVT_DELAY_COUNT_MSB 5 +#define I2C_PMU_PVT_DELAY_COUNT_LSB 0 + +#define I2C_PMU_OR_EN_CONT_CAL 4 +#define I2C_PMU_OR_EN_CONT_CAL_MSB 7 +#define I2C_PMU_OR_EN_CONT_CAL_LSB 7 + +#define I2C_PMU_I2C_RTC_DREG 5 +#define I2C_PMU_I2C_RTC_DREG_MSB 4 +#define I2C_PMU_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG 6 +#define I2C_PMU_I2C_DIG_DREG_MSB 4 +#define I2C_PMU_I2C_DIG_DREG_LSB 0 + +#define I2C_PMU_I2C_RTC_DREG_SLP 7 +#define I2C_PMU_I2C_RTC_DREG_SLP_MSB 3 +#define I2C_PMU_I2C_RTC_DREG_SLP_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG_SLP 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_MSB 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_LSB 4 + +#define I2C_PMU_EN_I2C_RTC_DREG 10 +#define I2C_PMU_EN_I2C_RTC_DREG_MSB 0 +#define I2C_PMU_EN_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_EN_I2C_DIG_DREG 10 +#define I2C_PMU_EN_I2C_DIG_DREG_MSB 1 +#define I2C_PMU_EN_I2C_DIG_DREG_LSB 1 + +#define I2C_PMU_EN_I2C_RTC_DREG_SLP 10 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_MSB 2 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_LSB 2 + +#define I2C_PMU_EN_I2C_DIG_DREG_SLP 10 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_MSB 3 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_LSB 3 + +#define I2C_PMU_ENX_RTC_DREG 11 +#define I2C_PMU_ENX_RTC_DREG_MSB 0 +#define I2C_PMU_ENX_RTC_DREG_LSB 0 + +#define I2C_PMU_ENX_DIG_DREG 11 +#define I2C_PMU_ENX_DIG_DREG_MSB 1 +#define I2C_PMU_ENX_DIG_DREG_LSB 1 + +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3 11 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_MSB 2 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_LSB 2 + +#define I2C_PMU_OR_XPD_RTC_REG 11 +#define I2C_PMU_OR_XPD_RTC_REG_MSB 4 +#define I2C_PMU_OR_XPD_RTC_REG_LSB 4 + +#define I2C_PMU_OR_XPD_DIG_REG 11 +#define I2C_PMU_OR_XPD_DIG_REG_MSB 5 +#define I2C_PMU_OR_XPD_DIG_REG_LSB 5 + +#define I2C_PMU_OR_PD_RTC_REG_SLP 11 +#define I2C_PMU_OR_PD_RTC_REG_SLP_MSB 6 +#define I2C_PMU_OR_PD_RTC_REG_SLP_LSB 6 + +#define I2C_PMU_OR_PD_DIG_REG_SLP 11 +#define I2C_PMU_OR_PD_DIG_REG_SLP_MSB 7 +#define I2C_PMU_OR_PD_DIG_REG_SLP_LSB 7 + +#define I2C_PMU_INT_DREG 12 +#define I2C_PMU_INT_DREG_MSB 4 +#define I2C_PMU_INT_DREG_LSB 0 + +#define I2C_PMU_O_UDF 12 +#define I2C_PMU_O_UDF_MSB 5 +#define I2C_PMU_O_UDF_LSB 5 + +#define I2C_PMU_O_OVF 12 +#define I2C_PMU_O_OVF_MSB 6 +#define I2C_PMU_O_OVF_LSB 6 + +#define I2C_PMU_O_UPDATE 12 +#define I2C_PMU_O_UPDATE_MSB 7 +#define I2C_PMU_O_UPDATE_LSB 7 + +#define I2C_PMU_PVT_COUNT_7_0 13 +#define I2C_PMU_PVT_COUNT_7_0_MSB 7 +#define I2C_PMU_PVT_COUNT_7_0_LSB 0 + +#define I2C_PMU_PVT_COUNT_11_8 14 +#define I2C_PMU_PVT_COUNT_11_8_MSB 3 +#define I2C_PMU_PVT_COUNT_11_8_LSB 0 + +#define I2C_PMU_IC_VGOOD_LVDET 14 +#define I2C_PMU_IC_VGOOD_LVDET_MSB 4 +#define I2C_PMU_IC_VGOOD_LVDET_LSB 4 + +#define I2C_PMU_IC_POWER_GOOD_DCDC 14 +#define I2C_PMU_IC_POWER_GOOD_DCDC_MSB 5 +#define I2C_PMU_IC_POWER_GOOD_DCDC_LSB 5 + +#define I2C_PMU_IC_VGOOD_DIGDET 14 +#define I2C_PMU_IC_VGOOD_DIGDET_MSB 6 +#define I2C_PMU_IC_VGOOD_DIGDET_LSB 6 + +#define I2C_PMU_OR_XPD_DCDC 15 +#define I2C_PMU_OR_XPD_DCDC_MSB 0 +#define I2C_PMU_OR_XPD_DCDC_LSB 0 + +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_MSB 1 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_LSB 1 + +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_MSB 2 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_LSB 2 + +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC 15 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_MSB 3 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_LSB 3 + +#define I2C_PMU_OR_ENX_REG_DCDC 15 +#define I2C_PMU_OR_ENX_REG_DCDC_MSB 4 +#define I2C_PMU_OR_ENX_REG_DCDC_LSB 4 + +#define I2C_PMU_OR_UNLOCK_DCDC 15 +#define I2C_PMU_OR_UNLOCK_DCDC_MSB 5 +#define I2C_PMU_OR_UNLOCK_DCDC_LSB 5 + +#define I2C_PMU_OR_FORCE_LOCK_DCDC 15 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_MSB 6 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_LSB 6 + +#define I2C_PMU_OR_ENB_SLOW_CLK 15 +#define I2C_PMU_OR_ENB_SLOW_CLK_MSB 7 +#define I2C_PMU_OR_ENB_SLOW_CLK_LSB 7 + +#define I2C_PMU_OC_SCK_DCAP 16 +#define I2C_PMU_OC_SCK_DCAP_MSB 7 +#define I2C_PMU_OC_SCK_DCAP_LSB 0 + +#define I2C_PMU_OC_XPD_LVDET 17 +#define I2C_PMU_OC_XPD_LVDET_MSB 0 +#define I2C_PMU_OC_XPD_LVDET_LSB 0 + +#define I2C_PMU_OC_MODE_LVDET 17 +#define I2C_PMU_OC_MODE_LVDET_MSB 1 +#define I2C_PMU_OC_MODE_LVDET_LSB 1 + +#define I2C_PMU_OR_XPD_TRX 17 +#define I2C_PMU_OR_XPD_TRX_MSB 2 +#define I2C_PMU_OR_XPD_TRX_LSB 2 + +#define I2C_PMU_OR_EN_RESET_CHIP 17 +#define I2C_PMU_OR_EN_RESET_CHIP_MSB 3 +#define I2C_PMU_OR_EN_RESET_CHIP_LSB 3 + +#define I2C_PMU_OC_DREF_LVDET 17 +#define I2C_PMU_OC_DREF_LVDET_MSB 6 +#define I2C_PMU_OC_DREF_LVDET_LSB 4 + +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE 17 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_MSB 7 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_LSB 7 + +#define I2C_PMU_DTEST 18 +#define I2C_PMU_DTEST_MSB 1 +#define I2C_PMU_DTEST_LSB 0 + +#define I2C_PMU_ENT_BIAS 18 +#define I2C_PMU_ENT_BIAS_MSB 2 +#define I2C_PMU_ENT_BIAS_LSB 2 + +#define I2C_PMU_ENT_VDD 18 +#define I2C_PMU_ENT_VDD_MSB 5 +#define I2C_PMU_ENT_VDD_LSB 3 + +#define I2C_PMU_EN_DMUX 18 +#define I2C_PMU_EN_DMUX_MSB 6 +#define I2C_PMU_EN_DMUX_LSB 6 + +#define I2C_PMU_WD_DISABLE 18 +#define I2C_PMU_WD_DISABLE_MSB 7 +#define I2C_PMU_WD_DISABLE_LSB 7 + +#define I2C_PMU_DTEST_DCDC 19 +#define I2C_PMU_DTEST_DCDC_MSB 0 +#define I2C_PMU_DTEST_DCDC_LSB 0 + +#define I2C_PMU_TESTEN_DCDC 19 +#define I2C_PMU_TESTEN_DCDC_MSB 1 +#define I2C_PMU_TESTEN_DCDC_LSB 1 + +#define I2C_PMU_ADD_DCDC 19 +#define I2C_PMU_ADD_DCDC_MSB 6 +#define I2C_PMU_ADD_DCDC_LSB 4 + +#define I2C_PMU_OR_POCPENB_DCDC 20 +#define I2C_PMU_OR_POCPENB_DCDC_MSB 0 +#define I2C_PMU_OR_POCPENB_DCDC_LSB 0 + +#define I2C_PMU_OR_SSTIME_DCDC 20 +#define I2C_PMU_OR_SSTIME_DCDC_MSB 1 +#define I2C_PMU_OR_SSTIME_DCDC_LSB 1 + +#define I2C_PMU_OR_CCM_DCDC 20 +#define I2C_PMU_OR_CCM_DCDC_MSB 2 +#define I2C_PMU_OR_CCM_DCDC_LSB 2 + +#define I2C_PMU_OR_VSET_LOW_DCDC 20 +#define I2C_PMU_OR_VSET_LOW_DCDC_MSB 7 +#define I2C_PMU_OR_VSET_LOW_DCDC_LSB 3 + +#define I2C_PMU_OR_FSW_DCDC 21 +#define I2C_PMU_OR_FSW_DCDC_MSB 2 +#define I2C_PMU_OR_FSW_DCDC_LSB 0 + +#define I2C_PMU_OR_DCMLEVEL_DCDC 21 +#define I2C_PMU_OR_DCMLEVEL_DCDC_MSB 4 +#define I2C_PMU_OR_DCMLEVEL_DCDC_LSB 3 + +#define I2C_PMU_OR_DCM2ENB_DCDC 21 +#define I2C_PMU_OR_DCM2ENB_DCDC_MSB 5 +#define I2C_PMU_OR_DCM2ENB_DCDC_LSB 5 + +#define I2C_PMU_OR_RAMP_DCDC 21 +#define I2C_PMU_OR_RAMP_DCDC_MSB 6 +#define I2C_PMU_OR_RAMP_DCDC_LSB 6 + +#define I2C_PMU_OR_RAMPLEVEL_DCDC 21 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_MSB 7 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_LSB 7 + +#define I2C_PMU_OR_VSET_HIGH_DCDC 22 +#define I2C_PMU_OR_VSET_HIGH_DCDC_MSB 4 +#define I2C_PMU_OR_VSET_HIGH_DCDC_LSB 0 + +#define I2C_PMU_OC_DEL_SSEND 22 +#define I2C_PMU_OC_DEL_SSEND_MSB 7 +#define I2C_PMU_OC_DEL_SSEND_LSB 5 + +#define I2C_PMU_OC_XPD_DIGDET 23 +#define I2C_PMU_OC_XPD_DIGDET_MSB 0 +#define I2C_PMU_OC_XPD_DIGDET_LSB 0 + +#define I2C_PMU_OC_MODE_DIGDET 23 +#define I2C_PMU_OC_MODE_DIGDET_MSB 1 +#define I2C_PMU_OC_MODE_DIGDET_LSB 1 + +#define I2C_PMU_OC_DREF_DIGDET 23 +#define I2C_PMU_OC_DREF_DIGDET_MSB 6 +#define I2C_PMU_OC_DREF_DIGDET_LSB 4 diff --git a/components/soc/esp32h2/i2c_ulp.h b/components/soc/esp32h2/i2c_ulp.h new file mode 100644 index 0000000000..5751f01936 --- /dev/null +++ b/components/soc/esp32h2/i2c_ulp.h @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_ULP 0x61 +#define I2C_ULP_HOSTID 0 + +#define I2C_ULP_IR_RESETB 0 +#define I2C_ULP_IR_RESETB_MSB 0 +#define I2C_ULP_IR_RESETB_LSB 0 + +#define I2C_ULP_XPD_REG_SLP 0 +#define I2C_ULP_XPD_REG_SLP_MSB 1 +#define I2C_ULP_XPD_REG_SLP_LSB 1 + +#define I2C_ULP_DBIAS_SLP 0 +#define I2C_ULP_DBIAS_SLP_MSB 7 +#define I2C_ULP_DBIAS_SLP_LSB 4 + +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_MSB 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_LSB 1 + +#define I2C_ULP_IR_FORCE_XPD_IPH 1 +#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 2 +#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 2 + +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_MSB 3 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_LSB 3 + +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP 1 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_MSB 4 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_LSB 4 + +#define I2C_ULP_IR_ZOS_XPD 2 +#define I2C_ULP_IR_ZOS_XPD_MSB 0 +#define I2C_ULP_IR_ZOS_XPD_LSB 0 + +#define I2C_ULP_IR_ZOS_RSTB 2 +#define I2C_ULP_IR_ZOS_RSTB_MSB 1 +#define I2C_ULP_IR_ZOS_RSTB_LSB 1 + +#define I2C_ULP_IR_ZOS_RESTART 2 +#define I2C_ULP_IR_ZOS_RESTART_MSB 2 +#define I2C_ULP_IR_ZOS_RESTART_LSB 2 + +#define I2C_ULP_DTEST 3 +#define I2C_ULP_DTEST_MSB 1 +#define I2C_ULP_DTEST_LSB 0 + +#define I2C_ULP_ENT_BG 3 +#define I2C_ULP_ENT_BG_MSB 2 +#define I2C_ULP_ENT_BG_LSB 2 + +#define I2C_ULP_MODE_LVDET 3 +#define I2C_ULP_MODE_LVDET_MSB 3 +#define I2C_ULP_MODE_LVDET_LSB 3 + +#define I2C_ULP_DREF_LVDET 3 +#define I2C_ULP_DREF_LVDET_MSB 6 +#define I2C_ULP_DREF_LVDET_LSB 4 + +#define I2C_ULP_XPD_LVDET 3 +#define I2C_ULP_XPD_LVDET_MSB 7 +#define I2C_ULP_XPD_LVDET_LSB 7 + +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG 4 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_MSB 0 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_LSB 0 + +#define I2C_ULP_INT_XPD_XTAL_BUF 4 +#define I2C_ULP_INT_XPD_XTAL_BUF_MSB 1 +#define I2C_ULP_INT_XPD_XTAL_BUF_LSB 1 + +#define I2C_ULP_INT_XPD_RC_CK 4 +#define I2C_ULP_INT_XPD_RC_CK_MSB 2 +#define I2C_ULP_INT_XPD_RC_CK_LSB 2 + +#define I2C_ULP_XTAL_DPHASE 4 +#define I2C_ULP_XTAL_DPHASE_MSB 3 +#define I2C_ULP_XTAL_DPHASE_LSB 3 + +#define I2C_ULP_INT_XPD_XTAL_LIN_REG 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_MSB 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_LSB 4 + +#define I2C_ULP_XTAL_RESTART_DC_CAL 4 +#define I2C_ULP_XTAL_RESTART_DC_CAL_MSB 5 +#define I2C_ULP_XTAL_RESTART_DC_CAL_LSB 5 + +#define I2C_ULP_XTAL_DAC 5 +#define I2C_ULP_XTAL_DAC_MSB 3 +#define I2C_ULP_XTAL_DAC_LSB 0 + +#define I2C_ULP_XTAL_DBLEED 6 +#define I2C_ULP_XTAL_DBLEED_MSB 4 +#define I2C_ULP_XTAL_DBLEED_LSB 0 + +#define I2C_ULP_XTAL_CAL_DONE 6 +#define I2C_ULP_XTAL_CAL_DONE_MSB 5 +#define I2C_ULP_XTAL_CAL_DONE_LSB 5 + +#define I2C_ULP_ZOS_DONE 6 +#define I2C_ULP_ZOS_DONE_MSB 6 +#define I2C_ULP_ZOS_DONE_LSB 6 diff --git a/components/soc/esp32h2/include/soc/rtc.h b/components/soc/esp32h2/include/soc/rtc.h index e117bdbb92..4c9e3c46a9 100644 --- a/components/soc/esp32h2/include/soc/rtc.h +++ b/components/soc/esp32h2/include/soc/rtc.h @@ -54,12 +54,12 @@ extern "C" { #define MHZ (1000000) #define RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12) -#define RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(cycles) (cycles << 12) +#define RTC_SLOW_CLK_RC32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12) #define RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(cycles) (cycles << 10) -#define RTC_SLOW_CLK_FREQ_150K 150000 -#define RTC_SLOW_CLK_FREQ_8MD256 (RTC_FAST_CLK_FREQ_APPROX / 256) +#define RTC_SLOW_CLK_FREQ_150K 130000 #define RTC_SLOW_CLK_FREQ_32K 32768 +#define RTC_SLOW_CLK_FREQ_RC32 32768 #define OTHER_BLOCKS_POWERUP 1 #define OTHER_BLOCKS_WAIT 1 @@ -68,14 +68,27 @@ extern "C" { * RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values. * Valid if RTC_CNTL_DBG_ATTEN is 0. */ -#define RTC_CNTL_DBIAS_SLP 0 //sleep dig_dbias & rtc_dbias -#define RTC_CNTL_DBIAS_1V00 0 -#define RTC_CNTL_DBIAS_1V05 4 -#define RTC_CNTL_DBIAS_1V10 5 -#define RTC_CNTL_DBIAS_1V15 6 -#define RTC_CNTL_DBIAS_1V20 7 +#define RTC_CNTL_DBIAS_SLP 0 //sleep dig_dbias & rtc_dbias +#define RTC_CNTL_DBIAS_1V00 0 +#define RTC_CNTL_DBIAS_1V05 4 +#define RTC_CNTL_DBIAS_1V10 5 +#define RTC_CNTL_DBIAS_1V15 6 +#define RTC_CNTL_DBIAS_1V20 7 +#define RTC_CNTL_DBIAS_DEFAULT 8 /* The value of 1V00 can be adjusted between 0~3*/ + +/* dcdc mode + */ +#define RTC_CNTL_DCDC_TRX_MODE 0b100 +#define RTC_CNTL_DCDC_LSLP_MODE 0b110 +#define RTC_CNTL_DCDC_DSLP_MODE 0b101 +#define RTC_CNTL_DCDC_FREQ_DEFAULT 3 + +#define DCDC_SLP_TRX_MODE 0 +#define DCDC_SLP_LSLP_MODE 1 +#define DCDC_SLP_DSLP_MODE 2 + #define RTC_CNTL_DIG_DBIAS_0V85 0 #define RTC_CNTL_DIG_DBIAS_0V90 1 #define RTC_CNTL_DIG_DBIAS_0V95 2 @@ -105,8 +118,10 @@ extern "C" { #define RTC_CNTL_CK8M_WAIT_DEFAULT 20 #define RTC_CK8M_ENABLE_WAIT_DEFAULT 5 -#define RTC_CNTL_CK8M_DFREQ_DEFAULT 100 -#define RTC_CNTL_SCK_DCAP_DEFAULT 255 +#define RTC_CNTL_CK8M_DFREQ_DEFAULT 600 +#define RTC_CNTL_SCK_DCAP_DEFAULT 128 +#define RTC_CNTL_RC32K_DFREQ_DEFAULT 707 + /* Various delays to be programmed into power control state machines */ #define RTC_CNTL_XTL_BUF_WAIT_SLP_US (250) @@ -138,28 +153,14 @@ typedef enum { RTC_XTAL_FREQ_40M = 40, //!< 40 MHz XTAL } rtc_xtal_freq_t; -/** - * @brief CPU frequency values - */ -typedef enum { - RTC_CPU_FREQ_XTAL = 0, //!< Main XTAL frequency - RTC_CPU_FREQ_80M = 1, //!< 80 MHz - RTC_CPU_FREQ_160M = 2, //!< 160 MHz - RTC_CPU_FREQ_240M = 3, //!< 240 MHz - RTC_CPU_FREQ_2M = 4, //!< 2 MHz - RTC_CPU_320M_80M = 5, //!< for test - RTC_CPU_320M_160M = 6, //!< for test - RTC_CPU_FREQ_XTAL_DIV2 = 7, //!< XTAL/2 after reset -} rtc_cpu_freq_t; - /** * @brief CPU clock source */ typedef enum { RTC_CPU_FREQ_SRC_XTAL, //!< XTAL - RTC_CPU_FREQ_SRC_PLL, //!< PLL (480M or 320M) - RTC_CPU_FREQ_SRC_8M, //!< Internal 8M RTC oscillator - RTC_CPU_FREQ_SRC_APLL //!< APLL + RTC_CPU_FREQ_SRC_PLL, //!< PLL (96M) + RTC_CPU_FREQ_SRC_8M, //!< Internal 18M RTC oscillator + RTC_CPU_FREQ_SRC_XTAL_D2 //!< XTAL/2 } rtc_cpu_freq_src_t; /** @@ -178,7 +179,7 @@ typedef struct rtc_cpu_freq_config_s { typedef enum { RTC_SLOW_FREQ_RTC = 0, //!< Internal 150 kHz RC oscillator RTC_SLOW_FREQ_32K_XTAL = 1, //!< External 32 kHz XTAL - RTC_SLOW_FREQ_8MD256 = 2, //!< Internal 8 MHz RC oscillator, divided by 256 + RTC_SLOW_FREQ_RC32K = 2, //!< Internal 32 KHz RC oscillator } rtc_slow_freq_t; /** @@ -202,7 +203,7 @@ typedef enum { */ typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK - RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 + RTC_CAL_RC32K = 1, //!< Internal 32 kHz RC oscillator RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL } rtc_cal_sel_t; @@ -217,21 +218,23 @@ typedef struct { uint32_t clk_rtc_clk_div : 8; uint32_t clk_8m_clk_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) uint32_t slow_clk_dcap : 8; //!< RTC 150k clock adjustment parameter (higher value leads to lower frequency) - uint32_t clk_8m_dfreq : 8; //!< RTC 8m clock adjustment parameter (higher value leads to higher frequency) + uint32_t clk_8m_dfreq : 10; //!< RTC 8m clock adjustment parameter (higher value leads to higher frequency) + uint32_t root_clk_slt : 2; //!< Select clock root source for esp32h2 (default 0: xtal_32M) } rtc_clk_config_t; /** * Default initializer for rtc_clk_config_t */ #define RTC_CLK_CONFIG_DEFAULT() { \ - .xtal_freq = RTC_XTAL_FREQ_40M, \ - .cpu_freq_mhz = 80, \ + .xtal_freq = RTC_XTAL_FREQ_32M, \ + .cpu_freq_mhz = 32, \ .fast_freq = RTC_FAST_FREQ_8M, \ .slow_freq = RTC_SLOW_FREQ_RTC, \ - .clk_rtc_clk_div = 0, \ - .clk_8m_clk_div = 0, \ + .clk_rtc_clk_div = 1, \ + .clk_8m_clk_div = 1, \ .slow_clk_dcap = RTC_CNTL_SCK_DCAP_DEFAULT, \ .clk_8m_dfreq = RTC_CNTL_CK8M_DFREQ_DEFAULT, \ + .root_clk_slt = 0, \ } typedef struct { @@ -241,6 +244,7 @@ typedef struct { uint32_t dbuf: 1; } x32k_config_t; + #define X32K_CONFIG_DEFAULT() { \ .dac = 3, \ .dres = 3, \ @@ -248,6 +252,14 @@ typedef struct { .dbuf = 1, \ } +typedef struct { + uint32_t dfreq : 10; +} rc32k_config_t; + +#define RC32K_CONFIG_DEFAULT() {\ + .dfreq = RTC_CNTL_RC32K_DFREQ_DEFAULT,\ +} + typedef struct { uint16_t wifi_powerup_cycles : 7; uint16_t wifi_wait_cycles : 9; @@ -499,6 +511,10 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq); */ uint32_t rtc_clk_apb_freq_get(void); +void rtc_clk_cpu_freq_set(uint32_t source, uint32_t div); +uint32_t rtc_clk_ahb_freq_get(void); + + uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles); /** @@ -633,7 +649,7 @@ typedef struct { uint32_t rtc_fastmem_pd_en : 1; //!< power down RTC fast memory uint32_t rtc_slowmem_pd_en : 1; //!< power down RTC slow memory uint32_t rtc_peri_pd_en : 1; //!< power down RTC peripherals - uint32_t wifi_pd_en : 1; //!< power down WiFi + uint32_t dig_ret_pd_en : 1; //!< power down dig_ret uint32_t bt_pd_en : 1; //!< power down BT uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep. uint32_t dig_peri_pd_en : 1; //!< power down digital peripherals @@ -662,7 +678,7 @@ typedef struct { .rtc_fastmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_FAST_MEM) ? 1 : 0, \ .rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \ .rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \ - .wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \ + .dig_ret_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_RET) ? 1 : 0, \ .bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \ .cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \ .dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \ @@ -683,7 +699,7 @@ typedef struct { #define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU #define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator -#define RTC_SLEEP_PD_WIFI BIT(6) //!< Power down WIFI +#define RTC_SLEEP_PD_DIG_RET BIT(6) //!< Power down WIFI #define RTC_SLEEP_PD_BT BIT(7) //!< Power down BT #define RTC_SLEEP_PD_CPU BIT(8) //!< Power down CPU when in lightsleep, but not restart #define RTC_SLEEP_PD_DIG_PERIPH BIT(9) //!< Power down DIG peripherals @@ -791,11 +807,11 @@ typedef struct { uint32_t pll_wait : 8; //!< Number of rtc_fast_clk cycles to wait for PLL to be ready uint32_t clkctl_init : 1; //!< Perform clock control related initialization uint32_t pwrctl_init : 1; //!< Perform power control related initialization - uint32_t rtc_dboost_fpd : 1; //!< Force power down RTC_DBOOST uint32_t xtal_fpu : 1; uint32_t bbpll_fpu : 1; uint32_t cpu_waiti_clk_gate : 1; uint32_t cali_ocode : 1; //!< Calibrate Ocode to make bangap voltage more precise. + uint32_t pmu_ctl : 1; } rtc_config_t; /** @@ -810,17 +826,93 @@ typedef struct { .pll_wait = RTC_CNTL_PLL_BUF_WAIT_DEFAULT, \ .clkctl_init = 1, \ .pwrctl_init = 1, \ - .rtc_dboost_fpd = 1, \ .xtal_fpu = 0, \ .bbpll_fpu = 0, \ .cpu_waiti_clk_gate = 1, \ - .cali_ocode = 0\ + .cali_ocode = 0, \ + .pmu_ctl = 1\ +} +typedef struct { + /* data */ + uint32_t or_en_cont_cal : 1; //!< default:0 rtc_init:0 pvt can be enable by either this register or digital -- if_en_cont_cal + uint32_t enx_rtc_dreg : 1; //!< default:1 rtc_init:1 use i2c registers to configure rtc regulator voltage level instead of pvt result -- int_dreg + uint32_t enx_dig_dreg : 1; //!< default:1 rtc_init:1 use i2c registers to configure dig regulator voltage level instead of pvt result -- int_dreg + uint32_t en_i2c_rtc_dreg : 1; //!< default:1 rtc_init:0 1: i2c_rtc_dreg; 0: if_rtc_dreg + uint32_t en_i2c_dig_dreg : 1; //!< default:1 rtc_init:0 1: i2c_dig_dreg; 0: if_dig_dreg + uint32_t en_i2c_rtc_dreg_slp : 1; //!< default:1 rtc_init:0 1: i2c_rtc_dreg_slp; 0: if_rtc_dreg_slp + uint32_t en_i2c_dig_dreg_slp : 1; //!< default:1 rtc_init:0 1: i2c_dig_dreg_slp; 0: if_dig_dreg_slp + uint32_t or_xpd_rtc_slave_3p3 : 1; //!< default:1 rtc_init:0 to turn off rtc slave, which is only required before DCDC running + uint32_t or_xpd_rtc_reg : 1; //!< default:1 rtc_init:0 handover control to digital -- if_xpd_rtc_reg + uint32_t or_xpd_dig_reg : 1; //!< default:1 rtc_init:0 handover control to digital -- if_xpd_dig_reg + uint32_t or_pd_rtc_reg_slp : 1; //!< default:0 rtc_init:1 configure this i2c to control rtc_sleep_regulator on off, no coressponding digital control signal + uint32_t or_pd_dig_reg_slp : 1; //!< default:0 rtc_init:0 default value 0 puts dig_sleep_regulator controlled by digital -- if_xpd_dig_reg_slp + uint32_t or_xpd_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_xpd_dcdc + uint32_t or_disalbe_deep_sleep_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_enable_deep_sleep_dcdc + uint32_t or_disalbe_light_sleep_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_enable_light_sleep_dcdc + uint32_t or_enalbe_trx_mode_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_enable_trx_mode_dcdc + uint32_t or_enx_reg_dcdc : 1; //!< default:0 rtc_init:1 handover dcdc configuration registers to digital control signals, including popenb, sstime, ccm, vset, fsw, dcmlevel, dcm2enb, ramp, ramplevel + uint32_t or_unlock_dcdc : 1; //!< default:0 rtc_init:0 not used in this version of silicon, can be unleashed if metal change if_vgood_lock_dcdc signal to high + uint32_t or_force_lock_dcdc : 1; //!< default:0 rtc_init:0 dcdc will be locked and shut-off if this register sets to 1 + uint32_t or_enb_slow_clk : 1; //!< default:0 rtc_init:1 handover slow clock control to digital -- if_enb_slow_clk + uint32_t or_xpd_trx : 1; //!< default:1 rtc_init:0 handover trx control to digital -- if_xpd_trx + uint32_t or_en_reset_chip : 1; //!< default:0 rtc_init:1 handover reset chip control to digital -- if_reset_chip + uint32_t or_force_xpd_reg_slave : 1; //!< default:0 rtc_init:1 set this reg to 1 after DCDC ready, to have rtc & dig slave control independent of DCDC status +} pmu_config_t; + +#define PMU_CONFIG_DEFAULT() {\ + .or_en_cont_cal = 0, \ + .enx_rtc_dreg = 1, \ + .enx_dig_dreg = 1, \ + .en_i2c_rtc_dreg = 0, \ + .en_i2c_dig_dreg = 0, \ + .en_i2c_rtc_dreg_slp = 0, \ + .en_i2c_dig_dreg_slp = 0, \ + .or_xpd_rtc_slave_3p3 = 0, \ + .or_xpd_rtc_reg = 0, \ + .or_xpd_dig_reg = 0, \ + .or_pd_rtc_reg_slp = 0, \ + .or_pd_dig_reg_slp = 0, \ + .or_xpd_dcdc = 0, \ + .or_disalbe_deep_sleep_dcdc = 0, \ + .or_disalbe_light_sleep_dcdc = 0, \ + .or_enalbe_trx_mode_dcdc = 0, \ + .or_enx_reg_dcdc = 1, \ + .or_unlock_dcdc = 0, \ + .or_force_lock_dcdc = 0, \ + .or_xpd_trx = 0, \ + .or_en_reset_chip = 1, \ + .or_force_xpd_reg_slave = 1\ +} + +typedef struct { + uint32_t swt_idle: 1; //!< If 1, swt_idle is sleep mode ; if 0, swt_idle is active mode + uint32_t swt_monitor: 1; //!< If 1, swt_monitor is sleep mode ; if 0, swt_monitor is active mode + uint32_t swt_slp: 1; //!< If 1, swt_slp is sleep mode ; if 0, swt_slp is active mode +} dbias_swt_cfg_t; + +#define DBIAS_SWITCH_CONFIG_DEFAULT(){\ + .swt_idle = 0, \ + .swt_monitor = 1, \ + .swt_slp = 1\ +} + +typedef struct { + /* data */ + uint32_t dig_regul0_en: 1; //!< If 1, dig_regulator0 is ctl by fsm; if 0, dig_regulator0 force pd. + uint32_t dig_regul1_en: 1; //!< If 1, dig_regulator1 is ctl by fsm; if 0, dig_regulator1 force pd. + uint32_t rtc_regul0_en: 1; //!< If 1, rtc_regulator0 is ctl by fsm; if 0, rtc_regulator0 force pd. +} regulator_cfg_t; + +#define REGULATOR_SET_DEFAULT(){\ + .dig_regul0_en = 1, \ + .dig_regul1_en = 1, \ + .rtc_regul0_en = 1, \ } /** - * Initialize RTC clock and power control related functions - * @param cfg configuration options as rtc_config_t - */ +* Initialize RTC clock and power control related functions +* @param cfg configuration options as rtc_config_t +*/ void rtc_init(rtc_config_t cfg); /** @@ -853,6 +945,47 @@ rtc_vddsdio_config_t rtc_vddsdio_get_config(void); */ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); + +/* Select clock root source for esp32h2. return source clk freq_mhz + */ +uint32_t root_clk_slt(uint32_t source); +uint32_t root_clk_get(void); + +/** + * Regulator config + */ +typedef struct { + uint32_t dig_source : 1; + uint32_t dig_active_dbias : 5; + uint32_t dig_slp_dbias : 5; + uint32_t rtc_source : 1; + uint32_t rtc_active_dbias : 5; + uint32_t rtc_slp_dbias : 5; +} regulator_config_t; + +#define REGULATOR0_CONFIG_DEFAULT() {\ + .dig_source = 0, \ + .dig_active_dbias = 20, \ + .dig_slp_dbias = 8, \ + .rtc_source = 0, \ + .rtc_active_dbias = 20, \ + .rtc_slp_dbias = 8 \ +} +#define REGULATOR1_CONFIG_DEFAULT() {\ + .dig_source = 1, \ + .dig_active_dbias = 15, \ + .dig_slp_dbias = 8, \ + .rtc_source = 1, \ + .rtc_active_dbias = 15, \ + .rtc_slp_dbias = 8 \ +} + + +/** + * gpio hangup + */ +void rtc_gpio_hangup(uint32_t gpio_no); + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index b280ce2437..42e3393923 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -245,9 +245,6 @@ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) -/*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/ -#define SOC_WIFI_HW_TSF (1) - /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) @@ -255,16 +252,9 @@ #define SOC_PHY_DIG_REGS_MEM_SIZE (21*4) #define SOC_MAC_BB_PD_MEM_SIZE (192*4) -/*--------------- WIFI LIGHT SLEEP CLOCK WIDTH CAPS --------------------------*/ -#define SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH (12) - /*-------------------------- Power Management CAPS ----------------------------*/ -#define SOC_PM_SUPPORT_WIFI_WAKEUP (1) - #define SOC_PM_SUPPORT_BT_WAKEUP (1) #define SOC_PM_SUPPORT_CPU_PD (1) -#define SOC_PM_SUPPORT_WIFI_PD (1) - #define SOC_PM_SUPPORT_BT_PD (1) From 45925c28fd9e6800154760ec30b30a12dd6097a2 Mon Sep 17 00:00:00 2001 From: intern Date: Mon, 9 Aug 2021 17:33:40 +0800 Subject: [PATCH 045/310] docs: update translation for jtag-debugging/index.rst and power_management.rst --- docs/en/api-guides/jtag-debugging/index.rst | 51 ++++--- .../api-reference/system/power_management.rst | 19 +-- .../zh_CN/api-guides/jtag-debugging/index.rst | 133 ++++++++++-------- .../api-reference/system/power_management.rst | 56 +++++--- 4 files changed, 146 insertions(+), 113 deletions(-) diff --git a/docs/en/api-guides/jtag-debugging/index.rst b/docs/en/api-guides/jtag-debugging/index.rst index 1ba519de07..93d58549dd 100644 --- a/docs/en/api-guides/jtag-debugging/index.rst +++ b/docs/en/api-guides/jtag-debugging/index.rst @@ -13,15 +13,15 @@ This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and d :ref:`jtag-debugging-setup-openocd` Procedure to install OpenOCD and verify that it is installed. :ref:`jtag-debugging-configuring-target` - Configuration of OpenOCD software and set up JTAG adapter hardware that will make together a debugging target. + Configuration of OpenOCD software and setting up of JTAG adapter hardware, which together make up the debugging target. :ref:`jtag-debugging-launching-debugger` Steps to start up a debug session with GDB from :ref:`jtag-debugging-using-debugger-eclipse` and from :ref:`jtag-debugging-using-debugger-command-line`. :ref:`jtag-debugging-examples` If you are not familiar with GDB, check this section for debugging examples provided from :ref:`jtag-debugging-examples-eclipse` as well as from :ref:`jtag-debugging-examples-command-line`. :ref:`jtag-debugging-building-openocd` - Procedure to build OpenOCD from sources for :doc:`Windows `, :doc:`Linux ` and :doc:`MacOS ` operating systems. + Procedure to build OpenOCD from sources for :doc:`Windows `, :doc:`Linux ` and :doc:`macOS ` operating systems. :ref:`jtag-debugging-tips-and-quirks` - This section provides collection of tips and quirks related JTAG debugging of {IDF_TARGET_NAME} with OpenOCD and GDB. + This section provides collection of tips and quirks related to JTAG debugging of {IDF_TARGET_NAME} with OpenOCD and GDB. .. include:: {IDF_TARGET_PATH_NAME}.inc @@ -36,24 +36,24 @@ Introduction .. only:: esp32 - The ESP32 has two powerful Xtensa cores, allowing for a great deal of variety of program architectures. The FreeRTOS OS that comes with ESP-IDF is capable of multi-core preemptive multithreading, allowing for an intuitive way of writing software. + The ESP32 has two powerful Xtensa cores, allowing for a great deal of variety of program architectures. The FreeRTOS OS that comes with ESP-IDF is capable of multi-core preemptive scheduling, allowing for an intuitive way of writing software. - The downside of the ease of programming is that debugging without the right tools is harder: figuring out a bug that is caused by two threads, running even simultaneously on two different CPU cores, can take a long time when all you have are printf statements. A better and in many cases quicker way to debug such problems is by using a debugger, connected to the processors over a debug port. + The downside of the ease of programming is that debugging without the right tools is harder: figuring out a bug that is caused by two threads, running even simultaneously on two different CPU cores, can take a long time when all you have are ``printf()`` statements. A better (and in many cases quicker) way to debug such problems is by using a debugger, connected to the processors over a debug port. -Espressif has ported OpenOCD to support the {IDF_TARGET_NAME} processor and the multicore FreeRTOS, which will be the foundation of most {IDF_TARGET_NAME} apps, and has written some tools to help with features OpenOCD does not support natively. +Espressif has ported OpenOCD to support the {IDF_TARGET_NAME} processor and the multi-core FreeRTOS (which is the foundation of most {IDF_TARGET_NAME} apps). Additionally, some extra tools have been written to provide extra features that OpenOCD does not support natively. -This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB under Linux, Windows and MacOS. Except for OS specific installation procedures, the s/w user interface and use procedures are the same across all supported operating systems. +This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB under Linux, Windows and macOS. Except for OS specific installation procedures, the s/w user interface and use procedures are the same across all supported operating systems. .. note:: - Screenshots presented in this document have been made for Eclipse Neon 3 running on Ubuntu 16.04 LTS. There may be some small differences in what a particular user interface looks like, depending on whether you are using Windows, MacOS or Linux and / or a different release of Eclipse. + Screenshots presented in this document have been made for Eclipse Neon 3 running on Ubuntu 16.04 LTS. There may be some small differences in what a particular user interface looks like, depending on whether you are using Windows, macOS or Linux and / or a different release of Eclipse. .. _jtag-debugging-how-it-works: How it Works? ------------- -The key software and hardware to perform debugging of {IDF_TARGET_NAME} with OpenOCD over JTAG (Joint Test Action Group) interface is presented below and includes {IDF_TARGET_TOOLCHAIN_PREFIX}-gdb debugger, OpenOCD on chip debugger and JTAG adapter connected to {IDF_TARGET_NAME} target. +The key software and hardware components that perform debugging of {IDF_TARGET_NAME} with OpenOCD over JTAG (Joint Test Action Group) interface is presented in the diagram below under the "Debugging With JTAG" label. These components include {IDF_TARGET_TOOLCHAIN_PREFIX}-gdb debugger, OpenOCD on chip debugger, and the JTAG adapter connected to {IDF_TARGET_NAME} target. .. figure:: ../../../_static/jtag-debugging-overview.jpg :align: center @@ -62,27 +62,26 @@ The key software and hardware to perform debugging of {IDF_TARGET_NAME} with Ope JTAG debugging - overview diagram -Under "Application Loading and Monitoring" there is another software and hardware to compile, build and flash application to {IDF_TARGET_NAME}, as well as to provide means to monitor diagnostic messages from {IDF_TARGET_NAME}. +Likewise, the "Application Loading and Monitoring" label indicates the key software and hardware components that allow an application to be compiled, built, and flashed to {IDF_TARGET_NAME}, as well as to provide means to monitor diagnostic messages from {IDF_TARGET_NAME}. -Debugging using JTAG and application loading / monitoring is integrated under the `Eclipse `_ environment, to provide quick and easy transition from writing, compiling and loading the code to debugging, back to writing the code, and so on. All the software is available for Windows, Linux and MacOS platforms. +"Debugging With JTAG" and "Application Loading and Monitoring" is integrated under the `Eclipse `_ IDE in order to provide a quick and easy transition between writing/compiling/loading/debugging code. The Eclipse IDE (and the integrated debugging software) is available for Windows, Linux and macOS platforms. .. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED - If the |devkit-name-with-link| is used, then connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the FT2232H chip, which provides two USB channels, one for JTAG and the one for UART connection. + If the |devkit-name-with-link| is used, then connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the FT2232H chip, which provides two USB channels, one for JTAG and the other for UART connection. .. only:: SOC_USB_SERIAL_JTAG_SUPPORTED - The connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the {IDF_TARGET_NAME} chip itself, which provides two USB channels, one for JTAG and one for the USB terminal connection. The USB cable should be connected the D+/D- USB pins of {IDF_TARGET_NAME} and not to the serial RxD/TxD throught an USB-to-UART chip. The proper connection is explained later in subsection :ref:`jtag-debugging-configuring-target`. + The connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the {IDF_TARGET_NAME} chip itself, which provides two USB channels, one for JTAG and the other for the USB terminal connection. The USB cable should be connected to the D+/D- USB pins of {IDF_TARGET_NAME} and not to the serial RxD/TxD through a USB-to-UART chip. The proper connection is explained later in subsection :ref:`jtag-debugging-configuring-target`. .. only:: esp32c3 .. note:: - Debugging through the USB interface implemented in ESP32-C3 requires to have a chip with revision 3 or newer. Please use other debugging options (e.g. with ESP-Prog) for chip revision 1 and 2. The easiest way to determine the chip revision is to look for the `Chip is ESP32-C3 (revision 3)` message near the end of a successful chip flashing done by `idf.py flash`. + Debugging through the USB interface implemented in {IDF_TARGET_NAME} requires to have a chip with revision 3 or newer. Please use other debugging options (e.g. with ESP-Prog) for chip revision 1 and 2. The easiest way to determine the chip revision is to look for the `Chip is ESP32-C3 (revision 3)` message near the end of a successful chip flashing done by `idf.py flash`. Depending on user preferences, both `debugger` and `idf.py build` can be operated directly from terminal/command line, instead from Eclipse. - .. _jtag-debugging-selecting-jtag-adapter: Selecting JTAG Adapter @@ -94,7 +93,7 @@ Selecting JTAG Adapter .. only:: SOC_USB_SERIAL_JTAG_SUPPORTED - The quickest and most convenient way to start with JTAG debugging is through an USB cable connected to the D+/D- USB pins of {IDF_TARGET_NAME}. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to {IDF_TARGET_NAME}. + The quickest and most convenient way to start with JTAG debugging is through a USB cable connected to the D+/D- USB pins of {IDF_TARGET_NAME}. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to {IDF_TARGET_NAME}. If you decide to use separate JTAG adapter, look for one that is compatible with both the voltage levels on the {IDF_TARGET_NAME} as well as with the OpenOCD software. The JTAG port on the {IDF_TARGET_NAME} is an industry-standard JTAG port which lacks (and does not need) the TRST pin. The JTAG I/O pins all are powered from the VDD_3P3_RTC pin (which normally would be powered by a 3.3 V rail) so the JTAG adapter needs to be able to work with JTAG pins in that voltage range. @@ -137,7 +136,7 @@ If any of these steps do not work, please go back to the :ref:`setting up the to Configuring {IDF_TARGET_NAME} Target ------------------------------------- -Once OpenOCD is installed, move to configuring {IDF_TARGET_NAME} target (i.e {IDF_TARGET_NAME} board with JTAG interface). You will do it in the following three steps: +Once OpenOCD is installed, you can proceed to configuring the {IDF_TARGET_NAME} target (i.e {IDF_TARGET_NAME} board with JTAG interface). Configuring the target is split into the following three steps: * Configure and connect JTAG interface * Run OpenOCD @@ -147,7 +146,7 @@ Once OpenOCD is installed, move to configuring {IDF_TARGET_NAME} target (i.e {ID Configure and connect JTAG interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This step depends on JTAG and {IDF_TARGET_NAME} board you are using - see the two cases described below. +This step depends on the JTAG and {IDF_TARGET_NAME} board you are using (see the two cases described below). .. toctree:: :maxdepth: 1 @@ -175,12 +174,11 @@ Open a terminal and set it up for using the ESP-IDF as described in the :ref:`se .. note:: - The files provided after ``-f`` above are specific for |run-openocd-device-name|. You may need to provide different files depending on used hardware. For guidance see :ref:`jtag-debugging-tip-openocd-configure-target`. + The files provided after ``-f`` above are specific for |run-openocd-device-name|. You may need to provide different files depending on the hardware that is used. For guidance see :ref:`jtag-debugging-tip-openocd-configure-target`. .. only:: esp32c3 - For example, ``board/esp32c3-ftdi.cfg`` can be used for a custom board with an FT2232H or FT232H chip used for JTAG connection, - or with ESP-Prog. + For example, ``board/esp32c3-ftdi.cfg`` can be used for a custom board with an FT2232H or FT232H chip used for JTAG connection, or with ESP-Prog. .. highlight:: none @@ -190,10 +188,9 @@ You should now see similar output (this log is for |run-openocd-device-name|): :start-after: run-openocd-output :end-before: --- -* If there is an error indicating permission problems, please see the "Permissions delegation" bit in the OpenOCD README file in ``~/esp/openocd-esp32`` directory. -* In case there is an error finding configuration files, e.g. |run-openocd-cfg-file-err|, check ``OPENOCD_SCRIPTS`` environment variable is set correctly. This variable is used by OpenOCD to look for the files specified after ``-f``. See :ref:`jtag-debugging-setup-openocd` section for details. Also check if the file is indeed under provided path. -* If you see JTAG errors (...all ones/...all zeroes) please check your connections, whether no other signals are connected to JTAG besides {IDF_TARGET_NAME}'s pins, and see if everything is powered on. - +* If there is an error indicating permission problems, please see section on "Permissions delegation" in the OpenOCD README file located in the ``~/esp/openocd-esp32`` directory. +* In case there is an error in finding the configuration files, e.g. |run-openocd-cfg-file-err|, check if the ``OPENOCD_SCRIPTS`` environment variable is set correctly. This variable is used by OpenOCD to look for the files specified after the ``-f`` option. See :ref:`jtag-debugging-setup-openocd` section for details. Also check if the file is indeed under the provided path. +* If you see JTAG errors (e.g., ``...all ones`` or ``...all zeroes``), please check your JTAG connections, whether other signals are connected to JTAG besides {IDF_TARGET_NAME}'s pins, and see if everything is powered on correctly. .. _jtag-upload-app-debug: @@ -218,7 +215,7 @@ OpenOCD flashing command ``program_esp`` has the following format: - ``reset`` - Optional. Reset target after programing. - ``exit`` - Optional. Finally exit OpenOCD. -You are now ready to start application debugging. Follow steps described in section below. +You are now ready to start application debugging. Follow the steps described in the section below. .. _jtag-debugging-launching-debugger: @@ -268,7 +265,7 @@ Please refer to separate documents listed below, that describe build process. Windows Linux - MacOS + macOS The examples of invoking OpenOCD in this document assume using pre-built binary distribution described in section :ref:`jtag-debugging-setup-openocd`. diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index a33df04d7e..d195388716 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -56,15 +56,18 @@ Power management locks have acquire/release counters. If the lock has been acqui {IDF_TARGET_NAME} supports three types of locks described in the table below. -============================ ====================================================== -Lock Description -============================ ====================================================== -``ESP_PM_CPU_FREQ_MAX`` Requests CPU frequency to be at the maximum value set with :cpp:func:`esp_pm_configure`. For {IDF_TARGET_NAME}, this value can be set to 80 MHz, 160 MHz, or 240 MHz. +.. list-table:: + :header-rows: 1 + :widths: 25 60 -``ESP_PM_APB_FREQ_MAX`` Requests the APB frequency to be at the maximum supported value. For {IDF_TARGET_NAME}, this is 80 MHz. - -``ESP_PM_NO_LIGHT_SLEEP`` Disables automatic switching to light sleep. -============================ ====================================================== + * - Lock + - Description + * - ``ESP_PM_CPU_FREQ_MAX`` + - Requests CPU frequency to be at the maximum value set with :cpp:func:`esp_pm_configure`. For {IDF_TARGET_NAME}, this value can be set to 80 MHz, 160 MHz, or 240 MHz. + * - ``ESP_PM_APB_FREQ_MAX`` + - Requests the APB frequency to be at the maximum supported value. For {IDF_TARGET_NAME}, this is 80 MHz. + * - ``ESP_PM_NO_LIGHT_SLEEP`` + - Disables automatic switching to light sleep. {IDF_TARGET_NAME} Power Management Algorithm --------------------------------------- diff --git a/docs/zh_CN/api-guides/jtag-debugging/index.rst b/docs/zh_CN/api-guides/jtag-debugging/index.rst index faf74c79fa..c29b6c719e 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/index.rst +++ b/docs/zh_CN/api-guides/jtag-debugging/index.rst @@ -2,24 +2,24 @@ JTAG 调试 ========= :link_to_translation:`en:[English]` -本文将指导安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,并介绍如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。本文的组织结构如下: +本文将介绍如何安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,以及如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。本文结构如下: :ref:`jtag-debugging-introduction` 介绍本指南主旨。 :ref:`jtag-debugging-how-it-works` - 介绍 {IDF_TARGET_NAME},JTAG(Joint Test Action Group)接口,OpenOCD 和 GDB 是如何相互连接从而实现 {IDF_TARGET_NAME} 的调试功能。 + 介绍 {IDF_TARGET_NAME}、JTAG(Joint Test Action Group)接口、OpenOCD 和 GDB 如何相互连接,从而实现 {IDF_TARGET_NAME} 的调试功能。 :ref:`jtag-debugging-selecting-jtag-adapter` 介绍有关 JTAG 硬件适配器的选择及参照标准。 :ref:`jtag-debugging-setup-openocd` 介绍如何安装官方预编译好的 OpenOCD 软件包并验证是否安装成功。 :ref:`jtag-debugging-configuring-target` - 介绍如何设置 OpenOCD 软件并安装 JTAG 硬件适配器,这两者共同组成最终的调试目标。 + 介绍如何设置 OpenOCD 软件并安装 JTAG 硬件,两项共同构成调试目标. :ref:`jtag-debugging-launching-debugger` 介绍如何从 :ref:`Eclipse 集成开发环境 ` 和 :ref:`命令行终端 ` 启动 GDB 调试会话。 :ref:`jtag-debugging-examples` - 如果你对 GDB 不太熟悉,本小节会分别针对 :ref:`Eclipse 集成开发环境 ` 和 :ref:`命令行终端 ` 来讲解调试的范例。 + 如果您不熟悉 GDB,请查看此小节以获取 :ref:`Eclipse 集成开发环境 ` 以及 :ref:`命令行终端 ` 提供的调试示例。 :ref:`jtag-debugging-building-openocd` - 介绍如何在 :doc:`Windows `,:doc:`Linux ` 和 :doc:`MacOS ` 操作系统上从源码构建 OpenOCD。 + 介绍如何在 :doc:`Windows `,:doc:`Linux ` 和 :doc:`macOS ` 操作系统上从源码构建 OpenOCD。 :ref:`jtag-debugging-tips-and-quirks` 介绍使用 OpenOCD 和 GDB 通过 JTAG 接口调试 {IDF_TARGET_NAME} 时的注意事项和补充内容。 @@ -36,25 +36,24 @@ JTAG 调试 .. only:: esp32 - ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF 自带的 FreeRTOS 操作系统具有多核抢占式多线程的功能,它允许用户以更加直观的方式编写软件。 + ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF 自带的 FreeRTOS 操作系统支持多核抢占式调度,允许用户以更加直观的方式编写软件。 + + 与此相对地,由于缺乏合适的工具,简便的编程方式也会给程序的调试带来困难,比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,那么仅凭 ``printf`` 语句会花费很长时间来定位该错误。调试此类问题更好(往往也更快)的方法是使用调试器,将其连接到处理器的调试端口。 - 与此相对地,简便的编程方式会给程序的调试带来困难(如果没有合适的工具),比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,仅凭 ``printf`` 语句会花费很长的时间来定位到该错误。在大多数情况下,调试此类问题更快的方法是使用调试器,连接到处理器的调试端口。 +乐鑫已完成 OpenOCD 移植,以支持 {IDF_TARGET_NAME} 处理器和多核 FreeRTOS 架构(此作为大多数 {IDF_TARGET_NAME} 应用程序的基础)。此外,乐鑫还提供了一些 OpenOCD 本身并不支持的工具,以进一步丰富调试功能。 -乐鑫已经为 {IDF_TARGET_NAME} 处理器和多核 FreeRTOS 架构移植好了 OpenOCD,它将成为大多数 {IDF_TARGET_NAME} 应用程序的基础。此外,乐鑫还提供了一些 OpenOCD 本身并不支持的工具来进一步丰富调试的功能。 - -本文将指导如何在 Linux,Windows 和 MacOS 环境下为 {IDF_TARGET_NAME} 安装 OpenOCD,并使用 GDB 进行软件调试。除了个别操作系统的安装过程有所差别以外,软件用户界面和使用流程都是一样的。 +本文将介绍如何在 Linux、Windows 和 macOS 环境下为 {IDF_TARGET_NAME} 安装 OpenOCD,并使用 GDB 进行软件调试。除部分安装流程有所不同外,所有操作系统的软件用户界面和使用流程都是相同的。 .. note:: - 本文使用的图片素材来自于 Ubuntu 16.04 LTS 上 Eclipse Neon 3 软件的截图,不同的操作系统(Windows, MacOS 或者 Linux)和 Eclipse 软件版本在用户界面上可能会有细微的差别。 + 本文使用的图片素材来自于 Ubuntu 16.04 LTS 上 Eclipse Neon 3 软件的截图,不同的操作系统(Windows、macOS 或 Linux)或不同的 Eclipse 软件版本在用户界面上可能会有细微差别。 .. _jtag-debugging-how-it-works: 工作原理 -------- -通过 JTAG(Joint Test Action Group)接口使用 OpenOCD 调试 {IDF_TARGET_NAME} 时所需要的一些关键的软件和硬件包括 **{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb -调试器**,**OpenOCD 片上调试器** 和连接到 **{IDF_TARGET_NAME}** 目标的 **JTAG 适配器**。 +通过 JTAG(Joint Test Action Group)接口使用 OpenOCD 调试 {IDF_TARGET_NAME} 时所需要的关键软件和硬件包括 **{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb 调试器**、**OpenOCD 片上调试器** 和连接到 **{IDF_TARGET_NAME}** 目标的 **JTAG 适配器**,如下图 “Application Loading and Monitoring” 标志所示。 .. figure:: ../../../_static/jtag-debugging-overview_zh.jpg :align: center @@ -63,27 +62,46 @@ JTAG 调试 JTAG 调试 - 概述图 -在 “Application Loading and Monitoring” 下还有另外一组软件和硬件,它们用来编译、构建和烧写应用程序到 {IDF_TARGET_NAME} 上,以及监视来自 {IDF_TARGET_NAME} 的运行诊断信息。 +“Application Loading and Monitoring” 标志显示一组关键的软件和硬件组件,可用于编译、构建和烧写应用程序到 {IDF_TARGET_NAME} 上,以及监视来自 {IDF_TARGET_NAME} 的运行诊断信息。 -`Eclipse `__ 环境集成了 JTAG 调试和应用程序加载、监视的功能,它使得软件从编写、编译、加载到调试的迭代过程变得更加快速而简单。所有的软件均适用于 Windows,Linux 和 MacOS 平台。 +`Eclipse `__ 环境集成了 JTAG 调试和应用程序加载、监视的功能,使得软件从编写、编译、加载到调试的迭代过程变得更加快速简单。Eclipse IDE 及其集成的调试软件均适用于 Windows、Linux 和 macOS 平台。 -如果你使用的是 |devkit-name-with-link|,得益于板载的 FT232H 芯片,PC 和 {IDF_TARGET_NAME} 的连接仅仅需要一根 USB 线即可完成。FT232H 提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 UART。 +.. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED + + 若使用 |devkit-name-with-link|,由于其板载 FT232H 芯片,仅需一根 USB 线即可连接 PC 与 {IDF_TARGET_NAME}。FT232H 提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 UART。 -根据用户的喜好,除了使用 Eclipse 集成开发环境,还可以直接在命令行终端运行 `debugger` 和 `idf.py build`。 +.. only:: SOC_USB_SERIAL_JTAG_SUPPORTED + + 仅需一根 USB 线即可高效连接 PC 与 {IDF_TARGET_NAME},因为 {IDF_TARGET_NAME} 芯片本身提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 USB 终端。应将 USB 线连接到 {IDF_TARGET_NAME} 的 D+/D- USB 管脚,而非通过 USB-UART 芯片连接到串行 RxD/TxD。后文中 :ref:`jtag-debugging-configuring-target` 小节将对此进行解释。 + +.. only:: esp32c3 + + .. note:: + + {IDF_TARGET_NAME} 中的 USB 接口只能用于调试版本 3 或更新版本的芯片,对于版本 1 或 2 的芯片,请使用其他调试板(例如 ESP-Prog)。确定芯片版本最简单的方法是通过 `idf.py flash` 完成芯片烧写,并在底部寻找 `芯片为 ESP32-C3 (版本 3)` 信息。 + +根据用户喜好,除了使用 Eclipse 集成开发环境,还可以直接在命令行终端运行 `debugger` 和 `idf.py build`。 .. _jtag-debugging-selecting-jtag-adapter: 选择 JTAG 适配器 ---------------- -上手 JTAG 最快速便捷的方式是使用 |devkit-name-with-link|,因为它板载了 JTAG 调试接口,无需使用外部的 JTAG 硬件适配器和额外的线缆来连接 JTAG 与 {IDF_TARGET_NAME}。|devkit-name| 采用 FT2232H 提供的 JTAG 接口,可以稳定运行在 20 MHz 的时钟频率,外接的适配器很难达到这个速度。 +.. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED -如果你想使用单独的 JTAG 适配器,请确保其与 {IDF_TARGET_NAME} 的电平电压和 OpenOCD 软件都兼容。{IDF_TARGET_NAME} 使用的是业界标准的 JTAG 接口,它省略了(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 引脚由 VDD_3P3_RTC 电源引脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的引脚需要能够在该电压范围内正常工作。 + 上手 JTAG 最快速便捷的方式是使用 |devkit-name-with-link|,因为它板载了 JTAG 调试接口,无需使用外部 JTAG 硬件适配器和额外线缆来连接 JTAG 与 {IDF_TARGET_NAME}。|devkit-name| 采用 FT2232H 提供的 JTAG 接口,可以稳定运行在 20 MHz 的时钟频率,外接的适配器很难达到这个速度。 -在软件方面,OpenOCD 支持相当多数量的 JTAG 适配器,可以参阅 `OpenOCD 支持的适配器列表 `_ (尽管上面显示的器件不太完整),这个页面还列出了兼容 SWD 接口的适配器,但是请注意,{IDF_TARGET_NAME} 目前并不支持 SWD。此外那些被硬编码为只支持特定产品线的 JTAG 适配器也不能在 {IDF_TARGET_NAME} 上工作,比如用于 STM32 产品家族的 ST-LINK 适配器。 +.. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED -JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 GND。某些 JTAG 适配器还需要 {IDF_TARGET_NAME} 提供一路电源到适配器的某个引脚上(比如 Vtar)用以设置适配器的工作电压。SRST 信号线是可选的,它可以连接到 {IDF_TARGET_NAME} 的 CH_PD 引脚上,尽管目前 OpenOCD 对该信号线的支持还非常有限。 + 上手 JTAG 最快速便捷的方式是将一根 USB 线连接到 {IDF_TARGET_NAME} 的 D+/D- USB 管脚,无需使用外部 JTAG 适配器和额外线缆。 +如果您想使用单独的 JTAG 适配器,请确保其与 {IDF_TARGET_NAME} 的电平电压和 OpenOCD 软件都兼容。{IDF_TARGET_NAME} 使用的是业界标准的 JTAG 接口,它未使用(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 管脚由 VDD_3P3_RTC 电源管脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的管脚需要能够在该电压范围内正常工作。 + +在软件方面,OpenOCD 支持相当多数量的 JTAG 适配器,请参阅 `OpenOCD 支持的适配器列表 `_ (请注意这一列表并不完整),其中还列出了兼容 SWD 接口的适配器,但请注意,{IDF_TARGET_NAME} 目前并不支持 SWD。此外,被硬编码为只支持特定产品线的 JTAG 适配器也无法在 {IDF_TARGET_NAME} 上工作,例如仅针对 STM32 系列产品的 ST-LINK 适配器。 + +JTAG 正常工作至少需要连接的信号线有:TDI、TDO、TCK、TMS 和 GND。一些 JTAG 适配器还需要 {IDF_TARGET_NAME} 提供一路电源到适配器的某个管脚上(比如 Vtar),用于设置适配器的工作电压。您也可以选择将 SRST 信号线连接到 {IDF_TARGET_NAME} 的 CH_PD 管脚上,但请注意,目前 OpenOCD 对该信号线提供的支持相当有限。 + +`ESP-Prog `_ 中展示了使用外部电路板进行调试的实例,方法是将其连接到 {IDF_TARGET_NAME} 的 JTAG 管脚上。 .. _jtag-debugging-setup-openocd: @@ -92,33 +110,33 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G .. highlight:: bash -如果你已经按照 :doc:`快速入门 <../../get-started/index>` 一文中的介绍安装好了 ESP-IDF 及其 CMake 构建系统,那么 OpenOCD 已经被默认安装到了你的开发系统中。在 :ref:`设置开发环境 ` 结束后,你应该能够在终端中运行如下 OpenOCD 命令:: +如果您已经按照 :doc:`快速入门 <../../get-started/index>` 完成了 ESP-IDF 及其 CMake 构建系统的安装,那么 OpenOCD 已经被默认安装到了您的开发系统中。在 :ref:`设置开发环境 ` 结束后,您应该能够在终端中运行如下 OpenOCD 命令:: openocd --version .. highlight:: none -终端会输出以下信息(实际版本号可能会比这里列出的更新):: +终端会输出以下信息(实际版本号可能会更新):: Open On-Chip Debugger v0.10.0-esp32-20190708 (2019-07-08-11:04) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html -你还可以检查 ``OPENOCD_SCRIPTS`` 环境变量的值来确认 OpenOCD 配置文件的路径,Linux 和 macOS 用户可以在终端输入 ``echo $OPENOCD_SCRIPTS``,Windows 用户需要输入 ``echo %OPENOCD_SCRIPTS%``。如果终端打印了有效的路径,则表明 OpenOCD 已经被正确安装。 +您还可以检查 ``OPENOCD_SCRIPTS`` 环境变量的值,以确认 OpenOCD 配置文件的路径,Linux 和 macOS 用户可以在终端输入 ``echo $OPENOCD_SCRIPTS``,Windows 用户需要输入 ``echo %OPENOCD_SCRIPTS%``。如果终端输出了有效路径,则表明您已经正确安装 OpenOCD。 -如果上述步骤没有成功执行,请返回快速入门手册,参考其中 :ref:`设置安装工具 ` 章节的说明。 +如果无法执行上述步骤,请再次阅读快速入门手册,参考 :ref:`设置安装工具 ` 章节。 .. note:: - 另外,我们还可以从源代码编译 OpenOCD 工具,相关详细信息请参阅 :ref:`jtag-debugging-building-openocd` 章节。 + 另外也可以从源代码编译 OpenOCD 工具,详细信息请参阅 :ref:`jtag-debugging-building-openocd` 章节。 .. _jtag-debugging-configuring-target: 配置 {IDF_TARGET_NAME} 目标板 ---------------------------- -安装好 OpenOCD 之后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG 接口的 {IDF_TARGET_NAME} 板),具体可以通过以下三个步骤进行: +OpenOCD 安装完成后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG 接口的 {IDF_TARGET_NAME} 板),具体分为以下三个步骤: - 配置并连接 JTAG 接口 - 运行 OpenOCD @@ -128,7 +146,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 配置并连接 JTAG 接口 ~~~~~~~~~~~~~~~~~~~~ -此步骤取决于您使用的 JTAG 和 {IDF_TARGET_NAME} 板,请参考以下两种情况。 +此步骤取决于使用的 JTAG 和 {IDF_TARGET_NAME} 板,请参考以下两种情况。 .. toctree:: :maxdepth: 1 @@ -148,7 +166,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G .. highlight:: bash -打开终端,按照快速入门中的指南 :ref:`设置好开发环境 ` ,然后运行如下命令,启动 OpenOCD(该命令在 Windows,Linux,和 macOS 中通用): +打开终端,按照快速入门指南中的 :ref:`设置好开发环境 ` 章节进行操作,然后运行如下命令,以启动 OpenOCD(该命令适用于 Windows、Linux 和 macOS): .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd @@ -156,45 +174,48 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G .. note:: - 上述命令中 ``-f`` 选项后跟的配置文件专用于 |run-openocd-device-name|。您可能需要根据具体使用的硬件而选择或修改不同的配置文件,相关指导请参阅 :ref:`jtag-debugging-tip-openocd-configure-target`。 + 上述命令中 ``-f`` 选项后跟的配置文件专用于 |run-openocd-device-name|。基于具体使用的硬件,您可能需要选择不同的配置文件,具体内容请参阅 :ref:`jtag-debugging-tip-openocd-configure-target`。 + + .. only:: esp32c3 + + 例如,对于带有用于 JTAG 连接的 FT2232H 或 FT232H 芯片的定制板,或带有 ESP-Prog 的定制板,可使用 ``board/esp32c3-ftdi.cfg``。 .. highlight:: none -现在应该可以看到如下输入(此日志来自 |run-openocd-device-name|): +现在您应该可以看到如下输出(此日志来自 |run-openocd-device-name|): .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-output :end-before: --- -- 如果出现指示权限问题的错误,请参阅 ``~/esp/openocd-esp32`` 目录下 OpenOCD README 文件中关于 “Permissions delegation” 的说明。 -- 如果发现配置文件有错误,例如 |run-openocd-cfg-file-err|,请检查 ``-s`` 后面的路径,OpenOCD 会根据此路径来查找 ``-f`` 指定的文件。此外,还需要检查配置文件是否确实位于该路径下。 -- 如果看到 JTAG 错误(输出全是 1 或者全是 0),请检查硬件连接,除了 {IDF_TARGET_NAME} 的引脚之外是否还有其他信号连接到了 JTAG,并查看是否所有器件都已经上电。 - +* 如果出现指示权限问题的错误,请打开 ``~/esp/openocd-esp32`` 目录,参阅 OpenOCD README 文件中关于 “Permissions delegation” 的说明。 +* 如果遇到无法找到配置文件的错误,例如 |run-openocd-cfg-file-err|,请检查 ``OPENOCD_SCRIPTS`` 环境变量是否设置正确,OpenOCD 根据此变量来查找 ``-f`` 指定的文件,详见 :ref:`jtag-debugging-setup-openocd`。此外,还需要检查配置文件是否确实位于该路径下。 +* 如果出现 JTAG 错误(例如输出为 ``...all ones`` 或 ``...all zeroes``),请检查硬件连接是否正确,除了 {IDF_TARGET_NAME} 的管脚之外是否还有其他信号连接到了 JTAG,并查看是否所有器件都已经上电。 .. _jtag-upload-app-debug: 上传待调试的应用程序 ~~~~~~~~~~~~~~~~~~~~ -您可以像往常一样构建并上传 {IDF_TARGET_NAME} 应用程序,具体请参阅 :ref:`get-started-build` 章节。 +按照正常步骤构建并上传 {IDF_TARGET_NAME} 应用程序,具体请参阅 :ref:`get-started-build` 章节。 -除此以外,还支持使用 OpenOCD 通过 JTAG 接口将应用程序镜像烧写到闪存中,命令如下: +除此以外,您还可以使用 OpenOCD 通过 JTAG 接口将应用程序镜像烧写到闪存中,命令如下: .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-upload :end-before: --- -其中 OpenOCD 的烧写命令 ``program_esp`` 具有以下格式: +其中 OpenOCD 的烧写命令 ``program_esp`` 格式如下: ``program_esp [verify] [reset] [exit]`` - - ``image_file`` - 程序镜像文件存放的路径 - - ``offset`` - 镜像烧写到闪存中的偏移地址 - - ``verify`` - 烧写完成后校验闪存中的内容(可选) - - ``reset`` - 烧写完成后重启目标(可选) - - ``exit`` - 烧写完成后退出 OpenOCD(可选) +- ``image_file`` - 程序镜像文件存放的路径 +- ``offset`` - 镜像烧写到闪存中的偏移地址 +- ``verify`` - 烧写完成后校验闪存中的内容(可选) +- ``reset`` - 烧写完成后重启目标(可选) +- ``exit`` - 烧写完成后退出 OpenOCD(可选) -现在可以进行应用程序的调试了,请按照以下章节中讲解的步骤进行操作。 +现在可以调试应用程序了,请按照以下章节中的步骤进行操作。 .. _jtag-debugging-launching-debugger: @@ -202,14 +223,14 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 启动调试器 ---------- -{IDF_TARGET_NAME} 的工具链中带有 GNU 调试器(简称 GDB) ``{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb``,它和其它工具链软件存放在同一个 bin 目录下。除了直接在命令行终端中调用并操作 GDB 外,还可以在 IDE (例如 Eclipse,Visual Studio Code 等)中调用它,在图形用户界面的帮助下间接操作 GDB,无需在终端中输入任何命令。 +{IDF_TARGET_NAME} 的工具链中带有 GNU 调试器(简称 GDB),它和其它工具链软件共同存放于 {IDF_TARGET_TOOLCHAIN_PREFIX}-gdb 中。除了直接在命令行终端中调用并操作 GDB 外,也可以在 IDE (例如 Eclipse、Visual Studio Code 等)中进行调用,使用图形用户界面间接操作 GDB,这一方法无需在终端中输入任何命令。 关于以上两种调试器的使用方法,详见以下链接。 * :ref:`jtag-debugging-using-debugger-eclipse` * :ref:`jtag-debugging-using-debugger-command-line` -建议首先检查调试器是否能在 :ref:`命令行终端 ` 下正常工作,然后再转到使用 Eclipse 等 :ref:`集成开发环境 ` 下进行调试工作。 +建议首先检查调试器能否在 :ref:`命令行终端 ` 下正常工作,然后再使用 Eclipse :ref:`集成开发环境 ` 进行调试工作。 .. _jtag-debugging-examples: @@ -217,7 +238,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 调试范例 -------- -本节适用于不熟悉 GDB 的用户,将使用 :example:`get-started/blink` 下简单的应用程序来演示 :ref:`调试会话的工作流程 `,同时会介绍以下常用的调试操作: +本节适用于不熟悉 GDB 的用户,下文将使用 :example:`get-started/blink` 下简单的应用程序来演示 :ref:`调试会话的工作流程 `,同时会介绍以下常用的调试操作: 1. :ref:`jtag-debugging-examples-eclipse-01` 2. :ref:`jtag-debugging-examples-eclipse-02` @@ -227,9 +248,9 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 6. :ref:`jtag-debugging-examples-eclipse-06` 7. :ref:`jtag-debugging-examples-eclipse-07` -此外还会提供 :ref:`在命令行终端进行调试 ` 的案例。 +此外还会提供在 :ref:`在命令行终端进行调试 ` 下使用 GDB 调试的案例。 -在演示之前,请设置好 {IDF_TARGET_NAME} 目标板并加载 :example:`get-started/blink` 至 {IDF_TARGET_NAME} 中。 +在演示之前,请完成 {IDF_TARGET_NAME} 目标板设置并加载 :example:`get-started/blink` 至 {IDF_TARGET_NAME} 中。 .. _jtag-debugging-building-openocd: @@ -237,18 +258,18 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 从源码构建 OpenOCD ------------------ -请参阅以下文档,它们分别介绍了在各大操作系统平台上从源码构建 OpenOCD 的流程。 +以下文档分别介绍了如何在各操作系统平台上从源码构建 OpenOCD。 .. toctree:: :maxdepth: 1 Windows Linux - MacOS + macOS -本文档演示所使用的 OpenOCD 是 :ref:`jtag-debugging-setup-openocd` 章节中介绍的预编译好的二进制发行版。 +本文档在演示中所使用的 OpenOCD 是预编译好的二进制发行版,在 :ref:`jtag-debugging-setup-openocd` 章节中有所介绍。 -如果要使用本地从源代码编译的 OpenOCD 程序,需要将相应可执行文件的路径修改为 ``src/openocd``,并设置 ``OPENOCD_SCRIPTS`` 环境变量,这样 OpenOCD 才能找到配置文件。Linux 和 macOS 用户可以执行: +如果要使用本地从源代码编译的 OpenOCD 程序,需要将相应可执行文件的路径修改为 ``src/openocd``,并设置 ``OPENOCD_SCRIPTS`` 环境变量,使得 OpenOCD 能够找到配置文件。Linux 和 macOS 用户可以执行: .. code-block:: bash @@ -262,13 +283,13 @@ Windows 用户可以执行: cd %USERPROFILE%\esp\openocd-esp32 set "OPENOCD_SCRIPTS=%CD%\tcl" -运行本地编译的 OpenOCD 的示例如下(Linux 和 macOS 用户): +针对 Linux 和 macOS 用户,运行本地编译的 OpenOCD 的示例: .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-src-linux :end-before: --- -Windows 用户: +Windows 用户的示例如下: .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-src-win @@ -279,7 +300,7 @@ Windows 用户: 注意事项和补充内容 -------------------- -本节列出了本指南中提到的所有注意事项和补充内容的链接。 +本节列出了上文中提到的所有注意事项和补充内容的链接。 .. toctree:: :maxdepth: 2 diff --git a/docs/zh_CN/api-reference/system/power_management.rst b/docs/zh_CN/api-reference/system/power_management.rst index 8e770a104b..c3d83a3c87 100644 --- a/docs/zh_CN/api-reference/system/power_management.rst +++ b/docs/zh_CN/api-reference/system/power_management.rst @@ -6,7 +6,7 @@ 概述 -------- -ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,调整外围总线 (APB) 频率、CPU 频率,并使芯片进入 Light-sleep 模式,尽可能减少运行应用程序的功耗。 +ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,调整外围总线 (APB) 频率和 CPU 频率,并使芯片进入 Light-sleep 模式,尽可能减少运行应用程序的功耗。 应用程序组件可以通过创建和获取电源管理锁来控制功耗。 @@ -16,7 +16,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, - RTOS 可以要求 CPU 在有任务准备开始运行时以最高配置频率工作。 - 一些外设可能需要中断才能启用,因此其驱动也会要求禁用 Light-sleep 模式。 -因为请求较高的 APB 频率或 CPU 频率,以及禁用 Light-sleep 模式会增加功耗,请将组件使用的电源管理锁降到最少。 +请求较高的 APB 频率或 CPU 频率以及禁用 Light-sleep 模式会增加功耗,因此请将组件使用的电源管理锁降到最少。 电源管理配置 ------------- @@ -25,20 +25,27 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 启用电源管理功能将会增加中断延迟。额外延迟与多个因素有关,例如:CPU 频率、单/双核模式、是否需要进行频率切换等。CPU 频率为 240 MHz 且未启用频率调节时,最小额外延迟为 0.2 us;如果启用频率调节,且在中断入口将频率由 40 MHz 调节至 80 MHz,则最大额外延迟为 40 us。 -应用程序可以通过调用 :cpp:func:`esp_pm_configure` 函数启用动态调频 (DFS) 功能和自动 Light-sleep 模式。此函数的参数为 :cpp:class:`esp_pm_config_{IDF_TARGET_PATH_NAME}_t`,定义了频率调节的相关设置。在此参数结构中,需要初始化下面三个字段: +通过调用 :cpp:func:`esp_pm_configure` 函数可以在应用程序中启用动态调频 (DFS) 功能和自动 Light-sleep 模式。此函数的参数 :cpp:class:`esp_pm_config_{IDF_TARGET_PATH_NAME}_t` 定义了频率调节的相关设置。在此参数结构中,需要初始化以下三个字段: - ``max_freq_mhz``:最大 CPU 频率 (MHz),即获取 ``ESP_PM_CPU_FREQ_MAX`` 锁后所使用的频率。该字段通常设置为 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ`。 - - ``min_freq_mhz``:最小 CPU 频率 (MHz),即仅获取 ``ESP_PM_APB_FREQ_MAX`` 锁后所使用的频率。该字段可设置为晶振 (XTAL) 频率值,或者 XTAL 频率值除以整数。注意,10 MHz 是生成 1 MHz 的 REF_TICK 默认时钟所需的最小频率。 - - ``light_sleep_enable``:没有获取任何管理锁时,决定系统是否需要自动进入 Light-sleep 状态 (``true``/``false``)。 -或者,如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。 + + 如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。 .. note:: - 1. 自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能,因此如果在 menuconfig 中没有启用 :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` 选项,在请求自动 Light-sleep 时,:cpp:func:`esp_pm_configure` 将会返回 `ESP_ERR_NOT_SUPPORTED` 错误。 - 2. 在 Light-sleep 状态下,外设设有时钟门控,不会产生来自 GPIO 和内部外设的中断。:doc:`sleep_modes` 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。例如,EXT0 和 EXT1 唤醒源就可以通过 GPIO 唤醒芯片。 + 自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能,因此如果在 menuconfig 中没有启用 :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` 选项,在请求自动 Light-sleep 时,:cpp:func:`esp_pm_configure` 将会返回 `ESP_ERR_NOT_SUPPORTED` 错误。 + +.. note:: + + Light-sleep 状态下,外设设有时钟门控,不会产生来自 GPIO 和内部外设的中断。:doc:`sleep_modes` 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。 + +.. only:: SOC_PM_SUPPORT_EXT_WAKEUP + + 例如,EXT0 和 EXT1 唤醒源可以通过 GPIO 唤醒芯片。 + 电源管理锁 ---------------------- @@ -47,24 +54,26 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 电源管理锁设有获取/释放计数器,如果已多次获取电源管理锁,则需要将电源管理锁释放相同次数以解除限制。 -{IDF_TARGET_NAME} 支持下表中所述的三种电源管理锁。 +{IDF_TARGET_NAME} 支持下表中三种电源管理锁。 -============================ ====================================================== -电源管理锁 描述 -============================ ====================================================== -``ESP_PM_CPU_FREQ_MAX`` 请求使用 :cpp:func:`esp_pm_configure` 将 CPU 频率设置为最大值。{IDF_TARGET_NAME} 可以将该值设置为 80 MHz、160 MHz 或 240 MHz。 +.. list-table:: + :header-rows: 1 + :widths: 25 60 -``ESP_PM_APB_FREQ_MAX`` 请求将 APB 频率设置为最大值,{IDF_TARGET_NAME} 支持的最大频率为 80 MHz。 - -``ESP_PM_NO_LIGHT_SLEEP`` 禁止自动切换至 Light-sleep 模式。 -============================ ====================================================== + * - 电源管理锁 + - 描述 + * - ``ESP_PM_CPU_FREQ_MAX`` + - 请求使用 :cpp:func:`esp_pm_configure` 将 CPU 频率设置为最大值。{IDF_TARGET_NAME} 可以将该值设置为 80 MHz、160 MHz 或 240 MHz。 + * - ``ESP_PM_APB_FREQ_MAX`` + - 请求将 APB 频率设置为最大值,{IDF_TARGET_NAME} 支持的最大频率为 80 MHz。 + * - ``ESP_PM_NO_LIGHT_SLEEP`` + - 禁止自动切换至 Light-sleep 模式。 {IDF_TARGET_NAME} 电源管理算法 -------------------------------- 下表列出了启用动态调频时如何切换 CPU 频率和 APB 频率。您可以使用 :cpp:func:`esp_pm_configure` 或者 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ` 指定 CPU 最大频率。 - .. only:: esp32 .. include:: inc/power_management_esp32.rst @@ -73,6 +82,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, .. include:: inc/power_management_esp32s2_and_later.rst + 如果没有获取任何管理锁,调用 :cpp:func:`esp_pm_configure` 将启动 Light-sleep 模式。 Light-sleep 模式持续时间由以下因素决定: - 处于阻塞状态的 FreeRTOS 任务数(有限超时) @@ -80,12 +90,15 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 您也可以设置 Light-sleep 模式在最近事件(任务解除阻塞,或计时器超时)之前持续多久才唤醒芯片。 +为了跳过不必要的唤醒,可以将 `skip_unhandled_events` 选项设置为 true 来初始化 esp_timer。带有此标志的定时器不会唤醒系统,有助于减少功耗。 + + 动态调频和外设驱动 ------------------------------------------------ 启用动态调频后,APB 频率可在一个 RTOS 滴答周期内多次更改。有些外设不受 APB 频率变更的影响,但有些外设可能会出现问题。例如,Timer Group 外设定时器会继续计数,但定时器计数的速度将随 APB 频率的变更而变更。 -下面的外设不受 APB 频率变更的影响: +以下外设不受 APB 频率变更的影响: - **UART**:如果 REF_TICK 用作时钟源,则 UART 不受 APB 频率变更影响。请查看 :cpp:class:`uart_config_t` 中的 `use_ref_tick`。 - **LEDC**:如果 REF_TICK 用作时钟源,则 LEDC 不受 APB 频率变更影响。请查看 :cpp:func:`ledc_timer_config` 函数。 @@ -100,14 +113,14 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 启用以下驱动程序时,将占用 ``ESP_PM_APB_FREQ_MAX`` 锁: - .. list:: - **SPI slave**:从调用 :cpp:func:`spi_slave_initialize` 至 :cpp:func:`spi_slave_free` 期间。 - **Ethernet**:从调用 :cpp:func:`esp_eth_driver_install` 至 :cpp:func:`esp_eth_driver_uninstall` 期间。 - **WiFi**:从调用 :cpp:func:`esp_wifi_start` 至 :cpp:func:`esp_wifi_stop` 期间。如果启用了调制解调器睡眠模式,广播关闭时将释放此管理锁。 - **TWAI**:从调用 :cpp:func:`twai_driver_install` 至 :cpp:func:`twai_driver_uninstall` 期间。 - :SOC_BT_SUPPORTED: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁。 + :SOC_BT_SUPPORTED and esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁,除非将 :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` 选项设置为 “外部 32 kHz 晶振”。 + :SOC_BT_SUPPORTED and esp32c3: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁。 以下外设驱动程序无法感知动态调频,应用程序需自己获取/释放管理锁: @@ -118,7 +131,6 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, - Timer group :esp32: - MCPWM - API 参考 ------------- From a8c7db62be3cedaf3a44c665f8c95fb048f82987 Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Thu, 26 Aug 2021 13:45:51 +0800 Subject: [PATCH 046/310] freertos: cherrypicked code layout changes from freertos upgrade branch --- components/freertos/event_groups.c | 9 +- .../freertos/include/freertos/event_groups.h | 3 +- components/freertos/list.c | 13 +- components/freertos/queue.c | 18 +- components/freertos/stream_buffer.c | 9 +- components/freertos/tasks.c | 1546 +++++++++-------- components/freertos/timers.c | 144 +- 7 files changed, 882 insertions(+), 860 deletions(-) diff --git a/components/freertos/event_groups.c b/components/freertos/event_groups.c index 301cef14d7..34150e490c 100644 --- a/components/freertos/event_groups.c +++ b/components/freertos/event_groups.c @@ -255,7 +255,6 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, } } } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); if( xTicksToWait != ( TickType_t ) 0 ) @@ -266,7 +265,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, * point either the required bits were set or the block time expired. If * the required bits were set they will have been stored in the task's * event list item, and they should now be retrieved then cleared. */ - uxReturn = uxTaskResetEventItemValue(); + uxReturn = uxTaskResetEventItemValue(); if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) { @@ -401,7 +400,6 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); } } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); if( xTicksToWait != ( TickType_t ) 0 ) @@ -538,7 +536,6 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, pxList = &( pxEventBits->xTasksWaitingForBits ); pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); { traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); @@ -619,8 +616,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, void vEventGroupDelete( EventGroupHandle_t xEventGroup ) { - EventGroup_t *pxEventBits = xEventGroup; - const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); + EventGroup_t * pxEventBits = xEventGroup; + const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); traceEVENT_GROUP_DELETE( xEventGroup ); diff --git a/components/freertos/include/freertos/event_groups.h b/components/freertos/include/freertos/event_groups.h index e1049a6c03..c0afb0c552 100644 --- a/components/freertos/include/freertos/event_groups.h +++ b/components/freertos/include/freertos/event_groups.h @@ -84,9 +84,8 @@ * \ingroup EventGroup */ struct EventGroupDef_t; -//typedef struct EventGroupDef_t * EventGroupHandle_t; typedef void * EventGroupHandle_t; - +// typedef struct EventGroupDef_t * EventGroupHandle_t; /* * The type that holds event bits always matches TickType_t - therefore the * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, diff --git a/components/freertos/list.c b/components/freertos/list.c index 47e4d751fb..78a45f75a1 100644 --- a/components/freertos/list.c +++ b/components/freertos/list.c @@ -129,27 +129,24 @@ void vListInsert( List_t * const pxList, { /* *** NOTE *********************************************************** * If you find your application is crashing here then likely causes are - * listed below. In addition see https://www.freertos.org/FAQHelp.html for + * listed below. In addition see https://www.FreeRTOS.org/FAQHelp.html for * more tips, and ensure configASSERT() is defined! - * https://www.freertos.org/a00110.html#configASSERT + * https://www.FreeRTOS.org/a00110.html#configASSERT * * 1) Stack overflow - - * see https://www.freertos.org/Stacks-and-stack-overflow-checking.html + * see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html * 2) Incorrect interrupt priority assignment, especially on Cortex-M * parts where numerically high priority values denote low actual * interrupt priorities, which can seem counter intuitive. See - * https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition * of configMAX_SYSCALL_INTERRUPT_PRIORITY on - * https://www.freertos.org/a00110.html + * https://www.FreeRTOS.org/a00110.html * 3) Calling an API function from within a critical section or when * the scheduler is suspended, or calling an API function that does * not end in "FromISR" from an interrupt. * 4) Using a queue or semaphore before it has been initialised or * before the scheduler has been started (are interrupts firing * before vTaskStartScheduler() has been called?). - * 5) If the FreeRTOS port supports interrupt nesting then ensure that - * the priority of the tick interrupt is at or below - * configMAX_SYSCALL_INTERRUPT_PRIORITY. **********************************************************************/ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ diff --git a/components/freertos/queue.c b/components/freertos/queue.c index f013eec49e..97b32f4611 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -92,7 +92,7 @@ typedef struct SemaphoreData /* * Definition of the queue used by the scheduler. * Items are queued by copy, not reference. See the following link for the - * rationale: https://www.freertos.org/Embedded-RTOS-Queues.html + * rationale: https://www.FreeRTOS.org/Embedded-RTOS-Queues.html */ typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { @@ -333,7 +333,7 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, StaticQueue_t * pxStaticQueue, const uint8_t ucQueueType ) { - Queue_t * pxNewQueue; + Queue_t * pxNewQueue; configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); @@ -416,7 +416,7 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) ); /* Check for addition overflow. */ - configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes ); + configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes ); /* Allocate the queue and storage area. Justification for MISRA * deviation as follows: pvPortMalloc() always ensures returned memory @@ -969,7 +969,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); /* Unlocking the queue means queue events can effect the - * event list. It is possible that interrupts occurring now + * event list. It is possible that interrupts occurring now * remove this task from the event list again - but as the * scheduler is suspended the task will go onto the pending * ready list instead of the actual ready list. */ @@ -1030,7 +1030,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, * system call interrupt priority. FreeRTOS maintains a separate interrupt * safe API to ensure interrupt entry is as fast and as simple as possible. * More information (albeit Cortex-M specific) is provided on the following - * link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); /* Similar to xQueueGenericSend, except without blocking if there is no room @@ -1199,7 +1199,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, * system call interrupt priority. FreeRTOS maintains a separate interrupt * safe API to ensure interrupt entry is as fast and as simple as possible. * More information (albeit Cortex-M specific) is provided on the following - * link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); @@ -1847,7 +1847,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, * system call interrupt priority. FreeRTOS maintains a separate interrupt * safe API to ensure interrupt entry is as fast and as simple as possible. * More information (albeit Cortex-M specific) is provided on the following - * link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); @@ -1944,7 +1944,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, * system call interrupt priority. FreeRTOS maintains a separate interrupt * safe API to ensure interrupt entry is as fast and as simple as possible. * More information (albeit Cortex-M specific) is provided on the following - * link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); @@ -2346,7 +2346,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) } /*-----------------------------------------------------------*/ -static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) +static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) { BaseType_t xReturn; Queue_t * pxQ = (Queue_t *)pxQueue; diff --git a/components/freertos/stream_buffer.c b/components/freertos/stream_buffer.c index af807255a4..41950d017f 100644 --- a/components/freertos/stream_buffer.c +++ b/components/freertos/stream_buffer.c @@ -109,7 +109,7 @@ #ifndef sbSEND_COMPLETE_FROM_ISR #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ { \ - UBaseType_t uxSavedInterruptStatus; \ + UBaseType_t uxSavedInterruptStatus; \ \ uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ { \ @@ -166,7 +166,7 @@ static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PR * no data is written into the buffer). */ static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, - const uint8_t *pucData, + const uint8_t * pucData, size_t xCount ) PRIVILEGED_FUNCTION; /* @@ -269,6 +269,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, pucAllocatedMemory = NULL; } + if( pucAllocatedMemory != NULL ) { prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */ @@ -711,7 +712,7 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, if( xShouldWrite != pdFALSE ) { /* Writes the data itself. */ - xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alighment and access. */ + xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alignment and access. */ } else { @@ -1118,7 +1119,7 @@ static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, /* Write as many bytes as can be written in the first write. */ configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength ); - ( void ) memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + ( void ) memcpy( ( void * ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */ /* If the number of bytes written was less than the number that could be * written in the first write... */ diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index b6d99836e5..a32e517c83 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -638,7 +638,7 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pvTaskCode, const char * const pcName, @@ -671,16 +671,16 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) if( ( pxTaskBuffer != NULL ) && ( pxStackBuffer != NULL ) ) { /* The memory used for the task's TCB and stack are passed into this - function - use them. */ + * function - use them. */ pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ pxNewTCB->pxStack = ( StackType_t * ) pxStackBuffer; - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ - { - /* Tasks can be created statically or dynamically, so note this - task was created statically in case the task is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; - } + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ + { + /* Tasks can be created statically or dynamically, so note this + * task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ prvInitialiseNewTask( pvTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL, xCoreID ); @@ -697,12 +697,13 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) #endif /* SUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) + BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) { - TCB_t *pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + TCB_t * pxNewTCB; + BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; configASSERT( pxTaskDefinition->puxStackBuffer != NULL ); configASSERT( pxTaskDefinition->pxTaskBuffer != NULL ); @@ -710,29 +711,29 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) ) { /* Allocate space for the TCB. Where the memory comes from depends - on the implementation of the port malloc function and whether or - not static allocation is being used. */ + * on the implementation of the port malloc function and whether or + * not static allocation is being used. */ pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer; /* Store the stack location in the TCB. */ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) - { - /* Tasks can be created statically or dynamically, so note this - task was created statically in case the task is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; - } + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note this + * task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, - pxTaskDefinition->pcName, - ( uint32_t ) pxTaskDefinition->usStackDepth, - pxTaskDefinition->pvParameters, - pxTaskDefinition->uxPriority, - pxCreatedTask, pxNewTCB, - pxTaskDefinition->xRegions, - tskNO_AFFINITY ); + prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, + pxTaskDefinition->pcName, + ( uint32_t ) pxTaskDefinition->usStackDepth, + pxTaskDefinition->pvParameters, + pxTaskDefinition->uxPriority, + pxCreatedTask, pxNewTCB, + pxTaskDefinition->xRegions, + tskNO_AFFINITY ); prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY); xReturn = pdPASS; @@ -744,20 +745,20 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) #endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*-----------------------------------------------------------*/ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) { - TCB_t *pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + TCB_t * pxNewTCB; + BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; configASSERT( pxTaskDefinition->puxStackBuffer ); if( pxTaskDefinition->puxStackBuffer != NULL ) { /* Allocate space for the TCB. Where the memory comes from depends - on the implementation of the port malloc function and whether or - not static allocation is being used. */ + * on the implementation of the port malloc function and whether or + * not static allocation is being used. */ pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); if( pxNewTCB != NULL ) @@ -765,23 +766,23 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) /* Store the stack location in the TCB. */ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) - { - /* Tasks can be created statically or dynamically, so note - this task had a statically allocated stack in case it is - later deleted. The TCB was allocated dynamically. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; - } + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note + * this task had a statically allocated stack in case it is + * later deleted. The TCB was allocated dynamically. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; + } #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, - pxTaskDefinition->pcName, - ( uint32_t ) pxTaskDefinition->usStackDepth, - pxTaskDefinition->pvParameters, - pxTaskDefinition->uxPriority, - pxCreatedTask, pxNewTCB, - pxTaskDefinition->xRegions, - tskNO_AFFINITY ); + prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, + pxTaskDefinition->pcName, + ( uint32_t ) pxTaskDefinition->usStackDepth, + pxTaskDefinition->pvParameters, + pxTaskDefinition->uxPriority, + pxCreatedTask, pxNewTCB, + pxTaskDefinition->xRegions, + tskNO_AFFINITY ); prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY); xReturn = pdPASS; @@ -794,7 +795,7 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) #endif /* portUSING_MPU_WRAPPERS */ /*-----------------------------------------------------------*/ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, const char * const pcName, @@ -804,73 +805,73 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) TaskHandle_t * const pvCreatedTask, const BaseType_t xCoreID) { - TCB_t *pxNewTCB; - BaseType_t xReturn; + TCB_t * pxNewTCB; + BaseType_t xReturn; /* If the stack grows down then allocate the stack then the TCB so the stack - does not grow into the TCB. Likewise if the stack grows up then allocate - the TCB then the stack. */ - #if( portSTACK_GROWTH > 0 ) - { - /* Allocate space for the TCB. Where the memory comes from depends on - the implementation of the port malloc function and whether or not static - allocation is being used. */ + * does not grow into the TCB. Likewise if the stack grows up then allocate + * the TCB then the stack. */ + #if ( portSTACK_GROWTH > 0 ) + { + /* Allocate space for the TCB. Where the memory comes from depends on + * the implementation of the port malloc function and whether or not static + * allocation is being used. */ pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); - if( pxNewTCB != NULL ) - { - /* Allocate space for the stack used by the task being created. - The base of the stack memory stored in the TCB so the task can - be deleted later if required. */ - pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - - if( pxNewTCB->pxStack == NULL ) - { - /* Could not allocate the stack. Delete the allocated TCB. */ - vPortFree( pxNewTCB ); - pxNewTCB = NULL; - } - } - } - #else /* portSTACK_GROWTH */ - { - StackType_t *pxStack; - - /* Allocate space for the stack used by the task being created. */ - pxStack = pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */ - - if( pxStack != NULL ) - { - /* Allocate space for the TCB. */ - pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */ - if( pxNewTCB != NULL ) { - /* Store the stack location in the TCB. */ - pxNewTCB->pxStack = pxStack; + /* Allocate space for the stack used by the task being created. + * The base of the stack memory stored in the TCB so the task can + * be deleted later if required. */ + pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + } + } + #else /* portSTACK_GROWTH */ + { + StackType_t * pxStack; + + /* Allocate space for the stack used by the task being created. */ + pxStack = pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */ + + if( pxStack != NULL ) + { + /* Allocate space for the TCB. */ + pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */ + + if( pxNewTCB != NULL ) + { + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxStack; + } + else + { + /* The stack cannot be used as the TCB was not created. Free + * it again. */ + vPortFree( pxStack ); + } } else { - /* The stack cannot be used as the TCB was not created. Free - it again. */ - vPortFree( pxStack ); + pxNewTCB = NULL; } } - else - { - pxNewTCB = NULL; - } - } #endif /* portSTACK_GROWTH */ if( pxNewTCB != NULL ) { - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */ - { - /* Tasks can be created statically or dynamically, so note this - task was created dynamically in case it is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; - } + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */ + { + /* Tasks can be created statically or dynamically, so note this + * task was created dynamically in case it is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; + } #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ prvInitialiseNewTask( pvTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pvCreatedTask, pxNewTCB, NULL, xCoreID ); @@ -894,20 +895,21 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, - TCB_t *pxNewTCB, + TCB_t * pxNewTCB, const MemoryRegion_t * const xRegions, BaseType_t xCoreID ) { -StackType_t *pxTopOfStack; -UBaseType_t x; + StackType_t * pxTopOfStack; + UBaseType_t x; #if (portNUM_PROCESSORS < 2) xCoreID = 0; #endif - #if( portUSING_MPU_WRAPPERS == 1 ) + #if ( portUSING_MPU_WRAPPERS == 1 ) /* Should the task be created in privileged mode? */ BaseType_t xRunPrivileged; + if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) { xRunPrivileged = pdTRUE; @@ -920,11 +922,11 @@ UBaseType_t x; #endif /* portUSING_MPU_WRAPPERS == 1 */ /* Avoid dependency on memset() if it is not required. */ - #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 ) - { - /* Fill the stack with a known value to assist debugging. */ - ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); - } + #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 ) + { + /* Fill the stack with a known value to assist debugging. */ + ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); + } #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */ #if( configUSE_TRACE_FACILITY == 1 ) @@ -935,36 +937,36 @@ UBaseType_t x; #endif /* ( configUSE_TRACE_FACILITY == 1 ) */ /* Calculate the top of stack address. This depends on whether the stack - grows from high memory to low (as per the 80x86) or vice versa. - portSTACK_GROWTH is used to make the result positive or negative as required - by the port. */ - #if( portSTACK_GROWTH < 0 ) - { - pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] ); - pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */ - - /* Check the alignment of the calculated top of stack is correct. */ - configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - - #if( configRECORD_STACK_HIGH_ADDRESS == 1 ) + * grows from high memory to low (as per the 80x86) or vice versa. + * portSTACK_GROWTH is used to make the result positive or negative as required + * by the port. */ + #if ( portSTACK_GROWTH < 0 ) { - /* Also record the stack's high address, which may assist - debugging. */ - pxNewTCB->pxEndOfStack = pxTopOfStack; + pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] ); + pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */ + + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + #if ( configRECORD_STACK_HIGH_ADDRESS == 1 ) + { + /* Also record the stack's high address, which may assist + * debugging. */ + pxNewTCB->pxEndOfStack = pxTopOfStack; + } + #endif /* configRECORD_STACK_HIGH_ADDRESS */ } - #endif /* configRECORD_STACK_HIGH_ADDRESS */ - } #else /* portSTACK_GROWTH */ - { - pxTopOfStack = pxNewTCB->pxStack; + { + pxTopOfStack = pxNewTCB->pxStack; - /* Check the alignment of the stack buffer is correct. */ - configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + /* Check the alignment of the stack buffer is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - /* The other extreme of the stack space is required if stack checking is - performed. */ - pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); - } + /* The other extreme of the stack space is required if stack checking is + * performed. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); + } #endif /* portSTACK_GROWTH */ /* Store the task name in the TCB. */ @@ -975,8 +977,8 @@ UBaseType_t x; pxNewTCB->pcTaskName[ x ] = pcName[ x ]; /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than - configMAX_TASK_NAME_LEN characters just in case the memory after the - string is not accessible (extremely unlikely). */ + * configMAX_TASK_NAME_LEN characters just in case the memory after the + * string is not accessible (extremely unlikely). */ if( pcName[ x ] == ( char ) 0x00 ) { break; @@ -988,18 +990,18 @@ UBaseType_t x; } /* Ensure the name string is terminated in the case that the string length - was greater or equal to configMAX_TASK_NAME_LEN. */ + * was greater or equal to configMAX_TASK_NAME_LEN. */ pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; } else { /* The task has not been given a name, so just ensure there is a NULL - terminator when it is read out. */ + * terminator when it is read out. */ pxNewTCB->pcTaskName[ 0 ] = 0x00; } /* This is used as an array index so must ensure it's not too large. First - remove the privilege bit if one is present. */ + * remove the privilege bit if one is present. */ if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) { uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; @@ -1012,17 +1014,17 @@ UBaseType_t x; pxNewTCB->uxPriority = uxPriority; pxNewTCB->xCoreID = xCoreID; #if ( configUSE_MUTEXES == 1 ) - { - pxNewTCB->uxBasePriority = uxPriority; - pxNewTCB->uxMutexesHeld = 0; - } + { + pxNewTCB->uxBasePriority = uxPriority; + pxNewTCB->uxMutexesHeld = 0; + } #endif /* configUSE_MUTEXES */ vListInitialiseItem( &( pxNewTCB->xStateListItem ) ); vListInitialiseItem( &( pxNewTCB->xEventListItem ) ); /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get - back to the containing TCB from a generic item in a list. */ + * back to the containing TCB from a generic item in a list. */ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB ); /* Event lists are always in priority order. */ @@ -1030,9 +1032,9 @@ UBaseType_t x; listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB ); #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - { - pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U; - } + { + pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U; + } #endif /* portCRITICAL_NESTING_IN_TCB */ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) @@ -1058,7 +1060,7 @@ UBaseType_t x; } #endif - #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) { for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) { @@ -1214,7 +1216,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, if( pxCurrentTCB[xCoreID] == NULL ) { /* There are no other tasks, or all the other tasks are in - the suspended state - make this the current task. */ + * the suspended state - make this the current task. */ pxCurrentTCB[xCoreID] = pxNewTCB; if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) @@ -1254,10 +1256,10 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, uxTaskNumber++; #if ( configUSE_TRACE_FACILITY == 1 ) - { - /* Add a counter into the TCB for tracing only. */ - pxNewTCB->uxTCBNumber = uxTaskNumber; - } + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } #endif /* configUSE_TRACE_FACILITY */ traceTASK_CREATE( pxNewTCB ); @@ -1270,7 +1272,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, if( xSchedulerRunning != pdFALSE ) { /* If the created task is of a higher priority than the current task - then it should run now. */ + * then it should run now. */ taskENTER_CRITICAL(&xTaskQueueMutex); curTCB = pxCurrentTCB[ xCoreID ]; @@ -1301,10 +1303,10 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, void vTaskDelete( TaskHandle_t xTaskToDelete ) { - TCB_t *pxTCB; - TCB_t *curTCB; - BaseType_t core; - BaseType_t xFreeNow = 0; + TCB_t * pxTCB; + TCB_t * curTCB; + BaseType_t core; + BaseType_t xFreeNow = 0; taskENTER_CRITICAL( &xTaskQueueMutex ); { @@ -1312,7 +1314,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, curTCB = pxCurrentTCB[core]; /* If null is passed in here then it is the calling task that is - being deleted. */ + * being deleted. */ pxTCB = prvGetTCBFromHandle( xTaskToDelete ); /* Remove task from the ready/delayed list. */ @@ -1336,9 +1338,9 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, } /* Increment the uxTaskNumber also so kernel aware debuggers can - detect that the task lists need re-generating. This is done before - portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will - not return. */ + * detect that the task lists need re-generating. This is done before + * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will + * not return. */ uxTaskNumber++; if( pxTCB == curTCB || @@ -1388,7 +1390,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, xFreeNow = pdTRUE; /* Reset the next expected unblock time in case it referred to - the task that has just been deleted. */ + * the task that has just been deleted. */ prvResetNextTaskUnblockTime(); } @@ -1426,7 +1428,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, #if ( INCLUDE_vTaskDelayUntil == 1 ) void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) + const TickType_t xTimeIncrement ) { TickType_t xTimeToWake; BaseType_t xShouldDelay = pdFALSE; @@ -1535,13 +1537,13 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, #endif /* INCLUDE_vTaskDelay */ /*-----------------------------------------------------------*/ -#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) ) +#if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) ) eTaskState eTaskGetState( TaskHandle_t xTask ) { - eTaskState eReturn; - List_t const * pxStateList, *pxDelayedList, *pxOverflowedDelayedList; - const TCB_t * const pxTCB = xTask; + eTaskState eReturn; + List_t const * pxStateList, * pxDelayedList, * pxOverflowedDelayedList; + const TCB_t * const pxTCB = xTask; configASSERT( pxTCB ); @@ -1567,7 +1569,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) ) { /* The task being queried is referenced from one of the Blocked - lists. */ + * lists. */ eReturn = eBlocked; } @@ -1658,11 +1660,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) { - TCB_t const *pxTCB; + TCB_t const * pxTCB; UBaseType_t uxReturn; /* RTOS ports that support interrupt nesting have the concept of a - * maximum system call (or maximum API call) interrupt priority. + * maximum system call (or maximum API call) interrupt priority. * Interrupts that are above the maximum system call priority are keep * permanently enabled, even when the RTOS kernel is in a critical section, * but cannot make any calls to FreeRTOS API functions. If configASSERT() @@ -1676,7 +1678,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * separate interrupt safe API to ensure interrupt entry is as fast and as * simple as possible. More information (albeit Cortex-M specific) is * provided on the following link: - * https://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portENTER_CRITICAL_ISR(&xTaskQueueMutex ); @@ -1802,26 +1804,26 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, uxPriorityUsedOnEntry = pxTCB->uxPriority; #if ( configUSE_MUTEXES == 1 ) - { - /* Only change the priority being used if the task is not - * currently using an inherited priority. */ - if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + /* Only change the priority being used if the task is not + * currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else /* if ( configUSE_MUTEXES == 1 ) */ { pxTCB->uxPriority = uxNewPriority; } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* The base priority gets set whatever. */ - pxTCB->uxBasePriority = uxNewPriority; - } - #else - { - pxTCB->uxPriority = uxNewPriority; - } - #endif + #endif /* if ( configUSE_MUTEXES == 1 ) */ /* Only reset the event list item value if the value is not * being used for anything else. */ @@ -1854,6 +1856,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, { mtCOVERAGE_TEST_MARKER(); } + prvAddTaskToReadyList( pxTCB ); } else @@ -1885,8 +1888,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, void vTaskSuspend( TaskHandle_t xTaskToSuspend ) { - TCB_t *pxTCB; - TCB_t *curTCB; + TCB_t * pxTCB; + TCB_t * curTCB; taskENTER_CRITICAL( &xTaskQueueMutex ); { @@ -2063,39 +2066,41 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, taskENTER_CRITICAL( &xTaskQueueMutex ); /* The parameter cannot be NULL as it is impossible to resume the - currently executing task. */ + * currently executing task. */ if( ( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) && ( pxTCB != NULL ) ) { - if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) { - traceTASK_RESUME( pxTCB ); - - /* The ready list can be accessed even if the scheduler is - * suspended because this is inside a critical section. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxTCB ); - - /* We may have just resumed a higher priority task. */ - if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) { - /* This yield may not cause the task just resumed to run, - * but will leave the lists in the correct state for the - * next yield. */ - taskYIELD_IF_USING_PREEMPTION(); - } - else if( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); + traceTASK_RESUME( pxTCB ); + + /* The ready list can be accessed even if the scheduler is + * suspended because this is inside a critical section. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* We may have just resumed a higher priority task. */ + if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* This yield may not cause the task just resumed to run, + * but will leave the lists in the correct state for the + * next yield. */ + taskYIELD_IF_USING_PREEMPTION(); + } + else if( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { mtCOVERAGE_TEST_MARKER(); } } - else - { - mtCOVERAGE_TEST_MARKER(); - } } else { @@ -2118,7 +2123,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, configASSERT( xTaskToResume ); /* RTOS ports that support interrupt nesting have the concept of a - * maximum system call (or maximum API call) interrupt priority. + * maximum system call (or maximum API call) interrupt priority. * Interrupts that are above the maximum system call priority are keep * permanently enabled, even when the RTOS kernel is in a critical section, * but cannot make any calls to FreeRTOS API functions. If configASSERT() @@ -2132,7 +2137,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * separate interrupt safe API to ensure interrupt entry is as fast and as * simple as possible. More information (albeit Cortex-M specific) is * provided on the following link: - * https://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ //portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); taskENTER_CRITICAL_ISR(&xTaskQueueMutex); @@ -2187,7 +2192,7 @@ void vTaskStartScheduler( void ) { BaseType_t xReturn; - #if( configSUPPORT_STATIC_ALLOCATION == 1 && configSUPPORT_STATIC_ALLOCATION == 0 ) + #if ( configSUPPORT_STATIC_ALLOCATION == 1 && configSUPPORT_STATIC_ALLOCATION == 0 ) StaticTask_t *pxIdleTaskTCBBuffer[portNUM_PROCESSORS] = {NULL}; StackType_t *pxIdleTaskStackBuffer[portNUM_PROCESSORS] = {NULL}; uint32_t ulIdleTaskStackSize; @@ -2219,7 +2224,7 @@ void vTaskStartScheduler( void ) xReturn = pdFAIL; } } - #else + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ { /* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreatePinnedToCore( prvIdleTask, @@ -2239,20 +2244,20 @@ void vTaskStartScheduler( void ) xReturn = pdFAIL; } } - #endif /* configSUPPORT_STATIC_ALLOCATION */ + #endif /* configSUPPORT_STATIC_ALLOCATION */ } #if ( configUSE_TIMERS == 1 ) - { - if( xReturn == pdPASS ) { - xReturn = xTimerCreateTimerTask(); + if( xReturn == pdPASS ) + { + xReturn = xTimerCreateTimerTask(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } #endif /* configUSE_TIMERS */ if( xReturn == pdPASS ) @@ -2584,7 +2589,7 @@ TickType_t xTaskGetTickCountFromISR( void ) * system call interrupt priority. FreeRTOS maintains a separate interrupt * safe API to ensure interrupt entry is as fast and as simple as possible. * More information (albeit Cortex-M specific) is provided on the following - * link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR(); @@ -2931,8 +2936,8 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) #if ( configUSE_PREEMPTION == 1 ) { /* Preemption is on, but a context switch should only be - * performed if the unblocked task has a priority that is - * equal to or higher than the currently executing task. */ + * performed if the unblocked task has a priority that is + * equal to or higher than the currently executing task. */ if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* Pend the yield to be performed when the scheduler @@ -2988,18 +2993,18 @@ BaseType_t xTaskIncrementTick( void ) } /* Called by the portable layer each time a tick interrupt occurs. - Increments the tick then checks to see if the new tick value will cause any - tasks to be unblocked. */ + * Increments the tick then checks to see if the new tick value will cause any + * tasks to be unblocked. */ traceTASK_INCREMENT_TICK( xTickCount ); if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) { taskENTER_CRITICAL_ISR( &xTaskQueueMutex ); /* Minor optimisation. The tick count cannot change in this - block. */ + * block. */ const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; /* Increment the RTOS tick, switching the delayed and overflowed - delayed lists if it wraps to 0. */ + * delayed lists if it wraps to 0. */ xTickCount = xConstTickCount; if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */ @@ -3139,7 +3144,7 @@ BaseType_t xTaskIncrementTick( void ) TCB_t *xTCB; /* If xTask is NULL then it is the task hook of the calling task that is - getting set. */ + * getting set. */ if( xTask == NULL ) { xTCB = ( TCB_t * ) pxCurrentTCB[xPortGetCoreID()]; @@ -3150,7 +3155,7 @@ BaseType_t xTaskIncrementTick( void ) } /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ + * the value can be accessed from an interrupt. */ taskENTER_CRITICAL( &xTaskQueueMutex ); { xTCB->pxTaskTag = pxHookFunction; @@ -3165,14 +3170,14 @@ BaseType_t xTaskIncrementTick( void ) TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) { - TCB_t *pxTCB; - TaskHookFunction_t xReturn; + TCB_t * pxTCB; + TaskHookFunction_t xReturn; /* If xTask is NULL then set the calling task's hook. */ pxTCB = prvGetTCBFromHandle( xTask ); /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ + * the value can be accessed from an interrupt. */ taskENTER_CRITICAL( &xTaskQueueMutex ); { xReturn = pxTCB->pxTaskTag; @@ -3189,15 +3194,15 @@ BaseType_t xTaskIncrementTick( void ) TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) { - TCB_t *pxTCB; - TaskHookFunction_t xReturn; - UBaseType_t uxSavedInterruptStatus; + TCB_t * pxTCB; + TaskHookFunction_t xReturn; + UBaseType_t uxSavedInterruptStatus; /* If xTask is NULL then set the calling task's hook. */ pxTCB = prvGetTCBFromHandle( xTask ); /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ + * the value can be accessed from an interrupt. */ portENTER_CRITICAL_ISR(&xTaskQueueMutex); { xReturn = pxTCB->pxTaskTag; @@ -3214,8 +3219,8 @@ BaseType_t xTaskIncrementTick( void ) BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) { - TCB_t *xTCB; - BaseType_t xReturn; + TCB_t * xTCB; + BaseType_t xReturn; /* If xTask is NULL then we are calling our own task hook. */ if( xTask == NULL ) @@ -3251,7 +3256,7 @@ void vTaskSwitchContext( void ) if( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) { /* The scheduler is currently suspended - do not allow a context - switch. */ + * switch. */ xYieldPending[ xPortGetCoreID() ] = pdTRUE; } else @@ -3261,7 +3266,7 @@ void vTaskSwitchContext( void ) traceTASK_SWITCHED_OUT(); #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { + { #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); #else @@ -3269,12 +3274,12 @@ void vTaskSwitchContext( void ) #endif /* Add the amount of time the task has been running to the - accumulated time so far. The time the task started running was - stored in ulTaskSwitchedInTime. Note that there is no overflow - protection here so count values are only valid until the timer - overflows. The guard against negative values is to protect - against suspect run time stat counter implementations - which - are provided by the application, not the kernel. */ + * accumulated time so far. The time the task started running was + * stored in ulTaskSwitchedInTime. Note that there is no overflow + * protection here so count values are only valid until the timer + * overflows. The guard against negative values is to protect + * against suspect run time stat counter implementations - which + * are provided by the application, not the kernel. */ taskENTER_CRITICAL_ISR(&xTaskQueueMutex); if( ulTotalRunTime > ulTaskSwitchedInTime[ xPortGetCoreID() ] ) { @@ -3286,7 +3291,7 @@ void vTaskSwitchContext( void ) } taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); ulTaskSwitchedInTime[ xPortGetCoreID() ] = ulTotalRunTime; - } + } #endif /* configGENERATE_RUN_TIME_STATS */ /* Check for stack overflow, if configured. */ @@ -3419,12 +3424,12 @@ void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksT taskENTER_CRITICAL(&xTaskQueueMutex); /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ + * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ /* Place the event list item of the TCB in the appropriate event list. - This is placed in the list in priority order so the highest priority task - is the first to be woken by the event. The queue that contains the event - list is locked, preventing simultaneous access from interrupts. */ + * This is placed in the list in priority order so the highest priority task + * is the first to be woken by the event. The queue that contains the event + * list is locked, preventing simultaneous access from interrupts. */ vListInsert( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait); @@ -3438,15 +3443,15 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte taskENTER_CRITICAL(&xTaskQueueMutex); /* Store the item value in the event list item. It is safe to access the - event list item here as interrupts won't access the event list item of a - task that is not in the Blocked state. */ + * event list item here as interrupts won't access the event list item of a + * task that is not in the Blocked state. */ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); /* Place the event list item of the TCB at the end of the appropriate event - list. It is safe to access the event list here because it is part of an - event group implementation - and interrupts don't access event groups - directly (instead they access them indirectly by pending function calls to - the task level). */ + * list. It is safe to access the event list here because it is part of an + * event group implementation - and interrupts don't access event groups + * directly (instead they access them indirectly by pending function calls to + * the task level). */ vListInsertEnd( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); @@ -3454,7 +3459,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte } /*-----------------------------------------------------------*/ -#if( configUSE_TIMERS == 1 ) +#if ( configUSE_TIMERS == 1 ) void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { @@ -3462,20 +3467,20 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte configASSERT( pxEventList ); /* This function should not be called by application code hence the - 'Restricted' in its name. It is not part of the public API. It is - designed for use by kernel code, and has special calling requirements - - it should be called with the scheduler suspended. */ + * 'Restricted' in its name. It is not part of the public API. It is + * designed for use by kernel code, and has special calling requirements - + * it should be called with the scheduler suspended. */ /* Place the event list item of the TCB in the appropriate event list. - In this case it is assume that this is the only task that is going to - be waiting on this event list, so the faster vListInsertEnd() function - can be used in place of vListInsert. */ + * In this case it is assume that this is the only task that is going to + * be waiting on this event list, so the faster vListInsertEnd() function + * can be used in place of vListInsert. */ vListInsertEnd( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); /* If the task should block indefinitely then set the block time to a - value that will be recognised as an indefinite delay inside the - prvAddCurrentTaskToDelayedList() function. */ + * value that will be recognised as an indefinite delay inside the + * prvAddCurrentTaskToDelayedList() function. */ if( xWaitIndefinitely != pdFALSE ) { xTicksToWait = portMAX_DELAY; @@ -3491,25 +3496,25 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) { -TCB_t *pxUnblockedTCB; -BaseType_t xReturn; -BaseType_t xTaskCanBeReady; -UBaseType_t i, uxTargetCPU; + TCB_t * pxUnblockedTCB; + BaseType_t xReturn; + BaseType_t xTaskCanBeReady; + UBaseType_t i, uxTargetCPU; taskENTER_CRITICAL_ISR(&xTaskQueueMutex); /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be - called from a critical section within an ISR. */ + * called from a critical section within an ISR. */ /* The event list is sorted in priority order, so the first in the list can - be removed as it is known to be the highest priority. Remove the TCB from - the delayed list, and add it to the ready list. - - If an event is for a queue that is locked then this function will never - get called - the lock count on the queue will get modified instead. This - means exclusive access to the event list is guaranteed here. - - This function assumes that a check has already been made to ensure that - pxEventList is not empty. */ + * be removed as it is known to be the highest priority. Remove the TCB from + * the delayed list, and add it to the ready list. + * + * If an event is for a queue that is locked then this function will never + * get called - the lock count on the queue will get modified instead. This + * means exclusive access to the event list is guaranteed here. + * + * This function assumes that a check has already been made to ensure that + * pxEventList is not empty. */ if ( ( listLIST_IS_EMPTY( pxEventList ) ) == pdFALSE ) { pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ @@ -3549,19 +3554,19 @@ UBaseType_t i, uxTargetCPU; else { /* The delayed and ready lists cannot be accessed, so hold this task - pending until the scheduler is resumed on this CPU. */ + * pending until the scheduler is resumed on this CPU. */ vListInsertEnd( &( xPendingReadyList[ uxTargetCPU ] ), &( pxUnblockedTCB->xEventListItem ) ); } if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* Return true if the task removed from the event list has a higher - priority than the calling task. This allows the calling task to know if - it should force a context switch now. */ + * priority than the calling task. This allows the calling task to know if + * it should force a context switch now. */ xReturn = pdTRUE; /* Mark that a yield is pending in case the user is not using the - "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ xYieldPending[ xPortGetCoreID() ] = pdTRUE; } else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() ) @@ -3595,8 +3600,8 @@ UBaseType_t i, uxTargetCPU; BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) { -TCB_t *pxUnblockedTCB; -BaseType_t xReturn; + TCB_t * pxUnblockedTCB; + BaseType_t xReturn; taskENTER_CRITICAL(&xTaskQueueMutex); @@ -3604,27 +3609,27 @@ BaseType_t xReturn; listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); /* Remove the event list form the event flag. Interrupts do not access - event flags. */ + * event flags. */ pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); configASSERT( pxUnblockedTCB ); ( void ) uxListRemove( pxEventListItem ); /* Remove the task from the delayed list and add it to the ready list. The - scheduler is suspended so interrupts will not be accessing the ready - lists. */ + * scheduler is suspended so interrupts will not be accessing the ready + * lists. */ ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* Return true if the task removed from the event list has - a higher priority than the calling task. This allows - the calling task to know if it should force a context - switch now. */ + * a higher priority than the calling task. This allows + * the calling task to know if it should force a context + * switch now. */ xReturn = pdTRUE; /* Mark that a yield is pending in case the user is not using the - "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ xYieldPending[ xPortGetCoreID() ] = pdTRUE; } else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() ) @@ -3664,7 +3669,7 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) { -BaseType_t xReturn; + BaseType_t xReturn; configASSERT( pxTimeOut ); configASSERT( pxTicksToWait ); @@ -3675,11 +3680,11 @@ BaseType_t xReturn; const TickType_t xConstTickCount = xTickCount; const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering; - #if( INCLUDE_xTaskAbortDelay == 1 ) + #if ( INCLUDE_xTaskAbortDelay == 1 ) if( pxCurrentTCB[xPortGetCoreID()]->ucDelayAborted != ( uint8_t ) pdFALSE ) { /* The delay was aborted, which is not the same as a time out, - but has the same result. */ + * but has the same result. */ pxCurrentTCB[xPortGetCoreID()]->ucDelayAborted = pdFALSE; xReturn = pdTRUE; } @@ -3690,8 +3695,8 @@ BaseType_t xReturn; if( *pxTicksToWait == portMAX_DELAY ) { /* If INCLUDE_vTaskSuspend is set to 1 and the block time - specified is the maximum block time then the task should block - indefinitely, and therefore never time out. */ + * specified is the maximum block time then the task should block + * indefinitely, and therefore never time out. */ xReturn = pdFALSE; } else @@ -3700,10 +3705,10 @@ BaseType_t xReturn; if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ { /* The tick count is greater than the time at which - vTaskSetTimeout() was called, but has also overflowed since - vTaskSetTimeOut() was called. It must have wrapped all the way - around and gone past again. This passed since vTaskSetTimeout() - was called. */ + * vTaskSetTimeout() was called, but has also overflowed since + * vTaskSetTimeOut() was called. It must have wrapped all the way + * around and gone past again. This passed since vTaskSetTimeout() + * was called. */ xReturn = pdTRUE; } else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */ @@ -3735,8 +3740,8 @@ void vTaskMissedYield( void ) UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) { - UBaseType_t uxReturn; - TCB_t const *pxTCB; + UBaseType_t uxReturn; + TCB_t const * pxTCB; if( xTask != NULL ) { @@ -3758,7 +3763,7 @@ void vTaskMissedYield( void ) void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) { - TCB_t * pxTCB; + TCB_t * pxTCB; if( xTask != NULL ) { @@ -3786,62 +3791,62 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) ( void ) pvParameters; /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE - SCHEDULER IS STARTED. **/ + * SCHEDULER IS STARTED. **/ /* In case a task that has a secure context deletes itself, in which case - the idle task is responsible for deleting the task's secure context, if - any. */ + * the idle task is responsible for deleting the task's secure context, if + * any. */ portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE ); - for( ;; ) + for( ; ; ) { /* See if any tasks have deleted themselves - if so then the idle task - is responsible for freeing the deleted task's TCB and stack. */ + * is responsible for freeing the deleted task's TCB and stack. */ prvCheckTasksWaitingTermination(); #if ( configUSE_PREEMPTION == 0 ) - { - /* If we are not using preemption we keep forcing a task switch to - see if any other task has become available. If we are using - preemption we don't need to do this as any task becoming available - will automatically get the processor anyway. */ - taskYIELD(); - } + { + /* If we are not using preemption we keep forcing a task switch to + * see if any other task has become available. If we are using + * preemption we don't need to do this as any task becoming available + * will automatically get the processor anyway. */ + taskYIELD(); + } #endif /* configUSE_PREEMPTION */ #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) - { - /* When using preemption tasks of equal priority will be - timesliced. If a task that is sharing the idle priority is ready - to run then the idle task should yield before the end of the - timeslice. - - A critical region is not required here as we are just reading from - the list, and an occasional incorrect value will not matter. If - the ready list at the idle priority contains more than one task - then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) { - taskYIELD(); + /* When using preemption tasks of equal priority will be + * timesliced. If a task that is sharing the idle priority is ready + * to run then the idle task should yield before the end of the + * timeslice. + * + * A critical region is not required here as we are just reading from + * the list, and an occasional incorrect value will not matter. If + * the ready list at the idle priority contains more than one task + * then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) + { + taskYIELD(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ #if ( configUSE_IDLE_HOOK == 1 ) - { - extern void vApplicationIdleHook( void ); + { + extern void vApplicationIdleHook( void ); - /* Call the user defined function from within the idle task. This - allows the application designer to add background functionality - without the overhead of a separate task. - NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, - CALL A FUNCTION THAT MIGHT BLOCK. */ - vApplicationIdleHook(); - } + /* Call the user defined function from within the idle task. This + * allows the application designer to add background functionality + * without the overhead of a separate task. + * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + * CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } #endif /* configUSE_IDLE_HOOK */ #if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 ) { @@ -3851,65 +3856,65 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #endif /* CONFIG_FREERTOS_LEGACY_HOOKS */ /* This conditional compilation should use inequality to 0, not equality - to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when - user defined low power mode implementations require - configUSE_TICKLESS_IDLE to be set to a value other than 1. */ + * to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when + * user defined low power mode implementations require + * configUSE_TICKLESS_IDLE to be set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) - { - TickType_t xExpectedIdleTime; - - /* It is not desirable to suspend then resume the scheduler on - each iteration of the idle task. Therefore, a preliminary - test of the expected idle time is performed without the - scheduler suspended. The result here is not necessarily - valid. */ - xExpectedIdleTime = prvGetExpectedIdleTime(); - - if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { - taskENTER_CRITICAL( &xTaskQueueMutex ); + TickType_t xExpectedIdleTime; + + /* It is not desirable to suspend then resume the scheduler on + * each iteration of the idle task. Therefore, a preliminary + * test of the expected idle time is performed without the + * scheduler suspended. The result here is not necessarily + * valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { - /* Now the scheduler is suspended, the expected idle - time can be sampled again, and this time its value can - be used. */ - configASSERT( xNextTaskUnblockTime >= xTickCount ); - xExpectedIdleTime = prvGetExpectedIdleTime(); - - /* Define the following macro to set xExpectedIdleTime to 0 - if the application does not want - portSUPPRESS_TICKS_AND_SLEEP() to be called. */ - configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime ); - - if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + taskENTER_CRITICAL( &xTaskQueueMutex ); { - traceLOW_POWER_IDLE_BEGIN(); - portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); - traceLOW_POWER_IDLE_END(); - } - else - { - mtCOVERAGE_TEST_MARKER(); + /* Now the scheduler is suspended, the expected idle + * time can be sampled again, and this time its value can + * be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); + + /* Define the following macro to set xExpectedIdleTime to 0 + * if the application does not want + * portSUPPRESS_TICKS_AND_SLEEP() to be called. */ + configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime ); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + traceLOW_POWER_IDLE_BEGIN(); + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + traceLOW_POWER_IDLE_END(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + taskEXIT_CRITICAL( &xTaskQueueMutex ); + } + else + { + mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL( &xTaskQueueMutex ); } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } #endif /* configUSE_TICKLESS_IDLE */ } } /*-----------------------------------------------------------*/ -#if( configUSE_TICKLESS_IDLE != 0 ) +#if ( configUSE_TICKLESS_IDLE != 0 ) eSleepModeStatus eTaskConfirmSleepModeStatus( void ) { - /* The idle task exists in addition to the application tasks. */ - const UBaseType_t uxNonApplicationTasks = 1; - eSleepModeStatus eReturn = eStandardSleep; + /* The idle task exists in addition to the application tasks. */ + const UBaseType_t uxNonApplicationTasks = 1; + eSleepModeStatus eReturn = eStandardSleep; taskEXIT_CRITICAL(&xTaskQueueMutex); if( listCURRENT_LIST_LENGTH( &xPendingReadyList[xPortGetCoreID()] ) != 0 ) @@ -3925,9 +3930,9 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) else { /* If all the tasks are in the suspended list (which might mean they - have an infinite block time rather than actually being suspended) - then it is safe to turn all clocks off and just wait for external - interrupts. */ + * have an infinite block time rather than actually being suspended) + * then it is safe to turn all clocks off and just wait for external + * interrupts. */ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) { eReturn = eNoTasksWaitingTimeout; @@ -3944,6 +3949,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) @@ -3969,9 +3975,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #else - void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, + BaseType_t xIndex, + void * pvValue ) { - TCB_t *pxTCB; + TCB_t * pxTCB; if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { @@ -3988,10 +3996,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) - void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) + void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, + BaseType_t xIndex ) { - void *pvReturn = NULL; - TCB_t *pxTCB; + void * pvReturn = NULL; + TCB_t * pxTCB; if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { @@ -4011,12 +4020,13 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #if ( portUSING_MPU_WRAPPERS == 1 ) - void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) + void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, + const MemoryRegion_t * const xRegions ) { - TCB_t *pxTCB; + TCB_t * pxTCB; /* If null is passed in here then we are modifying the MPU settings of - the calling task. */ + * the calling task. */ pxTCB = prvGetTCBFromHandle( xTaskToModify ); vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); @@ -4027,7 +4037,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) static void prvInitialiseTaskLists( void ) { -UBaseType_t uxPriority; + UBaseType_t uxPriority; for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) { @@ -4046,19 +4056,19 @@ UBaseType_t uxPriority; #endif #if ( INCLUDE_vTaskDelete == 1 ) - { - vListInitialise( &xTasksWaitingTermination ); - } + { + vListInitialise( &xTasksWaitingTermination ); + } #endif /* INCLUDE_vTaskDelete */ #if ( INCLUDE_vTaskSuspend == 1 ) - { - vListInitialise( &xSuspendedTaskList ); - } + { + vListInitialise( &xSuspendedTaskList ); + } #endif /* INCLUDE_vTaskSuspend */ /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList - using list2. */ + * using list2. */ pxDelayedTaskList = &xDelayedTaskList1; pxOverflowDelayedTaskList = &xDelayedTaskList2; } @@ -4066,78 +4076,79 @@ UBaseType_t uxPriority; static void prvCheckTasksWaitingTermination( void ) { - /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/ #if ( INCLUDE_vTaskDelete == 1 ) - { - BaseType_t xListIsEmpty; - BaseType_t core = xPortGetCoreID(); - - /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL( &xTaskQueueMutex ) - being called too often in the idle task. */ - while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) { - TCB_t *pxTCB = NULL; + BaseType_t xListIsEmpty; + BaseType_t core = xPortGetCoreID(); - taskENTER_CRITICAL(&xTaskQueueMutex); + /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL( &xTaskQueueMutex ) + * being called too often in the idle task. */ + while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) { - xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); - if( xListIsEmpty == pdFALSE ) + TCB_t *pxTCB = NULL; + + taskENTER_CRITICAL(&xTaskQueueMutex); { - /* We only want to kill tasks that ran on this core because e.g. _xt_coproc_release needs to - be called on the core the process is pinned on, if any */ - ListItem_t *target = listGET_HEAD_ENTRY(&xTasksWaitingTermination); - for( ; target != listGET_END_MARKER(&xTasksWaitingTermination); target = listGET_NEXT(target) ){ //Walk the list - TCB_t *tgt_tcb = ( TCB_t * )listGET_LIST_ITEM_OWNER(target); - int affinity = tgt_tcb->xCoreID; - //Self deleting tasks are added to Termination List before they switch context. Ensure they aren't still currently running - if( pxCurrentTCB[core] == tgt_tcb || (portNUM_PROCESSORS > 1 && pxCurrentTCB[!core] == tgt_tcb) ){ - continue; //Can't free memory of task that is still running + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + if( xListIsEmpty == pdFALSE ) + { + /* We only want to kill tasks that ran on this core because e.g. _xt_coproc_release needs to + be called on the core the process is pinned on, if any */ + ListItem_t *target = listGET_HEAD_ENTRY(&xTasksWaitingTermination); + for( ; target != listGET_END_MARKER(&xTasksWaitingTermination); target = listGET_NEXT(target) ){ //Walk the list + TCB_t *tgt_tcb = ( TCB_t * )listGET_LIST_ITEM_OWNER(target); + int affinity = tgt_tcb->xCoreID; + //Self deleting tasks are added to Termination List before they switch context. Ensure they aren't still currently running + if( pxCurrentTCB[core] == tgt_tcb || (portNUM_PROCESSORS > 1 && pxCurrentTCB[!core] == tgt_tcb) ){ + continue; //Can't free memory of task that is still running + } + if(affinity == core || affinity == tskNO_AFFINITY){ //Find first item not pinned to other core + pxTCB = tgt_tcb; + break; + } } - if(affinity == core || affinity == tskNO_AFFINITY){ //Find first item not pinned to other core - pxTCB = tgt_tcb; - break; + if(pxTCB != NULL){ + ( void ) uxListRemove( target ); //Remove list item from list + --uxCurrentNumberOfTasks; + --uxDeletedTasksWaitingCleanUp; } } - if(pxTCB != NULL){ - ( void ) uxListRemove( target ); //Remove list item from list - --uxCurrentNumberOfTasks; - --uxDeletedTasksWaitingCleanUp; - } } - } - taskEXIT_CRITICAL(&xTaskQueueMutex); //Need to call deletion callbacks outside critical section + taskEXIT_CRITICAL(&xTaskQueueMutex); //Need to call deletion callbacks outside critical section - if (pxTCB != NULL) { //Call deletion callbacks and free TCB memory - #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - prvDeleteTLS( pxTCB ); - #endif - prvDeleteTCB( pxTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - break; //No TCB found that could be freed by this core, break out of loop + if (pxTCB != NULL) { //Call deletion callbacks and free TCB memory + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + prvDeleteTLS( pxTCB ); + #endif + prvDeleteTCB( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + break; //No TCB found that could be freed by this core, break out of loop + } } } - - } #endif /* INCLUDE_vTaskDelete */ } /*-----------------------------------------------------------*/ -#if( configUSE_TRACE_FACILITY == 1 ) +#if ( configUSE_TRACE_FACILITY == 1 ) - void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) + void vTaskGetInfo( TaskHandle_t xTask, + TaskStatus_t * pxTaskStatus, + BaseType_t xGetFreeStackSpace, + eTaskState eState ) { - TCB_t *pxTCB; + TCB_t * pxTCB; /* xTask is NULL then get the state of the calling task. */ pxTCB = prvGetTCBFromHandle( xTask ); pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB; - pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] ); + pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] ); pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority; pxTaskStatus->pxStackBase = pxTCB->pxStack; pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber; @@ -4147,28 +4158,28 @@ static void prvCheckTasksWaitingTermination( void ) #endif /* configTASKLIST_INCLUDE_COREID */ #if ( configUSE_MUTEXES == 1 ) - { - pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; - } + { + pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; + } #else - { - pxTaskStatus->uxBasePriority = 0; - } + { + pxTaskStatus->uxBasePriority = 0; + } #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; - } + { + pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; + } #else - { - pxTaskStatus->ulRunTimeCounter = 0; - } + { + pxTaskStatus->ulRunTimeCounter = 0; + } #endif /* Obtaining the task state is a little fiddly, so is only done if the - value of eState passed into this function is eInvalid - otherwise the - state is just set to whatever is passed in. */ + * value of eState passed into this function is eInvalid - otherwise the + * state is just set to whatever is passed in. */ if( eState != eInvalid ) { if( pxTCB == pxCurrentTCB[xPortGetCoreID()] ) @@ -4180,22 +4191,22 @@ static void prvCheckTasksWaitingTermination( void ) pxTaskStatus->eCurrentState = eState; #if ( INCLUDE_vTaskSuspend == 1 ) - { - /* If the task is in the suspended list then there is a - chance it is actually just blocked indefinitely - so really - it should be reported as being in the Blocked state. */ - if( eState == eSuspended ) { - taskENTER_CRITICAL( &xTaskQueueMutex ); + /* If the task is in the suspended list then there is a + * chance it is actually just blocked indefinitely - so really + * it should be reported as being in the Blocked state. */ + if( eState == eSuspended ) { - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + taskENTER_CRITICAL( &xTaskQueueMutex ); { - pxTaskStatus->eCurrentState = eBlocked; + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + pxTaskStatus->eCurrentState = eBlocked; + } } - } taskEXIT_CRITICAL( &xTaskQueueMutex ); + } } - } #endif /* INCLUDE_vTaskSuspend */ } } @@ -4205,17 +4216,17 @@ static void prvCheckTasksWaitingTermination( void ) } /* Obtaining the stack space takes some time, so the xGetFreeStackSpace - parameter is provided to allow it to be skipped. */ + * parameter is provided to allow it to be skipped. */ if( xGetFreeStackSpace != pdFALSE ) { #if ( portSTACK_GROWTH > 0 ) - { - pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); - } + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); + } #else - { - pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); - } + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); + } #endif } else @@ -4239,19 +4250,21 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) #if ( configUSE_TRACE_FACILITY == 1 ) - static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) + static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray, + List_t * pxList, + eTaskState eState ) { - configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB; - UBaseType_t uxTask = 0; + configLIST_VOLATILE TCB_t * pxNextTCB, * pxFirstTCB; + UBaseType_t uxTask = 0; if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ /* Populate an TaskStatus_t structure within the - pxTaskStatusArray array for each task that is referenced from - pxList. See the definition of TaskStatus_t in task.h for the - meaning of each TaskStatus_t structure member. */ + * pxTaskStatusArray array for each task that is referenced from + * pxList. See the definition of TaskStatus_t in task.h for the + * meaning of each TaskStatus_t structure member. */ do { listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ @@ -4274,7 +4287,7 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) { - uint32_t ulCount = 0U; + uint32_t ulCount = 0U; while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) { @@ -4292,34 +4305,34 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) - /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the - same except for their return type. Using configSTACK_DEPTH_TYPE allows the - user to determine the return type. It gets around the problem of the value - overflowing on 8-bit types without breaking backward compatibility for - applications that expect an 8-bit return type. */ +/* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the + * same except for their return type. Using configSTACK_DEPTH_TYPE allows the + * user to determine the return type. It gets around the problem of the value + * overflowing on 8-bit types without breaking backward compatibility for + * applications that expect an 8-bit return type. */ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) { - TCB_t *pxTCB; - uint8_t *pucEndOfStack; - configSTACK_DEPTH_TYPE uxReturn; + TCB_t * pxTCB; + uint8_t * pucEndOfStack; + configSTACK_DEPTH_TYPE uxReturn; /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are - the same except for their return type. Using configSTACK_DEPTH_TYPE - allows the user to determine the return type. It gets around the - problem of the value overflowing on 8-bit types without breaking - backward compatibility for applications that expect an 8-bit return - type. */ + * the same except for their return type. Using configSTACK_DEPTH_TYPE + * allows the user to determine the return type. It gets around the + * problem of the value overflowing on 8-bit types without breaking + * backward compatibility for applications that expect an 8-bit return + * type. */ pxTCB = prvGetTCBFromHandle( xTask ); #if portSTACK_GROWTH < 0 - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } #else - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } #endif uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack ); @@ -4334,20 +4347,20 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) { - TCB_t *pxTCB; - uint8_t *pucEndOfStack; - UBaseType_t uxReturn; + TCB_t * pxTCB; + uint8_t * pucEndOfStack; + UBaseType_t uxReturn; pxTCB = prvGetTCBFromHandle( xTask ); #if portSTACK_GROWTH < 0 - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } #else - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } #endif uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); @@ -4374,58 +4387,60 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) #if ( INCLUDE_vTaskDelete == 1 ) - static void prvDeleteTCB( TCB_t *pxTCB ) + static void prvDeleteTCB( TCB_t * pxTCB ) { /* This call is required specifically for the TriCore port. It must be - above the vPortFree() calls. The call is also used by ports/demos that - want to allocate and clean RAM statically. */ + * above the vPortFree() calls. The call is also used by ports/demos that + * want to allocate and clean RAM statically. */ portCLEAN_UP_TCB( pxTCB ); /* Free up the memory allocated by the scheduler for the task. It is up - to the task to free any memory allocated at the application level. */ + * to the task to free any memory allocated at the application level. + * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + * for additional information. */ #if ( configUSE_NEWLIB_REENTRANT == 1 ) - { - _reclaim_reent( &( pxTCB->xNewLib_reent ) ); - } + { + _reclaim_reent( &( pxTCB->xNewLib_reent ) ); + } #endif /* configUSE_NEWLIB_REENTRANT */ #if ( portUSING_MPU_WRAPPERS == 1 ) vPortReleaseTaskMPUSettings( &( pxTCB->xMPUSettings) ); #endif - #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) - { - /* The task can only have been allocated dynamically - free both - the stack and TCB. */ - vPortFree( pxTCB->pxStack ); - vPortFree( pxTCB ); - } - #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ - { - /* The task could have been allocated statically or dynamically, so - check what was statically allocated before trying to free the - memory. */ - if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) + #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) { - /* Both the stack and TCB were allocated dynamically, so both - must be freed. */ + /* The task can only have been allocated dynamically - free both + * the stack and TCB. */ vPortFree( pxTCB->pxStack ); vPortFree( pxTCB ); } - else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ { - /* Only the stack was statically allocated, so the TCB is the - only memory that must be freed. */ - vPortFree( pxTCB ); + /* The task could have been allocated statically or dynamically, so + * check what was statically allocated before trying to free the + * memory. */ + if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) + { + /* Both the stack and TCB were allocated dynamically, so both + * must be freed. */ + vPortFree( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + { + /* Only the stack was statically allocated, so the TCB is the + * only memory that must be freed. */ + vPortFree( pxTCB ); + } + else + { + /* Neither the stack nor the TCB were allocated dynamically, so + * nothing needs to be freed. */ + configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ); + mtCOVERAGE_TEST_MARKER(); + } } - else - { - /* Neither the stack nor the TCB were allocated dynamically, so - nothing needs to be freed. */ - configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ); - mtCOVERAGE_TEST_MARKER(); - } - } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } @@ -4457,17 +4472,17 @@ TCB_t *pxTCB; if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) { /* The new current delayed list is empty. Set xNextTaskUnblockTime to - the maximum possible value so it is extremely unlikely that the - if( xTickCount >= xNextTaskUnblockTime ) test will pass until - there is an item in the delayed list. */ + * the maximum possible value so it is extremely unlikely that the + * if( xTickCount >= xNextTaskUnblockTime ) test will pass until + * there is an item in the delayed list. */ xNextTaskUnblockTime = portMAX_DELAY; } else { /* The new current delayed list is not empty, get the value of - the item at the head of the delayed list. This is the time at - which the task at the head of the delayed list should be removed - from the Blocked state. */ + * the item at the head of the delayed list. This is the time at + * which the task at the head of the delayed list should be removed + * from the Blocked state. */ ( pxTCB ) = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) ); } @@ -4478,8 +4493,8 @@ TCB_t *pxTCB; TaskHandle_t xTaskGetCurrentTaskHandle( void ) { - TaskHandle_t xReturn; - unsigned state; + TaskHandle_t xReturn; + unsigned state; state = portENTER_CRITICAL_NESTED(); xReturn = pxCurrentTCB[ xPortGetCoreID() ]; @@ -4507,7 +4522,7 @@ TCB_t *pxTCB; BaseType_t xTaskGetSchedulerState( void ) { - BaseType_t xReturn; + BaseType_t xReturn; if( xSchedulerRunning == pdFALSE ) { @@ -4535,23 +4550,23 @@ TCB_t *pxTCB; BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) { - TCB_t * const pxMutexHolderTCB = pxMutexHolder; - BaseType_t xReturn = pdFALSE; + TCB_t * const pxMutexHolderTCB = pxMutexHolder; + BaseType_t xReturn = pdFALSE; taskENTER_CRITICAL(&xTaskQueueMutex); /* If the mutex was given back by an interrupt while the queue was - locked then the mutex holder might now be NULL. _RB_ Is this still - needed as interrupts can no longer use mutexes? */ + * locked then the mutex holder might now be NULL. _RB_ Is this still + * needed as interrupts can no longer use mutexes? */ if( pxMutexHolder != NULL ) { /* If the holder of the mutex has a priority below the priority of - the task attempting to obtain the mutex then it will temporarily - inherit the priority of the task attempting to obtain the mutex. */ + * the task attempting to obtain the mutex then it will temporarily + * inherit the priority of the task attempting to obtain the mutex. */ if( pxMutexHolderTCB->uxPriority < pxCurrentTCB[xPortGetCoreID()]->uxPriority ) { /* Adjust the mutex holder state to account for its new - priority. Only reset the event list item value if the value is - not being used for anything else. */ + * priority. Only reset the event list item value if the value is + * not being used for anything else. */ if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) { listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[xPortGetCoreID()]->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ @@ -4562,14 +4577,14 @@ TCB_t *pxTCB; } /* If the task being modified is in the ready state it will need - to be moved into a new list. */ + * to be moved into a new list. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE ) { if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { /* It is known that the task is in its ready list so - there is no need to check again and the port level - reset macro can be called directly. */ + * there is no need to check again and the port level + * reset macro can be called directly. */ portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority ); } else @@ -4597,12 +4612,12 @@ TCB_t *pxTCB; if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB[xPortGetCoreID()]->uxPriority ) { /* The base priority of the mutex holder is lower than the - priority of the task attempting to take the mutex, but the - current priority of the mutex holder is not lower than the - priority of the task attempting to take the mutex. - Therefore the mutex holder must have already inherited a - priority, but inheritance would have occurred if that had - not been the case. */ + * priority of the task attempting to take the mutex, but the + * current priority of the mutex holder is not lower than the + * priority of the task attempting to take the mutex. + * Therefore the mutex holder must have already inherited a + * priority, but inheritance would have occurred if that had + * not been the case. */ xReturn = pdTRUE; } else @@ -4627,32 +4642,32 @@ TCB_t *pxTCB; BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) { - TCB_t * const pxTCB = pxMutexHolder; - BaseType_t xReturn = pdFALSE; + TCB_t * const pxTCB = pxMutexHolder; + BaseType_t xReturn = pdFALSE; taskENTER_CRITICAL(&xTaskQueueMutex); if( pxMutexHolder != NULL ) { /* A task can only have an inherited priority if it holds the mutex. - If the mutex is held by a task then it cannot be given from an - interrupt, and if a mutex is given by the holding task then it must - be the running state task. */ + * If the mutex is held by a task then it cannot be given from an + * interrupt, and if a mutex is given by the holding task then it must + * be the running state task. */ configASSERT( pxTCB == pxCurrentTCB[xPortGetCoreID()] ); configASSERT( pxTCB->uxMutexesHeld ); ( pxTCB->uxMutexesHeld )--; /* Has the holder of the mutex inherited the priority of another - task? */ + * task? */ if( pxTCB->uxPriority != pxTCB->uxBasePriority ) { /* Only disinherit if no other mutexes are held. */ if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) { /* A task can only have an inherited priority if it holds - the mutex. If the mutex is held by a task then it cannot be - given from an interrupt, and if a mutex is given by the - holding task then it must be the running state task. Remove - the holding task from the ready/delayed list. */ + * the mutex. If the mutex is held by a task then it cannot be + * given from an interrupt, and if a mutex is given by the + * holding task then it must be the running state task. Remove + * the holding task from the ready list. */ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); @@ -4663,24 +4678,24 @@ TCB_t *pxTCB; } /* Disinherit the priority before adding the task into the - new ready list. */ + * new ready list. */ traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); pxTCB->uxPriority = pxTCB->uxBasePriority; /* Reset the event list item value. It cannot be in use for - any other purpose if this task is running, and it must be - running to give back the mutex. */ + * any other purpose if this task is running, and it must be + * running to give back the mutex. */ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ prvAddTaskToReadyList( pxTCB ); /* Return true to indicate that a context switch is required. - This is only actually required in the corner case whereby - multiple mutexes were held and the mutexes were given back - in an order different to that in which they were taken. - If a context switch did not occur when the first mutex was - returned, even if a task was waiting on it, then a context - switch should occur when the last mutex is returned whether - a task is waiting on it or not. */ + * This is only actually required in the corner case whereby + * multiple mutexes were held and the mutexes were given back + * in an order different to that in which they were taken. + * If a context switch did not occur when the first mutex was + * returned, even if a task was waiting on it, then a context + * switch should occur when the last mutex is returned whether + * a task is waiting on it or not. */ xReturn = pdTRUE; } else @@ -4707,23 +4722,24 @@ TCB_t *pxTCB; #if ( configUSE_MUTEXES == 1 ) - void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask ) + void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, + UBaseType_t uxHighestPriorityWaitingTask ) { - TCB_t * const pxTCB = pxMutexHolder; - UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse; - const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1; + TCB_t * const pxTCB = pxMutexHolder; + UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse; + const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1; taskENTER_CRITICAL(&xTaskQueueMutex); if( pxMutexHolder != NULL ) { /* If pxMutexHolder is not NULL then the holder must hold at least - one mutex. */ + * one mutex. */ configASSERT( pxTCB->uxMutexesHeld ); /* Determine the priority to which the priority of the task that - holds the mutex should be set. This will be the greater of the - holding task's base priority and the priority of the highest - priority task that is waiting to obtain the mutex. */ + * holds the mutex should be set. This will be the greater of the + * holding task's base priority and the priority of the highest + * priority task that is waiting to obtain the mutex. */ if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask ) { uxPriorityToUse = uxHighestPriorityWaitingTask; @@ -4737,25 +4753,25 @@ TCB_t *pxTCB; if( pxTCB->uxPriority != uxPriorityToUse ) { /* Only disinherit if no other mutexes are held. This is a - simplification in the priority inheritance implementation. If - the task that holds the mutex is also holding other mutexes then - the other mutexes may have caused the priority inheritance. */ + * simplification in the priority inheritance implementation. If + * the task that holds the mutex is also holding other mutexes then + * the other mutexes may have caused the priority inheritance. */ if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld ) { /* If a task has timed out because it already holds the - mutex it was trying to obtain then it cannot of inherited - its own priority. */ + * mutex it was trying to obtain then it cannot of inherited + * its own priority. */ configASSERT( pxTCB != pxCurrentTCB[xPortGetCoreID()] ); /* Disinherit the priority, remembering the previous - priority to facilitate determining the subject task's - state. */ + * priority to facilitate determining the subject task's + * state. */ traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); uxPriorityUsedOnEntry = pxTCB->uxPriority; pxTCB->uxPriority = uxPriorityToUse; /* Only reset the event list item value if the value is not - being used for anything else. */ + * being used for anything else. */ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) { listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ @@ -4766,18 +4782,18 @@ TCB_t *pxTCB; } /* If the running task is not the task that holds the mutex - then the task that holds the mutex could be in either the - Ready, Blocked or Suspended states. Only remove the task - from its current state list if it is in the Ready state as - the task's priority is going to change and there is one - Ready list per priority. */ + * then the task that holds the mutex could be in either the + * Ready, Blocked or Suspended states. Only remove the task + * from its current state list if it is in the Ready state as + * the task's priority is going to change and there is one + * Ready list per priority. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) { if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { /* It is known that the task is in its ready list so - there is no need to check again and the port level - reset macro can be called directly. */ + * there is no need to check again and the port level + * reset macro can be called directly. */ portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority ); } else @@ -4823,11 +4839,11 @@ TCB_t *pxTCB; ( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting )++; /* This is not the interrupt safe version of the enter critical - function so assert() if it is being called from an interrupt - context. Only API functions that end in "FromISR" can be used in an - interrupt. Only assert if the critical nesting count is 1 to - protect against recursive calls if the assert function also uses a - critical section. */ + * function so assert() if it is being called from an interrupt + * context. Only API functions that end in "FromISR" can be used in an + * interrupt. Only assert if the critical nesting count is 1 to + * protect against recursive calls if the assert function also uses a + * critical section. */ if( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting == 1 ) { portASSERT_IF_IN_ISR(); @@ -4879,13 +4895,13 @@ TCB_t *pxTCB; static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) { - size_t x; + size_t x; /* Start by copying the entire string. */ strcpy( pcBuffer, pcTaskName ); /* Pad the end of the string with spaces to ensure columns line up when - printed out. */ + * printed out. */ for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ ) { pcBuffer[ x ] = ' '; @@ -4905,9 +4921,9 @@ TCB_t *pxTCB; void vTaskList( char * pcWriteBuffer ) { - TaskStatus_t *pxTaskStatusArray; - UBaseType_t uxArraySize, x; - char cStatus; + TaskStatus_t * pxTaskStatusArray; + UBaseType_t uxArraySize, x; + char cStatus; /* * PLEASE NOTE: @@ -4938,12 +4954,12 @@ TCB_t *pxTCB; *pcWriteBuffer = ( char ) 0x00; /* Take a snapshot of the number of tasks in case it changes while this - function is executing. */ + * function is executing. */ uxArraySize = uxCurrentNumberOfTasks; /* Allocate an array index for each task. NOTE! if - configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will - equate to NULL. */ + * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will + * equate to NULL. */ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ if( pxTaskStatusArray != NULL ) @@ -4956,30 +4972,35 @@ TCB_t *pxTCB; { switch( pxTaskStatusArray[ x ].eCurrentState ) { - case eRunning: cStatus = tskRUNNING_CHAR; - break; + case eRunning: + cStatus = tskRUNNING_CHAR; + break; - case eReady: cStatus = tskREADY_CHAR; - break; + case eReady: + cStatus = tskREADY_CHAR; + break; - case eBlocked: cStatus = tskBLOCKED_CHAR; - break; + case eBlocked: + cStatus = tskBLOCKED_CHAR; + break; - case eSuspended: cStatus = tskSUSPENDED_CHAR; - break; + case eSuspended: + cStatus = tskSUSPENDED_CHAR; + break; - case eDeleted: cStatus = tskDELETED_CHAR; - break; + case eDeleted: + cStatus = tskDELETED_CHAR; + break; - case eInvalid: /* Fall through. */ - default: /* Should not get here, but it is included - to prevent static checking errors. */ - cStatus = ( char ) 0x00; - break; + case eInvalid: /* Fall through. */ + default: /* Should not get here, but it is included + * to prevent static checking errors. */ + cStatus = ( char ) 0x00; + break; } /* Write the task name to the string, padding with spaces so it - can be printed in tabular form more easily. */ + * can be printed in tabular form more easily. */ pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); /* Write the rest of the string. */ @@ -4992,7 +5013,7 @@ TCB_t *pxTCB; } /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION - is 0 then vPortFree() will be #defined to nothing. */ + * is 0 then vPortFree() will be #defined to nothing. */ vPortFree( pxTaskStatusArray ); } else @@ -5006,16 +5027,16 @@ TCB_t *pxTCB; #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - void vTaskGetRunTimeStats( char *pcWriteBuffer ) + void vTaskGetRunTimeStats( char * pcWriteBuffer ) { - TaskStatus_t *pxTaskStatusArray; - UBaseType_t uxArraySize, x; - uint32_t ulTotalTime, ulStatsAsPercentage; + TaskStatus_t * pxTaskStatusArray; + UBaseType_t uxArraySize, x; + uint32_t ulTotalTime, ulStatsAsPercentage; - #if( configUSE_TRACE_FACILITY != 1 ) - { - #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). - } + #if ( configUSE_TRACE_FACILITY != 1 ) + { + #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). + } #endif /* @@ -5047,12 +5068,12 @@ TCB_t *pxTCB; *pcWriteBuffer = ( char ) 0x00; /* Take a snapshot of the number of tasks in case it changes while this - function is executing. */ + * function is executing. */ uxArraySize = uxCurrentNumberOfTasks; /* Allocate an array index for each task. NOTE! If - configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will - equate to NULL. */ + * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will + * equate to NULL. */ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ if( pxTaskStatusArray != NULL ) @@ -5070,43 +5091,43 @@ TCB_t *pxTCB; for( x = 0; x < uxArraySize; x++ ) { /* What percentage of the total run time has the task used? - This will always be rounded down to the nearest integer. - ulTotalRunTimeDiv100 has already been divided by 100. */ + * This will always be rounded down to the nearest integer. + * ulTotalRunTimeDiv100 has already been divided by 100. */ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; /* Write the task name to the string, padding with - spaces so it can be printed in tabular form more - easily. */ + * spaces so it can be printed in tabular form more + * easily. */ pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); if( ulStatsAsPercentage > 0UL ) { #ifdef portLU_PRINTF_SPECIFIER_REQUIRED - { - sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); - } + { + sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + } #else - { - /* sizeof( int ) == sizeof( long ) so a smaller - printf() library can be used. */ - sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ - } + { + /* sizeof( int ) == sizeof( long ) so a smaller + * printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ + } #endif } else { /* If the percentage is zero here then the task has - consumed less than 1% of the total run time. */ + * consumed less than 1% of the total run time. */ #ifdef portLU_PRINTF_SPECIFIER_REQUIRED - { - sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); - } + { + sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); + } #else - { - /* sizeof( int ) == sizeof( long ) so a smaller - printf() library can be used. */ - sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ - } + { + /* sizeof( int ) == sizeof( long ) so a smaller + * printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ + } #endif } @@ -5119,7 +5140,7 @@ TCB_t *pxTCB; } /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION - is 0 then vPortFree() will be #defined to nothing. */ + * is 0 then vPortFree() will be #defined to nothing. */ vPortFree( pxTaskStatusArray ); } else @@ -5133,13 +5154,13 @@ TCB_t *pxTCB; TickType_t uxTaskResetEventItemValue( void ) { -TickType_t uxReturn; + TickType_t uxReturn; taskENTER_CRITICAL(&xTaskQueueMutex); uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); /* Reset the event list item to its normal value - so it can be used with - queues and semaphores. */ + * queues and semaphores. */ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ taskEXIT_CRITICAL(&xTaskQueueMutex); @@ -5151,10 +5172,10 @@ TickType_t uxReturn; void *pvTaskIncrementMutexHeldCount( void ) { - TCB_t *curTCB; + TCB_t * curTCB; /* If xSemaphoreCreateMutex() is called before any tasks have been created - then pxCurrentTCB will be NULL. */ + * then pxCurrentTCB will be NULL. */ taskENTER_CRITICAL(&xTaskQueueMutex); if( pxCurrentTCB[ xPortGetCoreID() ] != NULL ) { @@ -5410,7 +5431,7 @@ TickType_t uxReturn; if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* The notified task has a priority above the currently - executing task so a yield is required. */ + * executing task so a yield is required. */ portYIELD_WITHIN_API(); } else if ( pxTCB->xCoreID != xPortGetCoreID() ) @@ -5698,8 +5719,8 @@ TickType_t uxReturn; static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const TickType_t xTicksToWait ) { -TickType_t xTimeToWake; -const TickType_t xConstTickCount = xTickCount; + TickType_t xTimeToWake; + const TickType_t xConstTickCount = xTickCount; if (portNUM_PROCESSORS > 1 && listIS_CONTAINED_WITHIN(&xTasksWaitingTermination, &( pxCurrentTCB[xCoreID]->xStateListItem))) { /* vTaskDelete() has been called to delete this task. This would have happened from the other core while this task was spinning on xTaskQueueMutex, @@ -5708,21 +5729,21 @@ const TickType_t xConstTickCount = xTickCount; return; } - #if( INCLUDE_xTaskAbortDelay == 1 ) - { - /* About to enter a delayed list, so ensure the ucDelayAborted flag is - reset to pdFALSE so it can be detected as having been set to pdTRUE - when the task leaves the Blocked state. */ + #if ( INCLUDE_xTaskAbortDelay == 1 ) + { + /* About to enter a delayed list, so ensure the ucDelayAborted flag is + * reset to pdFALSE so it can be detected as having been set to pdTRUE + * when the task leaves the Blocked state. */ pxCurrentTCB[xCoreID]->ucDelayAborted = pdFALSE; - } + } #endif /* Remove the task from the ready list before adding it to the blocked list - as the same list item is used for both lists. */ + * as the same list item is used for both lists. */ if( uxListRemove( &( pxCurrentTCB[xCoreID]->xStateListItem ) ) == ( UBaseType_t ) 0 ) { /* The current task must be in a ready list, so there is no need to - check, and the port reset macro can be called directly. */ + * check, and the port reset macro can be called directly. */ portRESET_READY_PRIORITY( pxCurrentTCB[xCoreID]->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB[xPortGetCoreID()] cannot change as it is the calling task. pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */ } else @@ -5731,19 +5752,55 @@ const TickType_t xConstTickCount = xTickCount; } #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( ( xTicksToWait == portMAX_DELAY ) ) { - /* Add the task to the suspended task list instead of a delayed task - list to ensure it is not woken by a timing event. It will block - indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + if( ( xTicksToWait == portMAX_DELAY ) ) + { + /* Add the task to the suspended task list instead of a delayed task + * list to ensure it is not woken by a timing event. It will block + * indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + * does not occur. This may overflow but this doesn't matter, the + * kernel will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xCoreID]->xStateListItem ), xTimeToWake ); + + if( xTimeToWake < xConstTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow + * list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list + * is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + + /* If the task entering the blocked state was placed at the + * head of the list of blocked tasks then xNextTaskUnblockTime + * needs to be updated too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } } - else + #else /* INCLUDE_vTaskSuspend */ { /* Calculate the time at which the task should be woken if the event - does not occur. This may overflow but this doesn't matter, the - kernel will manage it correctly. */ + * does not occur. This may overflow but this doesn't matter, the kernel + * will manage it correctly. */ xTimeToWake = xConstTickCount + xTicksToWait; /* The list item will be inserted in wake time order. */ @@ -5751,19 +5808,17 @@ const TickType_t xConstTickCount = xTickCount; if( xTimeToWake < xConstTickCount ) { - /* Wake time has overflowed. Place this item in the overflow - list. */ + /* Wake time has overflowed. Place this item in the overflow list. */ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); } else { - /* The wake time has not overflowed, so the current block list - is used. */ + /* The wake time has not overflowed, so the current block list is used. */ vListInsert( pxDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - /* If the task entering the blocked state was placed at the - head of the list of blocked tasks then xNextTaskUnblockTime - needs to be updated too. */ + /* If the task entering the blocked state was placed at the head of the + * list of blocked tasks then xNextTaskUnblockTime needs to be updated + * too. */ if( xTimeToWake < xNextTaskUnblockTime ) { xNextTaskUnblockTime = xTimeToWake; @@ -5774,52 +5829,19 @@ const TickType_t xConstTickCount = xTickCount; } } } - } - #else /* INCLUDE_vTaskSuspend */ - { - /* Calculate the time at which the task should be woken if the event - does not occur. This may overflow but this doesn't matter, the kernel - will manage it correctly. */ - xTimeToWake = xConstTickCount + xTicksToWait; - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xCoreID]->xStateListItem ), xTimeToWake ); - - if( xTimeToWake < xConstTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - } - else - { - /* The wake time has not overflowed, so the current block list is used. */ - vListInsert( pxDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - - /* If the task entering the blocked state was placed at the head of the - list of blocked tasks then xNextTaskUnblockTime needs to be updated - too. */ - if( xTimeToWake < xNextTaskUnblockTime ) - { - xNextTaskUnblockTime = xTimeToWake; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } #endif /* INCLUDE_vTaskSuspend */ } /* Code below here allows additional code to be inserted into this source file, -especially where access to file scope functions and data is needed (for example -when performing module tests). */ + * especially where access to file scope functions and data is needed (for example + * when performing module tests). */ #ifdef FREERTOS_MODULE_TEST #include "tasks_test_access_functions.h" #endif -#if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) + +#if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) #include "freertos_tasks_c_additions.h" @@ -5830,7 +5852,7 @@ when performing module tests). */ } #endif -#endif +#endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */ /* If timers.c is not referenced anywhere, don't create the timer task to save RAM */ BaseType_t __attribute__((weak)) xTimerCreateTimerTask( void ) diff --git a/components/freertos/timers.c b/components/freertos/timers.c index 97048bb9a0..b0f1f265f7 100644 --- a/components/freertos/timers.c +++ b/components/freertos/timers.c @@ -55,7 +55,7 @@ #if ( configUSE_TIMERS == 1 ) /* Misc definitions. */ -#define tmrNO_DELAY ( TickType_t ) 0U + #define tmrNO_DELAY ( TickType_t ) 0U /* The name assigned to the timer service task. This can be overridden by * defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */ @@ -476,7 +476,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) { - Timer_t * pxTimer = xTimer; + Timer_t * pxTimer = xTimer; TickType_t xReturn; configASSERT( xTimer ); @@ -487,7 +487,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { - Timer_t *pxTimer = xTimer; + Timer_t * pxTimer = xTimer; configASSERT( xTimer ); return pxTimer->pcTimerName; @@ -500,21 +500,21 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ /* Remove the timer from the list of active timers. A check has already - been performed to ensure the list is not empty. */ + * been performed to ensure the list is not empty. */ ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); traceTIMER_EXPIRED( pxTimer ); - /* If the timer is an auto reload timer then calculate the next - expiry time and re-insert the timer in the list of active timers. */ + /* If the timer is an auto-reload timer then calculate the next + * expiry time and re-insert the timer in the list of active timers. */ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) { /* The timer is inserted into a list using a time relative to anything - other than the current time. It will therefore be inserted into the - correct list relative to the time this task thinks it is now. */ + * other than the current time. It will therefore be inserted into the + * correct list relative to the time this task thinks it is now. */ if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE ) { /* The timer expired before it was added to the active timer - list. Reload it now. */ + * list. Reload it now. */ xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); configASSERT( xResult ); ( void ) xResult; @@ -543,26 +543,26 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; /* Just to avoid compiler warnings. */ ( void ) pvParameters; - #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 ) - { - extern void vApplicationDaemonTaskStartupHook( void ); + #if ( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 ) + { + extern void vApplicationDaemonTaskStartupHook( void ); - /* Allow the application writer to execute some code in the context of - this task at the point the task starts executing. This is useful if the - application includes initialisation code that would benefit from - executing after the scheduler has been started. */ - vApplicationDaemonTaskStartupHook(); - } + /* Allow the application writer to execute some code in the context of + * this task at the point the task starts executing. This is useful if the + * application includes initialisation code that would benefit from + * executing after the scheduler has been started. */ + vApplicationDaemonTaskStartupHook(); + } #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */ - for( ;; ) + for( ; ; ) { /* Query the timers list to see if it contains any timers, and if so, - obtain the time at which the next timer will expire. */ + * obtain the time at which the next timer will expire. */ xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); /* If a timer has expired, process it. Otherwise, block this task - until either a timer does expire, or a command is received. */ + * until either a timer does expire, or a command is received. */ prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); /* Empty the command queue. */ @@ -571,7 +571,8 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; } /*-----------------------------------------------------------*/ - static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) + static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, + BaseType_t xListWasEmpty ) { TickType_t xTimeNow; BaseType_t xTimerListsWereSwitched; @@ -579,11 +580,12 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; taskENTER_CRITICAL( &xTimerMux); { /* Obtain the time now to make an assessment as to whether the timer - has expired or not. If obtaining the time causes the lists to switch - then don't process this timer as any timers that remained in the list - when the lists were switched will have been processed within the - prvSampleTimeNow() function. */ + * has expired or not. If obtaining the time causes the lists to switch + * then don't process this timer as any timers that remained in the list + * when the lists were switched will have been processed within the + * prvSampleTimeNow() function. */ xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + if( xTimerListsWereSwitched == pdFALSE ) { /* The tick count has not overflowed, has the timer expired? */ @@ -595,15 +597,15 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; else { /* The tick count has not overflowed, and the next expire - time has not been reached yet. This task should therefore - block to wait for the next expire time or a command to be - received - whichever comes first. The following line cannot - be reached unless xNextExpireTime > xTimeNow, except in the - case when the current timer list is empty. */ + * time has not been reached yet. This task should therefore + * block to wait for the next expire time or a command to be + * received - whichever comes first. The following line cannot + * be reached unless xNextExpireTime > xTimeNow, except in the + * case when the current timer list is empty. */ if( xListWasEmpty != pdFALSE ) { /* The current timer list is empty - is the overflow list - also empty? */ + * also empty? */ xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList ); } @@ -612,9 +614,9 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; taskEXIT_CRITICAL( &xTimerMux); /* Yield to wait for either a command to arrive, or the - block time to expire. If a command arrived between the - critical section being exited and this yield then the yield - will not cause the task to block. */ + * block time to expire. If a command arrived between the + * critical section being exited and this yield then the yield + * will not cause the task to block. */ portYIELD_WITHIN_API(); } @@ -632,13 +634,14 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; TickType_t xNextExpireTime; /* Timers are listed in expiry time order, with the head of the list - referencing the task that will expire first. Obtain the time at which - the timer with the nearest expiry time will expire. If there are no - active timers then just set the next expire time to 0. That will cause - this task to unblock when the tick count overflows, at which point the - timer lists will be switched and the next expiry time can be - re-assessed. */ + * referencing the task that will expire first. Obtain the time at which + * the timer with the nearest expiry time will expire. If there are no + * active timers then just set the next expire time to 0. That will cause + * this task to unblock when the tick count overflows, at which point the + * timer lists will be switched and the next expiry time can be + * re-assessed. */ *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); + if( *pxListWasEmpty == pdFALSE ) { xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); @@ -676,7 +679,10 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; } /*-----------------------------------------------------------*/ - static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) + static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, + const TickType_t xNextExpiryTime, + const TickType_t xTimeNow, + const TickType_t xCommandTime ) { BaseType_t xProcessTimerNow = pdFALSE; @@ -686,11 +692,11 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; if( xNextExpiryTime <= xTimeNow ) { /* Has the expiry time elapsed between the command to start/reset a - timer was issued, and the time the command was processed? */ + * timer was issued, and the time the command was processed? */ if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ { /* The time between a command being issued and the command being - processed actually exceeds the timers period. */ + * processed actually exceeds the timers period. */ xProcessTimerNow = pdTRUE; } else @@ -703,8 +709,8 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) { /* If, since the command was issued, the tick count has overflowed - but the expiry time has not, then the timer must have already passed - its expiry time and should be processed immediately. */ + * but the expiry time has not, then the timer must have already passed + * its expiry time and should be processed immediately. */ xProcessTimerNow = pdTRUE; } else @@ -720,40 +726,40 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; static void prvProcessReceivedCommands( void ) { DaemonTaskMessage_t xMessage; - Timer_t *pxTimer; + Timer_t * pxTimer; BaseType_t xTimerListsWereSwitched, xResult; TickType_t xTimeNow; while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ { #if ( INCLUDE_xTimerPendFunctionCall == 1 ) - { - /* Negative commands are pended function calls rather than timer - commands. */ - if( xMessage.xMessageID < ( BaseType_t ) 0 ) { - const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); + /* Negative commands are pended function calls rather than timer + * commands. */ + if( xMessage.xMessageID < ( BaseType_t ) 0 ) + { + const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); - /* The timer uses the xCallbackParameters member to request a - callback be executed. Check the callback is not NULL. */ - configASSERT( pxCallback ); + /* The timer uses the xCallbackParameters member to request a + * callback be executed. Check the callback is not NULL. */ + configASSERT( pxCallback ); - /* Call the function. */ - pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); + /* Call the function. */ + pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } #endif /* INCLUDE_xTimerPendFunctionCall */ /* Commands that are positive are timer commands rather than pended - function calls. */ + * function calls. */ if( xMessage.xMessageID >= ( BaseType_t ) 0 ) { /* The messages uses the xTimerParameters member to work on a - software timer. */ + * software timer. */ pxTimer = xMessage.u.xTimerParameters.pxTimer; if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */ @@ -769,11 +775,11 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); /* In this case the xTimerListsWereSwitched parameter is not used, but - * it must be present in the function call. prvSampleTimeNow() must be - * called after the message is received from xTimerQueue so there is no - * possibility of a higher priority task adding a message to the message - * queue with a time that is ahead of the timer daemon task (because it - * pre-empted the timer daemon task after the xTimeNow value was set). */ + * it must be present in the function call. prvSampleTimeNow() must be + * called after the message is received from xTimerQueue so there is no + * possibility of a higher priority task adding a message to the message + * queue with a time that is ahead of the timer daemon task (because it + * pre-empted the timer daemon task after the xTimeNow value was set). */ xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); switch( xMessage.xMessageID ) From c2d5af17a22dadfdd65223e3115b2f39dd5519fd Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 25 Aug 2021 17:02:19 +0800 Subject: [PATCH 047/310] dac: apply generic check macro --- components/driver/dac_common.c | 24 +++++++++--------------- components/driver/esp32s2/dac.c | 24 +++++++++--------------- components/driver/gpio.c | 7 ++----- components/driver/ledc.c | 4 ++-- components/driver/pcnt.c | 7 ++----- components/driver/sigmadelta.c | 6 ++---- 6 files changed, 26 insertions(+), 46 deletions(-) diff --git a/components/driver/dac_common.c b/components/driver/dac_common.c index 79172eb984..791926b0fc 100644 --- a/components/driver/dac_common.c +++ b/components/driver/dac_common.c @@ -8,6 +8,7 @@ #include #include "esp_log.h" #include "esp_err.h" +#include "esp_check.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/timers.h" @@ -18,21 +19,14 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. -static const char *DAC_TAG = "DAC"; - -#define DAC_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(DAC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) +static const char *TAG = "DAC"; /*--------------------------------------------------------------- DAC ---------------------------------------------------------------*/ esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); *gpio_num = (gpio_num_t)dac_periph_signal.dac_channel_io_num[channel]; @@ -41,7 +35,7 @@ esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num) static esp_err_t dac_rtc_pad_init(dac_channel_t channel) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); gpio_num_t gpio_num = 0; dac_pad_get_io_num(channel, &gpio_num); @@ -55,7 +49,7 @@ static esp_err_t dac_rtc_pad_init(dac_channel_t channel) esp_err_t dac_output_enable(dac_channel_t channel) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); dac_rtc_pad_init(channel); portENTER_CRITICAL(&rtc_spinlock); @@ -68,7 +62,7 @@ esp_err_t dac_output_enable(dac_channel_t channel) esp_err_t dac_output_disable(dac_channel_t channel) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_power_down(channel); @@ -79,7 +73,7 @@ esp_err_t dac_output_disable(dac_channel_t channel) esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_update_output_value(channel, dac_value); @@ -90,7 +84,7 @@ esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value) esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_update_output_value(channel, dac_value); @@ -119,7 +113,7 @@ esp_err_t dac_cw_generator_disable(void) esp_err_t dac_cw_generator_config(dac_cw_config_t *cw) { - if (!cw) return ESP_ERR_INVALID_ARG; + ESP_RETURN_ON_FALSE(cw, ESP_ERR_INVALID_ARG, TAG, "invalid clock configuration"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_cw_generator_config(cw); diff --git a/components/driver/esp32s2/dac.c b/components/driver/esp32s2/dac.c index 7a1d0d40c5..16f8742a90 100644 --- a/components/driver/esp32s2/dac.c +++ b/components/driver/esp32s2/dac.c @@ -8,6 +8,7 @@ #include #include "esp_log.h" #include "esp_err.h" +#include "esp_check.h" #include "esp_pm.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" @@ -17,14 +18,7 @@ #include "soc/dac_periph.h" #include "hal/dac_hal.h" -static const char *DAC_TAG = "DAC"; - -#define DAC_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(DAC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) +static const char *TAG = "DAC"; extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. #define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) @@ -64,11 +58,11 @@ esp_err_t dac_digi_deinit(void) esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg) { - DAC_CHECK(cfg->mode < DAC_CONV_MAX, "DAC mode error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->interval > 0 && cfg->interval < 4096, "DAC interval error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->dig_clk.div_num < 256, "DAC clk div_num error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, "DAC clk div_b error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->dig_clk.div_a < 64, "DAC clk div_a error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(cfg->mode < DAC_CONV_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC mode error"); + ESP_RETURN_ON_FALSE(cfg->interval > 0 && cfg->interval < 4096, ESP_ERR_INVALID_ARG, TAG, "DAC interval error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_num < 256, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_num error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_b error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_a < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_a error"); #ifdef CONFIG_PM_ENABLE esp_err_t err; if (s_dac_digi_lock == NULL) { @@ -79,7 +73,7 @@ esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg) } if (err != ESP_OK) { s_dac_digi_lock = NULL; - ESP_LOGE(DAC_TAG, "DAC-DMA pm lock error"); + ESP_LOGE(TAG, "DAC-DMA pm lock error"); return err; } } @@ -95,7 +89,7 @@ esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg) esp_err_t dac_digi_start(void) { #ifdef CONFIG_PM_ENABLE - DAC_CHECK((s_dac_digi_lock), "Should start after call `dac_digi_controller_config`", ESP_FAIL); + ESP_RETURN_ON_FALSE(s_dac_digi_lock, ESP_FAIL, TAG, "Should start after call `dac_digi_controller_config`"); esp_pm_lock_acquire(s_dac_digi_lock); #endif DAC_ENTER_CRITICAL(); diff --git a/components/driver/gpio.c b/components/driver/gpio.c index f749c77a34..db27ab45ab 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -18,15 +18,12 @@ #include "soc/soc_caps.h" #include "soc/gpio_periph.h" #include "esp_log.h" +#include "esp_check.h" #include "hal/gpio_hal.h" #include "esp_rom_gpio.h" static const char *GPIO_TAG = "gpio"; -#define GPIO_CHECK(a, str, ret_val) \ - if (!(a)) { \ - ESP_LOGE(GPIO_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } +#define GPIO_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, GPIO_TAG, "%s", str) #define GPIO_ISR_CORE_ID_UNINIT (3) diff --git a/components/driver/ledc.c b/components/driver/ledc.c index ef0535b89d..6d82554795 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -22,8 +22,8 @@ static const char* LEDC_TAG = "ledc"; -#define LEDC_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, LEDC_TAG, "%s", str); -#define LEDC_ARG_CHECK(a, param) ESP_RETURN_ON_FALSE(a, ESP_ERR_INVALID_ARG, LEDC_TAG, param " argument is invalid"); +#define LEDC_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, LEDC_TAG, "%s", str) +#define LEDC_ARG_CHECK(a, param) ESP_RETURN_ON_FALSE(a, ESP_ERR_INVALID_ARG, LEDC_TAG, param " argument is invalid") typedef struct { ledc_mode_t speed_mode; diff --git a/components/driver/pcnt.c b/components/driver/pcnt.c index 060ff30a9d..9c72378d99 100644 --- a/components/driver/pcnt.c +++ b/components/driver/pcnt.c @@ -5,6 +5,7 @@ */ #include "freertos/FreeRTOS.h" #include "esp_log.h" +#include "esp_check.h" #include "soc/soc_caps.h" #if SOC_PCNT_SUPPORTED #include "driver/periph_ctrl.h" @@ -32,11 +33,7 @@ static const char *TAG = "pcnt"; -#define PCNT_CHECK(a, str, ret_val) \ - if (!(a)) { \ - ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } +#define PCNT_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, TAG, "%s", str) typedef struct { pcnt_hal_context_t hal; /*!< PCNT hal context*/ diff --git a/components/driver/sigmadelta.c b/components/driver/sigmadelta.c index 9d72c04f47..4e909a043f 100644 --- a/components/driver/sigmadelta.c +++ b/components/driver/sigmadelta.c @@ -5,6 +5,7 @@ */ #include "esp_log.h" +#include "esp_check.h" #include "esp_err.h" #include "driver/sigmadelta.h" #include "esp_heap_caps.h" @@ -14,10 +15,7 @@ static const char *TAG = "sigma-delta"; -#define SIGMADELTA_CHECK(a,str,ret_val) if(!(a)) { \ - ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } +#define SIGMADELTA_CHECK(a,str,ret_val) ESP_RETURN_ON_FALSE(a, ret_val, TAG, "%s", str) typedef struct { sigmadelta_hal_context_t hal; /*!< SIGMADELTA hal context*/ From c053ef0541249946962139cb7e54c898b9e066f6 Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Thu, 26 Aug 2021 14:24:32 +0800 Subject: [PATCH 048/310] examples: added support of ESP32-S3 chip in controller_hci_uart example --- components/hal/esp32c3/include/hal/uhci_ll.h | 10 +- components/hal/esp32h2/include/hal/uhci_ll.h | 10 +- components/hal/esp32s3/include/hal/uhci_ll.h | 139 ++++++++++++++++++ .../{esp32c3 => }/include/hal/uhci_types.h | 6 +- .../hci/controller_hci_uart_esp32c3/README.md | 10 +- 5 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 components/hal/esp32s3/include/hal/uhci_ll.h rename components/hal/{esp32c3 => }/include/hal/uhci_types.h (100%) diff --git a/components/hal/esp32c3/include/hal/uhci_ll.h b/components/hal/esp32c3/include/hal/uhci_ll.h index 235d28ab3a..a766797ea0 100644 --- a/components/hal/esp32c3/include/hal/uhci_ll.h +++ b/components/hal/esp32c3/include/hal/uhci_ll.h @@ -18,9 +18,13 @@ #pragma once #include -#include "uhci_types.h" +#include "hal/uhci_types.h" #include "soc/uhci_struct.h" +#ifdef __cplusplus +extern "C" { +#endif + #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) typedef enum { @@ -128,3 +132,7 @@ static inline void uhci_ll_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) hw->conf0.len_eof_en = 1; } } + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/uhci_ll.h b/components/hal/esp32h2/include/hal/uhci_ll.h index 235d28ab3a..a766797ea0 100644 --- a/components/hal/esp32h2/include/hal/uhci_ll.h +++ b/components/hal/esp32h2/include/hal/uhci_ll.h @@ -18,9 +18,13 @@ #pragma once #include -#include "uhci_types.h" +#include "hal/uhci_types.h" #include "soc/uhci_struct.h" +#ifdef __cplusplus +extern "C" { +#endif + #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) typedef enum { @@ -128,3 +132,7 @@ static inline void uhci_ll_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) hw->conf0.len_eof_en = 1; } } + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/uhci_ll.h b/components/hal/esp32s3/include/hal/uhci_ll.h new file mode 100644 index 0000000000..0ea4440853 --- /dev/null +++ b/components/hal/esp32s3/include/hal/uhci_ll.h @@ -0,0 +1,139 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The LL layer for UHCI register operations. +// Note that most of the register operations in this layer are non-atomic operations. + + +#pragma once +#include +#include "hal/uhci_types.h" +#include "soc/uhci_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) + +typedef enum { + UHCI_RX_BREAK_CHR_EOF = 0x1, + UHCI_RX_IDLE_EOF = 0x2, + UHCI_RX_LEN_EOF = 0x4, + UHCI_RX_EOF_MAX = 0x7, +} uhci_rxeof_cfg_t; + +static inline void uhci_ll_init(uhci_dev_t *hw) +{ + typeof(hw->conf0) conf0_reg; + hw->conf0.clk_en = 1; + conf0_reg.val = 0; + conf0_reg.clk_en = 1; + hw->conf0.val = conf0_reg.val; + hw->conf1.val = 0; +} + +static inline void uhci_ll_attach_uart_port(uhci_dev_t *hw, int uart_num) +{ + hw->conf0.uart0_ce = (uart_num == 0)? 1: 0; + hw->conf0.uart1_ce = (uart_num == 1)? 1: 0; + hw->conf0.uart2_ce = (uart_num == 2)? 1: 0; +} + +static inline void uhci_ll_set_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_char) +{ + if (seper_char->sub_chr_en) { + typeof(hw->esc_conf0) esc_conf0_reg = hw->esc_conf0; + esc_conf0_reg.seper_char = seper_char->seper_chr; + esc_conf0_reg.seper_esc_char0 = seper_char->sub_chr1; + esc_conf0_reg.seper_esc_char1 = seper_char->sub_chr2; + hw->esc_conf0.val = esc_conf0_reg.val; + hw->escape_conf.tx_c0_esc_en = 1; + hw->escape_conf.rx_c0_esc_en = 1; + } else { + hw->escape_conf.tx_c0_esc_en = 0; + hw->escape_conf.rx_c0_esc_en = 0; + } +} + +static inline void uhci_ll_get_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_chr) +{ + (void)hw; + (void)seper_chr; +} + +static inline void uhci_ll_set_swflow_ctrl_sub_chr(uhci_dev_t *hw, uhci_swflow_ctrl_sub_chr_t *sub_ctr) +{ + typeof(hw->escape_conf) escape_conf_reg = hw->escape_conf; + if (sub_ctr->flow_en == 1) { + typeof(hw->esc_conf2) esc_conf2_reg = hw->esc_conf2; + typeof(hw->esc_conf3) esc_conf3_reg = hw->esc_conf3; + esc_conf2_reg.seq1 = sub_ctr->xon_chr; + esc_conf2_reg.seq1_char0 = sub_ctr->xon_sub1; + esc_conf2_reg.seq1_char1 = sub_ctr->xon_sub2; + esc_conf3_reg.seq2 = sub_ctr->xoff_chr; + esc_conf3_reg.seq2_char0 = sub_ctr->xoff_sub1; + esc_conf3_reg.seq2_char1 = sub_ctr->xoff_sub2; + escape_conf_reg.tx_11_esc_en = 1; + escape_conf_reg.tx_13_esc_en = 1; + escape_conf_reg.rx_11_esc_en = 1; + escape_conf_reg.rx_13_esc_en = 1; + hw->esc_conf2.val = esc_conf2_reg.val; + hw->esc_conf3.val = esc_conf3_reg.val; + } else { + escape_conf_reg.tx_11_esc_en = 0; + escape_conf_reg.tx_13_esc_en = 0; + escape_conf_reg.rx_11_esc_en = 0; + escape_conf_reg.rx_13_esc_en = 0; + } + hw->escape_conf.val = escape_conf_reg.val; +} + +static inline void uhci_ll_enable_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_ena.val |= intr_mask; +} + +static inline void uhci_ll_disable_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_ena.val &= (~intr_mask); +} + +static inline void uhci_ll_clear_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_clr.val = intr_mask; +} + +static inline uint32_t uhci_ll_get_intr(uhci_dev_t *hw) +{ + return hw->int_st.val; +} + + +static inline void uhci_ll_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) +{ + if (eof_mode & UHCI_RX_BREAK_CHR_EOF) { + hw->conf0.uart_rx_brk_eof_en = 1; + } + if (eof_mode & UHCI_RX_IDLE_EOF) { + hw->conf0.uart_idle_eof_en = 1; + } + if (eof_mode & UHCI_RX_LEN_EOF) { + hw->conf0.len_eof_en = 1; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c3/include/hal/uhci_types.h b/components/hal/include/hal/uhci_types.h similarity index 100% rename from components/hal/esp32c3/include/hal/uhci_types.h rename to components/hal/include/hal/uhci_types.h index 7b7f41d0f9..7122e2a41a 100644 --- a/components/hal/esp32c3/include/hal/uhci_types.h +++ b/components/hal/include/hal/uhci_types.h @@ -19,13 +19,13 @@ #pragma once +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include -#include - /** * @brief UHCI escape sequence */ diff --git a/examples/bluetooth/hci/controller_hci_uart_esp32c3/README.md b/examples/bluetooth/hci/controller_hci_uart_esp32c3/README.md index 94e01fb8e4..03534fcd27 100644 --- a/examples/bluetooth/hci/controller_hci_uart_esp32c3/README.md +++ b/examples/bluetooth/hci/controller_hci_uart_esp32c3/README.md @@ -1,11 +1,11 @@ ESP-IDF UART HCI Controller ================================= -| Supported Targets | ESP32-C3 | -| ----------------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-S3 | +| ----------------- | -------- | -------- | This example demonstrates how to configure the Bluetooth Low Energy Controller's HCI (Host Controller Interface) to communicate over UART. -Using this example, BLE radio capabilities of ESP32-C3 chip, can be: +Using this example, BLE radio capabilities of ESP32-C3/ESP32-S3 chip, can be: 1. tested via standard HCI messages in Direct Test Mode @@ -19,7 +19,7 @@ This example uses LL/register access directly, because the UHCI driver hasn't be ### Hardware Required -This example should be able to run on any commonly available ESP32-C3 development board. To connect UART to PC, another board such as ESP_Test Board or FT232 USB UART board is usually needed. +This example should be able to run on any commonly available ESP32-C3/ESP32-S3 development board. To connect UART to PC, another board such as ESP_Test Board or FT232 USB UART board is usually needed. In this example, two UARTs are used: @@ -30,7 +30,7 @@ In this example, two UARTs are used: RTS and CTS lines of UART1 are required. GPIO4, GPIO5, GPIO6, GPIO7 are used as TxD, RxD, RTS, CTS PINs of UART1, respectively. -In a frequently-used scenario, if ESP_Test Board is used, connect the TX0, RX0, RTS0, CTS0 and GND of ESP_Test Board to ESP32-C3 UART1 PINs, and Attach ESP_Test board to the host PC. +In a frequently-used scenario, if ESP_Test Board is used, connect the TX0, RX0, RTS0, CTS0 and GND of ESP_Test Board to ESP32-C3/ESP32-S3 UART1 PINs, and Attach ESP_Test board to the host PC. ### Configure the project From 58aed7df986aca9b4ad39e5cc562f52eceae81b9 Mon Sep 17 00:00:00 2001 From: Martin Vychodil Date: Wed, 18 Aug 2021 13:31:35 +0200 Subject: [PATCH 049/310] ESP32S2: No assert()/abort() in Memprot API, use esp_err_t instead JIRA IDF-3634 --- .../include/soc/esp32s2/memprot.h | 194 ++-- .../esp_hw_support/port/esp32s2/memprot.c | 912 +++++++++++------- .../esp_system/port/arch/xtensa/panic_arch.c | 55 +- components/esp_system/port/cpu_start.c | 17 +- .../hal/esp32s2/include/hal/memprot_ll.h | 440 +++++---- .../hal/esp32s2/include/hal/memprot_peri_ll.h | 199 ++-- components/hal/include/hal/memprot_types.h | 35 + .../soc/esp32s2/include/soc/memprot_defs.h | 131 +++ .../memprot/main/esp32s2/test_memprot_main.c | 40 +- 9 files changed, 1237 insertions(+), 786 deletions(-) create mode 100644 components/hal/include/hal/memprot_types.h create mode 100644 components/soc/esp32s2/include/soc/memprot_defs.h diff --git a/components/esp_hw_support/include/soc/esp32s2/memprot.h b/components/esp_hw_support/include/soc/esp32s2/memprot.h index 55ad7258bb..0ebd647457 100644 --- a/components/esp_hw_support/include/soc/esp32s2/memprot.h +++ b/components/esp_hw_support/include/soc/esp32s2/memprot.h @@ -4,7 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ - /* INTERNAL API * generic interface to MMU memory protection features */ @@ -13,6 +12,7 @@ #include #include #include "esp_attr.h" +#include "esp_err.h" #ifdef __cplusplus extern "C" { @@ -43,6 +43,8 @@ extern "C" { #define MEMPROT_UNLOCK false #define DEF_SPLIT_LINE NULL +#define MEMPROT_INVALID_ADDRESS -1 + //memory range types typedef enum { MEMPROT_NONE = 0x00000000, @@ -69,23 +71,27 @@ typedef enum { uint32_t *IRAM_ATTR esp_memprot_get_split_addr(mem_type_prot_t mem_type); /** - * @brief Initializes illegal memory access control (MMU) for required memory section. + * @brief Initializes illegal memory access control for required memory section. * * All memory access interrupts share ETS_MEMACCESS_ERR_INUM input channel, it is caller's * responsibility to properly detect actual intr. source as well as possible prioritization in case * of multiple source reported during one intr.handling routine run * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (see mem_type_prot_t enum)\ + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_intr_init(mem_type_prot_t mem_type); +esp_err_t esp_memprot_intr_init(mem_type_prot_t mem_type); /** * @brief Enable/disable the memory protection interrupt * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param enable enable/disable + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); +esp_err_t esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); /** * @brief Sets a request for clearing interrupt-on flag for specified memory region (register write) @@ -94,8 +100,10 @@ void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); * Should be used only after the real interrupt appears, typically as the last step in interrupt handler's routine. * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_clear_intr(mem_type_prot_t mem_type); +esp_err_t esp_memprot_clear_intr(mem_type_prot_t mem_type); /** * @brief Detects which memory protection interrupt is active @@ -114,10 +122,11 @@ mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void); * @brief Gets interrupt status register contents for specified memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param fault_reg_val Contents of status register * - * @return Contents of status register + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type, uint32_t *fault_reg_val); /** * @brief Get details of given interrupt status @@ -130,8 +139,9 @@ uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type); * @param op_subtype Additional info for op_type [out] * IRAM0: 0 - instruction segment access, 1 - data segment access * DRAM0: 0 - non-atomic operation, 1 - atomic operation + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype); +esp_err_t IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype); /** * @brief Gets string representation of required memory region identifier @@ -155,26 +165,30 @@ bool esp_memprot_is_locked_any(void); * Locks can be unlocked only by digital system reset * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_lock(mem_type_prot_t mem_type); +esp_err_t esp_memprot_set_lock(mem_type_prot_t mem_type); /** * @brief Gets lock status for required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param locked Settings locked: true/false (locked/unlocked) * - * @return true/false (locked/unlocked) + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -bool esp_memprot_get_lock(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_lock(mem_type_prot_t mem_type, bool *locked); /** * @brief Gets permission control configuration register contents for required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param conf_reg_val Permission control register contents * - * @return Permission control register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type, uint32_t *conf_reg_val); /** * @brief Gets interrupt permission settings for unified management block @@ -182,21 +196,23 @@ uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type); * Gets interrupt permission settings register contents for required memory region, returns settings for unified management blocks * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param perm_reg Permission settings register contents * - * @return Permission settings register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type, uint32_t *perm_reg); /** * @brief Gets interrupt permission settings for split management block * - * Gets interrupt permission settings register contents for required memory region, returns settings for split management blocks + * Gets interrupt permission settings register contents for required memory region (unified management blocks) * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @return split_reg Unified management settings register contents * - * @return Permission settings register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type, uint32_t *split_reg); /** * @brief Detects whether any of the memory protection interrupts is enabled @@ -209,28 +225,30 @@ bool esp_memprot_is_intr_ena_any(void); * @brief Gets interrupt-enabled flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param enable_bit Interrupt-enabled flag * - * @return Interrupt-enabled value + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type, uint32_t *enable_bit); /** * @brief Gets interrupt-active flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param intr_on_bit Interrupt-active flag * - * @return Interrupt-active value - */ -uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type); + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ +esp_err_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type, uint32_t *intr_on_bit); /** * @brief Gets interrupt-clear request flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param clear_bit Interrupt-clear request flag * - * @return Interrupt-clear request value + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type, uint32_t *clear_bit); /** * @brief Gets read permission value for specified block and memory region @@ -240,10 +258,11 @@ uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type); * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param read_bit Read permission value for required block * - * @return Read permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *read_bit); /** * @brief Gets write permission value for specified block and memory region @@ -253,10 +272,11 @@ uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t b * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param write_bit Write permission value for required block * - * @return Write permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *write_bit); /** * @brief Gets execute permission value for specified block and memory region @@ -266,10 +286,11 @@ uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param exec_bit Execute permission value for required block * - * @return Execute permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *exec_bit); /** * @brief Sets permissions for specified block in DRAM region @@ -281,8 +302,10 @@ uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t b * @param block Memory block identifier (0-3) * @param write_perm Write permission flag * @param read_perm Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm); +esp_err_t esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm); /** * @brief Sets permissions for high and low memory segment in DRAM region @@ -297,8 +320,10 @@ void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t bloc * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); +esp_err_t esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); /** * @brief Sets permissions for specified block in IRAM region @@ -306,12 +331,17 @@ void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, b * Sets Read, Write and Execute permission for specified unified-management block (0-3) in given memory region. * Applicable only to IRAM memory types * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM) * @param block Memory block identifier (0-3) * @param write_perm Write permission flag + * @param read_perm Read permission flag * @param exec_perm Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type + * ESP_ERR_INVALID_ARG on incorrect block number */ -void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm); +esp_err_t esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm); /** * @brief Sets permissions for high and low memory segment in IRAM region @@ -328,8 +358,10 @@ void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t bloc * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); +esp_err_t esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); /** * @brief Activates memory protection for all supported memory region types @@ -339,8 +371,10 @@ void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, b * @param invoke_panic_handler map mem.prot interrupt to ETS_MEMACCESS_ERR_INUM and thus invokes panic handler when fired ('true' not suitable for testing) * @param lock_feature sets LOCK bit, see esp_memprot_set_lock() ('true' not suitable for testing) * @param mem_type_mask holds a set of required memory protection types (bitmask built of mem_type_prot_t). NULL means default (MEMPROT_ALL in this version) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); +esp_err_t esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); /** * @brief Get permission settings bits for IRAM0 split mgmt. Only IRAM0 memory types allowed @@ -352,8 +386,10 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); +esp_err_t esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); /** * @brief Get permission settings bits for DRAM0 split mgmt. Only DRAM0 memory types allowed @@ -363,8 +399,10 @@ void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bo * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); +esp_err_t esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); /** * @brief Sets permissions for high and low memory segment in PERIBUS1 region @@ -378,8 +416,10 @@ void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bo * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); +esp_err_t esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); /** * @brief Get permission settings bits for PERIBUS1 split mgmt. Only PERIBUS1 memory types allowed @@ -389,8 +429,10 @@ void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); +esp_err_t esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); /** * @brief Get permission settings bits for PERIBUS2 split mgmt. Only PERIBUS2 memory types allowed @@ -402,25 +444,32 @@ void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, b * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); +esp_err_t esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); /** - * @brief Sets permissions for high and low memory segment in PERIBUS2 region + * @brief Configures the memory protection for high and low segment in PERIBUS2 region * * Sets Read Write permission for both low and high memory segments given by splitting address. * Applicable only to PERIBUS2 memory types * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param split_addr Address to split the memory region to lower and higher segment + * @param mem_type Memory protection area type (MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) + * @param split_addr Address to split the memory region to lower and higher segment (32bit aligned) * @param lw Low segment Write permission flag * @param lr Low segment Read permission flag * @param lx Low segment Execute permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type + * ESP_ERR_INVALID_STATE on splitting address out of PERIBUS2 range + * ESP_ERR_INVALID_SIZE on splitting address not 32-bit aligned */ -void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); +esp_err_t esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); /** * @brief Get permissions for specified memory type. Irrelevant bits are ignored @@ -432,8 +481,12 @@ void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lw/lr/lx/hw/hr/hx args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); +esp_err_t esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); /** * @brief Get Read permission settings for low and high regions of given memory type @@ -441,8 +494,12 @@ void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, b * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Read permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lr/hr args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); +esp_err_t esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); /** * @brief Get Write permission settings for low and high regions of given memory type @@ -450,23 +507,33 @@ void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Write permission flag * @param hr High segment Write permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lw/hw args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw); +esp_err_t esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw); /** * @brief Get Execute permission settings for low and high regions of given memory type * Applicable only to IBUS-compatible memory types * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Exec permission flag - * @param hr High segment Exec permission flag + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM, MEMPROT_IRAM0_RTCFAST, MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) + * @param lx Low segment Exec permission flag + * @param hx High segment Exec permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lx/hx args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx); +esp_err_t esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx); /** * @brief Returns the lowest address in required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return Required address or MEMPROT_INVALID_ADDRESS for invalid mem_type */ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type); @@ -474,6 +541,8 @@ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type); * @brief Returns the highest address in required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return Required address or MEMPROT_INVALID_ADDRESS for invalid mem_type */ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type); @@ -483,8 +552,11 @@ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type); * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Read permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); +esp_err_t esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); /** * @brief Sets WRITE permission bit for required memory region @@ -492,17 +564,23 @@ void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Write permission flag * @param hr High segment Write permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw); +esp_err_t esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw); /** * @brief Sets EXECUTE permission bit for required memory region * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM, MEMPROT_IRAM0_RTCFAST, MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) * @param lr Low segment Exec permission flag * @param hr High segment Exec permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx); +esp_err_t esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx); #ifdef __cplusplus diff --git a/components/esp_hw_support/port/esp32s2/memprot.c b/components/esp_hw_support/port/esp32s2/memprot.c index d149cf6303..685acfa2f6 100644 --- a/components/esp_hw_support/port/esp32s2/memprot.c +++ b/components/esp_hw_support/port/esp32s2/memprot.c @@ -14,22 +14,30 @@ #include "soc/dport_access.h" #include "soc/periph_defs.h" #include "esp_intr_alloc.h" - -#include "esp_log.h" -static const char *TAG = "memprot"; - -#include "esp32s2/memprot.h" #include "hal/memprot_ll.h" #include "hal/memprot_peri_ll.h" +#include "esp32s2/memprot.h" #include "esp_fault.h" - #include "soc/cpu.h" +#include "esp32s2/rom/ets_sys.h" extern int _iram_text_end; extern int _data_start; extern int _rtc_text_end; extern int _rtc_dummy_end; +static inline esp_err_t esp_memprot_ll_err_to_esp_err(memprot_ll_err_t err) +{ + switch (err) { + case MEMP_LL_OK: return ESP_OK; + case MEMP_LL_FAIL: return ESP_FAIL; + case MEMP_LL_ERR_SPLIT_ADDR_INVALID: return ESP_ERR_INVALID_STATE; + case MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED: return ESP_ERR_INVALID_SIZE; + case MEMP_LL_ERR_UNI_BLOCK_INVALID: return ESP_ERR_NOT_FOUND; + default: + return ESP_FAIL; + } +} uint32_t *esp_memprot_iram0_sram_get_min_split_addr(void) { @@ -53,17 +61,17 @@ uint32_t *esp_memprot_dram0_rtcfast_get_min_split_addr(void) uint32_t *esp_memprot_peri1_rtcslow_get_min_split_addr(void) { - return (uint32_t *)(PERI1_RTCSLOW_ADDRESS_BASE); + return (uint32_t *)PERI1_RTCSLOW_ADDRESS_BASE; } uint32_t *esp_memprot_peri2_rtcslow_0_get_min_split_addr(void) { - return (uint32_t *)(PERI2_RTCSLOW_0_ADDRESS_BASE); + return (uint32_t *)PERI2_RTCSLOW_0_ADDRESS_BASE; } uint32_t *esp_memprot_peri2_rtcslow_1_get_min_split_addr(void) { - return (uint32_t *)(PERI2_RTCSLOW_1_ADDRESS_BASE); + return (uint32_t *)PERI2_RTCSLOW_1_ADDRESS_BASE; } uint32_t *esp_memprot_get_split_addr(mem_type_prot_t mem_type) @@ -84,8 +92,7 @@ uint32_t *esp_memprot_get_split_addr(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return esp_memprot_peri2_rtcslow_1_get_min_split_addr(); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return (uint32_t *)MEMPROT_INVALID_ADDRESS; } } @@ -107,541 +114,673 @@ const char *esp_memprot_type_to_str(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return "PERI2_RTCSLOW_1"; default: - return "UNKOWN"; + return "INVALID_MEM_TYPE"; } } -void esp_memprot_intr_init(mem_type_prot_t mem_type) +esp_err_t esp_memprot_intr_init(mem_type_prot_t mem_type) { ESP_INTR_DISABLE(ETS_MEMACCESS_ERR_INUM); switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_iram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_iram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_dram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_dram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_PERI1_RTCSLOW: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_peri1_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_peri1_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_peri2_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_peri2_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } ESP_INTR_ENABLE(ETS_MEMACCESS_ERR_INUM); + + return ESP_OK; } -void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable) +esp_err_t esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_intr_ena(enable); + memprot_ll_iram0_intr_ena(enable); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_intr_ena(enable); + memprot_ll_dram0_intr_ena(enable); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_intr_ena(enable); + memprot_ll_peri1_intr_ena(enable); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_intr_ena(enable); + memprot_ll_peri2_intr_ena(enable); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } mem_type_prot_t esp_memprot_get_active_intr_memtype() { - if (esp_memprot_iram0_sram_is_intr_mine()) { + if (memprot_ll_iram0_sram_is_intr_mine()) { return MEMPROT_IRAM0_SRAM; - } else if (esp_memprot_iram0_rtcfast_is_intr_mine()) { + } else if (memprot_ll_iram0_rtcfast_is_intr_mine()) { return MEMPROT_IRAM0_RTCFAST; - } else if (esp_memprot_dram0_sram_is_intr_mine()) { + } else if (memprot_ll_dram0_sram_is_intr_mine()) { return MEMPROT_DRAM0_SRAM; - } else if (esp_memprot_dram0_rtcfast_is_intr_mine()) { + } else if (memprot_ll_dram0_rtcfast_is_intr_mine()) { return MEMPROT_DRAM0_RTCFAST; - } else if (esp_memprot_peri1_rtcslow_is_intr_mine()) { + } else if (memprot_ll_peri1_rtcslow_is_intr_mine()) { return MEMPROT_PERI1_RTCSLOW; - } else if (esp_memprot_peri2_rtcslow_0_is_intr_mine()) { + } else if (memprot_ll_peri2_rtcslow_0_is_intr_mine()) { return MEMPROT_PERI2_RTCSLOW_0; - } else if (esp_memprot_peri2_rtcslow_1_is_intr_mine()) { + } else if (memprot_ll_peri2_rtcslow_1_is_intr_mine()) { return MEMPROT_PERI2_RTCSLOW_1; } return MEMPROT_NONE; } -void esp_memprot_clear_intr(mem_type_prot_t mem_type) +esp_err_t esp_memprot_clear_intr(mem_type_prot_t mem_type) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_clear_intr(); + memprot_ll_iram0_clear_intr(); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_clear_intr(); + memprot_ll_dram0_clear_intr(); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_clear_intr(); + memprot_ll_peri1_clear_intr(); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_clear_intr(); + memprot_ll_peri2_clear_intr(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_lock(mem_type_prot_t mem_type) +esp_err_t esp_memprot_set_lock(mem_type_prot_t mem_type) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_set_lock(); + memprot_ll_iram0_set_lock(); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_set_lock(); + memprot_ll_dram0_set_lock(); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_set_lock(); + memprot_ll_peri1_set_lock(); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_set_lock(); + memprot_ll_peri2_set_lock(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -bool esp_memprot_get_lock(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_lock(mem_type_prot_t mem_type, bool *locked) { + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_lock_bit() > 0; + *locked = memprot_ll_iram0_get_lock_bit() > 0; + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_lock_bit() > 0; + *locked = memprot_ll_dram0_get_lock_bit() > 0; + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_lock_bit() > 0; + *locked = memprot_ll_peri1_get_lock_bit() > 0; + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_lock_bit() > 0; + *locked = memprot_ll_peri2_get_lock_bit() > 0; + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } bool esp_memprot_is_locked_any() { return - esp_memprot_iram0_get_lock_bit() > 0 || - esp_memprot_dram0_get_lock_bit() > 0 || - esp_memprot_peri1_get_lock_bit() > 0 || - esp_memprot_peri2_get_lock_bit() > 0; + memprot_ll_iram0_get_lock_bit() > 0 || + memprot_ll_dram0_get_lock_bit() > 0 || + memprot_ll_peri1_get_lock_bit() > 0 || + memprot_ll_peri2_get_lock_bit() > 0; } -uint32_t esp_memprot_get_lock_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type, uint32_t *conf_reg_val) { + if (conf_reg_val == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_lock_bit(); + *conf_reg_val = memprot_ll_iram0_get_conf_reg(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_lock_bit(); + *conf_reg_val = memprot_ll_dram0_get_conf_reg(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_lock_bit(); + *conf_reg_val = memprot_ll_peri1_rtcslow_get_conf_reg(); + break; case MEMPROT_PERI2_RTCSLOW_0: + *conf_reg_val = memprot_ll_peri2_rtcslow_0_get_conf_reg(); + break; case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_lock_bit(); + *conf_reg_val = memprot_ll_peri2_rtcslow_1_get_conf_reg(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type, uint32_t *fault_reg_val) { + if (fault_reg_val == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_conf_reg(); + *fault_reg_val = memprot_ll_iram0_get_fault_reg(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_conf_reg(); + *fault_reg_val = memprot_ll_dram0_get_fault_reg(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_rtcslow_get_conf_reg(); + *fault_reg_val = memprot_ll_peri1_get_fault_reg(); + break; case MEMPROT_PERI2_RTCSLOW_0: - return esp_memprot_peri2_rtcslow_0_get_conf_reg(); case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_rtcslow_1_get_conf_reg(); + *fault_reg_val = memprot_ll_peri2_get_fault_reg(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) { - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_fault_reg(); - case MEMPROT_DRAM0_SRAM: - case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_fault_reg(); - case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_fault_reg(); - case MEMPROT_PERI2_RTCSLOW_0: - case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_fault_reg(); - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + if (*faulting_address == NULL || op_type == NULL || op_subtype == NULL) { + return ESP_ERR_INVALID_ARG; } -} -void esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) -{ switch (mem_type) { case MEMPROT_IRAM0_SRAM: - *faulting_address = esp_memprot_iram0_sram_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_iram0_sram_get_fault_address(); + memprot_ll_iram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_IRAM0_RTCFAST: - *faulting_address = esp_memprot_iram0_rtcfast_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_iram0_rtcfast_get_fault_address(); + memprot_ll_iram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_DRAM0_SRAM: - *faulting_address = esp_memprot_dram0_sram_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_dram0_sram_get_fault_address(); + memprot_ll_dram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_DRAM0_RTCFAST: - *faulting_address = esp_memprot_dram0_rtcfast_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_dram0_rtcfast_get_fault_address(); + memprot_ll_dram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_PERI1_RTCSLOW: - *faulting_address = esp_memprot_peri1_rtcslow_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_peri1_rtcslow_get_fault_address(); + memprot_ll_peri1_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_peri2_rtcslow_get_fault_address(); + memprot_ll_peri2_get_fault_op_type(op_type, op_subtype); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } - if (mem_type == MEMPROT_IRAM0_SRAM || mem_type == MEMPROT_IRAM0_RTCFAST) { - esp_memprot_iram0_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_DRAM0_SRAM || mem_type == MEMPROT_DRAM0_RTCFAST) { - esp_memprot_dram0_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_PERI1_RTCSLOW) { - esp_memprot_peri1_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_PERI2_RTCSLOW_0 || mem_type == MEMPROT_PERI2_RTCSLOW_1) { - esp_memprot_peri2_get_fault_op_type(op_type, op_subtype); - } + return ESP_OK; } bool esp_memprot_is_intr_ena_any() { return - esp_memprot_iram0_get_intr_ena_bit() > 0 || - esp_memprot_dram0_get_intr_ena_bit() > 0 || - esp_memprot_peri1_get_intr_ena_bit() > 0 || - esp_memprot_peri2_get_intr_ena_bit() > 0; + memprot_ll_iram0_get_intr_ena_bit() > 0 || + memprot_ll_dram0_get_intr_ena_bit() > 0 || + memprot_ll_peri1_get_intr_ena_bit() > 0 || + memprot_ll_peri2_get_intr_ena_bit() > 0; } -uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type, uint32_t *enable_bit) { + if (enable_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_ena_bit(); + *enable_bit = memprot_ll_iram0_get_intr_ena_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_ena_bit(); + *enable_bit = memprot_ll_dram0_get_intr_ena_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_ena_bit(); + *enable_bit = memprot_ll_peri1_get_intr_ena_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_ena_bit(); + *enable_bit = memprot_ll_peri2_get_intr_ena_bit(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type, uint32_t *intr_on_bit) { + if (intr_on_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_on_bit(); + *intr_on_bit = memprot_ll_iram0_get_intr_on_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_on_bit(); + *intr_on_bit = memprot_ll_dram0_get_intr_on_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_on_bit(); + *intr_on_bit = memprot_ll_peri1_get_intr_on_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_on_bit(); + *intr_on_bit = memprot_ll_peri2_get_intr_on_bit(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type, uint32_t *clear_bit) { + if (clear_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_clr_bit(); + *clear_bit = memprot_ll_iram0_get_intr_clr_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_clr_bit(); + *clear_bit = memprot_ll_dram0_get_intr_clr_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_clr_bit(); + *clear_bit = memprot_ll_peri1_get_intr_clr_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_clr_bit(); - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_read_bit(block); - case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_uni_block_read_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_write_bit(block); - case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_uni_block_write_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_exec_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm) -{ - switch (mem_type) { - case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_uni_block_perm(block, write_perm, read_perm); + *clear_bit = memprot_ll_peri2_get_intr_clr_bit(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *read_bit) { + if (read_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_OK; + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_perm_uni_reg(); + if (!memprot_ll_iram0_sram_get_uni_block_read_bit(block, read_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_perm_reg(); + if (!memprot_ll_dram0_sram_get_uni_block_read_bit(block, read_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + ret = ESP_ERR_NOT_SUPPORTED; + break; } + + return ret; } -uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *write_bit) { + if (write_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_OK; + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_perm_split_reg(); - case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_rtcfast_get_perm_split_reg(); + if (!memprot_ll_iram0_sram_get_uni_block_write_bit(block, write_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_perm_reg(); - case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_rtcfast_get_perm_split_reg(); - case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_rtcslow_get_conf_reg(); - case MEMPROT_PERI2_RTCSLOW_0: - return esp_memprot_peri2_rtcslow_0_get_conf_reg(); - case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_rtcslow_1_get_conf_reg(); + if (!memprot_ll_dram0_sram_get_uni_block_write_bit(block, write_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + ret = ESP_ERR_NOT_SUPPORTED; + break; } + + return ret; } -void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +esp_err_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *exec_bit) +{ + if (exec_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + if (!memprot_ll_iram0_sram_get_uni_block_exec_bit(block, exec_bit)) { + return ESP_ERR_NOT_FOUND; + } + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm) { switch (mem_type) { case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_sram_get_min_split_addr(), lw, lr, hw, hr); - break; - case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_rtcfast_get_min_split_addr(), lw, lr, hw, hr); - break; + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_sram_set_uni_block_perm(block, write_perm, read_perm)); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +esp_err_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type, uint32_t *perm_reg) { + if (perm_reg == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_uni_block_perm(block, write_perm, read_perm, exec_perm); + *perm_reg = memprot_ll_iram0_sram_get_perm_uni_reg(); + break; + case MEMPROT_DRAM0_SRAM: + *perm_reg = memprot_ll_dram0_sram_get_perm_reg(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +esp_err_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type, uint32_t *split_reg) { + if (split_reg == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_sram_get_min_split_addr(), lw, lr, lx, hw, hr, hx); + *split_reg = memprot_ll_iram0_sram_get_perm_split_reg(); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_rtcfast_get_min_split_addr(), lw, lr, lx, hw, hr, hx); + *split_reg = memprot_ll_iram0_rtcfast_get_perm_split_reg(); + break; + case MEMPROT_DRAM0_SRAM: + *split_reg = memprot_ll_dram0_sram_get_perm_reg(); + break; + case MEMPROT_DRAM0_RTCFAST: + *split_reg = memprot_ll_dram0_rtcfast_get_perm_split_reg(); + break; + case MEMPROT_PERI1_RTCSLOW: + *split_reg = memprot_ll_peri1_rtcslow_get_conf_reg(); + break; + case MEMPROT_PERI2_RTCSLOW_0: + *split_reg = memprot_ll_peri2_rtcslow_0_get_conf_reg(); + break; + case MEMPROT_PERI2_RTCSLOW_1: + *split_reg = memprot_ll_peri2_rtcslow_1_get_conf_reg(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; - case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} - -void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +esp_err_t esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { switch (mem_type) { case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_sram_get_min_split_addr(), lw, lr, hw, hr)); + case MEMPROT_DRAM0_RTCFAST: + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_rtcfast_get_min_split_addr(), lw, lr, hw, hr)); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +esp_err_t esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +{ + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + if (!memprot_ll_iram0_sram_set_uni_block_perm(block, write_perm, read_perm, exec_perm)) { + return ESP_ERR_INVALID_ARG; + } + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +{ + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + return esp_memprot_ll_err_to_esp_err(memprot_ll_iram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_sram_get_min_split_addr(), lw, lr, lx, hw, hr, hx)); + case MEMPROT_IRAM0_RTCFAST: + return esp_memprot_ll_err_to_esp_err(memprot_ll_iram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_rtcfast_get_min_split_addr(), lw, lr, lx, hw, hr, hx)); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +esp_err_t esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +{ + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + memprot_ll_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + case MEMPROT_IRAM0_RTCFAST: + memprot_ll_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +{ + if (lw == NULL || lr == NULL || hw == NULL || hr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_DRAM0_SRAM: + memprot_ll_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +esp_err_t esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +{ + if (lw == NULL || lr == NULL || hw == NULL || hr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_PERI1_RTCSLOW: + memprot_ll_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { switch (mem_type) { case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri1_rtcslow_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri1_rtcslow_get_min_split_addr(), + lw, + lr, + hw, + hr) + ); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +esp_err_t esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { - case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri1_rtcslow_get_min_split_addr(), lw, lr, hw, hr); + case MEMPROT_PERI2_RTCSLOW_0: + memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + case MEMPROT_PERI2_RTCSLOW_1: + memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +esp_err_t esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { switch (mem_type) { case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri2_rtcslow_0_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_0_get_min_split_addr(), + lw, + lr, + lx, + hw, + hr, + hx) + ); case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri2_rtcslow_1_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_1_get_min_split_addr(), + lw, + lr, + lx, + hw, + hr, + hx) + ); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +esp_err_t esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) { - switch (mem_type) { - case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_0_get_min_split_addr(), lw, lr, lx, hw, hr, hx); - break; - case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_1_get_min_split_addr(), lw, lr, lx, hw, hr, hx); - break; - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} + esp_err_t ret; -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) -{ //any IRAM0/DRAM0 enable/disable call applies to all memory modules connected uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask; bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM || required_mem_prot & MEMPROT_IRAM0_RTCFAST; @@ -650,17 +789,17 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t bool use_peri2 = required_mem_prot & MEMPROT_PERI2_RTCSLOW_0 || required_mem_prot & MEMPROT_PERI2_RTCSLOW_1; //disable protection - if (use_iram0) { - esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, false); + if (use_iram0 && (ret = esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, false)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, false); + if (use_dram0 && (ret = esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, false)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, false); + if (use_peri1 && (ret = esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, false)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, false); + if (use_peri2 && (ret = esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, false)) != ESP_OK) { + return ret; } //connect to intr. matrix if not being debugged @@ -670,134 +809,172 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t //initialize for specific buses (any memory type does the job) if (invoke_panic_handler) { - if (use_iram0) { - esp_memprot_intr_init(MEMPROT_IRAM0_SRAM); + if (use_iram0 && (ret = esp_memprot_intr_init(MEMPROT_IRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_init(MEMPROT_DRAM0_SRAM); + if (use_dram0 && (ret = esp_memprot_intr_init(MEMPROT_DRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_init(MEMPROT_PERI1_RTCSLOW); + if (use_peri1 && (ret = esp_memprot_intr_init(MEMPROT_PERI1_RTCSLOW)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_init(MEMPROT_PERI2_RTCSLOW_0); + if (use_peri2 && (ret = esp_memprot_intr_init(MEMPROT_PERI2_RTCSLOW_0)) != ESP_OK) { + return ret; } } //set permissions if (required_mem_prot & MEMPROT_IRAM0_SRAM) { - esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_IRAM0_RTCFAST) { - esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_DRAM0_SRAM) { - esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + ret = esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_DRAM0_RTCFAST) { - esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + ret = esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI1_RTCSLOW) { - esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS); + ret = esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_0) { - esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, DEF_SPLIT_LINE, WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS); + ret = esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, DEF_SPLIT_LINE, WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_1) { - esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } //reenable protection (bus based) - if (use_iram0) { - esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, true); + if (use_iram0 && (ret = esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, true)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, true); + if (use_dram0 && (ret = esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, true)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, true); + if (use_peri1 && (ret = esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, true)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, true); + if (use_peri2 && (ret = esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, true)) != ESP_OK) { + return ret; } //lock if required (bus based) if (lock_feature) { - if (use_iram0) { - esp_memprot_set_lock(MEMPROT_IRAM0_SRAM); + if (use_iram0 && (ret = esp_memprot_set_lock(MEMPROT_IRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_set_lock(MEMPROT_DRAM0_SRAM); + if (use_dram0 && (ret = esp_memprot_set_lock(MEMPROT_DRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_set_lock(MEMPROT_PERI1_RTCSLOW); + if (use_peri1 && (ret = esp_memprot_set_lock(MEMPROT_PERI1_RTCSLOW)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_set_lock(MEMPROT_PERI2_RTCSLOW_0); + if (use_peri2 && (ret = esp_memprot_set_lock(MEMPROT_PERI2_RTCSLOW_0)) != ESP_OK) { + return ret; } } } + + return ESP_OK; } -void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +esp_err_t esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr) +esp_err_t esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr) { bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lr = _lr; - *hr = _hr; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lr = _lr; + *hr = _hr; + } + return ret; } -void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw) +esp_err_t esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw) { bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lw = _lw; - *hw = _hw; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lw = _lw; + *hw = _hw; + } + + return ret; } -void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx) +esp_err_t esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx) { - if ( mem_type == MEMPROT_DRAM0_SRAM || + if (mem_type == MEMPROT_DRAM0_SRAM || mem_type == MEMPROT_DRAM0_RTCFAST || - mem_type == MEMPROT_PERI1_RTCSLOW ) { - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + mem_type == MEMPROT_PERI1_RTCSLOW) { + return ESP_ERR_NOT_SUPPORTED; } bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lx = _lx; - *hx = _hx; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lx = _lx; + *hx = _hx; + } + + return ret; } uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type) @@ -818,8 +995,7 @@ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return PERI2_RTCSLOW_1_ADDRESS_LOW; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return MEMPROT_INVALID_ADDRESS; } } @@ -841,88 +1017,90 @@ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return PERI2_RTCSLOW_1_ADDRESS_HIGH; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return MEMPROT_INVALID_ADDRESS; } } -void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr) +esp_err_t esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_read_perm(lr, hr); + memprot_ll_iram0_sram_set_read_perm(lr, hr); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_read_perm(lr, hr); + memprot_ll_dram0_sram_set_read_perm(lr, hr); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_read_perm(lr, hr); + memprot_ll_iram0_rtcfast_set_read_perm(lr, hr); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_read_perm(lr, hr); + memprot_ll_dram0_rtcfast_set_read_perm(lr, hr); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_read_perm(lr, hr); + memprot_ll_peri1_rtcslow_set_read_perm(lr, hr); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_read_perm(lr, hr); + memprot_ll_peri2_rtcslow_0_set_read_perm(lr, hr); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_read_perm(lr, hr); + memprot_ll_peri2_rtcslow_1_set_read_perm(lr, hr); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw) +esp_err_t esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_write_perm(lw, hw); + memprot_ll_iram0_sram_set_write_perm(lw, hw); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_write_perm(lw, hw); + memprot_ll_dram0_sram_set_write_perm(lw, hw); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_write_perm(lw, hw); + memprot_ll_iram0_rtcfast_set_write_perm(lw, hw); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_write_perm(lw, hw); + memprot_ll_dram0_rtcfast_set_write_perm(lw, hw); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_write_perm(lw, hw); + memprot_ll_peri1_rtcslow_set_write_perm(lw, hw); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_write_perm(lw, hw); + memprot_ll_peri2_rtcslow_0_set_write_perm(lw, hw); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_write_perm(lw, hw); + memprot_ll_peri2_rtcslow_1_set_write_perm(lw, hw); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx) +esp_err_t esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_exec_perm(lx, hx); + memprot_ll_iram0_sram_set_exec_perm(lx, hx); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_exec_perm(lx, hx); + memprot_ll_iram0_rtcfast_set_exec_perm(lx, hx); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_exec_perm(lx, hx); + memprot_ll_peri2_rtcslow_0_set_exec_perm(lx, hx); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_exec_perm(lx, hx); + memprot_ll_peri2_rtcslow_1_set_exec_perm(lx, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index fb1e021df0..6ca03b520c 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -76,7 +76,7 @@ void panic_print_registers(const void *f, int core) && ((core == 0 && frame->exccause == PANIC_RSN_INTWDT_CPU0) || (core == 1 && frame->exccause == PANIC_RSN_INTWDT_CPU1)) #endif //!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - ) { + ) { panic_print_str("\r\n"); @@ -264,27 +264,46 @@ static inline void print_cache_err_details(const void *f) } #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#define MEMPROT_OP_INVALID 0xFFFFFFFF static inline void print_memprot_err_details(const void *f) { uint32_t *fault_addr; uint32_t op_type, op_subtype; - mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); - esp_memprot_get_fault_status( mem_type, &fault_addr, &op_type, &op_subtype ); + char *operation_type; - char *operation_type = "Write"; - if ( op_type == 0 ) { - operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read"; + mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); + if (mem_type != MEMPROT_NONE) { +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + if (esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype) != ESP_OK) { + op_type = MEMPROT_OP_INVALID; + } +#else + esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype); +#endif } - panic_print_str( operation_type ); - panic_print_str( " operation at address 0x" ); - panic_print_hex( (uint32_t)fault_addr ); - panic_print_str(" not permitted.\r\n"); + if (op_type == MEMPROT_OP_INVALID) { + operation_type = "Unknown"; + fault_addr = (uint32_t *)MEMPROT_OP_INVALID; + } else { + if (op_type == 0) { + operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read"; + } else { + operation_type = "Write"; + } + } + + panic_print_str(operation_type); + panic_print_str(" operation at address 0x"); + panic_print_hex((uint32_t)fault_addr); + panic_print_str(" not permitted ("); + panic_print_str(esp_memprot_type_to_str(mem_type)); + panic_print_str(")\r\n"); } #endif #elif CONFIG_IDF_TARGET_ESP32S3 -static inline void print_cache_err_details(const void* f) +static inline void print_cache_err_details(const void *f) { uint32_t vaddr = 0, size = 0; uint32_t status; @@ -355,7 +374,7 @@ static inline void print_cache_err_details(const void* f) void panic_arch_fill_info(void *f, panic_info_t *info) { - XtExcFrame *frame = (XtExcFrame*) f; + XtExcFrame *frame = (XtExcFrame *) f; static const char *reason[] = { "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError", "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue", @@ -388,7 +407,7 @@ void panic_soc_fill_info(void *f, panic_info_t *info) { // [refactor-todo] this should be in the common port panic_handler.c, once // these special exceptions are supported in there. - XtExcFrame *frame = (XtExcFrame*) f; + XtExcFrame *frame = (XtExcFrame *) f; if (frame->exccause == PANIC_RSN_INTWDT_CPU0) { info->core = 0; info->exception = PANIC_EXCEPTION_IWDT; @@ -442,19 +461,19 @@ void panic_soc_fill_info(void *f, panic_info_t *info) #endif } -uint32_t panic_get_address(const void* f) +uint32_t panic_get_address(const void *f) { - return ((XtExcFrame*)f)->pc; + return ((XtExcFrame *)f)->pc; } -uint32_t panic_get_cause(const void* f) +uint32_t panic_get_cause(const void *f) { - return ((XtExcFrame*)f)->exccause; + return ((XtExcFrame *)f)->exccause; } void panic_set_address(void *f, uint32_t addr) { - ((XtExcFrame*)f)->pc = addr; + ((XtExcFrame *)f)->pc = addr; } void panic_print_backtrace(const void *f, int core) diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 9c91e94440..457b7c3992 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -305,7 +305,7 @@ void IRAM_ATTR call_start_cpu0(void) // from panic handler we can be reset by RWDT or TG0WDT if (rst_reas[0] == RESET_REASON_CORE_RTC_WDT || rst_reas[0] == RESET_REASON_CORE_MWDT0 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - || rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0 + || rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0 #endif ) { wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL}; @@ -513,15 +513,28 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE // Memprot cannot be locked during OS startup as the lock-on prevents any PMS changes until a next reboot // If such a situation appears, it is likely an malicious attempt to bypass the system safety setup -> print error & reset - if ( esp_memprot_is_locked_any() ) { + if (esp_memprot_is_locked_any()) { ESP_EARLY_LOGE(TAG, "Memprot feature locked after the system reset! Potential safety corruption, rebooting."); esp_restart_noos_dig(); } + esp_err_t memp_err = ESP_OK; #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + memp_err = esp_memprot_set_prot(true, true, NULL); +#else esp_memprot_set_prot(true, true, NULL); +#endif +#else +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + memp_err = esp_memprot_set_prot(true, false, NULL); #else esp_memprot_set_prot(true, false, NULL); #endif +#endif + if (memp_err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (error 0x%08X), rebooting.", memp_err); + esp_restart_noos_dig(); + } #endif bootloader_flash_update_id(); diff --git a/components/hal/esp32s2/include/hal/memprot_ll.h b/components/hal/esp32s2/include/hal/memprot_ll.h index eeaa73dcc8..fa77e2f3ab 100644 --- a/components/hal/esp32s2/include/hal/memprot_ll.h +++ b/components/hal/esp32s2/include/hal/memprot_ll.h @@ -14,7 +14,9 @@ #pragma once -#include "hal/assert.h" +#include +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" #ifdef __cplusplus extern "C" { @@ -25,23 +27,18 @@ extern "C" { * === IRAM0 common * ======================================================================================== */ -//IRAM0 interrupt status bitmasks -#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 -#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 -#define CONF_REG_ADDRESS_SHIFT 2 - -static inline void esp_memprot_iram0_clear_intr(void) +static inline void memprot_ll_iram0_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); } -static inline uint32_t esp_memprot_iram0_get_intr_source_num(void) +static inline uint32_t memprot_ll_iram0_get_intr_source_num(void) { return ETS_PMS_PRO_IRAM0_ILG_INTR_SOURCE; } -static inline void esp_memprot_iram0_intr_ena(bool enable) +static inline void memprot_ll_iram0_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN); @@ -50,55 +47,55 @@ static inline void esp_memprot_iram0_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_iram0_get_conf_reg(void) +static inline uint32_t memprot_ll_iram0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_4_REG); } -static inline uint32_t esp_memprot_iram0_get_fault_reg(void) +static inline uint32_t memprot_ll_iram0_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_5_REG); } -static inline void esp_memprot_iram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_iram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); *op_type = (uint32_t)status_bits & IRAM0_INTR_ST_OP_RW_BIT; *op_subtype = (uint32_t)status_bits & IRAM0_INTR_ST_OP_TYPE_BIT; } -static inline bool esp_memprot_iram0_is_assoc_intr(void) +static inline bool memprot_ll_iram0_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR) > 0; } -static inline uint32_t esp_memprot_iram0_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN); } -static inline uint32_t esp_memprot_iram0_get_intr_on_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR); } -static inline uint32_t esp_memprot_iram0_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); } //resets automatically on CPU restart -static inline void esp_memprot_iram0_set_lock(void) +static inline void memprot_ll_iram0_set_lock(void) { DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); } -static inline uint32_t esp_memprot_iram0_get_lock_reg(void) +static inline uint32_t memprot_ll_iram0_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_0_REG); } -static inline uint32_t esp_memprot_iram0_get_lock_bit(void) +static inline uint32_t memprot_ll_iram0_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); } @@ -108,52 +105,26 @@ static inline uint32_t esp_memprot_iram0_get_lock_bit(void) * === IRAM0 SRAM * ======================================================================================== */ -#define IRAM0_SRAM_BASE_ADDRESS 0x40000000 -#define IRAM0_SRAM_ADDRESS_LOW 0x40020000 -#define IRAM0_SRAM_ADDRESS_HIGH 0x4006FFFF - -#define IRAM0_SRAM_TOTAL_UNI_BLOCKS 4 -#define IRAM0_SRAM_UNI_BLOCK_0 0 -#define IRAM0_SRAM_UNI_BLOCK_1 1 -#define IRAM0_SRAM_UNI_BLOCK_2 2 -#define IRAM0_SRAM_UNI_BLOCK_3 3 - -//unified management (SRAM blocks 0-3) -#define IRAM0_SRAM_UNI_BLOCK_0_LOW 0x40020000 -#define IRAM0_SRAM_UNI_BLOCK_1_LOW 0x40022000 -#define IRAM0_SRAM_UNI_BLOCK_2_LOW 0x40024000 -#define IRAM0_SRAM_UNI_BLOCK_3_LOW 0x40026000 - -//split management (SRAM blocks 4-21) -#define IRAM0_SRAM_SPL_BLOCK_LOW 0x40028000 //block 4 low -#define IRAM0_SRAM_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high - -#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //bits 21:6 in the reg, as well as in real address -#define IRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x40000000 //high nonsignificant bits 31:22 of the faulting address - constant - -#define IRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) - -static inline uint32_t *esp_memprot_iram0_sram_get_fault_address(void) +static inline intptr_t memprot_ll_iram0_sram_get_fault_address(void) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); - return (uint32_t *)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_SRAM_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); + return (intptr_t)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_SRAM_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_iram0_sram_is_intr_mine(void) +static inline bool memprot_ll_iram0_sram_is_intr_mine(void) { - if (esp_memprot_iram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_iram0_sram_get_fault_address(); - return (uint32_t)faulting_address >= IRAM0_SRAM_ADDRESS_LOW && (uint32_t)faulting_address <= IRAM0_SRAM_ADDRESS_HIGH; + if (memprot_ll_iram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_iram0_sram_get_fault_address(); + return faulting_address >= IRAM0_SRAM_ADDRESS_LOW && faulting_address <= IRAM0_SRAM_ADDRESS_HIGH; } return false; } //block 0-3 -static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +static inline bool memprot_ll_iram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - uint32_t write_bit, read_bit, exec_bit; + switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; @@ -176,7 +147,7 @@ static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, boo exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; break; default: - abort(); + return false; } if (write_perm) { @@ -196,66 +167,78 @@ static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, boo } else { DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_1_REG, exec_bit); } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_read_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_read_bit(uint32_t block, uint32_t *read_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_write_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_write_bit(uint32_t block, uint32_t *write_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_exec_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_exec_bit(uint32_t block, uint32_t *exec_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F); + break; default: - abort(); + return false; } + + return true; } -static inline void esp_memprot_iram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit) +static inline bool memprot_ll_iram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: *write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; @@ -278,25 +261,33 @@ static inline void esp_memprot_iram0_sram_get_uni_block_sgnf_bits(uint32_t block *exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_perm_uni_reg(void) +static inline uint32_t memprot_ll_iram0_sram_get_perm_uni_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG); } -static inline uint32_t esp_memprot_iram0_sram_get_perm_split_reg(void) +static inline uint32_t memprot_ll_iram0_sram_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG); } -static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_iram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr <= IRAM0_SRAM_SPL_BLOCK_HIGH); - HAL_ASSERT(addr % 0x4 == 0); + + //sanity check: split address required above unified mgmt region & 32bit aligned + if (addr > IRAM0_SRAM_SPL_BLOCK_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //find possible split.address in low region blocks int uni_blocks_low = -1; @@ -318,7 +309,9 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw uint32_t uni_block_perm = 0; for (int x = 0; x < IRAM0_SRAM_TOTAL_UNI_BLOCKS; x++) { - esp_memprot_iram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit); + if (!memprot_ll_iram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } if (x <= uni_blocks_low) { if (lw) { uni_block_perm |= write_bit; @@ -346,7 +339,7 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw uint32_t reg_split_addr = 0; if (addr >= IRAM0_SRAM_SPL_BLOCK_LOW) { - reg_split_addr = IRAM0_SRAM_ADDR_TO_CONF_REG( addr ); //cfg reg - [16:0] + reg_split_addr = IRAM0_SRAM_ADDR_TO_CONF_REG(addr); //cfg reg - [16:0] } //prepare high & low permission mask (bits: [22:20] high range, [19:17] low range) @@ -373,9 +366,11 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw //write IRAM SRAM uni & splt cfg. registers DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG, uni_block_perm); DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG, (uint32_t)(reg_split_addr | permission_mask)); + + return MEMP_LL_OK; } -static inline void esp_memprot_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R); @@ -385,19 +380,19 @@ static inline void esp_memprot_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F); } -static inline void esp_memprot_iram0_sram_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_iram0_sram_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_R, hr ? 1 : 0); } -static inline void esp_memprot_iram0_sram_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_iram0_sram_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_W, hw ? 1 : 0); } -static inline void esp_memprot_iram0_sram_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_iram0_sram_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F, hx ? 1 : 0); @@ -409,37 +404,37 @@ static inline void esp_memprot_iram0_sram_set_exec_perm(bool lx, bool hx) * === IRAM0 RTC FAST * ======================================================================================== */ -#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000 -#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF -#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant) - -#define IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_iram0_rtcfast_get_fault_address(void) +static inline intptr_t memprot_ll_iram0_rtcfast_get_fault_address(void) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); - return (uint32_t *)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); + return (intptr_t)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_iram0_rtcfast_is_intr_mine(void) +static inline bool memprot_ll_iram0_rtcfast_is_intr_mine(void) { - if (esp_memprot_iram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_iram0_rtcfast_get_fault_address(); - return (uint32_t)faulting_address >= IRAM0_RTCFAST_ADDRESS_LOW && (uint32_t)faulting_address <= IRAM0_RTCFAST_ADDRESS_HIGH; + if (memprot_ll_iram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_iram0_rtcfast_get_fault_address(); + return faulting_address >= IRAM0_RTCFAST_ADDRESS_LOW && faulting_address <= IRAM0_RTCFAST_ADDRESS_HIGH; } return false; } -static inline uint32_t esp_memprot_iram0_rtcfast_get_perm_split_reg(void) +static inline uint32_t memprot_ll_iram0_rtcfast_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_3_REG); } -static inline void esp_memprot_iram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_iram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //32bit aligned + if (addr < IRAM0_RTCFAST_ADDRESS_LOW || addr > IRAM0_RTCFAST_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //conf reg [10:0] uint32_t reg_split_addr = IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr); @@ -467,9 +462,11 @@ static inline void esp_memprot_iram0_rtcfast_set_prot(uint32_t *split_addr, bool //write IRAM0 RTCFAST cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_3_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_R); @@ -479,19 +476,19 @@ static inline void esp_memprot_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_F); } -static inline void esp_memprot_iram0_rtcfast_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_iram0_rtcfast_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_R, hr ? 1 : 0); } -static inline void esp_memprot_iram0_rtcfast_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_iram0_rtcfast_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_W, hw ? 1 : 0); } -static inline void esp_memprot_iram0_rtcfast_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_iram0_rtcfast_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_F, hx ? 1 : 0); @@ -503,19 +500,12 @@ static inline void esp_memprot_iram0_rtcfast_set_exec_perm(bool lx, bool hx) * === DRAM0 common * ======================================================================================== */ -//DRAM0 interrupt status bitmasks -#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) -#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) -#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1 -#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1 - - -static inline uint32_t esp_memprot_dram0_get_intr_source_num(void) +static inline uint32_t memprot_ll_dram0_get_intr_source_num(void) { return ETS_PMS_PRO_DRAM0_ILG_INTR_SOURCE; } -static inline void esp_memprot_dram0_intr_ena(bool enable) +static inline void memprot_ll_dram0_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN); @@ -524,112 +514,87 @@ static inline void esp_memprot_dram0_intr_ena(bool enable) } } -static inline bool esp_memprot_dram0_is_assoc_intr(void) +static inline bool memprot_ll_dram0_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR) > 0; } -static inline void esp_memprot_dram0_clear_intr(void) +static inline void memprot_ll_dram0_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); } -static inline uint32_t esp_memprot_dram0_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN); } -static inline uint32_t esp_memprot_dram0_get_intr_on_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR); } -static inline uint32_t esp_memprot_dram0_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); } //lock resets automatically on CPU restart -static inline void esp_memprot_dram0_set_lock(void) +static inline void memprot_ll_dram0_set_lock(void) { DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); } -static inline uint32_t esp_memprot_dram0_get_lock_reg(void) +static inline uint32_t memprot_ll_dram0_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG); } -static inline uint32_t esp_memprot_dram0_get_lock_bit(void) +static inline uint32_t memprot_ll_dram0_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); } -static inline uint32_t esp_memprot_dram0_get_conf_reg(void) +static inline uint32_t memprot_ll_dram0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_3_REG); } -static inline uint32_t esp_memprot_dram0_get_fault_reg(void) +static inline uint32_t memprot_ll_dram0_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_4_REG); } -static inline void esp_memprot_dram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_dram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); *op_type = status_bits & DRAM0_INTR_ST_OP_RW_BIT; *op_subtype = status_bits & DRAM0_INTR_ST_OP_ATOMIC_BIT; } - /** * ======================================================================================== * === DRAM0 SRAM * ======================================================================================== */ -#define DRAM0_SRAM_ADDRESS_LOW 0x3FFB0000 -#define DRAM0_SRAM_ADDRESS_HIGH 0x3FFFFFFF - -#define DRAM0_SRAM_TOTAL_UNI_BLOCKS 4 -#define DRAM0_SRAM_UNI_BLOCK_0 0 -#define DRAM0_SRAM_UNI_BLOCK_1 1 -#define DRAM0_SRAM_UNI_BLOCK_2 2 -#define DRAM0_SRAM_UNI_BLOCK_3 3 - -//unified management (SRAM blocks 0-3) -#define DRAM0_SRAM_UNI_BLOCK_0_LOW 0x3FFB0000 -#define DRAM0_SRAM_UNI_BLOCK_1_LOW 0x3FFB2000 -#define DRAM0_SRAM_UNI_BLOCK_2_LOW 0x3FFB4000 -#define DRAM0_SRAM_UNI_BLOCK_3_LOW 0x3FFB6000 - -//split management (SRAM blocks 4-21) -#define DRAM0_SRAM_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high -#define DRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x3FF00000 //SRAM high bits 31:22 of the faulting address - constant - -#define DRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_dram0_sram_get_fault_address(void) +static inline intptr_t memprot_ll_dram0_sram_get_fault_address(void) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); - return (uint32_t *)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_SRAM_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); + return (intptr_t)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_SRAM_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_dram0_sram_is_intr_mine(void) +static inline bool memprot_ll_dram0_sram_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_dram0_sram_get_fault_address(); - return (uint32_t)faulting_address >= DRAM0_SRAM_ADDRESS_LOW && (uint32_t)faulting_address <= DRAM0_SRAM_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_dram0_sram_get_fault_address(); + return faulting_address >= DRAM0_SRAM_ADDRESS_LOW && faulting_address <= DRAM0_SRAM_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_dram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit) +static inline bool memprot_ll_dram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: *write_bit = DPORT_PMS_PRO_DRAM0_SRAM_0_W; @@ -648,79 +613,97 @@ static inline void esp_memprot_dram0_sram_get_uni_block_sgnf_bits(uint32_t block *read_bit = DPORT_PMS_PRO_DRAM0_SRAM_3_R; break; default: - abort(); + return false; } + + return true; } -static inline void esp_memprot_dram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm) +static inline memprot_ll_err_t memprot_ll_dram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - - uint32_t write_bit, read_bit; - esp_memprot_dram0_sram_get_uni_block_sgnf_bits(block, &write_bit, &read_bit); + //get block-specific WR flags offset within the conf.register + uint32_t write_bit_offset, read_bit_offset; + if (!memprot_ll_dram0_sram_get_uni_block_sgnf_bits(block, &write_bit_offset, &read_bit_offset)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } + //set/reset required flags if (write_perm) { - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit); + DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit_offset); } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit_offset); } if (read_perm) { - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit); + DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit_offset); } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit_offset); } + + return MEMP_LL_OK; } -static inline uint32_t esp_memprot_dram0_sram_get_uni_block_read_bit(uint32_t block) +static inline bool memprot_ll_dram0_sram_get_uni_block_read_bit(uint32_t block, uint32_t *read_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R); + break; case DRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R); + break; case DRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R); + break; case DRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_dram0_sram_get_uni_block_write_bit(uint32_t block) +static inline bool memprot_ll_dram0_sram_get_uni_block_write_bit(uint32_t block, uint32_t *write_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W); + break; case DRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W); + break; case DRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W); + break; case DRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W); + break; default: - abort(); + return false; } + + return true; } //DRAM0 has both unified blocks and split address configured in 1 register -static inline uint32_t esp_memprot_dram0_sram_get_perm_reg(void) +static inline uint32_t memprot_ll_dram0_sram_get_perm_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG); } -static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_dram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - //low boundary check provided by LD script. see comment in esp_memprot_iram0_sram_set_prot() - HAL_ASSERT(addr <= DRAM0_SRAM_SPL_BLOCK_HIGH); - HAL_ASSERT(addr % 0x4 == 0 ); + //low boundary check provided by LD script. see comment in memprot_ll_iram0_sram_set_prot() + if (addr > DRAM0_SRAM_SPL_BLOCK_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //set low region int uni_blocks_low = -1; @@ -740,7 +723,9 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw //set unified mgmt region uint32_t write_bit, read_bit, uni_block_perm = 0; for (int x = 0; x < DRAM0_SRAM_TOTAL_UNI_BLOCKS; x++) { - esp_memprot_dram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit); + if (!memprot_ll_dram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } if (x <= uni_blocks_low) { if (lw) { uni_block_perm |= write_bit; @@ -778,9 +763,11 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw //write DRAM0 SRAM cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG, reg_split_addr | permission_mask | uni_block_perm); + + return MEMP_LL_OK; } -static inline void esp_memprot_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R); @@ -788,13 +775,13 @@ static inline void esp_memprot_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R); } -static inline void esp_memprot_dram0_sram_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_dram0_sram_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R, hr ? 1 : 0); } -static inline void esp_memprot_dram0_sram_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_dram0_sram_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_W, hw ? 1 : 0); @@ -806,34 +793,35 @@ static inline void esp_memprot_dram0_sram_set_write_perm(bool lw, bool hw) * === DRAM0 RTC FAST * ======================================================================================== */ -#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000 -#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF -#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant -#define DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_dram0_rtcfast_get_fault_address(void) +static inline intptr_t memprot_ll_dram0_rtcfast_get_fault_address(void) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); - return (uint32_t *)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); + return (intptr_t)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_dram0_rtcfast_is_intr_mine(void) +static inline bool memprot_ll_dram0_rtcfast_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_dram0_rtcfast_get_fault_address(); - return (uint32_t)faulting_address >= DRAM0_RTCFAST_ADDRESS_LOW && (uint32_t)faulting_address <= DRAM0_RTCFAST_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_dram0_rtcfast_get_fault_address(); + return faulting_address >= DRAM0_RTCFAST_ADDRESS_LOW && faulting_address <= DRAM0_RTCFAST_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_dram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_dram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //addr: 32bit aligned, inside corresponding range + if (addr < DRAM0_RTCFAST_ADDRESS_LOW || addr > DRAM0_RTCFAST_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //conf reg [10:0] - uint32_t reg_split_addr = DRAM0_RTCFAST_ADDR_TO_CONF_REG( addr ); + uint32_t reg_split_addr = DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr); //prepare high & low permission mask uint32_t permission_mask = 0; @@ -852,9 +840,11 @@ static inline void esp_memprot_dram0_rtcfast_set_prot(uint32_t *split_addr, bool //write DRAM0 RTC FAST cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_2_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_R); @@ -862,18 +852,18 @@ static inline void esp_memprot_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_R); } -static inline uint32_t esp_memprot_dram0_rtcfast_get_perm_split_reg(void) +static inline uint32_t memprot_ll_dram0_rtcfast_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_2_REG); } -static inline void esp_memprot_dram0_rtcfast_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_dram0_rtcfast_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_R, hr ? 1 : 0); } -static inline void esp_memprot_dram0_rtcfast_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_dram0_rtcfast_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_W, hw ? 1 : 0); diff --git a/components/hal/esp32s2/include/hal/memprot_peri_ll.h b/components/hal/esp32s2/include/hal/memprot_peri_ll.h index d699df6cf4..4611f7a35d 100644 --- a/components/hal/esp32s2/include/hal/memprot_peri_ll.h +++ b/components/hal/esp32s2/include/hal/memprot_peri_ll.h @@ -14,38 +14,31 @@ #pragma once -#include "hal/assert.h" +#include +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" #ifdef __cplusplus extern "C" { #endif -#define RTCSLOW_MEMORY_SIZE 0x00002000 - /** * ======================================================================================== * === PeriBus1 common * ======================================================================================== */ -//PeriBus1 interrupt status bitmasks -#define PERI1_INTR_ST_OP_TYPE_BIT BIT(4) //0: non-atomic, 1: atomic -#define PERI1_INTR_ST_OP_HIGH_BITS BIT(5) //0: high bits = unchanged, 1: high bits = 0x03F40000 -#define PERI1_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) -#define PERI1_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) - - -static inline void esp_memprot_peri1_clear_intr(void) +static inline void memprot_ll_peri1_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR); } -static inline uint32_t esp_memprot_peri1_get_intr_source_num(void) +static inline uint32_t memprot_ll_peri1_get_intr_source_num(void) { return ETS_PMS_PRO_DPORT_ILG_INTR_SOURCE; } -static inline void esp_memprot_peri1_intr_ena(bool enable) +static inline void memprot_ll_peri1_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN); @@ -54,95 +47,94 @@ static inline void esp_memprot_peri1_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_peri1_get_ctrl_reg(void) +static inline uint32_t memprot_ll_peri1_get_ctrl_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_6_REG); } -static inline uint32_t esp_memprot_peri1_get_fault_reg(void) +static inline uint32_t memprot_ll_peri1_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_7_REG); } -static inline void esp_memprot_peri1_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_peri1_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_peri1_get_fault_reg(); + uint32_t status_bits = memprot_ll_peri1_get_fault_reg(); //*op_type = (uint32_t)status_bits & PERI1_INTR_ST_OP_RW_BIT; *op_type = 0; //! DPORT_PMS_PRO_DPORT_7_REG is missing op_type bit *op_subtype = (uint32_t)status_bits & PERI1_INTR_ST_OP_TYPE_BIT; } -static inline bool esp_memprot_peri1_is_assoc_intr(void) +static inline bool memprot_ll_peri1_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_7_REG, DPORT_PMS_PRO_DPORT_ILG_INTR) > 0; } -static inline uint32_t esp_memprot_peri1_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_peri1_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN); } -static inline uint32_t esp_memprot_peri1_get_intr_on_bit(void) +static inline uint32_t memprot_ll_peri1_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_INTR); } -static inline uint32_t esp_memprot_peri1_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_peri1_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR); } -static inline uint32_t esp_memprot_peri1_get_lock_reg(void) +static inline uint32_t memprot_ll_peri1_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_0_REG); } //resets automatically on CPU restart -static inline void esp_memprot_peri1_set_lock(void) +static inline void memprot_ll_peri1_set_lock(void) { DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DPORT_0_REG, DPORT_PMS_PRO_DPORT_LOCK); } -static inline uint32_t esp_memprot_peri1_get_lock_bit(void) +static inline uint32_t memprot_ll_peri1_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_0_REG, DPORT_PMS_PRO_DPORT_LOCK); } - /** * ======================================================================================== * === PeriBus1 RTC SLOW * ======================================================================================== */ -#define PERI1_RTCSLOW_ADDRESS_BASE 0x3F421000 -#define PERI1_RTCSLOW_ADDRESS_LOW PERI1_RTCSLOW_ADDRESS_BASE -#define PERI1_RTCSLOW_ADDRESS_HIGH PERI1_RTCSLOW_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE -#define PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 0x3F400000 - -#define PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR) << DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_S) - -static inline uint32_t *esp_memprot_peri1_rtcslow_get_fault_address(void) +static inline intptr_t memprot_ll_peri1_rtcslow_get_fault_address(void) { - uint32_t status_bits = esp_memprot_peri1_get_fault_reg(); + uint32_t status_bits = memprot_ll_peri1_get_fault_reg(); uint32_t fault_address = (status_bits & PERI1_INTR_ST_FAULTADDR_M) >> PERI1_INTR_ST_FAULTADDR_S; uint32_t high_bits = (status_bits & PERI1_INTR_ST_OP_HIGH_BITS) ? PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 : 0; - return (uint32_t *)(fault_address | high_bits); + return (intptr_t)(fault_address | high_bits); } -static inline bool esp_memprot_peri1_rtcslow_is_intr_mine(void) +static inline bool memprot_ll_peri1_rtcslow_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_peri1_rtcslow_get_fault_address(); - return (uint32_t)faulting_address >= PERI1_RTCSLOW_ADDRESS_LOW && (uint32_t)faulting_address <= PERI1_RTCSLOW_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri1_rtcslow_get_fault_address(); + return faulting_address >= PERI1_RTCSLOW_ADDRESS_LOW && faulting_address <= PERI1_RTCSLOW_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_peri1_rtcslow_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_peri1_rtcslow_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI1_RTCSLOW_ADDRESS_LOW || addr > PERI1_RTCSLOW_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr); @@ -163,9 +155,11 @@ static inline void esp_memprot_peri1_rtcslow_set_prot(uint32_t *split_addr, bool //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_R); @@ -173,46 +167,40 @@ static inline void esp_memprot_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_R); } -static inline void esp_memprot_peri1_rtcslow_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_peri1_rtcslow_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_R, hr ? 1 : 0); } -static inline void esp_memprot_peri1_rtcslow_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_peri1_rtcslow_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_W, hw ? 1 : 0); } -static inline uint32_t esp_memprot_peri1_rtcslow_get_conf_reg(void) +static inline uint32_t memprot_ll_peri1_rtcslow_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG); } - /** * ======================================================================================== * === PeriBus2 common * ======================================================================================== */ -//PeriBus2 interrupt status bitmasks -#define PERI2_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 -#define PERI2_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 -#define PERI2_INTR_ST_FAULTADDR_M 0xFFFFFFFC //(bits 31:2 in the reg) - -static inline void esp_memprot_peri2_clear_intr(void) +static inline void memprot_ll_peri2_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR); } -static inline uint32_t esp_memprot_peri2_get_intr_source_num(void) +static inline uint32_t memprot_ll_peri2_get_intr_source_num(void) { return ETS_PMS_PRO_AHB_ILG_INTR_SOURCE; } -static inline void esp_memprot_peri2_intr_ena(bool enable) +static inline void memprot_ll_peri2_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN); @@ -221,90 +209,90 @@ static inline void esp_memprot_peri2_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_peri2_get_ctrl_reg(void) +static inline uint32_t memprot_ll_peri2_get_ctrl_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_3_REG); } -static inline uint32_t esp_memprot_peri2_get_fault_reg(void) +static inline uint32_t memprot_ll_peri2_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_4_REG); } -static inline void esp_memprot_peri2_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_peri2_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_peri2_get_fault_reg(); + uint32_t status_bits = memprot_ll_peri2_get_fault_reg(); *op_type = (uint32_t)status_bits & PERI2_INTR_ST_OP_RW_BIT; *op_subtype = (uint32_t)status_bits & PERI2_INTR_ST_OP_TYPE_BIT; } -static inline bool esp_memprot_peri2_is_assoc_intr(void) +static inline bool memprot_ll_peri2_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_INTR) > 0; } -static inline uint32_t esp_memprot_peri2_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_peri2_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN); } -static inline uint32_t esp_memprot_peri2_get_intr_on_bit(void) +static inline uint32_t memprot_ll_peri2_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_INTR); } -static inline uint32_t esp_memprot_peri2_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_peri2_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR); } -static inline uint32_t esp_memprot_peri2_get_lock_reg(void) +static inline uint32_t memprot_ll_peri2_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_0_REG); } //resets automatically on CPU restart -static inline void esp_memprot_peri2_set_lock(void) +static inline void memprot_ll_peri2_set_lock(void) { DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_0_REG, DPORT_PMS_PRO_AHB_LOCK); } -static inline uint32_t esp_memprot_peri2_get_lock_bit(void) +static inline uint32_t memprot_ll_peri2_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_0_REG, DPORT_PMS_PRO_AHB_LOCK); } -static inline uint32_t *esp_memprot_peri2_rtcslow_get_fault_address(void) +static inline intptr_t memprot_ll_peri2_rtcslow_get_fault_address(void) { - uint32_t status_bits = esp_memprot_peri2_get_fault_reg(); - return (uint32_t *)(status_bits & PERI2_INTR_ST_FAULTADDR_M); + uint32_t status_bits = memprot_ll_peri2_get_fault_reg(); + return (intptr_t)(status_bits & PERI2_INTR_ST_FAULTADDR_M); } - /** * ======================================================================================== * === PeriBus2 RTC SLOW 0 (AHB0) * ======================================================================================== */ -#define PERI2_RTCSLOW_0_ADDRESS_BASE 0x50000000 -#define PERI2_RTCSLOW_0_ADDRESS_LOW PERI2_RTCSLOW_0_ADDRESS_BASE -#define PERI2_RTCSLOW_0_ADDRESS_HIGH PERI2_RTCSLOW_0_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE - -#define PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_S) - -static inline bool esp_memprot_peri2_rtcslow_0_is_intr_mine(void) +static inline bool memprot_ll_peri2_rtcslow_0_is_intr_mine(void) { - if (esp_memprot_peri2_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address(); - return (uint32_t)faulting_address >= PERI2_RTCSLOW_0_ADDRESS_LOW && (uint32_t)faulting_address <= PERI2_RTCSLOW_0_ADDRESS_HIGH; + if (memprot_ll_peri2_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri2_rtcslow_get_fault_address(); + return faulting_address >= PERI2_RTCSLOW_0_ADDRESS_LOW && faulting_address <= PERI2_RTCSLOW_0_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI2_RTCSLOW_0_ADDRESS_LOW || addr > PERI2_RTCSLOW_0_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr); @@ -331,9 +319,11 @@ static inline void esp_memprot_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bo //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_1_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_R); @@ -343,25 +333,25 @@ static inline void esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, boo *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_F); } -static inline void esp_memprot_peri2_rtcslow_0_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_peri2_rtcslow_0_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_R, hr ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_0_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_peri2_rtcslow_0_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_W, hw ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_0_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_peri2_rtcslow_0_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_F, hx ? 1 : 0); } -static inline uint32_t esp_memprot_peri2_rtcslow_0_get_conf_reg(void) +static inline uint32_t memprot_ll_peri2_rtcslow_0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG); } @@ -371,25 +361,26 @@ static inline uint32_t esp_memprot_peri2_rtcslow_0_get_conf_reg(void) * === PeriBus2 RTC SLOW 1 (AHB1) * ======================================================================================== */ -#define PERI2_RTCSLOW_1_ADDRESS_BASE 0x60021000 -#define PERI2_RTCSLOW_1_ADDRESS_LOW PERI2_RTCSLOW_1_ADDRESS_BASE -#define PERI2_RTCSLOW_1_ADDRESS_HIGH PERI2_RTCSLOW_1_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE - -#define PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_S) - -static inline bool esp_memprot_peri2_rtcslow_1_is_intr_mine(void) +static inline bool memprot_ll_peri2_rtcslow_1_is_intr_mine(void) { - if (esp_memprot_peri2_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address(); - return (uint32_t)faulting_address >= PERI2_RTCSLOW_1_ADDRESS_LOW && (uint32_t)faulting_address <= PERI2_RTCSLOW_1_ADDRESS_HIGH; + if (memprot_ll_peri2_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri2_rtcslow_get_fault_address(); + return faulting_address >= PERI2_RTCSLOW_1_ADDRESS_LOW && faulting_address <= PERI2_RTCSLOW_1_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI2_RTCSLOW_1_ADDRESS_LOW || addr > PERI2_RTCSLOW_1_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr); @@ -416,9 +407,11 @@ static inline void esp_memprot_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bo //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_2_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_R); @@ -428,25 +421,25 @@ static inline void esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, boo *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_F); } -static inline void esp_memprot_peri2_rtcslow_1_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_peri2_rtcslow_1_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_R, hr ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_1_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_peri2_rtcslow_1_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_W, hw ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_1_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_peri2_rtcslow_1_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_F, hx ? 1 : 0); } -static inline uint32_t esp_memprot_peri2_rtcslow_1_get_conf_reg(void) +static inline uint32_t memprot_ll_peri2_rtcslow_1_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_2_REG); } diff --git a/components/hal/include/hal/memprot_types.h b/components/hal/include/hal/memprot_types.h new file mode 100644 index 0000000000..42231f43ea --- /dev/null +++ b/components/hal/include/hal/memprot_types.h @@ -0,0 +1,35 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Memprot LL error codes + * + */ +typedef enum { + MEMP_LL_OK = 0, + MEMP_LL_FAIL = 1, + MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2, + MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED = 3, + MEMP_LL_ERR_UNI_BLOCK_INVALID = 4 +} memprot_ll_err_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32s2/include/soc/memprot_defs.h b/components/soc/esp32s2/include/soc/memprot_defs.h new file mode 100644 index 0000000000..f4b4ab9423 --- /dev/null +++ b/components/soc/esp32s2/include/soc/memprot_defs.h @@ -0,0 +1,131 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include "soc/soc.h" +#include "soc/sensitive_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//IRAM0 interrupt status bitmasks +#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 +#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 + +#define CONF_REG_ADDRESS_SHIFT 2 + +//IRAM0 range +#define IRAM0_SRAM_BASE_ADDRESS 0x40000000 +#define IRAM0_SRAM_ADDRESS_LOW 0x40020000 +#define IRAM0_SRAM_ADDRESS_HIGH 0x4006FFFF + +//IRAM0 unified managemnt blocks +#define IRAM0_SRAM_TOTAL_UNI_BLOCKS 4 +#define IRAM0_SRAM_UNI_BLOCK_0 0 +#define IRAM0_SRAM_UNI_BLOCK_1 1 +#define IRAM0_SRAM_UNI_BLOCK_2 2 +#define IRAM0_SRAM_UNI_BLOCK_3 3 + +//unified management addr range (blocks 0-3) +#define IRAM0_SRAM_UNI_BLOCK_0_LOW 0x40020000 +#define IRAM0_SRAM_UNI_BLOCK_1_LOW 0x40022000 +#define IRAM0_SRAM_UNI_BLOCK_2_LOW 0x40024000 +#define IRAM0_SRAM_UNI_BLOCK_3_LOW 0x40026000 + +//split management addr range (blocks 4-21) +#define IRAM0_SRAM_SPL_BLOCK_LOW 0x40028000 //block 4 low +#define IRAM0_SRAM_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high + +#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //bits 21:6 in the reg, as well as in real address +#define IRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x40000000 //high nonsignificant bits 31:22 of the faulting address - constant + +#define IRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) + +//IRAM0 RTCFAST +#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000 +#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF +#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant) + +#define IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_S) + +//DRAM0 interrupt status bitmasks +#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) +#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) +#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1 +#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1 + +#define DRAM0_SRAM_ADDRESS_LOW 0x3FFB0000 +#define DRAM0_SRAM_ADDRESS_HIGH 0x3FFFFFFF + +#define DRAM0_SRAM_TOTAL_UNI_BLOCKS 4 +#define DRAM0_SRAM_UNI_BLOCK_0 0 +#define DRAM0_SRAM_UNI_BLOCK_1 1 +#define DRAM0_SRAM_UNI_BLOCK_2 2 +#define DRAM0_SRAM_UNI_BLOCK_3 3 + +//unified management (SRAM blocks 0-3) +#define DRAM0_SRAM_UNI_BLOCK_0_LOW 0x3FFB0000 +#define DRAM0_SRAM_UNI_BLOCK_1_LOW 0x3FFB2000 +#define DRAM0_SRAM_UNI_BLOCK_2_LOW 0x3FFB4000 +#define DRAM0_SRAM_UNI_BLOCK_3_LOW 0x3FFB6000 + +//split management (SRAM blocks 4-21) +#define DRAM0_SRAM_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high +#define DRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x3FF00000 //SRAM high bits 31:22 of the faulting address - constant + +#define DRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) + +//DRAM0 RTCFAST +#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000 +#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF +#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant +#define DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_S) + +//RTCSLOW +#define RTCSLOW_MEMORY_SIZE 0x00002000 + +//PeriBus1 interrupt status bitmasks +#define PERI1_INTR_ST_OP_TYPE_BIT BIT(4) //0: non-atomic, 1: atomic +#define PERI1_INTR_ST_OP_HIGH_BITS BIT(5) //0: high bits = unchanged, 1: high bits = 0x03F40000 +#define PERI1_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) +#define PERI1_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) + +#define PERI1_RTCSLOW_ADDRESS_BASE 0x3F421000 +#define PERI1_RTCSLOW_ADDRESS_LOW PERI1_RTCSLOW_ADDRESS_BASE +#define PERI1_RTCSLOW_ADDRESS_HIGH PERI1_RTCSLOW_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE +#define PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 0x3F400000 + +#define PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR) << DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_S) + +//PeriBus2 interrupt status bitmasks +#define PERI2_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 +#define PERI2_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 +#define PERI2_INTR_ST_FAULTADDR_M 0xFFFFFFFC //(bits 31:2 in the reg) + +#define PERI2_RTCSLOW_0_ADDRESS_BASE 0x50000000 +#define PERI2_RTCSLOW_0_ADDRESS_LOW PERI2_RTCSLOW_0_ADDRESS_BASE +#define PERI2_RTCSLOW_0_ADDRESS_HIGH PERI2_RTCSLOW_0_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE + +#define PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_S) + +#define PERI2_RTCSLOW_1_ADDRESS_BASE 0x60021000 +#define PERI2_RTCSLOW_1_ADDRESS_LOW PERI2_RTCSLOW_1_ADDRESS_BASE +#define PERI2_RTCSLOW_1_ADDRESS_HIGH PERI2_RTCSLOW_1_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE + +#define PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_S) + +#ifdef __cplusplus +} +#endif diff --git a/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c b/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c index 1ad8333ea6..0dc7bf9c90 100644 --- a/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c +++ b/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c @@ -313,13 +313,23 @@ static void __attribute__((unused)) dump_bus_permissions(mem_type_prot_t mem_typ static void __attribute__((unused)) dump_status_register(mem_type_prot_t mem_type) { uint32_t *faulting_address, op_type, op_subtype; - esp_memprot_get_fault_status(mem_type, &faulting_address, &op_type, &op_subtype); - esp_rom_printf( - " FAULT [split addr: 0x%08X, fault addr: 0x%08X, fault status: 0x%08X]\n", - (uint32_t)test_memprot_get_split_addr(mem_type), - (uint32_t)faulting_address, - esp_memprot_get_fault_reg(mem_type) - ); + esp_err_t res = esp_memprot_get_fault_status(mem_type, &faulting_address, &op_type, &op_subtype); + if ( res == ESP_OK ) { + uint32_t fault_reg; + res = esp_memprot_get_fault_reg(mem_type, &fault_reg); + esp_rom_printf( + " FAULT [split addr: 0x%08X, fault addr: 0x%08X, fault status: ", + (uint32_t) test_memprot_get_split_addr(mem_type), + (uint32_t) faulting_address + ); + if ( res == ESP_OK ) { + esp_rom_printf("0x%08X]\n", fault_reg ); + } else { + esp_rom_printf("]\n", res ); + } + } else { + esp_rom_printf(" FAULT [failed to get fault details, error 0x%08X]\n", res); + } } @@ -328,13 +338,17 @@ static void __attribute__((unused)) dump_status_register(mem_type_prot_t mem_typ */ static void check_test_result(mem_type_prot_t mem_type, bool expected_status) { - uint32_t fault = esp_memprot_get_fault_reg(mem_type); - - bool test_result = expected_status ? fault == 0 : fault != 0; - if ( test_result ) { - esp_rom_printf("OK\n"); + uint32_t fault; + esp_err_t res = esp_memprot_get_fault_reg(mem_type, &fault); + if ( res == ESP_OK ) { + bool test_result = expected_status ? fault == 0 : fault != 0; + if (test_result) { + esp_rom_printf("OK\n"); + } else { + dump_status_register(mem_type); + } } else { - dump_status_register(mem_type); + esp_rom_printf(" FAULT [failed to get test results, error 0x%08X]\n", res); } } From e67bcda6d1d977171ce9232e0f6ac2e10f95f4dd Mon Sep 17 00:00:00 2001 From: SalimTerryLi Date: Wed, 25 Aug 2021 17:45:46 +0800 Subject: [PATCH 050/310] mcpwm: ISR can be placed to IRAM by menuconfig resolves https://github.com/espressif/esp-idf/issues/7449 --- components/driver/Kconfig | 14 ++++++++++++++ components/driver/mcpwm.c | 16 ++++++++++++---- components/hal/esp32/include/hal/mcpwm_ll.h | 4 ++++ components/hal/esp32s3/include/hal/mcpwm_ll.h | 4 ++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/components/driver/Kconfig b/components/driver/Kconfig index aedad08772..6ca95be2ca 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -21,6 +21,20 @@ menu "Driver configurations" endmenu # ADC Configuration + menu "MCPWM configuration" + + config MCPWM_ISR_IN_IRAM + bool "Place MCPWM ISR function into IRAM" + default n + help + If this option is not selected, the MCPWM interrupt will be deferred when the Cache + is in a disabled state (e.g. Flash write/erase operation). + + Note that if this option is selected, all user registered ISR callbacks should never + try to use cache as well. (with IRAM_ATTR) + + endmenu # MCPWM Configuration + menu "SPI configuration" config SPI_MASTER_IN_IRAM diff --git a/components/driver/mcpwm.c b/components/driver/mcpwm.c index be07fc9129..326680ab6b 100644 --- a/components/driver/mcpwm.c +++ b/components/driver/mcpwm.c @@ -36,6 +36,14 @@ static const char *TAG = "mcpwm"; #define MCPWM_DT_ERROR "MCPWM DEADTIME TYPE ERROR" #define MCPWM_CAP_EXIST_ERROR "MCPWM USER CAP INT SERVICE ALREADY EXISTS" +#ifdef CONFIG_MCPWM_ISR_IN_IRAM +#define MCPWM_ISR_ATTR IRAM_ATTR +#define MCPWM_INTR_FLAG (ESP_INTR_FLAG_IRAM) +#else +#define MCPWM_ISR_ATTR +#define MCPWM_INTR_FLAG 0 +#endif + #define MCPWM_GROUP_CLK_PRESCALE (16) #define MCPWM_GROUP_CLK_HZ (SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_PRESCALE) #define MCPWM_TIMER_CLK_HZ (MCPWM_GROUP_CLK_HZ / 10) @@ -729,7 +737,7 @@ esp_err_t mcpwm_fault_set_oneshot_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t tim return ESP_OK; } -static void mcpwm_default_isr_handler(void *arg) { +static void MCPWM_ISR_ATTR mcpwm_default_isr_handler(void *arg) { mcpwm_context_t *curr_context = (mcpwm_context_t *) arg; uint32_t intr_status = mcpwm_ll_intr_get_capture_status(curr_context->hal.dev); mcpwm_ll_intr_clear_capture_status(curr_context->hal.dev, intr_status); @@ -826,7 +834,7 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha context[mcpwm_num].cap_isr_func[cap_channel].args = cap_conf->user_data; esp_err_t ret = ESP_OK; if (context[mcpwm_num].mcpwm_intr_handle == NULL) { - ret = esp_intr_alloc(mcpwm_periph_signals.groups[mcpwm_num].irq_id, 0, + ret = esp_intr_alloc(mcpwm_periph_signals.groups[mcpwm_num].irq_id, MCPWM_INTR_FLAG, mcpwm_default_isr_handler, (void *) (context + mcpwm_num), &(context[mcpwm_num].mcpwm_intr_handle)); } @@ -873,7 +881,7 @@ esp_err_t mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_ch return ret; } -uint32_t mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) +uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) { ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); ESP_RETURN_ON_FALSE(cap_sig < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR); @@ -881,7 +889,7 @@ uint32_t mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num, mcpwm_capture_si return mcpwm_ll_capture_get_value(hal->dev, cap_sig); } -uint32_t mcpwm_capture_signal_get_edge(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) +uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_edge(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) { ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); ESP_RETURN_ON_FALSE(cap_sig < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR); diff --git a/components/hal/esp32/include/hal/mcpwm_ll.h b/components/hal/esp32/include/hal/mcpwm_ll.h index f2e3b34183..006fc44c0c 100644 --- a/components/hal/esp32/include/hal/mcpwm_ll.h +++ b/components/hal/esp32/include/hal/mcpwm_ll.h @@ -126,6 +126,7 @@ static inline uint32_t mcpwm_ll_intr_get_trip_ost_status(mcpwm_dev_t *mcpwm) return (mcpwm->int_st.val >> 24) & 0x07; } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) { return (mcpwm->int_st.val >> 27) & 0x07; @@ -173,6 +174,7 @@ static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint3 mcpwm->int_clr.val = (ost_mask & 0x07) << 24; } +__attribute__((always_inline)) static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) { mcpwm->int_clr.val = (capture_mask & 0x07) << 27; @@ -977,11 +979,13 @@ static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel mcpwm->cap_cfg_ch[channel].sw = 1; // auto clear } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) { return mcpwm->cap_val_ch[channel]; } +__attribute__((always_inline)) static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) { return mcpwm->cap_status.val & (1 << channel) ? true : false; diff --git a/components/hal/esp32s3/include/hal/mcpwm_ll.h b/components/hal/esp32s3/include/hal/mcpwm_ll.h index 93f44e2470..4ad6b3a2e3 100644 --- a/components/hal/esp32s3/include/hal/mcpwm_ll.h +++ b/components/hal/esp32s3/include/hal/mcpwm_ll.h @@ -131,6 +131,7 @@ static inline uint32_t mcpwm_ll_intr_get_trip_ost_status(mcpwm_dev_t *mcpwm) return (mcpwm->int_st.val >> 24) & 0x07; } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) { return (mcpwm->int_st.val >> 27) & 0x07; @@ -178,6 +179,7 @@ static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint3 mcpwm->int_clr.val = (ost_mask & 0x07) << 24; } +__attribute__((always_inline)) static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) { mcpwm->int_clr.val = (capture_mask & 0x07) << 27; @@ -996,11 +998,13 @@ static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel mcpwm->cap_cfg_ch[channel].sw = 1; // auto clear } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) { return mcpwm->cap_val_ch[channel]; } +__attribute__((always_inline)) static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) { return mcpwm->cap_status.val & (1 << channel) ? true : false; From e770817dc7f18fa02fa1d14937335096af5f5fe3 Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Wed, 25 Aug 2021 18:05:04 +0800 Subject: [PATCH 051/310] openthread: refine ot_rcp example documentation and APIs --- components/openthread/ftd.cmake | 1 + .../openthread-core-esp32x-ftd-config.h | 0 .../openthread-core-esp32x-radio-config.h | 38 +++++++++-- components/openthread/radio.cmake | 1 + docs/doxygen/Doxyfile | 2 - .../api-reference/network/esp_openthread.rst | 2 - examples/openthread/ot_rcp/README.md | 67 +++++-------------- .../openthread/ot_rcp/main/esp_ot_config.h | 2 +- 8 files changed, 53 insertions(+), 60 deletions(-) rename components/openthread/{include => private_include}/openthread-core-esp32x-ftd-config.h (100%) rename components/openthread/{include => private_include}/openthread-core-esp32x-radio-config.h (93%) diff --git a/components/openthread/ftd.cmake b/components/openthread/ftd.cmake index 89ef3e1735..d87bd93159 100644 --- a/components/openthread/ftd.cmake +++ b/components/openthread/ftd.cmake @@ -10,6 +10,7 @@ set(private_include_dirs "openthread/src/lib/hdlc" "openthread/src/lib/spinel" "openthread/src/ncp" + "private_include" ) set(src_dirs diff --git a/components/openthread/include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h similarity index 100% rename from components/openthread/include/openthread-core-esp32x-ftd-config.h rename to components/openthread/private_include/openthread-core-esp32x-ftd-config.h diff --git a/components/openthread/include/openthread-core-esp32x-radio-config.h b/components/openthread/private_include/openthread-core-esp32x-radio-config.h similarity index 93% rename from components/openthread/include/openthread-core-esp32x-radio-config.h rename to components/openthread/private_include/openthread-core-esp32x-radio-config.h index ace9c05e74..4e5e667dd1 100644 --- a/components/openthread/include/openthread-core-esp32x-radio-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-radio-config.h @@ -262,6 +262,38 @@ */ #define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1 +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE + * + * Define to 1 to enable software CSMA-CA backoff logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE + * + * Define to 1 to enable software retransmission logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE + * + * Define to 1 to enable software transmission security logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE + * + * Define to 1 to enable software transmission target time logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE 1 + /** * The configurable definitions via Kconfig */ @@ -284,9 +316,3 @@ #elif CONFIG_OPENTHREAD_RADIO #define OPENTHREAD_RADIO 1 #endif - - -#define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 1 -#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE 1 -#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 1 -#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE 1 diff --git a/components/openthread/radio.cmake b/components/openthread/radio.cmake index 3c5510c497..93b6f1166f 100644 --- a/components/openthread/radio.cmake +++ b/components/openthread/radio.cmake @@ -10,6 +10,7 @@ set(private_include_dirs "openthread/src/lib/hdlc" "openthread/src/lib/spinel" "openthread/src/ncp" + "private_include" ) set(src_dirs diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 7424a473b3..42781bcdf9 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -158,8 +158,6 @@ INPUT = \ $(PROJECT_PATH)/components/openthread/include/esp_openthread_lock.h \ $(PROJECT_PATH)/components/openthread/include/esp_openthread_netif_glue.h \ $(PROJECT_PATH)/components/openthread/include/esp_openthread_types.h \ - $(PROJECT_PATH)/components/openthread/include/openthread-core-esp32x-ftd-config.h \ - $(PROJECT_PATH)/components/openthread/include/openthread-core-esp32x-radio-config.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs_dev.h \ $(PROJECT_PATH)/components/vfs/include/esp_vfs_eventfd.h \ diff --git a/docs/en/api-reference/network/esp_openthread.rst b/docs/en/api-reference/network/esp_openthread.rst index 21f3933191..0843047962 100644 --- a/docs/en/api-reference/network/esp_openthread.rst +++ b/docs/en/api-reference/network/esp_openthread.rst @@ -29,5 +29,3 @@ ESP-IDF provides extra apis for launching and managing the OpenThread stack, bin .. include-build-file:: inc/esp_openthread_lock.inc .. include-build-file:: inc/esp_openthread_netif_glue.inc .. include-build-file:: inc/esp_openthread_border_router.inc -.. include-build-file:: inc/openthread-core-esp32x-ftd-config.inc - diff --git a/examples/openthread/ot_rcp/README.md b/examples/openthread/ot_rcp/README.md index ac3c8ae58a..e3f3cc6fc2 100644 --- a/examples/openthread/ot_rcp/README.md +++ b/examples/openthread/ot_rcp/README.md @@ -1,69 +1,38 @@ | Supported Targets | ESP32-H2 | | ----------------- | -------- | -# OpenThread radio co-processor (RCP) example +# OpenThread Radio Co-Processor (RCP) Example -## Overview +This example demonstrates an [OpenThread Radio Co-Processor](https://openthread.io/platforms/co-processor). -This example demonstrates an openthread radio co-processor. -The RCP can receive/transmit 15.4-type packets, encode and send the packet to the host device. -You can use the RCP to implement an Openthread sniffer. You cani also connect the RCP to the host device which do not have a 15.4-radio to join in an Openthread network. +OpenThread RCP doesn't function alone, it needs to work together with a Host and this example covers two common user scenarios: +- Work with a Host Processor to perform a [Thread Border Router](https://openthread.io/guides/border-router). +- Work as a [Thread Sniffer](https://openthread.io/guides/pyspinel/sniffer). + +## How to use example + +### Hardware Required To run this example, an ESP32-H2 board is required. -### Config ESP32-H2 uart +### Configure the project -Modify the file `esp_ot_config.h`. +The default communication interface is port 0 of ESP32-H2 UART running at 115200 baud, change the configuration in [esp_ot_config.h](main/esp_ot_config.h) if you want to use another interface or need different communication parameters. -In the file `esp_ot_config.h`, there are three parameters. -As for `ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG` and `ESP_OPENTHREAD_DEFAULT_PORT_CONFIG`, modification is not recommended. -As for the parameters in `ESP_OPENTHREAD_DEFAULT_HOST_CONFIG`, you can refer to ESP uart example `example/peripherals/uart/uart_echo/README.md` +### Build and Flash -### Build, Flash, and Run - -Build the project and flash it to the board +Build the project and flash it to the board: ``` idf.py -p build flash ``` -Now you'll get an ot-rcp (for this example, there is no output in console). +Now you'll get an OpenThread RCP, you can try the following use cases: -# OpenThread sniffer example (Linux or macOS based) +#### Thread Border Router -## Overview +Please refer to [ot_br](../ot_br) example for the setup steps. -This example is about how to run a sniffer to capture Thread packet, which refers to [openthread.io](https://openthread.io/guides/pyspinel/sniffer). -Openthread group just supports Linux and macOS. - -## How to use example - -### Hardware connection - -To run this example, you need an ESP32-H2 borad flashed with ot-rcp application. - -### Set up the sniffer environment - -The sniffer tool connects to an openthread RCP device and converts it into a promiscuous packet sniffer. RCP -will encode and send the packet to host after capturing a 15.4-type packet. On the host, Pyspinel should be run for -decoding the packet and generating a pcap (packet capture) stream to be saved or piped directly into Wireshark. - -Clone and install Pyspinel and dependencies, refer to [openthread.io](https://openthread.io/guides/pyspinel/sniffer#installation). - -### Install and config Wireshark - -For installing the Wireshark, refer to [Espressif Wireshark User Guide]( -https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wireshark-user-guide.html). - -You need to config Wireshark with some properties for the Thread network. -For Wireshark configuration, refer to [openthread.io](https://openthread.io/guides/pyspinel/sniffer#thread_network_properties). - -### Run the sniffer - -For example, to sniff on Channel 15 using a device mounted at /dev/ttyUSB0 with the baudrate 115200 in the Wireshark output: - -``` -cd ~/pyspinel -python sniffer.py -c 15 -u /dev/ttyUSB0 --crc -b 115200 | wireshark -k -i - -``` +#### Thread Sniffer +Please refer to [Thread Sniffer](https://openthread.io/guides/pyspinel/sniffer) for the detailed instructions. diff --git a/examples/openthread/ot_rcp/main/esp_ot_config.h b/examples/openthread/ot_rcp/main/esp_ot_config.h index 012f31d5ce..91cbd362bd 100644 --- a/examples/openthread/ot_rcp/main/esp_ot_config.h +++ b/examples/openthread/ot_rcp/main/esp_ot_config.h @@ -27,7 +27,7 @@ .port = 0, \ .uart_config = \ { \ - .baud_rate = 92160, \ + .baud_rate = 115200, \ .data_bits = UART_DATA_8_BITS, \ .parity = UART_PARITY_DISABLE, \ .stop_bits = UART_STOP_BITS_1, \ From dbdcada2e5112fa3450ed9e9a0e72e5236e598bc Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Thu, 26 Aug 2021 16:55:53 +0800 Subject: [PATCH 052/310] missing semicolon --- components/driver/esp32c3/adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/driver/esp32c3/adc.c b/components/driver/esp32c3/adc.c index 91dff0b5c5..585a139550 100644 --- a/components/driver/esp32c3/adc.c +++ b/components/driver/esp32c3/adc.c @@ -448,11 +448,11 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio) if (adc_unit & ADC_UNIT_1) { ADC_ENTER_CRITICAL(); adc_hal_vref_output(ADC_NUM_1, channel, true); - ADC_EXIT_CRITICAL() + ADC_EXIT_CRITICAL(); } else if (adc_unit & ADC_UNIT_2) { ADC_ENTER_CRITICAL(); adc_hal_vref_output(ADC_NUM_2, channel, true); - ADC_EXIT_CRITICAL() + ADC_EXIT_CRITICAL(); } ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel)); From 5691c9a8e8658360d36049140aae2693d3e57b55 Mon Sep 17 00:00:00 2001 From: Vikram Dattu Date: Mon, 31 May 2021 11:05:21 +0530 Subject: [PATCH 053/310] Added support for security1 in local control 1. Added config options to chose from protocom security. It can be chosen 0/1 or custom. Possible to set POP as well 2. Added support in `esp_local_ctrl.py` test script for sec_ver selection Signed-off-by: Vikram Dattu --- .../esp_local_ctrl/include/esp_local_ctrl.h | 36 ++++ .../esp_local_ctrl/src/esp_local_ctrl.c | 16 +- examples/protocols/esp_local_ctrl/README.md | 4 +- .../protocols/esp_local_ctrl/example_test.py | 1 + .../main/esp_local_ctrl_service.c | 5 + .../esp_local_ctrl/scripts/esp_local_ctrl.py | 182 ++++++++++++++++-- .../scripts/{proto.py => proto_lc.py} | 30 +-- tools/ci/mypy_ignore_list.txt | 2 +- 8 files changed, 240 insertions(+), 36 deletions(-) rename examples/protocols/esp_local_ctrl/scripts/{proto.py => proto_lc.py} (75%) diff --git a/components/esp_local_ctrl/include/esp_local_ctrl.h b/components/esp_local_ctrl/include/esp_local_ctrl.h index 9f4f89daa3..8322412eb3 100644 --- a/components/esp_local_ctrl/include/esp_local_ctrl.h +++ b/components/esp_local_ctrl/include/esp_local_ctrl.h @@ -228,6 +228,37 @@ typedef union { esp_local_ctrl_transport_config_httpd_t *httpd; } esp_local_ctrl_transport_config_t; +/** + * @brief Security types for esp_local_control + */ +typedef enum esp_local_ctrl_proto_sec { + PROTOCOM_SEC0 = 0, + PROTOCOM_SEC1, + PROTOCOM_SEC_CUSTOM, +} esp_local_ctrl_proto_sec_t; + +/** + * Protocom security configs + */ +typedef struct esp_local_ctrl_proto_sec_cfg { + /** + * This sets protocom security version, sec0/sec1 or custom + * If custom, user must provide handle via `proto_sec_custom_handle` below + */ + esp_local_ctrl_proto_sec_t version; + + /** + * Custom security handle if security is set custom via `proto_sec` above + * This handle must follow `protocomm_security_t` signature + */ + void *custom_handle; + + /** + * Proof of possession to be used for local control. Could be NULL. + */ + void *pop; +} esp_local_ctrl_proto_sec_cfg_t; + /** * @brief Configuration structure to pass to `esp_local_ctrl_start()` */ @@ -242,6 +273,11 @@ typedef struct esp_local_ctrl_config { */ esp_local_ctrl_transport_config_t transport_config; + /** + * Security version and POP + */ + esp_local_ctrl_proto_sec_cfg_t proto_sec; + /** * Register handlers for responding to get/set requests on properties */ diff --git a/components/esp_local_ctrl/src/esp_local_ctrl.c b/components/esp_local_ctrl/src/esp_local_ctrl.c index 1eead4d7c1..c99b96782b 100644 --- a/components/esp_local_ctrl/src/esp_local_ctrl.c +++ b/components/esp_local_ctrl/src/esp_local_ctrl.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "esp_local_ctrl_priv.h" @@ -149,8 +150,21 @@ esp_err_t esp_local_ctrl_start(const esp_local_ctrl_config_t *config) return ret; } + protocomm_security_t *proto_sec_handle; + switch (local_ctrl_inst_ctx->config.proto_sec.version) { + case PROTOCOM_SEC_CUSTOM: + proto_sec_handle = local_ctrl_inst_ctx->config.proto_sec.custom_handle; + break; + case PROTOCOM_SEC1: + proto_sec_handle = (protocomm_security_t *) &protocomm_security1; + break; + case PROTOCOM_SEC0: + default: + proto_sec_handle = (protocomm_security_t *) &protocomm_security0; + break; + } ret = protocomm_set_security(local_ctrl_inst_ctx->pc, "esp_local_ctrl/session", - &protocomm_security0, NULL); + proto_sec_handle, local_ctrl_inst_ctx->config.proto_sec.pop); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set session endpoint"); esp_local_ctrl_stop(); diff --git a/examples/protocols/esp_local_ctrl/README.md b/examples/protocols/esp_local_ctrl/README.md index d9498c5b29..d0ca7d48a0 100644 --- a/examples/protocols/esp_local_ctrl/README.md +++ b/examples/protocols/esp_local_ctrl/README.md @@ -28,12 +28,12 @@ Sample output: After you've tested the name resolution, run: ``` -python scripts/esp_local_ctrl.py +python scripts/esp_local_ctrl.py --sec_ver 0 ``` Sample output: ``` -python scripts/esp_local_ctrl.py +python scripts/esp_local_ctrl.py --sec_ver 0 ==== Acquiring properties information ==== diff --git a/examples/protocols/esp_local_ctrl/example_test.py b/examples/protocols/esp_local_ctrl/example_test.py index ae4a644ed8..5aac681dd0 100644 --- a/examples/protocols/esp_local_ctrl/example_test.py +++ b/examples/protocols/esp_local_ctrl/example_test.py @@ -29,6 +29,7 @@ def test_examples_esp_local_ctrl(env, extra_data): # Running mDNS services in docker is not a trivial task. Therefore, the script won't connect to the host name but # to IP address. However, the certificates were generated for the host name and will be rejected. cmd = ' '.join([sys.executable, os.path.join(idf_path, rel_project_path, 'scripts/esp_local_ctrl.py'), + '--sec_ver 0', '--name', dut_ip, '--dont-check-hostname']) # don't reject the certificate because of the hostname esp_local_ctrl_log = os.path.join(idf_path, rel_project_path, 'esp_local_ctrl.log') diff --git a/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c b/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c index 2e80baeebb..db5a0748de 100644 --- a/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c +++ b/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c @@ -178,6 +178,11 @@ void start_esp_local_ctrl_service(void) .transport_config = { .httpd = &https_conf }, + .proto_sec = { + .version = 0, + .custom_handle = NULL, + .pop = NULL, + }, .handlers = { /* User defined handler functions */ .get_prop_values = get_property_values, diff --git a/examples/protocols/esp_local_ctrl/scripts/esp_local_ctrl.py b/examples/protocols/esp_local_ctrl/scripts/esp_local_ctrl.py index 95979b401f..44e786db46 100644 --- a/examples/protocols/esp_local_ctrl/scripts/esp_local_ctrl.py +++ b/examples/protocols/esp_local_ctrl/scripts/esp_local_ctrl.py @@ -18,19 +18,28 @@ from __future__ import print_function import argparse +import json import os import ssl import struct import sys +import textwrap from builtins import input -import proto +import proto_lc from future.utils import tobytes -# The tools directory is already in the PATH in environment prepared by install.sh which would allow to import -# esp_prov as file but not as complete module. -sys.path.insert(0, os.path.join(os.environ['IDF_PATH'], 'tools/esp_prov')) -import esp_prov # noqa: E402 +try: + import esp_prov + import security + +except ImportError: + idf_path = os.environ['IDF_PATH'] + sys.path.insert(0, idf_path + '/components/protocomm/python') + sys.path.insert(1, idf_path + '/tools/esp_prov') + + import esp_prov + import security # Set this to true to allow exceptions to be thrown config_throw_except = False @@ -118,6 +127,14 @@ def on_except(err): print(err) +def get_security(secver, pop=None, verbose=False): + if secver == 1: + return security.Security1(pop, verbose) + elif secver == 0: + return security.Security0(verbose) + return None + + def get_transport(sel_transport, service_name, check_hostname): try: tp = None @@ -140,29 +157,99 @@ def get_transport(sel_transport, service_name, check_hostname): return None -def version_match(tp, expected, verbose=False): +def version_match(tp, protover, verbose=False): try: - response = tp.send_data('esp_local_ctrl/version', expected) - return (response.lower() == expected.lower()) + response = tp.send_data('proto-ver', protover) + + if verbose: + print('proto-ver response : ', response) + + # First assume this to be a simple version string + if response.lower() == protover.lower(): + return True + + try: + # Else interpret this as JSON structure containing + # information with versions and capabilities of both + # provisioning service and application + info = json.loads(response) + if info['prov']['ver'].lower() == protover.lower(): + return True + + except ValueError: + # If decoding as JSON fails, it means that capabilities + # are not supported + return False + except Exception as e: on_except(e) return None -def get_all_property_values(tp): +def has_capability(tp, capability='none', verbose=False): + # Note : default value of `capability` argument cannot be empty string + # because protocomm_httpd expects non zero content lengths + try: + response = tp.send_data('proto-ver', capability) + + if verbose: + print('proto-ver response : ', response) + + try: + # Interpret this as JSON structure containing + # information with versions and capabilities of both + # provisioning service and application + info = json.loads(response) + supported_capabilities = info['prov']['cap'] + if capability.lower() == 'none': + # No specific capability to check, but capabilities + # feature is present so return True + return True + elif capability in supported_capabilities: + return True + return False + + except ValueError: + # If decoding as JSON fails, it means that capabilities + # are not supported + return False + + except RuntimeError as e: + on_except(e) + + return False + + +def establish_session(tp, sec): + try: + response = None + while True: + request = sec.security_session(response) + if request is None: + break + response = tp.send_data('esp_local_ctrl/session', request) + if (response is None): + return False + return True + except RuntimeError as e: + on_except(e) + return None + + +def get_all_property_values(tp, security_ctx): try: props = [] - message = proto.get_prop_count_request() + message = proto_lc.get_prop_count_request(security_ctx) response = tp.send_data('esp_local_ctrl/control', message) - count = proto.get_prop_count_response(response) + count = proto_lc.get_prop_count_response(security_ctx, response) if count == 0: raise RuntimeError('No properties found!') indices = [i for i in range(count)] - message = proto.get_prop_vals_request(indices) + message = proto_lc.get_prop_vals_request(security_ctx, indices) response = tp.send_data('esp_local_ctrl/control', message) - props = proto.get_prop_vals_response(response) + props = proto_lc.get_prop_vals_response(security_ctx, response) if len(props) != count: - raise RuntimeError('Incorrect count of properties!') + raise RuntimeError('Incorrect count of properties!', len(props), count) for p in props: p['value'] = decode_prop_value(p, p['value']) return props @@ -171,20 +258,27 @@ def get_all_property_values(tp): return [] -def set_property_values(tp, props, indices, values, check_readonly=False): +def set_property_values(tp, security_ctx, props, indices, values, check_readonly=False): try: if check_readonly: for index in indices: if prop_is_readonly(props[index]): raise RuntimeError('Cannot set value of Read-Only property') - message = proto.set_prop_vals_request(indices, values) + message = proto_lc.set_prop_vals_request(security_ctx, indices, values) response = tp.send_data('esp_local_ctrl/control', message) - return proto.set_prop_vals_response(response) + return proto_lc.set_prop_vals_response(security_ctx, response) except RuntimeError as e: on_except(e) return False +def desc_format(*args): + desc = '' + for arg in args: + desc += textwrap.fill(replace_whitespace=False, text=arg) + '\n' + return desc + + if __name__ == '__main__': parser = argparse.ArgumentParser(add_help=False) @@ -199,6 +293,22 @@ if __name__ == '__main__': parser.add_argument('--name', dest='service_name', type=str, help='BLE Device Name / HTTP Server hostname or IP', default='') + parser.add_argument('--sec_ver', dest='secver', type=int, default=None, + help=desc_format( + 'Protocomm security scheme used by the provisioning service for secure ' + 'session establishment. Accepted values are :', + '\t- 0 : No security', + '\t- 1 : X25519 key exchange + AES-CTR encryption', + '\t + Authentication using Proof of Possession (PoP)', + 'In case device side application uses IDF\'s provisioning manager, ' + 'the compatible security version is automatically determined from ' + 'capabilities retrieved via the version endpoint')) + + parser.add_argument('--pop', dest='pop', type=str, default='', + help=desc_format( + 'This specifies the Proof of possession (PoP) when security scheme 1 ' + 'is used')) + parser.add_argument('--dont-check-hostname', action='store_true', # If enabled, the certificate won't be rejected for hostname mismatch. # This option is hidden because it should be used only for testing purposes. @@ -220,6 +330,31 @@ if __name__ == '__main__': print('---- Invalid transport ----') exit(1) + # If security version not specified check in capabilities + if args.secver is None: + # First check if capabilities are supported or not + if not has_capability(obj_transport): + print('Security capabilities could not be determined. Please specify \'--sec_ver\' explicitly') + print('---- Invalid Security Version ----') + exit(2) + + # When no_sec is present, use security 0, else security 1 + args.secver = int(not has_capability(obj_transport, 'no_sec')) + print('Security scheme determined to be :', args.secver) + + if (args.secver != 0) and not has_capability(obj_transport, 'no_pop'): + if len(args.pop) == 0: + print('---- Proof of Possession argument not provided ----') + exit(2) + elif len(args.pop) != 0: + print('---- Proof of Possession will be ignored ----') + args.pop = '' + + obj_security = get_security(args.secver, args.pop, False) + if obj_security is None: + print('---- Invalid Security Version ----') + exit(2) + if args.version != '': print('\n==== Verifying protocol version ====') if not version_match(obj_transport, args.version, args.verbose): @@ -227,8 +362,15 @@ if __name__ == '__main__': exit(2) print('==== Verified protocol version successfully ====') + print('\n==== Starting Session ====') + if not establish_session(obj_transport, obj_security): + print('Failed to establish session. Ensure that security scheme and proof of possession are correct') + print('---- Error in establishing session ----') + exit(3) + print('==== Session Established ====') + while True: - properties = get_all_property_values(obj_transport) + properties = get_all_property_values(obj_transport, obj_security) if len(properties) == 0: print('---- Error in reading property values ----') exit(4) @@ -245,7 +387,7 @@ if __name__ == '__main__': select = 0 while True: try: - inval = input("\nSelect properties to set (0 to re-read, 'q' to quit) : ") + inval = input('\nSelect properties to set (0 to re-read, \'q\' to quit) : ') if inval.lower() == 'q': print('Quitting...') exit(5) @@ -274,5 +416,5 @@ if __name__ == '__main__': set_values += [value] set_indices += [select - 1] - if not set_property_values(obj_transport, properties, set_indices, set_values): + if not set_property_values(obj_transport, obj_security, properties, set_indices, set_values): print('Failed to set values!') diff --git a/examples/protocols/esp_local_ctrl/scripts/proto.py b/examples/protocols/esp_local_ctrl/scripts/proto_lc.py similarity index 75% rename from examples/protocols/esp_local_ctrl/scripts/proto.py rename to examples/protocols/esp_local_ctrl/scripts/proto_lc.py index dcad41d1b9..71ed3a987e 100644 --- a/examples/protocols/esp_local_ctrl/scripts/proto.py +++ b/examples/protocols/esp_local_ctrl/scripts/proto_lc.py @@ -36,35 +36,39 @@ constants_pb2 = _load_source('constants_pb2', idf_path + '/components/protocomm/ local_ctrl_pb2 = _load_source('esp_local_ctrl_pb2', idf_path + '/components/esp_local_ctrl/python/esp_local_ctrl_pb2.py') -def get_prop_count_request(): +def get_prop_count_request(security_ctx): req = local_ctrl_pb2.LocalCtrlMessage() req.msg = local_ctrl_pb2.TypeCmdGetPropertyCount payload = local_ctrl_pb2.CmdGetPropertyCount() req.cmd_get_prop_count.MergeFrom(payload) - return req.SerializeToString() + enc_cmd = security_ctx.encrypt_data(req.SerializeToString()) + return enc_cmd -def get_prop_count_response(response_data): +def get_prop_count_response(security_ctx, response_data): + decrypt = security_ctx.decrypt_data(tobytes(response_data)) resp = local_ctrl_pb2.LocalCtrlMessage() - resp.ParseFromString(tobytes(response_data)) + resp.ParseFromString(decrypt) if (resp.resp_get_prop_count.status == 0): return resp.resp_get_prop_count.count else: return 0 -def get_prop_vals_request(indices): +def get_prop_vals_request(security_ctx, indices): req = local_ctrl_pb2.LocalCtrlMessage() req.msg = local_ctrl_pb2.TypeCmdGetPropertyValues payload = local_ctrl_pb2.CmdGetPropertyValues() payload.indices.extend(indices) req.cmd_get_prop_vals.MergeFrom(payload) - return req.SerializeToString() + enc_cmd = security_ctx.encrypt_data(req.SerializeToString()) + return enc_cmd -def get_prop_vals_response(response_data): +def get_prop_vals_response(security_ctx, response_data): + decrypt = security_ctx.decrypt_data(tobytes(response_data)) resp = local_ctrl_pb2.LocalCtrlMessage() - resp.ParseFromString(tobytes(response_data)) + resp.ParseFromString(decrypt) results = [] if (resp.resp_get_prop_vals.status == 0): for prop in resp.resp_get_prop_vals.props: @@ -77,7 +81,7 @@ def get_prop_vals_response(response_data): return results -def set_prop_vals_request(indices, values): +def set_prop_vals_request(security_ctx, indices, values): req = local_ctrl_pb2.LocalCtrlMessage() req.msg = local_ctrl_pb2.TypeCmdSetPropertyValues payload = local_ctrl_pb2.CmdSetPropertyValues() @@ -86,10 +90,12 @@ def set_prop_vals_request(indices, values): prop.index = i prop.value = v req.cmd_set_prop_vals.MergeFrom(payload) - return req.SerializeToString() + enc_cmd = security_ctx.encrypt_data(req.SerializeToString()) + return enc_cmd -def set_prop_vals_response(response_data): +def set_prop_vals_response(security_ctx, response_data): + decrypt = security_ctx.decrypt_data(tobytes(response_data)) resp = local_ctrl_pb2.LocalCtrlMessage() - resp.ParseFromString(tobytes(response_data)) + resp.ParseFromString(decrypt) return (resp.resp_set_prop_vals.status == 0) diff --git a/tools/ci/mypy_ignore_list.txt b/tools/ci/mypy_ignore_list.txt index 8227e8eebd..69c6834f0e 100644 --- a/tools/ci/mypy_ignore_list.txt +++ b/tools/ci/mypy_ignore_list.txt @@ -73,7 +73,7 @@ examples/protocols/cbor/example_test.py examples/protocols/esp_http_client/esp_http_client_test.py examples/protocols/esp_local_ctrl/example_test.py examples/protocols/esp_local_ctrl/scripts/esp_local_ctrl.py -examples/protocols/esp_local_ctrl/scripts/proto.py +examples/protocols/esp_local_ctrl/scripts/proto_lc.py examples/protocols/http_server/advanced_tests/http_server_advanced_test.py examples/protocols/http_server/advanced_tests/scripts/test.py examples/protocols/http_server/persistent_sockets/http_server_persistence_test.py From 5c41f98942ff5bd029c338aefa6c685594e27b8c Mon Sep 17 00:00:00 2001 From: Vikram Dattu Date: Thu, 26 Aug 2021 10:53:37 +0530 Subject: [PATCH 054/310] esp_local_ctrl: Added documentation to chose protocom security Signed-off-by: Vikram Dattu --- .../en/api-reference/protocols/esp_local_ctrl.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/en/api-reference/protocols/esp_local_ctrl.rst b/docs/en/api-reference/protocols/esp_local_ctrl.rst index 01df8a40a9..436c0753fe 100644 --- a/docs/en/api-reference/protocols/esp_local_ctrl.rst +++ b/docs/en/api-reference/protocols/esp_local_ctrl.rst @@ -24,6 +24,11 @@ Initialization of the **esp_local_ctrl** service over BLE transport is performed } } }, + .proto_sec = { + .version = PROTOCOM_SEC0, + .custom_handle = NULL, + .pop = NULL, + }, .handlers = { /* User defined handler functions */ .get_prop_values = get_property_values, @@ -65,6 +70,11 @@ Similarly for HTTPS transport: .transport_config = { .httpd = &https_conf }, + .proto_sec = { + .version = PROTOCOM_SEC0, + .custom_handle = NULL, + .pop = NULL, + }, .handlers = { /* User defined handler functions */ .get_prop_values = get_property_values, @@ -79,6 +89,11 @@ Similarly for HTTPS transport: /* Start esp_local_ctrl service */ ESP_ERROR_CHECK(esp_local_ctrl_start(&config)); +You may set security for transport in ESP local control using following options: + +1. `PROTOCOM_SEC1`: specifies that end to end encryption is used. +2. `PROTOCOM_SEC0`: specifies that data will be exchanged as a plain text. +3. `PROTOCOM_SEC_CUSTOM`: you can define your own security requirement. Please note that you will also have to provide `custom_handle` of type `protocomm_security_t *` in this context. Creating a property ------------------- From 6672862db8e6cd5046f65d7a78963013d0618db1 Mon Sep 17 00:00:00 2001 From: sU8U7SfkcwTJVH7PjaVmej7D <62424391+sU8U7SfkcwTJVH7PjaVmej7D@users.noreply.github.com> Date: Thu, 26 Aug 2021 12:00:00 +0200 Subject: [PATCH 055/310] Missing dependency for idf.py 'encrypted-flash' target --- components/app_update/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt index e6329224e6..8dd328215c 100644 --- a/components/app_update/CMakeLists.txt +++ b/components/app_update/CMakeLists.txt @@ -46,6 +46,7 @@ if(NOT BOOTLOADER_BUILD) add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file}) add_dependencies(flash blank_ota_data) + add_dependencies(encrypted-flash blank_ota_data) set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py) From d3a42d787d3d9a0ab916855bb48b1cd530e47961 Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Thu, 26 Aug 2021 14:59:40 +0530 Subject: [PATCH 056/310] wpa_supplicant: clean tls client state machine --- .../wpa_supplicant/src/crypto/tls_mbedtls.c | 56 +++++-------------- 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/components/wpa_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/src/crypto/tls_mbedtls.c index 9db60867ad..43bc8c9fe5 100644 --- a/components/wpa_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/src/crypto/tls_mbedtls.c @@ -121,6 +121,10 @@ static int tls_mbedtls_read(void *ctx, unsigned char *buf, size_t len) struct wpabuf *local_buf; size_t data_len = len; + if (data->in_data == NULL) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + if (len > wpabuf_len(data->in_data)) { wpa_printf(MSG_ERROR, "don't have suffient data\n"); data_len = wpabuf_len(data->in_data); @@ -556,56 +560,26 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, if (wpabuf_len(in_data)) { conn->tls_io_data.in_data = wpabuf_dup(in_data); } - ret = mbedtls_ssl_handshake_step(&tls->ssl); - if (ret < 0) { - wpa_printf(MSG_ERROR, "%s:%d", __func__, __LINE__); - goto end; - } /* Multiple reads */ - while (conn->tls_io_data.in_data) { + while (tls->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + if (tls->ssl.state == MBEDTLS_SSL_CLIENT_CERTIFICATE) { + /* Read random data before session completes, not present after handshake */ + if (tls->ssl.handshake) { + os_memcpy(conn->randbytes, tls->ssl.handshake->randbytes, + TLS_RANDOM_LEN * 2); + } + } ret = mbedtls_ssl_handshake_step(&tls->ssl); + if (ret < 0) break; } - - /* State machine just started, get client hello */ - if (tls->ssl.state == MBEDTLS_SSL_CLIENT_HELLO) { - ret = mbedtls_ssl_handshake_step(&tls->ssl); - } - - if (ret < 0) { - wpa_printf(MSG_ERROR, "%s:%d", __func__, __LINE__); + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ) { + wpa_printf(MSG_INFO, "%s: ret is %d line:%d", __func__, ret, __LINE__); goto end; } - /* Already read sever data till hello done */ - if (tls->ssl.state == MBEDTLS_SSL_CLIENT_CERTIFICATE) { - /* Read random data before session completes, not present after handshake */ - if (tls->ssl.handshake) { - os_memcpy(conn->randbytes, tls->ssl.handshake->randbytes, - TLS_RANDOM_LEN * 2); - } - - /* trigger state machine multiple times to reach till finish */ - while (tls->ssl.state <= MBEDTLS_SSL_CLIENT_FINISHED) { - ret = mbedtls_ssl_handshake_step(&tls->ssl); - if (ret < 0) { - break; - } - } - } - - /* Trigger state machine till handshake is complete or error occures */ - if (tls->ssl.state == MBEDTLS_SSL_FLUSH_BUFFERS) { - while (tls->ssl.state <= MBEDTLS_SSL_HANDSHAKE_OVER) { - ret = mbedtls_ssl_handshake_step(&tls->ssl); - if (ret < 0) { - break; - } - } - } - if (!conn->tls_io_data.out_data) { wpa_printf(MSG_INFO, "application data is null, adding one byte for ack"); u8 *dummy = os_zalloc(1); From 03746de96f65923983d2a3c52457c0667960853f Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 18 Jun 2021 17:25:04 +0800 Subject: [PATCH 057/310] light sleep: add cpu power down support for esp32s3 --- components/esp_hw_support/sleep_retention.c | 4 + components/esp_pm/Kconfig | 8 +- components/hal/CMakeLists.txt | 1 + .../hal/esp32c3/include/hal/rtc_cntl_ll.h | 12 ++- components/hal/esp32c3/rtc_cntl_hal.c | 41 ++++++++-- .../hal/esp32s3/include/hal/rtc_cntl_ll.h | 30 +++++++ components/hal/esp32s3/rtc_cntl_hal.c | 82 +++++++++++++++++++ components/hal/include/hal/rtc_hal.h | 9 +- components/soc/esp32s3/include/soc/soc_caps.h | 10 +++ 9 files changed, 181 insertions(+), 16 deletions(-) create mode 100644 components/hal/esp32s3/rtc_cntl_hal.c diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index f915f3f107..564b983a77 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -29,7 +29,11 @@ static DRAM_ATTR sleep_retention_t s_retention; #if SOC_PM_SUPPORT_CPU_PD +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 #define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT) +#else +#define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_DMA | MALLOC_CAP_DEFAULT) +#endif esp_err_t esp_sleep_cpu_pd_low_init(bool enable) { diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index dc0e14422f..d7f42245a3 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -96,10 +96,12 @@ menu "Power Management" config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP bool "Power down CPU in light sleep" - depends on IDF_TARGET_ESP32C3 + depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 default y help - If enabled, the CPU will be powered down in light sleep. Enabling this option will consume - 1.68 KB of internal RAM and will reduce sleep current consumption by about 100 uA. + If enabled, the CPU will be powered down in light sleep. On esp32c3 soc, enabling this + option will consume 1.68 KB of internal RAM and will reduce sleep current consumption + by about 100 uA. On esp32s3 soc, enabling this option will consume 8.58 KB of internal + RAM and will reduce sleep current consumption by about 650 uA. endmenu # "Power Management" diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index ba6e51db8b..2959ecbb50 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -85,6 +85,7 @@ if(NOT BOOTLOADER_BUILD) "esp32s3/hmac_hal.c" "esp32s3/interrupt_descriptor_table.c" "esp32s3/touch_sensor_hal.c" + "esp32s3/rtc_cntl_hal.c" "usbh_hal.c") endif() diff --git a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h index 72385568a4..1ff802fde7 100644 --- a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h @@ -47,12 +47,18 @@ static inline void rtc_cntl_ll_gpio_clear_wakeup_pins(void) REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR); } -static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr) +static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr) { - /* write memory address to register */ REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_LINK_ADDR, (uint32_t)addr); - /* Enable clock */ +} + +static inline void rtc_cntl_ll_enable_cpu_retention_clock(void) +{ REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); +} + +static inline void rtc_cntl_ll_enable_cpu_retention(void) +{ /* Enable retention when cpu sleep enable */ REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); } diff --git a/components/hal/esp32c3/rtc_cntl_hal.c b/components/hal/esp32c3/rtc_cntl_hal.c index 2fb14a5b2f..90b2e9d083 100644 --- a/components/hal/esp32c3/rtc_cntl_hal.c +++ b/components/hal/esp32c3/rtc_cntl_hal.c @@ -16,8 +16,10 @@ #include "soc/soc_caps.h" #include "soc/lldesc.h" +#include "hal/dma_types.h" #include "hal/rtc_hal.h" #include "hal/assert.h" +#include "esp_attr.h" #define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ @@ -34,7 +36,7 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) lldesc_t *plink = (lldesc_t *)elem; plink->eof = next ? 0 : 1; - plink->owner = 1; + plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; plink->size = size >> 4; /* in unit of 16 bytes */ plink->length = size >> 4; plink->buf = buff; @@ -44,18 +46,39 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) return (void *)plink; } +#if SOC_PM_SUPPORT_CPU_PD + void rtc_cntl_hal_enable_cpu_retention(void *addr) { + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + if (addr) { - lldesc_t *plink = (lldesc_t *)addr; + if (retent->cpu_pd_mem) { + lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem; - /* dma link buffer configure */ - rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; - pbuf->cfg[0] = 0; - pbuf->cfg[1] = 0; - pbuf->cfg[2] = 0; - pbuf->cfg[3] = (uint32_t)-1; + /* dma link buffer configure */ + rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; + pbuf->cfg[0] = 0; + pbuf->cfg[1] = 0; + pbuf->cfg[2] = 0; + pbuf->cfg[3] = (uint32_t)-1; - rtc_cntl_ll_enable_cpu_retention((uint32_t)addr); + rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink); + rtc_cntl_ll_enable_cpu_retention_clock(); + rtc_cntl_ll_enable_cpu_retention(); + } } } + +void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + rtc_cntl_ll_disable_cpu_retention(); + } + } +} + +#endif // SOC_PM_SUPPORT_CPU_PD diff --git a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h index e1ad1d52cd..518c95a014 100644 --- a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h @@ -17,6 +17,7 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "soc/apb_ctrl_reg.h" #ifdef __cplusplus extern "C" { @@ -53,6 +54,35 @@ static inline void rtc_cntl_ll_ulp_wakeup_enable(void) SET_PERI_REG_BITS(RTC_CNTL_STATE0_REG, RTC_CNTL_WAKEUP_ENA_V, 0x800, RTC_CNTL_WAKEUP_ENA_S); } +static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t link_addr) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_CPU_LINK_ADDR, link_addr); +} + +static inline void rtc_cntl_ll_enable_cpu_retention_clock(void) +{ + REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); /* Enable internal 20 MHz clock */ +} + +static inline void rtc_cntl_ll_enable_cpu_retention(void) +{ + uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); + + /* TODO: I/d-Cache tagmem retention has not been implementted yet, + * so i/d-cache tagmem retention is explicitly disabled */ + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE); + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE); + + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | 0x1)); + /* Enable retention when cpu sleep enable */ + REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + +static inline void rtc_cntl_ll_disable_cpu_retention(void) +{ + REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/rtc_cntl_hal.c b/components/hal/esp32s3/rtc_cntl_hal.c new file mode 100644 index 0000000000..10edc61cab --- /dev/null +++ b/components/hal/esp32s3/rtc_cntl_hal.c @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for RTC CNTL (common part) + +#include "hal/rtc_hal.h" +#include "soc/soc_caps.h" +#include "esp32s3/rom/lldesc.h" +#include "esp32s3/rom/cache.h" +#include "hal/dma_types.h" +#include "hal/assert.h" +#include "esp_attr.h" + +#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ + +typedef struct rtc_cntl_link_buf_conf { + uint32_t cfg[4]; /* 4 word for dma link buffer configuration */ +} rtc_cntl_link_buf_conf_t; + +void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) +{ + HAL_ASSERT(elem != NULL); + HAL_ASSERT(buff != NULL); + HAL_ASSERT(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN); + + lldesc_t *plink = (lldesc_t *)elem; + + plink->eof = next ? 0 : 1; + plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + plink->size = size >> 4; /* in unit of 16 bytes */ + plink->length = size >> 4; + plink->buf = buff; + plink->offset = 0; + plink->sosf = 0; + STAILQ_NEXT(plink, qe) = next; + return (void *)plink; +} + +#if SOC_PM_SUPPORT_CPU_PD + +void rtc_cntl_hal_enable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem; + + /* dma link buffer configure */ + rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; + pbuf->cfg[0] = 0; + pbuf->cfg[1] = 0; + pbuf->cfg[2] = 0; + pbuf->cfg[3] = 0xfffe0000; + + rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink); + rtc_cntl_ll_enable_cpu_retention_clock(); + rtc_cntl_ll_enable_cpu_retention(); + } + } +} + +void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + /* TODO: I/d-cache tagmem retention has not been implemented yet, + * so after the system wakes up, all the contents of i/d-cache need + * to be invalidated. */ + Cache_Invalidate_ICache_All(); + Cache_Invalidate_DCache_All(); + rtc_cntl_ll_disable_cpu_retention(); + } + } +} + +#endif // SOC_PM_SUPPORT_CPU_PD diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index 8d74f4c4cd..2f032c460d 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -14,12 +14,19 @@ #pragma once +#include "soc/soc_caps.h" #include "hal/gpio_types.h" #include "hal/rtc_cntl_ll.h" #if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 #include "hal/rtc_io_ll.h" #endif +typedef struct rtc_cntl_sleep_retent { +#if SOC_PM_SUPPORT_CPU_PD + void *cpu_pd_mem; /* Internal ram address for cpu retention */ +#endif // SOC_PM_SUPPORT_CPU_PD +} rtc_cntl_sleep_retent_t; + #define RTC_HAL_DMA_LINK_NODE_SIZE (16) #if SOC_PM_SUPPORT_EXT_WAKEUP @@ -48,7 +55,7 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next); void rtc_cntl_hal_enable_cpu_retention(void *addr); -#define rtc_cntl_hal_disable_cpu_retention() rtc_cntl_ll_disable_cpu_retention() +void rtc_cntl_hal_disable_cpu_retention(void *addr); /* * Enable wakeup from ULP coprocessor. diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 848c0b1e01..e20111243f 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -118,6 +118,14 @@ #define SOC_LCD_I80_BUS_WIDTH (16) /*!< Intel 8080 bus width */ #define SOC_LCD_RGB_DATA_WIDTH (16) /*!< Number of LCD data lines */ +/*-------------------------- RTC CAPS --------------------------------------*/ +#define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) +#define SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM (549) +#define SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) +#define SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) + +#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) + /*-------------------------- RTCIO CAPS --------------------------------------*/ #include "rtc_io_caps.h" @@ -210,6 +218,8 @@ #define SOC_PM_SUPPORT_BT_WAKEUP (1) +#define SOC_PM_SUPPORT_CPU_PD (1) + /*-------------------------- Flash Encryption CAPS----------------------------*/ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64) From ccf1a9a1fc56c9b9a1cde67a983c47a4e643d1c0 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 20 Aug 2021 20:33:33 +0800 Subject: [PATCH 058/310] light sleep: add i/d-cache tagmem retention support for esp32s3 --- components/esp_hw_support/sleep_retention.c | 142 ++++++++++++++++++ components/esp_pm/Kconfig | 9 ++ components/esp_pm/linker.lf | 2 + .../hal/esp32s3/include/hal/rtc_cntl_ll.h | 62 +++++++- components/hal/esp32s3/rtc_cntl_hal.c | 71 ++++++++- components/hal/include/hal/rtc_hal.h | 29 ++++ components/soc/esp32s3/include/soc/soc_caps.h | 6 + 7 files changed, 312 insertions(+), 9 deletions(-) diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 564b983a77..86a4d84b4d 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -12,12 +12,20 @@ #include "esp_attr.h" #include "esp_sleep.h" #include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_heap_caps.h" #include "soc/soc_caps.h" #include "hal/rtc_hal.h" #include "esp_private/sleep_retention.h" #include "sdkconfig.h" +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/cache.h" +#endif + +static __attribute__((unused)) const char *TAG = "sleep"; + /** * Internal structure which holds all requested light sleep memory retention parameters */ @@ -27,6 +35,126 @@ typedef struct { static DRAM_ATTR sleep_retention_t s_retention; +#if SOC_PM_SUPPORT_TAGMEM_PD + +#define TAGMEM_PD_MEM_TYPE_CAPS (MALLOC_CAP_DMA | MALLOC_CAP_DEFAULT) + +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) +{ + int sets; /* i/d-cache total set counts */ + int index; /* virtual address mapping i/d-cache row offset */ + int waysgrp; + int icache_tagmem_blk_gs, dcache_tagmem_blk_gs; + struct cache_mode imode = { .icache = 1 }; + struct cache_mode dmode = { .icache = 0 }; + + /* calculate/prepare i-cache tag memory retention parameters */ + Cache_Get_Mode(&imode); + sets = imode.cache_size / imode.cache_ways / imode.cache_line_size; + index = (code_seg_vaddr / imode.cache_line_size) % sets; + waysgrp = imode.cache_ways >> 2; + + code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size); + + s_retention.retent.tagmem.icache.start_point = index; + s_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff; + s_retention.retent.tagmem.icache.vld_size = s_retention.retent.tagmem.icache.size; + if (code_seg_size < imode.cache_size / imode.cache_ways) { + s_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp; + } + s_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0; + icache_tagmem_blk_gs = s_retention.retent.tagmem.icache.vld_size ? s_retention.retent.tagmem.icache.vld_size : sets * waysgrp; + icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs); + ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10), + imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs); + + /* calculate/prepare d-cache tag memory retention parameters */ + Cache_Get_Mode(&dmode); + sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size; + index = (data_seg_vaddr / dmode.cache_line_size) % sets; + waysgrp = dmode.cache_ways >> 2; + + data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size); + + s_retention.retent.tagmem.dcache.start_point = index; + s_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff; + s_retention.retent.tagmem.dcache.vld_size = s_retention.retent.tagmem.dcache.size; +#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB + if (data_seg_size < dmode.cache_size / dmode.cache_ways) { + s_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp; + } + s_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0; +#else + s_retention.retent.tagmem.dcache.enable = 1; +#endif + dcache_tagmem_blk_gs = s_retention.retent.tagmem.dcache.vld_size ? s_retention.retent.tagmem.dcache.vld_size : sets * waysgrp; + dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs); + ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10), + dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs); + + /* For I or D cache tagmem retention, backup and restore are performed through + * RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache + * tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically + * aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4 + * i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */ + return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3); +} +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + +static esp_err_t esp_sleep_tagmem_pd_low_init(bool enable) +{ + if (enable) { +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + if (s_retention.retent.tagmem.link_addr == NULL) { + extern char _stext[], _etext[]; + uint32_t code_start = (uint32_t)_stext; + uint32_t code_size = (uint32_t)(_etext - _stext); +#if !CONFIG_ESP32S3_SPIRAM_SUPPORT + extern char _rodata_start[], _rodata_reserved_end[]; + uint32_t data_start = (uint32_t)_rodata_start; + uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start); +#else + uint32_t data_start = SOC_DROM_LOW; + uint32_t data_size = (SOC_EXTRAM_DATA_HIGH-SOC_EXTRAM_DATA_LOW) + (SOC_DROM_HIGH-SOC_DROM_LOW); +#endif + ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB", + code_start, (float)code_size/1024, data_start, (float)data_size/1024); + int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, + tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE, + TAGMEM_PD_MEM_TYPE_CAPS); + if (buf) { + memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE); + s_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL); + } else { + s_retention.retent.tagmem.icache.enable = 0; + s_retention.retent.tagmem.dcache.enable = 0; + s_retention.retent.tagmem.link_addr = NULL; + return ESP_ERR_NO_MEM; + } + } +#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + s_retention.retent.tagmem.icache.enable = 0; + s_retention.retent.tagmem.dcache.enable = 0; + s_retention.retent.tagmem.link_addr = NULL; +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + } else { +#if SOC_PM_SUPPORT_TAGMEM_PD + if (s_retention.retent.tagmem.link_addr) { + heap_caps_free(s_retention.retent.tagmem.link_addr); + s_retention.retent.tagmem.icache.enable = 0; + s_retention.retent.tagmem.dcache.enable = 0; + s_retention.retent.tagmem.link_addr = NULL; + } +#endif + } + return ESP_OK; +} + +#endif // SOC_PM_SUPPORT_TAGMEM_PD + #if SOC_PM_SUPPORT_CPU_PD #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 @@ -56,6 +184,14 @@ esp_err_t esp_sleep_cpu_pd_low_init(bool enable) s_retention.retent.cpu_pd_mem = NULL; } } +#if SOC_PM_SUPPORT_TAGMEM_PD + if (esp_sleep_tagmem_pd_low_init(enable) != ESP_OK) { +#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB + esp_sleep_cpu_pd_low_init(false); + return ESP_ERR_NO_MEM; +#endif + } +#endif return ESP_OK; } @@ -73,6 +209,9 @@ void sleep_enable_memory_retention(void) #if SOC_PM_SUPPORT_CPU_PD rtc_cntl_hal_enable_cpu_retention(&s_retention.retent); #endif +#if SOC_PM_SUPPORT_TAGMEM_PD + rtc_cntl_hal_enable_tagmem_retention(&s_retention.retent); +#endif } void IRAM_ATTR sleep_disable_memory_retention(void) @@ -80,6 +219,9 @@ void IRAM_ATTR sleep_disable_memory_retention(void) #if SOC_PM_SUPPORT_CPU_PD rtc_cntl_hal_disable_cpu_retention(&s_retention.retent); #endif +#if SOC_PM_SUPPORT_TAGMEM_PD + rtc_cntl_hal_disable_tagmem_retention(&s_retention.retent); +#endif } #endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index d7f42245a3..f10e888746 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -97,6 +97,7 @@ menu "Power Management" config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP bool "Power down CPU in light sleep" depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + select PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB default y help If enabled, the CPU will be powered down in light sleep. On esp32c3 soc, enabling this @@ -104,4 +105,12 @@ menu "Power Management" by about 100 uA. On esp32s3 soc, enabling this option will consume 8.58 KB of internal RAM and will reduce sleep current consumption by about 650 uA. + config PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + bool "Power down I/D-cache tag memory in light sleep" + depends on IDF_TARGET_ESP32S3 && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP + default y + help + If enabled, the I/D-cache tag memory will be retained in light sleep. Depending on the the + cache configuration, if this option is enabled, it will consume up to 9 KB of internal RAM. + endmenu # "Power Management" diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index a8f3a9e6ab..91237ef1b5 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -77,3 +77,5 @@ entries: gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash) if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) + if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y: + rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash) diff --git a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h index 518c95a014..075b961aa2 100644 --- a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h @@ -23,6 +23,9 @@ extern "C" { #endif +#define RTC_CNTL_LL_RETENTION_TARGET_CPU (BIT(0)) +#define RTC_CNTL_LL_RETENTION_TARGET_TAGMEM (BIT(1)) + static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t) { WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX); @@ -54,6 +57,51 @@ static inline void rtc_cntl_ll_ulp_wakeup_enable(void) SET_PERI_REG_BITS(RTC_CNTL_STATE0_REG, RTC_CNTL_WAKEUP_ENA_V, 0x800, RTC_CNTL_WAKEUP_ENA_S); } +static inline void rtc_cntl_ll_set_tagmem_retention_link_addr(uint32_t link_addr) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL1_REG, APB_CTRL_RETENTION_TAG_LINK_ADDR, link_addr); +} + +static inline void rtc_cntl_ll_enable_tagmem_retention(void) +{ + /* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */ + uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | RTC_CNTL_LL_RETENTION_TARGET_TAGMEM)); +} + +static inline void rtc_cntl_ll_enable_icache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_START_POINT, start_point); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_VLD_SIZE, vld_size); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_SIZE, size); + REG_SET_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE); +} + +static inline void rtc_cntl_ll_enable_dcache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_START_POINT, start_point); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_VLD_SIZE, vld_size); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_SIZE, size); + REG_SET_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE); +} + +static inline void rtc_cntl_ll_disable_tagmem_retention(void) +{ + /* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */ + uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target & ~RTC_CNTL_LL_RETENTION_TARGET_TAGMEM)); +} + +static inline void rtc_cntl_ll_disable_icache_tagmem_retention(void) +{ + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE); +} + +static inline void rtc_cntl_ll_disable_dcache_tagmem_retention(void) +{ + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE); +} + static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t link_addr) { REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_CPU_LINK_ADDR, link_addr); @@ -68,16 +116,18 @@ static inline void rtc_cntl_ll_enable_cpu_retention(void) { uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); - /* TODO: I/d-Cache tagmem retention has not been implementted yet, - * so i/d-cache tagmem retention is explicitly disabled */ - REG_CLR_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE); - REG_CLR_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE); - - REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | 0x1)); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | RTC_CNTL_LL_RETENTION_TARGET_CPU)); /* Enable retention when cpu sleep enable */ REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); } +static inline void rtc_cntl_ll_config_cpu_retention_timing(int wait, int clkoff_wait, int done_wait) +{ + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_WAIT, wait); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_CLKOFF_WAIT, clkoff_wait); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_DONE_WAIT, done_wait); +} + static inline void rtc_cntl_ll_disable_cpu_retention(void) { REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); diff --git a/components/hal/esp32s3/rtc_cntl_hal.c b/components/hal/esp32s3/rtc_cntl_hal.c index 10edc61cab..27d3c605be 100644 --- a/components/hal/esp32s3/rtc_cntl_hal.c +++ b/components/hal/esp32s3/rtc_cntl_hal.c @@ -41,6 +41,10 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) #if SOC_PM_SUPPORT_CPU_PD +#define DEFAULT_RETENTION_WAIT_CYCLES (0x7f) +#define DEFAULT_RETENTION_CLKOFF_WAIT_CYCLES (0xf) +#define DEFAULT_RETENTION_DONE_WAIT_CYCLES (0x7) + void rtc_cntl_hal_enable_cpu_retention(void *addr) { rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; @@ -57,6 +61,11 @@ void rtc_cntl_hal_enable_cpu_retention(void *addr) pbuf->cfg[3] = 0xfffe0000; rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink); + rtc_cntl_ll_config_cpu_retention_timing( + DEFAULT_RETENTION_WAIT_CYCLES, + DEFAULT_RETENTION_CLKOFF_WAIT_CYCLES, + DEFAULT_RETENTION_DONE_WAIT_CYCLES + ); rtc_cntl_ll_enable_cpu_retention_clock(); rtc_cntl_ll_enable_cpu_retention(); } @@ -69,14 +78,70 @@ void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) if (addr) { if (retent->cpu_pd_mem) { - /* TODO: I/d-cache tagmem retention has not been implemented yet, - * so after the system wakes up, all the contents of i/d-cache need - * to be invalidated. */ + /* I/d-cache tagmem retention has not been included or not + * been enabled, after the system wakes up, all the contents + * of i/d-cache need to be invalidated. */ +#if SOC_PM_SUPPORT_TAGMEM_PD + if (!retent->tagmem.icache.enable) { + Cache_Invalidate_ICache_All(); + } + if (!retent->tagmem.dcache.enable) { + Cache_Invalidate_DCache_All(); + } +#else Cache_Invalidate_ICache_All(); Cache_Invalidate_DCache_All(); +#endif // SOC_PM_SUPPORT_TAGMEM_PD rtc_cntl_ll_disable_cpu_retention(); } } } #endif // SOC_PM_SUPPORT_CPU_PD + +#if SOC_PM_SUPPORT_TAGMEM_PD + +void rtc_cntl_hal_enable_tagmem_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->tagmem.link_addr) { + rtc_cntl_ll_set_tagmem_retention_link_addr((uint32_t)(retent->tagmem.link_addr)); + rtc_cntl_ll_enable_tagmem_retention(); + if (retent->tagmem.icache.enable) { + rtc_cntl_ll_enable_icache_tagmem_retention( + retent->tagmem.icache.start_point, + retent->tagmem.icache.vld_size, + retent->tagmem.icache.size + ); + } + if (retent->tagmem.dcache.enable) { + rtc_cntl_ll_enable_dcache_tagmem_retention( + retent->tagmem.dcache.start_point, + retent->tagmem.dcache.vld_size, + retent->tagmem.dcache.size + ); + } + } + } +} + +void IRAM_ATTR rtc_cntl_hal_disable_tagmem_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->tagmem.link_addr) { + rtc_cntl_ll_disable_tagmem_retention(); + if (retent->tagmem.icache.enable) { + rtc_cntl_ll_disable_icache_tagmem_retention(); + } + if (retent->tagmem.dcache.enable) { + rtc_cntl_ll_disable_dcache_tagmem_retention(); + } + } + } +} + +#endif // SOC_PM_SUPPORT_TAGMEM_PD diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index 2f032c460d..90f965ed58 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -25,6 +25,23 @@ typedef struct rtc_cntl_sleep_retent { #if SOC_PM_SUPPORT_CPU_PD void *cpu_pd_mem; /* Internal ram address for cpu retention */ #endif // SOC_PM_SUPPORT_CPU_PD +#if SOC_PM_SUPPORT_TAGMEM_PD + struct { + void *link_addr; /* Internal ram address for tagmem retention */ + struct { + uint32_t start_point: 8, /* the row of start for i-cache tag memory */ + vld_size: 8, /* valid size of i-cache tag memory, unit: 4 i-cache tagmem blocks */ + size: 8, /* i-cache tag memory size, unit: 4 i-cache tagmem blocks */ + enable: 1; /* enable or disable i-cache tagmem retention */ + } icache; + struct { + uint32_t start_point: 9, /* the row of start for d-cache tag memory */ + vld_size: 9, /* valid size of d-cache tag memory, unit: 4 d-cache tagmem blocks */ + size: 9, /* d-cache tag memory size, unit: 4 d-cache tagmem blocks */ + enable: 1; /* enable or disable d-cache tagmem retention */ + } dcache; + } tagmem; +#endif // SOC_PM_SUPPORT_TAGMEM_PD } rtc_cntl_sleep_retent_t; #define RTC_HAL_DMA_LINK_NODE_SIZE (16) @@ -53,10 +70,22 @@ typedef struct rtc_cntl_sleep_retent { void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next); +#if SOC_PM_SUPPORT_CPU_PD + void rtc_cntl_hal_enable_cpu_retention(void *addr); void rtc_cntl_hal_disable_cpu_retention(void *addr); +#endif + +#if SOC_PM_SUPPORT_TAGMEM_PD + +void rtc_cntl_hal_enable_tagmem_retention(void *addr); + +void rtc_cntl_hal_disable_tagmem_retention(void *addr); + +#endif + /* * Enable wakeup from ULP coprocessor. */ diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index e20111243f..973f2074e7 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -126,6 +126,10 @@ #define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) +/* I/D Cache tag memory retention hardware parameters */ +#define SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH (128) +#define SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH >> 3) + /*-------------------------- RTCIO CAPS --------------------------------------*/ #include "rtc_io_caps.h" @@ -220,6 +224,8 @@ #define SOC_PM_SUPPORT_CPU_PD (1) +#define SOC_PM_SUPPORT_TAGMEM_PD (1) + /*-------------------------- Flash Encryption CAPS----------------------------*/ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64) From b975bc9d3864c501e6d6e0191c22fb2f14ad65bb Mon Sep 17 00:00:00 2001 From: Shubham Kulkarni Date: Thu, 26 Aug 2021 10:35:47 +0530 Subject: [PATCH 059/310] cJSON: Update submodule to latest release. This update fixes NULL pointer dereference issues in previous release Closes https://github.com/espressif/esp-idf/issues/7317 --- components/json/cJSON | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/json/cJSON b/components/json/cJSON index d2735278ed..d348621ca9 160000 --- a/components/json/cJSON +++ b/components/json/cJSON @@ -1 +1 @@ -Subproject commit d2735278ed1c2e4556f53a7a782063b31331dbf7 +Subproject commit d348621ca93571343a56862df7de4ff3bc9b5667 From 65db2d3d808c44f1b8dacb4b258c3ec9341816b6 Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Tue, 20 Apr 2021 13:24:48 +0530 Subject: [PATCH 060/310] ttfw_idf: Added IDFFPGADUT class Provision to burn and reset efuses of ESP32C3 chip on FPGA --- tools/ci/python_packages/ttfw_idf/IDFApp.py | 7 + tools/ci/python_packages/ttfw_idf/IDFDUT.py | 185 ++++++++++++++++-- tools/ci/python_packages/ttfw_idf/__init__.py | 11 +- 3 files changed, 180 insertions(+), 23 deletions(-) diff --git a/tools/ci/python_packages/ttfw_idf/IDFApp.py b/tools/ci/python_packages/ttfw_idf/IDFApp.py index 20496d54e0..f073e8f9ca 100644 --- a/tools/ci/python_packages/ttfw_idf/IDFApp.py +++ b/tools/ci/python_packages/ttfw_idf/IDFApp.py @@ -296,6 +296,13 @@ class IDFApp(App.BaseApp): d[configs[0]] = configs[1].rstrip() return d + def get_sdkconfig_config_value(self, config_key): # type: (str) -> Any + sdkconfig_dict = self.get_sdkconfig() + value = None + if (config_key in sdkconfig_dict): + value = sdkconfig_dict[config_key] + return value + @abstractmethod def _try_get_binary_from_local_fs(self): # type: () -> Optional[str] pass diff --git a/tools/ci/python_packages/ttfw_idf/IDFDUT.py b/tools/ci/python_packages/ttfw_idf/IDFDUT.py index 9025db8daa..a31b8008d3 100644 --- a/tools/ci/python_packages/ttfw_idf/IDFDUT.py +++ b/tools/ci/python_packages/ttfw_idf/IDFDUT.py @@ -13,6 +13,7 @@ # limitations under the License. """ DUT for IDF applications """ +import collections import functools import io import os @@ -24,6 +25,7 @@ import tempfile import time import pexpect +import serial # python2 and python3 queue package name is different try: @@ -43,6 +45,9 @@ except ImportError: # cheat and use IDF's copy of esptool if available sys.path.insert(0, os.path.join(idf_path, 'components', 'esptool_py', 'esptool')) import esptool +import espefuse +import espsecure + class IDFToolError(OSError): pass @@ -122,10 +127,18 @@ def _uses_esptool(func): settings = self.port_inst.get_settings() try: - if not self._rom_inst: - self._rom_inst = esptool.ESPLoader.detect_chip(self.port_inst) - self._rom_inst.connect('hard_reset') - esp = self._rom_inst.run_stub() + if not self.rom_inst: + if not self.secure_boot_en: + self.rom_inst = esptool.ESPLoader.detect_chip(self.port_inst) + else: + self.rom_inst = self.get_rom()(self.port_inst) + self.rom_inst.connect('hard_reset') + + if (self.secure_boot_en): + esp = self.rom_inst + esp.flash_spi_attach(0) + else: + esp = self.rom_inst.run_stub() ret = func(self, esp, *args, **kwargs) # do hard reset after use esptool @@ -158,10 +171,12 @@ class IDFDUT(DUT.SerialDUT): self.allow_dut_exception = allow_dut_exception self.exceptions = _queue.Queue() self.performance_items = _queue.Queue() - self._rom_inst = None + self.rom_inst = None + self.secure_boot_en = self.app.get_sdkconfig_config_value('CONFIG_SECURE_BOOT') and \ + not self.app.get_sdkconfig_config_value('CONFIG_EFUSE_VIRTUAL') @classmethod - def _get_rom(cls): + def get_rom(cls): raise NotImplementedError('This is an abstraction class, method not defined.') @classmethod @@ -175,7 +190,7 @@ class IDFDUT(DUT.SerialDUT): """ esp = None try: - esp = cls._get_rom()(port) + esp = cls.get_rom()(port) esp.connect() return esp.read_mac() except RuntimeError: @@ -190,7 +205,7 @@ class IDFDUT(DUT.SerialDUT): def confirm_dut(cls, port, **kwargs): inst = None try: - expected_rom_class = cls._get_rom() + expected_rom_class = cls.get_rom() except NotImplementedError: expected_rom_class = None @@ -258,7 +273,7 @@ class IDFDUT(DUT.SerialDUT): else: encrypt_files.append((address, nvs_file)) - self._write_flash(flash_files, encrypt_files, False, encrypt) + self.write_flash_data(flash_files, encrypt_files, False, encrypt) finally: for (_, f) in flash_files: f.close() @@ -266,7 +281,7 @@ class IDFDUT(DUT.SerialDUT): f.close() @_uses_esptool - def _write_flash(self, esp, flash_files=None, encrypt_files=None, ignore_flash_encryption_efuse_setting=True, encrypt=False): + def write_flash_data(self, esp, flash_files=None, encrypt_files=None, ignore_flash_encryption_efuse_setting=True, encrypt=False): """ Try flashing at a particular baud rate. @@ -291,8 +306,8 @@ class IDFDUT(DUT.SerialDUT): 'flash_freq': self.app.flash_settings['flash_freq'], 'addr_filename': flash_files or None, 'encrypt_files': encrypt_files or None, - 'no_stub': False, - 'compress': True, + 'no_stub': self.secure_boot_en, + 'compress': not self.secure_boot_en, 'verify': False, 'encrypt': encrypt, 'ignore_flash_encryption_efuse_setting': ignore_flash_encryption_efuse_setting, @@ -369,7 +384,7 @@ class IDFDUT(DUT.SerialDUT): if encrypt_files: encrypt_offs_files = [(offs, open(path, 'rb')) for (offs, path) in encrypt_files] - self._write_flash(flash_offs_files, encrypt_offs_files, ignore_flash_encryption_efuse_setting, encrypt) + self.write_flash_data(flash_offs_files, encrypt_offs_files, ignore_flash_encryption_efuse_setting, encrypt) finally: for (_, f) in flash_offs_files: f.close() @@ -562,7 +577,7 @@ class ESP32DUT(IDFDUT): TOOLCHAIN_PREFIX = 'xtensa-esp32-elf-' @classmethod - def _get_rom(cls): + def get_rom(cls): return esptool.ESP32ROM @@ -571,7 +586,7 @@ class ESP32S2DUT(IDFDUT): TOOLCHAIN_PREFIX = 'xtensa-esp32s2-elf-' @classmethod - def _get_rom(cls): + def get_rom(cls): return esptool.ESP32S2ROM @@ -580,7 +595,7 @@ class ESP32S3DUT(IDFDUT): TOOLCHAIN_PREFIX = 'xtensa-esp32s3-elf-' @classmethod - def _get_rom(cls): + def get_rom(cls): return esptool.ESP32S3ROM def erase_partition(self, esp, partition): @@ -592,7 +607,7 @@ class ESP32C3DUT(IDFDUT): TOOLCHAIN_PREFIX = 'riscv32-esp-elf-' @classmethod - def _get_rom(cls): + def get_rom(cls): return esptool.ESP32C3ROM @@ -601,13 +616,13 @@ class ESP8266DUT(IDFDUT): TOOLCHAIN_PREFIX = 'xtensa-lx106-elf-' @classmethod - def _get_rom(cls): + def get_rom(cls): return esptool.ESP8266ROM def get_target_by_rom_class(cls): for c in [ESP32DUT, ESP32S2DUT, ESP32S3DUT, ESP32C3DUT, ESP8266DUT, IDFQEMUDUT]: - if c._get_rom() == cls: + if c.get_rom() == cls: return c.TARGET return None @@ -654,7 +669,7 @@ class IDFQEMUDUT(IDFDUT): self.flash_image.flush() @classmethod - def _get_rom(cls): + def get_rom(cls): return esptool.ESP32ROM @classmethod @@ -704,3 +719,133 @@ class IDFQEMUDUT(IDFDUT): class ESP32QEMUDUT(IDFQEMUDUT): TARGET = 'esp32' # type: ignore TOOLCHAIN_PREFIX = 'xtensa-esp32-elf-' # type: ignore + + +class IDFFPGADUT(IDFDUT): + TARGET = None # type: str + TOOLCHAIN_PREFIX = None # type: str + ERASE_NVS = True + FLASH_ENCRYPT_SCHEME = None # type: str + FLASH_ENCRYPT_CNT_KEY = None # type: str + FLASH_ENCRYPT_CNT_VAL = 0 + FLASH_ENCRYPT_PURPOSE = None # type: str + SECURE_BOOT_EN_KEY = None # type: str + SECURE_BOOT_EN_VAL = 0 + FLASH_SECTOR_SIZE = 4096 + + def __init__(self, name, port, log_file, app, allow_dut_exception=False, efuse_reset_port=None, **kwargs): + super(IDFFPGADUT, self).__init__(name, port, log_file, app, allow_dut_exception=allow_dut_exception, **kwargs) + self.esp = self.get_rom()(port) + self.efuses = None + self.efuse_operations = None + self.efuse_reset_port = efuse_reset_port + + @classmethod + def get_rom(cls): + raise NotImplementedError('This is an abstraction class, method not defined.') + + def erase_partition(self, esp, partition): + raise NotImplementedError() + + def enable_efuses(self): + # We use an extra COM port to reset the efuses on FPGA. + # Connect DTR pin of the COM port to the efuse reset pin on daughter board + # Set EFUSEPORT env variable to the extra COM port + if not self.efuse_reset_port: + raise RuntimeError('EFUSEPORT not specified') + + # Stop any previous serial port operation + self.stop_receive() + if self.secure_boot_en: + self.esp.connect() + self.efuses, self.efuse_operations = espefuse.get_efuses(self.esp, False, False, True) + + def burn_efuse(self, field, val): + if not self.efuse_operations: + self.enable_efuses() + BurnEfuseArgs = collections.namedtuple('burn_efuse_args', ['name_value_pairs', 'only_burn_at_end']) + args = BurnEfuseArgs({field: val}, False) + self.efuse_operations.burn_efuse(self.esp, self.efuses, args) + + def burn_efuse_key(self, key, purpose, block): + if not self.efuse_operations: + self.enable_efuses() + BurnKeyArgs = collections.namedtuple('burn_key_args', + ['keyfile', 'keypurpose', 'block', + 'force_write_always', 'no_write_protect', 'no_read_protect', 'only_burn_at_end']) + args = BurnKeyArgs([key], + [purpose], + [block], + False, False, False, False) + self.efuse_operations.burn_key(self.esp, self.efuses, args) + + def burn_efuse_key_digest(self, key, purpose, block): + if not self.efuse_operations: + self.enable_efuses() + BurnDigestArgs = collections.namedtuple('burn_key_digest_args', + ['keyfile', 'keypurpose', 'block', + 'force_write_always', 'no_write_protect', 'no_read_protect', 'only_burn_at_end']) + args = BurnDigestArgs([open(key, 'rb')], + [purpose], + [block], + False, False, True, False) + self.efuse_operations.burn_key_digest(self.esp, self.efuses, args) + + def reset_efuses(self): + if not self.efuse_reset_port: + raise RuntimeError('EFUSEPORT not specified') + with serial.Serial(self.efuse_reset_port) as efuseport: + print('Resetting efuses') + efuseport.dtr = 0 + self.port_inst.setRTS(1) + self.port_inst.setRTS(0) + time.sleep(1) + efuseport.dtr = 1 + self.efuse_operations = None + self.efuses = None + + def sign_data(self, data_file, key_files, version, append_signature=0): + SignDataArgs = collections.namedtuple('sign_data_args', + ['datafile','keyfile','output', 'version', 'append_signatures']) + outfile = tempfile.NamedTemporaryFile() + args = SignDataArgs(data_file, key_files, outfile.name, str(version), append_signature) + espsecure.sign_data(args) + outfile.seek(0) + return outfile.read() + + +class ESP32C3FPGADUT(IDFFPGADUT): + TARGET = 'esp32c3' + TOOLCHAIN_PREFIX = 'riscv32-esp-elf-' + FLASH_ENCRYPT_SCHEME = 'AES-XTS' + FLASH_ENCRYPT_CNT_KEY = 'SPI_BOOT_CRYPT_CNT' + FLASH_ENCRYPT_CNT_VAL = 1 + FLASH_ENCRYPT_PURPOSE = 'XTS_AES_128_KEY' + SECURE_BOOT_EN_KEY = 'SECURE_BOOT_EN' + SECURE_BOOT_EN_VAL = 1 + + @classmethod + def get_rom(cls): + return esptool.ESP32C3ROM + + def erase_partition(self, esp, partition): + raise NotImplementedError() + + def flash_encrypt_burn_cnt(self): + self.burn_efuse(self.FLASH_ENCRYPT_CNT_KEY, self.FLASH_ENCRYPT_CNT_VAL) + + def flash_encrypt_burn_key(self, key, block=0): + self.burn_efuse_key(key, self.FLASH_ENCRYPT_PURPOSE, 'BLOCK_KEY%d' % block) + + def flash_encrypt_get_scheme(self): + return self.FLASH_ENCRYPT_SCHEME + + def secure_boot_burn_en_bit(self): + self.burn_efuse(self.SECURE_BOOT_EN_KEY, self.SECURE_BOOT_EN_VAL) + + def secure_boot_burn_digest(self, digest, key_index=0, block=0): + self.burn_efuse_key_digest(digest, 'SECURE_BOOT_DIGEST%d' % key_index, 'BLOCK_KEY%d' % block) + + @classmethod + def confirm_dut(cls, port, **kwargs): + return True, cls.TARGET diff --git a/tools/ci/python_packages/ttfw_idf/__init__.py b/tools/ci/python_packages/ttfw_idf/__init__.py index d4e2768473..9dbd35b70e 100644 --- a/tools/ci/python_packages/ttfw_idf/__init__.py +++ b/tools/ci/python_packages/ttfw_idf/__init__.py @@ -23,8 +23,8 @@ from tiny_test_fw import TinyFW, Utility from .DebugUtils import CustomProcess, GDBBackend, OCDBackend # noqa: export DebugUtils for users from .IDFApp import UT, ComponentUTApp, Example, IDFApp, LoadableElfTestApp, TestApp # noqa: export all Apps for users -from .IDFDUT import (ESP32C3DUT, ESP32DUT, ESP32QEMUDUT, ESP32S2DUT, ESP32S3DUT, # noqa: export DUTs for users - ESP8266DUT, IDFDUT) +from .IDFDUT import (ESP32C3DUT, ESP32C3FPGADUT, ESP32DUT, ESP32QEMUDUT, ESP32S2DUT, # noqa: export DUTs for users + ESP32S3DUT, ESP8266DUT, IDFDUT) from .unity_test_parser import TestFormat, TestResults # pass TARGET_DUT_CLS_DICT to Env.py to avoid circular dependency issue. @@ -33,6 +33,7 @@ TARGET_DUT_CLS_DICT = { 'ESP32S2': ESP32S2DUT, 'ESP32S3': ESP32S3DUT, 'ESP32C3': ESP32C3DUT, + 'ESP32C3FPGA': ESP32C3FPGADUT, } @@ -81,7 +82,11 @@ def local_test_check(decorator_target): if isinstance(decorator_target, list): if idf_target not in decorator_target: - raise ValueError('IDF_TARGET set to {}, not in decorator target value'.format(idf_target)) + fpga_target = ''.join((idf_target, 'FPGA')) + if fpga_target not in decorator_target: + raise ValueError('IDF_TARGET set to {}, not in decorator target value'.format(idf_target)) + else: + idf_target = fpga_target else: if idf_target != decorator_target: raise ValueError('IDF_TARGET set to {}, not equal to decorator target value'.format(idf_target)) From 3f7fed787200c400ab2670cc26eb2e1e013603dd Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Tue, 20 Apr 2021 16:40:33 +0530 Subject: [PATCH 061/310] test_app: Added automated test cases for secure_boot --- .../test_apps/security/secure_boot/README.md | 64 +++++- .../security/secure_boot/example_test.py | 183 ++++++++++++++++++ 2 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 tools/test_apps/security/secure_boot/example_test.py diff --git a/tools/test_apps/security/secure_boot/README.md b/tools/test_apps/security/secure_boot/README.md index fede569c6f..9015e60c8c 100644 --- a/tools/test_apps/security/secure_boot/README.md +++ b/tools/test_apps/security/secure_boot/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-S2 | -| ----------------- | ----- | -------- | +| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | # Secure Boot @@ -9,7 +9,13 @@ The example checks if the secure boot feature is enabled/disabled and if enabled ### Hardware Required -ESP32 (supports Secure Boot V1) or ESP32-ECO3 (supports Secure Boot V2 & Secure Boot V1). It is recommended to use Secure Boot V2 from ESP32-ECO3 onwards. +Any of the following ESP module: +* ESP32 (supports Secure Boot V1) +* ESP32-ECO3 (supports Secure Boot V2 & Secure Boot V1) +* ESP32S2 (supports Secure Boot V2) +* ESP32C3-ECO3 (supports Secure Boot V2) + +It is recommended to use Secure Boot V2 from ESP32-ECO3 onwards. ### Configure the project @@ -54,3 +60,55 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Troubleshooting +--- + +# Secure Boot tests (For internal use only) + +Purpose of the example test cases (`example_test.py`) is to test the secure boot implementation and detect if it is broken. It consists of positive and negative test cases. + +### Hardware required + +* FPGA setup with ESP32C3 image + +* COM port for programming and export it as ESPPORT + e.g `export ESPPORT=/dev/ttyUSB0` + +* Use another COM port for resetting efuses and connect its DTR pin to efuse reset pin on the FPGA board. Export it as EFUSEPORT + e.g `export EFUSEPORT=/dev/ttyUSB1` + +### Configure the project + +``` +export IDF_ENV_FPGA=1 + +idf.py set-target esp32c3 + +idf.py menuconfig +``` + +Under `Security features` + +- Enable the `Enable hardware Secure Boot` + +- Set the secure boot signing key ("test_rsa_3072_key.pem") + +- Set UART ROM download mode to ENABLED (Required for the script to read the EFUSE) + +- Install and export TTFW requirements +``` +python -m pip install -r $IDF_PATH/tools/ci/python_packages/ttfw_idf/requirements.txt + +export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages" +``` + +### Build and test + +- Build the example +``` +idf.py build +``` + +- Run the example test +``` +python example_test.py +``` diff --git a/tools/test_apps/security/secure_boot/example_test.py b/tools/test_apps/security/secure_boot/example_test.py new file mode 100644 index 0000000000..17eae760fb --- /dev/null +++ b/tools/test_apps/security/secure_boot/example_test.py @@ -0,0 +1,183 @@ +from __future__ import print_function + +import os +import struct +import zlib +from io import BytesIO + +import ttfw_idf + +# To prepare a runner for these tests, +# 1. Connect an FPGA with C3 image +# 2. Use a COM port for programming and export it as ESPPORT +# e.g export ESPPORT=/dev/ttyUSB0 +# 3. Use another COM port for resetting efuses and connect its DTR pin to efuse reset pin on the FPGA board. +# Export it as EFUSEPORT +# e.g export EFUSEPORT=/dev/ttyUSB1 +# 4. Run these tests + + +def corrupt_signature(signed_bootloader, seed=0, corrupt_sig=True, corrupt_crc=False, corrupt_single_block=None): + # type: (bytes, int, bool, bool, int) -> bytes + image = signed_bootloader[:-4096] + signature = signed_bootloader[-4096:] + sig_blocks = (signature[0:1216], signature[1216:2432], signature[2432:3648]) + new_blocks = tuple(corrupt_sig_block(s, seed, corrupt_sig, corrupt_crc) for s in sig_blocks) + + # if corrupt_single_block is None, corrupt all blocks + # otherwise, only corrupt the one with that index set + corr_sig_blocks = tuple(new_blocks[n] if corrupt_single_block in [None, n] else sig_blocks[n] for n in range(3)) + + return image + b''.join(corr_sig_blocks) + signature[3648:] + + +def corrupt_sig_block(sig_block, seed=0, corrupt_sig=True, corrupt_crc=False): + # type: (bytes, int, bool, bool) -> bytes + assert len(sig_block) == 1216 + magic = sig_block[0] + assert magic in [0xe7, 0xff] + if magic != 0xe7: + return sig_block # not valid + data = sig_block[:812] + new_sig = sig = sig_block[812:1196] + crc = sig_block[1196:1200] + padding = sig_block[1200:1216] + + if corrupt_sig: + corrupt_idx = seed % len(sig) + corrupt_delta = zlib.crc32(bytes(seed)) & 0xFF + if corrupt_delta == 0: + corrupt_delta = 1 + + new_byte = sig[corrupt_idx] ^ corrupt_delta + + new_sig = sig[0:corrupt_idx] + bytes([new_byte]) + sig[corrupt_idx + 1:] + + assert new_sig != sig + + if not corrupt_crc: + crc = struct.pack(' None + dut.reset_efuses() + bootloader_bin = os.path.join(dut.app.binary_path, 'bootloader/bootloader.bin') + with open(bootloader_bin, 'rb') as f: + dut.write_flash_data([(0x0, f)], None, True, False) + dut.start_app() + + +# Test secure boot flow. +# Correctly signed bootloader + correctly signed app should work +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +def test_examples_security_secure_boot(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + efuse_port = os.getenv('EFUSEPORT') + dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) + dut_start_secure_app(dut) + dut.expect('Secure Boot is enabled', timeout=2) + + +# Test efuse key index and key block combination. +# Any key index can be written to any key block and should work +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +def test_examples_security_secure_boot_key_combo(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + efuse_port = os.getenv('EFUSEPORT') + dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) + dut_start_secure_app(dut) + for index in range(3): + for block in range(6): + dut.reset_efuses() + dut.secure_boot_burn_en_bit() + dut.secure_boot_burn_digest('test_rsa_3072_key.pem', index, block) + dut.reset() + dut.expect('Secure Boot is enabled', timeout=2) + + +# Test secure boot key revoke. +# If a key is revoked, bootloader signed with that key should fail verification +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +def test_examples_security_secure_boot_key_revoke(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + efuse_port = os.getenv('EFUSEPORT') + dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) + dut_start_secure_app(dut) + for index in range(3): + dut.reset_efuses() + dut.secure_boot_burn_en_bit() + dut.secure_boot_burn_digest('test_rsa_3072_key.pem', index, 0) + dut.burn_efuse('SECURE_BOOT_KEY_REVOKE%d' % index, 1) + dut.reset() + dut.expect('secure boot verification failed', timeout=2) + + +# Test bootloader signature corruption. +# Corrupt one byte at a time of bootloader signature and test that the verification fails +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +def test_examples_security_secure_boot_corrupt_bl_sig(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + efuse_port = os.getenv('EFUSEPORT') + dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) + dut.reset_efuses() + dut.secure_boot_burn_en_bit() + dut.secure_boot_burn_digest('test_rsa_3072_key.pem', 0, 0) + bootloader_bin = os.path.join(dut.app.binary_path, 'bootloader/bootloader.bin') + with open(bootloader_bin, 'rb') as f: + signed_bl = f.read() + + seeds = range(0, 384) + max_seed = max(seeds) + + for seed in seeds: + print('Case %d / %d' % (seed, max_seed)) + corrupt_bl = corrupt_signature(signed_bl, seed=seed) + dut.write_flash_data([(0x0, BytesIO(corrupt_bl))]) + dut.expect('Signature Check Failed', timeout=2) + + +# Test app signature corruption. +# Corrupt app signature, one byte at a time, and test that the verification fails +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +def test_examples_security_secure_boot_corrupt_app_sig(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + efuse_port = os.getenv('EFUSEPORT') + dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) + dut_start_secure_app(dut) + dut.reset_efuses() + dut.secure_boot_burn_en_bit() + dut.secure_boot_burn_digest('test_rsa_3072_key.pem', 0, 0) + app_bin = os.path.join(dut.app.binary_path, 'secure_boot.bin') + with open(app_bin, 'rb') as f: + signed_app = f.read() + + seeds = range(0, 384) + max_seed = max(seeds) + + for seed in seeds: + print('Case %d / %d' % (seed, max_seed)) + corrupt_app = corrupt_signature(signed_app, seed=seed) + dut.write_flash_data([(0x20000, BytesIO(corrupt_app))]) + dut.expect('Signature Check Failed', timeout=2) + dut.expect('image valid, signature bad', timeout=2) + + print('Testing invalid CRC...') + # Valid signature but invalid CRC + dut.reset_efuses() + dut.secure_boot_burn_en_bit() + dut.secure_boot_burn_digest('test_rsa_3072_key.pem', 0, 0) + + corrupt_app = corrupt_signature(signed_app, corrupt_sig=False, corrupt_crc=True) + dut.write_flash_data([(0x20000, BytesIO(corrupt_app))]) + dut.expect('Sig block 0 invalid: Stored CRC ends', timeout=2) + dut.expect('Secure boot signature verification failed', timeout=2) + dut.expect('No bootable app partitions in the partition table', timeout=2) + + +if __name__ == '__main__': + test_examples_security_secure_boot() + test_examples_security_secure_boot_key_combo() + test_examples_security_secure_boot_key_revoke() + test_examples_security_secure_boot_corrupt_bl_sig() + test_examples_security_secure_boot_corrupt_app_sig() From cfcb893289ed72696ec7d8f466a3b0f9f03d54ee Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Wed, 25 Aug 2021 22:16:52 +0530 Subject: [PATCH 062/310] ttfw_idf: Added ESP32-S3 FPGA support Provision to burn and reset efuses of ESP32S3 on FPGA test_app: Enabled automated test cases for ESP32S3 --- tools/ci/python_packages/ttfw_idf/IDFDUT.py | 37 +++++++++++++++++++ tools/ci/python_packages/ttfw_idf/__init__.py | 3 +- .../test_apps/security/secure_boot/README.md | 9 +++-- .../security/secure_boot/example_test.py | 10 ++--- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/tools/ci/python_packages/ttfw_idf/IDFDUT.py b/tools/ci/python_packages/ttfw_idf/IDFDUT.py index a31b8008d3..13a8b0977b 100644 --- a/tools/ci/python_packages/ttfw_idf/IDFDUT.py +++ b/tools/ci/python_packages/ttfw_idf/IDFDUT.py @@ -849,3 +849,40 @@ class ESP32C3FPGADUT(IDFFPGADUT): @classmethod def confirm_dut(cls, port, **kwargs): return True, cls.TARGET + + +class ESP32S3FPGADUT(IDFFPGADUT): + TARGET = 'esp32s3' + TOOLCHAIN_PREFIX = 'xtensa-esp32s3-elf-' + FLASH_ENCRYPT_SCHEME = 'AES-XTS' + FLASH_ENCRYPT_CNT_KEY = 'SPI_BOOT_CRYPT_CNT' + FLASH_ENCRYPT_CNT_VAL = 1 + FLASH_ENCRYPT_PURPOSE = 'XTS_AES_128_KEY' + SECURE_BOOT_EN_KEY = 'SECURE_BOOT_EN' + SECURE_BOOT_EN_VAL = 1 + + @classmethod + def get_rom(cls): + return esptool.ESP32S3ROM + + def erase_partition(self, esp, partition): + raise NotImplementedError() + + def flash_encrypt_burn_cnt(self): + self.burn_efuse(self.FLASH_ENCRYPT_CNT_KEY, self.FLASH_ENCRYPT_CNT_VAL) + + def flash_encrypt_burn_key(self, key, block=0): + self.burn_efuse_key(key, self.FLASH_ENCRYPT_PURPOSE, 'BLOCK_KEY%d' % block) + + def flash_encrypt_get_scheme(self): + return self.FLASH_ENCRYPT_SCHEME + + def secure_boot_burn_en_bit(self): + self.burn_efuse(self.SECURE_BOOT_EN_KEY, self.SECURE_BOOT_EN_VAL) + + def secure_boot_burn_digest(self, digest, key_index=0, block=0): + self.burn_efuse_key_digest(digest, 'SECURE_BOOT_DIGEST%d' % key_index, 'BLOCK_KEY%d' % block) + + @classmethod + def confirm_dut(cls, port, **kwargs): + return True, cls.TARGET diff --git a/tools/ci/python_packages/ttfw_idf/__init__.py b/tools/ci/python_packages/ttfw_idf/__init__.py index 9dbd35b70e..51c7d587ec 100644 --- a/tools/ci/python_packages/ttfw_idf/__init__.py +++ b/tools/ci/python_packages/ttfw_idf/__init__.py @@ -24,7 +24,7 @@ from tiny_test_fw import TinyFW, Utility from .DebugUtils import CustomProcess, GDBBackend, OCDBackend # noqa: export DebugUtils for users from .IDFApp import UT, ComponentUTApp, Example, IDFApp, LoadableElfTestApp, TestApp # noqa: export all Apps for users from .IDFDUT import (ESP32C3DUT, ESP32C3FPGADUT, ESP32DUT, ESP32QEMUDUT, ESP32S2DUT, # noqa: export DUTs for users - ESP32S3DUT, ESP8266DUT, IDFDUT) + ESP32S3DUT, ESP32S3FPGADUT, ESP8266DUT, IDFDUT) from .unity_test_parser import TestFormat, TestResults # pass TARGET_DUT_CLS_DICT to Env.py to avoid circular dependency issue. @@ -34,6 +34,7 @@ TARGET_DUT_CLS_DICT = { 'ESP32S3': ESP32S3DUT, 'ESP32C3': ESP32C3DUT, 'ESP32C3FPGA': ESP32C3FPGADUT, + 'ESP32S3FPGA': ESP32S3FPGADUT, } diff --git a/tools/test_apps/security/secure_boot/README.md b/tools/test_apps/security/secure_boot/README.md index 9015e60c8c..3d30576a4c 100644 --- a/tools/test_apps/security/secure_boot/README.md +++ b/tools/test_apps/security/secure_boot/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | -| ----------------- | ----- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | # Secure Boot @@ -14,6 +14,7 @@ Any of the following ESP module: * ESP32-ECO3 (supports Secure Boot V2 & Secure Boot V1) * ESP32S2 (supports Secure Boot V2) * ESP32C3-ECO3 (supports Secure Boot V2) +* ESP32S3 (supports Secure Boot V2) It is recommended to use Secure Boot V2 from ESP32-ECO3 onwards. @@ -68,7 +69,7 @@ Purpose of the example test cases (`example_test.py`) is to test the secure boot ### Hardware required -* FPGA setup with ESP32C3 image +* FPGA setup with ESP32C3/ESP32S3 image * COM port for programming and export it as ESPPORT e.g `export ESPPORT=/dev/ttyUSB0` @@ -81,7 +82,7 @@ Purpose of the example test cases (`example_test.py`) is to test the secure boot ``` export IDF_ENV_FPGA=1 -idf.py set-target esp32c3 +idf.py set-target esp32c3 #(or esp32s3) idf.py menuconfig ``` diff --git a/tools/test_apps/security/secure_boot/example_test.py b/tools/test_apps/security/secure_boot/example_test.py index 17eae760fb..ac2a14ad50 100644 --- a/tools/test_apps/security/secure_boot/example_test.py +++ b/tools/test_apps/security/secure_boot/example_test.py @@ -75,7 +75,7 @@ def dut_start_secure_app(dut): # type: (ttfw_idf.IDFDUT) -> None # Test secure boot flow. # Correctly signed bootloader + correctly signed app should work -@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga', 'esp32s3fpga'], ignore=True) def test_examples_security_secure_boot(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None efuse_port = os.getenv('EFUSEPORT') dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) @@ -85,7 +85,7 @@ def test_examples_security_secure_boot(env, _): # type: (ttfw_idf.TinyFW.Env, # Test efuse key index and key block combination. # Any key index can be written to any key block and should work -@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga', 'esp32s3fpga'], ignore=True) def test_examples_security_secure_boot_key_combo(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None efuse_port = os.getenv('EFUSEPORT') dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) @@ -101,7 +101,7 @@ def test_examples_security_secure_boot_key_combo(env, _): # type: (ttfw_idf # Test secure boot key revoke. # If a key is revoked, bootloader signed with that key should fail verification -@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga', 'esp32s3fpga'], ignore=True) def test_examples_security_secure_boot_key_revoke(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None efuse_port = os.getenv('EFUSEPORT') dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) @@ -117,7 +117,7 @@ def test_examples_security_secure_boot_key_revoke(env, _): # type: (ttfw_idf # Test bootloader signature corruption. # Corrupt one byte at a time of bootloader signature and test that the verification fails -@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga', 'esp32s3fpga'], ignore=True) def test_examples_security_secure_boot_corrupt_bl_sig(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None efuse_port = os.getenv('EFUSEPORT') dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) @@ -140,7 +140,7 @@ def test_examples_security_secure_boot_corrupt_bl_sig(env, _): # type: (ttfw # Test app signature corruption. # Corrupt app signature, one byte at a time, and test that the verification fails -@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga'], ignore=True) +@ttfw_idf.idf_custom_test(env_tag='Example_Secure_Boot', target=['esp32c3fpga', 'esp32s3fpga'], ignore=True) def test_examples_security_secure_boot_corrupt_app_sig(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None efuse_port = os.getenv('EFUSEPORT') dut = env.get_dut('secure_boot', 'tools/test_apps/security/secure_boot', efuse_reset_port=efuse_port) From 2213a3515628ed998156fbcfa25f03b0074a37d8 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Tue, 24 Aug 2021 14:23:41 +0800 Subject: [PATCH 063/310] openthread: fix mesh local prefix missing in border agent example --- components/ieee802154/lib | 2 +- components/openthread/lib | 2 +- examples/openthread/ot_br/main/esp_ot_br.c | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/components/ieee802154/lib b/components/ieee802154/lib index dd7afcc9f6..1751a7a4e2 160000 --- a/components/ieee802154/lib +++ b/components/ieee802154/lib @@ -1 +1 @@ -Subproject commit dd7afcc9f6d4bbd923f601e0d59b0e59b0170a91 +Subproject commit 1751a7a4e269822b8c193b291e58e02c2c670d22 diff --git a/components/openthread/lib b/components/openthread/lib index 5e09d71ee4..01a326d950 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 5e09d71ee4a6a8165ae4cdbabc46b79a88a95c11 +Subproject commit 01a326d9501b2757b4e04a900e6540c048f41b29 diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index a892e1dd7d..f539db0a2d 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -122,7 +122,6 @@ static void create_config_network(otInstance *instance) abort(); } dataset.mComponents.mIsPskcPresent = true; - dataset.mComponents.mIsMeshLocalPrefixPresent = false; if (otDatasetSetActive(instance, &dataset) != OT_ERROR_NONE) { ESP_LOGE(TAG, "Failed to set OpenThread active dataset."); abort(); From ab0c5fed257551468c29dd420b6e484ecc824f9c Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 17 Jun 2021 13:40:26 +0800 Subject: [PATCH 064/310] eth: dont warn nego timeout if link is down --- components/esp_eth/src/esp_eth_phy_dm9051.c | 7 ++++++- components/esp_eth/src/esp_eth_phy_dp83848.c | 8 ++++++-- components/esp_eth/src/esp_eth_phy_ip101.c | 8 ++++++-- components/esp_eth/src/esp_eth_phy_ksz80xx.c | 8 ++++++-- components/esp_eth/src/esp_eth_phy_ksz8851snl.c | 9 +++++++-- components/esp_eth/src/esp_eth_phy_lan87xx.c | 7 ++++++- components/esp_eth/src/esp_eth_phy_rtl8201.c | 8 ++++++-- 7 files changed, 43 insertions(+), 12 deletions(-) diff --git a/components/esp_eth/src/esp_eth_phy_dm9051.c b/components/esp_eth/src/esp_eth_phy_dm9051.c index 5c1c112a61..dcbc3d44fe 100644 --- a/components/esp_eth/src/esp_eth_phy_dm9051.c +++ b/components/esp_eth/src/esp_eth_phy_dm9051.c @@ -195,6 +195,11 @@ static esp_err_t dm9051_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `dm9051_get_link()` + */ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -222,7 +227,7 @@ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy) break; } } - if (to >= dm9051->autonego_timeout_ms / 100) { + if ((to >= dm9051->autonego_timeout_ms / 100) && (dm9051->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout"); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_dp83848.c b/components/esp_eth/src/esp_eth_phy_dp83848.c index cafef8d59c..a245a902d2 100644 --- a/components/esp_eth/src/esp_eth_phy_dp83848.c +++ b/components/esp_eth/src/esp_eth_phy_dp83848.c @@ -189,6 +189,11 @@ static esp_err_t dp83848_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `dp83848_get_link()` + */ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -216,8 +221,7 @@ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= dp83848->autonego_timeout_ms / 100) { + if ((to >= dp83848->autonego_timeout_ms / 100) && (dp83848->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_ip101.c b/components/esp_eth/src/esp_eth_phy_ip101.c index e8424288b6..280f116a3c 100644 --- a/components/esp_eth/src/esp_eth_phy_ip101.c +++ b/components/esp_eth/src/esp_eth_phy_ip101.c @@ -230,6 +230,11 @@ static esp_err_t ip101_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `ip101_get_link()` + */ static esp_err_t ip101_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -255,8 +260,7 @@ static esp_err_t ip101_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= ip101->autonego_timeout_ms / 100) { + if ((to >= ip101->autonego_timeout_ms / 100) && (ip101->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_ksz80xx.c b/components/esp_eth/src/esp_eth_phy_ksz80xx.c index 1674648085..638f22c2ff 100644 --- a/components/esp_eth/src/esp_eth_phy_ksz80xx.c +++ b/components/esp_eth/src/esp_eth_phy_ksz80xx.c @@ -208,6 +208,11 @@ static esp_err_t ksz80xx_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `ksz80xx_get_link()` + */ static esp_err_t ksz80xx_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -233,8 +238,7 @@ static esp_err_t ksz80xx_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= ksz80xx->autonego_timeout_ms / 100) { + if ((to >= ksz80xx->autonego_timeout_ms / 100) && (ksz80xx->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_ksz8851snl.c b/components/esp_eth/src/esp_eth_phy_ksz8851snl.c index 2f72e6b394..3871a3e010 100644 --- a/components/esp_eth/src/esp_eth_phy_ksz8851snl.c +++ b/components/esp_eth/src/esp_eth_phy_ksz8851snl.c @@ -160,6 +160,11 @@ err: return ret; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `phy_ksz8851_get_link()` + */ static esp_err_t phy_ksz8851_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -181,8 +186,8 @@ static esp_err_t phy_ksz8851_negotiate(esp_eth_phy_t *phy) break; } } - if (to >= ksz8851->autonego_timeout_ms / 100) { - ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout"); + if ((to >= ksz8851->autonego_timeout_ms / 100) && (ksz8851->link_status == ETH_LINK_UP)) { + ESP_LOGW(TAG, "auto negotiation timeout"); } ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed"); diff --git a/components/esp_eth/src/esp_eth_phy_lan87xx.c b/components/esp_eth/src/esp_eth_phy_lan87xx.c index 6678253f65..5dc21b5c9a 100644 --- a/components/esp_eth/src/esp_eth_phy_lan87xx.c +++ b/components/esp_eth/src/esp_eth_phy_lan87xx.c @@ -343,6 +343,11 @@ static esp_err_t lan87xx_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `lan87xx_get_link()` + */ static esp_err_t lan87xx_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -371,7 +376,7 @@ static esp_err_t lan87xx_negotiate(esp_eth_phy_t *phy) } } /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= lan87xx->autonego_timeout_ms / 100) { + if (to >= lan87xx->autonego_timeout_ms / 100 && (lan87xx->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_rtl8201.c b/components/esp_eth/src/esp_eth_phy_rtl8201.c index 8ba4a35445..6733328b80 100644 --- a/components/esp_eth/src/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/esp_eth_phy_rtl8201.c @@ -183,6 +183,11 @@ static esp_err_t rtl8201_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `rtl8201_get_link()` + */ static esp_err_t rtl8201_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -208,8 +213,7 @@ static esp_err_t rtl8201_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= rtl8201->autonego_timeout_ms / 100) { + if ((to >= rtl8201->autonego_timeout_ms / 100) && (rtl8201->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; From d9fdb9dc3f34abfea51d60fc763a29dce13ee95c Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 27 Aug 2021 12:47:08 +0530 Subject: [PATCH 065/310] esp_rom: remove "newlib.h" header We found conflict in "sizeof(time_t)" due to inclusion of this header over toolchain specific "newlib.h". Moreover, there are no users for this header and implementation for API is also not available in ROM. Hence removing it. --- .../esp_rom/include/esp32c3/rom/newlib.h | 50 ------------------- .../esp_rom/include/esp32h2/rom/newlib.h | 50 ------------------- 2 files changed, 100 deletions(-) delete mode 100644 components/esp_rom/include/esp32c3/rom/newlib.h delete mode 100644 components/esp_rom/include/esp32h2/rom/newlib.h diff --git a/components/esp_rom/include/esp32c3/rom/newlib.h b/components/esp_rom/include/esp32c3/rom/newlib.h deleted file mode 100644 index a852bdb7f5..0000000000 --- a/components/esp_rom/include/esp32c3/rom/newlib.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Global variables used by newlib in ROM - - Note that any of these symbols which are used by both ROM & IDF will have duplicate copies - in each "side" of the memory. However they're all pointers, and the pointers will be to the same - thing, so it's not a big memory waste and functionality is the same. - - Some variables which look like they should be here, but aren't: - - - __sf_fake_stdin, __sf_fake_stdout, __sf_fake_stderr - These are defined in ROM because ROM includes findfp.c, - but only used if _REENT_INIT or _REENT_INIT_PTR are ever called and ROM doesn't use these macros anywhere unless - printf() or similar is called without initializing reent first. ESP-IDF sets up its own minimal reent structures. - - - __lock___sinit_recursive_mutex, etc. - these are combined into common_recursive_mutex & common_mutex to save space -*/ -typedef struct { - _LOCK_T common_recursive_mutex; - _LOCK_T common_mutex; - struct _reent *global_reent; -} esp_rom_newlib_global_data_t; - -/* Called from IDF newlib component setup - to initialize common data shared between ROM and IDF -*/ -void esp_rom_newlib_init_global_data(const esp_rom_newlib_global_data_t *data); - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_rom/include/esp32h2/rom/newlib.h b/components/esp_rom/include/esp32h2/rom/newlib.h deleted file mode 100644 index a852bdb7f5..0000000000 --- a/components/esp_rom/include/esp32h2/rom/newlib.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Global variables used by newlib in ROM - - Note that any of these symbols which are used by both ROM & IDF will have duplicate copies - in each "side" of the memory. However they're all pointers, and the pointers will be to the same - thing, so it's not a big memory waste and functionality is the same. - - Some variables which look like they should be here, but aren't: - - - __sf_fake_stdin, __sf_fake_stdout, __sf_fake_stderr - These are defined in ROM because ROM includes findfp.c, - but only used if _REENT_INIT or _REENT_INIT_PTR are ever called and ROM doesn't use these macros anywhere unless - printf() or similar is called without initializing reent first. ESP-IDF sets up its own minimal reent structures. - - - __lock___sinit_recursive_mutex, etc. - these are combined into common_recursive_mutex & common_mutex to save space -*/ -typedef struct { - _LOCK_T common_recursive_mutex; - _LOCK_T common_mutex; - struct _reent *global_reent; -} esp_rom_newlib_global_data_t; - -/* Called from IDF newlib component setup - to initialize common data shared between ROM and IDF -*/ -void esp_rom_newlib_init_global_data(const esp_rom_newlib_global_data_t *data); - -#ifdef __cplusplus -} -#endif From 32abe5ce429bd00052450370e5b61c7f16d54431 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 27 Aug 2021 19:59:33 +0800 Subject: [PATCH 066/310] fix apb freq err temporarily --- components/esp32h2/Kconfig | 3 +++ components/soc/esp32h2/include/soc/soc.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/esp32h2/Kconfig b/components/esp32h2/Kconfig index 4413c4b0e5..f8e7f6fc56 100644 --- a/components/esp32h2/Kconfig +++ b/components/esp32h2/Kconfig @@ -10,10 +10,13 @@ menu "ESP32H2-Specific" config ESP32H2_DEFAULT_CPU_FREQ_16 bool "16 MHz" + depends on IDF_ENV_FPGA #ESP32H2-TODO: IDF-3786 config ESP32H2_DEFAULT_CPU_FREQ_32 bool "32 MHz" + depends on IDF_ENV_FPGA #ESP32H2-TODO: IDF-3786 config ESP32H2_DEFAULT_CPU_FREQ_64 bool "64 MHz" + depends on IDF_ENV_FPGA #ESP32H2-TODO: IDF-3786 config ESP32H2_DEFAULT_CPU_FREQ_96 bool "96 MHz" depends on !IDF_ENV_FPGA diff --git a/components/soc/esp32h2/include/soc/soc.h b/components/soc/esp32h2/include/soc/soc.h index bca83126d5..242c6eeab4 100644 --- a/components/soc/esp32h2/include/soc/soc.h +++ b/components/soc/esp32h2/include/soc/soc.h @@ -228,7 +228,7 @@ #if CONFIG_IDF_ENV_FPGA #define APB_CLK_FREQ ( 32*1000000 ) #else -#define APB_CLK_FREQ ( 96*1000000 ) +#define APB_CLK_FREQ ( 48*1000000 ) //ESP32H2-TODO: IDF-3786 #endif #define REF_CLK_FREQ ( 1000000 ) #define RTC_CLK_FREQ (17.5*1000000) From 07d7b4344f4a909c449881340741020481a50e0d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Aug 2021 14:01:53 +0200 Subject: [PATCH 067/310] docs: JTAG debugging updates for C3, S3 - give concrete JTAG pin names for S3 - describe efuses which are related to JTAG debugging (S3, C3) --- .../jtag-debugging/configure-other-jtag.rst | 13 +++++++++++++ docs/en/api-guides/jtag-debugging/esp32c3.inc | 3 +++ docs/en/api-guides/jtag-debugging/esp32s3.inc | 11 +++++++---- docs/en/api-guides/jtag-debugging/index.rst | 6 ++---- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst b/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst index cd4a03ae1f..0d28f2b4fb 100644 --- a/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst +++ b/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst @@ -5,6 +5,19 @@ Configure Other JTAG Interface Refer to section :ref:`jtag-debugging-selecting-jtag-adapter` for guidance what JTAG interface to select, so it is able to operate with OpenOCD and {IDF_TARGET_NAME}. Then follow three configuration steps below to get it working. +.. only:: SOC_USB_SERIAL_JTAG_SUPPORTED + + Configure eFuses + ^^^^^^^^^^^^^^^^ + + By default, {IDF_TARGET_NAME} JTAG interface is connected to the :doc:`built-in USB_SERIAL_JTAG peripheral `. To use an external JTAG adapter instead, you need to switch the JTAG interface to the GPIO pins. This can be done by burning eFuses using ``espefuse.py`` tool. + + Burning eFuses is an irreversible operation, so consider both options below before starting the process. + + - Burning ``DIS_USB_JTAG`` eFuse will permanently disable the connection between USB_SERIAL_JTAG and the JTAG port of the CPU. JTAG interface can then be connected to |jtag-gpio-list|. Note that USB CDC functionality of USB_SERIAL_JTAG will still be useable, i.e. flashing and monitoring over USB CDC will still work. + + - Burning ``JTAG_SEL_ENABLE`` eFuse will enable selection of JTAG interface by a strapping pin, |jtag-sel-gpio|. If the strapping pin is low when {IDF_TARGET_NAME} is reset, JTAG interface will use |jtag-gpio-list|. If the strapping pin is high, USB_SERIAL_JTAG will be used as the JTAG interface. + Configure Hardware ^^^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-guides/jtag-debugging/esp32c3.inc b/docs/en/api-guides/jtag-debugging/esp32c3.inc index 14373a45a5..4c065b6a57 100644 --- a/docs/en/api-guides/jtag-debugging/esp32c3.inc +++ b/docs/en/api-guides/jtag-debugging/esp32c3.inc @@ -125,6 +125,9 @@ * - MTMS / GPIO4 - TMS +.. |jtag-sel-gpio| replace:: GPIO10 +.. |jtag-gpio-list| replace:: GPIO4-GPIO7 + --- .. run-openocd-d3 diff --git a/docs/en/api-guides/jtag-debugging/esp32s3.inc b/docs/en/api-guides/jtag-debugging/esp32s3.inc index d83f3bd074..cd274ca066 100644 --- a/docs/en/api-guides/jtag-debugging/esp32s3.inc +++ b/docs/en/api-guides/jtag-debugging/esp32s3.inc @@ -111,15 +111,18 @@ * - ESP32-S3 Pin - JTAG Signal - * - MTDO + * - MTDO / GPIO40 - TDO - * - MTDI + * - MTDI / GPIO41 - TDI - * - MTCK + * - MTCK / GPIO39 - TCK - * - MTMS + * - MTMS / GPIO42 - TMS +.. |jtag-sel-gpio| replace:: GPIO3 +.. |jtag-gpio-list| replace:: GPIO39-GPIO42 + --- .. run-openocd-d3 diff --git a/docs/en/api-guides/jtag-debugging/index.rst b/docs/en/api-guides/jtag-debugging/index.rst index 93d58549dd..a889499007 100644 --- a/docs/en/api-guides/jtag-debugging/index.rst +++ b/docs/en/api-guides/jtag-debugging/index.rst @@ -64,7 +64,7 @@ The key software and hardware components that perform debugging of {IDF_TARGET_N Likewise, the "Application Loading and Monitoring" label indicates the key software and hardware components that allow an application to be compiled, built, and flashed to {IDF_TARGET_NAME}, as well as to provide means to monitor diagnostic messages from {IDF_TARGET_NAME}. -"Debugging With JTAG" and "Application Loading and Monitoring" is integrated under the `Eclipse `_ IDE in order to provide a quick and easy transition between writing/compiling/loading/debugging code. The Eclipse IDE (and the integrated debugging software) is available for Windows, Linux and macOS platforms. +"Debugging With JTAG" and "Application Loading and Monitoring" is integrated under the `Eclipse `_ IDE in order to provide a quick and easy transition between writing/compiling/loading/debugging code. The Eclipse IDE (and the integrated debugging software) is available for Windows, Linux and macOS platforms. Depending on user preferences, both the debugger and ``idf.py build`` can also be used directly from terminal/command line, instead of Eclipse. .. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED @@ -78,9 +78,7 @@ Likewise, the "Application Loading and Monitoring" label indicates the key softw .. note:: - Debugging through the USB interface implemented in {IDF_TARGET_NAME} requires to have a chip with revision 3 or newer. Please use other debugging options (e.g. with ESP-Prog) for chip revision 1 and 2. The easiest way to determine the chip revision is to look for the `Chip is ESP32-C3 (revision 3)` message near the end of a successful chip flashing done by `idf.py flash`. - -Depending on user preferences, both `debugger` and `idf.py build` can be operated directly from terminal/command line, instead from Eclipse. + Debugging through the USB interface implemented in {IDF_TARGET_NAME} requires to have a chip with revision 3 or newer. Please use other debugging options (e.g. with ESP-Prog) for chip revision 1 and 2. The easiest way to determine the chip revision is to look for the ``Chip is ESP32-C3 (revision 3)`` message near the end of a successful chip flashing done by ``idf.py flash``. .. _jtag-debugging-selecting-jtag-adapter: From 489033d8e3ddc1744c23fd649d418fa918d41120 Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Fri, 27 Aug 2021 21:23:33 +0800 Subject: [PATCH 068/310] openthread: enable ping sender module --- .../openthread-core-esp32x-ftd-config.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 254672aa88..07a6bdc754 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -330,6 +330,16 @@ */ #define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1 +/** + * @def OPENTHREAD_CONFIG_PING_SENDER_ENABLE + * + * Define to 1 to enable ping sender module. + * + * Ping sender module implements sending ICMPv6 Echo Request messages and processing ICMPv6 Echo Reply messages. + * + */ +#define OPENTHREAD_CONFIG_PING_SENDER_ENABLE 1 + /** * @def OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN * From 13360ab126dbe8be01863d6a93e8202160682f03 Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Sun, 29 Aug 2021 21:02:33 +0800 Subject: [PATCH 069/310] fix defines in doc --- .../freertos/include/freertos/event_groups.h | 28 +++++++++---------- .../include/freertos/message_buffer.h | 2 +- components/freertos/include/freertos/queue.h | 4 +-- components/freertos/include/freertos/semphr.h | 4 +-- .../freertos/include/freertos/stream_buffer.h | 2 +- components/freertos/include/freertos/task.h | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/components/freertos/include/freertos/event_groups.h b/components/freertos/include/freertos/event_groups.h index c0afb0c552..8d7f6f8039 100644 --- a/components/freertos/include/freertos/event_groups.h +++ b/components/freertos/include/freertos/event_groups.h @@ -268,8 +268,8 @@ typedef TickType_t EventBits_t; * * Example usage: * @code{c} - * \#define BIT_0 ( 1 << 0 ) - * \#define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * * void aFunction( EventGroupHandle_t xEventGroup ) * { @@ -336,8 +336,8 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, * * Example usage: * @code{c} - * \#define BIT_0 ( 1 << 0 ) - * \#define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * * void aFunction( EventGroupHandle_t xEventGroup ) * { @@ -409,8 +409,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, * * Example usage: * @code{c} - * \#define BIT_0 ( 1 << 0 ) - * \#define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * * // An event group which it is assumed has already been created by a call to * // xEventGroupCreate(). @@ -475,8 +475,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, * * Example usage: * @code{c} - * \#define BIT_0 ( 1 << 0 ) - * \#define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * * void aFunction( EventGroupHandle_t xEventGroup ) * { @@ -561,8 +561,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, * * Example usage: * @code{c} - * \#define BIT_0 ( 1 << 0 ) - * \#define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * * // An event group which it is assumed has already been created by a call to * // xEventGroupCreate(). @@ -656,11 +656,11 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, * Example usage: * @code{c} * // Bits used by the three tasks. - * \#define TASK_0_BIT ( 1 << 0 ) - * \#define TASK_1_BIT ( 1 << 1 ) - * \#define TASK_2_BIT ( 1 << 2 ) + * #define TASK_0_BIT ( 1 << 0 ) + * #define TASK_1_BIT ( 1 << 1 ) + * #define TASK_2_BIT ( 1 << 2 ) * - * \#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT ) + * #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT ) * * // Use an event group to synchronise three tasks. It is assumed this event * // group has already been created elsewhere. diff --git a/components/freertos/include/freertos/message_buffer.h b/components/freertos/include/freertos/message_buffer.h index 9a3a7978fc..9fe58f2765 100644 --- a/components/freertos/include/freertos/message_buffer.h +++ b/components/freertos/include/freertos/message_buffer.h @@ -185,7 +185,7 @@ typedef void * MessageBufferHandle_t; * * // Used to dimension the array used to hold the messages. The available space * // will actually be one less than this, so 999. - * \#define STORAGE_SIZE_BYTES 1000 + * #define STORAGE_SIZE_BYTES 1000 * * // Defines the memory that will actually hold the messages within the message * // buffer. diff --git a/components/freertos/include/freertos/queue.h b/components/freertos/include/freertos/queue.h index 5938527539..c03b1f8e69 100644 --- a/components/freertos/include/freertos/queue.h +++ b/components/freertos/include/freertos/queue.h @@ -187,8 +187,8 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * char ucData[ 20 ]; * }; * - * \#define QUEUE_LENGTH 10 - * \#define ITEM_SIZE sizeof( uint32_t ) + * #define QUEUE_LENGTH 10 + * #define ITEM_SIZE sizeof( uint32_t ) * * // xQueueBuffer will hold the queue structure. * StaticQueue_t xQueueBuffer; diff --git a/components/freertos/include/freertos/semphr.h b/components/freertos/include/freertos/semphr.h index 6a1da0ff71..f9cddcfaa5 100644 --- a/components/freertos/include/freertos/semphr.h +++ b/components/freertos/include/freertos/semphr.h @@ -607,8 +607,8 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * \#define LONG_TIME 0xffff - * \#define TICKS_TO_WAIT 10 + * #define LONG_TIME 0xffff + * #define TICKS_TO_WAIT 10 * SemaphoreHandle_t xSemaphore = NULL; * * // Repetitive task. diff --git a/components/freertos/include/freertos/stream_buffer.h b/components/freertos/include/freertos/stream_buffer.h index 0696c7c9b9..753b0cd880 100644 --- a/components/freertos/include/freertos/stream_buffer.h +++ b/components/freertos/include/freertos/stream_buffer.h @@ -193,7 +193,7 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * * // Used to dimension the array used to hold the streams. The available space * // will actually be one less than this, so 999. - * \#define STORAGE_SIZE_BYTES 1000 + * #define STORAGE_SIZE_BYTES 1000 * * // Defines the memory that will actually hold the streams within the stream * // buffer. diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index d443179701..bfd653168d 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -521,7 +521,7 @@ typedef enum * // Dimensions the buffer that the task being created will use as its stack. * // NOTE: This is the number of bytes the stack will hold, not the number of * // words as found in vanilla FreeRTOS. - * \#define STACK_SIZE 200 + * #define STACK_SIZE 200 * * // Structure that will hold the TCB of the task being created. * StaticTask_t xTaskBuffer; From 41c0e441857b139f6d9fcd948fbc55fb4fca1947 Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Mon, 30 Aug 2021 10:10:29 +0800 Subject: [PATCH 070/310] freertos: Upgrade to 10.4.3 - timers (cherry picked from commit c22a4c355603318a16adb3b898943744d9b826a5) --- components/freertos/include/freertos/timers.h | 41 ++++++++++++++++++- components/freertos/timers.c | 35 +++++++++++----- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/components/freertos/include/freertos/timers.h b/components/freertos/include/freertos/timers.h index 53a23c3f19..69512f949e 100644 --- a/components/freertos/include/freertos/timers.h +++ b/components/freertos/include/freertos/timers.h @@ -447,6 +447,10 @@ void vTimerSetTimerID( TimerHandle_t xTimer, BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** + * @cond + * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); + * @endcond + * * xTimerGetTimerDaemonTaskHandle() is only available if * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. * @@ -1254,7 +1258,7 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint * void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ); * * Updates a timer to be either an auto-reload timer, in which case the timer - * automatically resets itself each time it expires, or a one shot timer, in + * automatically resets itself each time it expires, or a one-shot timer, in * which case the timer will only expire once unless it is manually restarted. * * @param xTimer The handle of the timer being updated. @@ -1268,6 +1272,20 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION; +/** + * UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ); + * + * Queries a timer to determine if it is an auto-reload timer, in which case the timer + * automatically resets itself each time it expires, or a one-shot timer, in + * which case the timer will only expire once unless it is manually restarted. + * + * @param xTimer The handle of the timer being queried. + * + * @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise + * pdFALSE is returned. + */ +UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + /** * TickType_t xTimerGetPeriod( TimerHandle_t xTimer ); * @@ -1315,6 +1333,27 @@ BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, /** @endcond */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + + /** + * @cond + * task.h + *
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) 
+ * @endcond + * + * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer Task TCB. This function is required when + * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION + * + * @param ppxTimerTaskTCBBuffer A handle to a statically allocated TCB buffer + * @param ppxTimerTaskStackBuffer A handle to a statically allocated Stack buffer for thie idle task + * @param pulTimerTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer + */ + void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ); + +#endif + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/components/freertos/timers.c b/components/freertos/timers.c index b0f1f265f7..076aaf4b1f 100644 --- a/components/freertos/timers.c +++ b/components/freertos/timers.c @@ -147,16 +147,6 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - - /* If static allocation is supported then the application must provide the - * following callback function - which enables the application to optionally - * provide the memory that will be used by the timer task as the task's stack - * and TCB. */ - extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ); - -#endif - /* * Initialise the infrastructure used by the timer service task if it has not * been initialised already. @@ -474,6 +464,31 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; } /*-----------------------------------------------------------*/ + UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) + { + Timer_t * pxTimer = xTimer; + UBaseType_t uxReturn; + + configASSERT( xTimer ); + taskENTER_CRITICAL( &xTimerMux ); + { + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0 ) + { + /* Not an auto-reload timer. */ + uxReturn = ( UBaseType_t ) pdFALSE; + } + else + { + /* Is an auto-reload timer. */ + uxReturn = ( UBaseType_t ) pdTRUE; + } + } + taskEXIT_CRITICAL( &xTimerMux ); + + return uxReturn; + } +/*-----------------------------------------------------------*/ + TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) { Timer_t * pxTimer = xTimer; From 63280dfec01df0ea25dafd85b428d9dcf6d71645 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Mon, 30 Aug 2021 10:36:24 +0800 Subject: [PATCH 071/310] aes/sha: fixed driver reseting the wrong GDMA channel Driver was using the channel ID from tx when reseting rx. But since rx and tx is not necessarily from the same pair this could lead to the driver reseting the wrong DMA channel. --- .../mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c index ad1ec016b5..30ec888dd7 100644 --- a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c +++ b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c @@ -128,7 +128,7 @@ esp_err_t esp_crypto_shared_gdma_start(const lldesc_t *input, const lldesc_t *ou } /* tx channel is reset by gdma_connect(), also reset rx to ensure a known state */ - gdma_get_channel_id(tx_channel, &rx_ch_id); + gdma_get_channel_id(rx_channel, &rx_ch_id); gdma_ll_rx_reset_channel(&GDMA, rx_ch_id); gdma_start(tx_channel, (intptr_t)input); From dfb0d593ad6fae51f336b8e824d617c1b7f70e6e Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Mon, 23 Aug 2021 11:02:46 +0800 Subject: [PATCH 072/310] ci(sonarqube): update file pattern according to https://docs.sonarqube.org/7.6/project-administration/narrowing-the-focus/ --- sonar-project.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 164c54522c..4dfd721db6 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -7,13 +7,13 @@ sonar.sourceEncoding=UTF-8 # exclude list for sonarqube # Here're some examples: (relative with the idf_path) -# test/** +# test/**/* # test/*/*.c sonar.exclusion=\ components/freertos/*.c,\ components/freertos/include/freertos/*.h,\ - components/wpa_supplicant/src/**,\ - components/wpa_supplicant/include/** + components/wpa_supplicant/src/**/*,\ + components/wpa_supplicant/include/**/* sonar.inclusions=\ **/*.c,**/*.cpp,**/*.h,**/*.hpp,\ From 55a5c444b5525be77474c2a87e0abc94cca9cf8d Mon Sep 17 00:00:00 2001 From: SalimTerryLi Date: Mon, 30 Aug 2021 11:18:34 +0800 Subject: [PATCH 073/310] rtc_io, esp_himem: replace XXX_CHECK with ESP_RETURN_ON_FALSE --- components/driver/rtc_io.c | 50 ++++++++----------- .../esp_hw_support/port/esp32/esp_himem.c | 39 +++++++-------- 2 files changed, 41 insertions(+), 48 deletions(-) diff --git a/components/driver/rtc_io.c b/components/driver/rtc_io.c index db168476b2..84515814a2 100644 --- a/components/driver/rtc_io.c +++ b/components/driver/rtc_io.c @@ -7,6 +7,7 @@ #include #include "esp_log.h" #include "esp_err.h" +#include "esp_check.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/timers.h" @@ -15,13 +16,6 @@ static const char __attribute__((__unused__)) *RTCIO_TAG = "RTCIO"; -#define RTCIO_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(RTCIO_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) - extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. #define RTCIO_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) #define RTCIO_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) @@ -33,7 +27,7 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi ---------------------------------------------------------------*/ esp_err_t rtc_gpio_init(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_FUNC_RTC); RTCIO_EXIT_CRITICAL(); @@ -43,7 +37,7 @@ esp_err_t rtc_gpio_init(gpio_num_t gpio_num) esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); // Select Gpio as Digital Gpio rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_FUNC_DIGITAL); @@ -54,7 +48,7 @@ esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num) esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_level(rtc_io_number_get(gpio_num), level); RTCIO_EXIT_CRITICAL(); @@ -64,15 +58,15 @@ esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level) uint32_t rtc_gpio_get_level(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); return rtcio_hal_get_level(rtc_io_number_get(gpio_num)); } esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Output pad only", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(strength < GPIO_DRIVE_CAP_MAX, "RTCIO drive capability error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); + ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "Output pad only"); + ESP_RETURN_ON_FALSE(strength < GPIO_DRIVE_CAP_MAX, ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO drive capability error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_drive_capability(rtc_io_number_get(gpio_num), strength); RTCIO_EXIT_CRITICAL(); @@ -82,9 +76,9 @@ esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t st esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *strength) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Output pad only", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(strength != NULL, "GPIO drive pointer error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); + ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "Output pad only"); + ESP_RETURN_ON_FALSE(strength != NULL, ESP_ERR_INVALID_ARG, RTCIO_TAG, "GPIO drive pointer error"); *strength = (gpio_drive_cap_t)rtcio_hal_get_drive_capability(rtc_io_number_get(gpio_num)); return ESP_OK; @@ -92,7 +86,7 @@ esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *s esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_direction(rtc_io_number_get(gpio_num), mode); RTCIO_EXIT_CRITICAL(); @@ -102,7 +96,7 @@ esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode) esp_err_t rtc_gpio_set_direction_in_sleep(gpio_num_t gpio_num, rtc_gpio_mode_t mode) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_direction_in_sleep(rtc_io_number_get(gpio_num), mode); RTCIO_EXIT_CRITICAL(); @@ -112,7 +106,7 @@ esp_err_t rtc_gpio_set_direction_in_sleep(gpio_num_t gpio_num, rtc_gpio_mode_t m esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pullup_enable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -122,7 +116,7 @@ esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num) esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pullup_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -132,7 +126,7 @@ esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num) esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pulldown_enable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -142,7 +136,7 @@ esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num) esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pulldown_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -156,7 +150,7 @@ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num) esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_hold_enable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -165,7 +159,7 @@ esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num) esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_hold_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -174,7 +168,7 @@ esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num) esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_isolate(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -206,7 +200,7 @@ esp_err_t rtc_gpio_force_hold_dis_all(void) esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); if (intr_type == GPIO_INTR_POSEDGE || intr_type == GPIO_INTR_NEGEDGE || intr_type == GPIO_INTR_ANYEDGE) { return ESP_ERR_INVALID_ARG; // Dont support this mode. } @@ -218,7 +212,7 @@ esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_wakeup_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); diff --git a/components/esp_hw_support/port/esp32/esp_himem.c b/components/esp_hw_support/port/esp32/esp_himem.c index 12862b8037..4acaf90e7c 100644 --- a/components/esp_hw_support/port/esp32/esp_himem.c +++ b/components/esp_hw_support/port/esp32/esp_himem.c @@ -12,6 +12,7 @@ #include "esp32/himem.h" #include "soc/soc.h" #include "esp_log.h" +#include "esp_check.h" /* So, why does the API look this way and is so inflexible to not allow any maps beyond the full 32K chunks? Most of @@ -56,8 +57,6 @@ peripheral. This needs support for SPI1 to be in the SPI driver, however. #define TAG "esp_himem" -#define HIMEM_CHECK(cond, str, err) if (cond) do {ESP_LOGE(TAG, "%s: %s", __FUNCTION__, str); return err; } while(0) - // Metadata for a block of physical RAM typedef struct { unsigned int is_alloced: 1; @@ -134,10 +133,10 @@ void __attribute__((constructor)) esp_himem_init(void) if (SPIRAM_BANKSWITCH_RESERVE == 0) return; int maxram=esp_spiram_get_size(); //catch double init - HIMEM_CHECK(s_ram_descriptor != NULL, "already initialized", ); //Looks weird; last arg is empty so it expands to 'return ;' - HIMEM_CHECK(s_range_descriptor != NULL, "already initialized", ); + ESP_RETURN_ON_FALSE(s_ram_descriptor != NULL, , TAG, "already initialized"); //Looks weird; last arg is empty so it expands to 'return ;' + ESP_RETURN_ON_FALSE(s_range_descriptor != NULL, , TAG, "already initialized"); //need to have some reserved banks - HIMEM_CHECK(SPIRAM_BANKSWITCH_RESERVE == 0, "No banks reserved for himem", ); + ESP_RETURN_ON_FALSE(SPIRAM_BANKSWITCH_RESERVE == 0, , TAG, "No banks reserved for himem"); //Start and end of physical reserved memory. Note it starts slightly under //the 4MiB mark as the reserved banks can't have an unity mapping to be used by malloc //anymore; we treat them as himem instead. @@ -219,7 +218,7 @@ esp_err_t esp_himem_free(esp_himem_handle_t handle) //Check if any of the blocks is still mapped; fail if this is the case. for (int i = 0; i < handle->block_ct; i++) { assert(ramblock_idx_valid(handle->block[i])); - HIMEM_CHECK(s_ram_descriptor[handle->block[i]].is_mapped, "block in range still mapped", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(s_ram_descriptor[handle->block[i]].is_mapped, ESP_ERR_INVALID_ARG, TAG, "block in range still mapped"); } //Mark blocks as free portENTER_CRITICAL(&spinlock); @@ -237,8 +236,8 @@ esp_err_t esp_himem_free(esp_himem_handle_t handle) esp_err_t esp_himem_alloc_map_range(size_t size, esp_himem_rangehandle_t *handle_out) { - HIMEM_CHECK(s_ram_descriptor == NULL, "Himem not available!", ESP_ERR_INVALID_STATE); - HIMEM_CHECK(size % CACHE_BLOCKSIZE != 0, "requested size not aligned to blocksize", ESP_ERR_INVALID_SIZE); + ESP_RETURN_ON_FALSE(s_ram_descriptor == NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); + ESP_RETURN_ON_FALSE(size % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_SIZE, TAG, "requested size not aligned to blocksize"); int blocks = size / CACHE_BLOCKSIZE; esp_himem_rangedata_t *r = calloc(sizeof(esp_himem_rangedata_t), 1); if (!r) { @@ -280,7 +279,7 @@ esp_err_t esp_himem_free_map_range(esp_himem_rangehandle_t handle) for (int i = 0; i < handle->block_ct; i++) { assert(rangeblock_idx_valid(handle->block_start + i)); assert(s_range_descriptor[i + handle->block_start].is_alloced == 1); //should be, if handle is valid - HIMEM_CHECK(s_range_descriptor[i + handle->block_start].is_mapped, "memory still mapped to range", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(s_range_descriptor[i + handle->block_start].is_mapped, ESP_ERR_INVALID_ARG, TAG, "memory still mapped to range"); } //We should be good to free this. Mark blocks as free. portENTER_CRITICAL(&spinlock); @@ -298,19 +297,19 @@ esp_err_t esp_himem_map(esp_himem_handle_t handle, esp_himem_rangehandle_t range int ram_block = ram_offset / CACHE_BLOCKSIZE; int range_block = range_offset / CACHE_BLOCKSIZE; int blockcount = len / CACHE_BLOCKSIZE; - HIMEM_CHECK(s_ram_descriptor == NULL, "Himem not available!", ESP_ERR_INVALID_STATE); + ESP_RETURN_ON_FALSE(s_ram_descriptor == NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); //Offsets and length must be block-aligned - HIMEM_CHECK(ram_offset % CACHE_BLOCKSIZE != 0, "ram offset not aligned to blocksize", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(range_offset % CACHE_BLOCKSIZE != 0, "range not aligned to blocksize", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(len % CACHE_BLOCKSIZE != 0, "length not aligned to blocksize", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(ram_offset % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "ram offset not aligned to blocksize"); + ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "range not aligned to blocksize"); + ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "length not aligned to blocksize"); //ram and range should be within allocated range - HIMEM_CHECK(ram_block + blockcount > handle->block_ct, "args not in range of phys ram handle", ESP_ERR_INVALID_SIZE); - HIMEM_CHECK(range_block + blockcount > range->block_ct, "args not in range of range handle", ESP_ERR_INVALID_SIZE); + ESP_RETURN_ON_FALSE(ram_block + blockcount > handle->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of phys ram handle"); + ESP_RETURN_ON_FALSE(range_block + blockcount > range->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of range handle"); //Check if ram blocks aren't already mapped, and if memory range is unmapped for (int i = 0; i < blockcount; i++) { - HIMEM_CHECK(s_ram_descriptor[handle->block[i + ram_block]].is_mapped, "ram already mapped", ESP_ERR_INVALID_STATE); - HIMEM_CHECK(s_range_descriptor[range->block_start + i + range_block].is_mapped, "range already mapped", ESP_ERR_INVALID_STATE); + ESP_RETURN_ON_FALSE(s_ram_descriptor[handle->block[i + ram_block]].is_mapped, ESP_ERR_INVALID_STATE, TAG, "ram already mapped"); + ESP_RETURN_ON_FALSE(s_range_descriptor[range->block_start + i + range_block].is_mapped, ESP_ERR_INVALID_STATE, TAG, "range already mapped"); } //Map and mark as mapped @@ -339,9 +338,9 @@ esp_err_t esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr, size_t len) int range_offset = (uint32_t)ptr - VIRT_HIMEM_RANGE_START; int range_block = (range_offset / CACHE_BLOCKSIZE) - range->block_start; int blockcount = len / CACHE_BLOCKSIZE; - HIMEM_CHECK(range_offset % CACHE_BLOCKSIZE != 0, "range offset not block-aligned", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(len % CACHE_BLOCKSIZE != 0, "map length not block-aligned", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(range_block + blockcount > range->block_ct, "range out of bounds for handle", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "range offset not block-aligned"); + ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "map length not block-aligned"); + ESP_RETURN_ON_FALSE(range_block + blockcount > range->block_ct, ESP_ERR_INVALID_ARG, TAG, "range out of bounds for handle"); portENTER_CRITICAL(&spinlock); for (int i = 0; i < blockcount; i++) { From 065fc953691f83a37326416c1cb448413b0633cc Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Fri, 27 Aug 2021 15:05:01 +0800 Subject: [PATCH 074/310] ci: update pylint to 3.6 --- .gitlab-ci.yml | 1 + .gitlab/ci/static-code-analysis.yml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0607d2b2f9..da2de1785e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,6 +52,7 @@ variables: ESP_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-env:v4.4-1" AFL_FUZZER_TEST_IMAGE: "$CI_DOCKER_REGISTRY/afl-fuzzer-test:v4.4-1-1" CLANG_STATIC_ANALYSIS_IMAGE: "${CI_DOCKER_REGISTRY}/clang-static-analysis:v4.4-1-2" + SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:3" # target test config file, used by assign test job CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/.gitlab/ci/target-test.yml" diff --git a/.gitlab/ci/static-code-analysis.yml b/.gitlab/ci/static-code-analysis.yml index 74a7f67bb8..3239dddc56 100644 --- a/.gitlab/ci/static-code-analysis.yml +++ b/.gitlab/ci/static-code-analysis.yml @@ -30,7 +30,7 @@ check_pylint: - .pre_check_base_template - .rules:patterns:python-files - .before_script_minimal - image: $CI_DOCKER_REGISTRY/sonarqube-scanner:2 + image: $SONARQUBE_SCANNER_IMAGE artifacts: when: always paths: @@ -62,7 +62,7 @@ check_pylint: .sonar_scan_template: stage: build image: - name: $CI_DOCKER_REGISTRY/sonarqube-scanner:2 + name: $SONARQUBE_SCANNER_IMAGE before_script: - source tools/ci/utils.sh - export PYTHONPATH="$CI_PROJECT_DIR/tools:$CI_PROJECT_DIR/tools/ci/python_packages:$PYTHONPATH" From 342d1e5ee49ef3d6f8bd739fc974c7311cb52764 Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Mon, 30 Aug 2021 10:36:35 +0800 Subject: [PATCH 075/310] esp32h2: enable blink example --- examples/get-started/blink/main/Kconfig.projbuild | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/get-started/blink/main/Kconfig.projbuild b/examples/get-started/blink/main/Kconfig.projbuild index 1cf040f481..3b60f9b325 100644 --- a/examples/get-started/blink/main/Kconfig.projbuild +++ b/examples/get-started/blink/main/Kconfig.projbuild @@ -2,10 +2,8 @@ menu "Example Configuration" choice BLINK_LED prompt "Blink LED type" - default BLINK_LED_RMT if IDF_TARGET_ESP32C3 - default BLINK_LED_RMT if IDF_TARGET_ESP32S2 - default BLINK_LED_RMT if IDF_TARGET_ESP32S3 - default BLINK_LED_GPIO + default BLINK_LED_GPIO if IDF_TARGET_ESP32 + default BLINK_LED_RMT help Defines the default peripheral for blink example @@ -30,7 +28,7 @@ menu "Example Configuration" config BLINK_GPIO int "Blink GPIO number" range 0 48 - default 8 if IDF_TARGET_ESP32C3 + default 8 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32H2 default 18 if IDF_TARGET_ESP32S2 default 48 if IDF_TARGET_ESP32S3 default 5 From 874a720286b78e866684129ce18a6c948c8fa7fe Mon Sep 17 00:00:00 2001 From: SalimTerryLi Date: Mon, 23 Aug 2021 14:03:23 +0800 Subject: [PATCH 076/310] soc/ll: workaround compiler bug that generate 8/16 bits inst instead of 32 bits one update all struct headers to be more "standardized": - bit fields are properly wrapped with struct - bitwidth sum should be 32 within same struct, so that it's correctly padded with reserved bits - bit field should be uint32_t - typedef volatile struct xxx{} yyy;: xxx must exists. refer: https://github.com/espressif/esp-idf/pull/3199 added helper macros to force peripheral registers being accessed in 32 bitwidth added a check script into ci --- .gitlab/ci/pre_check.yml | 9 + components/hal/esp32/include/hal/adc_ll.h | 32 +- components/hal/esp32/include/hal/dac_ll.h | 13 +- components/hal/esp32/include/hal/emac_ll.h | 9 +- components/hal/esp32/include/hal/gpio_ll.h | 16 +- components/hal/esp32/include/hal/i2c_ll.h | 5 +- components/hal/esp32/include/hal/i2s_ll.h | 8 +- components/hal/esp32/include/hal/ledc_ll.h | 1 + components/hal/esp32/include/hal/mcpwm_ll.h | 47 +- components/hal/esp32/include/hal/mwdt_ll.h | 4 +- components/hal/esp32/include/hal/rmt_ll.h | 23 +- components/hal/esp32/include/hal/rtc_io_ll.h | 1 + components/hal/esp32/include/hal/rwdt_ll.h | 1 + .../hal/esp32/include/hal/sigmadelta_ll.h | 6 +- .../hal/esp32/include/hal/spi_flash_ll.h | 4 +- components/hal/esp32/include/hal/spi_ll.h | 7 +- components/hal/esp32/include/hal/timer_ll.h | 6 +- .../hal/esp32/include/hal/touch_sensor_ll.h | 25 +- components/hal/esp32/include/hal/twai_ll.h | 21 +- components/hal/esp32/include/hal/uart_ll.h | 27 +- components/hal/esp32c3/include/hal/adc_ll.h | 15 +- components/hal/esp32c3/include/hal/gpio_ll.h | 1 + .../hal/esp32c3/include/hal/gpspi_flash_ll.h | 4 +- components/hal/esp32c3/include/hal/i2c_ll.h | 9 +- components/hal/esp32c3/include/hal/i2s_ll.h | 8 +- components/hal/esp32c3/include/hal/ledc_ll.h | 1 + components/hal/esp32c3/include/hal/mwdt_ll.h | 1 + components/hal/esp32c3/include/hal/rmt_ll.h | 21 +- components/hal/esp32c3/include/hal/rwdt_ll.h | 4 +- .../hal/esp32c3/include/hal/sigmadelta_ll.h | 6 +- components/hal/esp32c3/include/hal/spi_ll.h | 7 +- .../hal/esp32c3/include/hal/spimem_flash_ll.h | 11 +- components/hal/esp32c3/include/hal/timer_ll.h | 6 +- components/hal/esp32c3/include/hal/twai_ll.h | 19 +- components/hal/esp32c3/include/hal/uart_ll.h | 27 +- components/hal/esp32h2/include/hal/adc_ll.h | 15 +- components/hal/esp32h2/include/hal/gpio_ll.h | 1 + .../hal/esp32h2/include/hal/gpspi_flash_ll.h | 4 +- components/hal/esp32h2/include/hal/i2c_ll.h | 9 +- components/hal/esp32h2/include/hal/i2s_ll.h | 8 +- components/hal/esp32h2/include/hal/ledc_ll.h | 1 + components/hal/esp32h2/include/hal/mwdt_ll.h | 1 + components/hal/esp32h2/include/hal/rmt_ll.h | 21 +- components/hal/esp32h2/include/hal/rwdt_ll.h | 4 +- .../hal/esp32h2/include/hal/sigmadelta_ll.h | 6 +- components/hal/esp32h2/include/hal/spi_ll.h | 7 +- .../hal/esp32h2/include/hal/spimem_flash_ll.h | 11 +- components/hal/esp32h2/include/hal/timer_ll.h | 6 +- components/hal/esp32h2/include/hal/twai_ll.h | 20 +- components/hal/esp32h2/include/hal/uart_ll.h | 27 +- .../esp32h2/include/hal/usb_serial_jtag_ll.h | 6 +- components/hal/esp32s2/include/hal/adc_ll.h | 30 +- components/hal/esp32s2/include/hal/dac_ll.h | 13 +- .../hal/esp32s2/include/hal/dedic_gpio_ll.h | 5 +- components/hal/esp32s2/include/hal/gpio_ll.h | 1 + .../hal/esp32s2/include/hal/gpspi_flash_ll.h | 4 +- components/hal/esp32s2/include/hal/i2c_ll.h | 1 + components/hal/esp32s2/include/hal/i2s_ll.h | 6 +- components/hal/esp32s2/include/hal/ledc_ll.h | 1 + components/hal/esp32s2/include/hal/mwdt_ll.h | 1 + components/hal/esp32s2/include/hal/rmt_ll.h | 23 +- .../hal/esp32s2/include/hal/rtc_io_ll.h | 2 + components/hal/esp32s2/include/hal/rwdt_ll.h | 4 +- .../hal/esp32s2/include/hal/sigmadelta_ll.h | 6 +- components/hal/esp32s2/include/hal/spi_ll.h | 9 +- .../hal/esp32s2/include/hal/spimem_flash_ll.h | 9 +- components/hal/esp32s2/include/hal/timer_ll.h | 6 +- .../hal/esp32s2/include/hal/touch_sensor_ll.h | 26 +- components/hal/esp32s2/include/hal/twai_ll.h | 19 +- components/hal/esp32s2/include/hal/uart_ll.h | 23 +- components/hal/esp32s3/include/hal/adc_ll.h | 26 +- components/hal/esp32s3/include/hal/gpio_ll.h | 1 + .../hal/esp32s3/include/hal/gpspi_flash_ll.h | 4 +- components/hal/esp32s3/include/hal/i2c_ll.h | 9 +- components/hal/esp32s3/include/hal/i2s_ll.h | 8 +- components/hal/esp32s3/include/hal/lcd_ll.h | 7 +- components/hal/esp32s3/include/hal/ledc_ll.h | 1 + components/hal/esp32s3/include/hal/mcpwm_ll.h | 36 +- components/hal/esp32s3/include/hal/mwdt_ll.h | 4 +- components/hal/esp32s3/include/hal/rmt_ll.h | 21 +- .../hal/esp32s3/include/hal/rtc_io_ll.h | 1 + components/hal/esp32s3/include/hal/rwdt_ll.h | 3 +- .../hal/esp32s3/include/hal/sigmadelta_ll.h | 6 +- components/hal/esp32s3/include/hal/spi_ll.h | 7 +- .../hal/esp32s3/include/hal/spimem_flash_ll.h | 7 +- components/hal/esp32s3/include/hal/timer_ll.h | 6 +- .../hal/esp32s3/include/hal/touch_sensor_ll.h | 18 +- components/hal/esp32s3/include/hal/twai_ll.h | 19 +- components/hal/esp32s3/include/hal/uart_ll.h | 28 +- .../hal/platform_port/include/hal/misc.h | 20 + .../soc/esp32/include/soc/emac_dma_struct.h | 2 +- .../soc/esp32/include/soc/emac_ext_struct.h | 2 +- .../soc/esp32/include/soc/emac_mac_struct.h | 2 +- components/soc/esp32/include/soc/i2c_struct.h | 4 +- .../soc/esp32/include/soc/pcnt_struct.h | 2 +- components/soc/esp32/include/soc/rmt_struct.h | 6 +- .../soc/esp32/include/soc/sdmmc_struct.h | 37 +- .../esp32/include/soc/timer_group_struct.h | 2 +- .../soc/esp32/include/soc/twai_struct.h | 87 +- .../soc/esp32/include/soc/uart_struct.h | 4 +- .../soc/esp32/include/soc/uhci_struct.h | 2 +- .../soc/esp32c3/include/soc/apb_ctrl_struct.h | 2 +- .../esp32c3/include/soc/apb_saradc_struct.h | 2 +- .../soc/esp32c3/include/soc/efuse_struct.h | 2 +- .../soc/esp32c3/include/soc/gdma_struct.h | 2 +- .../soc/esp32c3/include/soc/gpio_sd_struct.h | 2 +- .../soc/esp32c3/include/soc/gpio_struct.h | 2 +- .../soc/esp32c3/include/soc/i2c_struct.h | 2 +- .../soc/esp32c3/include/soc/i2s_struct.h | 2 +- .../soc/esp32c3/include/soc/ledc_struct.h | 2 +- .../soc/esp32c3/include/soc/rmt_struct.h | 8 +- .../soc/esp32c3/include/soc/rtc_cntl_struct.h | 2 +- .../soc/esp32c3/include/soc/rtc_i2c_struct.h | 2 +- .../esp32c3/include/soc/sensitive_struct.h | 5 +- .../soc/esp32c3/include/soc/spi_mem_struct.h | 2 +- .../soc/esp32c3/include/soc/spi_struct.h | 2 +- .../soc/esp32c3/include/soc/syscon_struct.h | 2 +- .../soc/esp32c3/include/soc/system_struct.h | 2 +- .../soc/esp32c3/include/soc/systimer_struct.h | 10 + .../soc/esp32c3/include/soc/twai_struct.h | 88 +- .../soc/esp32c3/include/soc/uart_struct.h | 2 +- .../soc/esp32c3/include/soc/uhci_struct.h | 2 +- .../include/soc/usb_serial_jtag_struct.h | 2 +- .../soc/esp32h2/include/soc/apb_ctrl_struct.h | 2 +- .../esp32h2/include/soc/apb_saradc_struct.h | 2 +- .../soc/esp32h2/include/soc/efuse_struct.h | 2 +- .../soc/esp32h2/include/soc/gdma_struct.h | 2 +- .../soc/esp32h2/include/soc/gpio_sd_struct.h | 2 +- .../soc/esp32h2/include/soc/gpio_struct.h | 2 +- .../soc/esp32h2/include/soc/i2c_struct.h | 2 +- .../soc/esp32h2/include/soc/i2s_struct.h | 2 +- .../soc/esp32h2/include/soc/ledc_struct.h | 2 +- .../soc/esp32h2/include/soc/rmt_struct.h | 8 +- .../soc/esp32h2/include/soc/rtc_cntl_struct.h | 2 +- .../soc/esp32h2/include/soc/rtc_i2c_struct.h | 2 +- .../esp32h2/include/soc/sensitive_struct.h | 2 +- .../soc/esp32h2/include/soc/spi_mem_struct.h | 2 +- .../soc/esp32h2/include/soc/spi_struct.h | 2 +- .../soc/esp32h2/include/soc/syscon_struct.h | 2 +- .../soc/esp32h2/include/soc/system_struct.h | 2 +- .../soc/esp32h2/include/soc/systimer_struct.h | 10 + .../soc/esp32h2/include/soc/twai_struct.h | 88 +- .../soc/esp32h2/include/soc/uart_struct.h | 2 +- .../soc/esp32h2/include/soc/uhci_struct.h | 2 +- .../include/soc/usb_serial_jtag_struct.h | 2 +- .../soc/esp32s2/include/soc/apb_ctrl_struct.h | 2 +- .../esp32s2/include/soc/apb_saradc_struct.h | 2 +- .../soc/esp32s2/include/soc/cp_dma_struct.h | 6 + .../esp32s2/include/soc/dedic_gpio_struct.h | 12 + .../soc/esp32s2/include/soc/efuse_struct.h | 2 +- .../soc/esp32s2/include/soc/gpio_sd_struct.h | 2 +- .../soc/esp32s2/include/soc/gpio_struct.h | 2 +- .../soc/esp32s2/include/soc/i2c_struct.h | 2 +- .../soc/esp32s2/include/soc/i2s_struct.h | 2 +- .../soc/esp32s2/include/soc/ledc_struct.h | 2 +- .../soc/esp32s2/include/soc/rmt_struct.h | 8 +- .../soc/esp32s2/include/soc/rtc_cntl_struct.h | 2 +- .../soc/esp32s2/include/soc/rtc_i2c_struct.h | 2 +- .../soc/esp32s2/include/soc/rtc_io_struct.h | 2 +- .../soc/esp32s2/include/soc/sens_struct.h | 2 +- .../soc/esp32s2/include/soc/syscon_struct.h | 2 +- .../soc/esp32s2/include/soc/systimer_struct.h | 4 + .../soc/esp32s2/include/soc/twai_struct.h | 86 +- .../soc/esp32s2/include/soc/uart_struct.h | 2 +- .../soc/esp32s2/include/soc/uhci_struct.h | 2 +- .../soc/esp32s2/include/soc/usb_wrap_struct.h | 1 + .../soc/esp32s2/include/soc/usbh_struct.h | 2 +- .../soc/esp32s3/include/soc/apb_ctrl_struct.h | 2 +- .../esp32s3/include/soc/apb_saradc_struct.h | 2 +- .../esp32s3/include/soc/assist_debug_struct.h | 2 +- .../soc/esp32s3/include/soc/efuse_struct.h | 2 +- .../soc/esp32s3/include/soc/extmem_struct.h | 2 +- .../soc/esp32s3/include/soc/gdma_struct.h | 2 +- .../soc/esp32s3/include/soc/gpio_sd_struct.h | 2 +- .../soc/esp32s3/include/soc/gpio_struct.h | 2 +- .../soc/esp32s3/include/soc/hinf_struct.h | 2 +- .../soc/esp32s3/include/soc/host_struct.h | 2 +- .../soc/esp32s3/include/soc/i2s_struct.h | 2 +- .../include/soc/interrupt_core0_struct.h | 2 +- .../include/soc/interrupt_core1_struct.h | 2 +- .../esp32s3/include/soc/interrupt_struct.h | 2 +- .../soc/esp32s3/include/soc/ledc_struct.h | 2 +- .../esp32s3/include/soc/peri_backup_struct.h | 2 +- .../soc/esp32s3/include/soc/rmt_struct.h | 4 +- .../soc/esp32s3/include/soc/rtc_cntl_struct.h | 2 +- .../soc/esp32s3/include/soc/rtc_io_struct.h | 2 +- .../soc/esp32s3/include/soc/sdmmc_struct.h | 38 +- .../soc/esp32s3/include/soc/sens_struct.h | 2 +- .../esp32s3/include/soc/sensitive_struct.h | 2 +- components/soc/esp32s3/include/soc/slc_reg.h | 1912 ----------------- .../soc/esp32s3/include/soc/slc_struct.h | 592 ----- .../soc/esp32s3/include/soc/spi_mem_struct.h | 2 +- .../soc/esp32s3/include/soc/spi_struct.h | 2 +- .../soc/esp32s3/include/soc/syscon_struct.h | 2 +- .../soc/esp32s3/include/soc/system_struct.h | 2 +- .../soc/esp32s3/include/soc/systimer_struct.h | 11 + .../soc/esp32s3/include/soc/twai_struct.h | 90 +- .../soc/esp32s3/include/soc/uhci_struct.h | 2 +- .../include/soc/usb_serial_jtag_struct.h | 2 +- .../soc/esp32s3/include/soc/usb_wrap_struct.h | 1 + .../soc/esp32s3/include/soc/usbh_struct.h | 2 +- .../include/soc/world_controller_struct.h | 2 +- .../soc/include/soc/sdio_slave_periph.h | 3 + tools/ci/check_soc_struct_headers.py | 420 ++++ tools/ci/executable-list.txt | 1 + 205 files changed, 1439 insertions(+), 3252 deletions(-) delete mode 100644 components/soc/esp32s3/include/soc/slc_reg.h delete mode 100644 components/soc/esp32s3/include/soc/slc_struct.h create mode 100755 tools/ci/check_soc_struct_headers.py diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index 3ddccfadca..676ef0a44b 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -113,6 +113,15 @@ check_public_headers: script: - python tools/ci/check_public_headers.py --jobs 4 --prefix xtensa-esp32-elf- +check_soc_struct_headers: + extends: + - .pre_check_base_template + - .rules:build + tags: + - build + script: + - find ${IDF_PATH}/components/soc/*/include/soc/ -name "*_struct.h" -print0 | xargs -0 -n1 ./tools/ci/check_soc_struct_headers.py + check_esp_err_to_name: extends: - .pre_check_base_template diff --git a/components/hal/esp32/include/hal/adc_ll.h b/components/hal/esp32/include/hal/adc_ll.h index 587d7e7a34..1b5969ac43 100644 --- a/components/hal/esp32/include/hal/adc_ll.h +++ b/components/hal/esp32/include/hal/adc_ll.h @@ -3,7 +3,11 @@ #include "soc/adc_periph.h" #include "hal/adc_types.h" #include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" +#include "soc/syscon_struct.h" +#include "soc/rtc_cntl_struct.h" #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -52,11 +56,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - SYSCON.saradc_fsm.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, rstb_wait, rst_wait); // Internal FSM start wait time - SYSCON.saradc_fsm.start_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, start_wait, start_wait); // Internal FSM standby wait time - SYSCON.saradc_fsm.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, standby_wait, standby_wait); } /** @@ -67,7 +71,7 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa */ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) { - SYSCON.saradc_fsm.sample_cycle = sample_cycle; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, sample_cycle, sample_cycle); } /** @@ -78,7 +82,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock divided from APB clk, e.g. 80 / 2 = 40Mhz, */ - SYSCON.saradc_ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_ctrl, sar_clk_div, div); } /** @@ -99,7 +103,7 @@ static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - SYSCON.saradc_ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_ctrl2, max_meas_num, meas_num); } /** @@ -320,7 +324,7 @@ static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n) static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel) { if (adc_n == ADC_NUM_1) { - while (SENS.sar_slave_addr1.meas_status != 0); + while (HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_slave_addr1, meas_status) != 0) {} SENS.sar_meas_start1.meas1_start_sar = 0; SENS.sar_meas_start1.meas1_start_sar = 1; } else { // adc_n == ADC_NUM_2 @@ -359,9 +363,9 @@ static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n) { int ret_val = 0; if (adc_n == ADC_NUM_1) { - ret_val = SENS.sar_meas_start1.meas1_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas_start1, meas1_data_sar); } else { // adc_n == ADC_NUM_2 - ret_val = SENS.sar_meas_start2.meas2_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas_start2, meas2_data_sar); } return ret_val; } @@ -444,9 +448,9 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void) static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) { if (adc_n == ADC_NUM_1) { - SENS.sar_read_ctrl.sar1_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl, sar1_clk_div, div); } else { // adc_n == ADC_NUM_2 - SENS.sar_read_ctrl2.sar2_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl2, sar2_clk_div, div); } } @@ -563,9 +567,9 @@ static inline void adc_ll_amp_disable(void) SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0; SENS.sar_meas_ctrl.amp_short_ref_fsm = 0; SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0; - SENS.sar_meas_wait1.sar_amp_wait1 = 1; - SENS.sar_meas_wait1.sar_amp_wait2 = 1; - SENS.sar_meas_wait2.sar_amp_wait3 = 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_meas_wait1, sar_amp_wait1, 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_meas_wait1, sar_amp_wait2, 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_meas_wait2, sar_amp_wait3, 1); } /*--------------------------------------------------------------- diff --git a/components/hal/esp32/include/hal/dac_ll.h b/components/hal/esp32/include/hal/dac_ll.h index 5ea4da8978..ec1c20c4fb 100644 --- a/components/hal/esp32/include/hal/dac_ll.h +++ b/components/hal/esp32/include/hal/dac_ll.h @@ -21,7 +21,10 @@ #pragma once #include +#include "hal/misc.h" #include "soc/dac_periph.h" +#include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" #include "hal/dac_types.h" #ifdef __cplusplus @@ -62,10 +65,10 @@ static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t val { if (channel == DAC_CHANNEL_1) { SENS.sar_dac_ctrl2.dac_cw_en1 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } else if (channel == DAC_CHANNEL_2) { SENS.sar_dac_ctrl2.dac_cw_en2 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } } @@ -124,7 +127,7 @@ static inline void dac_ll_cw_set_channel(dac_channel_t channel, bool enable) static inline void dac_ll_cw_set_freq(uint32_t freq) { uint32_t sw_freq = freq * 0xFFFF / RTC_FAST_CLK_FREQ_APPROX; - SENS.sar_dac_ctrl1.sw_fstep = (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl1, sw_fstep, (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq); } /** @@ -171,12 +174,12 @@ static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset) if (SENS.sar_dac_ctrl2.dac_inv1 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc1 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc1, offset ? offset : (-128 - offset)); } else if (channel == DAC_CHANNEL_2) { if (SENS.sar_dac_ctrl2.dac_inv2 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc2 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc2, offset ? offset : (-128 - offset)); } } diff --git a/components/hal/esp32/include/hal/emac_ll.h b/components/hal/esp32/include/hal/emac_ll.h index 36477e36f5..dff803b5a9 100644 --- a/components/hal/esp32/include/hal/emac_ll.h +++ b/components/hal/esp32/include/hal/emac_ll.h @@ -23,6 +23,7 @@ #pragma once #include +#include "hal/misc.h" #include "hal/eth_types.h" #include "soc/emac_dma_struct.h" #include "soc/emac_mac_struct.h" @@ -310,7 +311,7 @@ static inline void emac_ll_promiscuous_mode_enable(emac_mac_dev_t *mac_regs, boo /* gmacfc */ static inline void emac_ll_set_pause_time(emac_mac_dev_t *mac_regs, uint32_t time) { - mac_regs->gmacfc.pause_time = time; + HAL_FORCE_MODIFY_U32_REG_FIELD(mac_regs->gmacfc, pause_time, time); } static inline void emac_ll_zero_quanta_pause_enable(emac_mac_dev_t *mac_regs, bool enable) @@ -346,18 +347,18 @@ static inline void emac_ll_clear(emac_mac_dev_t *mac_regs) /* emacmiidata */ static inline void emac_ll_set_phy_data(emac_mac_dev_t *mac_regs, uint32_t data) { - mac_regs->emacmiidata.mii_data = data; + HAL_FORCE_MODIFY_U32_REG_FIELD(mac_regs->emacmiidata, mii_data, data); } static inline uint32_t emac_ll_get_phy_data(emac_mac_dev_t *mac_regs) { - return mac_regs->emacmiidata.mii_data; + return HAL_FORCE_READ_U32_REG_FIELD(mac_regs->emacmiidata, mii_data); } /* emacaddr0 */ static inline void emac_ll_set_addr(emac_mac_dev_t *mac_regs, const uint8_t *addr) { - mac_regs->emacaddr0high.address0_hi = (addr[5] << 8) | addr[4]; + HAL_FORCE_MODIFY_U32_REG_FIELD(mac_regs->emacaddr0high, address0_hi, (addr[5] << 8) | addr[4]); mac_regs->emacaddr0low = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | (addr[0]); } /*************** End of mac regs operation *********************/ diff --git a/components/hal/esp32/include/hal/gpio_ll.h b/components/hal/esp32/include/hal/gpio_ll.h index 8c1acb3a1c..f5ac5909d5 100644 --- a/components/hal/esp32/include/hal/gpio_ll.h +++ b/components/hal/esp32/include/hal/gpio_ll.h @@ -25,9 +25,11 @@ #include #include "soc/soc.h" #include "soc/gpio_periph.h" +#include "soc/gpio_struct.h" #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" #include "hal/gpio_types.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -245,7 +247,7 @@ static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uin */ static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status) { - *status = (core_id == 0) ? hw->pcpu_int1.intr : hw->acpu_int1.intr; + *status = (core_id == 0) ? HAL_FORCE_READ_U32_REG_FIELD(hw->pcpu_int1, intr) : HAL_FORCE_READ_U32_REG_FIELD(hw->pcpu_int1, intr); } /** @@ -267,7 +269,7 @@ static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask) */ static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask) { - hw->status1_w1tc.intr_st = mask; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->status1_w1tc, intr_st, mask); } /** @@ -330,7 +332,7 @@ static inline void gpio_ll_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num) if (gpio_num < 32) { hw->enable_w1tc = (0x1 << gpio_num); } else { - hw->enable1_w1tc.data = (0x1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1tc, data, (0x1 << (gpio_num - 32))); } // Ensure no other output signal is routed via GPIO matrix to this pin @@ -349,7 +351,7 @@ static inline void gpio_ll_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num) if (gpio_num < 32) { hw->enable_w1ts = (0x1 << gpio_num); } else { - hw->enable1_w1ts.data = (0x1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1ts, data, (0x1 << (gpio_num - 32))); } } @@ -432,13 +434,13 @@ static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32 if (gpio_num < 32) { hw->out_w1ts = (1 << gpio_num); } else { - hw->out1_w1ts.data = (1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1ts, data, (1 << (gpio_num - 32))); } } else { if (gpio_num < 32) { hw->out_w1tc = (1 << gpio_num); } else { - hw->out1_w1tc.data = (1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1tc, data, (1 << (gpio_num - 32))); } } } @@ -460,7 +462,7 @@ static inline int gpio_ll_get_level(gpio_dev_t *hw, gpio_num_t gpio_num) if (gpio_num < 32) { return (hw->in >> gpio_num) & 0x1; } else { - return (hw->in1.data >> (gpio_num - 32)) & 0x1; + return (HAL_FORCE_READ_U32_REG_FIELD(hw->in1, data) >> (gpio_num - 32)) & 0x1; } } diff --git a/components/hal/esp32/include/hal/i2c_ll.h b/components/hal/esp32/include/hal/i2c_ll.h index 550c1b76d2..650dbbaa04 100644 --- a/components/hal/esp32/include/hal/i2c_ll.h +++ b/components/hal/esp32/include/hal/i2c_ll.h @@ -15,7 +15,10 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #ifdef __cplusplus @@ -558,7 +561,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->fifo_data.data; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo_data, data); } } diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 0633030925..159446b41d 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -23,7 +23,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus @@ -272,7 +274,7 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) { - hw->clkm_conf.clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; hw->clkm_conf.clkm_div_a = set->a; } @@ -296,7 +298,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) { - hw->clkm_conf.clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; hw->clkm_conf.clkm_div_a = set->a; } @@ -775,7 +777,7 @@ static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_ena) */ static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - hw->pdm_conf.tx_prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->pdm_conf, tx_prescale, prescale); } /** diff --git a/components/hal/esp32/include/hal/ledc_ll.h b/components/hal/esp32/include/hal/ledc_ll.h index f7331872b6..1682c7c410 100644 --- a/components/hal/esp32/include/hal/ledc_ll.h +++ b/components/hal/esp32/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #define LEDC_LL_GET_HW() &LEDC diff --git a/components/hal/esp32/include/hal/mcpwm_ll.h b/components/hal/esp32/include/hal/mcpwm_ll.h index 2fff763661..02b667341c 100644 --- a/components/hal/esp32/include/hal/mcpwm_ll.h +++ b/components/hal/esp32/include/hal/mcpwm_ll.h @@ -23,6 +23,7 @@ #pragma once #include +#include "hal/misc.h" #include "soc/soc_caps.h" #include "soc/mcpwm_struct.h" #include "hal/mcpwm_types.h" @@ -44,17 +45,12 @@ extern "C" { // Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1) static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale) { - // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) - // We take care of the "read-modify-write" procedure by ourselves. - mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; - clkcfg.clk_prescale = pre_scale - 1; - mcpwm->clk_cfg = clkcfg; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, pre_scale - 1); } static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) { - mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; - return clkcfg.clk_prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale) + 1; } static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) @@ -272,25 +268,20 @@ static inline void mcpwm_ll_intr_enable_capture(mcpwm_dev_t *mcpwm, uint32_t cap static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale) { - // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) - // We take care of the "read-modify-write" procedure by ourselves. - mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; - cfg0.timer_prescale = prescale - 1; - mcpwm->timer[timer_id].timer_cfg0 = cfg0; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_prescale, prescale - 1); } static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; - return cfg0.timer_prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_prescale) + 1; } static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] - mcpwm->timer[timer_id].timer_cfg0.timer_period = peak - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1); } else { // in symmetric mode, period = [0,peak-1] + [peak,1] - mcpwm->timer[timer_id].timer_cfg0.timer_period = peak; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak); } } @@ -298,10 +289,10 @@ static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, { // asymmetric mode if (!symmetric) { - return mcpwm->timer[timer_id].timer_cfg0.timer_period + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1; } // symmetric mode - return mcpwm->timer[timer_id].timer_cfg0.timer_period; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period); } static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) @@ -385,7 +376,7 @@ static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int ti static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].timer_status.timer_value; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value); } static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) @@ -428,7 +419,7 @@ static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int time static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) { - mcpwm->timer[timer_id].timer_sync.timer_phase = phase_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_sync, timer_phase, phase_value); } static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) @@ -515,12 +506,12 @@ static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t * static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) { - mcpwm->operator[operator_id].timestamp[compare_id].gen = compare_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operator[operator_id].timestamp[compare_id], gen, compare_value); } static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - return mcpwm->operator[operator_id].timestamp[compare_id].gen; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operator[operator_id].timestamp[compare_id], gen); } static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) @@ -719,22 +710,22 @@ static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) { - mcpwm->operator[operator_id].dt_fed_cfg.dt_fed = fed - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operator[operator_id].dt_fed_cfg, dt_fed, fed - 1); } static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->operator[operator_id].dt_fed_cfg.dt_fed + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operator[operator_id].dt_fed_cfg, dt_fed) + 1; } static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) { - mcpwm->operator[operator_id].dt_red_cfg.dt_red = red - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operator[operator_id].dt_red_cfg, dt_red, red - 1); } static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->operator[operator_id].dt_red_cfg.dt_red + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operator[operator_id].dt_red_cfg, dt_red) + 1; } static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) @@ -1006,12 +997,12 @@ static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) { - mcpwm->cap_chn_cfg[channel].capn_prescale = prescale - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); } static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_chn_cfg[channel].capn_prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale) + 1; } #ifdef __cplusplus diff --git a/components/hal/esp32/include/hal/mwdt_ll.h b/components/hal/esp32/include/hal/mwdt_ll.h index 9a981c6855..267f15ef2c 100644 --- a/components/hal/esp32/include/hal/mwdt_ll.h +++ b/components/hal/esp32/include/hal/mwdt_ll.h @@ -23,7 +23,9 @@ extern "C" { #include #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" @@ -201,7 +203,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t* hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) { - hw->wdt_config1.clk_prescale = prescaler; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config1, clk_prescale, prescaler); } /** diff --git a/components/hal/esp32/include/hal/rmt_ll.h b/components/hal/esp32/include/hal/rmt_ll.h index edd4f27912..dfd8199d5b 100644 --- a/components/hal/esp32/include/hal/rmt_ll.h +++ b/components/hal/esp32/include/hal/rmt_ll.h @@ -15,6 +15,7 @@ #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus @@ -119,23 +120,23 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } @@ -146,12 +147,12 @@ static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, b static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf0.idle_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres, thres); } static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) { - return dev->conf_ch[channel].conf0.idle_thres; + return HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres); } static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) @@ -186,7 +187,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -324,14 +325,14 @@ static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev) static inline void rmt_ll_tx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) { - dev->carrier_duty_ch[channel].high = high_ticks; - dev->carrier_duty_ch[channel].low = low_ticks; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->carrier_duty_ch[channel], high, high_ticks); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->carrier_duty_ch[channel], low, low_ticks); } static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->carrier_duty_ch[channel].high; - *low_ticks = dev->carrier_duty_ch[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], low); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32/include/hal/rtc_io_ll.h b/components/hal/esp32/include/hal/rtc_io_ll.h index 3e5a1af8ff..f96452532e 100644 --- a/components/hal/esp32/include/hal/rtc_io_ll.h +++ b/components/hal/esp32/include/hal/rtc_io_ll.h @@ -22,6 +22,7 @@ #include #include "soc/rtc_io_periph.h" +#include "soc/rtc_io_struct.h" #include "hal/rtc_io_types.h" #include "hal/gpio_types.h" diff --git a/components/hal/esp32/include/hal/rwdt_ll.h b/components/hal/esp32/include/hal/rwdt_ll.h index c1d2d60607..e409eeaa8b 100644 --- a/components/hal/esp32/include/hal/rwdt_ll.h +++ b/components/hal/esp32/include/hal/rwdt_ll.h @@ -25,6 +25,7 @@ extern "C" { #include #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "esp_attr.h" //Type check wdt_stage_action_t diff --git a/components/hal/esp32/include/hal/sigmadelta_ll.h b/components/hal/esp32/include/hal/sigmadelta_ll.h index 929546fe0c..9e151871d2 100644 --- a/components/hal/esp32/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32/include/hal/spi_flash_ll.h b/components/hal/esp32/include/hal/spi_flash_ll.h index 7c0862eddc..3f18774a29 100644 --- a/components/hal/esp32/include/hal/spi_flash_ll.h +++ b/components/hal/esp32/include/hal/spi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -393,7 +395,7 @@ static inline void spi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void spi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } static inline void spi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n) diff --git a/components/hal/esp32/include/hal/spi_ll.h b/components/hal/esp32/include/hal/spi_ll.h index d9b520e473..89b4dedae3 100644 --- a/components/hal/esp32/include/hal/spi_ll.h +++ b/components/hal/esp32/include/hal/spi_ll.h @@ -27,6 +27,7 @@ #include "esp_types.h" #include "esp32/rom/lldesc.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/misc.h" #include "hal/spi_types.h" #include "hal/assert.h" @@ -700,7 +701,7 @@ static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int dela static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -858,13 +859,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } diff --git a/components/hal/esp32/include/hal/timer_ll.h b/components/hal/esp32/include/hal/timer_ll.h index f9efc82d22..35ce7d1025 100644 --- a/components/hal/esp32/include/hal/timer_ll.h +++ b/components/hal/esp32/include/hal/timer_ll.h @@ -22,9 +22,11 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "hal/assert.h" #include "hal/timer_types.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); _Static_assert(TIMER_INTR_T1 == TIMG_T1_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); @@ -50,7 +52,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u } int timer_en = hw->hw_timer[timer_num].config.enable; hw->hw_timer[timer_num].config.enable = 0; - hw->hw_timer[timer_num].config.divider = divider; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, divider, divider); hw->hw_timer[timer_num].config.enable = timer_en; } @@ -65,7 +67,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, divider); if (d == 0) { d = 65536; } else if (d == 1) { diff --git a/components/hal/esp32/include/hal/touch_sensor_ll.h b/components/hal/esp32/include/hal/touch_sensor_ll.h index 5642d28cc2..07f17d4b65 100644 --- a/components/hal/esp32/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32/include/hal/touch_sensor_ll.h @@ -24,7 +24,11 @@ #include #include +#include "hal/misc.h" #include "soc/touch_sensor_periph.h" +#include "soc/sens_struct.h" +#include "soc/rtc_io_struct.h" +#include "soc/rtc_cntl_struct.h" #include "hal/touch_sensor_types.h" @@ -60,9 +64,9 @@ static inline touch_pad_t touch_ll_num_wrap(touch_pad_t touch_num) static inline void touch_ll_set_meas_time(uint16_t meas_time) { //touch sensor measure time= meas_cycle / 8Mhz - SENS.sar_touch_ctrl1.touch_meas_delay = meas_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay, meas_time); //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD - SENS.sar_touch_ctrl1.touch_xpd_wait = SOC_TOUCH_PAD_MEASURE_WAIT_MAX; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_xpd_wait, SOC_TOUCH_PAD_MEASURE_WAIT_MAX); } /** @@ -72,7 +76,7 @@ static inline void touch_ll_set_meas_time(uint16_t meas_time) */ static inline void touch_ll_get_meas_time(uint16_t *meas_time) { - *meas_time = SENS.sar_touch_ctrl1.touch_meas_delay; + *meas_time = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay); } /** @@ -86,7 +90,7 @@ static inline void touch_ll_get_meas_time(uint16_t *meas_time) static inline void touch_ll_set_sleep_time(uint16_t sleep_time) { //touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK( can be 150k or 32k depending on the options) - SENS.sar_touch_ctrl2.touch_sleep_cycles = sleep_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles, sleep_time); } /** @@ -96,7 +100,7 @@ static inline void touch_ll_set_sleep_time(uint16_t sleep_time) */ static inline void touch_ll_get_sleep_time(uint16_t *sleep_time) { - *sleep_time = SENS.sar_touch_ctrl2.touch_sleep_cycles; + *sleep_time = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles); } /** @@ -291,9 +295,9 @@ static inline void touch_ll_set_threshold(touch_pad_t touch_num, uint16_t thresh { touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num); if (tp_wrap & 0x1) { - SENS.touch_thresh[tp_wrap / 2].l_thresh = threshold; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], l_thresh, threshold); } else { - SENS.touch_thresh[tp_wrap / 2].h_thresh = threshold; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], h_thresh, threshold); } } @@ -308,8 +312,8 @@ static inline void touch_ll_get_threshold(touch_pad_t touch_num, uint16_t *thres touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num); if (threshold) { *threshold = (tp_wrap & 0x1 ) ? - SENS.touch_thresh[tp_wrap / 2].l_thresh : - SENS.touch_thresh[tp_wrap / 2].h_thresh; + HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], l_thresh) : + HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], h_thresh); } } @@ -489,7 +493,8 @@ static inline void touch_ll_intr_clear(void) static inline uint32_t touch_ll_read_raw_data(touch_pad_t touch_num) { touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num); - return ((tp_wrap & 0x1) ? SENS.touch_meas[tp_wrap / 2].l_val : SENS.touch_meas[tp_wrap / 2].h_val); + return ((tp_wrap & 0x1) ? HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], l_val) : + HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], h_val)); } /** diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index 0a37c61631..72949aa9cf 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -32,6 +32,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -491,7 +492,7 @@ static inline void twai_ll_parse_err_code_cap(twai_dev_t *hw, */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -531,7 +532,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -559,7 +560,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -578,8 +579,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -614,7 +615,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -794,8 +795,8 @@ static inline void twai_ll_save_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_save reg_save->bus_timing_1_reg = (uint8_t) hw->bus_timing_1_reg.val; reg_save->error_warning_limit_reg = (uint8_t) hw->error_warning_limit_reg.val; for (int i = 0; i < 4; i++) { - reg_save->acr_reg[i] = hw->acceptance_filter.acr[i].byte; - reg_save->amr_reg[i] = hw->acceptance_filter.amr[i].byte; + reg_save->acr_reg[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte); + reg_save->amr_reg[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte); } reg_save->rx_error_counter_reg = (uint8_t) hw->rx_error_counter_reg.val; reg_save->tx_error_counter_reg = (uint8_t) hw->tx_error_counter_reg.val; @@ -821,8 +822,8 @@ static inline void twai_ll_restore_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_s hw->bus_timing_1_reg.val = reg_save->bus_timing_1_reg; hw->error_warning_limit_reg.val = reg_save->error_warning_limit_reg; for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = reg_save->acr_reg[i]; - hw->acceptance_filter.amr[i].byte = reg_save->amr_reg[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, reg_save->acr_reg[i]); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, reg_save->amr_reg[i]); } hw->rx_error_counter_reg.val = reg_save->rx_error_counter_reg; hw->tx_error_counter_reg.val = reg_save->tx_error_counter_reg; diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index ed52f969bd..de8fc640ff 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "esp_attr.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #include "hal/uart_types.h" #ifdef __cplusplus @@ -249,7 +252,7 @@ FORCE_INLINE_ATTR void uart_ll_rxfifo_rst(uart_dev_t *hw) //Get the UART APB fifo addr uint32_t fifo_addr = (hw == &UART0) ? UART_FIFO_REG(0) : (hw == &UART1) ? UART_FIFO_REG(1) : UART_FIFO_REG(2); do { - fifo_cnt = hw->status.rxfifo_cnt; + fifo_cnt = HAL_FORCE_READ_U32_REG_FIELD(hw->status, rxfifo_cnt); rxmem_sta.val = hw->mem_rx_status.val; if(fifo_cnt != 0 || (rxmem_sta.rd_addr != rxmem_sta.wr_addr)) { READ_PERI_REG(fifo_addr); @@ -287,7 +290,7 @@ FORCE_INLINE_ATTR void uart_ll_txfifo_rst(uart_dev_t *hw) */ FORCE_INLINE_ATTR uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) { - uint32_t fifo_cnt = hw->status.rxfifo_cnt; + uint32_t fifo_cnt = HAL_FORCE_READ_U32_REG_FIELD(hw->status, rxfifo_cnt); typeof(hw->mem_rx_status) rx_status = hw->mem_rx_status; uint32_t len = 0; @@ -313,7 +316,7 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) */ FORCE_INLINE_ATTR uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw) { - return UART_LL_FIFO_DEF_LEN - hw->status.txfifo_cnt; + return UART_LL_FIFO_DEF_LEN - HAL_FORCE_READ_U32_REG_FIELD(hw->status, txfifo_cnt); } /** @@ -453,7 +456,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if(break_num > 0) { - hw->idle_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->idle_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -518,10 +521,10 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl if(sw_flow_ctrl_en) { hw->flow_conf.xonoff_del = 1; hw->flow_conf.sw_flow_con_en = 1; - hw->swfc_conf.xon_threshold = flow_ctrl->xon_thrd; - hw->swfc_conf.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf.xon_char = flow_ctrl->xon_char; - hw->swfc_conf.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xon_threshold, flow_ctrl->xon_thrd); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xoff_threshold, flow_ctrl->xoff_thrd); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -543,8 +546,8 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl */ FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; @@ -729,8 +732,8 @@ FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index a2fd21f2b5..49ff4a23f4 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -15,6 +15,7 @@ #include #include +#include "hal/misc.h" #include "regi2c_ctrl.h" #include "esp_attr.h" @@ -94,11 +95,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -124,7 +125,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock devided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -135,7 +136,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div) */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -267,7 +268,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -404,7 +405,7 @@ static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index da61aa198c..6214bc06e3 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -24,6 +24,7 @@ #include "soc/soc.h" #include "soc/gpio_periph.h" +#include "soc/gpio_struct.h" #include "soc/rtc_cntl_reg.h" #include "hal/gpio_types.h" #include "stdlib.h" diff --git a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h index 9f7f8e54a1..212e03a06d 100644 --- a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -363,7 +365,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32c3/include/hal/i2c_ll.h b/components/hal/esp32c3/include/hal/i2c_ll.h index d8fbfd206c..31743005b6 100644 --- a/components/hal/esp32c3/include/hal/i2c_ll.h +++ b/components/hal/esp32c3/include/hal/i2c_ll.h @@ -15,8 +15,11 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" #include "soc/soc_caps.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #include "soc/rtc_cntl_reg.h" #include "esp_rom_sys.h" @@ -154,7 +157,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw) */ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) { - hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1); //scl period hw->scl_low_period.period = bus_cfg->scl_low - 1; hw->scl_high_period.period = bus_cfg->scl_high; @@ -576,7 +579,7 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for (int i = 0; i< len; i++) { - hw->fifo_data.data = ptr[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->fifo_data, data, ptr[i]); } } @@ -592,7 +595,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->fifo_data.data; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo_data, data); } } diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 3bca90102c..30fbfb7e51 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -21,7 +21,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus @@ -218,7 +220,7 @@ static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; } } - hw->tx_clkm_conf.tx_clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div); } /** @@ -257,7 +259,7 @@ static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; } } - hw->rx_clkm_conf.rx_clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div); } /** @@ -500,7 +502,7 @@ static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) */ static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - hw->tx_pcm2pdm_conf.tx_pdm_prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_pcm2pdm_conf, tx_pdm_prescale, prescale); } /** diff --git a/components/hal/esp32c3/include/hal/ledc_ll.h b/components/hal/esp32c3/include/hal/ledc_ll.h index eafae904ba..fb495b0319 100644 --- a/components/hal/esp32c3/include/hal/ledc_ll.h +++ b/components/hal/esp32c3/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32c3/include/hal/mwdt_ll.h b/components/hal/esp32c3/include/hal/mwdt_ll.h index b192a8400f..944108439e 100644 --- a/components/hal/esp32c3/include/hal/mwdt_ll.h +++ b/components/hal/esp32c3/include/hal/mwdt_ll.h @@ -24,6 +24,7 @@ extern "C" { #include #include #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" diff --git a/components/hal/esp32c3/include/hal/rmt_ll.h b/components/hal/esp32c3/include/hal/rmt_ll.h index f5427d150a..0f703aebc7 100644 --- a/components/hal/esp32c3/include/hal/rmt_ll.h +++ b/components/hal/esp32c3/include/hal/rmt_ll.h @@ -16,6 +16,7 @@ #include #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus @@ -58,7 +59,7 @@ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) dev->sys_conf.sclk_active = 0; dev->sys_conf.sclk_sel = src; - dev->sys_conf.sclk_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->sys_conf, sclk_div_num, div_num); dev->sys_conf.sclk_div_a = div_a; dev->sys_conf.sclk_div_b = div_b; dev->sys_conf.sclk_active = 1; @@ -140,22 +141,22 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->tx_conf[channel].div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_conf[channel], div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->rx_conf[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->tx_conf[channel].div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->tx_conf[channel], div_cnt); } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->rx_conf[channel].conf0.div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt); } static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -231,7 +232,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->rx_conf[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -441,14 +442,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->tx_carrier[channel].high; - *low_ticks = dev->tx_carrier[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], low); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->rx_carrier[channel].high_thres; - *low_ticks = dev->rx_carrier[channel].low_thres; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], high_thres); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], low_thres); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32c3/include/hal/rwdt_ll.h b/components/hal/esp32c3/include/hal/rwdt_ll.h index 87ae4f7294..0986ce3dec 100644 --- a/components/hal/esp32c3/include/hal/rwdt_ll.h +++ b/components/hal/esp32c3/include/hal/rwdt_ll.h @@ -23,8 +23,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -239,7 +241,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t *hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32c3/include/hal/sigmadelta_ll.h b/components/hal/esp32c3/include/hal/sigmadelta_ll.h index 87f75dab9e..f6c37054a3 100644 --- a/components/hal/esp32c3/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32c3/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32c3/include/hal/spi_ll.h b/components/hal/esp32c3/include/hal/spi_ll.h index 99dd305ac3..38e1676d04 100644 --- a/components/hal/esp32c3/include/hal/spi_ll.h +++ b/components/hal/esp32c3/include/hal/spi_ll.h @@ -27,6 +27,7 @@ #include "esp_attr.h" #include "esp_types.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -901,13 +902,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -923,7 +924,7 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32c3/include/hal/spimem_flash_ll.h b/components/hal/esp32c3/include/hal/spimem_flash_ll.h index 7641c3d723..92c8748dd4 100644 --- a/components/hal/esp32c3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c3/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -157,7 +158,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_cmd.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_pes_command, sus_cmd); } /** @@ -169,7 +170,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_cmd.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_per_command, res_cmd); } /** @@ -181,7 +182,7 @@ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t */ static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd) { - dev->flash_sus_cmd.wait_pesr_command = pesr_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, wait_pesr_command, pesr_cmd); } /** @@ -218,7 +219,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_conf) { dev->flash_sus_ctrl.frd_sus_2b = 0; - dev->flash_sus_ctrl.pesr_end_msk = sus_conf; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } /** @@ -229,7 +230,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti; dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti; } diff --git a/components/hal/esp32c3/include/hal/timer_ll.h b/components/hal/esp32c3/include/hal/timer_ll.h index b85436f0d3..5e51b102f1 100644 --- a/components/hal/esp32c3/include/hal/timer_ll.h +++ b/components/hal/esp32c3/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -55,7 +57,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u int timer_en = hw->hw_timer[timer_num].config.tx_en; hw->hw_timer[timer_num].config.tx_en = 0; hw->hw_timer[timer_num].config.tx_divcnt_rst = 1; - hw->hw_timer[timer_num].config.tx_divider = divider; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider); hw->hw_timer[timer_num].config.tx_en = timer_en; } @@ -70,7 +72,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.tx_divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider); if (d == 0) { d = 65536; } else if (d == 1) { diff --git a/components/hal/esp32c3/include/hal/twai_ll.h b/components/hal/esp32c3/include/hal/twai_ll.h index 92e0401118..371d4dd361 100644 --- a/components/hal/esp32c3/include/hal/twai_ll.h +++ b/components/hal/esp32c3/include/hal/twai_ll.h @@ -31,6 +31,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -399,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -439,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -467,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -486,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -522,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -652,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 344a6ecc42..f94296327a 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #ifdef __cplusplus extern "C" { @@ -163,7 +166,7 @@ static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) // an integer part and a fractional part. hw->clk_div.div_int = clk_div >> 4; hw->clk_div.div_frag = clk_div & 0xf; - hw->clk_conf.sclk_div_num = sclk_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); #undef DIV_UP } @@ -178,7 +181,7 @@ static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw) { uint32_t sclk_freq = uart_ll_get_sclk_freq(hw); typeof(hw->clk_div) div_reg = hw->clk_div; - return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (hw->clk_conf.sclk_div_num + 1)); + return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1)); } /** @@ -451,7 +454,7 @@ static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num) static inline void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if (break_num > 0) { - hw->txbrk_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->txbrk_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -518,8 +521,8 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -541,11 +544,11 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * */ static inline void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -734,8 +737,8 @@ static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ static inline void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32h2/include/hal/adc_ll.h b/components/hal/esp32h2/include/hal/adc_ll.h index 6e6ce7c2fc..7806465258 100644 --- a/components/hal/esp32h2/include/hal/adc_ll.h +++ b/components/hal/esp32h2/include/hal/adc_ll.h @@ -24,6 +24,7 @@ #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -94,11 +95,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -124,7 +125,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock devided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -135,7 +136,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div) */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -267,7 +268,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -404,7 +405,7 @@ static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** diff --git a/components/hal/esp32h2/include/hal/gpio_ll.h b/components/hal/esp32h2/include/hal/gpio_ll.h index e35a71db39..c6d751847c 100644 --- a/components/hal/esp32h2/include/hal/gpio_ll.h +++ b/components/hal/esp32h2/include/hal/gpio_ll.h @@ -25,6 +25,7 @@ #include "soc/soc.h" #include "soc/gpio_periph.h" #include "soc/rtc_cntl_reg.h" +#include "soc/gpio_struct.h" #include "hal/gpio_types.h" #include "stdlib.h" diff --git a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h index d26e00c720..d6b227e6f6 100644 --- a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -363,7 +365,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32h2/include/hal/i2c_ll.h b/components/hal/esp32h2/include/hal/i2c_ll.h index 88d4493b0e..2e34e4a55c 100644 --- a/components/hal/esp32h2/include/hal/i2c_ll.h +++ b/components/hal/esp32h2/include/hal/i2c_ll.h @@ -15,8 +15,11 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" #include "soc/soc_caps.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #include "soc/rtc_cntl_reg.h" #include "esp_rom_sys.h" @@ -154,7 +157,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw) */ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) { - hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1); //scl period hw->scl_low_period.period = bus_cfg->scl_low - 1; hw->scl_high_period.period = bus_cfg->scl_high; @@ -576,7 +579,7 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for (int i = 0; i< len; i++) { - hw->fifo_data.data = ptr[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->fifo_data, data, ptr[i]); } } @@ -592,7 +595,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->fifo_data.data; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo_data, data); } } diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 398c2487ec..9819a8ed4b 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus @@ -219,7 +221,7 @@ static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; } } - hw->tx_clkm_conf.tx_clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div); } /** @@ -258,7 +260,7 @@ static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; } } - hw->rx_clkm_conf.rx_clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div); } /** @@ -501,7 +503,7 @@ static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) */ static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - hw->tx_pcm2pdm_conf.tx_pdm_prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_pcm2pdm_conf, tx_pdm_prescale, prescale); } /** diff --git a/components/hal/esp32h2/include/hal/ledc_ll.h b/components/hal/esp32h2/include/hal/ledc_ll.h index eafae904ba..fb495b0319 100644 --- a/components/hal/esp32h2/include/hal/ledc_ll.h +++ b/components/hal/esp32h2/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32h2/include/hal/mwdt_ll.h b/components/hal/esp32h2/include/hal/mwdt_ll.h index b192a8400f..944108439e 100644 --- a/components/hal/esp32h2/include/hal/mwdt_ll.h +++ b/components/hal/esp32h2/include/hal/mwdt_ll.h @@ -24,6 +24,7 @@ extern "C" { #include #include #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" diff --git a/components/hal/esp32h2/include/hal/rmt_ll.h b/components/hal/esp32h2/include/hal/rmt_ll.h index f5427d150a..6aa3655075 100644 --- a/components/hal/esp32h2/include/hal/rmt_ll.h +++ b/components/hal/esp32h2/include/hal/rmt_ll.h @@ -17,6 +17,7 @@ #include #include #include "soc/rmt_struct.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -58,7 +59,7 @@ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) dev->sys_conf.sclk_active = 0; dev->sys_conf.sclk_sel = src; - dev->sys_conf.sclk_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->sys_conf, sclk_div_num, div_num); dev->sys_conf.sclk_div_a = div_a; dev->sys_conf.sclk_div_b = div_b; dev->sys_conf.sclk_active = 1; @@ -140,22 +141,22 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->tx_conf[channel].div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_conf[channel], div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->rx_conf[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->tx_conf[channel].div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->tx_conf[channel], div_cnt); } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->rx_conf[channel].conf0.div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt); } static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -231,7 +232,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->rx_conf[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -441,14 +442,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->tx_carrier[channel].high; - *low_ticks = dev->tx_carrier[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], low); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->rx_carrier[channel].high_thres; - *low_ticks = dev->rx_carrier[channel].low_thres; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], high_thres); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], low_thres); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32h2/include/hal/rwdt_ll.h b/components/hal/esp32h2/include/hal/rwdt_ll.h index 87ae4f7294..0986ce3dec 100644 --- a/components/hal/esp32h2/include/hal/rwdt_ll.h +++ b/components/hal/esp32h2/include/hal/rwdt_ll.h @@ -23,8 +23,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -239,7 +241,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t *hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32h2/include/hal/sigmadelta_ll.h b/components/hal/esp32h2/include/hal/sigmadelta_ll.h index 87f75dab9e..f6c37054a3 100644 --- a/components/hal/esp32h2/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32h2/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32h2/include/hal/spi_ll.h b/components/hal/esp32h2/include/hal/spi_ll.h index 0cbb0bf3d5..764f3fd872 100644 --- a/components/hal/esp32h2/include/hal/spi_ll.h +++ b/components/hal/esp32h2/include/hal/spi_ll.h @@ -27,6 +27,7 @@ #include "esp_attr.h" #include "esp_types.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -900,13 +901,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -922,7 +923,7 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32h2/include/hal/spimem_flash_ll.h b/components/hal/esp32h2/include/hal/spimem_flash_ll.h index 14613abe02..0c464a20b2 100644 --- a/components/hal/esp32h2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32h2/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -157,7 +158,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_cmd.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_pes_command, sus_cmd); } /** @@ -169,7 +170,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_cmd.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_per_command, res_cmd); } /** @@ -181,7 +182,7 @@ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t */ static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd) { - dev->flash_sus_cmd.wait_pesr_command = pesr_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, wait_pesr_command, pesr_cmd); } /** @@ -218,7 +219,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_conf) { dev->flash_sus_ctrl.frd_sus_2b = 0; - dev->flash_sus_ctrl.pesr_end_msk = sus_conf; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } /** @@ -229,7 +230,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti; dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti; } diff --git a/components/hal/esp32h2/include/hal/timer_ll.h b/components/hal/esp32h2/include/hal/timer_ll.h index 9a5318f194..4032a1b1dd 100644 --- a/components/hal/esp32h2/include/hal/timer_ll.h +++ b/components/hal/esp32h2/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -55,7 +57,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u int timer_en = hw->hw_timer[timer_num].config.tx_en; hw->hw_timer[timer_num].config.tx_en = 0; hw->hw_timer[timer_num].config.tx_divcnt_rst = 1; - hw->hw_timer[timer_num].config.tx_divider = divider; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider); hw->hw_timer[timer_num].config.tx_en = timer_en; } @@ -70,7 +72,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.tx_divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider); if (d == 0) { d = 65536; } else if (d == 1) { diff --git a/components/hal/esp32h2/include/hal/twai_ll.h b/components/hal/esp32h2/include/hal/twai_ll.h index ed6fbc5795..92c46d010b 100644 --- a/components/hal/esp32h2/include/hal/twai_ll.h +++ b/components/hal/esp32h2/include/hal/twai_ll.h @@ -28,8 +28,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -398,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -438,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -466,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -485,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = __builtin_bswap32(code); uint32_t mask_swapped = __builtin_bswap32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -521,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -651,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index 6d8fd0f3e9..ca51779548 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #ifdef __cplusplus extern "C" { @@ -163,7 +166,7 @@ static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) // an integer part and a fractional part. hw->clk_div.div_int = clk_div >> 4; hw->clk_div.div_frag = clk_div & 0xf; - hw->clk_conf.sclk_div_num = sclk_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); #undef DIV_UP } @@ -178,7 +181,7 @@ static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw) { uint32_t sclk_freq = uart_ll_get_sclk_freq(hw); typeof(hw->clk_div) div_reg = hw->clk_div; - return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (hw->clk_conf.sclk_div_num + 1)); + return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1)); } /** @@ -451,7 +454,7 @@ static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num) static inline void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if (break_num > 0) { - hw->txbrk_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->txbrk_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -518,8 +521,8 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -541,11 +544,11 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * */ static inline void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -734,8 +737,8 @@ static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ static inline void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h index e75cf67b43..0241436ec4 100644 --- a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h @@ -15,6 +15,8 @@ // The LL layer of the USB-serial-jtag controller #pragma once + +#include "hal/misc.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/usb_serial_jtag_struct.h" @@ -108,7 +110,7 @@ static inline int usb_serial_jtag_ll_read_rxfifo(uint8_t *buf, uint32_t rd_len) int i; for (i = 0; i < (int)rd_len; i++) { if (!USB_SERIAL_JTAG.ep1_conf.serial_out_ep_data_avail) break; - buf[i] = USB_SERIAL_JTAG.ep1.rdwr_byte; + buf[i] = HAL_FORCE_READ_U32_REG_FIELD(USB_SERIAL_JTAG.ep1, rdwr_byte); } return i; } @@ -127,7 +129,7 @@ static inline int usb_serial_jtag_ll_write_txfifo(const uint8_t *buf, uint32_t w int i; for (i = 0; i < (int)wr_len; i++) { if (!USB_SERIAL_JTAG.ep1_conf.serial_in_ep_data_free) break; - USB_SERIAL_JTAG.ep1.rdwr_byte = buf[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(USB_SERIAL_JTAG.ep1, rdwr_byte, buf[i]); } return i; } diff --git a/components/hal/esp32s2/include/hal/adc_ll.h b/components/hal/esp32s2/include/hal/adc_ll.h index ffad47a5c3..a44f50915f 100644 --- a/components/hal/esp32s2/include/hal/adc_ll.h +++ b/components/hal/esp32s2/include/hal/adc_ll.h @@ -1,9 +1,11 @@ #pragma once #include +#include "hal/misc.h" #include "soc/adc_periph.h" #include "hal/adc_types.h" #include "soc/apb_saradc_struct.h" +#include "soc/sens_struct.h" #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" @@ -83,11 +85,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -115,7 +117,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock devided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -136,7 +138,7 @@ static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -307,7 +309,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -427,9 +429,9 @@ static inline void adc_ll_digi_filter_enable(adc_ll_num_t adc_n, bool enable) static inline uint32_t adc_ll_digi_filter_read_data(adc_ll_num_t adc_n) { if (adc_n == ADC_NUM_1) { - return APB_SARADC.filter_status.adc1_filter_data; + return HAL_FORCE_READ_U32_REG_FIELD(APB_SARADC.filter_status, adc1_filter_data); } else { // adc_n == ADC_NUM_2 - return APB_SARADC.filter_status.adc2_filter_data; + return HAL_FORCE_READ_U32_REG_FIELD(APB_SARADC.filter_status, adc2_filter_data); } } @@ -595,7 +597,7 @@ static inline uint32_t adc_ll_digi_get_intr_status(adc_ll_num_t adc_n) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** @@ -710,7 +712,7 @@ static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n) static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel) { if (adc_n == ADC_NUM_1) { - while (SENS.sar_slave_addr1.meas_status != 0); + while (HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_slave_addr1, meas_status) != 0) {} SENS.sar_meas1_ctrl2.meas1_start_sar = 0; SENS.sar_meas1_ctrl2.meas1_start_sar = 1; } else { // adc_n == ADC_NUM_2 @@ -749,9 +751,9 @@ static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n) { int ret_val = 0; if (adc_n == ADC_NUM_1) { - ret_val = SENS.sar_meas1_ctrl2.meas1_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas1_ctrl2, meas1_data_sar); } else { // adc_n == ADC_NUM_2 - ret_val = SENS.sar_meas2_ctrl2.meas2_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas2_ctrl2, meas2_data_sar); } return ret_val; } @@ -906,9 +908,9 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void) static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) { if (adc_n == ADC_NUM_1) { - SENS.sar_reader1_ctrl.sar1_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div); } else { // adc_n == ADC_NUM_2 - SENS.sar_reader2_ctrl.sar2_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div); } } diff --git a/components/hal/esp32s2/include/hal/dac_ll.h b/components/hal/esp32s2/include/hal/dac_ll.h index 11f3284f11..28c8ae2066 100644 --- a/components/hal/esp32s2/include/hal/dac_ll.h +++ b/components/hal/esp32s2/include/hal/dac_ll.h @@ -21,9 +21,12 @@ #pragma once #include +#include "hal/misc.h" #include "soc/dac_periph.h" #include "hal/dac_types.h" #include "soc/apb_saradc_struct.h" +#include "soc/sens_struct.h" +#include "soc/rtc_io_struct.h" #include "soc/apb_saradc_reg.h" #ifdef __cplusplus @@ -74,10 +77,10 @@ static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t val { if (channel == DAC_CHANNEL_1) { SENS.sar_dac_ctrl2.dac_cw_en1 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } else if (channel == DAC_CHANNEL_2) { SENS.sar_dac_ctrl2.dac_cw_en2 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } } @@ -145,7 +148,7 @@ static inline void dac_ll_cw_set_channel(dac_channel_t channel, bool enable) static inline void dac_ll_cw_set_freq(uint32_t freq) { uint32_t sw_freq = freq * 0xFFFF / RTC_FAST_CLK_FREQ_APPROX; - SENS.sar_dac_ctrl1.sw_fstep = (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl1, sw_fstep, (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq); } /** @@ -192,12 +195,12 @@ static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset) if (SENS.sar_dac_ctrl2.dac_inv1 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc1 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc1, offset ? offset : (-128 - offset)); } else if (channel == DAC_CHANNEL_2) { if (SENS.sar_dac_ctrl2.dac_inv2 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc2 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc2, offset ? offset : (-128 - offset)); } } diff --git a/components/hal/esp32s2/include/hal/dedic_gpio_ll.h b/components/hal/esp32s2/include/hal/dedic_gpio_ll.h index 3cbf29b7bb..8fcdd0e7a6 100644 --- a/components/hal/esp32s2/include/hal/dedic_gpio_ll.h +++ b/components/hal/esp32s2/include/hal/dedic_gpio_ll.h @@ -19,6 +19,7 @@ extern "C" { #include #include +#include "hal/misc.h" #include "soc/dedic_gpio_struct.h" static inline void dedic_gpio_ll_enable_instruction_access_out(dedic_dev_t *dev, uint32_t channel_mask, bool enable) @@ -61,12 +62,12 @@ static inline void dedic_gpio_ll_toggle_channel(dedic_dev_t *dev, uint32_t chann static inline uint32_t dedic_gpio_ll_read_out_all(dedic_dev_t *dev) { - return dev->gpio_out_scan.gpio_out_status; + return HAL_FORCE_READ_U32_REG_FIELD(dev->gpio_out_scan, gpio_out_status); } static inline uint32_t dedic_gpio_ll_read_in_all(dedic_dev_t *dev) { - return dev->gpio_in_scan.gpio_in_status; + return HAL_FORCE_READ_U32_REG_FIELD(dev->gpio_in_scan, gpio_in_status); } static inline void dedic_gpio_ll_set_input_delay(dedic_dev_t *dev, uint32_t channel, uint32_t delay_cpu_clks) diff --git a/components/hal/esp32s2/include/hal/gpio_ll.h b/components/hal/esp32s2/include/hal/gpio_ll.h index d6330db630..34cdc464bc 100644 --- a/components/hal/esp32s2/include/hal/gpio_ll.h +++ b/components/hal/esp32s2/include/hal/gpio_ll.h @@ -26,6 +26,7 @@ #include "soc/gpio_periph.h" #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" +#include "soc/gpio_struct.h" #include "hal/gpio_types.h" #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h index 6f7d441c06..79fc727bdd 100644 --- a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -357,7 +359,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32s2/include/hal/i2c_ll.h b/components/hal/esp32s2/include/hal/i2c_ll.h index 81fb326b55..1d2b8a0c13 100644 --- a/components/hal/esp32s2/include/hal/i2c_ll.h +++ b/components/hal/esp32s2/include/hal/i2c_ll.h @@ -16,6 +16,7 @@ #pragma once #include "soc/i2c_periph.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 810ee64c7b..725d4343b2 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -23,7 +23,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus @@ -268,7 +270,7 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) { - hw->clkm_conf.clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; hw->clkm_conf.clkm_div_a = set->a; } @@ -292,7 +294,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) { - hw->clkm_conf.clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; hw->clkm_conf.clkm_div_a = set->a; } diff --git a/components/hal/esp32s2/include/hal/ledc_ll.h b/components/hal/esp32s2/include/hal/ledc_ll.h index 19d61f127f..677a2e36d3 100644 --- a/components/hal/esp32s2/include/hal/ledc_ll.h +++ b/components/hal/esp32s2/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32s2/include/hal/mwdt_ll.h b/components/hal/esp32s2/include/hal/mwdt_ll.h index 2d9fcd9850..6d50f740b6 100644 --- a/components/hal/esp32s2/include/hal/mwdt_ll.h +++ b/components/hal/esp32s2/include/hal/mwdt_ll.h @@ -24,6 +24,7 @@ extern "C" { #include #include #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" diff --git a/components/hal/esp32s2/include/hal/rmt_ll.h b/components/hal/esp32s2/include/hal/rmt_ll.h index 0354afc766..958fe7aef5 100644 --- a/components/hal/esp32s2/include/hal/rmt_ll.h +++ b/components/hal/esp32s2/include/hal/rmt_ll.h @@ -15,6 +15,7 @@ #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus @@ -126,23 +127,23 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } @@ -153,12 +154,12 @@ static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, b static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf0.idle_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres, thres); } static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) { - return dev->conf_ch[channel].conf0.idle_thres; + return HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres); } static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) @@ -219,7 +220,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -415,14 +416,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->carrier_duty_ch[channel].high; - *low_ticks = dev->carrier_duty_ch[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], low); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->ch_rx_carrier_rm[channel].carrier_high_thres_ch; - *low_ticks = dev->ch_rx_carrier_rm[channel].carrier_low_thres_ch; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->ch_rx_carrier_rm[channel], carrier_high_thres_ch); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->ch_rx_carrier_rm[channel], carrier_low_thres_ch); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32s2/include/hal/rtc_io_ll.h b/components/hal/esp32s2/include/hal/rtc_io_ll.h index c519f70030..cdd19466b6 100644 --- a/components/hal/esp32s2/include/hal/rtc_io_ll.h +++ b/components/hal/esp32s2/include/hal/rtc_io_ll.h @@ -22,6 +22,8 @@ #include #include "soc/rtc_io_periph.h" +#include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" #include "hal/rtc_io_types.h" #include "hal/gpio_types.h" diff --git a/components/hal/esp32s2/include/hal/rwdt_ll.h b/components/hal/esp32s2/include/hal/rwdt_ll.h index 681c2fdf4f..f3cc3c0cc4 100644 --- a/components/hal/esp32s2/include/hal/rwdt_ll.h +++ b/components/hal/esp32s2/include/hal/rwdt_ll.h @@ -23,8 +23,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -239,7 +241,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t* hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32s2/include/hal/sigmadelta_ll.h b/components/hal/esp32s2/include/hal/sigmadelta_ll.h index e06464a5ff..20406e19fd 100644 --- a/components/hal/esp32s2/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32s2/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index 894fa9affe..b81b36c53b 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -27,6 +27,7 @@ #include "esp_types.h" #include "esp_attr.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -734,7 +735,7 @@ static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int dela static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -895,13 +896,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -1071,7 +1072,7 @@ static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw) static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) { - return hw->slave1.last_addr; + return HAL_FORCE_READ_U32_REG_FIELD(hw->slave1, last_addr); } /*------------------------------------------------------------------------------ diff --git a/components/hal/esp32s2/include/hal/spimem_flash_ll.h b/components/hal/esp32s2/include/hal/spimem_flash_ll.h index b04020eb51..2bbd6e90ff 100644 --- a/components/hal/esp32s2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s2/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -167,7 +168,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_ctrl.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_pes_command, sus_cmd); } /** @@ -179,7 +180,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_ctrl.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_per_command, res_cmd); } /** @@ -226,7 +227,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; // Set the command to send, to fetch flash status reg value. + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); // Set the command to send, to fetch flash status reg value. dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function. } @@ -516,7 +517,7 @@ static inline void spimem_flash_ll_set_usr_address(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32s2/include/hal/timer_ll.h b/components/hal/esp32s2/include/hal/timer_ll.h index cc728169ec..59921e2364 100644 --- a/components/hal/esp32s2/include/hal/timer_ll.h +++ b/components/hal/esp32s2/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -50,7 +52,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u } int timer_en = hw->hw_timer[timer_num].config.tx_en; hw->hw_timer[timer_num].config.tx_en = 0; - hw->hw_timer[timer_num].config.tx_divider = divider; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider); hw->hw_timer[timer_num].config.tx_en = timer_en; } @@ -65,7 +67,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.tx_divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider); if (d == 0) { d = 65536; } else if (d == 1) { diff --git a/components/hal/esp32s2/include/hal/touch_sensor_ll.h b/components/hal/esp32s2/include/hal/touch_sensor_ll.h index 2fa8227153..30c3cc1014 100644 --- a/components/hal/esp32s2/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s2/include/hal/touch_sensor_ll.h @@ -24,8 +24,12 @@ #include #include +#include "hal/misc.h" #include "soc/touch_sensor_periph.h" #include "soc/soc_caps.h" +#include "soc/sens_struct.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/rtc_io_struct.h" #include "hal/touch_sensor_types.h" #ifdef __cplusplus @@ -47,9 +51,9 @@ extern "C" { static inline void touch_ll_set_meas_times(uint16_t meas_time) { //The times of charge and discharge in each measure process of touch channels. - RTCCNTL.touch_ctrl1.touch_meas_num = meas_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num, meas_time); //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD - RTCCNTL.touch_ctrl2.touch_xpd_wait = SOC_TOUCH_PAD_MEASURE_WAIT_MAX; //wait volt stable + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl2, touch_xpd_wait, SOC_TOUCH_PAD_MEASURE_WAIT_MAX); //wait volt stable } /** @@ -59,7 +63,7 @@ static inline void touch_ll_set_meas_times(uint16_t meas_time) */ static inline void touch_ll_get_measure_times(uint16_t *meas_time) { - *meas_time = RTCCNTL.touch_ctrl1.touch_meas_num; + *meas_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num); } /** @@ -73,7 +77,7 @@ static inline void touch_ll_get_measure_times(uint16_t *meas_time) static inline void touch_ll_set_sleep_time(uint16_t sleep_time) { // touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK(90k) - RTCCNTL.touch_ctrl1.touch_sleep_cycles = sleep_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles, sleep_time); } /** @@ -83,7 +87,7 @@ static inline void touch_ll_set_sleep_time(uint16_t sleep_time) */ static inline void touch_ll_get_sleep_time(uint16_t *sleep_time) { - *sleep_time = RTCCNTL.touch_ctrl1.touch_sleep_cycles; + *sleep_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles); } /** @@ -990,7 +994,7 @@ static inline void touch_ll_proximity_get_channel_num(touch_pad_t prox_pad[]) */ static inline void touch_ll_proximity_set_meas_times(uint32_t times) { - RTCCNTL.touch_approach.touch_approach_meas_time = times; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time, times); } /** @@ -1000,7 +1004,7 @@ static inline void touch_ll_proximity_set_meas_times(uint32_t times) */ static inline void touch_ll_proximity_get_meas_times(uint32_t *times) { - *times = RTCCNTL.touch_approach.touch_approach_meas_time; + *times = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time); } /** @@ -1011,11 +1015,11 @@ static inline void touch_ll_proximity_get_meas_times(uint32_t *times) static inline void touch_ll_proximity_read_meas_cnt(touch_pad_t touch_num, uint32_t *cnt) { if (SENS.sar_touch_conf.touch_approach_pad0 == touch_num) { - *cnt = SENS.sar_touch_appr_status.touch_approach_pad0_cnt; + *cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_approach_pad0_cnt); } else if (SENS.sar_touch_conf.touch_approach_pad1 == touch_num) { - *cnt = SENS.sar_touch_appr_status.touch_approach_pad1_cnt; + *cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_approach_pad1_cnt); } else if (SENS.sar_touch_conf.touch_approach_pad2 == touch_num) { - *cnt = SENS.sar_touch_appr_status.touch_approach_pad2_cnt; + *cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_approach_pad2_cnt); } } @@ -1163,7 +1167,7 @@ static inline void touch_ll_sleep_read_debounce(uint32_t *debounce) */ static inline void touch_ll_sleep_read_proximity_cnt(uint32_t *approach_cnt) { - *approach_cnt = SENS.sar_touch_appr_status.touch_slp_approach_cnt; + *approach_cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_slp_approach_cnt); } /** diff --git a/components/hal/esp32s2/include/hal/twai_ll.h b/components/hal/esp32s2/include/hal/twai_ll.h index 106f3adc6f..7a04c18aef 100644 --- a/components/hal/esp32s2/include/hal/twai_ll.h +++ b/components/hal/esp32s2/include/hal/twai_ll.h @@ -31,6 +31,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -399,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -439,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -467,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -486,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -522,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -652,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index 15b96f8bed..9309d3b8f2 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #include "esp_attr.h" #ifdef __cplusplus @@ -403,7 +406,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if(break_num > 0) { - hw->idle_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->idle_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -470,8 +473,8 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -493,11 +496,11 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl */ FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -679,8 +682,8 @@ FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 58302045e5..c554e6cf4b 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -18,9 +18,11 @@ #include "soc/adc_periph.h" #include "hal/adc_types.h" #include "soc/apb_saradc_struct.h" +#include "soc/sens_struct.h" #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -109,11 +111,11 @@ typedef struct { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -138,7 +140,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock divided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -149,7 +151,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div) */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -307,7 +309,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -450,7 +452,7 @@ static inline void adc_ll_digi_monitor_enable(adc_ll_num_t adc_n, bool enable) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** @@ -765,9 +767,9 @@ static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, b static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) { if (adc_n == ADC_NUM_1) { - SENS.sar_reader1_ctrl.sar1_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div); } else { // adc_n == ADC_NUM_2 - SENS.sar_reader2_ctrl.sar2_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div); } } @@ -828,7 +830,7 @@ static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n) static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel) { if (adc_n == ADC_NUM_1) { - while (SENS.sar_slave_addr1.meas_status != 0); + while (HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_slave_addr1, meas_status) != 0) {} SENS.sar_meas1_ctrl2.meas1_start_sar = 0; SENS.sar_meas1_ctrl2.meas1_start_sar = 1; } else { // adc_n == ADC_NUM_2 @@ -867,9 +869,9 @@ static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n) { int ret_val = 0; if (adc_n == ADC_NUM_1) { - ret_val = SENS.sar_meas1_ctrl2.meas1_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas1_ctrl2, meas1_data_sar); } else { // adc_n == ADC_NUM_2 - ret_val = SENS.sar_meas2_ctrl2.meas2_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas2_ctrl2, meas2_data_sar); } return ret_val; } diff --git a/components/hal/esp32s3/include/hal/gpio_ll.h b/components/hal/esp32s3/include/hal/gpio_ll.h index 0b054bf25d..2248c41afc 100644 --- a/components/hal/esp32s3/include/hal/gpio_ll.h +++ b/components/hal/esp32s3/include/hal/gpio_ll.h @@ -28,6 +28,7 @@ #include "soc/rtc_io_reg.h" #include "soc/usb_serial_jtag_reg.h" #include "hal/gpio_types.h" +#include "soc/gpio_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h index 6669db4be2..47f11e637a 100644 --- a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -369,7 +371,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1) } /** diff --git a/components/hal/esp32s3/include/hal/i2c_ll.h b/components/hal/esp32s3/include/hal/i2c_ll.h index 566ada8b3f..eae2a660fb 100644 --- a/components/hal/esp32s3/include/hal/i2c_ll.h +++ b/components/hal/esp32s3/include/hal/i2c_ll.h @@ -15,8 +15,11 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" #include "soc/soc_caps.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #ifdef __cplusplus @@ -148,7 +151,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw) */ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) { - hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1); //scl period hw->scl_low_period.scl_low_period = bus_cfg->scl_low - 1; hw->scl_high_period.scl_high_period = bus_cfg->scl_high; @@ -574,7 +577,7 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for (int i = 0; i< len; i++) { - hw->data.fifo_rdata = ptr[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->data, fifo_rdata, ptr[i]); } } @@ -590,7 +593,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->data.fifo_rdata; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->data, fifo_rdata); } } diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 4dff8f3a12..791918fae0 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -21,7 +21,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus @@ -221,7 +223,7 @@ static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; } } - hw->tx_clkm_conf.tx_clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div); } /** @@ -260,7 +262,7 @@ static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; } } - hw->rx_clkm_conf.rx_clkm_div_num = set->mclk_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div); } /** @@ -555,7 +557,7 @@ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) */ static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - hw->tx_pcm2pdm_conf.tx_prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_pcm2pdm_conf, tx_prescale, prescale); } /** diff --git a/components/hal/esp32s3/include/hal/lcd_ll.h b/components/hal/esp32s3/include/hal/lcd_ll.h index d93abb3672..1d95d9e125 100644 --- a/components/hal/esp32s3/include/hal/lcd_ll.h +++ b/components/hal/esp32s3/include/hal/lcd_ll.h @@ -15,6 +15,7 @@ #include #include +#include "hal/misc.h" #include "soc/lcd_cam_reg.h" #include "soc/lcd_cam_struct.h" #include "hal/assert.h" @@ -47,7 +48,7 @@ static inline void lcd_ll_set_group_clock_src(lcd_cam_dev_t *dev, int src, int d // lcd_clk = module_clock_src / (div_num + div_b / div_a) HAL_ASSERT(div_num >= 2); dev->lcd_clock.lcd_clk_sel = src; - dev->lcd_clock.lcd_clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_clock, lcd_clkm_div_num, div_num); dev->lcd_clock.lcd_clkm_div_a = div_a; dev->lcd_clock.lcd_clkm_div_b = div_b; } @@ -188,7 +189,7 @@ static inline void lcd_ll_enable_output_hsync_in_porch_region(lcd_cam_dev_t *dev static inline void lcd_ll_set_hsync_position(lcd_cam_dev_t *dev, uint32_t offset_in_line) { - dev->lcd_ctrl2.lcd_hsync_position = offset_in_line; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_ctrl2, lcd_hsync_position, offset_in_line); } static inline void lcd_ll_set_horizontal_timing(lcd_cam_dev_t *dev, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp) @@ -202,7 +203,7 @@ static inline void lcd_ll_set_horizontal_timing(lcd_cam_dev_t *dev, uint32_t hsw static inline void lcd_ll_set_vertical_timing(lcd_cam_dev_t *dev, uint32_t vsw, uint32_t vbp, uint32_t active_height, uint32_t vfp) { dev->lcd_ctrl2.lcd_vsync_width = vsw - 1; - dev->lcd_ctrl1.lcd_vb_front = vbp + vsw - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_ctrl1, lcd_vb_front, vbp + vsw - 1); dev->lcd_ctrl.lcd_va_height = active_height - 1; dev->lcd_ctrl.lcd_vt_height = vsw + vbp + active_height + vfp - 1; } diff --git a/components/hal/esp32s3/include/hal/ledc_ll.h b/components/hal/esp32s3/include/hal/ledc_ll.h index eafae904ba..fb495b0319 100644 --- a/components/hal/esp32s3/include/hal/ledc_ll.h +++ b/components/hal/esp32s3/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32s3/include/hal/mcpwm_ll.h b/components/hal/esp32s3/include/hal/mcpwm_ll.h index 958a1c31f4..ddd66b144d 100644 --- a/components/hal/esp32s3/include/hal/mcpwm_ll.h +++ b/components/hal/esp32s3/include/hal/mcpwm_ll.h @@ -23,6 +23,7 @@ #pragma once #include +#include "hal/misc.h" #include "soc/soc_caps.h" #include "soc/mcpwm_struct.h" #include "hal/mcpwm_types.h" @@ -288,9 +289,9 @@ static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] - mcpwm->timer[timer_id].timer_cfg0.timer_period = peak - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1); } else { // in symmetric mode, period = [0,peak-1] + [peak,1] - mcpwm->timer[timer_id].timer_cfg0.timer_period = peak; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak); } } @@ -298,10 +299,10 @@ static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, { // asymmetric mode if (!symmetric) { - return mcpwm->timer[timer_id].timer_cfg0.timer_period + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1; } // symmetric mode - return mcpwm->timer[timer_id].timer_cfg0.timer_period; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period); } static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) @@ -388,13 +389,16 @@ static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int ti // status.value saves the "next count value", so need an extra round up here to get the current count value according to count mode // timer is paused if (mcpwm->timer[timer_id].timer_cfg1.timer_mod == 0) { - return mcpwm->timer[timer_id].timer_status.timer_value; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value); } if (mcpwm->timer[timer_id].timer_status.timer_direction) { // down direction - return (mcpwm->timer[timer_id].timer_status.timer_value + 1) % (mcpwm->timer[timer_id].timer_cfg0.timer_period + 1); + return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value) + 1) % + (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1); } // up direction - return (mcpwm->timer[timer_id].timer_status.timer_value + mcpwm->timer[timer_id].timer_cfg0.timer_period) % (mcpwm->timer[timer_id].timer_cfg0.timer_period + 1); + return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value) + + HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period)) % + (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1); } static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) @@ -437,7 +441,7 @@ static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int time static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) { - mcpwm->timer[timer_id].timer_sync.timer_phase = phase_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_sync, timer_phase, phase_value); } static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) @@ -524,12 +528,12 @@ static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t * static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) { - mcpwm->operator[operator_id].timestamp[compare_id].gen = compare_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operator[operator_id].timestamp[compare_id], gen, compare_value); } static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - return mcpwm->operator[operator_id].timestamp[compare_id].gen; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operator[operator_id].timestamp[compare_id], gen); } static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) @@ -728,22 +732,22 @@ static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) { - mcpwm->operator[operator_id].dt_fed_cfg.dt_fed = fed - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operator[operator_id].dt_fed_cfg, dt_fed, fed - 1); } static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->operator[operator_id].dt_fed_cfg.dt_fed + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operator[operator_id].dt_fed_cfg, dt_fed) + 1; } static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) { - mcpwm->operator[operator_id].dt_red_cfg.dt_red = red - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operator[operator_id].dt_red_cfg, dt_red, red - 1); } static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->operator[operator_id].dt_red_cfg.dt_red + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operator[operator_id].dt_red_cfg, dt_red) + 1; } static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) @@ -1015,12 +1019,12 @@ static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) { - mcpwm->cap_chn_cfg[channel].capn_prescale = prescale - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); } static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_chn_cfg[channel].capn_prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale) + 1; } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/mwdt_ll.h b/components/hal/esp32s3/include/hal/mwdt_ll.h index 0d34e2cc87..c15d7b8cd5 100644 --- a/components/hal/esp32s3/include/hal/mwdt_ll.h +++ b/components/hal/esp32s3/include/hal/mwdt_ll.h @@ -23,7 +23,9 @@ extern "C" { #include #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" @@ -219,7 +221,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t *hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) { - hw->wdtconfig1.wdt_clk_prescale = prescaler; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdtconfig1, wdt_clk_prescale, prescaler); } /** diff --git a/components/hal/esp32s3/include/hal/rmt_ll.h b/components/hal/esp32s3/include/hal/rmt_ll.h index 0dc87853fa..2ef9273be1 100644 --- a/components/hal/esp32s3/include/hal/rmt_ll.h +++ b/components/hal/esp32s3/include/hal/rmt_ll.h @@ -15,6 +15,7 @@ #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus @@ -57,7 +58,7 @@ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) dev->sys_conf.sclk_active = 0; dev->sys_conf.sclk_sel = src; - dev->sys_conf.sclk_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->sys_conf, sclk_div_num, div_num); dev->sys_conf.sclk_div_a = div_a; dev->sys_conf.sclk_div_b = div_b; dev->sys_conf.sclk_active = 1; @@ -139,22 +140,22 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->chnconf0[channel].div_cnt_n = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chnconf0[channel], div_cnt_n, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->chmconf[channel].conf0.div_cnt_m = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf0, div_cnt_m, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->chnconf0[channel].div_cnt_n; + return HAL_FORCE_READ_U32_REG_FIELD(dev->chnconf0[channel], div_cnt_n); } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->chmconf[channel].conf0.div_cnt_m; + return HAL_FORCE_READ_U32_REG_FIELD(dev->chmconf[channel].conf0, div_cnt_m); } static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -230,7 +231,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->chmconf[channel].conf1.rx_filter_thres_m = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf1, rx_filter_thres_m, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -440,14 +441,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks ) { - *high_ticks = dev->chncarrier_duty[channel].carrier_high_chn; - *low_ticks = dev->chncarrier_duty[channel].carrier_low_chn; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_high_chn); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_low_chn); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->chm_rx_carrier_rm[channel].carrier_high_thres_chm; - *low_ticks = dev->chm_rx_carrier_rm[channel].carrier_low_thres_chm; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_high_thres_chm); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_low_thres_chm); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32s3/include/hal/rtc_io_ll.h b/components/hal/esp32s3/include/hal/rtc_io_ll.h index 22990e6504..bde6bf3c66 100644 --- a/components/hal/esp32s3/include/hal/rtc_io_ll.h +++ b/components/hal/esp32s3/include/hal/rtc_io_ll.h @@ -22,6 +22,7 @@ #include #include "soc/rtc_io_periph.h" +#include "soc/rtc_io_struct.h" #include "hal/rtc_io_types.h" #include "hal/gpio_types.h" diff --git a/components/hal/esp32s3/include/hal/rwdt_ll.h b/components/hal/esp32s3/include/hal/rwdt_ll.h index 57af63721b..da716126ff 100644 --- a/components/hal/esp32s3/include/hal/rwdt_ll.h +++ b/components/hal/esp32s3/include/hal/rwdt_ll.h @@ -25,6 +25,7 @@ extern "C" { #include #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -259,7 +260,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t *hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32s3/include/hal/sigmadelta_ll.h b/components/hal/esp32s3/include/hal/sigmadelta_ll.h index 99d75853c5..ecae8cf352 100644 --- a/components/hal/esp32s3/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32s3/include/hal/sigmadelta_ll.h @@ -23,7 +23,9 @@ #include #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint8_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index c67cf1351c..bc4a68b6bf 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -27,6 +27,7 @@ #include "esp_attr.h" #include "esp_types.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -915,13 +916,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -938,7 +939,7 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32s3/include/hal/spimem_flash_ll.h b/components/hal/esp32s3/include/hal/spimem_flash_ll.h index 098c14c4c2..d435cbfaf7 100644 --- a/components/hal/esp32s3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s3/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -157,7 +158,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_ctrl.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_pes_command, sus_cmd); } /** @@ -169,7 +170,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_ctrl.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_per_command, res_cmd); } /** @@ -226,7 +227,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; // Set the command to send, to fetch flash status reg value. + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); // Set the command to send, to fetch flash status reg value. dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function. } diff --git a/components/hal/esp32s3/include/hal/timer_ll.h b/components/hal/esp32s3/include/hal/timer_ll.h index de95e437ea..36288f7887 100644 --- a/components/hal/esp32s3/include/hal/timer_ll.h +++ b/components/hal/esp32s3/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -55,7 +57,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u } int timer_en = hw->hw_timer[timer_num].config.tn_en; hw->hw_timer[timer_num].config.tn_en = 0; - hw->hw_timer[timer_num].config.tn_divider = divider; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tn_divider, divider); hw->hw_timer[timer_num].config.tn_en = timer_en; } @@ -70,7 +72,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.tn_divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tn_divider); if (d == 0) { d = 65536; } else if (d == 1) { diff --git a/components/hal/esp32s3/include/hal/touch_sensor_ll.h b/components/hal/esp32s3/include/hal/touch_sensor_ll.h index 48d62faf47..1d62690be0 100644 --- a/components/hal/esp32s3/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s3/include/hal/touch_sensor_ll.h @@ -24,7 +24,11 @@ #include #include +#include "hal/misc.h" #include "soc/touch_sensor_periph.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" #include "soc/soc_caps.h" #include "hal/touch_sensor_types.h" @@ -47,9 +51,9 @@ extern "C" { static inline void touch_ll_set_meas_times(uint16_t meas_time) { //The times of charge and discharge in each measure process of touch channels. - RTCCNTL.touch_ctrl1.touch_meas_num = meas_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num, meas_time); //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD - RTCCNTL.touch_ctrl2.touch_xpd_wait = SOC_TOUCH_PAD_MEASURE_WAIT_MAX; //wait volt stable + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl2, touch_xpd_wait, SOC_TOUCH_PAD_MEASURE_WAIT_MAX); //wait volt stable } /** @@ -59,7 +63,7 @@ static inline void touch_ll_set_meas_times(uint16_t meas_time) */ static inline void touch_ll_get_measure_times(uint16_t *meas_time) { - *meas_time = RTCCNTL.touch_ctrl1.touch_meas_num; + *meas_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num); } /** @@ -73,7 +77,7 @@ static inline void touch_ll_get_measure_times(uint16_t *meas_time) static inline void touch_ll_set_sleep_time(uint16_t sleep_time) { // touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK(150k) - RTCCNTL.touch_ctrl1.touch_sleep_cycles = sleep_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles, sleep_time); } /** @@ -83,7 +87,7 @@ static inline void touch_ll_set_sleep_time(uint16_t sleep_time) */ static inline void touch_ll_get_sleep_time(uint16_t *sleep_time) { - *sleep_time = RTCCNTL.touch_ctrl1.touch_sleep_cycles; + *sleep_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles); } /** @@ -990,7 +994,7 @@ static inline void touch_ll_proximity_get_channel_num(touch_pad_t prox_pad[]) */ static inline void touch_ll_proximity_set_meas_times(uint32_t times) { - RTCCNTL.touch_approach.touch_approach_meas_time = times; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time, times); } /** @@ -1000,7 +1004,7 @@ static inline void touch_ll_proximity_set_meas_times(uint32_t times) */ static inline void touch_ll_proximity_get_meas_times(uint32_t *times) { - *times = RTCCNTL.touch_approach.touch_approach_meas_time; + *times = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time); } /** diff --git a/components/hal/esp32s3/include/hal/twai_ll.h b/components/hal/esp32s3/include/hal/twai_ll.h index 62941845a4..e9eef59104 100644 --- a/components/hal/esp32s3/include/hal/twai_ll.h +++ b/components/hal/esp32s3/include/hal/twai_ll.h @@ -31,6 +31,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -399,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -439,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -467,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -486,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -522,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -652,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 5570d58bf3..f437c502e0 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #include "esp_attr.h" #ifdef __cplusplus @@ -149,7 +152,7 @@ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) // an integer part and a fractional part. hw->clkdiv.clkdiv = clk_div >> 4; hw->clkdiv.clkdiv_frag = clk_div & 0xf; - hw->clk_conf.sclk_div_num = sclk_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); #undef DIV_UP } @@ -164,7 +167,8 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw) { uint32_t sclk_freq = uart_ll_get_sclk_freq(hw); uart_clkdiv_reg_t div_reg = hw->clkdiv; - return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * (hw->clk_conf.sclk_div_num + 1)); + return ((sclk_freq << 4)) / + (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * (HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1)); } /** @@ -437,7 +441,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if (break_num > 0) { - hw->txbrk_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->txbrk_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -503,8 +507,8 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -526,11 +530,11 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl */ FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.at_cmd_char = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, at_cmd_char, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -713,8 +717,8 @@ FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.at_cmd_char; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, at_cmd_char); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/platform_port/include/hal/misc.h b/components/hal/platform_port/include/hal/misc.h index 472ec8be2a..3b2f172ab9 100644 --- a/components/hal/platform_port/include/hal/misc.h +++ b/components/hal/platform_port/include/hal/misc.h @@ -16,3 +16,23 @@ #define HAL_SWAP16(d) __builtin_bswap16((d)) #define HAL_SWAP32(d) __builtin_bswap32((d)) #define HAL_SWAP64(d) __builtin_bswap64((d)) + +/** @cond */ //Doxy command to hide preprocessor definitions from docs */ + +// In case the compiler optimise a 32bit instruction (e.g. s32i) into 8/16bit instruction with size optimization enabled +// which is not allowed on s2 and later chips (s2, s3, c3, h2) +// use these wrappers for manually read-modify-write with l32i and s32i + +// modify register as uint32_t +#define HAL_FORCE_MODIFY_U32_REG_FIELD(base_reg, field, val) \ +{ \ + typeof(base_reg) temp_reg = (base_reg); \ + temp_reg.field = (val); \ + (base_reg) = temp_reg; \ +} + +// read register as uint32_t +#define HAL_FORCE_READ_U32_REG_FIELD(base_reg, field) \ +( ((typeof(base_reg))((base_reg).val)).field ) + +/** @endcond */ diff --git a/components/soc/esp32/include/soc/emac_dma_struct.h b/components/soc/esp32/include/soc/emac_dma_struct.h index 35d1361281..1f9a9832e1 100644 --- a/components/soc/esp32/include/soc/emac_dma_struct.h +++ b/components/soc/esp32/include/soc/emac_dma_struct.h @@ -20,7 +20,7 @@ extern "C" #include -typedef volatile struct { +typedef volatile struct emac_dma_dev_s { union { struct { uint32_t sw_rst : 1; /*When this bit is set the MAC DMA Controller resets the logic and all internal registers of the MAC. It is cleared automatically after the reset operation is complete in all of the ETH_MAC clock domains. Before reprogramming any register of the ETH_MAC you should read a zero (0) value in this bit.*/ diff --git a/components/soc/esp32/include/soc/emac_ext_struct.h b/components/soc/esp32/include/soc/emac_ext_struct.h index 9b65c8d91c..5d2e1fecf5 100644 --- a/components/soc/esp32/include/soc/emac_ext_struct.h +++ b/components/soc/esp32/include/soc/emac_ext_struct.h @@ -19,7 +19,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct emac_ext_dev_s { union { struct { uint32_t div_num : 4; diff --git a/components/soc/esp32/include/soc/emac_mac_struct.h b/components/soc/esp32/include/soc/emac_mac_struct.h index b7f5b80ff5..a798b00f99 100644 --- a/components/soc/esp32/include/soc/emac_mac_struct.h +++ b/components/soc/esp32/include/soc/emac_mac_struct.h @@ -19,7 +19,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct emac_mac_dev_s { union { struct { uint32_t pltf : 2; /*These bits control the number of preamble bytes that are added to the beginning of every Transmit frame. The preamble reduction occurs only when the MAC is operating in the full-duplex mode.2'b00: 7 bytes of preamble. 2'b01: 5 bytes of preamble. 2'b10: 3 bytes of preamble.*/ diff --git a/components/soc/esp32/include/soc/i2c_struct.h b/components/soc/esp32/include/soc/i2c_struct.h index 3b17aeb463..7e4afb0601 100644 --- a/components/soc/esp32/include/soc/i2c_struct.h +++ b/components/soc/esp32/include/soc/i2c_struct.h @@ -104,8 +104,8 @@ typedef volatile struct i2c_dev_s { } fifo_conf; union { struct { - uint8_t data; /*The register represent the byte data read from rx_fifo when use apb fifo access*/ - uint8_t reserved[3]; + uint32_t data: 8; /*The register represent the byte data read from rx_fifo when use apb fifo access*/ + uint32_t reserved: 24; }; uint32_t val; } fifo_data; diff --git a/components/soc/esp32/include/soc/pcnt_struct.h b/components/soc/esp32/include/soc/pcnt_struct.h index caeb02ac23..ecb79f3f4f 100644 --- a/components/soc/esp32/include/soc/pcnt_struct.h +++ b/components/soc/esp32/include/soc/pcnt_struct.h @@ -21,7 +21,7 @@ extern "C" { #endif typedef volatile struct pcnt_dev_s { - struct{ + struct { union { struct { uint32_t filter_thres: 10; /*This register is used to filter pulse whose width is smaller than this value for unit0.*/ diff --git a/components/soc/esp32/include/soc/rmt_struct.h b/components/soc/esp32/include/soc/rmt_struct.h index 9736a28a77..fd1815a498 100644 --- a/components/soc/esp32/include/soc/rmt_struct.h +++ b/components/soc/esp32/include/soc/rmt_struct.h @@ -24,7 +24,7 @@ typedef volatile struct rmt_dev_s { uint32_t data_ch[8]; /*The R/W ram address for channel0-7 by apb fifo access. Note that in some circumstances, data read from the FIFO may get lost. As RMT memory area accesses using the RMTMEM method do not have this issue and provide all the functionality that the FIFO register has, it is encouraged to use that instead.*/ - struct{ + struct { union { struct { uint32_t div_cnt: 8; /*This register is used to configure the frequency divider's factor in channel0-7.*/ @@ -250,9 +250,7 @@ typedef struct rmt_item32_s { //Allow access to RMT memory using RMTMEM.chan[0].data32[8] typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[64]; - }; + rmt_item32_t data32[64]; } chan[8]; } rmt_mem_t; extern rmt_mem_t RMTMEM; diff --git a/components/soc/esp32/include/soc/sdmmc_struct.h b/components/soc/esp32/include/soc/sdmmc_struct.h index 8a3bd8fcf6..814a255249 100644 --- a/components/soc/esp32/include/soc/sdmmc_struct.h +++ b/components/soc/esp32/include/soc/sdmmc_struct.h @@ -23,18 +23,22 @@ extern "C" { #endif typedef struct sdmmc_desc_s { - uint32_t reserved1: 1; - uint32_t disable_int_on_completion: 1; - uint32_t last_descriptor: 1; - uint32_t first_descriptor: 1; - uint32_t second_address_chained: 1; - uint32_t end_of_ring: 1; - uint32_t reserved2: 24; - uint32_t card_error_summary: 1; - uint32_t owned_by_idmac: 1; - uint32_t buffer1_size: 13; - uint32_t buffer2_size: 13; - uint32_t reserved3: 6; + struct { + uint32_t reserved1: 1; + uint32_t disable_int_on_completion: 1; + uint32_t last_descriptor: 1; + uint32_t first_descriptor: 1; + uint32_t second_address_chained: 1; + uint32_t end_of_ring: 1; + uint32_t reserved2: 24; + uint32_t card_error_summary: 1; + uint32_t owned_by_idmac: 1; + }; + struct { + uint32_t buffer1_size: 13; + uint32_t buffer2_size: 13; + uint32_t reserved3: 6; + }; void* buffer1_ptr; union { void* buffer2_ptr; @@ -146,8 +150,10 @@ typedef volatile struct sdmmc_dev_s { uint32_t val; } ctype; - uint32_t blksiz: 16; ///< block size, default 0x200 - uint32_t : 16; + struct { + uint32_t blksiz: 16; ///< block size, default 0x200 + uint32_t reserved: 16; + }; uint32_t bytcnt; ///< number of bytes to be transferred @@ -326,6 +332,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t ces: 1; ///< card error summary uint32_t reserved2: 2; uint32_t nis: 1; ///< normal interrupt summary + uint32_t ais: 1; ///< abnormal interrupt summary uint32_t fbe_code: 3; ///< code of fatal bus error uint32_t fsm: 4; ///< DMAC FSM state uint32_t reserved3: 15; @@ -362,6 +369,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t write_thr_en : 1; ///< equivalent of read_thr_en for writes uint32_t reserved1 : 13; uint32_t card_threshold : 12; ///< threshold value for reads/writes, in bytes + uint32_t reserved28: 4; }; uint32_t val; } cardthrctl; @@ -378,6 +386,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t div_factor_p: 4; ///< controls clock period; it will be (div_factor_p + 1) / 160MHz uint32_t div_factor_h: 4; ///< controls length of high pulse; it will be (div_factor_h + 1) / 160MHz uint32_t div_factor_m: 4; ///< should be equal to div_factor_p + uint32_t reserved21: 11; }; uint32_t val; } clock; diff --git a/components/soc/esp32/include/soc/timer_group_struct.h b/components/soc/esp32/include/soc/timer_group_struct.h index 4ea1abe75d..ec43f6d7a3 100644 --- a/components/soc/esp32/include/soc/timer_group_struct.h +++ b/components/soc/esp32/include/soc/timer_group_struct.h @@ -21,7 +21,7 @@ extern "C" { #endif typedef volatile struct timg_dev_s { - struct{ + struct { union { struct { uint32_t reserved0: 10; diff --git a/components/soc/esp32/include/soc/twai_struct.h b/components/soc/esp32/include/soc/twai_struct.h index e9454e1cc5..e4349d33ed 100644 --- a/components/soc/esp32/include/soc/twai_struct.h +++ b/components/soc/esp32/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -60,23 +60,24 @@ typedef volatile struct twai_dev_s { uint32_t ts: 1; /* SR.5 Transmit Status */ uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ @@ -87,70 +88,70 @@ typedef volatile struct twai_dev_s { uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 6; /* BTR0[5:0] Baud Rate Prescaler */ uint32_t sjw: 2; /* BTR0[7:6] Synchronization Jump Width*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -158,47 +159,51 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 3; /* CDR[2:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.3 CLKOUT enable/disable */ - uint32_t reserved3: 3; /* Internal Reserved. RXINTEN and CBP not supported */ + uint32_t reserved4: 3; /* Internal Reserved. RXINTEN and CBP not supported */ uint32_t cm: 1; /* CDR.7 Register Layout. Basic:0 Extended:1 */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved6: 24; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32/include/soc/uart_struct.h b/components/soc/esp32/include/soc/uart_struct.h index 7dc9b5144c..9feb0cb353 100644 --- a/components/soc/esp32/include/soc/uart_struct.h +++ b/components/soc/esp32/include/soc/uart_struct.h @@ -23,8 +23,8 @@ extern "C" { typedef volatile struct uart_dev_s { union { struct { - uint8_t rw_byte; /*This register stores one byte data read by rx fifo.*/ - uint8_t reserved[3]; + uint32_t rw_byte: 8; /*This register stores one byte data read by rx fifo.*/ + uint32_t reserved: 24; }; uint32_t val; } fifo; diff --git a/components/soc/esp32/include/soc/uhci_struct.h b/components/soc/esp32/include/soc/uhci_struct.h index 3f42536c31..764268b35a 100644 --- a/components/soc/esp32/include/soc/uhci_struct.h +++ b/components/soc/esp32/include/soc/uhci_struct.h @@ -277,7 +277,7 @@ typedef volatile struct uhci_dev_s { }; uint32_t val; } quick_sent; - struct{ + struct { uint32_t w_data[2]; /*This register stores the content of short packet's dword*/ } q_data[7]; union { diff --git a/components/soc/esp32c3/include/soc/apb_ctrl_struct.h b/components/soc/esp32c3/include/soc/apb_ctrl_struct.h index 9b832df8dd..dd20d37894 100644 --- a/components/soc/esp32c3/include/soc/apb_ctrl_struct.h +++ b/components/soc/esp32c3/include/soc/apb_ctrl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_ctrl_dev_s { union { struct { uint32_t pre_div: 10; diff --git a/components/soc/esp32c3/include/soc/apb_saradc_struct.h b/components/soc/esp32c3/include/soc/apb_saradc_struct.h index c3ea73f150..c75e582f7d 100644 --- a/components/soc/esp32c3/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32c3/include/soc/apb_saradc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force: 1; diff --git a/components/soc/esp32c3/include/soc/efuse_struct.h b/components/soc/esp32c3/include/soc/efuse_struct.h index 1c51e71475..eed9c2544f 100644 --- a/components/soc/esp32c3/include/soc/efuse_struct.h +++ b/components/soc/esp32c3/include/soc/efuse_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; /*Register 0 that stores data to be programmed.*/ union { struct { diff --git a/components/soc/esp32c3/include/soc/gdma_struct.h b/components/soc/esp32c3/include/soc/gdma_struct.h index 446ff4c112..dde520f5ed 100644 --- a/components/soc/esp32c3/include/soc/gdma_struct.h +++ b/components/soc/esp32c3/include/soc/gdma_struct.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gdma_dev_s { struct { union { struct { diff --git a/components/soc/esp32c3/include/soc/gpio_sd_struct.h b/components/soc/esp32c3/include/soc/gpio_sd_struct.h index cc73cebd03..45e21d58e1 100644 --- a/components/soc/esp32c3/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32c3/include/soc/gpio_sd_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty: 8; diff --git a/components/soc/esp32c3/include/soc/gpio_struct.h b/components/soc/esp32c3/include/soc/gpio_struct.h index f260adbd2a..45f5e55412 100644 --- a/components/soc/esp32c3/include/soc/gpio_struct.h +++ b/components/soc/esp32c3/include/soc/gpio_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; /**/ union { struct { diff --git a/components/soc/esp32c3/include/soc/i2c_struct.h b/components/soc/esp32c3/include/soc/i2c_struct.h index 22c6c47041..ccd5fdb5b0 100644 --- a/components/soc/esp32c3/include/soc/i2c_struct.h +++ b/components/soc/esp32c3/include/soc/i2c_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct i2c_dev_s { union { struct { uint32_t period : 9; diff --git a/components/soc/esp32c3/include/soc/i2s_struct.h b/components/soc/esp32c3/include/soc/i2s_struct.h index 2f9c862b85..44334a8789 100644 --- a/components/soc/esp32c3/include/soc/i2s_struct.h +++ b/components/soc/esp32c3/include/soc/i2s_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32c3/include/soc/ledc_struct.h b/components/soc/esp32c3/include/soc/ledc_struct.h index 9e5a2a96c1..0eb8c18268 100644 --- a/components/soc/esp32c3/include/soc/ledc_struct.h +++ b/components/soc/esp32c3/include/soc/ledc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32c3/include/soc/rmt_struct.h b/components/soc/esp32c3/include/soc/rmt_struct.h index 7fc1890b12..b9b7533b3d 100644 --- a/components/soc/esp32c3/include/soc/rmt_struct.h +++ b/components/soc/esp32c3/include/soc/rmt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rmt_dev_s { uint32_t data_ch[4]; /**/ union { struct { @@ -291,11 +291,9 @@ typedef struct { } rmt_item32_t; //Allow access to RMT memory using RMTMEM.chan[0].data32[8] -typedef volatile struct { +typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[48]; - }; + rmt_item32_t data32[48]; } chan[4]; } rmt_mem_t; diff --git a/components/soc/esp32c3/include/soc/rtc_cntl_struct.h b/components/soc/esp32c3/include/soc/rtc_cntl_struct.h index 358ebaded7..9478048648 100644 --- a/components/soc/esp32c3/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32c3/include/soc/rtc_cntl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0: 2; /*{reg_sw_stall_appcpu_c1[5:0] reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32c3/include/soc/rtc_i2c_struct.h b/components/soc/esp32c3/include/soc/rtc_i2c_struct.h index 5141eebcd6..9f97a70cad 100644 --- a/components/soc/esp32c3/include/soc/rtc_i2c_struct.h +++ b/components/soc/esp32c3/include/soc/rtc_i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_i2c_dev_s { union { struct { uint32_t period: 20; /*time period that scl = 0*/ diff --git a/components/soc/esp32c3/include/soc/sensitive_struct.h b/components/soc/esp32c3/include/soc/sensitive_struct.h index a24ccf6402..ba860e45cd 100644 --- a/components/soc/esp32c3/include/soc/sensitive_struct.h +++ b/components/soc/esp32c3/include/soc/sensitive_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct sensitive_dev_s { union { struct { uint32_t reg_rom_table_lock : 1; /*rom_table_lock*/ @@ -959,8 +959,7 @@ typedef volatile struct { union { struct { uint32_t reg_clk_en : 1; /*clk_en*/ - uint32_t reserved1 : 31; - uint32_t reservedNone : None; /*SENSITIVE_CLOCK_GATE_REG_REG*/ + uint32_t reserved1 : 31; /*SENSITIVE_CLOCK_GATE_REG_REG*/ }; uint32_t val; } clock_gate; diff --git a/components/soc/esp32c3/include/soc/spi_mem_struct.h b/components/soc/esp32c3/include/soc/spi_mem_struct.h index e0f62b0d15..cde08c0207 100644 --- a/components/soc/esp32c3/include/soc/spi_mem_struct.h +++ b/components/soc/esp32c3/include/soc/spi_mem_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_mem_dev_s { union { struct { uint32_t mst_st: 4; /*The current status of SPI1 master FSM.*/ diff --git a/components/soc/esp32c3/include/soc/spi_struct.h b/components/soc/esp32c3/include/soc/spi_struct.h index cc22595dd0..4011c8fed9 100644 --- a/components/soc/esp32c3/include/soc/spi_struct.h +++ b/components/soc/esp32c3/include/soc/spi_struct.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_dev_s { union { struct { uint32_t conf_bitlen : 18; /*Define the APB cycles of SPI_CONF state. Can be configured in CONF state.*/ diff --git a/components/soc/esp32c3/include/soc/syscon_struct.h b/components/soc/esp32c3/include/soc/syscon_struct.h index 2a9485aa87..4be6b7f791 100644 --- a/components/soc/esp32c3/include/soc/syscon_struct.h +++ b/components/soc/esp32c3/include/soc/syscon_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { union { struct { uint32_t apb_ctrl_pre_div_cnt: 10; diff --git a/components/soc/esp32c3/include/soc/system_struct.h b/components/soc/esp32c3/include/soc/system_struct.h index f07fab0aff..5e04cec828 100644 --- a/components/soc/esp32c3/include/soc/system_struct.h +++ b/components/soc/esp32c3/include/soc/system_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct system_dev_s { union { struct { uint32_t reserved0 : 6; /*reserved*/ diff --git a/components/soc/esp32c3/include/soc/systimer_struct.h b/components/soc/esp32c3/include/soc/systimer_struct.h index af41b1f3e2..f10bc1f126 100644 --- a/components/soc/esp32c3/include/soc/systimer_struct.h +++ b/components/soc/esp32c3/include/soc/systimer_struct.h @@ -88,6 +88,7 @@ typedef union { * update timer_unit0 */ uint32_t timer_unit_update: 1; + uint32_t reserved31: 1; }; uint32_t val; } systimer_unit_op_reg_t; @@ -102,6 +103,7 @@ typedef struct { * timer unit load high 32 bit */ uint32_t timer_unit_load_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -126,6 +128,7 @@ typedef struct { * timer target high 32 bit */ uint32_t timer_target_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -172,6 +175,7 @@ typedef struct { * timer read value high 20bit */ uint32_t timer_unit_value_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -195,6 +199,7 @@ typedef union { * timer comp load value */ uint32_t timer_comp_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_comp_load_reg_t; @@ -208,6 +213,7 @@ typedef union { * timer unit load value */ uint32_t timer_unit_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_unit_load_reg_t; @@ -230,6 +236,7 @@ typedef union { * interupt2 enable */ uint32_t target2_int_ena: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -251,6 +258,7 @@ typedef union { * interupt2 raw */ uint32_t target2_int_raw: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -272,6 +280,7 @@ typedef union { * interupt2 clear */ uint32_t target2_int_clr: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_clr_reg_t; @@ -293,6 +302,7 @@ typedef union { * reg_target2_int_st */ uint32_t target2_int_st: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_st_reg_t; diff --git a/components/soc/esp32c3/include/soc/twai_struct.h b/components/soc/esp32c3/include/soc/twai_struct.h index 64cb80e5ed..fafc36393a 100644 --- a/components/soc/esp32c3/include/soc/twai_struct.h +++ b/components/soc/esp32c3/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -61,97 +61,99 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved23: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 13; /* BTR0[12:0] Baud Rate Prescaler */ - uint32_t reserved1: 1; /* Internal Reserved */ + uint32_t reserved13: 1; /* Internal Reserved */ uint32_t sjw: 2; /* BTR0[15:14] Synchronization Jump Width*/ uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -159,45 +161,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32c3/include/soc/uart_struct.h b/components/soc/esp32c3/include/soc/uart_struct.h index ad9ca42ff7..82f8ef6686 100644 --- a/components/soc/esp32c3/include/soc/uart_struct.h +++ b/components/soc/esp32c3/include/soc/uart_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uart_dev_s { union { struct { uint32_t rw_byte; /*a*/ diff --git a/components/soc/esp32c3/include/soc/uhci_struct.h b/components/soc/esp32c3/include/soc/uhci_struct.h index a89c4d0126..164f1a1334 100644 --- a/components/soc/esp32c3/include/soc/uhci_struct.h +++ b/components/soc/esp32c3/include/soc/uhci_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t tx_rst: 1; /*Write 1 then write 0 to this bit to reset decode state machine.*/ diff --git a/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h index 5ae44587a6..c1cfced04b 100644 --- a/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct usb_serial_jtag_dev_s { union { struct { uint32_t rdwr_byte : 32; /*Although only low 8-bits is valid, but change it to 32bits to avoid there's no read/modify/write behaviour*/ /*Write and read byte data to/from UART Tx/Rx FIFO through this field. When USB_SERIAL_JTAG_SERIAL_IN_EMPTY_INT is set then user can write data (up to 64 bytes) into UART Tx FIFO. When USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT is set, user can check USB_SERIAL_JTAG_OUT_EP1_WR_ADDR and USB_SERIAL_JTAG_OUT_EP0_RD_ADDR to know how many data is received, then read that amount of data from UART Rx FIFO. */ diff --git a/components/soc/esp32h2/include/soc/apb_ctrl_struct.h b/components/soc/esp32h2/include/soc/apb_ctrl_struct.h index 53edfec0dd..f97227ca11 100644 --- a/components/soc/esp32h2/include/soc/apb_ctrl_struct.h +++ b/components/soc/esp32h2/include/soc/apb_ctrl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_ctrl_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32h2/include/soc/apb_saradc_struct.h b/components/soc/esp32h2/include/soc/apb_saradc_struct.h index 67242d822d..a286c3c557 100644 --- a/components/soc/esp32h2/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32h2/include/soc/apb_saradc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force: 1; diff --git a/components/soc/esp32h2/include/soc/efuse_struct.h b/components/soc/esp32h2/include/soc/efuse_struct.h index 1c51e71475..eed9c2544f 100644 --- a/components/soc/esp32h2/include/soc/efuse_struct.h +++ b/components/soc/esp32h2/include/soc/efuse_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; /*Register 0 that stores data to be programmed.*/ union { struct { diff --git a/components/soc/esp32h2/include/soc/gdma_struct.h b/components/soc/esp32h2/include/soc/gdma_struct.h index 446ff4c112..dde520f5ed 100644 --- a/components/soc/esp32h2/include/soc/gdma_struct.h +++ b/components/soc/esp32h2/include/soc/gdma_struct.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gdma_dev_s { struct { union { struct { diff --git a/components/soc/esp32h2/include/soc/gpio_sd_struct.h b/components/soc/esp32h2/include/soc/gpio_sd_struct.h index cc73cebd03..45e21d58e1 100644 --- a/components/soc/esp32h2/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32h2/include/soc/gpio_sd_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty: 8; diff --git a/components/soc/esp32h2/include/soc/gpio_struct.h b/components/soc/esp32h2/include/soc/gpio_struct.h index f260adbd2a..45f5e55412 100644 --- a/components/soc/esp32h2/include/soc/gpio_struct.h +++ b/components/soc/esp32h2/include/soc/gpio_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; /**/ union { struct { diff --git a/components/soc/esp32h2/include/soc/i2c_struct.h b/components/soc/esp32h2/include/soc/i2c_struct.h index 22c6c47041..ccd5fdb5b0 100644 --- a/components/soc/esp32h2/include/soc/i2c_struct.h +++ b/components/soc/esp32h2/include/soc/i2c_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct i2c_dev_s { union { struct { uint32_t period : 9; diff --git a/components/soc/esp32h2/include/soc/i2s_struct.h b/components/soc/esp32h2/include/soc/i2s_struct.h index 9d3537004c..9ea88c5a12 100644 --- a/components/soc/esp32h2/include/soc/i2s_struct.h +++ b/components/soc/esp32h2/include/soc/i2s_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32h2/include/soc/ledc_struct.h b/components/soc/esp32h2/include/soc/ledc_struct.h index 9e5a2a96c1..0eb8c18268 100644 --- a/components/soc/esp32h2/include/soc/ledc_struct.h +++ b/components/soc/esp32h2/include/soc/ledc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32h2/include/soc/rmt_struct.h b/components/soc/esp32h2/include/soc/rmt_struct.h index 7fc1890b12..b9b7533b3d 100644 --- a/components/soc/esp32h2/include/soc/rmt_struct.h +++ b/components/soc/esp32h2/include/soc/rmt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rmt_dev_s { uint32_t data_ch[4]; /**/ union { struct { @@ -291,11 +291,9 @@ typedef struct { } rmt_item32_t; //Allow access to RMT memory using RMTMEM.chan[0].data32[8] -typedef volatile struct { +typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[48]; - }; + rmt_item32_t data32[48]; } chan[4]; } rmt_mem_t; diff --git a/components/soc/esp32h2/include/soc/rtc_cntl_struct.h b/components/soc/esp32h2/include/soc/rtc_cntl_struct.h index 68100c9cee..473f236249 100644 --- a/components/soc/esp32h2/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32h2/include/soc/rtc_cntl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0: 2; /*{reg_sw_stall_appcpu_c1[5:0] reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32h2/include/soc/rtc_i2c_struct.h b/components/soc/esp32h2/include/soc/rtc_i2c_struct.h index 5141eebcd6..9f97a70cad 100644 --- a/components/soc/esp32h2/include/soc/rtc_i2c_struct.h +++ b/components/soc/esp32h2/include/soc/rtc_i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_i2c_dev_s { union { struct { uint32_t period: 20; /*time period that scl = 0*/ diff --git a/components/soc/esp32h2/include/soc/sensitive_struct.h b/components/soc/esp32h2/include/soc/sensitive_struct.h index cf27320a79..8747c8a5e0 100644 --- a/components/soc/esp32h2/include/soc/sensitive_struct.h +++ b/components/soc/esp32h2/include/soc/sensitive_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct sensitive_dev_s { union { struct { uint32_t reg_rom_table_lock : 1; /*rom_table_lock*/ diff --git a/components/soc/esp32h2/include/soc/spi_mem_struct.h b/components/soc/esp32h2/include/soc/spi_mem_struct.h index e0f62b0d15..cde08c0207 100644 --- a/components/soc/esp32h2/include/soc/spi_mem_struct.h +++ b/components/soc/esp32h2/include/soc/spi_mem_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_mem_dev_s { union { struct { uint32_t mst_st: 4; /*The current status of SPI1 master FSM.*/ diff --git a/components/soc/esp32h2/include/soc/spi_struct.h b/components/soc/esp32h2/include/soc/spi_struct.h index 867510549d..dcdec116ad 100644 --- a/components/soc/esp32h2/include/soc/spi_struct.h +++ b/components/soc/esp32h2/include/soc/spi_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct spi_dev_s { union { struct { uint32_t conf_bitlen : 18; /*Define the APB cycles of SPI_CONF state. Can be configured in CONF state.*/ diff --git a/components/soc/esp32h2/include/soc/syscon_struct.h b/components/soc/esp32h2/include/soc/syscon_struct.h index e25e44179f..536c28058d 100644 --- a/components/soc/esp32h2/include/soc/syscon_struct.h +++ b/components/soc/esp32h2/include/soc/syscon_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32h2/include/soc/system_struct.h b/components/soc/esp32h2/include/soc/system_struct.h index 58c1c6b99f..8b9d4892bb 100644 --- a/components/soc/esp32h2/include/soc/system_struct.h +++ b/components/soc/esp32h2/include/soc/system_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct system_dev_s { union { struct { uint32_t reserved0 : 6; /*reserved*/ diff --git a/components/soc/esp32h2/include/soc/systimer_struct.h b/components/soc/esp32h2/include/soc/systimer_struct.h index af41b1f3e2..f10bc1f126 100644 --- a/components/soc/esp32h2/include/soc/systimer_struct.h +++ b/components/soc/esp32h2/include/soc/systimer_struct.h @@ -88,6 +88,7 @@ typedef union { * update timer_unit0 */ uint32_t timer_unit_update: 1; + uint32_t reserved31: 1; }; uint32_t val; } systimer_unit_op_reg_t; @@ -102,6 +103,7 @@ typedef struct { * timer unit load high 32 bit */ uint32_t timer_unit_load_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -126,6 +128,7 @@ typedef struct { * timer target high 32 bit */ uint32_t timer_target_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -172,6 +175,7 @@ typedef struct { * timer read value high 20bit */ uint32_t timer_unit_value_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -195,6 +199,7 @@ typedef union { * timer comp load value */ uint32_t timer_comp_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_comp_load_reg_t; @@ -208,6 +213,7 @@ typedef union { * timer unit load value */ uint32_t timer_unit_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_unit_load_reg_t; @@ -230,6 +236,7 @@ typedef union { * interupt2 enable */ uint32_t target2_int_ena: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -251,6 +258,7 @@ typedef union { * interupt2 raw */ uint32_t target2_int_raw: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -272,6 +280,7 @@ typedef union { * interupt2 clear */ uint32_t target2_int_clr: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_clr_reg_t; @@ -293,6 +302,7 @@ typedef union { * reg_target2_int_st */ uint32_t target2_int_st: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_st_reg_t; diff --git a/components/soc/esp32h2/include/soc/twai_struct.h b/components/soc/esp32h2/include/soc/twai_struct.h index a2c72e5afa..8c9b60059c 100644 --- a/components/soc/esp32h2/include/soc/twai_struct.h +++ b/components/soc/esp32h2/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -61,97 +61,99 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved23: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 13; /* BTR0[12:0] Baud Rate Prescaler */ - uint32_t reserved1: 1; /* Internal Reserved */ + uint32_t reserved13: 1; /* Internal Reserved */ uint32_t sjw: 2; /* BTR0[15:14] Synchronization Jump Width*/ uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -159,45 +161,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32h2/include/soc/uart_struct.h b/components/soc/esp32h2/include/soc/uart_struct.h index ad9ca42ff7..82f8ef6686 100644 --- a/components/soc/esp32h2/include/soc/uart_struct.h +++ b/components/soc/esp32h2/include/soc/uart_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uart_dev_s { union { struct { uint32_t rw_byte; /*a*/ diff --git a/components/soc/esp32h2/include/soc/uhci_struct.h b/components/soc/esp32h2/include/soc/uhci_struct.h index a89c4d0126..164f1a1334 100644 --- a/components/soc/esp32h2/include/soc/uhci_struct.h +++ b/components/soc/esp32h2/include/soc/uhci_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t tx_rst: 1; /*Write 1 then write 0 to this bit to reset decode state machine.*/ diff --git a/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h index 72c1005d30..e9e4b8b8ea 100644 --- a/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct usb_serial_jtag_dev_s { union { struct { uint32_t rdwr_byte : 8; /*Write and read byte data to/from UART Tx/Rx FIFO through this field. When USB_SERIAL_JTAG_SERIAL_IN_EMPTY_INT is set then user can write data (up to 64 bytes) into UART Tx FIFO. When USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT is set, user can check USB_SERIAL_JTAG_OUT_EP1_WR_ADDR and USB_SERIAL_JTAG_OUT_EP0_RD_ADDR to know how many data is received, then read that amount of data from UART Rx FIFO. */ diff --git a/components/soc/esp32s2/include/soc/apb_ctrl_struct.h b/components/soc/esp32s2/include/soc/apb_ctrl_struct.h index d05c2c9a00..dbf2e4e3ef 100644 --- a/components/soc/esp32s2/include/soc/apb_ctrl_struct.h +++ b/components/soc/esp32s2/include/soc/apb_ctrl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_ctrl_dev_s { union { struct { uint32_t pre_div: 10; diff --git a/components/soc/esp32s2/include/soc/apb_saradc_struct.h b/components/soc/esp32s2/include/soc/apb_saradc_struct.h index e9811dab60..505596f994 100644 --- a/components/soc/esp32s2/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32s2/include/soc/apb_saradc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force: 1; diff --git a/components/soc/esp32s2/include/soc/cp_dma_struct.h b/components/soc/esp32s2/include/soc/cp_dma_struct.h index 208c82939c..15fb42e451 100644 --- a/components/soc/esp32s2/include/soc/cp_dma_struct.h +++ b/components/soc/esp32s2/include/soc/cp_dma_struct.h @@ -69,6 +69,7 @@ typedef union { * This is the interrupt raw bit. Triggered when crc calculation is done. */ uint32_t dma_crc_done_int_raw: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_raw_reg_t; @@ -123,6 +124,7 @@ typedef union { * cp_crc_done_int_ena is set to 1. */ uint32_t dma_crc_done_int_st: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_st_reg_t; @@ -168,6 +170,7 @@ typedef union { * This is the interrupt enable bit for cp_crc_done_int interrupt. */ uint32_t dma_crc_done_int_ena: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_ena_reg_t; @@ -213,6 +216,7 @@ typedef union { * Set this bit to clear cp_crc_done_int interrupt. */ uint32_t dma_crc_done_int_clr: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_clr_reg_t; @@ -491,6 +495,7 @@ typedef union { * Copy DMA FIFO empty signal. */ uint32_t dma_fifo_empty: 1; + uint32_t reserved24: 8; }; uint32_t val; } cp_dma_in_st_reg_t; @@ -516,6 +521,7 @@ typedef union { * Copy DMA FIFO full signal. */ uint32_t dma_fifo_full: 1; + uint32_t reserved24: 8; }; uint32_t val; } cp_dma_out_st_reg_t; diff --git a/components/soc/esp32s2/include/soc/dedic_gpio_struct.h b/components/soc/esp32s2/include/soc/dedic_gpio_struct.h index 3ccd588b97..04aae779ad 100644 --- a/components/soc/esp32s2/include/soc/dedic_gpio_struct.h +++ b/components/soc/esp32s2/include/soc/dedic_gpio_struct.h @@ -31,6 +31,7 @@ typedef union { * gpio. */ uint32_t gpio_out_drt_vlaue: 8; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_out_drt_reg_t; @@ -49,6 +50,7 @@ typedef union { * channel's output would be masked. */ uint32_t gpio_out_msk: 8; + uint32_t reserved16: 16; }; uint32_t val; } dedic_gpio_out_msk_reg_t; @@ -98,6 +100,7 @@ typedef union { * clear output value; 3: inverse output value. */ uint32_t gpio_out_idv_ch7: 2; + uint32_t reserved16: 16; }; uint32_t val; } dedic_gpio_out_idv_reg_t; @@ -147,6 +150,7 @@ typedef union { * select CPU instructors. */ uint32_t gpio_out_cpu_sel7: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_out_cpu_reg_t; @@ -196,6 +200,7 @@ typedef union { * 3: three clock delay. */ uint32_t gpio_in_dly_ch7: 2; + uint32_t reserved16: 16; }; uint32_t val; } dedic_gpio_in_dly_reg_t; @@ -285,6 +290,7 @@ typedef union { * 6/7: falling and raising edge trigger. */ uint32_t gpio_intr_mode_ch7: 3; + uint32_t reserved24: 8; }; uint32_t val; } dedic_gpio_intr_rcgn_reg_t; @@ -301,6 +307,7 @@ typedef union { * DEDIC_GPIO_OUT_IDV_REG. */ uint32_t gpio_out_status: 8; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_out_scan_reg_t; @@ -314,6 +321,7 @@ typedef union { * gpio in value after configured by DEDIC_GPIO_IN_DLY_REG. */ uint32_t gpio_in_status: 8; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_in_scan_reg_t; @@ -365,6 +373,7 @@ typedef union { * change configured by DEDIC_GPIO_INTR_RCGN_REG. */ uint32_t gpio7_int_raw: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_raw_reg_t; @@ -406,6 +415,7 @@ typedef union { * This enable bit for reg_gpio7_int_st register. */ uint32_t gpio7_int_ena: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_rls_reg_t; @@ -447,6 +457,7 @@ typedef union { * This is the status bit for reg_gpio7_int_raw when reg_gpio7_int_ena is set to 1. */ uint32_t gpio7_int_st: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_st_reg_t; @@ -488,6 +499,7 @@ typedef union { * Set this bit to clear the reg_gpio7_int_raw interrupt. */ uint32_t gpio7_int_clr: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_clr_reg_t; diff --git a/components/soc/esp32s2/include/soc/efuse_struct.h b/components/soc/esp32s2/include/soc/efuse_struct.h index a9679c267c..1ba78a4147 100644 --- a/components/soc/esp32s2/include/soc/efuse_struct.h +++ b/components/soc/esp32s2/include/soc/efuse_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; /**/ union { struct { diff --git a/components/soc/esp32s2/include/soc/gpio_sd_struct.h b/components/soc/esp32s2/include/soc/gpio_sd_struct.h index 6c28df52a8..71131ae881 100644 --- a/components/soc/esp32s2/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32s2/include/soc/gpio_sd_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty: 8; diff --git a/components/soc/esp32s2/include/soc/gpio_struct.h b/components/soc/esp32s2/include/soc/gpio_struct.h index 70e82ee1fe..0dc1efdfda 100644 --- a/components/soc/esp32s2/include/soc/gpio_struct.h +++ b/components/soc/esp32s2/include/soc/gpio_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; /**/ uint32_t out; /**/ uint32_t out_w1ts; /**/ diff --git a/components/soc/esp32s2/include/soc/i2c_struct.h b/components/soc/esp32s2/include/soc/i2c_struct.h index e54038aaea..150384992b 100644 --- a/components/soc/esp32s2/include/soc/i2c_struct.h +++ b/components/soc/esp32s2/include/soc/i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2c_dev_s { union { struct { uint32_t period: 14; diff --git a/components/soc/esp32s2/include/soc/i2s_struct.h b/components/soc/esp32s2/include/soc/i2s_struct.h index 789f2c21c2..99220407e7 100644 --- a/components/soc/esp32s2/include/soc/i2s_struct.h +++ b/components/soc/esp32s2/include/soc/i2s_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; union { diff --git a/components/soc/esp32s2/include/soc/ledc_struct.h b/components/soc/esp32s2/include/soc/ledc_struct.h index a6f02a788b..b38edb0d61 100644 --- a/components/soc/esp32s2/include/soc/ledc_struct.h +++ b/components/soc/esp32s2/include/soc/ledc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32s2/include/soc/rmt_struct.h b/components/soc/esp32s2/include/soc/rmt_struct.h index b92c42a775..5e43004093 100644 --- a/components/soc/esp32s2/include/soc/rmt_struct.h +++ b/components/soc/esp32s2/include/soc/rmt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rmt_dev_s { uint32_t data_ch[4]; /* Data FIFO, Can only be accessed by PeriBus2 */ struct { union { @@ -300,11 +300,9 @@ typedef struct { } rmt_item32_t; //Allow access to RMT memory using RMTMEM.chan[0].data32[8] -typedef volatile struct { +typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[64]; - }; + rmt_item32_t data32[64]; } chan[4]; } rmt_mem_t; extern rmt_mem_t RMTMEM; diff --git a/components/soc/esp32s2/include/soc/rtc_cntl_struct.h b/components/soc/esp32s2/include/soc/rtc_cntl_struct.h index 4a901a3231..695d18c616 100644 --- a/components/soc/esp32s2/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32s2/include/soc/rtc_cntl_struct.h @@ -19,7 +19,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0: 2; /*{reg_sw_stall_appcpu_c1[5:0] reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32s2/include/soc/rtc_i2c_struct.h b/components/soc/esp32s2/include/soc/rtc_i2c_struct.h index 2b9e6532d6..8f46d82fa3 100644 --- a/components/soc/esp32s2/include/soc/rtc_i2c_struct.h +++ b/components/soc/esp32s2/include/soc/rtc_i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_i2c_dev_s { union { struct { uint32_t period: 20; /*time period that scl = 0*/ diff --git a/components/soc/esp32s2/include/soc/rtc_io_struct.h b/components/soc/esp32s2/include/soc/rtc_io_struct.h index c38c9fd4ab..6d4c883ed0 100644 --- a/components/soc/esp32s2/include/soc/rtc_io_struct.h +++ b/components/soc/esp32s2/include/soc/rtc_io_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_io_dev_s { union { struct { uint32_t reserved0: 10; diff --git a/components/soc/esp32s2/include/soc/sens_struct.h b/components/soc/esp32s2/include/soc/sens_struct.h index 5f56714ee6..5a029dd9fe 100644 --- a/components/soc/esp32s2/include/soc/sens_struct.h +++ b/components/soc/esp32s2/include/soc/sens_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct sens_dev_s { union { struct { uint32_t sar1_clk_div: 8; /*clock divider*/ diff --git a/components/soc/esp32s2/include/soc/syscon_struct.h b/components/soc/esp32s2/include/soc/syscon_struct.h index d40e2dff50..f50baa2f9c 100644 --- a/components/soc/esp32s2/include/soc/syscon_struct.h +++ b/components/soc/esp32s2/include/soc/syscon_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { union { struct { uint32_t pre_div: 10; diff --git a/components/soc/esp32s2/include/soc/systimer_struct.h b/components/soc/esp32s2/include/soc/systimer_struct.h index 48b1d79276..23783b39f4 100644 --- a/components/soc/esp32s2/include/soc/systimer_struct.h +++ b/components/soc/esp32s2/include/soc/systimer_struct.h @@ -91,6 +91,7 @@ typedef union { * system timer accumulation step when using PLL */ uint32_t timer_pll_step: 10; + uint32_t reserved20: 12; }; uint32_t val; } systimer_step_reg_t; @@ -201,6 +202,7 @@ typedef union { * system timer target2 interrupt enable */ uint32_t systimer_int2_ena: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -222,6 +224,7 @@ typedef union { * system timer target2 interrupt raw */ uint32_t systimer_int2_raw: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -243,6 +246,7 @@ typedef union { * system timer target2 interrupt clear */ uint32_t systimer_int2_clr: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_clr_reg_t; diff --git a/components/soc/esp32s2/include/soc/twai_struct.h b/components/soc/esp32s2/include/soc/twai_struct.h index 5cba4d409a..00a006501c 100644 --- a/components/soc/esp32s2/include/soc/twai_struct.h +++ b/components/soc/esp32s2/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -61,37 +61,39 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved23: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 14; /* BTR0[13:0] Baud Rate Prescaler */ @@ -99,58 +101,58 @@ typedef volatile struct twai_dev_s { uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -158,45 +160,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32s2/include/soc/uart_struct.h b/components/soc/esp32s2/include/soc/uart_struct.h index a470b6b968..5eb977825b 100644 --- a/components/soc/esp32s2/include/soc/uart_struct.h +++ b/components/soc/esp32s2/include/soc/uart_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uart_dev_s { union { struct { uint32_t rw_byte;/*note: rw_byte is a uint8_t field, however, ESP32-S2 do not support 8 bits read/write*/ diff --git a/components/soc/esp32s2/include/soc/uhci_struct.h b/components/soc/esp32s2/include/soc/uhci_struct.h index aadc2a6303..63cc074161 100644 --- a/components/soc/esp32s2/include/soc/uhci_struct.h +++ b/components/soc/esp32s2/include/soc/uhci_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t in_rst: 1; diff --git a/components/soc/esp32s2/include/soc/usb_wrap_struct.h b/components/soc/esp32s2/include/soc/usb_wrap_struct.h index 147afc3228..c196743ec0 100644 --- a/components/soc/esp32s2/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32s2/include/soc/usb_wrap_struct.h @@ -153,6 +153,7 @@ typedef union { * USB D- rx value in test. */ uint32_t test_rx_dm:1; + uint32_t reserved:25; }; uint32_t val; } usb_wrap_test_conf_reg_t; diff --git a/components/soc/esp32s2/include/soc/usbh_struct.h b/components/soc/esp32s2/include/soc/usbh_struct.h index ace84d7fa9..182a6034d1 100644 --- a/components/soc/esp32s2/include/soc/usbh_struct.h +++ b/components/soc/esp32s2/include/soc/usbh_struct.h @@ -830,7 +830,7 @@ typedef union { uint32_t bbleerr: 1; uint32_t nakintrpt: 1; uint32_t nyetintrpt: 1; - uint32_t reserved16: 16; + uint32_t reserved15: 17; }; uint32_t val; } usb_diepint_reg_t; diff --git a/components/soc/esp32s3/include/soc/apb_ctrl_struct.h b/components/soc/esp32s3/include/soc/apb_ctrl_struct.h index cf4d08a6c8..b47dff1739 100644 --- a/components/soc/esp32s3/include/soc/apb_ctrl_struct.h +++ b/components/soc/esp32s3/include/soc/apb_ctrl_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_ctrl_dev_s { union { struct { uint32_t pre_div : 10; diff --git a/components/soc/esp32s3/include/soc/apb_saradc_struct.h b/components/soc/esp32s3/include/soc/apb_saradc_struct.h index 9c4637e31a..d6684c5387 100644 --- a/components/soc/esp32s3/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32s3/include/soc/apb_saradc_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force : 1; diff --git a/components/soc/esp32s3/include/soc/assist_debug_struct.h b/components/soc/esp32s3/include/soc/assist_debug_struct.h index a9cedd804c..a6152af468 100644 --- a/components/soc/esp32s3/include/soc/assist_debug_struct.h +++ b/components/soc/esp32s3/include/soc/assist_debug_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct assist_debug_dev_s { union { struct { uint32_t core_0_area_dram0_0_rd : 1; diff --git a/components/soc/esp32s3/include/soc/efuse_struct.h b/components/soc/esp32s3/include/soc/efuse_struct.h index 908f07ea64..7002e4ae15 100644 --- a/components/soc/esp32s3/include/soc/efuse_struct.h +++ b/components/soc/esp32s3/include/soc/efuse_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; uint32_t pgm_data1; uint32_t pgm_data2; diff --git a/components/soc/esp32s3/include/soc/extmem_struct.h b/components/soc/esp32s3/include/soc/extmem_struct.h index e27283b702..58ca646294 100644 --- a/components/soc/esp32s3/include/soc/extmem_struct.h +++ b/components/soc/esp32s3/include/soc/extmem_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct extmem_dev_s { union { struct { uint32_t dcache_enable : 1; /*The bit is used to activate the data cache. 0: disable, 1: enable*/ diff --git a/components/soc/esp32s3/include/soc/gdma_struct.h b/components/soc/esp32s3/include/soc/gdma_struct.h index ebb2b79e1d..730333e67d 100644 --- a/components/soc/esp32s3/include/soc/gdma_struct.h +++ b/components/soc/esp32s3/include/soc/gdma_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gdma_dev_s { struct { struct { union { diff --git a/components/soc/esp32s3/include/soc/gpio_sd_struct.h b/components/soc/esp32s3/include/soc/gpio_sd_struct.h index bb71322294..7bb05aafb5 100644 --- a/components/soc/esp32s3/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32s3/include/soc/gpio_sd_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty : 8; diff --git a/components/soc/esp32s3/include/soc/gpio_struct.h b/components/soc/esp32s3/include/soc/gpio_struct.h index cd2711531c..be1c3223dd 100644 --- a/components/soc/esp32s3/include/soc/gpio_struct.h +++ b/components/soc/esp32s3/include/soc/gpio_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; uint32_t out; uint32_t out_w1ts; diff --git a/components/soc/esp32s3/include/soc/hinf_struct.h b/components/soc/esp32s3/include/soc/hinf_struct.h index 7accb59330..965f8bd43c 100644 --- a/components/soc/esp32s3/include/soc/hinf_struct.h +++ b/components/soc/esp32s3/include/soc/hinf_struct.h @@ -20,7 +20,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct hinf_dev_s { union { struct { uint32_t user_id_fn1: 16; diff --git a/components/soc/esp32s3/include/soc/host_struct.h b/components/soc/esp32s3/include/soc/host_struct.h index b6dad107a5..1a6b89e281 100644 --- a/components/soc/esp32s3/include/soc/host_struct.h +++ b/components/soc/esp32s3/include/soc/host_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct host_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32s3/include/soc/i2s_struct.h b/components/soc/esp32s3/include/soc/i2s_struct.h index fc02adc0b8..553580d32c 100644 --- a/components/soc/esp32s3/include/soc/i2s_struct.h +++ b/components/soc/esp32s3/include/soc/i2s_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32s3/include/soc/interrupt_core0_struct.h b/components/soc/esp32s3/include/soc/interrupt_core0_struct.h index 54ff95b47b..aa27462fb0 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core0_struct.h +++ b/components/soc/esp32s3/include/soc/interrupt_core0_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct interrupt_core0_dev_s { union { struct { uint32_t core0_mac_intr_map: 5; diff --git a/components/soc/esp32s3/include/soc/interrupt_core1_struct.h b/components/soc/esp32s3/include/soc/interrupt_core1_struct.h index ba60403aa8..d4dee29ae5 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core1_struct.h +++ b/components/soc/esp32s3/include/soc/interrupt_core1_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct interrupt_core1_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32s3/include/soc/interrupt_struct.h b/components/soc/esp32s3/include/soc/interrupt_struct.h index 48a595047f..03bf5df953 100644 --- a/components/soc/esp32s3/include/soc/interrupt_struct.h +++ b/components/soc/esp32s3/include/soc/interrupt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct interrupt_dev_s { } interrupt_dev_t; extern interrupt_dev_t INTERRUPT; #ifdef __cplusplus diff --git a/components/soc/esp32s3/include/soc/ledc_struct.h b/components/soc/esp32s3/include/soc/ledc_struct.h index 5713035056..85cea78e58 100644 --- a/components/soc/esp32s3/include/soc/ledc_struct.h +++ b/components/soc/esp32s3/include/soc/ledc_struct.h @@ -20,7 +20,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32s3/include/soc/peri_backup_struct.h b/components/soc/esp32s3/include/soc/peri_backup_struct.h index 0561bd4c23..20d6673f2e 100644 --- a/components/soc/esp32s3/include/soc/peri_backup_struct.h +++ b/components/soc/esp32s3/include/soc/peri_backup_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct peri_backup_dev_s { union { struct { uint32_t reg_peri_backup_flow_err : 3; diff --git a/components/soc/esp32s3/include/soc/rmt_struct.h b/components/soc/esp32s3/include/soc/rmt_struct.h index bfdcf33546..275bfebce6 100644 --- a/components/soc/esp32s3/include/soc/rmt_struct.h +++ b/components/soc/esp32s3/include/soc/rmt_struct.h @@ -1103,9 +1103,7 @@ typedef struct { typedef struct { struct { - union { - volatile rmt_item32_t data32[48]; - }; + volatile rmt_item32_t data32[48]; } chan[8]; } rmt_mem_t; diff --git a/components/soc/esp32s3/include/soc/rtc_cntl_struct.h b/components/soc/esp32s3/include/soc/rtc_cntl_struct.h index 32493d8359..d3366dd0f9 100644 --- a/components/soc/esp32s3/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32s3/include/soc/rtc_cntl_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0 : 2; /*{reg_sw_stall_appcpu_c1[5:0], reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32s3/include/soc/rtc_io_struct.h b/components/soc/esp32s3/include/soc/rtc_io_struct.h index c366c65cf2..1154be038b 100644 --- a/components/soc/esp32s3/include/soc/rtc_io_struct.h +++ b/components/soc/esp32s3/include/soc/rtc_io_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_io_dev_s { union { struct { uint32_t reserved0 : 10; diff --git a/components/soc/esp32s3/include/soc/sdmmc_struct.h b/components/soc/esp32s3/include/soc/sdmmc_struct.h index 78b21aa156..599528a34a 100644 --- a/components/soc/esp32s3/include/soc/sdmmc_struct.h +++ b/components/soc/esp32s3/include/soc/sdmmc_struct.h @@ -21,18 +21,22 @@ extern "C" { #endif typedef struct sdmmc_desc_s { - uint32_t reserved1: 1; - uint32_t disable_int_on_completion: 1; - uint32_t last_descriptor: 1; - uint32_t first_descriptor: 1; - uint32_t second_address_chained: 1; - uint32_t end_of_ring: 1; - uint32_t reserved2: 24; - uint32_t card_error_summary: 1; - uint32_t owned_by_idmac: 1; - uint32_t buffer1_size: 13; - uint32_t buffer2_size: 13; - uint32_t reserved3: 6; + struct { + uint32_t reserved1: 1; + uint32_t disable_int_on_completion: 1; + uint32_t last_descriptor: 1; + uint32_t first_descriptor: 1; + uint32_t second_address_chained: 1; + uint32_t end_of_ring: 1; + uint32_t reserved2: 24; + uint32_t card_error_summary: 1; + uint32_t owned_by_idmac: 1; + }; + struct { + uint32_t buffer1_size: 13; + uint32_t buffer2_size: 13; + uint32_t reserved3: 6; + }; void* buffer1_ptr; union { void* buffer2_ptr; @@ -144,8 +148,10 @@ typedef volatile struct sdmmc_dev_s { uint32_t val; } ctype; - uint32_t blksiz: 16; ///< block size, default 0x200 - uint32_t : 16; + struct { + uint32_t blksiz: 16; ///< block size, default 0x200 + uint32_t reserved: 16; + }; uint32_t bytcnt; ///< number of bytes to be transferred @@ -324,6 +330,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t ces: 1; ///< card error summary uint32_t reserved2: 2; uint32_t nis: 1; ///< normal interrupt summary + uint32_t ais: 1; ///< abnormal interrupt summary uint32_t fbe_code: 3; ///< code of fatal bus error uint32_t fsm: 4; ///< DMAC FSM state uint32_t reserved3: 15; @@ -359,7 +366,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t busy_clr_int_en : 1; ///< enable generation of busy clear interrupts uint32_t write_thr_en : 1; ///< equivalent of read_thr_en for writes uint32_t reserved1 : 13; - uint32_t card_threshold : 12; ///< threshold value for reads/writes, in bytes + uint32_t card_threshold : 16; ///< threshold value for reads/writes, in bytes }; uint32_t val; } cardthrctl; @@ -378,6 +385,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t div_factor_m: 4; ///< should be equal to div_factor_p uint32_t reserved1 : 2; uint32_t clk_sel : 1; ///< clock source select (0: XTAL, 1: 160 MHz from PLL) + uint32_t reserved24: 8; }; uint32_t val; } clock; diff --git a/components/soc/esp32s3/include/soc/sens_struct.h b/components/soc/esp32s3/include/soc/sens_struct.h index 915675bf71..3fee23099d 100644 --- a/components/soc/esp32s3/include/soc/sens_struct.h +++ b/components/soc/esp32s3/include/soc/sens_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct sens_dev_s { union { struct { uint32_t sar1_clk_div : 8; /*clock divider*/ diff --git a/components/soc/esp32s3/include/soc/sensitive_struct.h b/components/soc/esp32s3/include/soc/sensitive_struct.h index 69feaf37b2..e9919cb0a6 100644 --- a/components/soc/esp32s3/include/soc/sensitive_struct.h +++ b/components/soc/esp32s3/include/soc/sensitive_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct sensitive_dev_s { union { struct { uint32_t cache_dataarray_connect_lock : 1; diff --git a/components/soc/esp32s3/include/soc/slc_reg.h b/components/soc/esp32s3/include/soc/slc_reg.h deleted file mode 100644 index 31b1a55e59..0000000000 --- a/components/soc/esp32s3/include/soc/slc_reg.h +++ /dev/null @@ -1,1912 +0,0 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _SOC_SLC_REG_H_ -#define _SOC_SLC_REG_H_ - - -#include "soc.h" -#ifdef __cplusplus -extern "C" { -#endif - -#define SLC_SLCCONF0_REG (DR_REG_SLC_BASE + 0x0) -/* SLC_SLC0_WR_RETRY_MASK_EN : R/W ;bitpos:[18] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_MASK_EN (BIT(18)) -#define SLC_SLC0_WR_RETRY_MASK_EN_M (BIT(18)) -#define SLC_SLC0_WR_RETRY_MASK_EN_V 0x1 -#define SLC_SLC0_WR_RETRY_MASK_EN_S 18 -/* SLC_SLC0_TOKEN_SEL : R/W ;bitpos:[15] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN_SEL (BIT(15)) -#define SLC_SLC0_TOKEN_SEL_M (BIT(15)) -#define SLC_SLC0_TOKEN_SEL_V 0x1 -#define SLC_SLC0_TOKEN_SEL_S 15 -/* SLC_SLC0_TOKEN_AUTO_CLR : R/W ;bitpos:[14] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN_AUTO_CLR (BIT(14)) -#define SLC_SLC0_TOKEN_AUTO_CLR_M (BIT(14)) -#define SLC_SLC0_TOKEN_AUTO_CLR_V 0x1 -#define SLC_SLC0_TOKEN_AUTO_CLR_S 14 -/* SLC_SLC0_TXDATA_BURST_EN : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TXDATA_BURST_EN (BIT(13)) -#define SLC_SLC0_TXDATA_BURST_EN_M (BIT(13)) -#define SLC_SLC0_TXDATA_BURST_EN_V 0x1 -#define SLC_SLC0_TXDATA_BURST_EN_S 13 -/* SLC_SLC0_TXDSCR_BURST_EN : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TXDSCR_BURST_EN (BIT(12)) -#define SLC_SLC0_TXDSCR_BURST_EN_M (BIT(12)) -#define SLC_SLC0_TXDSCR_BURST_EN_V 0x1 -#define SLC_SLC0_TXDSCR_BURST_EN_S 12 -/* SLC_SLC0_TXLINK_AUTO_RET : R/W ;bitpos:[11] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_AUTO_RET (BIT(11)) -#define SLC_SLC0_TXLINK_AUTO_RET_M (BIT(11)) -#define SLC_SLC0_TXLINK_AUTO_RET_V 0x1 -#define SLC_SLC0_TXLINK_AUTO_RET_S 11 -/* SLC_SLC0_RXLINK_AUTO_RET : R/W ;bitpos:[10] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_AUTO_RET (BIT(10)) -#define SLC_SLC0_RXLINK_AUTO_RET_M (BIT(10)) -#define SLC_SLC0_RXLINK_AUTO_RET_V 0x1 -#define SLC_SLC0_RXLINK_AUTO_RET_S 10 -/* SLC_SLC0_RXDATA_BURST_EN : R/W ;bitpos:[9] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RXDATA_BURST_EN (BIT(9)) -#define SLC_SLC0_RXDATA_BURST_EN_M (BIT(9)) -#define SLC_SLC0_RXDATA_BURST_EN_V 0x1 -#define SLC_SLC0_RXDATA_BURST_EN_S 9 -/* SLC_SLC0_RXDSCR_BURST_EN : R/W ;bitpos:[8] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RXDSCR_BURST_EN (BIT(8)) -#define SLC_SLC0_RXDSCR_BURST_EN_M (BIT(8)) -#define SLC_SLC0_RXDSCR_BURST_EN_V 0x1 -#define SLC_SLC0_RXDSCR_BURST_EN_S 8 -/* SLC_SLC0_RX_NO_RESTART_CLR : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_NO_RESTART_CLR (BIT(7)) -#define SLC_SLC0_RX_NO_RESTART_CLR_M (BIT(7)) -#define SLC_SLC0_RX_NO_RESTART_CLR_V 0x1 -#define SLC_SLC0_RX_NO_RESTART_CLR_S 7 -/* SLC_SLC0_RX_AUTO_WRBACK : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_AUTO_WRBACK (BIT(6)) -#define SLC_SLC0_RX_AUTO_WRBACK_M (BIT(6)) -#define SLC_SLC0_RX_AUTO_WRBACK_V 0x1 -#define SLC_SLC0_RX_AUTO_WRBACK_S 6 -/* SLC_SLC0_RX_LOOP_TEST : R/W ;bitpos:[5] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_LOOP_TEST (BIT(5)) -#define SLC_SLC0_RX_LOOP_TEST_M (BIT(5)) -#define SLC_SLC0_RX_LOOP_TEST_V 0x1 -#define SLC_SLC0_RX_LOOP_TEST_S 5 -/* SLC_SLC0_TX_LOOP_TEST : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_LOOP_TEST (BIT(4)) -#define SLC_SLC0_TX_LOOP_TEST_M (BIT(4)) -#define SLC_SLC0_TX_LOOP_TEST_V 0x1 -#define SLC_SLC0_TX_LOOP_TEST_S 4 -/* SLC_AHBM_RST : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_AHBM_RST (BIT(3)) -#define SLC_AHBM_RST_M (BIT(3)) -#define SLC_AHBM_RST_V 0x1 -#define SLC_AHBM_RST_S 3 -/* SLC_AHBM_FIFO_RST : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_AHBM_FIFO_RST (BIT(2)) -#define SLC_AHBM_FIFO_RST_M (BIT(2)) -#define SLC_AHBM_FIFO_RST_V 0x1 -#define SLC_AHBM_FIFO_RST_S 2 -/* SLC_SLC0_RX_RST : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_RST (BIT(1)) -#define SLC_SLC0_RX_RST_M (BIT(1)) -#define SLC_SLC0_RX_RST_V 0x1 -#define SLC_SLC0_RX_RST_S 1 -/* SLC_SLC0_TX_RST : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_RST (BIT(0)) -#define SLC_SLC0_TX_RST_M (BIT(0)) -#define SLC_SLC0_TX_RST_V 0x1 -#define SLC_SLC0_TX_RST_S 0 - -#define SLC_INT_RAW_REG (DR_REG_SLC_BASE + 0x4) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_RAW : RO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_S 26 -/* SLC_CMD_DTC_INT_RAW : RO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_RAW (BIT(25)) -#define SLC_CMD_DTC_INT_RAW_M (BIT(25)) -#define SLC_CMD_DTC_INT_RAW_V 0x1 -#define SLC_CMD_DTC_INT_RAW_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_RAW : RO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_RAW (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_RAW_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_RAW_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_RAW : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_RAW : RO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_RAW (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_RAW_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_RAW_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_RAW_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_RAW : RO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_RAW : RO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_RAW : RO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_S 19 -/* SLC_SLC0_TOHOST_INT_RAW : RO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_RAW (BIT(18)) -#define SLC_SLC0_TOHOST_INT_RAW_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_RAW_V 0x1 -#define SLC_SLC0_TOHOST_INT_RAW_S 18 -/* SLC_SLC0_RX_EOF_INT_RAW : RO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_RAW (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_RAW_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_RX_EOF_INT_RAW_S 17 -/* SLC_SLC0_RX_DONE_INT_RAW : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_RAW (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_RAW_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_RAW_V 0x1 -#define SLC_SLC0_RX_DONE_INT_RAW_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_RAW : RO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_RAW (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_RAW_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_RAW_S 15 -/* SLC_SLC0_TX_DONE_INT_RAW : RO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_RAW (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_RAW_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_RAW_V 0x1 -#define SLC_SLC0_TX_DONE_INT_RAW_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_RAW : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_RAW : RO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_S 12 -/* SLC_SLC0_TX_OVF_INT_RAW : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_RAW (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_RAW_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_RAW_V 0x1 -#define SLC_SLC0_TX_OVF_INT_RAW_S 11 -/* SLC_SLC0_RX_UDF_INT_RAW : RO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_RAW (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_RAW_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_RAW_V 0x1 -#define SLC_SLC0_RX_UDF_INT_RAW_S 10 -/* SLC_SLC0_TX_START_INT_RAW : RO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_RAW (BIT(9)) -#define SLC_SLC0_TX_START_INT_RAW_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_RAW_V 0x1 -#define SLC_SLC0_TX_START_INT_RAW_S 9 -/* SLC_SLC0_RX_START_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_RAW (BIT(8)) -#define SLC_SLC0_RX_START_INT_RAW_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_RAW_V 0x1 -#define SLC_SLC0_RX_START_INT_RAW_S 8 -/* SLC_FRHOST_BIT7_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_RAW (BIT(7)) -#define SLC_FRHOST_BIT7_INT_RAW_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT7_INT_RAW_S 7 -/* SLC_FRHOST_BIT6_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_RAW (BIT(6)) -#define SLC_FRHOST_BIT6_INT_RAW_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT6_INT_RAW_S 6 -/* SLC_FRHOST_BIT5_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_RAW (BIT(5)) -#define SLC_FRHOST_BIT5_INT_RAW_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT5_INT_RAW_S 5 -/* SLC_FRHOST_BIT4_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_RAW (BIT(4)) -#define SLC_FRHOST_BIT4_INT_RAW_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT4_INT_RAW_S 4 -/* SLC_FRHOST_BIT3_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_RAW (BIT(3)) -#define SLC_FRHOST_BIT3_INT_RAW_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT3_INT_RAW_S 3 -/* SLC_FRHOST_BIT2_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_RAW (BIT(2)) -#define SLC_FRHOST_BIT2_INT_RAW_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT2_INT_RAW_S 2 -/* SLC_FRHOST_BIT1_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_RAW (BIT(1)) -#define SLC_FRHOST_BIT1_INT_RAW_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT1_INT_RAW_S 1 -/* SLC_FRHOST_BIT0_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_RAW (BIT(0)) -#define SLC_FRHOST_BIT0_INT_RAW_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT0_INT_RAW_S 0 - -#define SLC_INT_ST_REG (DR_REG_SLC_BASE + 0x8) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ST : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ST : RO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ST (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ST_S 26 -/* SLC_CMD_DTC_INT_ST : RO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ST (BIT(25)) -#define SLC_CMD_DTC_INT_ST_M (BIT(25)) -#define SLC_CMD_DTC_INT_ST_V 0x1 -#define SLC_CMD_DTC_INT_ST_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ST : RO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ST (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ST_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ST : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ST (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ST_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ST : RO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ST (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ST_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ST : RO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ST : RO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ST (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ST_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ST : RO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ST (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ST_S 19 -/* SLC_SLC0_TOHOST_INT_ST : RO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ST (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST_V 0x1 -#define SLC_SLC0_TOHOST_INT_ST_S 18 -/* SLC_SLC0_RX_EOF_INT_ST : RO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ST (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ST_S 17 -/* SLC_SLC0_RX_DONE_INT_ST : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ST (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ST_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ST : RO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ST (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ST_S 15 -/* SLC_SLC0_TX_DONE_INT_ST : RO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ST (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ST_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ST (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ST_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ST : RO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ST (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ST_S 12 -/* SLC_SLC0_TX_OVF_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ST (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ST_S 11 -/* SLC_SLC0_RX_UDF_INT_ST : RO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ST (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ST_S 10 -/* SLC_SLC0_TX_START_INT_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ST (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST_V 0x1 -#define SLC_SLC0_TX_START_INT_ST_S 9 -/* SLC_SLC0_RX_START_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ST (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST_V 0x1 -#define SLC_SLC0_RX_START_INT_ST_S 8 -/* SLC_FRHOST_BIT7_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ST (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST_V 0x1 -#define SLC_FRHOST_BIT7_INT_ST_S 7 -/* SLC_FRHOST_BIT6_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ST (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST_V 0x1 -#define SLC_FRHOST_BIT6_INT_ST_S 6 -/* SLC_FRHOST_BIT5_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ST (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST_V 0x1 -#define SLC_FRHOST_BIT5_INT_ST_S 5 -/* SLC_FRHOST_BIT4_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ST (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST_V 0x1 -#define SLC_FRHOST_BIT4_INT_ST_S 4 -/* SLC_FRHOST_BIT3_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ST (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST_V 0x1 -#define SLC_FRHOST_BIT3_INT_ST_S 3 -/* SLC_FRHOST_BIT2_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ST (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST_V 0x1 -#define SLC_FRHOST_BIT2_INT_ST_S 2 -/* SLC_FRHOST_BIT1_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ST (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST_V 0x1 -#define SLC_FRHOST_BIT1_INT_ST_S 1 -/* SLC_FRHOST_BIT0_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ST (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST_V 0x1 -#define SLC_FRHOST_BIT0_INT_ST_S 0 - -#define SLC_INT_ENA_REG (DR_REG_SLC_BASE + 0xC) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA : R/W ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ENA : R/W ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_S 26 -/* SLC_CMD_DTC_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ENA (BIT(25)) -#define SLC_CMD_DTC_INT_ENA_M (BIT(25)) -#define SLC_CMD_DTC_INT_ENA_V 0x1 -#define SLC_CMD_DTC_INT_ENA_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ENA (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ENA_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ENA (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ENA_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_S 19 -/* SLC_SLC0_TOHOST_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ENA (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA_V 0x1 -#define SLC_SLC0_TOHOST_INT_ENA_S 18 -/* SLC_SLC0_RX_EOF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ENA (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ENA_S 17 -/* SLC_SLC0_RX_DONE_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ENA (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ENA_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ENA (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ENA_S 15 -/* SLC_SLC0_TX_DONE_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ENA (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ENA_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_S 12 -/* SLC_SLC0_TX_OVF_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ENA (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ENA_S 11 -/* SLC_SLC0_RX_UDF_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ENA (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ENA_S 10 -/* SLC_SLC0_TX_START_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ENA (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA_V 0x1 -#define SLC_SLC0_TX_START_INT_ENA_S 9 -/* SLC_SLC0_RX_START_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ENA (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA_V 0x1 -#define SLC_SLC0_RX_START_INT_ENA_S 8 -/* SLC_FRHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ENA (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT7_INT_ENA_S 7 -/* SLC_FRHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ENA (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT6_INT_ENA_S 6 -/* SLC_FRHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ENA (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT5_INT_ENA_S 5 -/* SLC_FRHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ENA (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT4_INT_ENA_S 4 -/* SLC_FRHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ENA (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT3_INT_ENA_S 3 -/* SLC_FRHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ENA (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT2_INT_ENA_S 2 -/* SLC_FRHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ENA (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT1_INT_ENA_S 1 -/* SLC_FRHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ENA (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT0_INT_ENA_S 0 - -#define SLC_INT_CLR_REG (DR_REG_SLC_BASE + 0x10) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR : WO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_CLR : WO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_S 26 -/* SLC_CMD_DTC_INT_CLR : WO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_CLR (BIT(25)) -#define SLC_CMD_DTC_INT_CLR_M (BIT(25)) -#define SLC_CMD_DTC_INT_CLR_V 0x1 -#define SLC_CMD_DTC_INT_CLR_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_CLR : WO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_CLR (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_CLR_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_CLR_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_CLR : WO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_CLR : WO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_CLR (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_CLR_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_CLR_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_CLR_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_CLR : WO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_CLR : WO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_CLR : WO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_S 19 -/* SLC_SLC0_TOHOST_INT_CLR : WO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_CLR (BIT(18)) -#define SLC_SLC0_TOHOST_INT_CLR_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_CLR_V 0x1 -#define SLC_SLC0_TOHOST_INT_CLR_S 18 -/* SLC_SLC0_RX_EOF_INT_CLR : WO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_CLR (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_CLR_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_RX_EOF_INT_CLR_S 17 -/* SLC_SLC0_RX_DONE_INT_CLR : WO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_CLR (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_CLR_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_CLR_V 0x1 -#define SLC_SLC0_RX_DONE_INT_CLR_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_CLR : WO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_CLR (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_CLR_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_CLR_S 15 -/* SLC_SLC0_TX_DONE_INT_CLR : WO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_CLR (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_CLR_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_CLR_V 0x1 -#define SLC_SLC0_TX_DONE_INT_CLR_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_CLR : WO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_CLR : WO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_S 12 -/* SLC_SLC0_TX_OVF_INT_CLR : WO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_CLR (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_CLR_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_CLR_V 0x1 -#define SLC_SLC0_TX_OVF_INT_CLR_S 11 -/* SLC_SLC0_RX_UDF_INT_CLR : WO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_CLR (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_CLR_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_CLR_V 0x1 -#define SLC_SLC0_RX_UDF_INT_CLR_S 10 -/* SLC_SLC0_TX_START_INT_CLR : WO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_CLR (BIT(9)) -#define SLC_SLC0_TX_START_INT_CLR_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_CLR_V 0x1 -#define SLC_SLC0_TX_START_INT_CLR_S 9 -/* SLC_SLC0_RX_START_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_CLR (BIT(8)) -#define SLC_SLC0_RX_START_INT_CLR_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_CLR_V 0x1 -#define SLC_SLC0_RX_START_INT_CLR_S 8 -/* SLC_FRHOST_BIT7_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_CLR (BIT(7)) -#define SLC_FRHOST_BIT7_INT_CLR_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT7_INT_CLR_S 7 -/* SLC_FRHOST_BIT6_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_CLR (BIT(6)) -#define SLC_FRHOST_BIT6_INT_CLR_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT6_INT_CLR_S 6 -/* SLC_FRHOST_BIT5_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_CLR (BIT(5)) -#define SLC_FRHOST_BIT5_INT_CLR_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT5_INT_CLR_S 5 -/* SLC_FRHOST_BIT4_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_CLR (BIT(4)) -#define SLC_FRHOST_BIT4_INT_CLR_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT4_INT_CLR_S 4 -/* SLC_FRHOST_BIT3_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_CLR (BIT(3)) -#define SLC_FRHOST_BIT3_INT_CLR_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT3_INT_CLR_S 3 -/* SLC_FRHOST_BIT2_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_CLR (BIT(2)) -#define SLC_FRHOST_BIT2_INT_CLR_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT2_INT_CLR_S 2 -/* SLC_FRHOST_BIT1_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_CLR (BIT(1)) -#define SLC_FRHOST_BIT1_INT_CLR_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT1_INT_CLR_S 1 -/* SLC_FRHOST_BIT0_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_CLR (BIT(0)) -#define SLC_FRHOST_BIT0_INT_CLR_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT0_INT_CLR_S 0 - -#define SLC_SLCRX_STATUS_REG (DR_REG_SLC_BASE + 0x24) -/* SLC_SLC0_RX_BUF_LEN : RO ;bitpos:[13:2] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_BUF_LEN 0x00000FFF -#define SLC_SLC0_RX_BUF_LEN_M ((SLC_SLC0_RX_BUF_LEN_V)<<(SLC_SLC0_RX_BUF_LEN_S)) -#define SLC_SLC0_RX_BUF_LEN_V 0xFFF -#define SLC_SLC0_RX_BUF_LEN_S 2 -/* SLC_SLC0_RX_EMPTY : RO ;bitpos:[1] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EMPTY (BIT(1)) -#define SLC_SLC0_RX_EMPTY_M (BIT(1)) -#define SLC_SLC0_RX_EMPTY_V 0x1 -#define SLC_SLC0_RX_EMPTY_S 1 -/* SLC_SLC0_RX_FULL : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_FULL (BIT(0)) -#define SLC_SLC0_RX_FULL_M (BIT(0)) -#define SLC_SLC0_RX_FULL_V 0x1 -#define SLC_SLC0_RX_FULL_S 0 - -#define SLC_RXFIFO_PUSH_REG (DR_REG_SLC_BASE + 0x28) -/* SLC_SLC0_RXFIFO_PUSH : R/W ;bitpos:[16] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXFIFO_PUSH (BIT(16)) -#define SLC_SLC0_RXFIFO_PUSH_M (BIT(16)) -#define SLC_SLC0_RXFIFO_PUSH_V 0x1 -#define SLC_SLC0_RXFIFO_PUSH_S 16 -/* SLC_SLC0_RXFIFO_WDATA : R/W ;bitpos:[8:0] ;default: 9'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXFIFO_WDATA 0x000001FF -#define SLC_SLC0_RXFIFO_WDATA_M ((SLC_SLC0_RXFIFO_WDATA_V)<<(SLC_SLC0_RXFIFO_WDATA_S)) -#define SLC_SLC0_RXFIFO_WDATA_V 0x1FF -#define SLC_SLC0_RXFIFO_WDATA_S 0 - -#define SLC_SLCTX_STATUS_REG (DR_REG_SLC_BASE + 0x30) -/* SLC_SLC0_TX_EMPTY : RO ;bitpos:[1] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_EMPTY (BIT(1)) -#define SLC_SLC0_TX_EMPTY_M (BIT(1)) -#define SLC_SLC0_TX_EMPTY_V 0x1 -#define SLC_SLC0_TX_EMPTY_S 1 -/* SLC_SLC0_TX_FULL : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_FULL (BIT(0)) -#define SLC_SLC0_TX_FULL_M (BIT(0)) -#define SLC_SLC0_TX_FULL_V 0x1 -#define SLC_SLC0_TX_FULL_S 0 - -#define SLC_TXFIFO_POP_REG (DR_REG_SLC_BASE + 0x34) -/* SLC_SLC0_TXFIFO_POP : R/W ;bitpos:[16] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXFIFO_POP (BIT(16)) -#define SLC_SLC0_TXFIFO_POP_M (BIT(16)) -#define SLC_SLC0_TXFIFO_POP_V 0x1 -#define SLC_SLC0_TXFIFO_POP_S 16 -/* SLC_SLC0_TXFIFO_RDATA : RO ;bitpos:[10:0] ;default: 11'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXFIFO_RDATA 0x000007FF -#define SLC_SLC0_TXFIFO_RDATA_M ((SLC_SLC0_TXFIFO_RDATA_V)<<(SLC_SLC0_TXFIFO_RDATA_S)) -#define SLC_SLC0_TXFIFO_RDATA_V 0x7FF -#define SLC_SLC0_TXFIFO_RDATA_S 0 - -#define SLC_RX_LINK_REG (DR_REG_SLC_BASE + 0x3C) -/* SLC_SLC0_RXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_PARK (BIT(31)) -#define SLC_SLC0_RXLINK_PARK_M (BIT(31)) -#define SLC_SLC0_RXLINK_PARK_V 0x1 -#define SLC_SLC0_RXLINK_PARK_S 31 -/* SLC_SLC0_RXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_RESTART (BIT(30)) -#define SLC_SLC0_RXLINK_RESTART_M (BIT(30)) -#define SLC_SLC0_RXLINK_RESTART_V 0x1 -#define SLC_SLC0_RXLINK_RESTART_S 30 -/* SLC_SLC0_RXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_START (BIT(29)) -#define SLC_SLC0_RXLINK_START_M (BIT(29)) -#define SLC_SLC0_RXLINK_START_V 0x1 -#define SLC_SLC0_RXLINK_START_S 29 -/* SLC_SLC0_RXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_STOP (BIT(28)) -#define SLC_SLC0_RXLINK_STOP_M (BIT(28)) -#define SLC_SLC0_RXLINK_STOP_V 0x1 -#define SLC_SLC0_RXLINK_STOP_S 28 -/* SLC_SLC0_RXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_ADDR 0x000FFFFF -#define SLC_SLC0_RXLINK_ADDR_M ((SLC_SLC0_RXLINK_ADDR_V)<<(SLC_SLC0_RXLINK_ADDR_S)) -#define SLC_SLC0_RXLINK_ADDR_V 0xFFFFF -#define SLC_SLC0_RXLINK_ADDR_S 0 - -#define SLC_TX_LINK_REG (DR_REG_SLC_BASE + 0x40) -/* SLC_SLC0_TXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_PARK (BIT(31)) -#define SLC_SLC0_TXLINK_PARK_M (BIT(31)) -#define SLC_SLC0_TXLINK_PARK_V 0x1 -#define SLC_SLC0_TXLINK_PARK_S 31 -/* SLC_SLC0_TXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_RESTART (BIT(30)) -#define SLC_SLC0_TXLINK_RESTART_M (BIT(30)) -#define SLC_SLC0_TXLINK_RESTART_V 0x1 -#define SLC_SLC0_TXLINK_RESTART_S 30 -/* SLC_SLC0_TXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_START (BIT(29)) -#define SLC_SLC0_TXLINK_START_M (BIT(29)) -#define SLC_SLC0_TXLINK_START_V 0x1 -#define SLC_SLC0_TXLINK_START_S 29 -/* SLC_SLC0_TXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_STOP (BIT(28)) -#define SLC_SLC0_TXLINK_STOP_M (BIT(28)) -#define SLC_SLC0_TXLINK_STOP_V 0x1 -#define SLC_SLC0_TXLINK_STOP_S 28 -/* SLC_SLC0_TXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_ADDR 0x000FFFFF -#define SLC_SLC0_TXLINK_ADDR_M ((SLC_SLC0_TXLINK_ADDR_V)<<(SLC_SLC0_TXLINK_ADDR_S)) -#define SLC_SLC0_TXLINK_ADDR_V 0xFFFFF -#define SLC_SLC0_TXLINK_ADDR_S 0 - -#define SLC_SLCINTVEC_TOHOST_REG (DR_REG_SLC_BASE + 0x4C) -/* SLC_SLC0_TOHOST_INTVEC : WO ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INTVEC 0x000000FF -#define SLC_SLC0_TOHOST_INTVEC_M ((SLC_SLC0_TOHOST_INTVEC_V)<<(SLC_SLC0_TOHOST_INTVEC_S)) -#define SLC_SLC0_TOHOST_INTVEC_V 0xFF -#define SLC_SLC0_TOHOST_INTVEC_S 0 - -#define SLC_TOKEN0_REG (DR_REG_SLC_BASE + 0x50) -/* SLC_SLC0_TOKEN0 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0 0x00000FFF -#define SLC_SLC0_TOKEN0_M ((SLC_SLC0_TOKEN0_V)<<(SLC_SLC0_TOKEN0_S)) -#define SLC_SLC0_TOKEN0_V 0xFFF -#define SLC_SLC0_TOKEN0_S 16 -/* SLC_SLC0_TOKEN0_INC_MORE : WO ;bitpos:[14] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_INC_MORE (BIT(14)) -#define SLC_SLC0_TOKEN0_INC_MORE_M (BIT(14)) -#define SLC_SLC0_TOKEN0_INC_MORE_V 0x1 -#define SLC_SLC0_TOKEN0_INC_MORE_S 14 -/* SLC_SLC0_TOKEN0_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_INC (BIT(13)) -#define SLC_SLC0_TOKEN0_INC_M (BIT(13)) -#define SLC_SLC0_TOKEN0_INC_V 0x1 -#define SLC_SLC0_TOKEN0_INC_S 13 -/* SLC_SLC0_TOKEN0_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_WR (BIT(12)) -#define SLC_SLC0_TOKEN0_WR_M (BIT(12)) -#define SLC_SLC0_TOKEN0_WR_V 0x1 -#define SLC_SLC0_TOKEN0_WR_S 12 -/* SLC_SLC0_TOKEN0_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_WDATA 0x00000FFF -#define SLC_SLC0_TOKEN0_WDATA_M ((SLC_SLC0_TOKEN0_WDATA_V)<<(SLC_SLC0_TOKEN0_WDATA_S)) -#define SLC_SLC0_TOKEN0_WDATA_V 0xFFF -#define SLC_SLC0_TOKEN0_WDATA_S 0 - -#define SLC_TOKEN1_REG (DR_REG_SLC_BASE + 0x54) -/* SLC_SLC0_TOKEN1 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1 0x00000FFF -#define SLC_SLC0_TOKEN1_M ((SLC_SLC0_TOKEN1_V)<<(SLC_SLC0_TOKEN1_S)) -#define SLC_SLC0_TOKEN1_V 0xFFF -#define SLC_SLC0_TOKEN1_S 16 -/* SLC_SLC0_TOKEN1_INC_MORE : WO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_INC_MORE (BIT(14)) -#define SLC_SLC0_TOKEN1_INC_MORE_M (BIT(14)) -#define SLC_SLC0_TOKEN1_INC_MORE_V 0x1 -#define SLC_SLC0_TOKEN1_INC_MORE_S 14 -/* SLC_SLC0_TOKEN1_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_INC (BIT(13)) -#define SLC_SLC0_TOKEN1_INC_M (BIT(13)) -#define SLC_SLC0_TOKEN1_INC_V 0x1 -#define SLC_SLC0_TOKEN1_INC_S 13 -/* SLC_SLC0_TOKEN1_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_WR (BIT(12)) -#define SLC_SLC0_TOKEN1_WR_M (BIT(12)) -#define SLC_SLC0_TOKEN1_WR_V 0x1 -#define SLC_SLC0_TOKEN1_WR_S 12 -/* SLC_SLC0_TOKEN1_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_WDATA 0x00000FFF -#define SLC_SLC0_TOKEN1_WDATA_M ((SLC_SLC0_TOKEN1_WDATA_V)<<(SLC_SLC0_TOKEN1_WDATA_S)) -#define SLC_SLC0_TOKEN1_WDATA_V 0xFFF -#define SLC_SLC0_TOKEN1_WDATA_S 0 - -#define SLC_SLCCONF1_REG (DR_REG_SLC_BASE + 0x60) -/* SLC_CLK_EN : R/W ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CLK_EN (BIT(22)) -#define SLC_CLK_EN_M (BIT(22)) -#define SLC_CLK_EN_V 0x1 -#define SLC_CLK_EN_S 22 -/* SLC_HOST_INT_LEVEL_SEL : R/W ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_HOST_INT_LEVEL_SEL (BIT(19)) -#define SLC_HOST_INT_LEVEL_SEL_M (BIT(19)) -#define SLC_HOST_INT_LEVEL_SEL_V 0x1 -#define SLC_HOST_INT_LEVEL_SEL_S 19 -/* SLC_SLC0_RX_STITCH_EN : R/W ;bitpos:[6] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_STITCH_EN (BIT(6)) -#define SLC_SLC0_RX_STITCH_EN_M (BIT(6)) -#define SLC_SLC0_RX_STITCH_EN_V 0x1 -#define SLC_SLC0_RX_STITCH_EN_S 6 -/* SLC_SLC0_TX_STITCH_EN : R/W ;bitpos:[5] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_STITCH_EN (BIT(5)) -#define SLC_SLC0_TX_STITCH_EN_M (BIT(5)) -#define SLC_SLC0_TX_STITCH_EN_V 0x1 -#define SLC_SLC0_TX_STITCH_EN_S 5 -/* SLC_SLC0_LEN_AUTO_CLR : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_AUTO_CLR (BIT(4)) -#define SLC_SLC0_LEN_AUTO_CLR_M (BIT(4)) -#define SLC_SLC0_LEN_AUTO_CLR_V 0x1 -#define SLC_SLC0_LEN_AUTO_CLR_S 4 -/* SLC_CMD_HOLD_EN : R/W ;bitpos:[3] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_CMD_HOLD_EN (BIT(3)) -#define SLC_CMD_HOLD_EN_M (BIT(3)) -#define SLC_CMD_HOLD_EN_V 0x1 -#define SLC_CMD_HOLD_EN_S 3 -/* SLC_SLC0_RX_CHECK_SUM_EN : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_CHECK_SUM_EN (BIT(2)) -#define SLC_SLC0_RX_CHECK_SUM_EN_M (BIT(2)) -#define SLC_SLC0_RX_CHECK_SUM_EN_V 0x1 -#define SLC_SLC0_RX_CHECK_SUM_EN_S 2 -/* SLC_SLC0_TX_CHECK_SUM_EN : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_CHECK_SUM_EN (BIT(1)) -#define SLC_SLC0_TX_CHECK_SUM_EN_M (BIT(1)) -#define SLC_SLC0_TX_CHECK_SUM_EN_V 0x1 -#define SLC_SLC0_TX_CHECK_SUM_EN_S 1 -/* SLC_SLC0_CHECK_OWNER : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_CHECK_OWNER (BIT(0)) -#define SLC_SLC0_CHECK_OWNER_M (BIT(0)) -#define SLC_SLC0_CHECK_OWNER_V 0x1 -#define SLC_SLC0_CHECK_OWNER_S 0 - -#define SLC_STATE0_REG (DR_REG_SLC_BASE + 0x64) -/* SLC_SLC0_STATE0 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_STATE0 0xFFFFFFFF -#define SLC_SLC0_STATE0_M ((SLC_SLC0_STATE0_V)<<(SLC_SLC0_STATE0_S)) -#define SLC_SLC0_STATE0_V 0xFFFFFFFF -#define SLC_SLC0_STATE0_S 0 - -#define SLC_STATE1_REG (DR_REG_SLC_BASE + 0x68) -/* SLC_SLC0_STATE1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_STATE1 0xFFFFFFFF -#define SLC_SLC0_STATE1_M ((SLC_SLC0_STATE1_V)<<(SLC_SLC0_STATE1_S)) -#define SLC_SLC0_STATE1_V 0xFFFFFFFF -#define SLC_SLC0_STATE1_S 0 - -#define SLC_SLCBRIDGE_CONF_REG (DR_REG_SLC_BASE + 0x74) -/* SLC_TX_PUSH_IDLE_NUM : R/W ;bitpos:[31:16] ;default: 16'ha ; */ -/*description: .*/ -#define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF -#define SLC_TX_PUSH_IDLE_NUM_M ((SLC_TX_PUSH_IDLE_NUM_V)<<(SLC_TX_PUSH_IDLE_NUM_S)) -#define SLC_TX_PUSH_IDLE_NUM_V 0xFFFF -#define SLC_TX_PUSH_IDLE_NUM_S 16 -/* SLC_HDA_MAP_128K : R/W ;bitpos:[13] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_HDA_MAP_128K (BIT(13)) -#define SLC_HDA_MAP_128K_M (BIT(13)) -#define SLC_HDA_MAP_128K_V 0x1 -#define SLC_HDA_MAP_128K_S 13 -/* SLC_SLC0_TX_DUMMY_MODE : R/W ;bitpos:[12] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DUMMY_MODE (BIT(12)) -#define SLC_SLC0_TX_DUMMY_MODE_M (BIT(12)) -#define SLC_SLC0_TX_DUMMY_MODE_V 0x1 -#define SLC_SLC0_TX_DUMMY_MODE_S 12 -/* SLC_FIFO_MAP_ENA : R/W ;bitpos:[11:8] ;default: 4'h7 ; */ -/*description: .*/ -#define SLC_FIFO_MAP_ENA 0x0000000F -#define SLC_FIFO_MAP_ENA_M ((SLC_FIFO_MAP_ENA_V)<<(SLC_FIFO_MAP_ENA_S)) -#define SLC_FIFO_MAP_ENA_V 0xF -#define SLC_FIFO_MAP_ENA_S 8 -/* SLC_TXEOF_ENA : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: .*/ -#define SLC_TXEOF_ENA 0x0000003F -#define SLC_TXEOF_ENA_M ((SLC_TXEOF_ENA_V)<<(SLC_TXEOF_ENA_S)) -#define SLC_TXEOF_ENA_V 0x3F -#define SLC_TXEOF_ENA_S 0 - -#define SLC_TO_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x78) -/* SLC_SLC0_TO_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TO_EOF_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_DES_ADDR_M ((SLC_SLC0_TO_EOF_DES_ADDR_V)<<(SLC_SLC0_TO_EOF_DES_ADDR_S)) -#define SLC_SLC0_TO_EOF_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_DES_ADDR_S 0 - -#define SLC_TX_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x7C) -/* SLC_SLC0_TX_SUC_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_M ((SLC_SLC0_TX_SUC_EOF_DES_ADDR_V)<<(SLC_SLC0_TX_SUC_EOF_DES_ADDR_S)) -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_S 0 - -#define SLC_TO_EOF_BFR_DES_ADDR_REG (DR_REG_SLC_BASE + 0x80) -/* SLC_SLC0_TO_EOF_BFR_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_M ((SLC_SLC0_TO_EOF_BFR_DES_ADDR_V)<<(SLC_SLC0_TO_EOF_BFR_DES_ADDR_S)) -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_S 0 - -#define SLC_AHB_TEST_REG (DR_REG_SLC_BASE + 0x90) -/* SLC_AHB_TESTADDR : R/W ;bitpos:[5:4] ;default: 2'b0 ; */ -/*description: .*/ -#define SLC_AHB_TESTADDR 0x00000003 -#define SLC_AHB_TESTADDR_M ((SLC_AHB_TESTADDR_V)<<(SLC_AHB_TESTADDR_S)) -#define SLC_AHB_TESTADDR_V 0x3 -#define SLC_AHB_TESTADDR_S 4 -/* SLC_AHB_TESTMODE : R/W ;bitpos:[2:0] ;default: 3'b0 ; */ -/*description: .*/ -#define SLC_AHB_TESTMODE 0x00000007 -#define SLC_AHB_TESTMODE_M ((SLC_AHB_TESTMODE_V)<<(SLC_AHB_TESTMODE_S)) -#define SLC_AHB_TESTMODE_V 0x7 -#define SLC_AHB_TESTMODE_S 0 - -#define SLC_SDIO_ST_REG (DR_REG_SLC_BASE + 0x94) -/* SLC_FUNC1_ACC_STATE : RO ;bitpos:[20:16] ;default: 5'b0 ; */ -/*description: .*/ -#define SLC_FUNC1_ACC_STATE 0x0000001F -#define SLC_FUNC1_ACC_STATE_M ((SLC_FUNC1_ACC_STATE_V)<<(SLC_FUNC1_ACC_STATE_S)) -#define SLC_FUNC1_ACC_STATE_V 0x1F -#define SLC_FUNC1_ACC_STATE_S 16 -/* SLC_BUS_ST : RO ;bitpos:[14:12] ;default: 3'b0 ; */ -/*description: .*/ -#define SLC_BUS_ST 0x00000007 -#define SLC_BUS_ST_M ((SLC_BUS_ST_V)<<(SLC_BUS_ST_S)) -#define SLC_BUS_ST_V 0x7 -#define SLC_BUS_ST_S 12 -/* SLC_SDIO_WAKEUP : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SDIO_WAKEUP (BIT(8)) -#define SLC_SDIO_WAKEUP_M (BIT(8)) -#define SLC_SDIO_WAKEUP_V 0x1 -#define SLC_SDIO_WAKEUP_S 8 -/* SLC_FUNC_ST : RO ;bitpos:[7:4] ;default: 4'b0 ; */ -/*description: .*/ -#define SLC_FUNC_ST 0x0000000F -#define SLC_FUNC_ST_M ((SLC_FUNC_ST_V)<<(SLC_FUNC_ST_S)) -#define SLC_FUNC_ST_V 0xF -#define SLC_FUNC_ST_S 4 -/* SLC_CMD_ST : RO ;bitpos:[2:0] ;default: 3'b0 ; */ -/*description: .*/ -#define SLC_CMD_ST 0x00000007 -#define SLC_CMD_ST_M ((SLC_CMD_ST_V)<<(SLC_CMD_ST_S)) -#define SLC_CMD_ST_V 0x7 -#define SLC_CMD_ST_S 0 - -#define SLC_RX_DSCR_CONF_REG (DR_REG_SLC_BASE + 0x98) -/* SLC_SLC0_RD_RETRY_THRESHOLD : R/W ;bitpos:[15:5] ;default: 11'h80 ; */ -/*description: .*/ -#define SLC_SLC0_RD_RETRY_THRESHOLD 0x000007FF -#define SLC_SLC0_RD_RETRY_THRESHOLD_M ((SLC_SLC0_RD_RETRY_THRESHOLD_V)<<(SLC_SLC0_RD_RETRY_THRESHOLD_S)) -#define SLC_SLC0_RD_RETRY_THRESHOLD_V 0x7FF -#define SLC_SLC0_RD_RETRY_THRESHOLD_S 5 -/* SLC_SLC0_RX_FILL_EN : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_FILL_EN (BIT(4)) -#define SLC_SLC0_RX_FILL_EN_M (BIT(4)) -#define SLC_SLC0_RX_FILL_EN_V 0x1 -#define SLC_SLC0_RX_FILL_EN_S 4 -/* SLC_SLC0_RX_EOF_MODE : R/W ;bitpos:[3] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_MODE (BIT(3)) -#define SLC_SLC0_RX_EOF_MODE_M (BIT(3)) -#define SLC_SLC0_RX_EOF_MODE_V 0x1 -#define SLC_SLC0_RX_EOF_MODE_S 3 -/* SLC_SLC0_RX_FILL_MODE : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_FILL_MODE (BIT(2)) -#define SLC_SLC0_RX_FILL_MODE_M (BIT(2)) -#define SLC_SLC0_RX_FILL_MODE_V 0x1 -#define SLC_SLC0_RX_FILL_MODE_S 2 -/* SLC_SLC0_INFOR_NO_REPLACE : R/W ;bitpos:[1] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_INFOR_NO_REPLACE (BIT(1)) -#define SLC_SLC0_INFOR_NO_REPLACE_M (BIT(1)) -#define SLC_SLC0_INFOR_NO_REPLACE_V 0x1 -#define SLC_SLC0_INFOR_NO_REPLACE_S 1 -/* SLC_SLC0_TOKEN_NO_REPLACE : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN_NO_REPLACE (BIT(0)) -#define SLC_SLC0_TOKEN_NO_REPLACE_M (BIT(0)) -#define SLC_SLC0_TOKEN_NO_REPLACE_V 0x1 -#define SLC_SLC0_TOKEN_NO_REPLACE_S 0 - -#define SLC_TXLINK_DSCR_REG (DR_REG_SLC_BASE + 0x9C) -/* SLC_SLC0_TXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_DSCR 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_M ((SLC_SLC0_TXLINK_DSCR_V)<<(SLC_SLC0_TXLINK_DSCR_S)) -#define SLC_SLC0_TXLINK_DSCR_V 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_S 0 - -#define SLC_TXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xA0) -/* SLC_SLC0_TXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_DSCR_BF0 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF0_M ((SLC_SLC0_TXLINK_DSCR_BF0_V)<<(SLC_SLC0_TXLINK_DSCR_BF0_S)) -#define SLC_SLC0_TXLINK_DSCR_BF0_V 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF0_S 0 - -#define SLC_TXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xA4) -/* SLC_SLC0_TXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_DSCR_BF1 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF1_M ((SLC_SLC0_TXLINK_DSCR_BF1_V)<<(SLC_SLC0_TXLINK_DSCR_BF1_S)) -#define SLC_SLC0_TXLINK_DSCR_BF1_V 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF1_S 0 - -#define SLC_RXLINK_DSCR_REG (DR_REG_SLC_BASE + 0xA8) -/* SLC_SLC0_RXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_DSCR 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_M ((SLC_SLC0_RXLINK_DSCR_V)<<(SLC_SLC0_RXLINK_DSCR_S)) -#define SLC_SLC0_RXLINK_DSCR_V 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_S 0 - -#define SLC_RXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xAC) -/* SLC_SLC0_RXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_DSCR_BF0 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF0_M ((SLC_SLC0_RXLINK_DSCR_BF0_V)<<(SLC_SLC0_RXLINK_DSCR_BF0_S)) -#define SLC_SLC0_RXLINK_DSCR_BF0_V 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF0_S 0 - -#define SLC_RXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xB0) -/* SLC_SLC0_RXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_DSCR_BF1 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF1_M ((SLC_SLC0_RXLINK_DSCR_BF1_V)<<(SLC_SLC0_RXLINK_DSCR_BF1_S)) -#define SLC_SLC0_RXLINK_DSCR_BF1_V 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF1_S 0 - -#define SLC_TX_ERREOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0xCC) -/* SLC_SLC0_TX_ERR_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_M ((SLC_SLC0_TX_ERR_EOF_DES_ADDR_V)<<(SLC_SLC0_TX_ERR_EOF_DES_ADDR_S)) -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_S 0 - -#define SLC_TOKEN_LAT_REG (DR_REG_SLC_BASE + 0xD4) -/* SLC_SLC0_TOKEN : RO ;bitpos:[11:0] ;default: 12'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN 0x00000FFF -#define SLC_SLC0_TOKEN_M ((SLC_SLC0_TOKEN_V)<<(SLC_SLC0_TOKEN_S)) -#define SLC_SLC0_TOKEN_V 0xFFF -#define SLC_SLC0_TOKEN_S 0 - -#define SLC_TX_DSCR_CONF_REG (DR_REG_SLC_BASE + 0xD8) -/* SLC_WR_RETRY_THRESHOLD : R/W ;bitpos:[10:0] ;default: 11'h80 ; */ -/*description: .*/ -#define SLC_WR_RETRY_THRESHOLD 0x000007FF -#define SLC_WR_RETRY_THRESHOLD_M ((SLC_WR_RETRY_THRESHOLD_V)<<(SLC_WR_RETRY_THRESHOLD_S)) -#define SLC_WR_RETRY_THRESHOLD_V 0x7FF -#define SLC_WR_RETRY_THRESHOLD_S 0 - -#define SLC_CMD_INFOR0_REG (DR_REG_SLC_BASE + 0xDC) -/* SLC_CMD_CONTENT0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_CMD_CONTENT0 0xFFFFFFFF -#define SLC_CMD_CONTENT0_M ((SLC_CMD_CONTENT0_V)<<(SLC_CMD_CONTENT0_S)) -#define SLC_CMD_CONTENT0_V 0xFFFFFFFF -#define SLC_CMD_CONTENT0_S 0 - -#define SLC_CMD_INFOR1_REG (DR_REG_SLC_BASE + 0xE0) -/* SLC_CMD_CONTENT1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_CMD_CONTENT1 0xFFFFFFFF -#define SLC_CMD_CONTENT1_M ((SLC_CMD_CONTENT1_V)<<(SLC_CMD_CONTENT1_S)) -#define SLC_CMD_CONTENT1_V 0xFFFFFFFF -#define SLC_CMD_CONTENT1_S 0 - -#define SLC_LEN_CONF_REG (DR_REG_SLC_BASE + 0xE4) -/* SLC_SLC0_TX_NEW_PKT_IND : RO ;bitpos:[28] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_NEW_PKT_IND (BIT(28)) -#define SLC_SLC0_TX_NEW_PKT_IND_M (BIT(28)) -#define SLC_SLC0_TX_NEW_PKT_IND_V 0x1 -#define SLC_SLC0_TX_NEW_PKT_IND_S 28 -/* SLC_SLC0_RX_NEW_PKT_IND : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_NEW_PKT_IND (BIT(27)) -#define SLC_SLC0_RX_NEW_PKT_IND_M (BIT(27)) -#define SLC_SLC0_RX_NEW_PKT_IND_V 0x1 -#define SLC_SLC0_RX_NEW_PKT_IND_S 27 -/* SLC_SLC0_TX_GET_USED_DSCR : WO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_GET_USED_DSCR (BIT(26)) -#define SLC_SLC0_TX_GET_USED_DSCR_M (BIT(26)) -#define SLC_SLC0_TX_GET_USED_DSCR_V 0x1 -#define SLC_SLC0_TX_GET_USED_DSCR_S 26 -/* SLC_SLC0_RX_GET_USED_DSCR : WO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_GET_USED_DSCR (BIT(25)) -#define SLC_SLC0_RX_GET_USED_DSCR_M (BIT(25)) -#define SLC_SLC0_RX_GET_USED_DSCR_V 0x1 -#define SLC_SLC0_RX_GET_USED_DSCR_S 25 -/* SLC_SLC0_TX_PACKET_LOAD_EN : R/W ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PACKET_LOAD_EN (BIT(24)) -#define SLC_SLC0_TX_PACKET_LOAD_EN_M (BIT(24)) -#define SLC_SLC0_TX_PACKET_LOAD_EN_V 0x1 -#define SLC_SLC0_TX_PACKET_LOAD_EN_S 24 -/* SLC_SLC0_RX_PACKET_LOAD_EN : R/W ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PACKET_LOAD_EN (BIT(23)) -#define SLC_SLC0_RX_PACKET_LOAD_EN_M (BIT(23)) -#define SLC_SLC0_RX_PACKET_LOAD_EN_V 0x1 -#define SLC_SLC0_RX_PACKET_LOAD_EN_S 23 -/* SLC_SLC0_LEN_INC_MORE : WO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_INC_MORE (BIT(22)) -#define SLC_SLC0_LEN_INC_MORE_M (BIT(22)) -#define SLC_SLC0_LEN_INC_MORE_V 0x1 -#define SLC_SLC0_LEN_INC_MORE_S 22 -/* SLC_SLC0_LEN_INC : WO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_INC (BIT(21)) -#define SLC_SLC0_LEN_INC_M (BIT(21)) -#define SLC_SLC0_LEN_INC_V 0x1 -#define SLC_SLC0_LEN_INC_S 21 -/* SLC_SLC0_LEN_WR : WO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_WR (BIT(20)) -#define SLC_SLC0_LEN_WR_M (BIT(20)) -#define SLC_SLC0_LEN_WR_V 0x1 -#define SLC_SLC0_LEN_WR_S 20 -/* SLC_SLC0_LEN_WDATA : WO ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_WDATA 0x000FFFFF -#define SLC_SLC0_LEN_WDATA_M ((SLC_SLC0_LEN_WDATA_V)<<(SLC_SLC0_LEN_WDATA_S)) -#define SLC_SLC0_LEN_WDATA_V 0xFFFFF -#define SLC_SLC0_LEN_WDATA_S 0 - -#define SLC_LENGTH_REG (DR_REG_SLC_BASE + 0xE8) -/* SLC_SLC0_LEN : RO ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN 0x000FFFFF -#define SLC_SLC0_LEN_M ((SLC_SLC0_LEN_V)<<(SLC_SLC0_LEN_S)) -#define SLC_SLC0_LEN_V 0xFFFFF -#define SLC_SLC0_LEN_S 0 - -#define SLC_TXPKT_H_DSCR_REG (DR_REG_SLC_BASE + 0xEC) -/* SLC_SLC0_TX_PKT_H_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_H_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_H_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_S 0 - -#define SLC_TXPKT_E_DSCR_REG (DR_REG_SLC_BASE + 0xF0) -/* SLC_SLC0_TX_PKT_E_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_E_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_E_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_S 0 - -#define SLC_RXPKT_H_DSCR_REG (DR_REG_SLC_BASE + 0xF4) -/* SLC_SLC0_RX_PKT_H_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_H_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_H_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_S 0 - -#define SLC_RXPKT_E_DSCR_REG (DR_REG_SLC_BASE + 0xF8) -/* SLC_SLC0_RX_PKT_E_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_E_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_E_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_S 0 - -#define SLC_TXPKTU_H_DSCR_REG (DR_REG_SLC_BASE + 0xFC) -/* SLC_SLC0_TX_PKT_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_START_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_START_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_S 0 - -#define SLC_TXPKTU_E_DSCR_REG (DR_REG_SLC_BASE + 0x100) -/* SLC_SLC0_TX_PKT_END_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_END_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_END_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_S 0 - -#define SLC_RXPKTU_H_DSCR_REG (DR_REG_SLC_BASE + 0x104) -/* SLC_SLC0_RX_PKT_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_START_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_START_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_S 0 - -#define SLC_RXPKTU_E_DSCR_REG (DR_REG_SLC_BASE + 0x108) -/* SLC_SLC0_RX_PKT_END_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_END_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_END_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_S 0 - -#define SLC_SEQ_POSITION_REG (DR_REG_SLC_BASE + 0x114) -/* SLC_SLC0_SEQ_POSITION : R/W ;bitpos:[7:0] ;default: 8'h9 ; */ -/*description: .*/ -#define SLC_SLC0_SEQ_POSITION 0x000000FF -#define SLC_SLC0_SEQ_POSITION_M ((SLC_SLC0_SEQ_POSITION_V)<<(SLC_SLC0_SEQ_POSITION_S)) -#define SLC_SLC0_SEQ_POSITION_V 0xFF -#define SLC_SLC0_SEQ_POSITION_S 0 - -#define SLC_DSCR_REC_CONF_REG (DR_REG_SLC_BASE + 0x118) -/* SLC_SLC0_RX_DSCR_REC_LIM : R/W ;bitpos:[9:0] ;default: 10'h3ff ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_REC_LIM 0x000003FF -#define SLC_SLC0_RX_DSCR_REC_LIM_M ((SLC_SLC0_RX_DSCR_REC_LIM_V)<<(SLC_SLC0_RX_DSCR_REC_LIM_S)) -#define SLC_SLC0_RX_DSCR_REC_LIM_V 0x3FF -#define SLC_SLC0_RX_DSCR_REC_LIM_S 0 - -#define SLC_SDIO_CRC_ST0_REG (DR_REG_SLC_BASE + 0x11C) -/* SLC_DAT3_CRC_ERR_CNT : RO ;bitpos:[31:24] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT3_CRC_ERR_CNT 0x000000FF -#define SLC_DAT3_CRC_ERR_CNT_M ((SLC_DAT3_CRC_ERR_CNT_V)<<(SLC_DAT3_CRC_ERR_CNT_S)) -#define SLC_DAT3_CRC_ERR_CNT_V 0xFF -#define SLC_DAT3_CRC_ERR_CNT_S 24 -/* SLC_DAT2_CRC_ERR_CNT : RO ;bitpos:[23:16] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT2_CRC_ERR_CNT 0x000000FF -#define SLC_DAT2_CRC_ERR_CNT_M ((SLC_DAT2_CRC_ERR_CNT_V)<<(SLC_DAT2_CRC_ERR_CNT_S)) -#define SLC_DAT2_CRC_ERR_CNT_V 0xFF -#define SLC_DAT2_CRC_ERR_CNT_S 16 -/* SLC_DAT1_CRC_ERR_CNT : RO ;bitpos:[15:8] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT1_CRC_ERR_CNT 0x000000FF -#define SLC_DAT1_CRC_ERR_CNT_M ((SLC_DAT1_CRC_ERR_CNT_V)<<(SLC_DAT1_CRC_ERR_CNT_S)) -#define SLC_DAT1_CRC_ERR_CNT_V 0xFF -#define SLC_DAT1_CRC_ERR_CNT_S 8 -/* SLC_DAT0_CRC_ERR_CNT : RO ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT0_CRC_ERR_CNT 0x000000FF -#define SLC_DAT0_CRC_ERR_CNT_M ((SLC_DAT0_CRC_ERR_CNT_V)<<(SLC_DAT0_CRC_ERR_CNT_S)) -#define SLC_DAT0_CRC_ERR_CNT_V 0xFF -#define SLC_DAT0_CRC_ERR_CNT_S 0 - -#define SLC_SDIO_CRC_ST1_REG (DR_REG_SLC_BASE + 0x120) -/* SLC_ERR_CNT_CLR : R/W ;bitpos:[31] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_ERR_CNT_CLR (BIT(31)) -#define SLC_ERR_CNT_CLR_M (BIT(31)) -#define SLC_ERR_CNT_CLR_V 0x1 -#define SLC_ERR_CNT_CLR_S 31 -/* SLC_CMD_CRC_ERR_CNT : RO ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_CMD_CRC_ERR_CNT 0x000000FF -#define SLC_CMD_CRC_ERR_CNT_M ((SLC_CMD_CRC_ERR_CNT_V)<<(SLC_CMD_CRC_ERR_CNT_S)) -#define SLC_CMD_CRC_ERR_CNT_V 0xFF -#define SLC_CMD_CRC_ERR_CNT_S 0 - -#define SLC_EOF_START_DES_REG (DR_REG_SLC_BASE + 0x124) -/* SLC_SLC0_EOF_START_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_EOF_START_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_EOF_START_DES_ADDR_M ((SLC_SLC0_EOF_START_DES_ADDR_V)<<(SLC_SLC0_EOF_START_DES_ADDR_S)) -#define SLC_SLC0_EOF_START_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_EOF_START_DES_ADDR_S 0 - -#define SLC_PUSH_DSCR_ADDR_REG (DR_REG_SLC_BASE + 0x128) -/* SLC_SLC0_RX_PUSH_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PUSH_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PUSH_DSCR_ADDR_M ((SLC_SLC0_RX_PUSH_DSCR_ADDR_V)<<(SLC_SLC0_RX_PUSH_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PUSH_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PUSH_DSCR_ADDR_S 0 - -#define SLC_DONE_DSCR_ADDR_REG (DR_REG_SLC_BASE + 0x12C) -/* SLC_SLC0_RX_DONE_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_DONE_DSCR_ADDR_M ((SLC_SLC0_RX_DONE_DSCR_ADDR_V)<<(SLC_SLC0_RX_DONE_DSCR_ADDR_S)) -#define SLC_SLC0_RX_DONE_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_DONE_DSCR_ADDR_S 0 - -#define SLC_SUB_START_DES_REG (DR_REG_SLC_BASE + 0x130) -/* SLC_SLC0_SUB_PAC_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_M ((SLC_SLC0_SUB_PAC_START_DSCR_ADDR_V)<<(SLC_SLC0_SUB_PAC_START_DSCR_ADDR_S)) -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_S 0 - -#define SLC_DSCR_CNT_REG (DR_REG_SLC_BASE + 0x134) -/* SLC_SLC0_RX_GET_EOF_OCC : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_GET_EOF_OCC (BIT(16)) -#define SLC_SLC0_RX_GET_EOF_OCC_M (BIT(16)) -#define SLC_SLC0_RX_GET_EOF_OCC_V 0x1 -#define SLC_SLC0_RX_GET_EOF_OCC_S 16 -/* SLC_SLC0_RX_DSCR_CNT_LAT : RO ;bitpos:[9:0] ;default: 10'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_CNT_LAT 0x000003FF -#define SLC_SLC0_RX_DSCR_CNT_LAT_M ((SLC_SLC0_RX_DSCR_CNT_LAT_V)<<(SLC_SLC0_RX_DSCR_CNT_LAT_S)) -#define SLC_SLC0_RX_DSCR_CNT_LAT_V 0x3FF -#define SLC_SLC0_RX_DSCR_CNT_LAT_S 0 - -#define SLC_LEN_LIM_CONF_REG (DR_REG_SLC_BASE + 0x138) -/* SLC_SLC0_LEN_LIM : R/W ;bitpos:[19:0] ;default: 20'h5400 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_LIM 0x000FFFFF -#define SLC_SLC0_LEN_LIM_M ((SLC_SLC0_LEN_LIM_V)<<(SLC_SLC0_LEN_LIM_S)) -#define SLC_SLC0_LEN_LIM_V 0xFFFFF -#define SLC_SLC0_LEN_LIM_S 0 - -#define SLC_INT_ST1_REG (DR_REG_SLC_BASE + 0x13C) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1 : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1 (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ST1 : RO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1 (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_S 26 -/* SLC_CMD_DTC_INT_ST1 : RO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ST1 (BIT(25)) -#define SLC_CMD_DTC_INT_ST1_M (BIT(25)) -#define SLC_CMD_DTC_INT_ST1_V 0x1 -#define SLC_CMD_DTC_INT_ST1_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ST1 : RO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ST1 (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST1_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ST1_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ST1 : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1 (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ST1 : RO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ST1 (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST1_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST1_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ST1_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ST1 : RO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1 (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ST1 : RO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1 (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ST1 : RO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1 (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_S 19 -/* SLC_SLC0_TOHOST_INT_ST1 : RO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ST1 (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST1_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST1_V 0x1 -#define SLC_SLC0_TOHOST_INT_ST1_S 18 -/* SLC_SLC0_RX_EOF_INT_ST1 : RO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ST1 (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST1_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ST1_S 17 -/* SLC_SLC0_RX_DONE_INT_ST1 : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ST1 (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST1_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST1_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ST1_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ST1 : RO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ST1 (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST1_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ST1_S 15 -/* SLC_SLC0_TX_DONE_INT_ST1 : RO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ST1 (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST1_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST1_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ST1_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ST1 : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1 (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ST1 : RO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1 (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_S 12 -/* SLC_SLC0_TX_OVF_INT_ST1 : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ST1 (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST1_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST1_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ST1_S 11 -/* SLC_SLC0_RX_UDF_INT_ST1 : RO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ST1 (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST1_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST1_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ST1_S 10 -/* SLC_SLC0_TX_START_INT_ST1 : RO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ST1 (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST1_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST1_V 0x1 -#define SLC_SLC0_TX_START_INT_ST1_S 9 -/* SLC_SLC0_RX_START_INT_ST1 : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ST1 (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST1_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST1_V 0x1 -#define SLC_SLC0_RX_START_INT_ST1_S 8 -/* SLC_FRHOST_BIT7_INT_ST1 : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ST1 (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST1_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT7_INT_ST1_S 7 -/* SLC_FRHOST_BIT6_INT_ST1 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ST1 (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST1_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT6_INT_ST1_S 6 -/* SLC_FRHOST_BIT5_INT_ST1 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ST1 (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST1_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT5_INT_ST1_S 5 -/* SLC_FRHOST_BIT4_INT_ST1 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ST1 (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST1_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT4_INT_ST1_S 4 -/* SLC_FRHOST_BIT3_INT_ST1 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ST1 (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST1_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT3_INT_ST1_S 3 -/* SLC_FRHOST_BIT2_INT_ST1 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ST1 (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST1_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT2_INT_ST1_S 2 -/* SLC_FRHOST_BIT1_INT_ST1 : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ST1 (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST1_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT1_INT_ST1_S 1 -/* SLC_FRHOST_BIT0_INT_ST1 : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ST1 (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST1_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT0_INT_ST1_S 0 - -#define SLC_INT_ENA1_REG (DR_REG_SLC_BASE + 0x140) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1 : R/W ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1 (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ENA1 : R/W ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1 (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_S 26 -/* SLC_CMD_DTC_INT_ENA1 : R/W ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ENA1 (BIT(25)) -#define SLC_CMD_DTC_INT_ENA1_M (BIT(25)) -#define SLC_CMD_DTC_INT_ENA1_V 0x1 -#define SLC_CMD_DTC_INT_ENA1_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ENA1 : R/W ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1 (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ENA1 : R/W ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1 (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ENA1 : R/W ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1 (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1 : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1 (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1 (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1 (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_S 19 -/* SLC_SLC0_TOHOST_INT_ENA1 : R/W ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ENA1 (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA1_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA1_V 0x1 -#define SLC_SLC0_TOHOST_INT_ENA1_S 18 -/* SLC_SLC0_RX_EOF_INT_ENA1 : R/W ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ENA1 (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA1_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ENA1_S 17 -/* SLC_SLC0_RX_DONE_INT_ENA1 : R/W ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ENA1 (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA1_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ENA1_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ENA1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1 (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_S 15 -/* SLC_SLC0_TX_DONE_INT_ENA1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ENA1 (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA1_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ENA1_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ENA1 : R/W ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1 (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ENA1 : R/W ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1 (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_S 12 -/* SLC_SLC0_TX_OVF_INT_ENA1 : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ENA1 (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA1_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ENA1_S 11 -/* SLC_SLC0_RX_UDF_INT_ENA1 : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ENA1 (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA1_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ENA1_S 10 -/* SLC_SLC0_TX_START_INT_ENA1 : R/W ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ENA1 (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA1_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_START_INT_ENA1_S 9 -/* SLC_SLC0_RX_START_INT_ENA1 : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ENA1 (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA1_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_START_INT_ENA1_S 8 -/* SLC_FRHOST_BIT7_INT_ENA1 : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ENA1 (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA1_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT7_INT_ENA1_S 7 -/* SLC_FRHOST_BIT6_INT_ENA1 : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ENA1 (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA1_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT6_INT_ENA1_S 6 -/* SLC_FRHOST_BIT5_INT_ENA1 : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ENA1 (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA1_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT5_INT_ENA1_S 5 -/* SLC_FRHOST_BIT4_INT_ENA1 : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ENA1 (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA1_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT4_INT_ENA1_S 4 -/* SLC_FRHOST_BIT3_INT_ENA1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ENA1 (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA1_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT3_INT_ENA1_S 3 -/* SLC_FRHOST_BIT2_INT_ENA1 : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ENA1 (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA1_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT2_INT_ENA1_S 2 -/* SLC_FRHOST_BIT1_INT_ENA1 : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ENA1 (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA1_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT1_INT_ENA1_S 1 -/* SLC_FRHOST_BIT0_INT_ENA1 : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ENA1 (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA1_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT0_INT_ENA1_S 0 - -#define SLC_SLCDATE_REG (DR_REG_SLC_BASE + 0x1F8) -/* SLC_DATE : R/W ;bitpos:[31:0] ;default: 32'h18080700 ; */ -/*description: .*/ -#define SLC_DATE 0xFFFFFFFF -#define SLC_DATE_M ((SLC_DATE_V)<<(SLC_DATE_S)) -#define SLC_DATE_V 0xFFFFFFFF -#define SLC_DATE_S 0 - -#define SLC_SLCID_REG (DR_REG_SLC_BASE + 0x1FC) -/* SLC_ID : R/W ;bitpos:[31:0] ;default: 32'h0100 ; */ -/*description: .*/ -#define SLC_ID 0xFFFFFFFF -#define SLC_ID_M ((SLC_ID_V)<<(SLC_ID_S)) -#define SLC_ID_V 0xFFFFFFFF -#define SLC_ID_S 0 - - -#ifdef __cplusplus -} -#endif - - - -#endif /*_SOC_SLC_REG_H_ */ diff --git a/components/soc/esp32s3/include/soc/slc_struct.h b/components/soc/esp32s3/include/soc/slc_struct.h deleted file mode 100644 index 896e781e7d..0000000000 --- a/components/soc/esp32s3/include/soc/slc_struct.h +++ /dev/null @@ -1,592 +0,0 @@ -// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _SOC_SLC_STRUCT_H_ -#define _SOC_SLC_STRUCT_H_ - - -#include -#ifdef __cplusplus -extern "C" { -#endif - -typedef volatile struct { - union { - struct { - uint32_t tx_rst : 1; - uint32_t rx_rst : 1; - uint32_t ahbm_fifo_rst : 1; - uint32_t ahbm_rst : 1; - uint32_t tx_loop_test : 1; - uint32_t rx_loop_test : 1; - uint32_t rx_auto_wrback : 1; - uint32_t rx_no_restart_clr : 1; - uint32_t rxdscr_burst_en : 1; - uint32_t rxdata_burst_en : 1; - uint32_t auto_ret : 1; - uint32_t txdscr_burst_en : 1; - uint32_t txdata_burst_en : 1; - uint32_t token_auto_clr : 1; - uint32_t token_sel : 1; - uint32_t reserved16 : 2; - uint32_t wr_retry_mask_en : 1; - uint32_t reserved19 : 13; - }; - uint32_t val; - } slcconf0; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_raw; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_st; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_ena; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_clr; - uint32_t reserved_14; - uint32_t reserved_18; - uint32_t reserved_1c; - uint32_t reserved_20; - union { - struct { - uint32_t rx_full : 1; - uint32_t rx_empty : 1; - uint32_t rx_buf_len : 12; - uint32_t reserved14 : 18; - }; - uint32_t val; - } rx_status; - union { - struct { - uint32_t rxfifo_wdata : 9; - uint32_t reserved9 : 7; - uint32_t rxfifo_push : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } slc0_rxfifo_push; - uint32_t reserved_2c; - union { - struct { - uint32_t tx_full : 1; - uint32_t tx_empty : 1; - uint32_t reserved2 : 30; - }; - uint32_t val; - } tx_status; - union { - struct { - uint32_t txfifo_rdata : 11; - uint32_t reserved11 : 5; - uint32_t txfifo_pop : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } slc0_txfifo_pop; - uint32_t reserved_38; - union { - struct { - uint32_t addr : 20; - uint32_t reserved20 : 8; - uint32_t stop : 1; - uint32_t start : 1; - uint32_t restart : 1; - uint32_t park : 1; - }; - uint32_t val; - } slc0_rx_link; - union { - struct { - uint32_t addr : 20; - uint32_t reserved20 : 8; - uint32_t stop : 1; - uint32_t start : 1; - uint32_t restart : 1; - uint32_t park : 1; - }; - uint32_t val; - } slc0_tx_link; - uint32_t reserved_44; - uint32_t reserved_48; - union { - struct { - uint32_t tohost_intvec : 8; - uint32_t reserved8 : 24; - }; - uint32_t val; - } slcintvec_tohost; - union { - struct { - uint32_t wdata : 12; - uint32_t wr : 1; - uint32_t inc : 1; - uint32_t inc_more : 1; - uint32_t reserved15 : 1; - uint32_t token0 : 12; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0token0; - union { - struct { - uint32_t wdata : 12; - uint32_t wr : 1; - uint32_t inc : 1; - uint32_t inc_more : 1; - uint32_t reserved15 : 1; - uint32_t token1 : 12; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_token1; - uint32_t reserved_58; - uint32_t reserved_5c; - union { - struct { - uint32_t check_owner : 1; - uint32_t tx_check_sum_en : 1; - uint32_t rx_check_sum_en : 1; - uint32_t reg_cmd_hold_en : 1; - uint32_t len_auto_clr : 1; - uint32_t tx_stitch_en : 1; - uint32_t rx_stitch_en : 1; - uint32_t reserved7 : 12; - uint32_t host_int_level_sel : 1; - uint32_t reserved20 : 2; - uint32_t reg_clk_en : 1; - uint32_t reserved23 : 9; - }; - uint32_t val; - } slcconf1; - uint32_t slc0_state0; - uint32_t slc0_state1; - uint32_t reserved_6c; - uint32_t reserved_70; - union { - struct { - uint32_t txeof_ena : 6; - uint32_t reserved6 : 2; - uint32_t fifo_map_ena : 4; - uint32_t tx_dummy_mode : 1; - uint32_t hda_map_128k : 1; - uint32_t reserved14 : 2; - uint32_t tx_push_idle_num : 16; - }; - uint32_t val; - } slcbridge_conf; - uint32_t slc0_to_eof_des_addr; - uint32_t slc0_tx_eof_des_addr; - uint32_t slc0_to_eof_bfr_des_addr; - uint32_t reserved_84; - uint32_t reserved_88; - uint32_t reserved_8c; - union { - struct { - uint32_t mode : 3; - uint32_t reserved3 : 1; - uint32_t addr : 2; - uint32_t reserved6 : 26; - }; - uint32_t val; - } ahb_test; - union { - struct { - uint32_t cmd_st : 3; - uint32_t reserved3 : 1; - uint32_t func_st : 4; - uint32_t sdio_wakeup : 1; - uint32_t reserved9 : 3; - uint32_t bus_st : 3; - uint32_t reserved15 : 1; - uint32_t func1_acc_state : 5; - uint32_t reserved21 : 11; - }; - uint32_t val; - } sdio_st; - union { - struct { - uint32_t token_no_replace : 1; - uint32_t infor_no_replace : 1; - uint32_t rx_fill_mode : 1; - uint32_t rx_eof_mode : 1; - uint32_t rx_fill_en : 1; - uint32_t rd_retry_threshold : 11; - uint32_t reserved16 : 16; - }; - uint32_t val; - } rx_dscr_conf; - uint32_t slc0_txlink_dscr; - uint32_t slc0_txlink_dscr_bf0; - uint32_t slc0_txlink_dscr_bf1; - uint32_t slc0_rxlink_dscr; - uint32_t slc0_rxlink_dscr_bf0; - uint32_t slc0_rxlink_dscr_bf1; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t slc0_tx_erreof_des_addr; - uint32_t reserved_d0; - union { - struct { - uint32_t token : 12; - uint32_t reserved12 : 20; - }; - uint32_t val; - } token_lat; - union { - struct { - uint32_t wr_retry_threshold : 11; - uint32_t reserved11 : 21; - }; - uint32_t val; - } tx_dscr_conf; - uint32_t cmd_infor0; - uint32_t cmd_infor1; - union { - struct { - uint32_t len_wdata : 20; - uint32_t len_wr : 1; - uint32_t len_inc : 1; - uint32_t len_inc_more : 1; - uint32_t rx_packet_load_en : 1; - uint32_t tx_packet_load_en : 1; - uint32_t rx_get_used_dscr : 1; - uint32_t tx_get_used_dscr : 1; - uint32_t rx_new_pkt_ind : 1; - uint32_t tx_new_pkt_ind : 1; - uint32_t reserved29 : 3; - }; - uint32_t val; - } slc0_len_conf; - union { - struct { - uint32_t len : 20; - uint32_t reserved20 : 12; - }; - uint32_t val; - } slc0_length; - uint32_t slc0_txpkt_h_dscr; - uint32_t slc0_txpkt_e_dscr; - uint32_t slc0_rxpkt_h_dscr; - uint32_t slc0_rxpkt_e_dscr; - uint32_t slc0_txpktu_h_dscr; - uint32_t slc0_txpktu_e_dscr; - uint32_t slc0_rxpktu_h_dscr; - uint32_t slc0_rxpktu_e_dscr; - uint32_t reserved_10c; - uint32_t reserved_110; - union { - struct { - uint32_t seq_position : 8; - uint32_t reserved8 : 24; - }; - uint32_t val; - } seq_position; - union { - struct { - uint32_t rx_dscr_rec_lim : 10; - uint32_t reserved10 : 22; - }; - uint32_t val; - } slc0_dscr_rec_conf; - union { - struct { - uint32_t dat0_crc_err_cnt : 8; - uint32_t dat1_crc_err_cnt : 8; - uint32_t dat2_crc_err_cnt : 8; - uint32_t dat3_crc_err_cnt : 8; - }; - uint32_t val; - } sdio_crc_st0; - union { - struct { - uint32_t cmd_crc_err_cnt : 8; - uint32_t reserved8 : 23; - uint32_t err_cnt_clr : 1; - }; - uint32_t val; - } sdio_crc_st1; - uint32_t slc0_eof_start_des; - uint32_t slc0_push_dscr_addr; - uint32_t slc0_done_dscr_addr; - uint32_t slc0_sub_start_des; - union { - struct { - uint32_t rx_dscr_cnt_lat : 10; - uint32_t reserved10 : 6; - uint32_t rx_get_eof_occ : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } slc0_dscr_cnt; - union { - struct { - uint32_t len_lim : 20; - uint32_t reserved20 : 12; - }; - uint32_t val; - } slc0_len_lim_conf; - union { - struct { - uint32_t frhost_bit01 : 1; - uint32_t frhost_bit11 : 1; - uint32_t frhost_bit21 : 1; - uint32_t frhost_bit31 : 1; - uint32_t frhost_bit41 : 1; - uint32_t frhost_bit51 : 1; - uint32_t frhost_bit61 : 1; - uint32_t frhost_bit71 : 1; - uint32_t rx_start1 : 1; - uint32_t tx_start1 : 1; - uint32_t rx_udf1 : 1; - uint32_t tx_ovf1 : 1; - uint32_t token0_1to01 : 1; - uint32_t token1_1to01 : 1; - uint32_t tx_done1 : 1; - uint32_t tx_suc_eof1 : 1; - uint32_t rx_done1 : 1; - uint32_t rx_eof1 : 1; - uint32_t tohost1 : 1; - uint32_t tx_dscr_err1 : 1; - uint32_t rx_dscr_err1 : 1; - uint32_t tx_dscr_empty1 : 1; - uint32_t host_rd_ack1 : 1; - uint32_t wr_retry_done1 : 1; - uint32_t tx_err_eof1 : 1; - uint32_t cmd_dtc1 : 1; - uint32_t rx_quick_eof1 : 1; - uint32_t host_pop_eof_err1 : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_st1; - union { - struct { - uint32_t frhost_bit01 : 1; - uint32_t frhost_bit11 : 1; - uint32_t frhost_bit21 : 1; - uint32_t frhost_bit31 : 1; - uint32_t frhost_bit41 : 1; - uint32_t frhost_bit51 : 1; - uint32_t frhost_bit61 : 1; - uint32_t frhost_bit71 : 1; - uint32_t rx_start1 : 1; - uint32_t tx_start1 : 1; - uint32_t rx_udf1 : 1; - uint32_t tx_ovf1 : 1; - uint32_t token0_1to01 : 1; - uint32_t token1_1to01 : 1; - uint32_t tx_done1 : 1; - uint32_t tx_suc_eof1 : 1; - uint32_t rx_done1 : 1; - uint32_t rx_eof1 : 1; - uint32_t tohost1 : 1; - uint32_t tx_dscr_err1 : 1; - uint32_t rx_dscr_err1 : 1; - uint32_t tx_dscr_empty1 : 1; - uint32_t host_rd_ack1 : 1; - uint32_t wr_retry_done1 : 1; - uint32_t tx_err_eof1 : 1; - uint32_t cmd_dtc1 : 1; - uint32_t rx_quick_eof1 : 1; - uint32_t host_pop_eof_err1 : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_ena1; - uint32_t reserved_144; - uint32_t reserved_148; - uint32_t reserved_14c; - uint32_t reserved_150; - uint32_t reserved_154; - uint32_t reserved_158; - uint32_t reserved_15c; - uint32_t reserved_160; - uint32_t reserved_164; - uint32_t reserved_168; - uint32_t reserved_16c; - uint32_t reserved_170; - uint32_t reserved_174; - uint32_t reserved_178; - uint32_t reserved_17c; - uint32_t reserved_180; - uint32_t reserved_184; - uint32_t reserved_188; - uint32_t reserved_18c; - uint32_t reserved_190; - uint32_t reserved_194; - uint32_t reserved_198; - uint32_t reserved_19c; - uint32_t reserved_1a0; - uint32_t reserved_1a4; - uint32_t reserved_1a8; - uint32_t reserved_1ac; - uint32_t reserved_1b0; - uint32_t reserved_1b4; - uint32_t reserved_1b8; - uint32_t reserved_1bc; - uint32_t reserved_1c0; - uint32_t reserved_1c4; - uint32_t reserved_1c8; - uint32_t reserved_1cc; - uint32_t reserved_1d0; - uint32_t reserved_1d4; - uint32_t reserved_1d8; - uint32_t reserved_1dc; - uint32_t reserved_1e0; - uint32_t reserved_1e4; - uint32_t reserved_1e8; - uint32_t reserved_1ec; - uint32_t reserved_1f0; - uint32_t reserved_1f4; - uint32_t date; - uint32_t id; -} slc_dev_t; -extern slc_dev_t SLC; -#ifdef __cplusplus -} -#endif - - - -#endif /*_SOC_SLC_STRUCT_H_ */ diff --git a/components/soc/esp32s3/include/soc/spi_mem_struct.h b/components/soc/esp32s3/include/soc/spi_mem_struct.h index 32ce1bf933..aa6f388653 100644 --- a/components/soc/esp32s3/include/soc/spi_mem_struct.h +++ b/components/soc/esp32s3/include/soc/spi_mem_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_mem_dev_s { union { struct { uint32_t reserved0 : 17; /*reserved*/ diff --git a/components/soc/esp32s3/include/soc/spi_struct.h b/components/soc/esp32s3/include/soc/spi_struct.h index c57ad937ce..2a3abd257c 100644 --- a/components/soc/esp32s3/include/soc/spi_struct.h +++ b/components/soc/esp32s3/include/soc/spi_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_dev_s { union { struct { uint32_t conf_bitlen : 18; /*Define the APB cycles of SPI_CONF state. Can be configured in CONF state.*/ diff --git a/components/soc/esp32s3/include/soc/syscon_struct.h b/components/soc/esp32s3/include/soc/syscon_struct.h index 6c32efe3d6..98c5a64619 100644 --- a/components/soc/esp32s3/include/soc/syscon_struct.h +++ b/components/soc/esp32s3/include/soc/syscon_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { union { struct { uint32_t apb_ctrl_pre_div_cnt: 10; diff --git a/components/soc/esp32s3/include/soc/system_struct.h b/components/soc/esp32s3/include/soc/system_struct.h index d81146c9b0..6c4ce1f118 100644 --- a/components/soc/esp32s3/include/soc/system_struct.h +++ b/components/soc/esp32s3/include/soc/system_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct system_dev_s { union { struct { uint32_t control_core_1_runstall : 1; diff --git a/components/soc/esp32s3/include/soc/systimer_struct.h b/components/soc/esp32s3/include/soc/systimer_struct.h index 1d5c4a8c5f..115058c522 100644 --- a/components/soc/esp32s3/include/soc/systimer_struct.h +++ b/components/soc/esp32s3/include/soc/systimer_struct.h @@ -90,6 +90,7 @@ typedef union { * update timer_unit0 */ uint32_t timer_unit_update: 1; + uint32_t reserved_32: 1; }; uint32_t val; } systimer_unit_op_reg_t; @@ -104,6 +105,7 @@ typedef struct { * timer unit load high 32 bit */ uint32_t timer_unit_load_hi: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; @@ -129,6 +131,7 @@ typedef struct { * timer target high 32 bit */ uint32_t timer_target_hi: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; @@ -177,6 +180,7 @@ typedef struct { * timer read value high 20bit */ uint32_t timer_unit_value_hi: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; @@ -201,6 +205,7 @@ typedef union { * timer comp load value */ uint32_t timer_comp_load: 1; + uint32_t reserved_1: 31; }; uint32_t val; } systimer_comp_load_reg_t; @@ -215,6 +220,7 @@ typedef union { * timer unit load value */ uint32_t timer_unit_load: 1; + uint32_t reserved_1: 31; }; uint32_t val; } systimer_unit_load_reg_t; @@ -238,6 +244,7 @@ typedef union { * interupt2 enable */ uint32_t target2_int_ena: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -259,6 +266,7 @@ typedef union { * interupt2 raw */ uint32_t target2_int_raw: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -280,6 +288,7 @@ typedef union { * interupt2 clear */ uint32_t target2_int_clr: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_clr_reg_t; @@ -301,6 +310,7 @@ typedef union { * interupt2 status */ uint32_t target2_int_st: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_st_reg_t; @@ -325,6 +335,7 @@ typedef struct { * actual target value value high 20bits */ uint32_t target_hi_ro: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; diff --git a/components/soc/esp32s3/include/soc/twai_struct.h b/components/soc/esp32s3/include/soc/twai_struct.h index 19810eda15..df022feb47 100644 --- a/components/soc/esp32s3/include/soc/twai_struct.h +++ b/components/soc/esp32s3/include/soc/twai_struct.h @@ -23,7 +23,7 @@ extern "C" { /* ---------------------------- Register Layout ------------------------------ */ -/* The TWAI peripheral's registers are 8bits, however the ESP32 can only access +/* The TWAI peripheral's registers are 8bits, however the ESP32-S3 can only access * peripheral registers every 32bits. Therefore each TWAI register is mapped to * the least significant byte of every 32bits. */ @@ -36,10 +36,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -47,10 +47,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -62,97 +62,99 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 13; /* BTR0[12:0] Baud Rate Prescaler */ - uint32_t reserved1: 1; /* Internal Reserved */ + uint32_t reserved13: 1; /* Internal Reserved */ uint32_t sjw: 2; /* BTR0[15:14] Synchronization Jump Width*/ uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -160,45 +162,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32s3/include/soc/uhci_struct.h b/components/soc/esp32s3/include/soc/uhci_struct.h index 2f7f2cee28..6fdd2cad1f 100644 --- a/components/soc/esp32s3/include/soc/uhci_struct.h +++ b/components/soc/esp32s3/include/soc/uhci_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t tx_rst : 1; diff --git a/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h index cac2ddedac..539717f267 100644 --- a/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct usb_serial_jtag_dev_s { union { struct { uint32_t rdwr_byte : 32; /*Although only low 8-bits is valid, but change it to 32bits to avoid there's no read/modify/write behaviour*/ /*Write and read byte data to/from UART Tx/Rx FIFO through this field. When USB_DEVICE_SERIAL_IN_EMPTY_INT is set, then user can write data (up to 64 bytes) into UART Tx FIFO. When USB_DEVICE_SERIAL_OUT_RECV_PKT_INT is set, user can check USB_DEVICE_OUT_EP1_WR_ADDR USB_DEVICE_OUT_EP0_RD_ADDR to know how many data is received, then read data from UART Rx FIFO.*/ diff --git a/components/soc/esp32s3/include/soc/usb_wrap_struct.h b/components/soc/esp32s3/include/soc/usb_wrap_struct.h index ba38facf52..91b79d9119 100644 --- a/components/soc/esp32s3/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32s3/include/soc/usb_wrap_struct.h @@ -154,6 +154,7 @@ typedef union { * USB D- rx value in test. */ uint32_t test_rx_dm:1; + uint32_t reserved7: 25; }; uint32_t val; } usb_wrap_test_conf_reg_t; diff --git a/components/soc/esp32s3/include/soc/usbh_struct.h b/components/soc/esp32s3/include/soc/usbh_struct.h index 7401bbf9cf..3a52bf9952 100644 --- a/components/soc/esp32s3/include/soc/usbh_struct.h +++ b/components/soc/esp32s3/include/soc/usbh_struct.h @@ -831,7 +831,7 @@ typedef union { uint32_t bbleerr: 1; uint32_t nakintrpt: 1; uint32_t nyetintrpt: 1; - uint32_t reserved16: 16; + uint32_t reserved15: 17; }; uint32_t val; } usb_diepint_reg_t; diff --git a/components/soc/esp32s3/include/soc/world_controller_struct.h b/components/soc/esp32s3/include/soc/world_controller_struct.h index da042acda5..89a317d9a3 100644 --- a/components/soc/esp32s3/include/soc/world_controller_struct.h +++ b/components/soc/esp32s3/include/soc/world_controller_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct world_controller_dev_s { uint32_t wcl_core_0_entry_1_addr; uint32_t wcl_core_0_entry_2_addr; uint32_t wcl_core_0_entry_3_addr; diff --git a/components/soc/include/soc/sdio_slave_periph.h b/components/soc/include/soc/sdio_slave_periph.h index d39f72f526..0f748ae12e 100644 --- a/components/soc/include/soc/sdio_slave_periph.h +++ b/components/soc/include/soc/sdio_slave_periph.h @@ -15,9 +15,12 @@ #pragma once #include //include soc related (generated) definitions +#include "soc/soc_caps.h" #include "soc/soc_pins.h" +#ifdef SOC_SDIO_SLAVE_SUPPORTED #include "soc/slc_reg.h" #include "soc/slc_struct.h" +#endif #include "soc/host_reg.h" #include "soc/host_struct.h" #include "soc/hinf_reg.h" diff --git a/tools/ci/check_soc_struct_headers.py b/tools/ci/check_soc_struct_headers.py new file mode 100755 index 0000000000..7611a4a2fa --- /dev/null +++ b/tools/ci/check_soc_struct_headers.py @@ -0,0 +1,420 @@ +#!/usr/bin/env python + +# A check script that just works at the time of writing... +# +# also builds a structure tree for further reference +# +# Input file format must be similiar to those headers generated by regtool, or this script makes no sense at all +# +# Known limitation: +# 1. won't accept /* ... */ /* ... */': badly behavior with multiline comment +# 2. won't accept multiple expression within same line' (but will info that) +# 3. won't accept single line struct/union definition +# +# Check list: +# 1. a structure should not contain bitfield member alongside with nested struct/union +# 2. bitfield sum in a struct should be 32 (means being well padded) +# 3. each bitfield type should be uint32_t +# 4. expecting union to be `union { struct {xxx}; uint32_t val; }` and complain if it is not an u32 val (but not fail) +# 5. typedef volatile struct xxx{}: xxx must exists +# +# Otherwise won't fail but warning + +import os +import re +import sys +from typing import Any + + +class MemberField: + member_type = '' + bitfield = None + + def __init__(self, m_type: str, m_bits: int=None) -> None: + self.member_type = m_type + self.bitfield = m_bits + + def __unicode__(self) -> str: + return self.__str__() + + def __repr__(self) -> str: + return self.__str__() + + def __str__(self) -> str: + if self.bitfield is None: + return '"Field type={}"'.format(self.member_type) + return '"Field type={} bit={}"'.format(self.member_type, self.bitfield) + + +class SoCStructureHeaderChecker: + # capture: typedef, volatile, struct name + __REGEXP_MATCH_STRUCTURE_BEGIN = r'^[\s]*(typedef)?(?:[\s]+(volatile))?[\s]+struct[\s]+([\w]+)?[\s\S]*$' + # capture: typedef, volatile, union name + __REGEXP_MATCH_UNION_BEGIN = r'^[\s]*(typedef)?(?:[\s]+(volatile))?[\s]+union[\s]+([\w]+)?[\s\S]*$' + # capture: type_var_name + __REGEXP_MATCH_STRUCT_UNION_END_NAME = r'^[\s]*}[\s]*([\w\[\]\*]*)[\s]*;[\s\S]*$' + # capture: type, name, bitfield + __REGEXP_MATCH_BITFIELD_MEMBER = (r'^[\s]*(?:(?:volatile[\s]+)|(?:))([\w\*]+)[\s]+([\w\*]+(?:(?:\[[\s\S]*\])|(?:)))' + r'[\s]*(?:(?:[\s]*;)|(?::[\s]*([\d]+)[\s]*;))[\s\S]*$') + # should be useless and can be safely deleted + __REGEXP_MATCH_MULTILINE_COMMENT = r'^[\s]*[\/]{0,2}\*[\/]?[\s\S]*$' + __REGEX_MATCH_SIMPLE_VAL_FIELD = r'^[\s]*(?:(?:volatile[\s]+)|(?:))([\w]+)[\s]+([\w\[\]\*]+)[\s]*;[\s]*$' + # capture: type, name + __REGEX_MATCH_ROOT_EXTERNAL = r'^[\s]*extern[\s]+([\w]+)[\s]+([\w]+)[\s]*;[\s]*$' + + __linecount = 0 + __fd = None # type: Any + __is_eof = False + + # generated reference tree + __ref_tree = dict() # type: dict + # middle result of generated tree, shared + # named typedef, or named struct/union. referd but will not delete + __temp_ref_types = dict() # type: dict + + def __expand_type(self, member_type: str, bitfield: int=None) -> Any: + if member_type == 'uint32_t': + return MemberField(member_type, bitfield) + if bitfield is not None: + print('\033[0;31mERROR\033[0m: non-u32 type with bitfield') + return None + if member_type in self.__temp_ref_types: + return self.__temp_ref_types[member_type] + return None + + def __getline(self, incomment:bool=False) -> Any: + rawline = self.__fd.readline() + if not rawline: + self.__is_eof = True + return None + self.__linecount += 1 + + if incomment: + pos = rawline.find('*/') + if pos != -1: + # set string that is behind comment + rawline = rawline[pos + 2:] + else: + # continue multiple line + return self.__getline(True) + + # preprocess: remove '// comment' + match_obj = re.match(r'^([^(\/\/)]*)\/\/[\s\S]*$', rawline) + if match_obj is not None: + rawline = match_obj.groups()[0] + # preprocess: remove '/* comment' + match_obj = re.match(r'^([^(\/\*)]*)\/\*([\s\S]*)$', rawline) + if match_obj is not None: + rawline = match_obj.groups()[0] + # check if multiline commit in oneline + pos = match_obj.groups()[1].find('*/') + if pos != -1: + # apply string that is behind comment + rawline = rawline + match_obj.groups()[1][pos + 2:] + else: + # multiple line + return self.__getline(True) + + if re.match(r'^[\s]*$', rawline): + # skip empty line + return self.__getline() + if rawline.count(';') > 1: + print('\033[0;34mINFO\033[0m: line: {}: possibily multiple expression within same line'.format(self.__linecount)) + print(rawline) + return rawline + + def __process_structure(self, name: str, is_typedef: bool, is_volatile: bool) -> Any: + ret_val = 0 + # first check for anonymous register structs + if is_typedef and is_volatile and name is None: + print('\033[0;31mERROR\033[0m: line {}: annoymous struct'.format(self.__linecount)) + ret_val = -1 + node_tree = dict() + bitcount = 0 + has_nested_struct_union = False + has_non_bitfield_member = False + parsed_varname = '' + while not self.__is_eof: + rawline = self.__getline() + if rawline is None: + break + # check for nested structure + match_obj = re.match(self.__REGEXP_MATCH_STRUCTURE_BEGIN, rawline) + if match_obj is not None: + has_nested_struct_union = True + ret, inherited_node_tree = self.__process_structure( + match_obj.groups()[2], match_obj.groups()[0] == 'typedef', match_obj.groups()[1] == 'volatile') + if ret != 0: + ret_val = -2 + if inherited_node_tree is not None: + for node in inherited_node_tree: + node_tree[node] = inherited_node_tree[node] + continue + match_obj = re.match(self.__REGEXP_MATCH_UNION_BEGIN, rawline) + if match_obj is not None: + has_nested_struct_union = True + ret, inherited_node_tree = self.__process_union(match_obj.groups()[2], match_obj.groups()[0] == 'typedef', match_obj.groups()[1] == 'volatile') + if ret != 0: + ret_val = -2 + if inherited_node_tree is not None: + for node in inherited_node_tree: + node_tree[node] = inherited_node_tree[node] + continue + # check if end of struct + match_obj = re.match(self.__REGEXP_MATCH_STRUCT_UNION_END_NAME, rawline) + if match_obj is not None: + # end of struct + if bitcount not in (0, 32): + ret_val = -2 + if is_typedef: + print('\033[0;31mERROR\033[0m: line {}: bitfield count is {}, type {}'.format(self.__linecount, bitcount, match_obj.groups()[0])) + else: + print('\033[0;31mERROR\033[0m: line {}: bitfield count is {}, type {}, varname "{}"' + .format(self.__linecount, bitcount, name, match_obj.groups()[0])) + parsed_varname = match_obj.groups()[0] + if is_typedef: + # is a typedef + if match_obj.groups()[0] == '' or match_obj.groups()[0].find('[') != -1: + # should be c error + print('\033[0;31mERROR\033[0m: line {}: C error'.format(self.__linecount)) + ret_val = -3 + if match_obj.groups()[0] in self.__temp_ref_types: + # duplication, script bug: we are putting all types into same namespace + print('script run into bug...') + self.__temp_ref_types[match_obj.groups()[0]] = dict() + for member in node_tree: + self.__temp_ref_types[match_obj.groups()[0]][member] = node_tree[member] + elif name is not None: + # currently this kind of expression doesn't exist + print('!!!!!!UNDEALED CONDITION!!!!!') + elif match_obj.groups()[0] != '': + # named member, wrap and overwrite + if len(node_tree) == 0: + node_tree = None + else: + array_match = re.match(r'^([\w]*)\[[\s\S]*\]$', match_obj.groups()[0]) + if array_match is not None: + node_tree = {array_match.groups()[0] + '[]': node_tree} + else: + node_tree = {match_obj.groups()[0]: node_tree} + else: + # not a type, no member name, treat its fields as its parent's + pass + break + # check member + match_obj = re.match(self.__REGEXP_MATCH_BITFIELD_MEMBER, rawline) + if match_obj is not None: + field_bit = None + if match_obj.groups()[2] is not None: + field_bit = int(match_obj.groups()[2]) + bitcount += field_bit + # bitfield should be u32 + if match_obj.groups()[0] != 'uint32_t': + print('\033[0;33mWARN\033[0m: line: {}: {} has type {}'.format(self.__linecount, match_obj.groups()[1], match_obj.groups()[0])) + else: + has_non_bitfield_member = True + # append to node tree + member_node = self.__expand_type(match_obj.groups()[0], field_bit) + if member_node is not None: + array_match = re.match(r'^([\w]*)\[[\s\S]*\]$', match_obj.groups()[1]) + if array_match is not None: + node_tree[array_match.groups()[0] + '[]'] = member_node + else: + node_tree[match_obj.groups()[1]] = member_node + else: + if '*' not in match_obj.groups()[0]: + print('\033[0;33mWARN\033[0m: line {}: unknown type {}'.format(self.__linecount, match_obj.groups()[0])) + else: + print('\033[0;33mWARN\033[0m: line {}: pointer type {}'.format(self.__linecount, match_obj.groups()[0])) + continue + # check comments + match_obj = re.match(self.__REGEXP_MATCH_MULTILINE_COMMENT, rawline) + if match_obj is not None: + # code comments + continue + # dump out unmatched condition + print(('\033[0;33mWARN\033[0m: line: {}: unexpected expression: {}'.format(self.__linecount, rawline)).replace('\n', '')) + + if bitcount != 0 and has_nested_struct_union: + print('\033[0;33mWARN\033[0m: line: {}: mixed bitfield member and nested structure/union'.format(self.__linecount)) + if bitcount != 0 and has_non_bitfield_member: + print('\033[0;33mWARN\033[0m: line: {}: mixed bitfield member and non-bitfield member'.format(self.__linecount)) + if is_typedef and is_volatile and name is None: + if parsed_varname != '': + print('SUGGEST: {}'.format(parsed_varname.rstrip('t') + 's')) + if name is not None and is_typedef and is_volatile and parsed_varname.rstrip('t') != name.rstrip('s'): + print('\033[0;33mWARN\033[0m: line: {}: different type and typedef name: {} {}'.format(self.__linecount, name, parsed_varname)) + return ret_val, node_tree + + def __process_union(self, name: str, is_typedef: bool, is_volatile: bool) -> Any: + ret_val = 0 + # first check for anonymous register structs + if is_typedef and is_volatile and name is None: + print('\033[0;31mERROR\033[0m: line {}: annoymous union'.format(self.__linecount)) + ret_val = -1 + node_tree = dict() # type: Any + has_struct_count = 0 + has_val_field_count = 0 + while not self.__is_eof: + rawline = self.__getline() + if rawline is None: + break + # check for nested structure + match_obj = re.match(self.__REGEXP_MATCH_STRUCTURE_BEGIN, rawline) + if match_obj is not None: + has_struct_count += 1 + ret, inherited_node_tree = self.__process_structure( + match_obj.groups()[2], match_obj.groups()[0] == 'typedef', match_obj.groups()[1] == 'volatile') + if ret != 0: + ret_val = -2 + if inherited_node_tree is not None: + for node in inherited_node_tree: + node_tree[node] = inherited_node_tree[node] + continue + match_obj = re.match(self.__REGEXP_MATCH_UNION_BEGIN, rawline) + if match_obj is not None: + has_struct_count += 1 + ret, inherited_node_tree = self.__process_union(match_obj.groups()[2], match_obj.groups()[0] == 'typedef', match_obj.groups()[1] == 'volatile') + if ret != 0: + ret_val = -2 + if inherited_node_tree is not None: + for node in inherited_node_tree: + node_tree[node] = inherited_node_tree[node] + continue + match_obj = re.match(self.__REGEXP_MATCH_STRUCT_UNION_END_NAME, rawline) + if match_obj is not None: + parsed_varname = match_obj.groups()[0] + # end of struct + if is_typedef: + # is a typedef + if match_obj.groups()[0] == '': + # should be c error + print('\033[0;31mERROR\033[0m: line {}: C error'.format(self.__linecount)) + ret_val = -3 + if match_obj.groups()[0] in self.__temp_ref_types: + # duplication, script bug: we are putting all types into same namespace + print('script run into bug...') + self.__temp_ref_types[match_obj.groups()[0]] = dict() + for member in node_tree: + self.__temp_ref_types[match_obj.groups()[0]][member] = node_tree[member] + node_tree = None + elif name is not None: + # currently this kind of expression doesn't exist + print('!!!!!!UNDEALED CONDITION!!!!!') + elif match_obj.groups()[0] != '': + # named member, wrap and overwrite + if len(node_tree) == 0: + node_tree = None + else: + array_match = re.match(r'^([\w]*)\[[\s\S]*\]$', match_obj.groups()[0]) + if array_match is not None: + node_tree = {array_match.groups()[0] + '[]': node_tree} + else: + node_tree = {match_obj.groups()[0]: node_tree} + else: + # not a type, no member name, treat its fields as its parent's + pass + break + match_obj = re.match(self.__REGEXP_MATCH_MULTILINE_COMMENT, rawline) + if match_obj is not None: + # code comments + continue + match_obj = re.match(self.__REGEX_MATCH_SIMPLE_VAL_FIELD, rawline) + if match_obj is not None: + # expecting to see 'uint32_t val;' + if match_obj.groups()[0] != 'uint32_t' or match_obj.groups()[1] != 'val': + print(('\033[0;33mWARN\033[0m: unexpected union member at {}: {}'.format(self.__linecount, rawline)).replace('\n', '')) + else: + has_val_field_count += 1 + # append to node tree + member_node = self.__expand_type(match_obj.groups()[0], None) + if member_node is not None: + node_tree[match_obj.groups()[1]] = member_node + else: + if '*' not in match_obj.groups()[0]: + print('\033[0;31mERROR\033[0m: line {}: unknown type {}'.format(self.__linecount, match_obj.groups()[0])) + else: + print('\033[0;33mWARN\033[0m: line {}: pointer type {}'.format(self.__linecount, match_obj.groups()[0])) + continue + # dump out unmatched condition + print(('\033[0;33mWARN\033[0m: line: {}: unexpected expression: {}'.format(self.__linecount, rawline)).replace('\n', '')) + + if not (has_struct_count == 1 and has_val_field_count == 1): + print('\033[0;34mINFO\033[0m: line: {}: not a typical union: {} nested structures, {} u32 val member' + .format(self.__linecount, has_struct_count, has_val_field_count)) + if is_typedef and is_volatile and name is None: + if parsed_varname != '': + print('SUGGEST: {}'.format(parsed_varname.rstrip('t') + 's')) + if name is not None and is_typedef and is_volatile and parsed_varname.rstrip('t') != name.rstrip('s'): + print('\033[0;33mWARN\033[0m: line: {}: different type and typedef name: {} {}'.format(self.__linecount, name, parsed_varname)) + return ret_val, node_tree + + def __process_root(self) -> int: + ret_val = 0 + node_tree = dict() + + while not self.__is_eof: + rawline = self.__getline() + if rawline is None: + break + # start checking by finding any of structure or union + match_obj = re.match(self.__REGEXP_MATCH_STRUCTURE_BEGIN, rawline) + if match_obj is not None: + ret, inherited_node_tree = self.__process_structure( + match_obj.groups()[2], match_obj.groups()[0] == 'typedef', match_obj.groups()[1] == 'volatile') + if ret != 0: + ret_val = -2 + if inherited_node_tree is not None: + for node in inherited_node_tree: + node_tree[node] = inherited_node_tree[node] + continue + match_obj = re.match(self.__REGEXP_MATCH_UNION_BEGIN, rawline) + if match_obj is not None: + ret, inherited_node_tree = self.__process_union(match_obj.groups()[2], match_obj.groups()[0] == 'typedef', match_obj.groups()[1] == 'volatile') + if ret != 0: + ret_val = -2 + if inherited_node_tree is not None: + for node in inherited_node_tree: + node_tree[node] = inherited_node_tree[node] + continue + # processing root level external declaration + match_obj = re.match(self.__REGEX_MATCH_ROOT_EXTERNAL, rawline) + if match_obj is not None: + self.__ref_tree[match_obj.groups()[1]] = self.__expand_type(match_obj.groups()[0]) + continue + return ret_val + + def check(self, file: str) -> int: + self.__fd = open(file, 'r', encoding='utf8') + self.__linecount = 0 + self.__is_eof = False + + ret_val = self.__process_root() + + self.__fd.close() + if ret_val != 0: + print('\033[0;31mCHECK FAILED\033[0m:\t{}'.format(file)) + else: + print('\033[0;32mCHECK PASSED\033[0m:\t{}'.format(file)) + return ret_val + + def get_ref_tree(self) -> Any: + return self.__ref_tree + + +def main() -> None: + ret = 0 + if len(sys.argv) <= 1 or not os.path.isfile(sys.argv[1]): + print('file not exist') + exit(-1) + checker = SoCStructureHeaderChecker() + print('CHECKING:\t{}'.format(sys.argv[1])) + ret = checker.check(sys.argv[1]) + if len(sys.argv) == 3 and sys.argv[2] == 'print': + print(checker.get_ref_tree()) + del checker + sys.exit(ret) + + +if __name__ == '__main__': + main() diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index 370042d92c..08a7100646 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -47,6 +47,7 @@ tools/ci/check_idf_version.sh tools/ci/check_kconfigs.py tools/ci/check_readme_links.py tools/ci/check_rules_yml.py +tools/ci/check_soc_struct_headers.py tools/ci/check_tools_files_patterns.py tools/ci/check_type_comments.py tools/ci/check_ut_cmake_make.sh From 892f5e7df324157824e4ce2bf45e24de39f050f2 Mon Sep 17 00:00:00 2001 From: SalimTerryLi Date: Tue, 24 Aug 2021 15:32:08 +0800 Subject: [PATCH 077/310] timer_group: fix wrongly generated reg header that introduced in 443845fd54e6cf874933138ea492e70aa6345140 --- .../soc/esp32c3/include/soc/timer_group_reg.h | 46 +++++----- .../soc/esp32h2/include/soc/timer_group_reg.h | 46 +++++----- .../soc/esp32s2/include/soc/timer_group_reg.h | 84 +++++++++---------- 3 files changed, 88 insertions(+), 88 deletions(-) diff --git a/components/soc/esp32c3/include/soc/timer_group_reg.h b/components/soc/esp32c3/include/soc/timer_group_reg.h index 35f29209aa..4d591035fc 100644 --- a/components/soc/esp32c3/include/soc/timer_group_reg.h +++ b/components/soc/esp32c3/include/soc/timer_group_reg.h @@ -35,7 +35,7 @@ extern "C" { /** TIMG_T0CONFIG_REG register * Timer 0 configuration register */ -#define TIMG_T0CONFIG_REG (DR_REG_TIMG_BASE + 0x0) +#define TIMG_T0CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x0) /** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source * clock of timer group. @@ -92,7 +92,7 @@ extern "C" { /** TIMG_T0LO_REG register * Timer 0 current value, low 32 bits */ -#define TIMG_T0LO_REG (DR_REG_TIMG_BASE + 0x4) +#define TIMG_T0LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x4) /** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; * After writing to TIMG_T0UPDATE_REG, the low 32 bits of the time-base counter * of timer 0 can be read here. @@ -105,7 +105,7 @@ extern "C" { /** TIMG_T0HI_REG register * Timer $x current value, high 22 bits */ -#define TIMG_T0HI_REG (DR_REG_TIMG_BASE + 0x8) +#define TIMG_T0HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x8) /** TIMG_T0_HI : RO; bitpos: [21:0]; default: 0; * After writing to TIMG_T$xUPDATE_REG, the high 22 bits of the time-base counter * of timer $x can be read here. @@ -118,7 +118,7 @@ extern "C" { /** TIMG_T0UPDATE_REG register * Write to copy current timer value to TIMGn_T$x_(LO/HI)_REG */ -#define TIMG_T0UPDATE_REG (DR_REG_TIMG_BASE + 0xc) +#define TIMG_T0UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xc) /** TIMG_T0_UPDATE : R/W/SC; bitpos: [31]; default: 0; * After writing 0 or 1 to TIMG_T$xUPDATE_REG, the counter value is latched. */ @@ -130,7 +130,7 @@ extern "C" { /** TIMG_T0ALARMLO_REG register * Timer $x alarm value, low 32 bits */ -#define TIMG_T0ALARMLO_REG (DR_REG_TIMG_BASE + 0x10) +#define TIMG_T0ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x10) /** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Timer $x alarm trigger time-base counter value, low 32 bits. */ @@ -142,7 +142,7 @@ extern "C" { /** TIMG_T0ALARMHI_REG register * Timer $x alarm value, high bits */ -#define TIMG_T0ALARMHI_REG (DR_REG_TIMG_BASE + 0x14) +#define TIMG_T0ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x14) /** TIMG_T0_ALARM_HI : R/W; bitpos: [21:0]; default: 0; * Timer $x alarm trigger time-base counter value, high 22 bits. */ @@ -154,7 +154,7 @@ extern "C" { /** TIMG_T0LOADLO_REG register * Timer $x reload value, low 32 bits */ -#define TIMG_T0LOADLO_REG (DR_REG_TIMG_BASE + 0x18) +#define TIMG_T0LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x18) /** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * Low 32 bits of the value that a reload will load onto timer $x time-base * Counter. @@ -167,7 +167,7 @@ extern "C" { /** TIMG_T0LOADHI_REG register * Timer $x reload value, high 22 bits */ -#define TIMG_T0LOADHI_REG (DR_REG_TIMG_BASE + 0x1c) +#define TIMG_T0LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x1c) /** TIMG_T0_LOAD_HI : R/W; bitpos: [21:0]; default: 0; * High 22 bits of the value that a reload will load onto timer $x time-base * counter. @@ -180,7 +180,7 @@ extern "C" { /** TIMG_T0LOAD_REG register * Write to reload timer from TIMG_T$x_(LOADLOLOADHI)_REG */ -#define TIMG_T0LOAD_REG (DR_REG_TIMG_BASE + 0x20) +#define TIMG_T0LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x20) /** TIMG_T0_LOAD : WT; bitpos: [31:0]; default: 0; * * Write any value to trigger a timer $x time-base counter reload. @@ -193,7 +193,7 @@ extern "C" { /** TIMG_WDTCONFIG0_REG register * Watchdog timer configuration register */ -#define TIMG_WDTCONFIG0_REG (DR_REG_TIMG_BASE + 0x48) +#define TIMG_WDTCONFIG0_REG(i) (DR_REG_TIMG_BASE(i) + 0x48) /** TIMG_WDT_APPCPU_RESET_EN : R/W; bitpos: [12]; default: 0; * WDT reset CPU enable. */ @@ -284,7 +284,7 @@ extern "C" { /** TIMG_WDTCONFIG1_REG register * Watchdog timer prescaler register */ -#define TIMG_WDTCONFIG1_REG (DR_REG_TIMG_BASE + 0x4c) +#define TIMG_WDTCONFIG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x4c) /** TIMG_WDT_DIVCNT_RST : WT; bitpos: [0]; default: 0; * When set, WDT 's clock divider counter will be reset. */ @@ -304,7 +304,7 @@ extern "C" { /** TIMG_WDTCONFIG2_REG register * Watchdog timer stage 0 timeout value */ -#define TIMG_WDTCONFIG2_REG (DR_REG_TIMG_BASE + 0x50) +#define TIMG_WDTCONFIG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x50) /** TIMG_WDT_STG0_HOLD : R/W; bitpos: [31:0]; default: 26000000; * Stage 0 timeout value, in MWDT clock cycles. */ @@ -316,7 +316,7 @@ extern "C" { /** TIMG_WDTCONFIG3_REG register * Watchdog timer stage 1 timeout value */ -#define TIMG_WDTCONFIG3_REG (DR_REG_TIMG_BASE + 0x54) +#define TIMG_WDTCONFIG3_REG(i) (DR_REG_TIMG_BASE(i) + 0x54) /** TIMG_WDT_STG1_HOLD : R/W; bitpos: [31:0]; default: 134217727; * Stage 1 timeout value, in MWDT clock cycles. */ @@ -328,7 +328,7 @@ extern "C" { /** TIMG_WDTCONFIG4_REG register * Watchdog timer stage 2 timeout value */ -#define TIMG_WDTCONFIG4_REG (DR_REG_TIMG_BASE + 0x58) +#define TIMG_WDTCONFIG4_REG(i) (DR_REG_TIMG_BASE(i) + 0x58) /** TIMG_WDT_STG2_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 2 timeout value, in MWDT clock cycles. */ @@ -340,7 +340,7 @@ extern "C" { /** TIMG_WDTCONFIG5_REG register * Watchdog timer stage 3 timeout value */ -#define TIMG_WDTCONFIG5_REG (DR_REG_TIMG_BASE + 0x5c) +#define TIMG_WDTCONFIG5_REG(i) (DR_REG_TIMG_BASE(i) + 0x5c) /** TIMG_WDT_STG3_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 3 timeout value, in MWDT clock cycles. */ @@ -352,7 +352,7 @@ extern "C" { /** TIMG_WDTFEED_REG register * Write to feed the watchdog timer */ -#define TIMG_WDTFEED_REG (DR_REG_TIMG_BASE + 0x60) +#define TIMG_WDTFEED_REG(i) (DR_REG_TIMG_BASE(i) + 0x60) /** TIMG_WDT_FEED : WT; bitpos: [31:0]; default: 0; * Write any value to feed the MWDT. (WO) */ @@ -364,7 +364,7 @@ extern "C" { /** TIMG_WDTWPROTECT_REG register * Watchdog write protect register */ -#define TIMG_WDTWPROTECT_REG (DR_REG_TIMG_BASE + 0x64) +#define TIMG_WDTWPROTECT_REG(i) (DR_REG_TIMG_BASE(i) + 0x64) /** TIMG_WDT_WKEY : R/W; bitpos: [31:0]; default: 1356348065; * If the register contains a different value than its reset value, write * protection is enabled. @@ -436,7 +436,7 @@ extern "C" { /** TIMG_INT_ENA_TIMERS_REG register * Interrupt enable bits */ -#define TIMG_INT_ENA_TIMERS_REG (DR_REG_TIMG_BASE + 0x70) +#define TIMG_INT_ENA_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x70) /** TIMG_T0_INT_ENA : R/W; bitpos: [0]; default: 0; * The interrupt enable bit for the TIMG_T$x_INT interrupt. */ @@ -455,7 +455,7 @@ extern "C" { /** TIMG_INT_RAW_TIMERS_REG register * Raw interrupt status */ -#define TIMG_INT_RAW_TIMERS_REG (DR_REG_TIMG_BASE + 0x74) +#define TIMG_INT_RAW_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x74) /** TIMG_T0_INT_RAW : R/SS/WTC; bitpos: [0]; default: 0; * The raw interrupt status bit for the TIMG_T$x_INT interrupt. */ @@ -474,7 +474,7 @@ extern "C" { /** TIMG_INT_ST_TIMERS_REG register * Masked interrupt status */ -#define TIMG_INT_ST_TIMERS_REG (DR_REG_TIMG_BASE + 0x78) +#define TIMG_INT_ST_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x78) /** TIMG_T0_INT_ST : RO; bitpos: [0]; default: 0; * The masked interrupt status bit for the TIMG_T$x_INT interrupt. */ @@ -493,7 +493,7 @@ extern "C" { /** TIMG_INT_CLR_TIMERS_REG register * Interrupt clear bits */ -#define TIMG_INT_CLR_TIMERS_REG (DR_REG_TIMG_BASE + 0x7c) +#define TIMG_INT_CLR_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x7c) /** TIMG_T0_INT_CLR : WT; bitpos: [0]; default: 0; * Set this bit to clear the TIMG_T$x_INT interrupt. */ @@ -539,7 +539,7 @@ extern "C" { /** TIMG_NTIMERS_DATE_REG register * Timer version control register */ -#define TIMG_NTIMERS_DATE_REG (DR_REG_TIMG_BASE + 0xf8) +#define TIMG_NTIMERS_DATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xf8) /** TIMG_NTIMGS_DATE : R/W; bitpos: [27:0]; default: 33579409; * Timer version control register */ @@ -551,7 +551,7 @@ extern "C" { /** TIMG_REGCLK_REG register * Timer group clock gate register */ -#define TIMG_REGCLK_REG (DR_REG_TIMG_BASE + 0xfc) +#define TIMG_REGCLK_REG(i) (DR_REG_TIMG_BASE(i) + 0xfc) /** TIMG_WDT_CLK_IS_ACTIVE : R/W; bitpos: [29]; default: 1; * enable WDT's clock */ diff --git a/components/soc/esp32h2/include/soc/timer_group_reg.h b/components/soc/esp32h2/include/soc/timer_group_reg.h index 35f29209aa..4d591035fc 100644 --- a/components/soc/esp32h2/include/soc/timer_group_reg.h +++ b/components/soc/esp32h2/include/soc/timer_group_reg.h @@ -35,7 +35,7 @@ extern "C" { /** TIMG_T0CONFIG_REG register * Timer 0 configuration register */ -#define TIMG_T0CONFIG_REG (DR_REG_TIMG_BASE + 0x0) +#define TIMG_T0CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x0) /** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source * clock of timer group. @@ -92,7 +92,7 @@ extern "C" { /** TIMG_T0LO_REG register * Timer 0 current value, low 32 bits */ -#define TIMG_T0LO_REG (DR_REG_TIMG_BASE + 0x4) +#define TIMG_T0LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x4) /** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; * After writing to TIMG_T0UPDATE_REG, the low 32 bits of the time-base counter * of timer 0 can be read here. @@ -105,7 +105,7 @@ extern "C" { /** TIMG_T0HI_REG register * Timer $x current value, high 22 bits */ -#define TIMG_T0HI_REG (DR_REG_TIMG_BASE + 0x8) +#define TIMG_T0HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x8) /** TIMG_T0_HI : RO; bitpos: [21:0]; default: 0; * After writing to TIMG_T$xUPDATE_REG, the high 22 bits of the time-base counter * of timer $x can be read here. @@ -118,7 +118,7 @@ extern "C" { /** TIMG_T0UPDATE_REG register * Write to copy current timer value to TIMGn_T$x_(LO/HI)_REG */ -#define TIMG_T0UPDATE_REG (DR_REG_TIMG_BASE + 0xc) +#define TIMG_T0UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xc) /** TIMG_T0_UPDATE : R/W/SC; bitpos: [31]; default: 0; * After writing 0 or 1 to TIMG_T$xUPDATE_REG, the counter value is latched. */ @@ -130,7 +130,7 @@ extern "C" { /** TIMG_T0ALARMLO_REG register * Timer $x alarm value, low 32 bits */ -#define TIMG_T0ALARMLO_REG (DR_REG_TIMG_BASE + 0x10) +#define TIMG_T0ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x10) /** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Timer $x alarm trigger time-base counter value, low 32 bits. */ @@ -142,7 +142,7 @@ extern "C" { /** TIMG_T0ALARMHI_REG register * Timer $x alarm value, high bits */ -#define TIMG_T0ALARMHI_REG (DR_REG_TIMG_BASE + 0x14) +#define TIMG_T0ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x14) /** TIMG_T0_ALARM_HI : R/W; bitpos: [21:0]; default: 0; * Timer $x alarm trigger time-base counter value, high 22 bits. */ @@ -154,7 +154,7 @@ extern "C" { /** TIMG_T0LOADLO_REG register * Timer $x reload value, low 32 bits */ -#define TIMG_T0LOADLO_REG (DR_REG_TIMG_BASE + 0x18) +#define TIMG_T0LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x18) /** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * Low 32 bits of the value that a reload will load onto timer $x time-base * Counter. @@ -167,7 +167,7 @@ extern "C" { /** TIMG_T0LOADHI_REG register * Timer $x reload value, high 22 bits */ -#define TIMG_T0LOADHI_REG (DR_REG_TIMG_BASE + 0x1c) +#define TIMG_T0LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x1c) /** TIMG_T0_LOAD_HI : R/W; bitpos: [21:0]; default: 0; * High 22 bits of the value that a reload will load onto timer $x time-base * counter. @@ -180,7 +180,7 @@ extern "C" { /** TIMG_T0LOAD_REG register * Write to reload timer from TIMG_T$x_(LOADLOLOADHI)_REG */ -#define TIMG_T0LOAD_REG (DR_REG_TIMG_BASE + 0x20) +#define TIMG_T0LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x20) /** TIMG_T0_LOAD : WT; bitpos: [31:0]; default: 0; * * Write any value to trigger a timer $x time-base counter reload. @@ -193,7 +193,7 @@ extern "C" { /** TIMG_WDTCONFIG0_REG register * Watchdog timer configuration register */ -#define TIMG_WDTCONFIG0_REG (DR_REG_TIMG_BASE + 0x48) +#define TIMG_WDTCONFIG0_REG(i) (DR_REG_TIMG_BASE(i) + 0x48) /** TIMG_WDT_APPCPU_RESET_EN : R/W; bitpos: [12]; default: 0; * WDT reset CPU enable. */ @@ -284,7 +284,7 @@ extern "C" { /** TIMG_WDTCONFIG1_REG register * Watchdog timer prescaler register */ -#define TIMG_WDTCONFIG1_REG (DR_REG_TIMG_BASE + 0x4c) +#define TIMG_WDTCONFIG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x4c) /** TIMG_WDT_DIVCNT_RST : WT; bitpos: [0]; default: 0; * When set, WDT 's clock divider counter will be reset. */ @@ -304,7 +304,7 @@ extern "C" { /** TIMG_WDTCONFIG2_REG register * Watchdog timer stage 0 timeout value */ -#define TIMG_WDTCONFIG2_REG (DR_REG_TIMG_BASE + 0x50) +#define TIMG_WDTCONFIG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x50) /** TIMG_WDT_STG0_HOLD : R/W; bitpos: [31:0]; default: 26000000; * Stage 0 timeout value, in MWDT clock cycles. */ @@ -316,7 +316,7 @@ extern "C" { /** TIMG_WDTCONFIG3_REG register * Watchdog timer stage 1 timeout value */ -#define TIMG_WDTCONFIG3_REG (DR_REG_TIMG_BASE + 0x54) +#define TIMG_WDTCONFIG3_REG(i) (DR_REG_TIMG_BASE(i) + 0x54) /** TIMG_WDT_STG1_HOLD : R/W; bitpos: [31:0]; default: 134217727; * Stage 1 timeout value, in MWDT clock cycles. */ @@ -328,7 +328,7 @@ extern "C" { /** TIMG_WDTCONFIG4_REG register * Watchdog timer stage 2 timeout value */ -#define TIMG_WDTCONFIG4_REG (DR_REG_TIMG_BASE + 0x58) +#define TIMG_WDTCONFIG4_REG(i) (DR_REG_TIMG_BASE(i) + 0x58) /** TIMG_WDT_STG2_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 2 timeout value, in MWDT clock cycles. */ @@ -340,7 +340,7 @@ extern "C" { /** TIMG_WDTCONFIG5_REG register * Watchdog timer stage 3 timeout value */ -#define TIMG_WDTCONFIG5_REG (DR_REG_TIMG_BASE + 0x5c) +#define TIMG_WDTCONFIG5_REG(i) (DR_REG_TIMG_BASE(i) + 0x5c) /** TIMG_WDT_STG3_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 3 timeout value, in MWDT clock cycles. */ @@ -352,7 +352,7 @@ extern "C" { /** TIMG_WDTFEED_REG register * Write to feed the watchdog timer */ -#define TIMG_WDTFEED_REG (DR_REG_TIMG_BASE + 0x60) +#define TIMG_WDTFEED_REG(i) (DR_REG_TIMG_BASE(i) + 0x60) /** TIMG_WDT_FEED : WT; bitpos: [31:0]; default: 0; * Write any value to feed the MWDT. (WO) */ @@ -364,7 +364,7 @@ extern "C" { /** TIMG_WDTWPROTECT_REG register * Watchdog write protect register */ -#define TIMG_WDTWPROTECT_REG (DR_REG_TIMG_BASE + 0x64) +#define TIMG_WDTWPROTECT_REG(i) (DR_REG_TIMG_BASE(i) + 0x64) /** TIMG_WDT_WKEY : R/W; bitpos: [31:0]; default: 1356348065; * If the register contains a different value than its reset value, write * protection is enabled. @@ -436,7 +436,7 @@ extern "C" { /** TIMG_INT_ENA_TIMERS_REG register * Interrupt enable bits */ -#define TIMG_INT_ENA_TIMERS_REG (DR_REG_TIMG_BASE + 0x70) +#define TIMG_INT_ENA_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x70) /** TIMG_T0_INT_ENA : R/W; bitpos: [0]; default: 0; * The interrupt enable bit for the TIMG_T$x_INT interrupt. */ @@ -455,7 +455,7 @@ extern "C" { /** TIMG_INT_RAW_TIMERS_REG register * Raw interrupt status */ -#define TIMG_INT_RAW_TIMERS_REG (DR_REG_TIMG_BASE + 0x74) +#define TIMG_INT_RAW_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x74) /** TIMG_T0_INT_RAW : R/SS/WTC; bitpos: [0]; default: 0; * The raw interrupt status bit for the TIMG_T$x_INT interrupt. */ @@ -474,7 +474,7 @@ extern "C" { /** TIMG_INT_ST_TIMERS_REG register * Masked interrupt status */ -#define TIMG_INT_ST_TIMERS_REG (DR_REG_TIMG_BASE + 0x78) +#define TIMG_INT_ST_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x78) /** TIMG_T0_INT_ST : RO; bitpos: [0]; default: 0; * The masked interrupt status bit for the TIMG_T$x_INT interrupt. */ @@ -493,7 +493,7 @@ extern "C" { /** TIMG_INT_CLR_TIMERS_REG register * Interrupt clear bits */ -#define TIMG_INT_CLR_TIMERS_REG (DR_REG_TIMG_BASE + 0x7c) +#define TIMG_INT_CLR_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x7c) /** TIMG_T0_INT_CLR : WT; bitpos: [0]; default: 0; * Set this bit to clear the TIMG_T$x_INT interrupt. */ @@ -539,7 +539,7 @@ extern "C" { /** TIMG_NTIMERS_DATE_REG register * Timer version control register */ -#define TIMG_NTIMERS_DATE_REG (DR_REG_TIMG_BASE + 0xf8) +#define TIMG_NTIMERS_DATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xf8) /** TIMG_NTIMGS_DATE : R/W; bitpos: [27:0]; default: 33579409; * Timer version control register */ @@ -551,7 +551,7 @@ extern "C" { /** TIMG_REGCLK_REG register * Timer group clock gate register */ -#define TIMG_REGCLK_REG (DR_REG_TIMG_BASE + 0xfc) +#define TIMG_REGCLK_REG(i) (DR_REG_TIMG_BASE(i) + 0xfc) /** TIMG_WDT_CLK_IS_ACTIVE : R/W; bitpos: [29]; default: 1; * enable WDT's clock */ diff --git a/components/soc/esp32s2/include/soc/timer_group_reg.h b/components/soc/esp32s2/include/soc/timer_group_reg.h index 8fb0e517ad..a74c3e2e5e 100644 --- a/components/soc/esp32s2/include/soc/timer_group_reg.h +++ b/components/soc/esp32s2/include/soc/timer_group_reg.h @@ -35,7 +35,7 @@ extern "C" { /** TIMG_T0CONFIG_REG register * Timer 0 configuration register */ -#define TIMG_T0CONFIG_REG (DR_REG_TIMG_BASE + 0x0) +#define TIMG_T0CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x0) /** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source * clock of timer group. @@ -101,7 +101,7 @@ extern "C" { /** TIMG_T0LO_REG register * Timer 0 current value, low 32 bits */ -#define TIMG_T0LO_REG (DR_REG_TIMG_BASE + 0x4) +#define TIMG_T0LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x4) /** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; * After writing to TIMG_T0UPDATE_REG, the low 32 bits of the time-base counter * @@ -115,7 +115,7 @@ extern "C" { /** TIMG_T0HI_REG register * Timer 0 current value, high 32 bits */ -#define TIMG_T0HI_REG (DR_REG_TIMG_BASE + 0x8) +#define TIMG_T0HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x8) /** TIMG_T0_HI : RO; bitpos: [31:0]; default: 0; * After writing to TIMG_T0UPDATE_REG, the high 32 bits of the time-base counter * @@ -129,7 +129,7 @@ extern "C" { /** TIMG_T0UPDATE_REG register * Write to copy current timer value to TIMGn_T0_(LO/HI)_REG */ -#define TIMG_T0UPDATE_REG (DR_REG_TIMG_BASE + 0xc) +#define TIMG_T0UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xc) /** TIMG_T0_UPDATE : R/W; bitpos: [31]; default: 0; * After writing 0 or 1 to TIMG_T0UPDATE_REG, the counter value is latched. */ @@ -141,7 +141,7 @@ extern "C" { /** TIMG_T0ALARMLO_REG register * Timer 0 alarm value, low 32 bits */ -#define TIMG_T0ALARMLO_REG (DR_REG_TIMG_BASE + 0x10) +#define TIMG_T0ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x10) /** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Timer 0 alarm trigger time-base counter value, low 32 bits. */ @@ -153,7 +153,7 @@ extern "C" { /** TIMG_T0ALARMHI_REG register * Timer 0 alarm value, high bits */ -#define TIMG_T0ALARMHI_REG (DR_REG_TIMG_BASE + 0x14) +#define TIMG_T0ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x14) /** TIMG_T0_ALARM_HI : R/W; bitpos: [31:0]; default: 0; * * @@ -167,7 +167,7 @@ extern "C" { /** TIMG_T0LOADLO_REG register * Timer 0 reload value, low 32 bits */ -#define TIMG_T0LOADLO_REG (DR_REG_TIMG_BASE + 0x18) +#define TIMG_T0LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x18) /** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * * @@ -183,7 +183,7 @@ extern "C" { /** TIMG_T0LOADHI_REG register * Timer 0 reload value, high 32 bits */ -#define TIMG_T0LOADHI_REG (DR_REG_TIMG_BASE + 0x1c) +#define TIMG_T0LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x1c) /** TIMG_T0_LOAD_HI : R/W; bitpos: [31:0]; default: 0; * * @@ -199,7 +199,7 @@ extern "C" { /** TIMG_T0LOAD_REG register * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG */ -#define TIMG_T0LOAD_REG (DR_REG_TIMG_BASE + 0x20) +#define TIMG_T0LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x20) /** TIMG_T0_LOAD : WO; bitpos: [31:0]; default: 0; * * @@ -213,7 +213,7 @@ extern "C" { /** TIMG_T1CONFIG_REG register * Timer 1 configuration register */ -#define TIMG_T1CONFIG_REG (DR_REG_TIMG_BASE + 0x24) +#define TIMG_T1CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x24) /** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source * clock of timer group. @@ -279,7 +279,7 @@ extern "C" { /** TIMG_T1LO_REG register * Timer 1 current value, low 32 bits */ -#define TIMG_T1LO_REG (DR_REG_TIMG_BASE + 0x28) +#define TIMG_T1LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x28) /** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; * After writing to TIMG_T1UPDATE_REG, the low 32 bits of the time-base counter * @@ -293,7 +293,7 @@ extern "C" { /** TIMG_T1HI_REG register * Timer 1 current value, high 32 bits */ -#define TIMG_T1HI_REG (DR_REG_TIMG_BASE + 0x2c) +#define TIMG_T1HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x2c) /** TIMG_T0_HI : RO; bitpos: [31:0]; default: 0; * After writing to TIMG_T1UPDATE_REG, the high 32 bits of the time-base counter * @@ -307,7 +307,7 @@ extern "C" { /** TIMG_T1UPDATE_REG register * Write to copy current timer value to TIMGn_T1_(LO/HI)_REG */ -#define TIMG_T1UPDATE_REG (DR_REG_TIMG_BASE + 0x30) +#define TIMG_T1UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0x30) /** TIMG_T0_UPDATE : R/W; bitpos: [31]; default: 0; * After writing 0 or 1 to TIMG_T1UPDATE_REG, the counter value is latched. */ @@ -319,7 +319,7 @@ extern "C" { /** TIMG_T1ALARMLO_REG register * Timer 1 alarm value, low 32 bits */ -#define TIMG_T1ALARMLO_REG (DR_REG_TIMG_BASE + 0x34) +#define TIMG_T1ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x34) /** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Timer 1 alarm trigger time-base counter value, low 32 bits. */ @@ -331,7 +331,7 @@ extern "C" { /** TIMG_T1ALARMHI_REG register * Timer 1 alarm value, high bits */ -#define TIMG_T1ALARMHI_REG (DR_REG_TIMG_BASE + 0x38) +#define TIMG_T1ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x38) /** TIMG_T0_ALARM_HI : R/W; bitpos: [31:0]; default: 0; * * @@ -345,7 +345,7 @@ extern "C" { /** TIMG_T1LOADLO_REG register * Timer 1 reload value, low 32 bits */ -#define TIMG_T1LOADLO_REG (DR_REG_TIMG_BASE + 0x3c) +#define TIMG_T1LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x3c) /** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * * @@ -361,7 +361,7 @@ extern "C" { /** TIMG_T1LOADHI_REG register * Timer 1 reload value, high 32 bits */ -#define TIMG_T1LOADHI_REG (DR_REG_TIMG_BASE + 0x40) +#define TIMG_T1LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x40) /** TIMG_T0_LOAD_HI : R/W; bitpos: [31:0]; default: 0; * * @@ -377,7 +377,7 @@ extern "C" { /** TIMG_T1LOAD_REG register * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG */ -#define TIMG_T1LOAD_REG (DR_REG_TIMG_BASE + 0x44) +#define TIMG_T1LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x44) /** TIMG_T0_LOAD : WO; bitpos: [31:0]; default: 0; * * @@ -391,7 +391,7 @@ extern "C" { /** TIMG_WDTCONFIG0_REG register * Watchdog timer configuration register */ -#define TIMG_WDTCONFIG0_REG (DR_REG_TIMG_BASE + 0x48) +#define TIMG_WDTCONFIG0_REG(i) (DR_REG_TIMG_BASE(i) + 0x48) /** TIMG_WDT_APPCPU_RESET_EN : R/W; bitpos: [12]; default: 0; * Reserved */ @@ -492,7 +492,7 @@ extern "C" { /** TIMG_WDTCONFIG1_REG register * Watchdog timer prescaler register */ -#define TIMG_WDTCONFIG1_REG (DR_REG_TIMG_BASE + 0x4c) +#define TIMG_WDTCONFIG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x4c) /** TIMG_WDT_CLK_PRESCALER : R/W; bitpos: [31:16]; default: 1; * MWDT clock prescaler value. MWDT clock period = 12.5 ns * * @@ -506,7 +506,7 @@ extern "C" { /** TIMG_WDTCONFIG2_REG register * Watchdog timer stage 0 timeout value */ -#define TIMG_WDTCONFIG2_REG (DR_REG_TIMG_BASE + 0x50) +#define TIMG_WDTCONFIG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x50) /** TIMG_WDT_STG0_HOLD : R/W; bitpos: [31:0]; default: 26000000; * Stage 0 timeout value, in MWDT clock cycles. */ @@ -518,7 +518,7 @@ extern "C" { /** TIMG_WDTCONFIG3_REG register * Watchdog timer stage 1 timeout value */ -#define TIMG_WDTCONFIG3_REG (DR_REG_TIMG_BASE + 0x54) +#define TIMG_WDTCONFIG3_REG(i) (DR_REG_TIMG_BASE(i) + 0x54) /** TIMG_WDT_STG1_HOLD : R/W; bitpos: [31:0]; default: 134217727; * Stage 1 timeout value, in MWDT clock cycles. */ @@ -530,7 +530,7 @@ extern "C" { /** TIMG_WDTCONFIG4_REG register * Watchdog timer stage 2 timeout value */ -#define TIMG_WDTCONFIG4_REG (DR_REG_TIMG_BASE + 0x58) +#define TIMG_WDTCONFIG4_REG(i) (DR_REG_TIMG_BASE(i) + 0x58) /** TIMG_WDT_STG2_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 2 timeout value, in MWDT clock cycles. */ @@ -542,7 +542,7 @@ extern "C" { /** TIMG_WDTCONFIG5_REG register * Watchdog timer stage 3 timeout value */ -#define TIMG_WDTCONFIG5_REG (DR_REG_TIMG_BASE + 0x5c) +#define TIMG_WDTCONFIG5_REG(i) (DR_REG_TIMG_BASE(i) + 0x5c) /** TIMG_WDT_STG3_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 3 timeout value, in MWDT clock cycles. */ @@ -554,7 +554,7 @@ extern "C" { /** TIMG_WDTFEED_REG register * Write to feed the watchdog timer */ -#define TIMG_WDTFEED_REG (DR_REG_TIMG_BASE + 0x60) +#define TIMG_WDTFEED_REG(i) (DR_REG_TIMG_BASE(i) + 0x60) /** TIMG_WDT_FEED : WO; bitpos: [31:0]; default: 0; * Write any value to feed the MWDT. (WO) */ @@ -566,7 +566,7 @@ extern "C" { /** TIMG_WDTWPROTECT_REG register * Watchdog write protect register */ -#define TIMG_WDTWPROTECT_REG (DR_REG_TIMG_BASE + 0x64) +#define TIMG_WDTWPROTECT_REG(i) (DR_REG_TIMG_BASE(i) + 0x64) /** TIMG_WDT_WKEY : R/W; bitpos: [31:0]; default: 1356348065; * If the register contains a different value than its reset value, write * @@ -639,7 +639,7 @@ extern "C" { /** TIMG_LACTCONFIG_REG register * LACT configuration register */ -#define TIMG_LACTCONFIG_REG (DR_REG_TIMG_BASE + 0x70) +#define TIMG_LACTCONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x70) /** TIMG_LACT_USE_REFTICK : R/W; bitpos: [6]; default: 0; * Reserved */ @@ -721,7 +721,7 @@ extern "C" { /** TIMG_LACTRTC_REG register * LACT RTC register */ -#define TIMG_LACTRTC_REG (DR_REG_TIMG_BASE + 0x74) +#define TIMG_LACTRTC_REG(i) (DR_REG_TIMG_BASE(i) + 0x74) /** TIMG_LACT_RTC_STEP_LEN : R/W; bitpos: [31:6]; default: 0; * Reserved */ @@ -733,7 +733,7 @@ extern "C" { /** TIMG_LACTLO_REG register * LACT low register */ -#define TIMG_LACTLO_REG (DR_REG_TIMG_BASE + 0x78) +#define TIMG_LACTLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x78) /** TIMG_LACT_LO : RO; bitpos: [31:0]; default: 0; * Reserved */ @@ -745,7 +745,7 @@ extern "C" { /** TIMG_LACTHI_REG register * LACT high register */ -#define TIMG_LACTHI_REG (DR_REG_TIMG_BASE + 0x7c) +#define TIMG_LACTHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x7c) /** TIMG_LACT_HI : RO; bitpos: [31:0]; default: 0; * Reserved */ @@ -757,7 +757,7 @@ extern "C" { /** TIMG_LACTUPDATE_REG register * LACT update register */ -#define TIMG_LACTUPDATE_REG (DR_REG_TIMG_BASE + 0x80) +#define TIMG_LACTUPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0x80) /** TIMG_LACT_UPDATE : WO; bitpos: [31:0]; default: 0; * Reserved */ @@ -769,7 +769,7 @@ extern "C" { /** TIMG_LACTALARMLO_REG register * LACT alarm low register */ -#define TIMG_LACTALARMLO_REG (DR_REG_TIMG_BASE + 0x84) +#define TIMG_LACTALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x84) /** TIMG_LACT_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Reserved */ @@ -781,7 +781,7 @@ extern "C" { /** TIMG_LACTALARMHI_REG register * LACT alarm high register */ -#define TIMG_LACTALARMHI_REG (DR_REG_TIMG_BASE + 0x88) +#define TIMG_LACTALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x88) /** TIMG_LACT_ALARM_HI : R/W; bitpos: [31:0]; default: 0; * Reserved */ @@ -793,7 +793,7 @@ extern "C" { /** TIMG_LACTLOADLO_REG register * LACT load low register */ -#define TIMG_LACTLOADLO_REG (DR_REG_TIMG_BASE + 0x8c) +#define TIMG_LACTLOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x8c) /** TIMG_LACT_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * Reserved */ @@ -805,7 +805,7 @@ extern "C" { /** TIMG_LACTLOADHI_REG register * Timer LACT load high register */ -#define TIMG_LACTLOADHI_REG (DR_REG_TIMG_BASE + 0x90) +#define TIMG_LACTLOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x90) /** TIMG_LACT_LOAD_HI : R/W; bitpos: [31:0]; default: 0; * Reserved */ @@ -817,7 +817,7 @@ extern "C" { /** TIMG_LACTLOAD_REG register * Timer LACT load register */ -#define TIMG_LACTLOAD_REG (DR_REG_TIMG_BASE + 0x94) +#define TIMG_LACTLOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x94) /** TIMG_LACT_LOAD : WO; bitpos: [31:0]; default: 0; * Reserved */ @@ -829,7 +829,7 @@ extern "C" { /** TIMG_INT_ENA_TIMERS_REG register * Interrupt enable bits */ -#define TIMG_INT_ENA_TIMERS_REG (DR_REG_TIMG_BASE + 0x98) +#define TIMG_INT_ENA_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x98) /** TIMG_T0_INT_ENA : R/W; bitpos: [0]; default: 0; * The interrupt enable bit for the TIMG_T0_INT interrupt. */ @@ -862,7 +862,7 @@ extern "C" { /** TIMG_INT_RAW_TIMERS_REG register * Raw interrupt status */ -#define TIMG_INT_RAW_TIMERS_REG (DR_REG_TIMG_BASE + 0x9c) +#define TIMG_INT_RAW_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x9c) /** TIMG_T0_INT_RAW : RO; bitpos: [0]; default: 0; * The raw interrupt status bit for the TIMG_T0_INT interrupt. */ @@ -895,7 +895,7 @@ extern "C" { /** TIMG_INT_ST_TIMERS_REG register * Masked interrupt status */ -#define TIMG_INT_ST_TIMERS_REG (DR_REG_TIMG_BASE + 0xa0) +#define TIMG_INT_ST_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0xa0) /** TIMG_T0_INT_ST : RO; bitpos: [0]; default: 0; * The masked interrupt status bit for the TIMG_T0_INT interrupt. */ @@ -928,7 +928,7 @@ extern "C" { /** TIMG_INT_CLR_TIMERS_REG register * Interrupt clear bits */ -#define TIMG_INT_CLR_TIMERS_REG (DR_REG_TIMG_BASE + 0xa4) +#define TIMG_INT_CLR_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0xa4) /** TIMG_T0_INT_CLR : WO; bitpos: [0]; default: 0; * Set this bit to clear the TIMG_T0_INT interrupt. */ @@ -988,7 +988,7 @@ extern "C" { /** TIMG_TIMERS_DATE_REG register * Version control register */ -#define TIMG_TIMERS_DATE_REG (DR_REG_TIMG_BASE + 0xf8) +#define TIMG_TIMERS_DATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xf8) /** TIMG_TIMERS_DATE : R/W; bitpos: [27:0]; default: 26243681; * Version control register. */ @@ -1000,7 +1000,7 @@ extern "C" { /** TIMG_REGCLK_REG register * Timer group clock gate register */ -#define TIMG_REGCLK_REG (DR_REG_TIMG_BASE + 0xfc) +#define TIMG_REGCLK_REG(i) (DR_REG_TIMG_BASE(i) + 0xfc) /** TIMG_CLK_EN : R/W; bitpos: [31]; default: 0; * Register clock gate signal. 1: Registers can be read and written to by software. 0: * Registers can not be read or written to by software. From 5f2a66a8a5ecab94f39752c4cbcfd18e15ae7fca Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Mon, 30 Aug 2021 14:45:31 +0800 Subject: [PATCH 078/310] freertos: Reduce ESP specific code --- components/freertos/event_groups.c | 40 ++-- components/freertos/include/freertos/task.h | 28 ++- components/freertos/queue.c | 150 ++++++------ components/freertos/stream_buffer.c | 34 ++- components/freertos/tasks.c | 241 +++++++++++--------- components/freertos/timers.c | 44 ++-- 6 files changed, 314 insertions(+), 223 deletions(-) diff --git a/components/freertos/event_groups.c b/components/freertos/event_groups.c index 34150e490c..c3ad94f214 100644 --- a/components/freertos/event_groups.c +++ b/components/freertos/event_groups.c @@ -38,6 +38,18 @@ #include "timers.h" #include "event_groups.h" +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &pxEventBits->eventGroupMux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the @@ -212,7 +224,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, } #endif - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); + taskENTER_CRITICAL(); { uxOriginalBitValue = pxEventBits->uxEventBits; @@ -255,7 +267,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, } } } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + taskEXIT_CRITICAL(); if( xTicksToWait != ( TickType_t ) 0 ) { @@ -270,7 +282,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) { /* The task timed out, just return the current event bit value. */ - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); + taskENTER_CRITICAL(); { uxReturn = pxEventBits->uxEventBits; @@ -287,7 +299,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + taskEXIT_CRITICAL(); xTimeoutOccurred = pdTRUE; } @@ -332,7 +344,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, } #endif - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); + taskENTER_CRITICAL(); { const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; @@ -400,7 +412,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); } } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + taskEXIT_CRITICAL(); if( xTicksToWait != ( TickType_t ) 0 ) { @@ -414,7 +426,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) { - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); + taskENTER_CRITICAL(); { /* The task timed out, just return the current event bit value. */ uxReturn = pxEventBits->uxEventBits; @@ -439,7 +451,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, xTimeoutOccurred = pdTRUE; } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + taskEXIT_CRITICAL(); } else { @@ -470,7 +482,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, configASSERT( xEventGroup ); configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); + taskENTER_CRITICAL(); { traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); @@ -481,7 +493,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, /* Clear the bits. */ pxEventBits->uxEventBits &= ~uxBitsToClear; } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + taskEXIT_CRITICAL(); return uxReturn; } @@ -536,7 +548,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, pxList = &( pxEventBits->xTasksWaitingForBits ); pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); + taskENTER_CRITICAL(); { traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); @@ -608,7 +620,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, * bit was set in the control word. */ pxEventBits->uxEventBits &= ~uxBitsToClear; } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + taskEXIT_CRITICAL(); return pxEventBits->uxEventBits; } @@ -621,7 +633,7 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) traceEVENT_GROUP_DELETE( xEventGroup ); - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); + taskENTER_CRITICAL(); { while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) { @@ -631,7 +643,7 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); } } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + taskEXIT_CRITICAL(); #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) { diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index d443179701..8220b55478 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -203,9 +203,18 @@ typedef enum * @endcond * \ingroup SchedulerControl */ -#define taskENTER_CRITICAL( x ) portENTER_CRITICAL( x ) +#ifdef ESP_PLATFORM +#define taskENTER_CRITICAL( x ) portENTER_CRITICAL( x ) +#else +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( ) +#endif // ESP_PLATFORM #define taskENTER_CRITICAL_FROM_ISR( ) portSET_INTERRUPT_MASK_FROM_ISR() -#define taskENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) + +#ifdef ESP_PLATFORM +#define taskENTER_CRITICAL_ISR( x ) portENTER_CRITICAL_ISR( x ) +#else +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( ) +#endif // ESP_PLATFORM /** * task. h @@ -221,10 +230,19 @@ typedef enum * @endcond * \ingroup SchedulerControl */ -#define taskEXIT_CRITICAL( x ) portEXIT_CRITICAL( x ) -#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) -#define taskEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) +#ifdef ESP_PLATFORM +#define taskEXIT_CRITICAL( x ) portEXIT_CRITICAL( x ) +#else +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( ) +#endif // ESP_PLATFORM +#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) + +#ifdef ESP_PLATFORM +#define taskEXIT_CRITICAL_ISR( x ) portEXIT_CRITICAL_ISR( x ) +#else +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( ) +#endif // ESP_PLATFORM /** * task. h * diff --git a/components/freertos/queue.c b/components/freertos/queue.c index 97b32f4611..2557117988 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -40,6 +40,18 @@ #include "croutine.h" #endif +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &((Queue_t *)pxQueue)->mux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the @@ -252,7 +264,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, * accessing the queue event lists. */ #define prvLockQueue( pxQueue ) \ - taskENTER_CRITICAL( &pxQueue->mux ); \ + taskENTER_CRITICAL(); \ { \ if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ { \ @@ -263,7 +275,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ } \ } \ - taskEXIT_CRITICAL( &pxQueue->mux ) + taskEXIT_CRITICAL() /*-----------------------------------------------------------*/ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, @@ -278,7 +290,7 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, vPortCPUInitializeMutex(&pxQueue->mux); } - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; @@ -317,7 +329,7 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); } } - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); /* A value is returned for calling semantic consistency with previous * versions. */ @@ -585,7 +597,10 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, * calling task is the mutex holder, but not a good way of determining the * identity of the mutex holder, as the holder may change between the * following critical section exiting and the function returning. */ - taskENTER_CRITICAL( &pxSemaphore->mux ); +#ifdef ESP_PLATFORM + Queue_t * const pxQueue = (Queue_t *)pxSemaphore; +#endif + taskENTER_CRITICAL(); { if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX ) { @@ -596,7 +611,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, pxReturn = NULL; } } - taskEXIT_CRITICAL( &pxSemaphore->mux ); + taskEXIT_CRITICAL(); return pxReturn; } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ @@ -816,7 +831,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, * interest of execution time efficiency. */ for( ; ; ) { - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { /* Is there room on the queue now? The running task must be the * highest priority task wanting to access the queue. If the head item @@ -922,7 +937,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, } #endif /* configUSE_QUEUE_SETS */ - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); return pdPASS; } else @@ -931,7 +946,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, { /* The queue was full and no block time is specified (or * the block time has expired) so leave now. */ - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); /* Return to the original privilege level before exiting * the function. */ @@ -952,12 +967,12 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ - taskENTER_CRITICAL( &pxQueue->mux); + taskENTER_CRITICAL(); prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -980,7 +995,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, * task is already in the ready list before it yields - in which * case the yield will not cause a context switch unless there * is also a higher priority task in the pending ready list. */ - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); portYIELD_WITHIN_API(); } @@ -988,14 +1003,14 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, { /* Try again. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); } } else { /* The timeout has expired. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); traceQUEUE_SEND_FAILED( pxQueue ); return errQUEUE_FULL; @@ -1040,7 +1055,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, * post). */ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { - taskENTER_CRITICAL_ISR(&pxQueue->mux); + taskENTER_CRITICAL_ISR(); if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { @@ -1154,7 +1169,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, xReturn = errQUEUE_FULL; } - taskEXIT_CRITICAL_ISR( &pxQueue->mux ); + taskEXIT_CRITICAL_ISR(); } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); @@ -1204,7 +1219,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { - taskENTER_CRITICAL_ISR(&pxQueue->mux); + taskENTER_CRITICAL_ISR(); const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1323,7 +1338,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ); xReturn = errQUEUE_FULL; } - taskEXIT_CRITICAL_ISR(&pxQueue->mux); + taskEXIT_CRITICAL_ISR(); } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); @@ -1358,7 +1373,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, * interest of execution time efficiency. */ for( ; ; ) { - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1390,7 +1405,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); return pdPASS; } else @@ -1399,7 +1414,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, { /* The queue was empty and no block time is specified (or * the block time has expired) so leave now. */ - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); traceQUEUE_RECEIVE_FAILED( pxQueue ); return errQUEUE_EMPTY; } @@ -1417,12 +1432,12 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ - taskENTER_CRITICAL( &pxQueue->mux); + taskENTER_CRITICAL(); prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -1435,7 +1450,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); portYIELD_WITHIN_API(); } else @@ -1443,7 +1458,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /* The queue contains data again. Loop back to try and read the * data. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); } } else @@ -1451,7 +1466,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /* Timed out. If there is no data in the queue exit, otherwise loop * back and attempt to read the data. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { @@ -1497,7 +1512,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, * of execution time efficiency. */ for( ; ; ) { - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { /* Semaphores are queues with an item size of 0, and where the * number of messages in the queue is the semaphore's count value. */ @@ -1546,7 +1561,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); return pdPASS; } else @@ -1564,7 +1579,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, /* The semaphore count was 0 and no block time is specified * (or the block time has expired) so exit now. */ - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); traceQUEUE_RECEIVE_FAILED( pxQueue ); return errQUEUE_EMPTY; } @@ -1582,12 +1597,12 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); /* Interrupts and other tasks can give to and take from the semaphore * now the critical section has been exited. */ - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -1605,11 +1620,11 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, { if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { - taskENTER_CRITICAL( &pxQueue->mux); + taskENTER_CRITICAL(); { xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); } - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); } else { @@ -1620,7 +1635,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); portYIELD_WITHIN_API(); } else @@ -1628,14 +1643,14 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, /* There was no timeout and the semaphore count was not 0, so * attempt to take the semaphore again. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); } } else { /* Timed out. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); /* If the semaphore count is 0 exit now as the timeout has * expired. Otherwise return to attempt to take the semaphore that is @@ -1650,7 +1665,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, * test the mutex type again to check it is actually a mutex. */ if( xInheritanceOccurred != pdFALSE ) { - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { UBaseType_t uxHighestWaitingPriority; @@ -1662,7 +1677,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue ); vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); } } #endif /* configUSE_MUTEXES */ @@ -1707,7 +1722,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, * interest of execution time efficiency. */ for( ; ; ) { - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1745,7 +1760,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); return pdPASS; } else @@ -1754,7 +1769,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, { /* The queue was empty and no block time is specified (or * the block time has expired) so leave now. */ - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); traceQUEUE_PEEK_FAILED( pxQueue ); return errQUEUE_EMPTY; } @@ -1773,12 +1788,12 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, } } } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -1791,7 +1806,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, traceBLOCKING_ON_QUEUE_PEEK( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); portYIELD_WITHIN_API(); } else @@ -1799,7 +1814,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /* There is data in the queue now, so don't enter the blocked * state, instead return to try and obtain the data. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); } } else @@ -1807,7 +1822,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /* The timeout has expired. If there is still no data in the queue * exit, otherwise go back and try to read the data again. */ prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { @@ -1852,7 +1867,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { - taskENTER_CRITICAL_ISR(&pxQueue->mux); + taskENTER_CRITICAL_ISR(); const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1911,7 +1926,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, xReturn = pdFAIL; traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); } - taskEXIT_CRITICAL_ISR(&pxQueue->mux); + taskEXIT_CRITICAL_ISR(); } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); @@ -1948,7 +1963,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - taskENTER_CRITICAL_ISR(&pxQueue->mux); + taskENTER_CRITICAL_ISR(); { /* Cannot block in an ISR, so check there is data available. */ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) @@ -1969,7 +1984,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); } } - taskEXIT_CRITICAL_ISR(&pxQueue->mux); + taskEXIT_CRITICAL_ISR(); portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; @@ -1983,11 +1998,11 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) configASSERT( xQueue ); - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ @@ -2000,11 +2015,11 @@ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) configASSERT( pxQueue ); - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ @@ -2234,7 +2249,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) * removed from the queue while the queue was locked. When a queue is * locked items can be added or removed, but the event lists cannot be * updated. */ - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { int8_t cTxLock = pxQueue->cTxLock; @@ -2312,10 +2327,10 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) pxQueue->cTxLock = queueUNLOCKED; } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); /* Do the same for the Rx lock. */ - taskENTER_CRITICAL( &pxQueue->mux ); + taskENTER_CRITICAL(); { int8_t cRxLock = pxQueue->cRxLock; @@ -2342,15 +2357,14 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) pxQueue->cRxLock = queueUNLOCKED; } - taskEXIT_CRITICAL( &pxQueue->mux ); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) { BaseType_t xReturn; - Queue_t * pxQ = (Queue_t *)pxQueue; - taskENTER_CRITICAL( &pxQ->mux ); + taskENTER_CRITICAL(); { if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) { @@ -2361,7 +2375,7 @@ static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) xReturn = pdFALSE; } } - taskEXIT_CRITICAL( &pxQ->mux ); + taskEXIT_CRITICAL(); return xReturn; } @@ -2872,8 +2886,11 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) QueueSetHandle_t xQueueSet ) { BaseType_t xReturn; +#ifdef ESP_PLATFORM + Queue_t * pxQueue = (Queue_t * )xQueueOrSemaphore; +#endif - taskENTER_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux)); + taskENTER_CRITICAL(); { if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) { @@ -2892,7 +2909,7 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) xReturn = pdPASS; } } - taskEXIT_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux)); + taskEXIT_CRITICAL(); return xReturn; } @@ -2922,12 +2939,15 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } else { - taskENTER_CRITICAL(&(pxQueueOrSemaphore->mux)); +#ifdef ESP_PLATFORM + Queue_t* pxQueue = (Queue_t*)pxQueueOrSemaphore; +#endif + taskENTER_CRITICAL(); { /* The queue is no longer contained in the set. */ pxQueueOrSemaphore->pxQueueSetContainer = NULL; } - taskEXIT_CRITICAL(&(pxQueueOrSemaphore->mux)); + taskEXIT_CRITICAL(); xReturn = pdPASS; } diff --git a/components/freertos/stream_buffer.c b/components/freertos/stream_buffer.c index 41950d017f..00ea670238 100644 --- a/components/freertos/stream_buffer.c +++ b/components/freertos/stream_buffer.c @@ -38,6 +38,18 @@ #include "task.h" #include "stream_buffer.h" +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &pxStreamBuffer->xStreamBufferMux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + #if ( configUSE_TASK_NOTIFICATIONS != 1 ) #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c #endif @@ -54,7 +66,7 @@ /*lint -save -e9026 Function like macros allowed and needed here so they can be overridden. */ #ifndef sbRECEIVE_COMPLETED #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \ + taskENTER_CRITICAL(); \ { \ if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ { \ @@ -64,7 +76,7 @@ ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ } \ } \ - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskEXIT_CRITICAL(); #endif /* sbRECEIVE_COMPLETED */ #ifndef sbRECEIVE_COMPLETED_FROM_ISR @@ -93,7 +105,7 @@ * that uses task notifications. */ #ifndef sbSEND_COMPLETED #define sbSEND_COMPLETED( pxStreamBuffer ) \ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \ + taskENTER_CRITICAL(); \ { \ if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ { \ @@ -103,7 +115,7 @@ ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ } \ } \ - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskEXIT_CRITICAL(); #endif /* sbSEND_COMPLETED */ #ifndef sbSEND_COMPLETE_FROM_ISR @@ -422,7 +434,7 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) #endif /* Can only reset a message buffer if there are no tasks blocked on it. */ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskENTER_CRITICAL(); { if( pxStreamBuffer->xTaskWaitingToReceive == NULL ) { @@ -445,7 +457,7 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) } } } - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskEXIT_CRITICAL(); return xReturn; } @@ -554,7 +566,7 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, { /* Wait until the required number of bytes are free in the message * buffer. */ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskENTER_CRITICAL(); { xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); @@ -569,11 +581,11 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, } else { - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskEXIT_CRITICAL(); break; } } - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskEXIT_CRITICAL(); traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ); ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); @@ -752,7 +764,7 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, { /* Checking if there is data and clearing the notification state must be * performed atomically. */ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskENTER_CRITICAL(); { xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); @@ -775,7 +787,7 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + taskEXIT_CRITICAL(); if( xBytesAvailable <= xBytesToStoreMessageLength ) { diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index a32e517c83..4b02759566 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -39,6 +39,18 @@ #include "timers.h" #include "stack_macros.h" +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &xTaskQueueMutex +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the @@ -358,7 +370,10 @@ PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Del PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ PRIVILEGED_DATA static List_t xPendingReadyList[ portNUM_PROCESSORS ]; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ + +#ifdef ESP_PLATFORM PRIVILEGED_DATA static portMUX_TYPE xTaskQueueMutex = portMUX_INITIALIZER_UNLOCKED; +#endif // ESP_PLATFORM #if ( INCLUDE_vTaskDelete == 1 ) @@ -1173,7 +1188,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, /* Ensure interrupts don't access the task lists while the lists are being * updated. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { uxCurrentNumberOfTasks++; @@ -1267,13 +1282,13 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, portSETUP_TCB( pxNewTCB ); } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); if( xSchedulerRunning != pdFALSE ) { /* If the created task is of a higher priority than the current task * then it should run now. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); curTCB = pxCurrentTCB[ xCoreID ]; if( curTCB == NULL || curTCB->uxPriority < pxNewTCB->uxPriority ) @@ -1290,7 +1305,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } else { @@ -1308,7 +1323,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, BaseType_t core; BaseType_t xFreeNow = 0; - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { core = xPortGetCoreID(); curTCB = pxCurrentTCB[core]; @@ -1396,7 +1411,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, traceTASK_DELETE( pxTCB ); } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); if(xFreeNow == pdTRUE) { #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) @@ -1437,7 +1452,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, configASSERT( ( xTimeIncrement > 0U ) ); configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* Minor optimisation. The tick count cannot change in this * block. */ @@ -1493,7 +1508,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); /* Force a reschedule, we may have put ourselves to sleep. */ portYIELD_WITHIN_API(); @@ -1510,7 +1525,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, if( xTicksToDelay > ( TickType_t ) 0U ) { configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { traceTASK_DELAY(); @@ -1523,7 +1538,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * executing task. */ prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToDelay ); } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } else { @@ -1547,7 +1562,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, configASSERT( pxTCB ); - taskENTER_CRITICAL( &xTaskQueueMutex ); //Need critical section incase either core context switches in between + taskENTER_CRITICAL(); //Need critical section incase either core context switches in between if( pxTCB == pxCurrentTCB[xPortGetCoreID()]) { /* The task calling this function is querying its own state. */ @@ -1626,7 +1641,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, eReturn = eReady; } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return eReturn; } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ @@ -1641,14 +1656,14 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, TCB_t const * pxTCB; UBaseType_t uxReturn; - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* If null is passed in here then it is the priority of the task * that called uxTaskPriorityGet() that is being queried. */ pxTCB = prvGetTCBFromHandle( xTask ); uxReturn = pxTCB->uxPriority; } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return uxReturn; } @@ -1717,7 +1732,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, mtCOVERAGE_TEST_MARKER(); } - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* If null is passed in here then it is the priority of the calling * task that is being changed. */ @@ -1878,7 +1893,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, ( void ) uxPriorityUsedOnEntry; } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } #endif /* INCLUDE_vTaskPrioritySet */ @@ -1891,7 +1906,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, TCB_t * pxTCB; TCB_t * curTCB; - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* If null is passed in here then it is the running task that is * being suspended. */ @@ -1934,17 +1949,17 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, } #endif } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); if( xSchedulerRunning != pdFALSE ) { /* Reset the next expected unblock time in case it referred to the * task that is now in the Suspended state. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { prvResetNextTaskUnblockTime(); } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } else { @@ -1956,9 +1971,9 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, if( xSchedulerRunning != pdFALSE ) { /* The current task has just been suspended. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); BaseType_t suspended = uxSchedulerSuspended[xPortGetCoreID()]; - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); configASSERT( suspended == 0 ); (void)suspended; @@ -1975,9 +1990,9 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * NULL so when the next task is created pxCurrentTCB will * be set to point to it no matter what its relative priority * is. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); pxCurrentTCB[ xPortGetCoreID() ] = NULL; - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } else { @@ -1992,11 +2007,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, /* A task other than the currently running task was suspended, * reset the next expected unblock time in case it referred to the * task that is now in the Suspended state. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); { prvResetNextTaskUnblockTime(); } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } else { @@ -2063,7 +2078,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, /* It does not make sense to resume the calling task. */ configASSERT( xTaskToResume ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); /* The parameter cannot be NULL as it is impossible to resume the * currently executing task. */ @@ -2106,7 +2121,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } #endif /* INCLUDE_vTaskSuspend */ @@ -2140,7 +2155,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ //portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + taskENTER_CRITICAL_ISR(); { if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) { @@ -2180,7 +2195,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(); return xYieldRequired; } @@ -2394,7 +2409,7 @@ void vTaskSuspendAll( void ) TickType_t xReturn; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority > tskIDLE_PRIORITY ) { xReturn = 0; @@ -2421,7 +2436,7 @@ void vTaskSuspendAll( void ) { xReturn = xNextTaskUnblockTime - xTickCount; } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return xReturn; } @@ -2436,7 +2451,7 @@ BaseType_t xTaskResumeAll( void ) TickType_t xTicksToNextUnblockTime; /* If uxSchedulerSuspended[xPortGetCoreID()] is zero then this function does not match a - * previous call to taskENTER_CRITICAL( &xTaskQueueMutex ). */ + * previous call to taskENTER_CRITICAL(). */ configASSERT( uxSchedulerSuspended[xPortGetCoreID()] ); /* It is possible that an ISR caused a task to be removed from an event @@ -2444,7 +2459,7 @@ BaseType_t xTaskResumeAll( void ) * removed task will have been added to the xPendingReadyList. Once the * scheduler has been resumed it is safe to move all the pending ready * tasks from this list into their appropriate ready list. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { --uxSchedulerSuspended[xPortGetCoreID()]; @@ -2555,7 +2570,7 @@ BaseType_t xTaskResumeAll( void ) mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xAlreadyYielded; } @@ -2701,7 +2716,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* Search the ready lists. */ do @@ -2747,7 +2762,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char } #endif } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return pxTCB; } @@ -2763,7 +2778,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char { UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) @@ -2822,7 +2837,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return uxTask; } @@ -2860,11 +2875,11 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char /* Correct the tick count value after a period during which the tick * was suppressed. Note this does *not* call the tick hook function for * each stepped tick. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); xTickCount += xTicksToJump; traceINCREASE_TICK_COUNT( xTicksToJump ); - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } #endif /* configUSE_TICKLESS_IDLE */ @@ -2880,9 +2895,9 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */ - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); xPendedTicks += xTicksToCatchUp; - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xYieldRequired; } @@ -2897,7 +2912,7 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) configASSERT( pxTCB ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* A task can only be prematurely removed from the Blocked state if * it is actually in the Blocked state. */ @@ -2914,7 +2929,7 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) * the event list too. Interrupts can touch the event list item, * even though the scheduler is suspended, so a critical section * is used. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { @@ -2926,7 +2941,7 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); /* Place the unblocked task into the appropriate ready list. */ prvAddTaskToReadyList( pxTCB ); @@ -2960,7 +2975,7 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) xReturn = pdFAIL; } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xReturn; } @@ -2998,7 +3013,7 @@ BaseType_t xTaskIncrementTick( void ) traceTASK_INCREMENT_TICK( xTickCount ); if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) { - taskENTER_CRITICAL_ISR( &xTaskQueueMutex ); + taskENTER_CRITICAL_ISR(); /* Minor optimisation. The tick count cannot change in this * block. */ const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; @@ -3113,7 +3128,7 @@ BaseType_t xTaskIncrementTick( void ) } } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(); } else { @@ -3156,11 +3171,11 @@ BaseType_t xTaskIncrementTick( void ) /* Save the hook function in the TCB. A critical section is required as * the value can be accessed from an interrupt. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { xTCB->pxTaskTag = pxHookFunction; } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } #endif /* configUSE_APPLICATION_TASK_TAG */ @@ -3178,11 +3193,11 @@ BaseType_t xTaskIncrementTick( void ) /* Save the hook function in the TCB. A critical section is required as * the value can be accessed from an interrupt. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { xReturn = pxTCB->pxTaskTag; } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xReturn; } @@ -3280,7 +3295,7 @@ void vTaskSwitchContext( void ) * overflows. The guard against negative values is to protect * against suspect run time stat counter implementations - which * are provided by the application, not the kernel. */ - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + taskENTER_CRITICAL_ISR(); if( ulTotalRunTime > ulTaskSwitchedInTime[ xPortGetCoreID() ] ) { pxCurrentTCB[ xPortGetCoreID() ]->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime[ xPortGetCoreID() ] ); @@ -3289,7 +3304,7 @@ void vTaskSwitchContext( void ) { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(); ulTaskSwitchedInTime[ xPortGetCoreID() ] = ulTotalRunTime; } #endif /* configGENERATE_RUN_TIME_STATS */ @@ -3301,7 +3316,7 @@ void vTaskSwitchContext( void ) /* Select a new task to run */ /* - We cannot do taskENTER_CRITICAL_ISR(&xTaskQueueMutex); here because it saves the interrupt context to the task tcb, and we're + We cannot do taskENTER_CRITICAL_ISR(); here because it saves the interrupt context to the task tcb, and we're swapping that out here. Instead, we're going to do the work here ourselves. Because interrupts are already disabled, we only need to acquire the mutex. */ @@ -3405,9 +3420,11 @@ void vTaskSwitchContext( void ) traceTASK_SWITCHED_IN(); xSwitchingContext[ xPortGetCoreID() ] = pdFALSE; +#ifdef ESP_PLATFORM //Exit critical region manually as well: release the mux now, interrupts will be re-enabled when we //exit the function. vPortCPUReleaseMutex( &xTaskQueueMutex ); +#endif // ESP_PLATFORM #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK vPortSetStackWatchpoint(pxCurrentTCB[xPortGetCoreID()]->pxStack); @@ -3421,7 +3438,7 @@ void vTaskSwitchContext( void ) void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) { configASSERT( pxEventList ); - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ @@ -3433,14 +3450,14 @@ void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksT vListInsert( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait); - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) { configASSERT( pxEventList ); - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); /* Store the item value in the event list item. It is safe to access the * event list item here as interrupts won't access the event list item of a @@ -3455,7 +3472,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte vListInsertEnd( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ @@ -3463,7 +3480,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); configASSERT( pxEventList ); /* This function should not be called by application code hence the @@ -3488,7 +3505,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte traceTASK_DELAY_UNTIL( ); prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } #endif /* configUSE_TIMERS */ @@ -3501,7 +3518,7 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) BaseType_t xTaskCanBeReady; UBaseType_t i, uxTargetCPU; - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + taskENTER_CRITICAL_ISR(); /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be * called from a critical section within an ISR. */ @@ -3523,7 +3540,7 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) } else { - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(); return pdFALSE; } @@ -3593,7 +3610,7 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) } #endif - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(); return xReturn; } /*-----------------------------------------------------------*/ @@ -3603,7 +3620,7 @@ BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, cons TCB_t * pxUnblockedTCB; BaseType_t xReturn; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); /* Store the new item value in the event list. */ listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); @@ -3642,7 +3659,7 @@ BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, cons xReturn = pdFALSE; } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return xReturn; } /*-----------------------------------------------------------*/ @@ -3650,12 +3667,12 @@ BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, cons void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) { configASSERT( pxTimeOut ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { pxTimeOut->xOverflowCount = xNumOfOverflows; pxTimeOut->xTimeOnEntering = xTickCount; } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ @@ -3674,7 +3691,7 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const configASSERT( pxTimeOut ); configASSERT( pxTicksToWait ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* Minor optimisation. The tick count cannot change in this block. */ const TickType_t xConstTickCount = xTickCount; @@ -3724,7 +3741,7 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const xReturn = pdTRUE; } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xReturn; } @@ -3872,7 +3889,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* Now the scheduler is suspended, the expected idle * time can be sampled again, and this time its value can @@ -3896,7 +3913,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } else { @@ -3916,7 +3933,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) const UBaseType_t uxNonApplicationTasks = 1; eSleepModeStatus eReturn = eStandardSleep; - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); if( listCURRENT_LIST_LENGTH( &xPendingReadyList[xPortGetCoreID()] ) != 0 ) { /* A task was made ready while the scheduler was suspended. */ @@ -3942,7 +3959,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return eReturn; } @@ -3960,11 +3977,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); pxTCB = prvGetTCBFromHandle( xTaskToSet ); pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; pxTCB->pvThreadLocalStoragePointersDelCallback[ xIndex ] = xDelCallback; - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } } @@ -3983,10 +4000,10 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); pxTCB = prvGetTCBFromHandle( xTaskToSet ); pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } } #endif /* configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS */ @@ -4083,13 +4100,13 @@ static void prvCheckTasksWaitingTermination( void ) BaseType_t xListIsEmpty; BaseType_t core = xPortGetCoreID(); - /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL( &xTaskQueueMutex ) + /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL() * being called too often in the idle task. */ while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) { TCB_t *pxTCB = NULL; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); { xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); if( xListIsEmpty == pdFALSE ) @@ -4116,7 +4133,7 @@ static void prvCheckTasksWaitingTermination( void ) } } } - taskEXIT_CRITICAL(&xTaskQueueMutex); //Need to call deletion callbacks outside critical section + taskEXIT_CRITICAL(); //Need to call deletion callbacks outside critical section if (pxTCB != NULL) { //Call deletion callbacks and free TCB memory #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) @@ -4197,14 +4214,14 @@ static void prvCheckTasksWaitingTermination( void ) * it should be reported as being in the Blocked state. */ if( eState == eSuspended ) { - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { pxTaskStatus->eCurrentState = eBlocked; } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); } } #endif /* INCLUDE_vTaskSuspend */ @@ -4553,7 +4570,7 @@ TCB_t *pxTCB; TCB_t * const pxMutexHolderTCB = pxMutexHolder; BaseType_t xReturn = pdFALSE; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); /* If the mutex was given back by an interrupt while the queue was * locked then the mutex holder might now be NULL. _RB_ Is this still * needed as interrupts can no longer use mutexes? */ @@ -4630,7 +4647,7 @@ TCB_t *pxTCB; { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return xReturn; } @@ -4645,7 +4662,7 @@ TCB_t *pxTCB; TCB_t * const pxTCB = pxMutexHolder; BaseType_t xReturn = pdFALSE; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); if( pxMutexHolder != NULL ) { /* A task can only have an inherited priority if it holds the mutex. @@ -4712,7 +4729,7 @@ TCB_t *pxTCB; { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return xReturn; } @@ -4729,7 +4746,7 @@ TCB_t *pxTCB; UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse; const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); if( pxMutexHolder != NULL ) { /* If pxMutexHolder is not NULL then the holder must hold at least @@ -4822,7 +4839,7 @@ TCB_t *pxTCB; { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); } #endif /* configUSE_MUTEXES */ @@ -5156,13 +5173,13 @@ TickType_t uxTaskResetEventItemValue( void ) { TickType_t uxReturn; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); /* Reset the event list item to its normal value - so it can be used with * queues and semaphores. */ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return uxReturn; } @@ -5176,13 +5193,13 @@ TickType_t uxTaskResetEventItemValue( void ) /* If xSemaphoreCreateMutex() is called before any tasks have been created * then pxCurrentTCB will be NULL. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); if( pxCurrentTCB[ xPortGetCoreID() ] != NULL ) { ( pxCurrentTCB[ xPortGetCoreID() ]->uxMutexesHeld )++; } curTCB = pxCurrentTCB[ xPortGetCoreID() ]; - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return curTCB; } @@ -5196,7 +5213,7 @@ TickType_t uxTaskResetEventItemValue( void ) { uint32_t ulReturn; - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* Only block if the notification count is not already non-zero. */ if( pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue == 0UL ) @@ -5225,9 +5242,9 @@ TickType_t uxTaskResetEventItemValue( void ) mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { traceTASK_NOTIFY_TAKE(); ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; @@ -5250,7 +5267,7 @@ TickType_t uxTaskResetEventItemValue( void ) pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return ulReturn; } @@ -5264,7 +5281,7 @@ TickType_t uxTaskResetEventItemValue( void ) { BaseType_t xReturn; - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { /* Only block if a notification is not already pending. */ if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) @@ -5298,9 +5315,9 @@ TickType_t uxTaskResetEventItemValue( void ) mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { traceTASK_NOTIFY_WAIT(); @@ -5330,7 +5347,7 @@ TickType_t uxTaskResetEventItemValue( void ) pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xReturn; } @@ -5349,7 +5366,7 @@ TickType_t uxTaskResetEventItemValue( void ) configASSERT( xTaskToNotify ); pxTCB = xTaskToNotify; - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { if( pulPreviousNotificationValue != NULL ) { @@ -5448,7 +5465,7 @@ TickType_t uxTaskResetEventItemValue( void ) mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xReturn; } @@ -5486,7 +5503,7 @@ TickType_t uxTaskResetEventItemValue( void ) pxTCB = xTaskToNotify; - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + taskENTER_CRITICAL_ISR(); { if( pulPreviousNotificationValue != NULL ) { @@ -5576,7 +5593,7 @@ TickType_t uxTaskResetEventItemValue( void ) } } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(); return xReturn; } @@ -5614,7 +5631,7 @@ TickType_t uxTaskResetEventItemValue( void ) pxTCB = xTaskToNotify; - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + taskENTER_CRITICAL_ISR(); { ucOriginalNotifyState = pxTCB->ucNotifyState; pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; @@ -5665,7 +5682,7 @@ TickType_t uxTaskResetEventItemValue( void ) } } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + taskEXIT_CRITICAL_ISR(); } #endif /* configUSE_TASK_NOTIFICATIONS */ @@ -5683,7 +5700,7 @@ TickType_t uxTaskResetEventItemValue( void ) its notification state cleared. */ pxTCB = prvGetTCBFromHandle( xTask ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); { if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) { @@ -5695,7 +5712,7 @@ TickType_t uxTaskResetEventItemValue( void ) xReturn = pdFAIL; } } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskEXIT_CRITICAL(); return xReturn; } @@ -5707,9 +5724,9 @@ TickType_t uxTaskResetEventItemValue( void ) uint32_t ulTaskGetIdleRunTimeCounter( void ) { - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); tskTCB *pxTCB = (tskTCB *)xIdleTaskHandle[xPortGetCoreID()]; - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskEXIT_CRITICAL(); return pxTCB->ulRunTimeCounter; } diff --git a/components/freertos/timers.c b/components/freertos/timers.c index 076aaf4b1f..9783299f76 100644 --- a/components/freertos/timers.c +++ b/components/freertos/timers.c @@ -41,6 +41,18 @@ #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. #endif +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &xTimerMux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the @@ -449,7 +461,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; Timer_t * pxTimer = xTimer; configASSERT( xTimer ); - taskENTER_CRITICAL( &xTimerMux ); + taskENTER_CRITICAL(); { if( uxAutoReload != pdFALSE ) { @@ -460,7 +472,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD; } } - taskEXIT_CRITICAL( &xTimerMux ); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ @@ -470,7 +482,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; UBaseType_t uxReturn; configASSERT( xTimer ); - taskENTER_CRITICAL( &xTimerMux ); + taskENTER_CRITICAL( ); { if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0 ) { @@ -483,7 +495,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; uxReturn = ( UBaseType_t ) pdTRUE; } } - taskEXIT_CRITICAL( &xTimerMux ); + taskEXIT_CRITICAL(); return uxReturn; } @@ -592,7 +604,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; TickType_t xTimeNow; BaseType_t xTimerListsWereSwitched; - taskENTER_CRITICAL( &xTimerMux); + taskENTER_CRITICAL(); { /* Obtain the time now to make an assessment as to whether the timer * has expired or not. If obtaining the time causes the lists to switch @@ -606,7 +618,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; /* The tick count has not overflowed, has the timer expired? */ if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) { - taskEXIT_CRITICAL( &xTimerMux); + taskEXIT_CRITICAL(); prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); } else @@ -626,7 +638,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty ); - taskEXIT_CRITICAL( &xTimerMux); + taskEXIT_CRITICAL(); /* Yield to wait for either a command to arrive, or the * block time to expire. If a command arrived between the @@ -638,7 +650,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; } else { - taskEXIT_CRITICAL( &xTimerMux); + taskEXIT_CRITICAL(); } } } @@ -956,7 +968,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; if( xTimerQueue == NULL ) vPortCPUInitializeMutex( &xTimerMux ); - taskENTER_CRITICAL( &xTimerMux); + taskENTER_CRITICAL(); { if( xTimerQueue == NULL ) { @@ -998,7 +1010,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL( &xTimerMux ); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ @@ -1010,7 +1022,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; configASSERT( xTimer ); /* Is the timer in the list of active timers? */ - taskENTER_CRITICAL( &xTimerMux ); + taskENTER_CRITICAL(); { if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 ) { @@ -1021,7 +1033,7 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; xReturn = pdTRUE; } } - taskEXIT_CRITICAL( &xTimerMux ); + taskEXIT_CRITICAL(); return xReturn; } /*lint !e818 Can't be pointer to const due to the typedef. */ @@ -1034,11 +1046,11 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; configASSERT( xTimer ); - taskENTER_CRITICAL( &xTimerMux ); + taskENTER_CRITICAL(); { pvReturn = pxTimer->pvTimerID; } - taskEXIT_CRITICAL( &xTimerMux ); + taskEXIT_CRITICAL(); return pvReturn; } @@ -1051,11 +1063,11 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; configASSERT( xTimer ); - taskENTER_CRITICAL( &xTimerMux ); + taskENTER_CRITICAL(); { pxTimer->pvTimerID = pvNewID; } - taskEXIT_CRITICAL( &xTimerMux ); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ From 5bdbfd1d05ea38f5858abaa04477391758c4a7f0 Mon Sep 17 00:00:00 2001 From: yuanjm Date: Fri, 27 Aug 2021 17:17:56 +0800 Subject: [PATCH 079/310] Revert "Merge branch 'bugfix/fix_ws_handle_big_messages_error' into 'master'" This reverts commit d838a11d78c2df2e1e163953dbe0cd880c68a3a5, reversing changes made to 70fd8529e9705df55ea3a391107cdf49d80f3f3d. --- components/esp_http_server/src/httpd_ws.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/components/esp_http_server/src/httpd_ws.c b/components/esp_http_server/src/httpd_ws.c index c4dd8c07e3..c2f0ad581d 100644 --- a/components/esp_http_server/src/httpd_ws.c +++ b/components/esp_http_server/src/httpd_ws.c @@ -328,15 +328,9 @@ esp_err_t httpd_ws_recv_frame(httpd_req_t *req, httpd_ws_frame_t *frame, size_t return ESP_FAIL; } - int read_len = 0, left_len = frame->len; - while (left_len > 0) { - if ((read_len = httpd_recv_with_opt(req, (char *)frame->payload + read_len, left_len, false)) <= 0) { - ESP_LOGW(TAG, LOG_FMT("Failed to receive payload")); - return ESP_FAIL; - } - if (left_len -= read_len) { - ESP_LOGD(TAG, "recv data length is less than the data length we want. Read again!"); - } + if (httpd_recv_with_opt(req, (char *)frame->payload, frame->len, false) <= 0) { + ESP_LOGW(TAG, LOG_FMT("Failed to receive payload")); + return ESP_FAIL; } /* Unmask payload */ From 5db3853c2cfb0c1ae2087367db02168c280bb423 Mon Sep 17 00:00:00 2001 From: yuanjm Date: Fri, 27 Aug 2021 17:20:14 +0800 Subject: [PATCH 080/310] esp_http_server: Fix ws server handle length over 1440(MTU) messages incorrectly. Closes https://github.com/espressif/esp-idf/issues/7457 --- components/esp_http_server/src/httpd_ws.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/components/esp_http_server/src/httpd_ws.c b/components/esp_http_server/src/httpd_ws.c index c2f0ad581d..d4597b464b 100644 --- a/components/esp_http_server/src/httpd_ws.c +++ b/components/esp_http_server/src/httpd_ws.c @@ -328,9 +328,19 @@ esp_err_t httpd_ws_recv_frame(httpd_req_t *req, httpd_ws_frame_t *frame, size_t return ESP_FAIL; } - if (httpd_recv_with_opt(req, (char *)frame->payload, frame->len, false) <= 0) { - ESP_LOGW(TAG, LOG_FMT("Failed to receive payload")); - return ESP_FAIL; + size_t left_len = frame->len; + size_t offset = 0; + + while (left_len > 0) { + int read_len = httpd_recv_with_opt(req, (char *)frame->payload + offset, left_len, false); + if (read_len <= 0) { + ESP_LOGW(TAG, LOG_FMT("Failed to receive payload")); + return ESP_FAIL; + } + offset += read_len; + left_len -= read_len; + + ESP_LOGD(TAG, "Frame length: %d, Bytes Read: %d", frame->len, offset); } /* Unmask payload */ From 29ae014fd656b7c9f405779597d11b7cd4cc0ccd Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Mon, 30 Aug 2021 15:13:27 +0800 Subject: [PATCH 081/310] remaining
 to @code changes

---
 .../freertos/include/freertos/croutine.h      | 39 +++++------
 .../freertos/include/freertos/event_groups.h  | 44 ++++++------
 .../include/freertos/message_buffer.h         | 56 +++++++--------
 components/freertos/include/freertos/queue.h  | 70 +++++++++----------
 components/freertos/include/freertos/semphr.h | 60 ++++++++--------
 .../freertos/include/freertos/stream_buffer.h | 60 ++++++++--------
 components/freertos/include/freertos/task.h   | 62 ++++++++--------
 components/freertos/include/freertos/timers.h |  4 +-
 8 files changed, 198 insertions(+), 197 deletions(-)

diff --git a/components/freertos/include/freertos/croutine.h b/components/freertos/include/freertos/croutine.h
index 2b13df26c2..9b0a47de87 100644
--- a/components/freertos/include/freertos/croutine.h
+++ b/components/freertos/include/freertos/croutine.h
@@ -61,13 +61,13 @@ typedef struct corCoRoutineControlBlock
 /**
  * @cond
  * croutine. h
- * 
+ * @code{c}
  * BaseType_t xCoRoutineCreate(
  *                               crCOROUTINE_CODE pxCoRoutineCode,
  *                               UBaseType_t uxPriority,
  *                               UBaseType_t uxIndex
  *                             );
- * 
+ * @endcode * @endcond * * Create a new co-routine and add it to the list of co-routines that are @@ -143,9 +143,9 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, /** * @cond * croutine. h - *
+ * @code{c}
  * void vCoRoutineSchedule( void );
- * 
+ * @endcode * @endcond * Run a co-routine. * @@ -177,7 +177,7 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, * vCoRoutineSchedule(); * } * } - *
+ * @endcode * @endcode * @cond * \defgroup vCoRoutineSchedule vCoRoutineSchedule @@ -189,9 +189,9 @@ void vCoRoutineSchedule( void ); /** * @cond * croutine. h - *
+ * @code{c}
  * crSTART( CoRoutineHandle_t xHandle );
- * 
+ * @endcode * @endcond * * This macro MUST always be called at the start of a co-routine function. @@ -228,9 +228,9 @@ void vCoRoutineSchedule( void ); /** * @cond * croutine. h - *
+ * @code{c}
  * crEND();
- * 
+ * @endcode * @endcond * * This macro MUST always be called at the end of a co-routine function. @@ -276,9 +276,9 @@ void vCoRoutineSchedule( void ); /** * @cond * croutine. h - *
+ * @code{c}
  * crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
- * 
+ * @endcode * @endcond * * Delay a co-routine for a fixed period of time. @@ -334,7 +334,7 @@ void vCoRoutineSchedule( void ); /** * @cond - *
+ * @code{c}
  * crQUEUE_SEND(
  *                CoRoutineHandle_t xHandle,
  *                QueueHandle_t pxQueue,
@@ -342,7 +342,7 @@ void vCoRoutineSchedule( void );
  *                TickType_t xTicksToWait,
  *                BaseType_t *pxResult
  *           )
- * 
+ * @endcode * @endcond * * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine @@ -439,7 +439,7 @@ void vCoRoutineSchedule( void ); /** * @cond * croutine. h - *
+ * @code{c}
  * crQUEUE_RECEIVE(
  *                   CoRoutineHandle_t xHandle,
  *                   QueueHandle_t pxQueue,
@@ -447,7 +447,7 @@ void vCoRoutineSchedule( void );
  *                   TickType_t xTicksToWait,
  *                   BaseType_t *pxResult
  *               )
- * 
+ * @endcode * @endcond * * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine @@ -513,7 +513,6 @@ void vCoRoutineSchedule( void ); * * crEND(); * } - * * @endcode * @cond * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE @@ -538,13 +537,13 @@ void vCoRoutineSchedule( void ); /** * @cond * croutine. h - *
+ * @code{c}
  * crQUEUE_SEND_FROM_ISR(
  *                          QueueHandle_t pxQueue,
  *                          void *pvItemToQueue,
  *                          BaseType_t xCoRoutinePreviouslyWoken
  *                     )
- * 
+ * @endcode * @endcond * * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the @@ -642,13 +641,13 @@ void vCoRoutineSchedule( void ); /** * @cond * croutine. h - *
+ * @code{c}
  * crQUEUE_SEND_FROM_ISR(
  *                          QueueHandle_t pxQueue,
  *                          void *pvBuffer,
  *                          BaseType_t * pxCoRoutineWoken
  *                     )
- * 
+ * @endcode * @endcond * * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the diff --git a/components/freertos/include/freertos/event_groups.h b/components/freertos/include/freertos/event_groups.h index 8d7f6f8039..23bbaacfe8 100644 --- a/components/freertos/include/freertos/event_groups.h +++ b/components/freertos/include/freertos/event_groups.h @@ -101,9 +101,9 @@ typedef TickType_t EventBits_t; /** * @cond * event_groups.h - *
+ * @code{c}
  * EventGroupHandle_t xEventGroupCreate( void );
- * 
+ * @endcode * @endcond * * Create a new event group. @@ -161,9 +161,9 @@ typedef TickType_t EventBits_t; /** * @cond * event_groups.h - *
+ * @code{c}
  * EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
- * 
+ * @endcode * @endcond * * Create a new event group. @@ -216,13 +216,13 @@ typedef TickType_t EventBits_t; /** * @cond * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupWaitBits(    EventGroupHandle_t xEventGroup,
  *                                      const EventBits_t uxBitsToWaitFor,
  *                                      const BaseType_t xClearOnExit,
  *                                      const BaseType_t xWaitForAllBits,
  *                                      const TickType_t xTicksToWait );
- * 
+ * @endcode * @endcond * * [Potentially] block to wait for one or more bits to be set within a @@ -318,9 +318,9 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, /** * @cond * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
- * 
+ * @endcode * @endcond * * Clear bits within an event group. This function cannot be called from an @@ -380,9 +380,9 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, /** * @cond * event_groups.h - *
+ * @code{c}
  *  BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
- * 
+ * @endcode * @endcond * * A version of xEventGroupClearBits() that can be called from an interrupt. @@ -445,9 +445,9 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, /** * @cond * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
- * 
+ * @endcode * @endcond * * Set bits within an event group. @@ -524,9 +524,9 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /** * @cond * event_groups.h - *
+ * @code{c}
  *  BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * A version of xEventGroupSetBits() that can be called from an interrupt. @@ -609,12 +609,12 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /** * @cond * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupSync(    EventGroupHandle_t xEventGroup,
  *                                  const EventBits_t uxBitsToSet,
  *                                  const EventBits_t uxBitsToWaitFor,
  *                                  TickType_t xTicksToWait );
- * 
+ * @endcode * @endcond * * Atomically set bits within an event group, then wait for a combination of @@ -743,9 +743,9 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, /** * @cond * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
- * 
+ * @endcode * @endcond * * Returns the current value of the bits in an event group. This function @@ -765,9 +765,9 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, /** * @cond * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
- * 
+ * @endcode * @endcond * * A version of xEventGroupGetBits() that can be called from an ISR. @@ -786,9 +786,9 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEG /** * @cond * event_groups.h - *
+ * @code{c}
  *  void xEventGroupDelete( EventGroupHandle_t xEventGroup );
- * 
+ * @endcode * @endcond * * Delete an event group that was previously created by a call to diff --git a/components/freertos/include/freertos/message_buffer.h b/components/freertos/include/freertos/message_buffer.h index 9fe58f2765..a2f56fe868 100644 --- a/components/freertos/include/freertos/message_buffer.h +++ b/components/freertos/include/freertos/message_buffer.h @@ -88,9 +88,9 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
- * 
+ * @endcode * @endcond * * Creates a new message buffer using dynamically allocated memory. See @@ -151,11 +151,11 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
  *                                                uint8_t *pucMessageBufferStorageArea,
  *                                                StaticMessageBuffer_t *pxStaticMessageBuffer );
- * 
+ * @endcode * @endcond * Creates a new message buffer using statically allocated memory. See * xMessageBufferCreate() for a version that uses dynamically allocated memory. @@ -222,12 +222,12 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
  *                         const void *pvTxData,
  *                         size_t xDataLengthBytes,
  *                         TickType_t xTicksToWait );
- * 
+ * @endcode * @endcond * * Sends a discrete message to the message buffer. The message can be any @@ -326,12 +326,12 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
  *                                const void *pvTxData,
  *                                size_t xDataLengthBytes,
  *                                BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * Interrupt safe version of the API function that sends a discrete message to @@ -435,12 +435,12 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
  *                            void *pvRxData,
  *                            size_t xBufferLengthBytes,
  *                            TickType_t xTicksToWait );
- * 
+ * @endcode * @endcond * * Receives a discrete message from a message buffer. Messages can be of @@ -529,12 +529,12 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
  *                                   void *pvRxData,
  *                                   size_t xBufferLengthBytes,
  *                                   BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * An interrupt safe version of the API function that receives a discrete @@ -634,9 +634,9 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * @endcond * * Deletes a message buffer that was previously created using a call to @@ -656,9 +656,9 @@ typedef void * MessageBufferHandle_t; /** * @cond * message_buffer.h - *
+ * @code{c}
  * BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) );
- * 
+ * @endcode * @endcond * * Tests to see if a message buffer is full. A message buffer is full if it @@ -676,9 +676,9 @@ typedef void * MessageBufferHandle_t; /** * @cond * message_buffer.h - *
+ * @code{c}{c}
  * BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) );
- * 
+ * @endcode * @endcond * * Tests to see if a message buffer is empty (does not contain any messages). @@ -695,9 +695,9 @@ typedef void * MessageBufferHandle_t; /** * @cond * message_buffer.h - *
+ * @code{c}
  * BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * @endcond * * Resets a message buffer to its initial empty state, discarding any message it @@ -724,9 +724,9 @@ typedef void * MessageBufferHandle_t; /** * @cond * message_buffer.h - *
+ * @code{c}
  * size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
- * 
+ * @endcode * @endcond * * Returns the number of bytes of free space in the message buffer. @@ -753,9 +753,9 @@ typedef void * MessageBufferHandle_t; /** * @cond * message_buffer.h - *
+ * @code{c}
  * size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) );
- * 
+ * @endcode * @endcond * * Returns the length (in bytes) of the next message in a message buffer. @@ -779,9 +779,9 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * For advanced users only. @@ -823,9 +823,9 @@ typedef void * MessageBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * For advanced users only. diff --git a/components/freertos/include/freertos/queue.h b/components/freertos/include/freertos/queue.h index c03b1f8e69..9ff31d7eb8 100644 --- a/components/freertos/include/freertos/queue.h +++ b/components/freertos/include/freertos/queue.h @@ -136,14 +136,14 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * @cond * queue. h - *
+ * @code{c}
  * QueueHandle_t xQueueCreateStatic(
  *                            UBaseType_t uxQueueLength,
  *                            UBaseType_t uxItemSize,
  *                            uint8_t *pucQueueStorageBuffer,
  *                            StaticQueue_t *pxQueueBuffer
  *                        );
- * 
+ * @endcode * @endcond * Creates a new queue instance, and returns a handle by which the new queue * can be referenced. @@ -225,13 +225,13 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendToToFront(
  *                                 QueueHandle_t    xQueue,
  *                                 const void       *pvItemToQueue,
  *                                 TickType_t       xTicksToWait
  *                             );
- * 
+ * @endcode * @endcond * * Post an item to the front of a queue. The item is queued by copy, not by @@ -310,13 +310,13 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendToBack(
  *                                 QueueHandle_t    xQueue,
  *                                 const void       *pvItemToQueue,
  *                                 TickType_t       xTicksToWait
  *                             );
- * 
+ * @endcode * @endcond * * This is a macro that calls xQueueGenericSend(). @@ -397,13 +397,13 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSend(
  *                            QueueHandle_t xQueue,
  *                            const void * pvItemToQueue,
  *                            TickType_t xTicksToWait
  *                       );
- * 
+ * @endcode * @endcond * * This is a macro that calls xQueueGenericSend(). It is included for @@ -486,12 +486,12 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueOverwrite(
  *                            QueueHandle_t xQueue,
  *                            const void * pvItemToQueue
  *                       );
- * 
+ * @endcode * @endcond * * Only for use with queues that have a length of one - so the queue is either @@ -575,14 +575,14 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueGenericSend(
  *                                  QueueHandle_t xQueue,
  *                                  const void * pvItemToQueue,
  *                                  TickType_t xTicksToWait
  *                                  BaseType_t xCopyPosition
  *                              );
- * 
+ * @endcode * @endcond * * It is preferred that the macros xQueueSend(), xQueueSendToFront() and @@ -669,13 +669,13 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueuePeek(
  *                           QueueHandle_t xQueue,
  *                           void * const pvBuffer,
  *                           TickType_t xTicksToWait
  *                       );
- * 
+ * @endcode * @endcond * * Receive an item from a queue without removing the item from the queue. @@ -770,12 +770,12 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueuePeekFromISR(
  *                                  QueueHandle_t xQueue,
  *                                  void *pvBuffer,
  *                              );
- * 
+ * @endcode * @endcond * * A version of xQueuePeek() that can be called from an interrupt service @@ -809,7 +809,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueReceive(
  *                               QueueHandle_t xQueue,
  *                               void *pvBuffer,
@@ -907,9 +907,9 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue,
 /**
  * @cond
  * queue. h
- * 
+ * @code{c}
  * UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
- * 
+ * @endcode * @endcond * * Return the number of messages stored in a queue. @@ -928,9 +928,9 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNC /** * @cond * queue. h - *
+ * @code{c}
  * UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
- * 
+ * @endcode * @endcond * * Return the number of free spaces available in a queue. This is equal to the @@ -951,9 +951,9 @@ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNC /** * @cond * queue. h - *
+ * @code{c}
  * void vQueueDelete( QueueHandle_t xQueue );
- * 
+ * @endcode * @endcond * * Delete a queue - freeing all the memory allocated for storing of items @@ -971,13 +971,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendToFrontFromISR(
  *                                       QueueHandle_t xQueue,
  *                                       const void *pvItemToQueue,
  *                                       BaseType_t *pxHigherPriorityTaskWoken
  *                                    );
- * 
+ * @endcode * @endcond * * This is a macro that calls xQueueGenericSendFromISR(). @@ -1047,13 +1047,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendToBackFromISR(
  *                                       QueueHandle_t xQueue,
  *                                       const void *pvItemToQueue,
  *                                       BaseType_t *pxHigherPriorityTaskWoken
  *                                    );
- * 
+ * @endcode * @endcond * * This is a macro that calls xQueueGenericSendFromISR(). @@ -1122,13 +1122,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueOverwriteFromISR(
  *                            QueueHandle_t xQueue,
  *                            const void * pvItemToQueue,
  *                            BaseType_t *pxHigherPriorityTaskWoken
  *                       );
- * 
+ * @endcode * @endcond * * A version of xQueueOverwrite() that can be used in an interrupt service @@ -1214,13 +1214,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendFromISR(
  *                                   QueueHandle_t xQueue,
  *                                   const void *pvItemToQueue,
  *                                   BaseType_t *pxHigherPriorityTaskWoken
  *                              );
- * 
+ * @endcode * @endcond * * This is a macro that calls xQueueGenericSendFromISR(). It is included @@ -1295,14 +1295,14 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueGenericSendFromISR(
  *                                         QueueHandle_t    xQueue,
  *                                         const    void    *pvItemToQueue,
  *                                         BaseType_t  *pxHigherPriorityTaskWoken,
  *                                         BaseType_t  xCopyPosition
  *                                     );
- * 
+ * @endcode * @endcond * * It is preferred that the macros xQueueSendFromISR(), @@ -1382,13 +1382,13 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, /** * @cond * queue. h - *
+ * @code{c}
  * BaseType_t xQueueReceiveFromISR(
  *                                     QueueHandle_t    xQueue,
  *                                     void             *pvBuffer,
  *                                     BaseType_t       *pxTaskWoken
  *                                 );
- * 
+ * @endcode * @endcond * * Receive an item from a queue. It is safe to use this function from within an diff --git a/components/freertos/include/freertos/semphr.h b/components/freertos/include/freertos/semphr.h index f9cddcfaa5..d692375e65 100644 --- a/components/freertos/include/freertos/semphr.h +++ b/components/freertos/include/freertos/semphr.h @@ -42,9 +42,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** @cond */ /** * semphr. h - *
+ * @code{c}
  * vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore );
- * 
+ * @endcode * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! @@ -72,7 +72,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore = NULL;
  *
  * void vATask( void * pvParameters )
@@ -87,7 +87,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      // The semaphore can now be used.
  *  }
  * }
- * 
+ * @endcode * @cond * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * @endcond @@ -108,9 +108,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateBinary( void );
- * 
+ * @endcode * @endcond * * Creates a new binary semaphore instance, and returns a handle by which the @@ -175,9 +175,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer );
- * 
+ * @endcode * @endcond * * Creates a new binary semaphore instance, and returns a handle by which the @@ -241,12 +241,12 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * xSemaphoreTake(
  *                   SemaphoreHandle_t xSemaphore,
  *                   TickType_t xBlockTime
  *               );
- * 
+ * @endcode * @endcond * * Macro to obtain a semaphore. The semaphore must have previously been @@ -481,9 +481,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex );
- * 
+ * @endcode * @endcond * * Macro to recursively release, or 'give', a mutex type semaphore. @@ -674,12 +674,12 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * xSemaphoreTakeFromISR(
  *                        SemaphoreHandle_t xSemaphore,
  *                        BaseType_t *pxHigherPriorityTaskWoken
  *                    );
- * 
+ * @endcode * @endcond * * Macro to take a semaphore from an ISR. The semaphore must have @@ -711,9 +711,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateMutex( void );
- * 
+ * @endcode * @endcond * * Creates a new mutex type semaphore instance, and returns a handle by which @@ -776,9 +776,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );
- * 
+ * @endcode * @endcond * * Creates a new mutex type semaphore instance, and returns a handle by which @@ -976,9 +976,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount );
- * 
+ * @endcode * @endcond * * Creates a new counting semaphore instance, and returns a handle by which the @@ -1062,9 +1062,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer );
- * 
+ * @endcode * @endcond * * Creates a new counting semaphore instance, and returns a handle by which the @@ -1153,9 +1153,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr. h - *
+ * @code{c}
  * void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
- * 
+ * @endcode * @endcond * * Delete a semaphore. This function must be used with care. For example, @@ -1173,9 +1173,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr.h - *
+ * @code{c}
  * TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
- * 
+ * @endcode * @endcond * * If xMutex is indeed a mutex type semaphore, return the current mutex holder. @@ -1192,9 +1192,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr.h - *
+ * @code{c}
  * TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex );
- * 
+ * @endcode * @endcond * * If xMutex is indeed a mutex type semaphore, return the current mutex holder. @@ -1207,9 +1207,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * @cond * semphr.h - *
+ * @code{c}
  * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
- * 
+ * @endcode * @endcond * * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns diff --git a/components/freertos/include/freertos/stream_buffer.h b/components/freertos/include/freertos/stream_buffer.h index 753b0cd880..ba8282ce73 100644 --- a/components/freertos/include/freertos/stream_buffer.h +++ b/components/freertos/include/freertos/stream_buffer.h @@ -74,9 +74,9 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * @cond * message_buffer.h * - *
+ * @code{c}
  * StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
- * 
+ * @endcode * @endcond * * Creates a new stream buffer using dynamically allocated memory. See @@ -145,12 +145,12 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * @cond * stream_buffer.h * - *
+ * @code{c}
  * StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
  *                                              size_t xTriggerLevelBytes,
  *                                              uint8_t *pucStreamBufferStorageArea,
  *                                              StaticStreamBuffer_t *pxStaticStreamBuffer );
- * 
+ * @endcode * @endcond * * Creates a new stream buffer using statically allocated memory. See @@ -232,12 +232,12 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * @cond * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
  *                        const void *pvTxData,
  *                        size_t xDataLengthBytes,
  *                        TickType_t xTicksToWait );
- * 
+ * @endcode * @endcond * * Sends bytes to a stream buffer. The bytes are copied into the stream buffer. @@ -333,12 +333,12 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, * @cond * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
  *                               const void *pvTxData,
  *                               size_t xDataLengthBytes,
  *                               BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * Interrupt safe version of the API function that sends a stream of bytes to @@ -438,12 +438,12 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, * @cond * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
  *                           void *pvRxData,
  *                           size_t xBufferLengthBytes,
  *                           TickType_t xTicksToWait );
- * 
+ * @endcode * @endcond * * Receives bytes from a stream buffer. @@ -531,12 +531,12 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, * @cond * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
  *                                  void *pvRxData,
  *                                  size_t xBufferLengthBytes,
  *                                  BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * An interrupt safe version of the API function that receives bytes from a @@ -621,9 +621,9 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, * @cond * stream_buffer.h * - *
+ * @code{c}
  * void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * @endcond * * Deletes a stream buffer that was previously created using a call to @@ -647,9 +647,9 @@ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTI * @cond * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * @endcond * * Queries a stream buffer to see if it is full. A stream buffer is full if it @@ -671,9 +671,9 @@ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_ * @cond * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * @endcond * * Queries a stream buffer to see if it is empty. A stream buffer is empty if @@ -695,9 +695,9 @@ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED * @cond * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * @endcond * * Resets a stream buffer to its initial, empty, state. Any data that was in @@ -722,9 +722,9 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_F * @cond * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * @endcond * * Queries a stream buffer to see how much free space it contains, which is @@ -747,9 +747,9 @@ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVIL * @cond * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * @endcond * * Queries a stream buffer to see how much data it contains, which is equal to @@ -772,9 +772,9 @@ size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILE * @cond * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
- * 
+ * @endcode * @endcond * * A stream buffer's trigger level is the number of bytes that must be in the @@ -814,9 +814,9 @@ BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, * @cond * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * For advanced users only. @@ -858,9 +858,9 @@ BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer * @cond * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * @endcond * * For advanced users only. diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 8053c80645..123d6c99b8 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -763,9 +763,9 @@ typedef enum /** * @cond * task. h - *
+ * @code{c}
  * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
- * 
+ * @endcode * @endcond * * Memory regions are assigned to a restricted task when the task is created by @@ -975,9 +975,9 @@ void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, /** * @cond * task. h - *
+ * @code{c}
  * BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
- * 
+ * @endcode * @endcond * * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this @@ -1011,9 +1011,9 @@ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * @cond * task. h - *
+ * @code{c}
  * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );
- * 
+ * @endcode * @endcond * * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. @@ -1064,9 +1064,9 @@ UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * @cond * task. h - *
+ * @code{c}
  * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask );
- * 
+ * @endcode * @endcond * * A version of uxTaskPriorityGet() that can be used from an ISR. @@ -1076,9 +1076,9 @@ UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNC /** * @cond * task. h - *
+ * @code{c}
  * eTaskState eTaskGetState( TaskHandle_t xTask );
- * 
+ * @endcode * @endcond * * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. @@ -1098,9 +1098,9 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * @cond * task. h - *
+ * @code{c}
  * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
- * 
+ * @endcode * @endcond * * configUSE_TRACE_FACILITY must be defined as 1 for this function to be @@ -1163,9 +1163,9 @@ void vTaskGetInfo( TaskHandle_t xTask, /** * @cond * task. h - *
+ * @code{c}
  * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
- * 
+ * @endcode * @endcond * * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. @@ -1264,9 +1264,9 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; /** * @cond * task. h - *
+ * @code{c}
  * void vTaskResume( TaskHandle_t xTaskToResume );
- * 
+ * @endcode * @endcond * * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. @@ -1361,7 +1361,7 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; * tasks and starting the kernel. * * Example usage: - *
+ * @code{c}
  * void vAFunction( void )
  * {
  *   // Create at least one task before starting the kernel.
@@ -1372,7 +1372,7 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
  *
  *   // Will not get here unless a task calls vTaskEndScheduler ()
  * }
- * 
+ * @endcode * * @cond * \defgroup vTaskStartScheduler vTaskStartScheduler @@ -1404,7 +1404,7 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; * tasks. * * Example usage: - *
+ * @code{c}
  * void vTaskCode( void * pvParameters )
  * {
  *   for( ;; )
@@ -1429,7 +1429,7 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
  *   // vTaskEndScheduler ().  When we get here we are back to single task
  *   // execution.
  * }
- * 
+ * @endcode * * @cond * \defgroup vTaskEndScheduler vTaskEndScheduler @@ -1494,9 +1494,9 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; /** * @cond * task. h - *
+ * @code{c}
  * BaseType_t xTaskResumeAll( void );
- * 
+ * @endcode * @endcond * * Resumes scheduler activity after it was suspended by a call to @@ -1706,9 +1706,9 @@ uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) PRIVILEGED_FUNCTION; /** * @cond * task.h - *
+ * @code{c}
  * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
- * 
+ * @endcode * @endcond * * Sets pxHookFunction to be the task hook function used by the task xTask. @@ -1723,9 +1723,9 @@ uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) PRIVILEGED_FUNCTION; /** * @cond * task.h - *
+ * @code{c}
  * void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
- * 
+ * @endcode * @endcond * * Returns the pxHookFunction value assigned to the task xTask. Do not @@ -1737,9 +1737,9 @@ uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) PRIVILEGED_FUNCTION; /** * @cond * task.h - *
+ * @code{c}
  * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask );
- * 
+ * @endcode * @endcond * * Returns the pxHookFunction value assigned to the task xTask. Can @@ -1820,9 +1820,9 @@ uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) PRIVILEGED_FUNCTION; /** * @cond * task.h - *
+ * @code{c}
  * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
- * 
+ * @endcode * @endcond * * Calls the hook function associated with xTask. Passing xTask as NULL has @@ -2052,7 +2052,7 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin /** * @cond * task. h - *
uint32_t ulTaskGetIdleRunTimeCounter( void );
+ * @code{c}uint32_t ulTaskGetIdleRunTimeCounter( void );@endcode * @endcond * * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS diff --git a/components/freertos/include/freertos/timers.h b/components/freertos/include/freertos/timers.h index 69512f949e..af0a08943b 100644 --- a/components/freertos/include/freertos/timers.h +++ b/components/freertos/include/freertos/timers.h @@ -1338,7 +1338,9 @@ BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, /** * @cond * task.h - *
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) 
+ * @code{c} + * void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) + * @endcode * @endcond * * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer Task TCB. This function is required when From 59cedcb7486ced0f5b4bdb299d76a47989b97e8c Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Mon, 30 Aug 2021 17:38:16 +0800 Subject: [PATCH 082/310] soc: remove outdated description of interrupts on RISCV CPUs --- components/soc/esp32c3/include/soc/soc.h | 49 ++---------------------- components/soc/esp32h2/include/soc/soc.h | 49 ++---------------------- 2 files changed, 6 insertions(+), 92 deletions(-) diff --git a/components/soc/esp32c3/include/soc/soc.h b/components/soc/esp32c3/include/soc/soc.h index 921a3ea448..72dbb15a60 100644 --- a/components/soc/esp32c3/include/soc/soc.h +++ b/components/soc/esp32c3/include/soc/soc.h @@ -268,56 +268,13 @@ // Start (highest address) of ROM boot stack, only relevant during early boot #define SOC_ROM_STACK_START 0x3fcebf10 -//interrupt cpu using table, Please see the core-isa.h -/************************************************************************************************************* - * Intr num Level Type PRO CPU usage - * 0 1 extern level Panic - * 1 1 extern level WMAC - * 2 1 extern level - * 3 1 extern level - * 4 1 extern level WBB - * 5 1 extern level BT/BLE Controller - * 6 1 timer FreeRTOS Tick(L1) - * 7 1 software - * 8 1 extern level BT/BLE BB(RX/TX) - * 9 1 extern level - * 10 1 extern edge - * 11 3 profiling - * 12 1 extern level - * 13 1 extern level - * 14 7 nmi Reserved - * 15 3 timer FreeRTOS Tick(L3) - * 16 5 timer - * 17 1 extern level - * 18 1 extern level - * 19 2 extern level - * 20 2 extern level - * 21 2 extern level - * 22 3 extern edge - * 23 3 extern level - * 24 4 extern level TG1_WDT - * 25 4 extern level CACHEERR - * 26 5 extern level - * 27 3 extern level Reserved - * 28 4 extern edge Reserved - * 29 3 software Reserved - * 30 4 extern edge Reserved - * 31 5 extern level - ************************************************************************************************************* - */ +//On RISC-V CPUs, the interrupt sources are all external interrupts, whose type, source and priority are configured by SW. +//There is no HW NMI conception. SW should controlled the masked levels through INT_THRESH_REG. -//CPU0 Interrupt number reserved, not touch this. -#define ETS_WMAC_INUM 1 -//#define ETS_BT_HOST_INUM 1 -#define ETS_WBB_INUM 4 -#define ETS_SYSTICK_INUM 9 -#define ETS_TG0_T1_INUM 10 /* use edge interrupt */ -#define ETS_CPU_INTR0_INUM 12 /* used as freertos soft intr */ -#define ETS_FRC1_INUM 22 +//CPU0 Interrupt number reserved in riscv/vector.S, not touch this. #define ETS_T1_WDT_INUM 24 #define ETS_CACHEERR_INUM 25 #define ETS_MEMPROT_ERR_INUM 26 - //CPU0 Max valid interrupt number #define ETS_MAX_INUM 31 diff --git a/components/soc/esp32h2/include/soc/soc.h b/components/soc/esp32h2/include/soc/soc.h index bca83126d5..c51e6c41a3 100644 --- a/components/soc/esp32h2/include/soc/soc.h +++ b/components/soc/esp32h2/include/soc/soc.h @@ -297,56 +297,13 @@ // Start (highest address) of ROM boot stack, only relevant during early boot #define SOC_ROM_STACK_START 0x3fcebf10 -//interrupt cpu using table, Please see the core-isa.h -/************************************************************************************************************* - * Intr num Level Type PRO CPU usage - * 0 1 extern level Panic - * 1 1 extern level WMAC - * 2 1 extern level - * 3 1 extern level - * 4 1 extern level WBB - * 5 1 extern level BT/BLE Controller - * 6 1 timer FreeRTOS Tick(L1) - * 7 1 software - * 8 1 extern level BT/BLE BB(RX/TX) - * 9 1 extern level - * 10 1 extern edge - * 11 3 profiling - * 12 1 extern level - * 13 1 extern level - * 14 7 nmi Reserved - * 15 3 timer FreeRTOS Tick(L3) - * 16 5 timer - * 17 1 extern level - * 18 1 extern level - * 19 2 extern level - * 20 2 extern level - * 21 2 extern level - * 22 3 extern edge - * 23 3 extern level - * 24 4 extern level TG1_WDT - * 25 4 extern level CACHEERR - * 26 5 extern level - * 27 3 extern level Reserved - * 28 4 extern edge Reserved - * 29 3 software Reserved - * 30 4 extern edge Reserved - * 31 5 extern level - ************************************************************************************************************* - */ +//On RISC-V CPUs, the interrupt sources are all external interrupts, whose type, source and priority are configured by SW. +//There is no HW NMI conception. SW should controlled the masked levels through INT_THRESH_REG. -//CPU0 Interrupt number reserved, not touch this. -#define ETS_WMAC_INUM 1 -//#define ETS_BT_HOST_INUM 1 -#define ETS_WBB_INUM 4 -#define ETS_SYSTICK_INUM 9 -#define ETS_TG0_T1_INUM 10 /* use edge interrupt */ -#define ETS_CPU_INTR0_INUM 12 /* used as freertos soft intr */ -#define ETS_FRC1_INUM 22 +//CPU0 Interrupt number reserved in riscv/vector.S, not touch this. #define ETS_T1_WDT_INUM 24 #define ETS_CACHEERR_INUM 25 #define ETS_MEMPROT_ERR_INUM 26 - //CPU0 Max valid interrupt number #define ETS_MAX_INUM 31 From c6f6bd6a426f8345d032d531784eb1acceba147d Mon Sep 17 00:00:00 2001 From: Sergei Silnov Date: Wed, 5 May 2021 13:10:41 +0300 Subject: [PATCH 083/310] Add idf-component-manager python dependency --- .gitignore | 3 +++ requirements.txt | 1 + tools/ci/test_build_system_cmake.sh | 5 ----- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 61e02dae70..38ebd38bef 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,6 @@ build # lock files for examples and components dependencies.lock + +# managed_components for examples +managed_components diff --git a/requirements.txt b/requirements.txt index 120562c49b..23de87ac77 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,6 +11,7 @@ future>=0.15.2 cryptography>=2.1.4 pyparsing>=2.0.3,<2.4.0 pyelftools>=0.22 +idf-component-manager>=0.2.99-beta gdbgui==0.13.2.0 # 0.13.2.1 supports Python 3.6+ only diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index 8eda08f8a7..b864c03c2c 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -717,14 +717,9 @@ endmenu\n" >> ${IDF_PATH}/Kconfig print_status "Compiles with dependencies delivered by component manager" clean_build_dir - # Make sure that component manager is not installed - pip uninstall -y idf_component_manager printf "\n#include \"test_component.h\"\n" >> main/main.c printf "dependencies:\n test_component:\n path: test_component\n git: ${COMPONENT_MANAGER_TEST_REPO}\n" >> main/idf_component.yml - ! idf.py build || failure "Build should fail if dependencies are not installed" - pip install ${COMPONENT_MANAGER_PACKAGE} --upgrade || failure "Failed to install component manager" idf.py reconfigure build || failure "Build didn't succeed with required components installed by package manager" - pip uninstall -y idf_component_manager rm main/idf_component.yml git checkout main/main.c From 37b791e242b95473dc0feb71bd680465d5db17d6 Mon Sep 17 00:00:00 2001 From: Sergei Silnov Date: Mon, 2 Aug 2021 20:49:42 +0200 Subject: [PATCH 084/310] Build System: Don't track dependencies.lock --- tools/cmake/component.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index 1a6aa0a921..12cf324586 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -434,9 +434,8 @@ function(idf_component_register) __component_check_target() __component_add_sources(sources) - # Add component manifest and lock files to list of dependencies + # Add component manifest to the list of dependencies set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${COMPONENT_DIR}/idf_component.yml") - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${COMPONENT_DIR}/dependencies.lock") # Create the final target for the component. This target is the target that is # visible outside the build system. From 8202c12a8328ec27f77efdc320ccf422c531c79a Mon Sep 17 00:00:00 2001 From: Sergei Silnov Date: Sat, 3 Jul 2021 10:30:52 +0200 Subject: [PATCH 085/310] docs: Add component manager documentation --- .../tools/idf-component-manager.rst | 72 +++++++++++++++++++ docs/en/api-guides/tools/index.rst | 1 + .../tools/idf-component-manager.rst | 1 + docs/zh_CN/api-guides/tools/index.rst | 1 + 4 files changed, 75 insertions(+) create mode 100644 docs/en/api-guides/tools/idf-component-manager.rst create mode 100644 docs/zh_CN/api-guides/tools/idf-component-manager.rst diff --git a/docs/en/api-guides/tools/idf-component-manager.rst b/docs/en/api-guides/tools/idf-component-manager.rst new file mode 100644 index 0000000000..3700256194 --- /dev/null +++ b/docs/en/api-guides/tools/idf-component-manager.rst @@ -0,0 +1,72 @@ +********************* +IDF Component Manager +********************* + +The IDF Component manager is a tool that downloads dependencies for any ESP-IDF CMake project. The download happens automatically during a run of CMake. It can source components either from `the component registry `_ or from a git repository. + +A list of components can be found on ``_ + +Activating the Component Manager +================================ + +If CMake is started using ``idf.py`` or `ESP-IDF VSCode Extension `_ then the component manager will be activated by default. + +If CMake is used directly or with some CMake-based IDE like CLion, it's necessary to set the ``IDF_COMPONENT_MANAGER`` environment variable to ``1`` to enable the component manager integration with the build system. + +Using with a project +==================== + +Dependencies for each component in the project are defined in a separate manifest file named ``idf_component.yml`` placed in the root of the component. The manifest file template can be created for a component by running ``idf.py create-manifest --component=my_component``. When a new manifest is added to one of the components in the project it's necessary to reconfigure it manually by running ``idf.py reconfigure``. Then build will track changes in ``idf_component.yml`` manifests and automatically triggers CMake when necessary. + +There is an example application: example:`build_system/cmake/component_manager` that uses components installed by the component manager. + +It's not necessary to have a manifest for components that don't need any managed dependencies. + +When CMake configures the project (e.g. ``idf.py reconfigure``) component manager does a few things: + +- Processes ``idf_component.yml`` manifests for every component in the project and recursively solves dependencies +- Creates a ``dependencies.lock`` file in the root of the project with a full list of dependencies +- Downloads all dependencies to the ``managed_components`` directory + +The lock-file ``dependencies.lock`` and content of ``managed_components`` directory is not supposed to be modified by a user. When the component manager runs it always make sure they are up to date. If these files were accidentally modified it's possible to re-run the component manager by triggering CMake with ``idf.py reconfigure`` + +Defining dependencies in the manifest +===================================== + +.. code-block:: yaml + + dependencies: + # Required IDF version + idf: ">=4.1" + # Defining a dependency from the registry: + # https://components.espressif.com/component/example/cmp + example/cmp: ">=1.0.0" + + # # Other ways to define dependencies + # + # # For components maintained by Espressif only name can be used. + # # Same as `espressif/cmp` + # component: "~1.0.0" + # + # # Or in a longer form with extra parameters + # component2: + # version: ">=2.0.0" + # + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't affect the `main` component. + # # All dependencies of `main` are public by default. + # public: true + # + # # For components hosted on non-default registry: + # service_url: "https://componentregistry.company.com" + # + # # For components in git repository: + # test_component: + # path: test_component + # git: ssh://git@gitlab.com/user/components.git + # + # # For test projects during component development + # # components can be used from a local directory + # # with relative or absolute path + # some_local_component: + # path: ../../projects/component diff --git a/docs/en/api-guides/tools/index.rst b/docs/en/api-guides/tools/index.rst index 862cbb4367..49b85291c3 100644 --- a/docs/en/api-guides/tools/index.rst +++ b/docs/en/api-guides/tools/index.rst @@ -8,3 +8,4 @@ Tools IDF Monitor IDF Docker image IDF Windows Installer + IDF Component Manager diff --git a/docs/zh_CN/api-guides/tools/idf-component-manager.rst b/docs/zh_CN/api-guides/tools/idf-component-manager.rst new file mode 100644 index 0000000000..8017f17fbc --- /dev/null +++ b/docs/zh_CN/api-guides/tools/idf-component-manager.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-guides/tools/idf-component-manager.rst diff --git a/docs/zh_CN/api-guides/tools/index.rst b/docs/zh_CN/api-guides/tools/index.rst index ef6903c591..41438ae874 100644 --- a/docs/zh_CN/api-guides/tools/index.rst +++ b/docs/zh_CN/api-guides/tools/index.rst @@ -8,3 +8,4 @@ IDF 监视器 IDF Docker image IDF Windows Installer + IDF Component Manager From 7fc28f78836be1324e07a21342d03c347b36fc6a Mon Sep 17 00:00:00 2001 From: Sergei Silnov Date: Mon, 2 Aug 2021 18:59:33 +0200 Subject: [PATCH 086/310] examples: Add the component manager example --- .../cmake/component_manager/CMakeLists.txt | 8 +++ .../cmake/component_manager/README.md | 55 +++++++++++++++++++ .../component_manager/main/CMakeLists.txt | 2 + .../main/component_manager.c | 7 +++ .../component_manager/main/idf_component.yml | 36 ++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 examples/build_system/cmake/component_manager/CMakeLists.txt create mode 100644 examples/build_system/cmake/component_manager/README.md create mode 100644 examples/build_system/cmake/component_manager/main/CMakeLists.txt create mode 100644 examples/build_system/cmake/component_manager/main/component_manager.c create mode 100644 examples/build_system/cmake/component_manager/main/idf_component.yml diff --git a/examples/build_system/cmake/component_manager/CMakeLists.txt b/examples/build_system/cmake/component_manager/CMakeLists.txt new file mode 100644 index 0000000000..9b15cac787 --- /dev/null +++ b/examples/build_system/cmake/component_manager/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# 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(component_manager) diff --git a/examples/build_system/cmake/component_manager/README.md b/examples/build_system/cmake/component_manager/README.md new file mode 100644 index 0000000000..182664f553 --- /dev/null +++ b/examples/build_system/cmake/component_manager/README.md @@ -0,0 +1,55 @@ +# Using the component manager for downloading dependencies + +This example demonstrates how to use [IDF Component Manager](https://pypi.org/project/idf-component-manager/) for downloading dependencies from [the component registry](https://components.espressif.com). More details and use cases of IDF Component Manager can be found in the programming guide under `API Guides` -> `Tools` -> `IDF Component Manager`. + +## How to use the example +### Hardware Required + +This example is designed to work with any commonly available development kit. + +### Build and Flash + +Run `idf.py reconfigure` to configure this project. During CMake execution the component manager will process data from the manifest file `./main/idf_component.yml` where 2 dependencies are defined: + +- `idf: ">=4.1"` - Specifies required version of ESP-IDF. +- `example/cmp: ">=3.3.3"` - Defines dependency on [example/cmp](https://components.espressif.com/component/example/cmp) component that is used by the main component. + +CMake Output: +``` +... +Solving dependencies requirements +Updating lock file at /home/user/esp-idf/examples/build_system/cmake/component_manager/dependencies.lock +Processing 2 dependencies: +[1/2] example/cmp +[2/2] idf +... +``` + +Content of the `./managed_components` directory after successful build: +``` +> find ./managed_components +./managed_components +./managed_components/example__cmp +./managed_components/example__cmp/include +./managed_components/example__cmp/include/cmp.h +./managed_components/example__cmp/LICENSE +./managed_components/example__cmp/README.md +./managed_components/example__cmp/CMakeLists.txt +./managed_components/example__cmp/changelog.md +./managed_components/example__cmp/cmp.c +./managed_components/example__cmp/idf_component.yml +``` + +Flash the project and run the serial monitor to view the output: + +``` +idf.py -p PORT flash monitor +``` + +### Example Output + +The example outputs a line from the `cmp_hello` function from the component downloaded by the component manager. + +``` +Hello from example component! +``` diff --git a/examples/build_system/cmake/component_manager/main/CMakeLists.txt b/examples/build_system/cmake/component_manager/main/CMakeLists.txt new file mode 100644 index 0000000000..9bc2623419 --- /dev/null +++ b/examples/build_system/cmake/component_manager/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "component_manager.c" + INCLUDE_DIRS ".") diff --git a/examples/build_system/cmake/component_manager/main/component_manager.c b/examples/build_system/cmake/component_manager/main/component_manager.c new file mode 100644 index 0000000000..6358d964dd --- /dev/null +++ b/examples/build_system/cmake/component_manager/main/component_manager.c @@ -0,0 +1,7 @@ +#include +#include "cmp.h" + +void app_main(void) +{ + cmp_hello(); +} diff --git a/examples/build_system/cmake/component_manager/main/idf_component.yml b/examples/build_system/cmake/component_manager/main/idf_component.yml new file mode 100644 index 0000000000..1a90a2c8c4 --- /dev/null +++ b/examples/build_system/cmake/component_manager/main/idf_component.yml @@ -0,0 +1,36 @@ +dependencies: + # Required IDF version + idf: ">=4.1" + + # Defining a dependency from the registry: + # https://components.espressif.com/component/example/cmp + example/cmp: ">=3.3.3" + + # # Other ways to define dependencies + # + # # For components maintained by Espressif only name can be used. + # # Same as `espressif/cmp` + # component: "~1.0.0" + # + # # Or in a longer form with extra parameters + # component2: + # version: ">=2.0.0" + # + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect for the `main` component. + # # All dependencies of `main` are public by default. + # public: true + # + # # For components hosted on non-default registry: + # service_url: "https://componentregistry.company.com" + # + # # For components in git repository: + # test_component: + # path: test_component + # git: ssh://git@gitlab.com/user/components.git + # + # # For test projects during component development + # # components can be used from a local directory + # # with relative or absolute path + # some_local_component: + # path: ../../projects/component From b910724ea9950af14e9b9aac82e34a0586f35714 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Mon, 30 Aug 2021 22:59:36 +0800 Subject: [PATCH 087/310] example: fixed the issue that config struct is not properly initialized --- .../peripherals/gpio/generic_gpio/main/gpio_example_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c index 425f8fa9e1..faf584b48e 100644 --- a/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c +++ b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c @@ -59,7 +59,8 @@ static void gpio_task_example(void* arg) void app_main(void) { - gpio_config_t io_conf; + //zero-initialize the config structure. + gpio_config_t io_conf = {}; //disable interrupt io_conf.intr_type = GPIO_INTR_DISABLE; //set as output mode From 2e0cab6f94eb6455d88191ea0b78058788e68b61 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 31 Aug 2021 08:46:27 +0800 Subject: [PATCH 088/310] himem: reverse error check logic in himem --- .../esp_hw_support/port/esp32/esp_himem.c | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/components/esp_hw_support/port/esp32/esp_himem.c b/components/esp_hw_support/port/esp32/esp_himem.c index 4acaf90e7c..061b2661aa 100644 --- a/components/esp_hw_support/port/esp32/esp_himem.c +++ b/components/esp_hw_support/port/esp32/esp_himem.c @@ -133,10 +133,10 @@ void __attribute__((constructor)) esp_himem_init(void) if (SPIRAM_BANKSWITCH_RESERVE == 0) return; int maxram=esp_spiram_get_size(); //catch double init - ESP_RETURN_ON_FALSE(s_ram_descriptor != NULL, , TAG, "already initialized"); //Looks weird; last arg is empty so it expands to 'return ;' - ESP_RETURN_ON_FALSE(s_range_descriptor != NULL, , TAG, "already initialized"); + ESP_RETURN_ON_FALSE(s_ram_descriptor == NULL, , TAG, "already initialized"); //Looks weird; last arg is empty so it expands to 'return ;' + ESP_RETURN_ON_FALSE(s_range_descriptor == NULL, , TAG, "already initialized"); //need to have some reserved banks - ESP_RETURN_ON_FALSE(SPIRAM_BANKSWITCH_RESERVE == 0, , TAG, "No banks reserved for himem"); + ESP_RETURN_ON_FALSE(SPIRAM_BANKSWITCH_RESERVE != 0, , TAG, "No banks reserved for himem"); //Start and end of physical reserved memory. Note it starts slightly under //the 4MiB mark as the reserved banks can't have an unity mapping to be used by malloc //anymore; we treat them as himem instead. @@ -218,7 +218,7 @@ esp_err_t esp_himem_free(esp_himem_handle_t handle) //Check if any of the blocks is still mapped; fail if this is the case. for (int i = 0; i < handle->block_ct; i++) { assert(ramblock_idx_valid(handle->block[i])); - ESP_RETURN_ON_FALSE(s_ram_descriptor[handle->block[i]].is_mapped, ESP_ERR_INVALID_ARG, TAG, "block in range still mapped"); + ESP_RETURN_ON_FALSE(!s_ram_descriptor[handle->block[i]].is_mapped, ESP_ERR_INVALID_ARG, TAG, "block in range still mapped"); } //Mark blocks as free portENTER_CRITICAL(&spinlock); @@ -236,8 +236,8 @@ esp_err_t esp_himem_free(esp_himem_handle_t handle) esp_err_t esp_himem_alloc_map_range(size_t size, esp_himem_rangehandle_t *handle_out) { - ESP_RETURN_ON_FALSE(s_ram_descriptor == NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); - ESP_RETURN_ON_FALSE(size % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_SIZE, TAG, "requested size not aligned to blocksize"); + ESP_RETURN_ON_FALSE(s_ram_descriptor != NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); + ESP_RETURN_ON_FALSE(size % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_SIZE, TAG, "requested size not aligned to blocksize"); int blocks = size / CACHE_BLOCKSIZE; esp_himem_rangedata_t *r = calloc(sizeof(esp_himem_rangedata_t), 1); if (!r) { @@ -279,7 +279,7 @@ esp_err_t esp_himem_free_map_range(esp_himem_rangehandle_t handle) for (int i = 0; i < handle->block_ct; i++) { assert(rangeblock_idx_valid(handle->block_start + i)); assert(s_range_descriptor[i + handle->block_start].is_alloced == 1); //should be, if handle is valid - ESP_RETURN_ON_FALSE(s_range_descriptor[i + handle->block_start].is_mapped, ESP_ERR_INVALID_ARG, TAG, "memory still mapped to range"); + ESP_RETURN_ON_FALSE(!s_range_descriptor[i + handle->block_start].is_mapped, ESP_ERR_INVALID_ARG, TAG, "memory still mapped to range"); } //We should be good to free this. Mark blocks as free. portENTER_CRITICAL(&spinlock); @@ -297,19 +297,19 @@ esp_err_t esp_himem_map(esp_himem_handle_t handle, esp_himem_rangehandle_t range int ram_block = ram_offset / CACHE_BLOCKSIZE; int range_block = range_offset / CACHE_BLOCKSIZE; int blockcount = len / CACHE_BLOCKSIZE; - ESP_RETURN_ON_FALSE(s_ram_descriptor == NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); + ESP_RETURN_ON_FALSE(s_ram_descriptor != NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); //Offsets and length must be block-aligned - ESP_RETURN_ON_FALSE(ram_offset % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "ram offset not aligned to blocksize"); - ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "range not aligned to blocksize"); - ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "length not aligned to blocksize"); + ESP_RETURN_ON_FALSE(ram_offset % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "ram offset not aligned to blocksize"); + ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "range not aligned to blocksize"); + ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "length not aligned to blocksize"); //ram and range should be within allocated range - ESP_RETURN_ON_FALSE(ram_block + blockcount > handle->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of phys ram handle"); - ESP_RETURN_ON_FALSE(range_block + blockcount > range->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of range handle"); + ESP_RETURN_ON_FALSE(ram_block + blockcount <= handle->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of phys ram handle"); + ESP_RETURN_ON_FALSE(range_block + blockcount <= range->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of range handle"); //Check if ram blocks aren't already mapped, and if memory range is unmapped for (int i = 0; i < blockcount; i++) { - ESP_RETURN_ON_FALSE(s_ram_descriptor[handle->block[i + ram_block]].is_mapped, ESP_ERR_INVALID_STATE, TAG, "ram already mapped"); - ESP_RETURN_ON_FALSE(s_range_descriptor[range->block_start + i + range_block].is_mapped, ESP_ERR_INVALID_STATE, TAG, "range already mapped"); + ESP_RETURN_ON_FALSE(!s_ram_descriptor[handle->block[i + ram_block]].is_mapped, ESP_ERR_INVALID_STATE, TAG, "ram already mapped"); + ESP_RETURN_ON_FALSE(!s_range_descriptor[range->block_start + i + range_block].is_mapped, ESP_ERR_INVALID_STATE, TAG, "range already mapped"); } //Map and mark as mapped @@ -338,9 +338,9 @@ esp_err_t esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr, size_t len) int range_offset = (uint32_t)ptr - VIRT_HIMEM_RANGE_START; int range_block = (range_offset / CACHE_BLOCKSIZE) - range->block_start; int blockcount = len / CACHE_BLOCKSIZE; - ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "range offset not block-aligned"); - ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE != 0, ESP_ERR_INVALID_ARG, TAG, "map length not block-aligned"); - ESP_RETURN_ON_FALSE(range_block + blockcount > range->block_ct, ESP_ERR_INVALID_ARG, TAG, "range out of bounds for handle"); + ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "range offset not block-aligned"); + ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "map length not block-aligned"); + ESP_RETURN_ON_FALSE(range_block + blockcount <= range->block_ct, ESP_ERR_INVALID_ARG, TAG, "range out of bounds for handle"); portENTER_CRITICAL(&spinlock); for (int i = 0; i < blockcount; i++) { From 4bad316700f74afb5b9ad4d095998a52cc278821 Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Tue, 31 Aug 2021 10:32:54 +0800 Subject: [PATCH 089/310] freertos: several ESP specific things clearly marked --- components/freertos/event_groups.c | 9 ++++++--- components/freertos/include/freertos/event_groups.h | 5 ++++- components/freertos/include/freertos/task.h | 9 ++++++++- components/freertos/include/freertos/timers.h | 5 ++++- components/freertos/queue.c | 13 ++++++++----- components/freertos/timers.c | 9 +++++++-- 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/components/freertos/event_groups.c b/components/freertos/event_groups.c index c3ad94f214..f4be8973ae 100644 --- a/components/freertos/event_groups.c +++ b/components/freertos/event_groups.c @@ -84,7 +84,9 @@ typedef struct EventGroupDef_t uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ #endif +#ifdef ESP_PLATFORM portMUX_TYPE eventGroupMux; //Mutex required due to SMP +#endif // ESP_PLATFORM } EventGroup_t; /*-----------------------------------------------------------*/ @@ -140,8 +142,9 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ traceEVENT_GROUP_CREATE( pxEventBits ); - +#ifdef ESP_PLATFORM vPortCPUInitializeMutex( &pxEventBits->eventGroupMux ); +#endif // ESP_PLATFORM } else { @@ -191,9 +194,9 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, pxEventBits->ucStaticallyAllocated = pdFALSE; } #endif /* configSUPPORT_STATIC_ALLOCATION */ - +#ifdef ESP_PLATFORM vPortCPUInitializeMutex( &pxEventBits->eventGroupMux ); - +#endif // ESP_PLATFORM traceEVENT_GROUP_CREATE( pxEventBits ); } else diff --git a/components/freertos/include/freertos/event_groups.h b/components/freertos/include/freertos/event_groups.h index 8d7f6f8039..4d74120bc4 100644 --- a/components/freertos/include/freertos/event_groups.h +++ b/components/freertos/include/freertos/event_groups.h @@ -84,8 +84,11 @@ * \ingroup EventGroup */ struct EventGroupDef_t; +#ifdef ESP_PLATFORM // IDF-3770 typedef void * EventGroupHandle_t; -// typedef struct EventGroupDef_t * EventGroupHandle_t; +#else +typedef struct EventGroupDef_t * EventGroupHandle_t; +#endif // ESP_PLATFORM /* * The type that holds event bits always matches TickType_t - therefore the * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 8053c80645..2f6798caea 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -33,7 +33,9 @@ #endif #include "list.h" +#ifdef ESP_PLATFORM // IDF-3793 #include "freertos/portmacro.h" +#endif // ESP_PLATFORM /* *INDENT-OFF* */ #ifdef __cplusplus @@ -72,8 +74,11 @@ * \ingroup Tasks */ struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -//typedef struct tskTaskControlBlock* TaskHandle_t; +#ifdef ESP_PLATFORM // IDF-3769 typedef void* TaskHandle_t; +#else +typedef struct tskTaskControlBlock* TaskHandle_t; +#endif // ESP_PLATFORM /** * Defines the prototype to which the application task hook function must * conform. @@ -2768,8 +2773,10 @@ TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; */ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; +#ifdef ESP_PLATFORM /* TODO: IDF-3683 */ #include "freertos/task_snapshot.h" +#endif // ESP_PLATFORM /** @endcond */ diff --git a/components/freertos/include/freertos/timers.h b/components/freertos/include/freertos/timers.h index 69512f949e..6f3648aa77 100644 --- a/components/freertos/include/freertos/timers.h +++ b/components/freertos/include/freertos/timers.h @@ -75,8 +75,11 @@ * (for example, xTimerStart(), xTimerReset(), etc.). */ struct tmrTimerControl; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -//typedef struct tmrTimerControl * TimerHandle_t; +#ifdef ESP_PLATFORM // IDF-3768 typedef void* TimerHandle_t; +#else +typedef struct tmrTimerControl * TimerHandle_t; +#endif // ESP_PLATFORM /* * Defines the prototype to which timer callback functions must conform. */ diff --git a/components/freertos/queue.c b/components/freertos/queue.c index 2557117988..712fbd2119 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -139,9 +139,9 @@ typedef struct QueueDefinition /* The old naming convention is used to prevent b UBaseType_t uxQueueNumber; uint8_t ucQueueType; #endif - +#ifdef ESP_PLATFORM portMUX_TYPE mux; //Mutex required due to SMP - +#endif // ESP_PLATFORM } xQUEUE; /* The old xQUEUE name is maintained above then typedefed to the new Queue_t @@ -174,10 +174,10 @@ typedef xQUEUE Queue_t; * The pcQueueName member of a structure being NULL is indicative of the * array position being vacant. */ PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; - +#ifdef ESP_PLATFORM //Need to add queue registry mutex to protect against simultaneous access static portMUX_TYPE queue_registry_spinlock = portMUX_INITIALIZER_UNLOCKED; - +#endif // ESP_PLATFORM #endif /* configQUEUE_REGISTRY_SIZE */ /* @@ -285,10 +285,12 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, configASSERT( pxQueue ); +#ifdef ESP_PLATFORM if( xNewQueue == pdTRUE ) { vPortCPUInitializeMutex(&pxQueue->mux); } +#endif // ESP_PLATFORM taskENTER_CRITICAL(); { @@ -532,8 +534,9 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, /* In case this is a recursive mutex. */ pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0; +#ifdef ESP_PLATFORM vPortCPUInitializeMutex(&pxNewQueue->mux); - +#endif // ESP_PLATFORM traceCREATE_MUTEX( pxNewQueue ); /* Start with the semaphore in the expected state. */ diff --git a/components/freertos/timers.c b/components/freertos/timers.c index 9783299f76..76fc364fb6 100644 --- a/components/freertos/timers.c +++ b/components/freertos/timers.c @@ -152,8 +152,10 @@ PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; +#ifdef ESP_PLATFORM /* Mux. We use a single mux for all the timers for now. ToDo: maybe increase granularity here? */ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; +#endif // ESP_PLATFORM /*lint -restore */ @@ -521,13 +523,15 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; } /*-----------------------------------------------------------*/ - static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) + static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, + const TickType_t xTimeNow ) { BaseType_t xResult; Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ /* Remove the timer from the list of active timers. A check has already * been performed to ensure the list is not empty. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); traceTIMER_EXPIRED( pxTimer ); @@ -965,8 +969,9 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; /* Check that the list from which active timers are referenced, and the * queue used to communicate with the timer service, have been * initialised. */ - +#ifdef ESP_PLATFORM if( xTimerQueue == NULL ) vPortCPUInitializeMutex( &xTimerMux ); +#endif // ESP_PLATFORM taskENTER_CRITICAL(); { From 1e10851eacf01a461d983769459b600389f07ea0 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Tue, 24 Aug 2021 15:13:10 +0800 Subject: [PATCH 090/310] Fix docs: C3 has GPIO9 as bootstrap pin, not GPIO0. --- docs/en/api-guides/usb-serial-jtag-console.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/api-guides/usb-serial-jtag-console.rst b/docs/en/api-guides/usb-serial-jtag-console.rst index b2834d9d4c..0bdfeec4fd 100644 --- a/docs/en/api-guides/usb-serial-jtag-console.rst +++ b/docs/en/api-guides/usb-serial-jtag-console.rst @@ -46,7 +46,9 @@ Limitations There are several limitations to the USB console feature. These may or may not be significant, depending on the type of application being developed, and the development workflow. -1. If the application accidentally reconfigures the USB peripheral pins, or disables the USB Serial/JTAG Controller, the device will disappear from the system. After fixing the issue in the application, you will need to manually put the {IDF_TARGET_NAME} into download mode by pulling low GPIO0 and resetting the chip. +{IDF_TARGET_BOOT_PIN:default = "GPIO0", esp32c3 = "GPIO9"} + +1. If the application accidentally reconfigures the USB peripheral pins, or disables the USB Serial/JTAG Controller, the device will disappear from the system. After fixing the issue in the application, you will need to manually put the {IDF_TARGET_NAME} into download mode by pulling low {IDF_TARGET_BOOT_PIN} and resetting the chip. 2. If the application enters light sleep (including automatic light sleep) or deep sleep mode, USB CDC device will disappear from the system. From ed3d44042878b15779ce586fbb78ffe560fa2399 Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Tue, 2 Mar 2021 15:32:07 +0000 Subject: [PATCH 091/310] libcoap_430: Update code for use with libcoap 4.3.0 Remove no longer needed code from coap_server/coap_client. Add in multicast support for coap_server/coap_client. Update libcoap logging to use esp-idf logging Signed-off-by: Harshit Malpani --- components/coap/CMakeLists.txt | 18 +- components/coap/Kconfig | 3 + components/coap/component.mk | 6 +- components/coap/libcoap | 2 +- components/coap/port/coap_debug.c | 888 -------- components/coap/port/coap_mbedtls.c | 1869 ----------------- components/coap/port/coap_notls.c | 190 -- components/coap/port/include/coap/coap_dtls.h | 631 ------ .../coap/port/include/{coap => coap3}/coap.h | 41 +- .../coap/port/include/coap_config_posix.h | 3 +- examples/protocols/coap_client/README.md | 28 +- .../coap_client/main/certs/coap_ca.pem | 46 +- .../coap_client/main/certs/coap_client.crt | 79 +- .../coap_client/main/certs/coap_client.key | 31 +- .../main/coap_client_example_main.c | 614 +++--- .../protocols/coap_client/sdkconfig.defaults | 1 + examples/protocols/coap_server/README.md | 9 +- .../coap_server/main/Kconfig.projbuild | 50 + .../coap_server/main/certs/coap_ca.pem | 46 +- .../coap_server/main/certs/coap_server.crt | 79 +- .../coap_server/main/certs/coap_server.key | 31 +- .../main/coap_server_example_main.c | 109 +- .../protocols/coap_server/sdkconfig.defaults | 1 + 23 files changed, 598 insertions(+), 4177 deletions(-) delete mode 100644 components/coap/port/coap_debug.c delete mode 100644 components/coap/port/coap_mbedtls.c delete mode 100644 components/coap/port/coap_notls.c delete mode 100644 components/coap/port/include/coap/coap_dtls.h rename components/coap/port/include/{coap => coap3}/coap.h (53%) diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt index 2c3b57e1a2..77576e0a40 100644 --- a/components/coap/CMakeLists.txt +++ b/components/coap/CMakeLists.txt @@ -6,17 +6,24 @@ if(NOT CONFIG_LWIP_IPV6 AND NOT CMAKE_BUILD_EARLY_EXPANSION) return() endif() -set(include_dirs port/include port/include/coap libcoap/include libcoap/include/coap2) +set(include_dirs port/include port/include libcoap/include) set(srcs "libcoap/src/address.c" "libcoap/src/async.c" "libcoap/src/block.c" + "libcoap/src/coap_asn1.c" + "libcoap/src/coap_cache.c" + "libcoap/src/coap_debug.c" "libcoap/src/coap_event.c" "libcoap/src/coap_hashkey.c" + "libcoap/src/coap_io.c" + "libcoap/src/coap_mbedtls.c" + "libcoap/src/coap_notls.c" + "libcoap/src/coap_prng.c" "libcoap/src/coap_session.c" + "libcoap/src/coap_tcp.c" "libcoap/src/coap_time.c" - "port/coap_debug.c" "libcoap/src/encode.c" "libcoap/src/mem.c" "libcoap/src/net.c" @@ -25,17 +32,14 @@ set(srcs "libcoap/src/resource.c" "libcoap/src/str.c" "libcoap/src/subscribe.c" - "libcoap/src/uri.c" - "libcoap/src/coap_io.c" - "port/coap_notls.c" - "port/coap_mbedtls.c") + "libcoap/src/uri.c") idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" REQUIRES lwip mbedtls) # Silence format truncation warning, until it is fixed upstream -set_source_files_properties(port/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation) +# set_source_files_properties(libcoap/src/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation) # Needed for coap headers in public builds, also. # diff --git a/components/coap/Kconfig b/components/coap/Kconfig index a5d613e146..1221523c2b 100644 --- a/components/coap/Kconfig +++ b/components/coap/Kconfig @@ -52,6 +52,8 @@ menu "CoAP Configuration" bool "Info" config COAP_LOG_DEBUG bool "Debug" + config COAP_LOG_MBEDTLS + bool "mbedTLS" endchoice config COAP_LOG_DEFAULT_LEVEL @@ -65,5 +67,6 @@ menu "CoAP Configuration" default 5 if COAP_LOG_NOTICE default 6 if COAP_LOG_INFO default 7 if COAP_LOG_DEBUG + default 9 if COAP_LOG_MBEDTLS endmenu diff --git a/components/coap/component.mk b/components/coap/component.mk index eeec323f0c..19ef7fd50b 100644 --- a/components/coap/component.mk +++ b/components/coap/component.mk @@ -4,15 +4,15 @@ ifdef CONFIG_LWIP_IPV6 -COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap2 +COMPONENT_ADD_INCLUDEDIRS := port/include port/include libcoap/include -COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_session.o libcoap/src/coap_time.o port/coap_debug.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_mbedtls.o libcoap/src/coap_io.o port/coap_notls.o +COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_asn1.o libcoap/src/coap_cache.o libcoap/src/coap_debug.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_io.o libcoap/src/coap_mbedtls.o libcoap/src/coap_notls.o libcoap/src/coap_prng.o libcoap/src/coap_session.o libcoap/src/coap_tcp.o libcoap/src/coap_time.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o COMPONENT_SRCDIRS := libcoap/src libcoap port COMPONENT_SUBMODULES += libcoap # Silence format truncation warning, until it is fixed upstream -port/coap_debug.o: CFLAGS += -Wno-format-truncation +# libcoap/src/coap_debug.o: CFLAGS += -Wno-format-truncation endif # CONFIG_LWIP_IPV6 diff --git a/components/coap/libcoap b/components/coap/libcoap index 98954eb30a..9b6451c365 160000 --- a/components/coap/libcoap +++ b/components/coap/libcoap @@ -1 +1 @@ -Subproject commit 98954eb30a2e728e172a6cd29430ae5bc999b585 +Subproject commit 9b6451c3654bc1f625e36c87f018c2da34bea5e6 diff --git a/components/coap/port/coap_debug.c b/components/coap/port/coap_debug.c deleted file mode 100644 index 64d6a01800..0000000000 --- a/components/coap/port/coap_debug.c +++ /dev/null @@ -1,888 +0,0 @@ -/* debug.c -- debug utilities - * - * Copyright (C) 2010--2012,2014--2019 Olaf Bergmann and others - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#ifdef HAVE_TIME_H -#include -#endif - -#include "libcoap.h" -#include "coap_dtls.h" -#include "block.h" -#include "coap_debug.h" -#include "encode.h" -#include "net.h" -#include "coap_mutex.h" - -#ifdef WITH_LWIP -# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__)) -# define fflush(...) -#endif - -#ifdef WITH_CONTIKI -# ifndef DEBUG -# define DEBUG DEBUG_PRINT -# endif /* DEBUG */ -#include "net/ip/uip-debug.h" -#endif - -static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */ - -static int use_fprintf_for_show_pdu = 1; /* non zero to output with fprintf */ - -const char *coap_package_name(void) { - return PACKAGE_NAME; -} - -const char *coap_package_version(void) { - return PACKAGE_STRING; -} - -void -coap_set_show_pdu_output(int use_fprintf) { - use_fprintf_for_show_pdu = use_fprintf; -} - -coap_log_t -coap_get_log_level(void) { - return maxlog; -} - -void -coap_set_log_level(coap_log_t level) { - maxlog = level; -} - -/* this array has the same order as the type log_t */ -static const char *loglevels[] = { - "EMRG", "ALRT", "CRIT", "ERR ", "WARN", "NOTE", "INFO", "DEBG" -}; - -#ifdef HAVE_TIME_H - -COAP_STATIC_INLINE size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { - struct tm *tmp; - time_t now = coap_ticks_to_rt(t); - tmp = localtime(&now); - return strftime(s, len, "%b %d %H:%M:%S", tmp); -} - -#else /* alternative implementation: just print the timestamp */ - -COAP_STATIC_INLINE size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { -#ifdef HAVE_SNPRINTF - return snprintf(s, len, "%u.%03u", - (unsigned int)coap_ticks_to_rt(t), - (unsigned int)(t % COAP_TICKS_PER_SECOND)); -#else /* HAVE_SNPRINTF */ - /* @todo do manual conversion of timestamp */ - return 0; -#endif /* HAVE_SNPRINTF */ -} - -#endif /* HAVE_TIME_H */ - -#ifndef HAVE_STRNLEN -/** - * A length-safe strlen() fake. - * - * @param s The string to count characters != 0. - * @param maxlen The maximum length of @p s. - * - * @return The length of @p s. - */ -static inline size_t -strnlen(const char *s, size_t maxlen) { - size_t n = 0; - while(*s++ && n < maxlen) - ++n; - return n; -} -#endif /* HAVE_STRNLEN */ - -static size_t -print_readable( const uint8_t *data, size_t len, - unsigned char *result, size_t buflen, int encode_always ) { - const uint8_t hex[] = "0123456789ABCDEF"; - size_t cnt = 0; - assert(data || len == 0); - - if (buflen == 0) { /* there is nothing we can do here but return */ - return 0; - } - - while (len) { - if (!encode_always && isprint(*data)) { - if (cnt+1 < buflen) { /* keep one byte for terminating zero */ - *result++ = *data; - ++cnt; - } else { - break; - } - } else { - if (cnt+4 < buflen) { /* keep one byte for terminating zero */ - *result++ = '\\'; - *result++ = 'x'; - *result++ = hex[(*data & 0xf0) >> 4]; - *result++ = hex[*data & 0x0f]; - cnt += 4; - } else - break; - } - - ++data; --len; - } - - *result = '\0'; /* add a terminating zero */ - return cnt; -} - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -size_t -coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) { -#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H ) - const void *addrptr = NULL; - in_port_t port; - unsigned char *p = buf; - size_t need_buf; - - switch (addr->addr.sa.sa_family) { - case AF_INET: - addrptr = &addr->addr.sin.sin_addr; - port = ntohs(addr->addr.sin.sin_port); - need_buf = INET_ADDRSTRLEN; - break; - case AF_INET6: - if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */ - return 0; - - *p++ = '['; - - addrptr = &addr->addr.sin6.sin6_addr; - port = ntohs(addr->addr.sin6.sin6_port); - need_buf = INET6_ADDRSTRLEN; - - break; - default: - memcpy(buf, "(unknown address type)", min(22, len)); - return min(22, len); - } - - /* Cast needed for Windows, since it doesn't have the correct API signature. */ - if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, - min(len, need_buf)) == 0) { - perror("coap_print_addr"); - return 0; - } - - p += strnlen((char *)p, len); - - if (addr->addr.sa.sa_family == AF_INET6) { - if (p < buf + len) { - *p++ = ']'; - } else - return 0; - } - - p += snprintf((char *)p, buf + len - p + 1, ":%d", port); - - return buf + len - p; -#else /* HAVE_ARPA_INET_H */ -# if WITH_CONTIKI - unsigned char *p = buf; - uint8_t i; -# if NETSTACK_CONF_WITH_IPV6 - const uint8_t hex[] = "0123456789ABCDEF"; - - if (len < 41) - return 0; - - *p++ = '['; - - for (i=0; i < 16; i += 2) { - if (i) { - *p++ = ':'; - } - *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i] & 0x0f)]; - *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; - } - *p++ = ']'; -# else /* WITH_UIP6 */ -# warning "IPv4 network addresses will not be included in debug output" - - if (len < 21) - return 0; -# endif /* WITH_UIP6 */ - if (buf + len - p < 6) - return 0; - -#ifdef HAVE_SNPRINTF - p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port)); -#else /* HAVE_SNPRINTF */ - /* @todo manual conversion of port number */ -#endif /* HAVE_SNPRINTF */ - - return p - buf; -# else /* WITH_CONTIKI */ - /* TODO: output addresses manually */ -# warning "inet_ntop() not available, network addresses will not be included in debug output" -# endif /* WITH_CONTIKI */ - return 0; -#endif -} - -#ifdef WITH_CONTIKI -# define fprintf(fd, ...) PRINTF(__VA_ARGS__) -# define fflush(...) - -# ifdef HAVE_VPRINTF -# define vfprintf(fd, ...) vprintf(__VA_ARGS__) -# else /* HAVE_VPRINTF */ -# define vfprintf(fd, ...) PRINTF(__VA_ARGS__) -# endif /* HAVE_VPRINTF */ -#endif /* WITH_CONTIKI */ - -/** Returns a textual description of the message type @p t. */ -static const char * -msg_type_string(uint16_t t) { - static const char *types[] = { "CON", "NON", "ACK", "RST", "???" }; - - return types[min(t, sizeof(types)/sizeof(char *) - 1)]; -} - -/** Returns a textual description of the method or response code. */ -static const char * -msg_code_string(uint16_t c) { - static const char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE", - "FETCH", "PATCH", "iPATCH" }; - static const char *signals[] = { "7.00", "CSM", "Ping", "Pong", "Release", - "Abort" }; - static char buf[5]; - - if (c < sizeof(methods)/sizeof(const char *)) { - return methods[c]; - } else if (c >= 224 && c - 224 < (int)(sizeof(signals)/sizeof(const char *))) { - return signals[c-224]; - } else { - snprintf(buf, sizeof(buf), "%u.%02u", (c >> 5) & 0x7, c & 0x1f); - return buf; - } -} - -/** Returns a textual description of the option name. */ -static const char * -msg_option_string(uint8_t code, uint16_t option_type) { - struct option_desc_t { - uint16_t type; - const char *name; - }; - - static struct option_desc_t options[] = { - { COAP_OPTION_IF_MATCH, "If-Match" }, - { COAP_OPTION_URI_HOST, "Uri-Host" }, - { COAP_OPTION_ETAG, "ETag" }, - { COAP_OPTION_IF_NONE_MATCH, "If-None-Match" }, - { COAP_OPTION_OBSERVE, "Observe" }, - { COAP_OPTION_URI_PORT, "Uri-Port" }, - { COAP_OPTION_LOCATION_PATH, "Location-Path" }, - { COAP_OPTION_URI_PATH, "Uri-Path" }, - { COAP_OPTION_CONTENT_FORMAT, "Content-Format" }, - { COAP_OPTION_MAXAGE, "Max-Age" }, - { COAP_OPTION_URI_QUERY, "Uri-Query" }, - { COAP_OPTION_ACCEPT, "Accept" }, - { COAP_OPTION_LOCATION_QUERY, "Location-Query" }, - { COAP_OPTION_BLOCK2, "Block2" }, - { COAP_OPTION_BLOCK1, "Block1" }, - { COAP_OPTION_PROXY_URI, "Proxy-Uri" }, - { COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" }, - { COAP_OPTION_SIZE1, "Size1" }, - { COAP_OPTION_SIZE2, "Size2" }, - { COAP_OPTION_NORESPONSE, "No-Response" } - }; - - static struct option_desc_t options_csm[] = { - { COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, "Max-Message-Size" }, - { COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, "Block-wise-Transfer" } - }; - - static struct option_desc_t options_pingpong[] = { - { COAP_SIGNALING_OPTION_CUSTODY, "Custody" } - }; - - static struct option_desc_t options_release[] = { - { COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS, "Alternative-Address" }, - { COAP_SIGNALING_OPTION_HOLD_OFF, "Hold-Off" } - }; - - static struct option_desc_t options_abort[] = { - { COAP_SIGNALING_OPTION_BAD_CSM_OPTION, "Bad-CSM-Option" } - }; - - static char buf[6]; - size_t i; - - if (code == COAP_SIGNALING_CSM) { - for (i = 0; i < sizeof(options_csm)/sizeof(struct option_desc_t); i++) { - if (option_type == options_csm[i].type) { - return options_csm[i].name; - } - } - } else if (code == COAP_SIGNALING_PING || code == COAP_SIGNALING_PONG) { - for (i = 0; i < sizeof(options_pingpong)/sizeof(struct option_desc_t); i++) { - if (option_type == options_pingpong[i].type) { - return options_pingpong[i].name; - } - } - } else if (code == COAP_SIGNALING_RELEASE) { - for (i = 0; i < sizeof(options_release)/sizeof(struct option_desc_t); i++) { - if (option_type == options_release[i].type) { - return options_release[i].name; - } - } - } else if (code == COAP_SIGNALING_ABORT) { - for (i = 0; i < sizeof(options_abort)/sizeof(struct option_desc_t); i++) { - if (option_type == options_abort[i].type) { - return options_abort[i].name; - } - } - } else { - /* search option_type in list of known options */ - for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) { - if (option_type == options[i].type) { - return options[i].name; - } - } - } - /* unknown option type, just print to buf */ - snprintf(buf, sizeof(buf), "%u", option_type); - return buf; -} - -static unsigned int -print_content_format(unsigned int format_type, - unsigned char *result, unsigned int buflen) { - struct desc_t { - unsigned int type; - const char *name; - }; - - static struct desc_t formats[] = { - { COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" }, - { COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" }, - { COAP_MEDIATYPE_APPLICATION_XML, "application/xml" }, - { COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" }, - { COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" }, - { COAP_MEDIATYPE_APPLICATION_JSON, "application/json" }, - { COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" }, - { COAP_MEDIATYPE_APPLICATION_COSE_SIGN, "application/cose; cose-type=\"cose-sign\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_SIGN1, "application/cose; cose-type=\"cose-sign1\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, "application/cose; cose-type=\"cose-encrypt\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0, "application/cose; cose-type=\"cose-encrypt0\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_MAC, "application/cose; cose-type=\"cose-mac\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_MAC0, "application/cose; cose-type=\"cose-mac0\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_KEY, "application/cose-key" }, - { COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, "application/cose-key-set" }, - { COAP_MEDIATYPE_APPLICATION_SENML_JSON, "application/senml+json" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_JSON, "application/sensml+json" }, - { COAP_MEDIATYPE_APPLICATION_SENML_CBOR, "application/senml+cbor" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_CBOR, "application/sensml+cbor" }, - { COAP_MEDIATYPE_APPLICATION_SENML_EXI, "application/senml-exi" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_EXI, "application/sensml-exi" }, - { COAP_MEDIATYPE_APPLICATION_SENML_XML, "application/senml+xml" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_XML, "application/sensml+xml" }, - { 75, "application/dcaf+cbor" } - }; - - size_t i; - - /* search format_type in list of known content formats */ - for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) { - if (format_type == formats[i].type) { - return snprintf((char *)result, buflen, "%s", formats[i].name); - } - } - - /* unknown content format, just print numeric value to buf */ - return snprintf((char *)result, buflen, "%d", format_type); -} - -/** - * Returns 1 if the given @p content_format is either unknown or known - * to carry binary data. The return value @c 0 hence indicates - * printable data which is also assumed if @p content_format is @c 01. - */ -COAP_STATIC_INLINE int -is_binary(int content_format) { - return !(content_format == -1 || - content_format == COAP_MEDIATYPE_TEXT_PLAIN || - content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT || - content_format == COAP_MEDIATYPE_APPLICATION_XML || - content_format == COAP_MEDIATYPE_APPLICATION_JSON); -} - -#define COAP_DO_SHOW_OUTPUT_LINE \ - do { \ - if (use_fprintf_for_show_pdu) { \ - fprintf(COAP_DEBUG_FD, "%s", outbuf); \ - } \ - else { \ - coap_log(level, "%s", outbuf); \ - } \ - } while (0) - -void -coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t static_show_pdu_mutex = COAP_MUTEX_INITIALIZER; - static unsigned char buf[1024]; /* need some space for output creation */ - static char outbuf[COAP_DEBUG_BUF_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - unsigned char buf[1024]; /* need some space for output creation */ - char outbuf[COAP_DEBUG_BUF_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - size_t buf_len = 0; /* takes the number of bytes written to buf */ - int encode = 0, have_options = 0, i; - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - int content_format = -1; - size_t data_len; - unsigned char *data; - int outbuflen = 0; - - /* Save time if not needed */ - if (level > coap_get_log_level()) - return; - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&static_show_pdu_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - snprintf(outbuf, sizeof(outbuf), "v:%d t:%s c:%s i:%04x {", - COAP_DEFAULT_VERSION, msg_type_string(pdu->type), - msg_code_string(pdu->code), pdu->tid); - - for (i = 0; i < pdu->token_length; i++) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%02x", pdu->token[i]); - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "}"); - - /* show options, if any */ - coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ["); - while ((option = coap_option_next(&opt_iter))) { - if (!have_options) { - have_options = 1; - } else { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ","); - } - - if (pdu->code == COAP_SIGNALING_CSM) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else if (pdu->code == COAP_SIGNALING_PING - || pdu->code == COAP_SIGNALING_PONG) { - buf_len = 0; - } else if (pdu->code == COAP_SIGNALING_RELEASE) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS: - buf_len = print_readable(coap_opt_value(option), - coap_opt_length(option), - buf, sizeof(buf), 0); - break; - case COAP_SIGNALING_OPTION_HOLD_OFF: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else if (pdu->code == COAP_SIGNALING_ABORT) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_BAD_CSM_OPTION: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else switch (opt_iter.type) { - case COAP_OPTION_CONTENT_FORMAT: - content_format = (int)coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option)); - - buf_len = print_content_format(content_format, buf, sizeof(buf)); - break; - - case COAP_OPTION_BLOCK1: - case COAP_OPTION_BLOCK2: - /* split block option into number/more/size where more is the - * letter M if set, the _ otherwise */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u", - coap_opt_block_num(option), /* block number */ - COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */ - (1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */ - - break; - - case COAP_OPTION_URI_PORT: - case COAP_OPTION_MAXAGE: - case COAP_OPTION_OBSERVE: - case COAP_OPTION_SIZE1: - case COAP_OPTION_SIZE2: - /* show values as unsigned decimal value */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - - default: - /* generic output function for all other option types */ - if (opt_iter.type == COAP_OPTION_URI_PATH || - opt_iter.type == COAP_OPTION_PROXY_URI || - opt_iter.type == COAP_OPTION_URI_HOST || - opt_iter.type == COAP_OPTION_LOCATION_PATH || - opt_iter.type == COAP_OPTION_LOCATION_QUERY || - opt_iter.type == COAP_OPTION_URI_QUERY) { - encode = 0; - } else { - encode = 1; - } - - buf_len = print_readable(coap_opt_value(option), - coap_opt_length(option), - buf, sizeof(buf), encode); - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - " %s:%.*s", msg_option_string(pdu->code, opt_iter.type), - (int)buf_len, buf); - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ]"); - - if (coap_get_data(pdu, &data_len, &data)) { - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " :: "); - - if (is_binary(content_format)) { - int keep_data_len = data_len; - uint8_t *keep_data = data; - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "binary data length %zu\n", data_len); - COAP_DO_SHOW_OUTPUT_LINE; - /* - * Output hex dump of binary data as a continuous entry - */ - outbuf[0] = '\000'; - snprintf(outbuf, sizeof(outbuf), "<<"); - while (data_len--) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%02x", *data++); - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); - data_len = keep_data_len; - data = keep_data; - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); - COAP_DO_SHOW_OUTPUT_LINE; - /* - * Output ascii readable (if possible), immediately under the - * hex value of the character output above to help binary debugging - */ - outbuf[0] = '\000'; - snprintf(outbuf, sizeof(outbuf), "<<"); - while (data_len--) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%c ", isprint (*data) ? *data : '.'); - data++; - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); - } else { - if (print_readable(data, data_len, buf, sizeof(buf), 0)) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "'%s'", buf); - } - } - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); - COAP_DO_SHOW_OUTPUT_LINE; - -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&static_show_pdu_mutex); -#endif /* COAP_CONSTRAINED_STACK */ -} - -void coap_show_tls_version(coap_log_t level) -{ - char buffer[64]; - coap_string_tls_version(buffer, sizeof(buffer)); - coap_log(level, "%s\n", buffer); -} - -char *coap_string_tls_version(char *buffer, size_t bufsize) -{ - coap_tls_version_t *tls_version = coap_get_tls_library_version(); - char beta[8]; - char sub[2]; - char b_beta[8]; - char b_sub[2]; - - switch (tls_version->type) { - case COAP_TLS_LIBRARY_NOTLS: - snprintf(buffer, bufsize, "TLS Library: None"); - break; - case COAP_TLS_LIBRARY_TINYDTLS: - snprintf(buffer, bufsize, "TLS Library: TinyDTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 16), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->version & 0xff), - (unsigned long)(tls_version->built_version >> 16), - (unsigned long)((tls_version->built_version >> 8) & 0xff), - (unsigned long)(tls_version->built_version & 0xff)); - break; - case COAP_TLS_LIBRARY_OPENSSL: - switch (tls_version->version &0xf) { - case 0: - strcpy(beta, "-dev"); - break; - case 0xf: - strcpy(beta, ""); - break; - default: - strcpy(beta, "-beta"); - beta[5] = (tls_version->version &0xf) + '0'; - beta[6] = '\000'; - break; - } - sub[0] = ((tls_version->version >> 4) & 0xff) ? - ((tls_version->version >> 4) & 0xff) + 'a' -1 : '\000'; - sub[1] = '\000'; - switch (tls_version->built_version &0xf) { - case 0: - strcpy(b_beta, "-dev"); - break; - case 0xf: - strcpy(b_beta, ""); - break; - default: - strcpy(b_beta, "-beta"); - b_beta[5] = (tls_version->built_version &0xf) + '0'; - b_beta[6] = '\000'; - break; - } - b_sub[0] = ((tls_version->built_version >> 4) & 0xff) ? - ((tls_version->built_version >> 4) & 0xff) + 'a' -1 : '\000'; - b_sub[1] = '\000'; - snprintf(buffer, bufsize, "TLS Library: OpenSSL - runtime " - "%lu.%lu.%lu%s%s, libcoap built for %lu.%lu.%lu%s%s", - (unsigned long)(tls_version->version >> 28), - (unsigned long)((tls_version->version >> 20) & 0xff), - (unsigned long)((tls_version->version >> 12) & 0xff), sub, beta, - (unsigned long)(tls_version->built_version >> 28), - (unsigned long)((tls_version->built_version >> 20) & 0xff), - (unsigned long)((tls_version->built_version >> 12) & 0xff), - b_sub, b_beta); - break; - case COAP_TLS_LIBRARY_GNUTLS: - snprintf(buffer, bufsize, "TLS Library: GnuTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 16), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->version & 0xff), - (unsigned long)(tls_version->built_version >> 16), - (unsigned long)((tls_version->built_version >> 8) & 0xff), - (unsigned long)(tls_version->built_version & 0xff)); - break; - case COAP_TLS_LIBRARY_MBEDTLS: - snprintf(buffer, bufsize, "TLS Library: MbedTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 24), - (unsigned long)((tls_version->version >> 16) & 0xff), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->built_version >> 24), - (unsigned long)((tls_version->built_version >> 16) & 0xff), - (unsigned long)((tls_version->built_version >> 8) & 0xff)); - break; - default: - snprintf(buffer, bufsize, "Library type %d unknown", tls_version->type); - break; - } - return buffer; -} - -static coap_log_handler_t log_handler = NULL; - -void coap_set_log_handler(coap_log_handler_t handler) { - log_handler = handler; -} - -void -coap_log_impl(coap_log_t level, const char *format, ...) { - - if (maxlog < level) - return; - - if (log_handler) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t static_log_mutex = COAP_MUTEX_INITIALIZER; - static char message[COAP_DEBUG_BUF_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - char message[COAP_DEBUG_BUF_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - va_list ap; - va_start(ap, format); -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&static_log_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - vsnprintf( message, sizeof(message), format, ap); - va_end(ap); - log_handler(level, message); -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&static_log_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - } else { - char timebuf[32]; - coap_tick_t now; - va_list ap; - FILE *log_fd; - - log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD; - - coap_ticks(&now); - if (print_timestamp(timebuf,sizeof(timebuf), now)) - fprintf(log_fd, "%s ", timebuf); - - if (level <= LOG_DEBUG) - fprintf(log_fd, "%s ", loglevels[level]); - - va_start(ap, format); - vfprintf(log_fd, format, ap); - va_end(ap); - fflush(log_fd); - } -} - -static struct packet_num_interval { - int start; - int end; -} packet_loss_intervals[10]; -static int num_packet_loss_intervals = 0; -static int packet_loss_level = 0; -static int send_packet_count = 0; - -int coap_debug_set_packet_loss(const char *loss_level) { - const char *p = loss_level; - char *end = NULL; - int n = (int)strtol(p, &end, 10), i = 0; - if (end == p || n < 0) - return 0; - if (*end == '%') { - if (n > 100) - n = 100; - packet_loss_level = n * 65536 / 100; - coap_log(LOG_DEBUG, "packet loss level set to %d%%\n", n); - } else { - if (n <= 0) - return 0; - while (i < 10) { - packet_loss_intervals[i].start = n; - if (*end == '-') { - p = end + 1; - n = (int)strtol(p, &end, 10); - if (end == p || n <= 0) - return 0; - } - packet_loss_intervals[i++].end = n; - if (*end == 0) - break; - if (*end != ',') - return 0; - p = end + 1; - n = (int)strtol(p, &end, 10); - if (end == p || n <= 0) - return 0; - } - if (i == 10) - return 0; - num_packet_loss_intervals = i; - } - send_packet_count = 0; - return 1; -} - -int coap_debug_send_packet(void) { - ++send_packet_count; - if (num_packet_loss_intervals > 0) { - int i; - for (i = 0; i < num_packet_loss_intervals; i++) { - if (send_packet_count >= packet_loss_intervals[i].start - && send_packet_count <= packet_loss_intervals[i].end) - return 0; - } - } - if ( packet_loss_level > 0 ) { - uint16_t r = 0; - prng( (uint8_t*)&r, 2 ); - if ( r < packet_loss_level ) - return 0; - } - return 1; -} diff --git a/components/coap/port/coap_mbedtls.c b/components/coap/port/coap_mbedtls.c deleted file mode 100644 index ef016a125d..0000000000 --- a/components/coap/port/coap_mbedtls.c +++ /dev/null @@ -1,1869 +0,0 @@ -/* -* coap_mbedtls.c -- mbedTLS Datagram Transport Layer Support for libcoap -* -* Copyright (C) 2019 Jon Shallow -* 2019 Jitin George -* -* This file is part of the CoAP library libcoap. Please see README for terms -* of use. -*/ - -/* - * Naming used to prevent confusion between coap sessions, mbedtls sessions etc. - * when reading the code. - * - * c_context A coap_context_t * - * c_session A coap_session_t * - * m_context A coap_mbedtls_context_t * (held in c_context->dtls_context) - * m_env A coap_mbedtls_env_t * (held in c_session->tls) - */ - -#include "coap_config.h" - -#ifdef HAVE_MBEDTLS - -/* - * Once PS #335 has been merged in, then code following a rebase needs to be - * updated removing sections that are "#ifndef PSK2_PR", and then remove all - * references to PSK2_PR. - */ -#undef PSK2_PR - -#include "libcoap.h" -#include "coap_dtls.h" -#include "net.h" -#include "mem.h" -#include "coap_debug.h" -#include "prng.h" -#include "coap_mutex.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) -#include -#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ -#include -#include - -#define mbedtls_malloc(a) malloc(a) -#define mbedtls_realloc(a,b) realloc(a,b) -#define mbedtls_strdup(a) strdup(a) - -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else /* __GNUC__ */ -#define UNUSED -#endif /* __GNUC__ */ - -#define IS_PSK (1 << 0) -#define IS_PKI (1 << 1) -#define IS_CLIENT (1 << 6) -#define IS_SERVER (1 << 7) - -typedef struct coap_ssl_t { - const uint8_t *pdu; - unsigned pdu_len; - unsigned peekmode; - coap_tick_t timeout; -} coap_ssl_t; - -/* - * This structure encapsulates the mbedTLS session object. - * It handles both TLS and DTLS. - * c_session->tls points to this. - */ -typedef struct coap_mbedtls_env_t { - mbedtls_ssl_context ssl; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_config conf; - mbedtls_timing_delay_context timer; - mbedtls_x509_crt cacert; - mbedtls_x509_crt public_cert; - mbedtls_pk_context private_key; - mbedtls_ssl_cookie_ctx cookie_ctx; - /* If not set, need to do do_mbedtls_handshake */ - int established; - int seen_client_hello; - coap_ssl_t coap_ssl_data; -} coap_mbedtls_env_t; - -typedef struct pki_sni_entry { - char *sni; - coap_dtls_key_t pki_key; - mbedtls_x509_crt cacert; - mbedtls_x509_crt public_cert; - mbedtls_pk_context private_key; -} pki_sni_entry; - -#ifdef PSK2_PR -typedef struct psk_sni_entry { - coap_string_t sni; - coap_dtls_spsk_info_t psk_info; -} psk_sni_entry; -#endif /* PSK2_PR */ - -typedef struct coap_mbedtls_context_t { - coap_dtls_pki_t setup_data; - size_t pki_sni_count; - pki_sni_entry *pki_sni_entry_list; -#ifdef PSK2_PR - size_t psk_sni_count; - psk_sni_entry *psk_sni_entry_list; -#endif /* PSK2_PR */ - char *root_ca_file; - char *root_ca_path; - int psk_pki_enabled; -} coap_mbedtls_context_t; - -static int coap_dgram_read(void *ctx, unsigned char *out, size_t outl) -{ - ssize_t ret = 0; - coap_session_t *c_session = (struct coap_session_t *)ctx; - coap_ssl_t *data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data; - - if (!c_session->tls) { - errno = EAGAIN; - return MBEDTLS_ERR_SSL_WANT_READ; - } - - if (out != NULL) { - if (data != NULL && data->pdu_len > 0) { - if (outl < data->pdu_len) { - memcpy(out, data->pdu, outl); - ret = outl; - data->pdu += outl; - data->pdu_len -= outl; - } - else { - memcpy(out, data->pdu, data->pdu_len); - ret = data->pdu_len; - if (!data->peekmode) { - data->pdu_len = 0; - data->pdu = NULL; - } - } - } - else { - ret = MBEDTLS_ERR_SSL_WANT_READ; - errno = EAGAIN; - return ret; - } - } - return ret; -} - -/* - * return +ve data amount - * 0 no more - * -1 error (error in errno) - */ -/* callback function given to mbedtls for sending data over socket */ -static int -coap_dgram_write(void *ctx, const unsigned char *send_buffer, - size_t send_buffer_length) -{ - ssize_t result = -1; - coap_session_t *c_session = (struct coap_session_t *)ctx; - - if (c_session) { - result = coap_session_send(c_session, send_buffer, send_buffer_length); - if (result != (int)send_buffer_length) { - coap_log(LOG_WARNING, "coap_network_send failed (%zd != %zd)\n", - result, send_buffer_length); - result = 0; - } - } else { - result = 0; - } - return result; -} - -#if !defined(ESPIDF_VERSION) || (defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) && defined(CONFIG_MBEDTLS_TLS_SERVER)) -static char* -get_ip_addr(const struct coap_address_t *addr) -{ - const void *addrptr = NULL; - size_t buf_len; - - if (!addr) { - return NULL; - } - switch (addr->addr.sa.sa_family) { - case AF_INET: - addrptr = &addr->addr.sin.sin_addr; - buf_len = INET_ADDRSTRLEN; - break; - case AF_INET6: - addrptr = &addr->addr.sin6.sin6_addr; - buf_len = INET6_ADDRSTRLEN; - break; - default: - return NULL; - } - char *str = (char *)mbedtls_calloc(1, buf_len); - if (!str) { - coap_log(LOG_ERR, "Memory allocation failed\n"); - return NULL; - } - if (inet_ntop(addr->addr.sa.sa_family, addrptr, str, - buf_len) == 0) { - perror("coap_print_addr"); - return 0; - } - return str; -} -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ - -#if !defined(ESPIDF_VERSION) || (defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) && defined(CONFIG_MBEDTLS_PSK_MODES) && defined(CONFIG_MBEDTLS_TLS_SERVER)) -/* - * Server side PSK callback - */ -static int psk_server_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *name, size_t name_len ) -{ - coap_session_t *c_session = - (coap_session_t *)p_info; - uint8_t buf[128]; - size_t psk_len; -#ifdef PSK2_PR - coap_dtls_spsk_t *setup_data; -#endif /* PSK2_PR */ - coap_mbedtls_env_t *m_env; - - coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n", - (int)name_len, name); - - if (c_session == NULL || c_session->context == NULL || - c_session->context->get_server_psk == NULL) { - return -1; - } - m_env = (coap_mbedtls_env_t *)c_session->tls; -#ifdef PSK2_PR - setup_data = &c_session->context->spsk_setup_data; - - if (setup_data->validate_id_call_back) { - coap_bin_const_t lidentity; - lidentity.length = name_len; - lidentity.s = (const uint8_t*)name; - const coap_bin_const_t *psk_key = - setup_data->validate_id_call_back(&lidentity, - c_session, - setup_data->id_call_back_arg); - - if (psk_key == NULL) - return -1; - mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length); - coap_session_refresh_psk_key(c_session, psk_key); - m_env->seen_client_hello = 1; - return 0; - } -#endif /* PSK2_PR */ - - psk_len = c_session->context->get_server_psk(c_session, - (const uint8_t*)name, - name_len, - (uint8_t*)buf, sizeof(buf)); - m_env->seen_client_hello = 1; - mbedtls_ssl_set_hs_psk(ssl, buf, psk_len); - return 0; -} -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_PSK_MODES && CONFIG_MBEDTLS_TLS_SERVER) */ - -static char* -get_san_or_cn_from_cert(mbedtls_x509_crt *crt) -{ - if (crt) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t a_static_mutex = COAP_MUTEX_INITIALIZER; - static char buf[1024]; -#else /* ! COAP_CONSTRAINED_STACK */ - char buf[1024]; -#endif /* ! COAP_CONSTRAINED_STACK */ - char *cn; - char *cp; - char *tcp; - int n; - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt ); - - /* Look first to see if Subject Alt Name is defined */ - cp = strstr(buf, "subject alt name"); - if (cp) { - cp = strchr(cp, ':'); - if (cp) { - cp++; - while (*cp == ' ') cp++; - tcp = strchr(cp, '\n'); - if (tcp) - *tcp = '\000'; - /* Take only the first entry */ - tcp = strchr(cp, ','); - if (tcp) - *tcp = '\000'; - /* Return the Subject Alt Name */ -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return mbedtls_strdup(cp); - } - } - - /* Pull CN= out of subject name */ - cp = strstr(buf, "subject name"); - if (cp) { - cp = strchr(cp, ':'); - if (cp) { - cp++; - while (*cp == ' ') cp++; - tcp = strchr(cp, '\n'); - if (tcp) - *tcp = '\000'; - - /* Need to emulate strcasestr() here. Looking for CN= */ - n = strlen(cp) - 3; - cn = cp; - while (n > 0) { - if (((cn[0] == 'C') || (cn[0] == 'c')) && - ((cn[1] == 'N') || (cn[1] == 'n')) && - (cn[2] == '=')) { - cn += 3; - break; - } - cn++; - n--; - } - if (n > 0) { - tcp = strchr(cn, ','); - if (tcp) - *tcp = '\000'; -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return mbedtls_strdup(cn); - } - } - } -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - } - return NULL; -} - -/* - * return 0 All OK - * -ve Error Code - */ -static int -cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt, - int depth, uint32_t *flags) -{ - coap_session_t *c_session = (coap_session_t*)data; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - coap_dtls_pki_t *setup_data = &m_context->setup_data; - char *cn = NULL; - - if (*flags == 0) - return 0; - - if (!setup_data->verify_peer_cert) { - /* Nothing is being checked */ - *flags = 0; - return 0; - } - - cn = get_san_or_cn_from_cert(crt); - - if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) { - if (setup_data->allow_expired_certs) { - *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has expired", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_FUTURE) { - if (setup_data->allow_expired_certs) { - *flags &= ~MBEDTLS_X509_BADCERT_FUTURE; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a future date", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) { - if (setup_data->allow_bad_md_hash) { - *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a bad MD hash", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) { - if (setup_data->allow_short_rsa_length) { - *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a short RSA length", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) { - if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { - *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate's CRL has expired", cn ? cn : "?", depth); - } - else if (!setup_data->check_cert_revocation) { - *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; - } - } - if (*flags & MBEDTLS_X509_BADCRL_FUTURE) { - if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { - *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate's CRL has a future date", cn ? cn : "?", depth); - } - else if (!setup_data->check_cert_revocation) { - *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; - } - } - - if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) { - *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - if (setup_data->validate_cn_call_back) { - if (!setup_data->validate_cn_call_back(cn, - crt->raw.p, - crt->raw.len, - c_session, - depth, - *flags == 0, - setup_data->cn_call_back_arg)) { - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - } - if (*flags != 0) { - char buf[128]; - char *tcp; - - mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags); - tcp = strchr(buf, '\n'); - while (tcp) { - *tcp = '\000'; - coap_log(LOG_WARNING, - " %s: %s: issue 0x%x: '%s' depth %d\n", - coap_session_str(c_session), - buf, *flags, cn ? cn : "?", depth); - tcp = strchr(tcp+1, '\n'); - } - } - - if (cn) - mbedtls_free(cn); - - return 0; -} - -static int -setup_pki_credentials(mbedtls_x509_crt *cacert, - mbedtls_x509_crt *public_cert, - mbedtls_pk_context *private_key, - coap_mbedtls_env_t *m_env, - coap_mbedtls_context_t *m_context, - coap_session_t *c_session, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role) -{ - int ret; - - switch (setup_data->pki_key.key_type) { - case COAP_PKI_KEY_PEM: - if (setup_data->pki_key.key.pem.public_cert && - setup_data->pki_key.key.pem.public_cert[0] && - setup_data->pki_key.key.pem.private_key && - setup_data->pki_key.key.pem.private_key[0]) { - - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - - ret = mbedtls_x509_crt_parse_file(public_cert, - setup_data->pki_key.key.pem.public_cert); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse_file returned -0x%x\n\n", - -ret); - return ret; - } - - ret = mbedtls_pk_parse_keyfile(private_key, - setup_data->pki_key.key.pem.private_key, NULL); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } - else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.pem.ca_file && - setup_data->pki_key.key.pem.ca_file[0]) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse_file(cacert, - setup_data->pki_key.key.pem.ca_file); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - case COAP_PKI_KEY_PEM_BUF: - if (setup_data->pki_key.key.pem_buf.public_cert && - setup_data->pki_key.key.pem_buf.public_cert_len && - setup_data->pki_key.key.pem_buf.private_key && - setup_data->pki_key.key.pem_buf.private_key_len > 0) { - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - ret = mbedtls_x509_crt_parse(public_cert, - (const unsigned char *)setup_data->pki_key.key.pem_buf.public_cert, - setup_data->pki_key.key.pem_buf.public_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_pk_parse_key(private_key, - (const unsigned char *)setup_data->pki_key.key.pem_buf.private_key, - setup_data->pki_key.key.pem_buf.private_key_len, NULL, 0); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.pem_buf.ca_cert && - setup_data->pki_key.key.pem_buf.ca_cert_len > 0) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse(cacert, - (const unsigned char *)setup_data->pki_key.key.pem_buf.ca_cert, - setup_data->pki_key.key.pem_buf.ca_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - case COAP_PKI_KEY_ASN1: - if (setup_data->pki_key.key.asn1.public_cert && - setup_data->pki_key.key.asn1.public_cert_len && - setup_data->pki_key.key.asn1.private_key && - setup_data->pki_key.key.asn1.private_key_len > 0) { - - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - ret = mbedtls_x509_crt_parse(public_cert, - (const unsigned char *)setup_data->pki_key.key.asn1.public_cert, - setup_data->pki_key.key.asn1.public_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_pk_parse_key(private_key, - (const unsigned char *)setup_data->pki_key.key.asn1.private_key, - setup_data->pki_key.key.asn1.private_key_len, NULL, 0); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.asn1.ca_cert && - setup_data->pki_key.key.asn1.ca_cert_len > 0) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse(cacert, - (const unsigned char *)setup_data->pki_key.key.asn1.ca_cert, - setup_data->pki_key.key.asn1.ca_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - default: - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: Unknown key type %d\n", - setup_data->pki_key.key_type); - return -1; - } - - if (m_context->root_ca_file) { - ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - if (m_context->root_ca_path) { - ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_path); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - - /* - * Verify Peer. - * Need to do all checking, even if setup_data->verify_peer_cert is not set - */ - mbedtls_ssl_conf_verify(&m_env->conf, - cert_verify_callback_mbedtls, c_session); - - return 0; -} - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) -/* - * PKI SNI callback. - */ -static int -pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *uname, size_t name_len) -{ - unsigned int i; - coap_dtls_pki_t sni_setup_data; - coap_session_t *c_session = (coap_session_t *)p_info; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - - /* Is this a cached entry? */ - for (i = 0; i < m_context->pki_sni_count; i++) { - if (name_len == strlen(m_context->pki_sni_entry_list[i].sni) && - memcmp(uname, m_context->pki_sni_entry_list[i].sni, name_len) == 0) { - break; - } - } - if (i == m_context->pki_sni_count) { - /* - * New PKI SNI request - */ - char *name; - coap_dtls_key_t *new_entry; - - name = mbedtls_malloc(name_len+1); - if (name == NULL) { - ret = -1; - goto end; - } - - memcpy(name, uname, name_len); - name[name_len] = '\000'; - new_entry = - m_context->setup_data.validate_sni_call_back(name, - m_context->setup_data.sni_call_back_arg); - if (!new_entry) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->pki_sni_entry_list = - mbedtls_realloc(m_context->pki_sni_entry_list, - (i+1)*sizeof(pki_sni_entry)); - if (m_context->pki_sni_entry_list == NULL) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->pki_sni_entry_list[i].sni = name; - m_context->pki_sni_entry_list[i].pki_key = *new_entry; - sni_setup_data = m_context->setup_data; - sni_setup_data.pki_key = *new_entry; - if ((ret = setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert, - &m_context->pki_sni_entry_list[i].public_cert, - &m_context->pki_sni_entry_list[i].private_key, - m_env, - m_context, - c_session, - &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) { - ret = -1; - mbedtls_free(name); - goto end; - } - m_context->pki_sni_count++; - } - -end: - if (ret != -1) { - mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert, - NULL); - return mbedtls_ssl_set_hs_own_cert(ssl, - &m_context->pki_sni_entry_list[i].public_cert, - &m_context->pki_sni_entry_list[i].private_key); - } - return ret; -} -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_SERVER */ - -#ifdef PSK2_PR -/* - * PSK SNI callback. - */ -static int -psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *uname, size_t name_len) -{ - unsigned int i; - coap_dtls_spsk_t sni_setup_data; - coap_session_t *c_session = (coap_session_t *)p_info; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - - /* Is this a cached entry? */ - for (i = 0; i < m_context->psk_sni_count; i++) { - if (name_len == m_context->psk_sni_entry_list[i].sni.length && - memcmp(uname, m_context->psk_sni_entry_list[i].sni.s, name_len) == 0) { - break; - } - } - if (i == m_context->psk_sni_count) { - /* - * New PSK SNI request - */ - coap_str_const_t lsni; - uint8_t *name; - const coap_dtls_spsk_info_t *new_entry; - - name = mbedtls_malloc(name_len+1); - if (name == NULL) { - ret = -1; - goto end; - } - - memcpy(name, uname, name_len); - name[name_len] = '\000'; - - lsni.s = name; - lsni.length = name_len; - new_entry = - c_session->context->spsk_setup_data.validate_sni_call_back(&lsni, - c_session, - c_session->context->spsk_setup_data.sni_call_back_arg); - if (!new_entry) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->psk_sni_entry_list = - mbedtls_realloc(m_context->psk_sni_entry_list, - (i+1)*sizeof(psk_sni_entry)); - - if (m_context->psk_sni_entry_list == NULL) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->psk_sni_entry_list[i].sni.s = name; - m_context->psk_sni_entry_list[i].sni.length = name_len; - m_context->psk_sni_entry_list[i].psk_info = *new_entry; - sni_setup_data = c_session->context->spsk_setup_data; - sni_setup_data.psk_info = *new_entry; - m_context->psk_sni_count++; - } - -end: - if (ret != -1) { - coap_session_refresh_psk_hint(c_session, - &m_context->psk_sni_entry_list[i].psk_info.hint); - coap_session_refresh_psk_key(c_session, - &m_context->psk_sni_entry_list[i].psk_info.key); - return mbedtls_ssl_set_hs_psk(ssl, - m_context->psk_sni_entry_list[i].psk_info.key.s, - m_context->psk_sni_entry_list[i].psk_info.key.length); - } - return ret; -} -#endif /* PSK2_PR */ - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) - -static int setup_server_ssl_session(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) -{ - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - m_context->psk_pki_enabled |= IS_SERVER; - - mbedtls_ssl_cookie_init(&m_env->cookie_ctx); - if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, - MBEDTLS_SSL_IS_SERVER, - c_session->proto == COAP_PROTO_DTLS ? - MBEDTLS_SSL_TRANSPORT_DATAGRAM : - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x\n", -ret); - goto fail; - } - - mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_handshake_timeout(&m_env->conf, 1000, 60000); - - if (m_context->psk_pki_enabled & IS_PSK) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session); -#ifdef PSK2_PR - if (c_session->context->spsk_setup_data.validate_sni_call_back) { - mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session); - } -#endif /* PSK2_PR */ -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - - if (m_context->psk_pki_enabled & IS_PKI) { - ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, - &m_env->private_key, m_env, m_context, - c_session, &m_context->setup_data, - COAP_DTLS_ROLE_SERVER); - if (ret < 0) { - coap_log(LOG_ERR, "PKI setup failed\n"); - return ret; - } - if (m_context->setup_data.validate_sni_call_back) { - mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session); - } - } - - if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx, - mbedtls_ctr_drbg_random, - &m_env->ctr_drbg)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_cookie_setup: returned -0x%x\n", -ret); - goto fail; - } - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write, - mbedtls_ssl_cookie_check, - &m_env->cookie_ctx ); - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -fail: - return ret; -} -#endif /* !defined(ESPIDF_VERSION) || CONFIG_MBEDTLS_TLS_SERVER) */ - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) -#define MAX_CIPHERS 100 -static int psk_ciphers[MAX_CIPHERS]; -static int pki_ciphers[MAX_CIPHERS]; -static int processed_ciphers = 0; - -static void -set_ciphersuites(mbedtls_ssl_config *conf, int is_psk) -{ - if (!processed_ciphers) { - const int *list = mbedtls_ssl_list_ciphersuites(); - int *psk_list = psk_ciphers; - int *pki_list = pki_ciphers; - - while (*list) { - const mbedtls_ssl_ciphersuite_t *cur = - mbedtls_ssl_ciphersuite_from_id(*list); - - if (cur) { - if (mbedtls_ssl_ciphersuite_uses_psk(cur)) { - if (&psk_ciphers[MAX_CIPHERS] - psk_list > 1) { - *psk_list = *list; - psk_list++; - } - else { - static int done = 0; - - if (!done) { - done = 1; - coap_log(LOG_ERR, "psk_ciphers[MAX_CIPHERS] insufficient\n"); - } - } - } - else { - if (&pki_ciphers[MAX_CIPHERS] - pki_list > 1) { - *pki_list = *list; - pki_list++; - } - else { - static int done = 0; - - if (!done) { - done = 1; - coap_log(LOG_ERR, "pki_ciphers[MAX_CIPHERS] insufficient\n"); - } - } - } - } - list++; - } - /* zero terminate */ - *psk_list = 0; - *pki_list = 0; - processed_ciphers = 1; - } - mbedtls_ssl_conf_ciphersuites(conf, is_psk ? psk_ciphers : pki_ciphers); -} -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - -static int setup_client_ssl_session(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) -{ - int ret; - - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - - m_context->psk_pki_enabled |= IS_CLIENT; - - if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, - MBEDTLS_SSL_IS_CLIENT, - c_session->proto == COAP_PROTO_DTLS ? - MBEDTLS_SSL_TRANSPORT_DATAGRAM : - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x", -ret); - goto fail; - } - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_handshake_timeout(&m_env->conf, 1000, 60000); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - - mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); - - if (m_context->psk_pki_enabled & IS_PSK) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - uint8_t identity[64]; - size_t identity_len; - uint8_t psk_key[64]; - size_t psk_len; - size_t max_identity_len = sizeof(identity); - - coap_log(LOG_INFO, "Setting PSK key\n"); - psk_len = c_session->context->get_client_psk(c_session, - NULL, - 0, - identity, - &identity_len, - max_identity_len, - psk_key, - sizeof(psk_key)); - assert(identity_len < sizeof(identity)); - mbedtls_ssl_conf_psk(&m_env->conf, (const unsigned char *)psk_key, - psk_len, (const unsigned char *)identity, - identity_len); -#ifdef PSK2_PR - if (c_session->cpsk_setup_data.client_sni) { - mbedtls_ssl_set_hostname(&m_env->ssl, - c_session->cpsk_setup_data.client_sni); - } -#if 0 -/* Identity Hint currently not supported in MbedTLS */ - if (c_session->cpsk_setup_data.validate_ih_call_back) { - coap_log(LOG_DEBUG, - "CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n"); - mbedtls_ssl_conf_max_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_3); - } -#endif -#endif /* PSK2_PR */ - set_ciphersuites(&m_env->conf, 1); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } - else if ((m_context->psk_pki_enabled & IS_PKI) || - (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { - /* - * If neither PSK or PKI have been set up, use PKI basics. - * This works providing COAP_PKI_KEY_PEM has a value of 0. - */ - if ((m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { - mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); - } - ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, - &m_env->private_key, m_env, m_context, - c_session, &m_context->setup_data, - COAP_DTLS_ROLE_CLIENT); - if (ret < 0) { - coap_log(LOG_ERR, "PKI setup failed\n"); - return ret; - } -#if !defined(ESPIDF_VERSION) ||(defined(CONFIG_MBEDTLS_TLS_SERVER) && defined(CONFIG_MBEDTLS_SSL_ALPN)) - if (c_session->proto == COAP_PROTO_TLS) { - const char *alpn_list[2]; - - memset(alpn_list, 0, sizeof(alpn_list)); - alpn_list[0] = "coap"; - ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list); - if (ret != 0) { - coap_log(LOG_ERR, "ALPN setup failed %d)\n", ret); - } - } -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_TLS_SERVER && CONFIG_MBEDTLS_SSL_ALPN) */ - if (m_context->setup_data.client_sni) { - mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni); - } -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - set_ciphersuites(&m_env->conf, 0); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } - return 0; - -fail: - return ret; -} - -static void mbedtls_cleanup(coap_mbedtls_env_t *m_env) -{ - if (!m_env) { - return; - } - - mbedtls_x509_crt_free(&m_env->cacert); - mbedtls_x509_crt_free(&m_env->public_cert); - mbedtls_pk_free(&m_env->private_key); - mbedtls_entropy_free(&m_env->entropy); - mbedtls_ssl_config_free(&m_env->conf); - mbedtls_ctr_drbg_free(&m_env->ctr_drbg); - mbedtls_ssl_free(&m_env->ssl); - mbedtls_ssl_cookie_free(&m_env->cookie_ctx); -} - -static void -coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) { - if (m_env) { - mbedtls_cleanup(m_env); - free(m_env); - } -} - -/* - * return -1 failure - * 0 not completed - * 1 established - */ -static int do_mbedtls_handshake(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) { - int ret; - char buf[128]; - - ret = mbedtls_ssl_handshake(&m_env->ssl); - switch (ret) { - case 0: - m_env->established = 1; - coap_log(LOG_DEBUG, "* %s: MbedTLS established\n", - coap_session_str(c_session)); - ret = 1; - break; - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - errno = EAGAIN; - ret = 0; - break; - case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: - coap_log(LOG_INFO, "hello verification requested\n"); - ret = -1; - mbedtls_ssl_session_reset(&m_env->ssl); - break; - case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - ret = -1; - break; - default: - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "do_mbedtls_handshake: session establish " - "returned -0x%x: '%s'\n", - -ret, buf); - ret = -1; - break; - } - return ret; -} - -static void -mbedtls_debug_out(void *ctx UNUSED, int level, - const char *file, int line, const char *str) { - int log_level; - - switch (level) { - case 4: - case 3: - case 2: - log_level = LOG_DEBUG; - break; - case 1: - log_level = LOG_ERR; - break; - case 0: - default: - log_level = 0; - break; - } - coap_log(log_level, "%s:%04d: %s", file, line, str); -} - -static coap_mbedtls_env_t *coap_dtls_new_mbedtls_env(coap_session_t *c_session, - coap_dtls_role_t role) -{ - int ret = 0; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - - if (m_env) - return m_env; - - m_env = (coap_mbedtls_env_t *)calloc(1, sizeof(coap_mbedtls_env_t)); - if (!m_env) { - return NULL; - } - - mbedtls_ssl_init(&m_env->ssl); - mbedtls_ctr_drbg_init(&m_env->ctr_drbg); - mbedtls_ssl_config_init(&m_env->conf); - mbedtls_entropy_init(&m_env->entropy); - -#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) - mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL); -#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ - if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg, - mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) { - coap_log(LOG_ERR, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); - goto fail; - } - - if (role == COAP_DTLS_ROLE_CLIENT) { - if (setup_client_ssl_session(c_session, m_env) != 0) { - goto fail; - } -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) - } else if (role == COAP_DTLS_ROLE_SERVER) { - if (setup_server_ssl_session(c_session, m_env) != 0) { - goto fail; - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_SERVER */ - } else { - goto fail; - } - - if ((ret = mbedtls_ssl_setup(&m_env->ssl, &m_env->conf)) != 0) { - goto fail; - } - mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write, - coap_dgram_read, NULL); - mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer, - mbedtls_timing_set_delay, - mbedtls_timing_get_delay); - - mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout); - return m_env; - -fail: - if (m_env) { - free(m_env); - } - return NULL; -} - -int coap_dtls_is_supported(void) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - return 1; -#else /* ESPIDF_VERSION && !CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - coap_log(LOG_EMERG, - "libcoap not compiled for DTLS with MbedTLS" - " - update MbedTLS to include DTLS\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -} - -int coap_tls_is_supported(void) -{ - return 0; -} - -void *coap_dtls_new_context(struct coap_context_t *c_context) -{ - coap_mbedtls_context_t *m_context; - (void)c_context; - - m_context = (coap_mbedtls_context_t *)calloc(1, sizeof(coap_mbedtls_context_t)); - if (m_context) { - memset(m_context, 0, sizeof(coap_mbedtls_context_t)); - } - return m_context; -} - -#ifndef PSK2_PR -int coap_dtls_context_set_psk(struct coap_context_t *c_context, - const char *identity_hint UNUSED, - coap_dtls_role_t role UNUSED) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_PSK_MODES) || !defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK)) - coap_log(LOG_EMERG, "coap_dtls_context_set_psk:" - " libcoap not compiled with MBEDTLS_PSK_MODES and MBEDTLS_KEY_EXCHANGE_PSK" - " - update mbedTLS to include psk mode configs\n"); - return 0; -#endif /* ESPIDF_VERSION && (!CONFIG_MBEDTLS_PSK_MODES || !CONFIG_MBEDTLS_KEY_EXCHANGE_PSK) */ - -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_SERVER) - coap_log(LOG_EMERG, "coap_dtls_context_set_psk:" - " libcoap not compiled for Server Mode for MbedTLS" - " - update MbedTLS to include Server Mode\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_TLS_SERVER */ - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} -#else /* PSK2_PR */ -/* - * return 0 failed - * 1 passed - */ -int -coap_dtls_context_set_spsk(coap_context_t *c_context, - coap_dtls_spsk_t *setup_data -) { - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_SERVER) - coap_log(LOG_EMERG, "coap_dtls_context_set_spsk:" - " libcoap not compiled for Server Mode for MbedTLS" - " - update MbedTLS to include Server Mode\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_TLS_SERVER */ - if (!m_context || !setup_data) - return 0; - - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} - -/* - * return 0 failed - * 1 passed - */ -int -coap_dtls_context_set_cpsk(coap_context_t *c_context, - coap_dtls_cpsk_t *setup_data -) { - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - if (!m_context || !setup_data) - return 0; - - if (setup_data->validate_ih_call_back) { - coap_log(LOG_WARNING, - "CoAP Client with MbedTLS does not support Identity Hint selection\n"); - } - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} - -#endif /* PSK2_PR */ - -int coap_dtls_context_set_pki(struct coap_context_t *c_context, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role UNUSED) -{ -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_PSK_MODES) || !defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK)) - coap_log(LOG_EMERG, "coap_dtls_context_set_pki:" - " libcoap not compiled with MBEDTLS_PSK_MODES and MBEDTLS_KEY_EXCHANGE_PSK" - " - update mbedTLS to include psk mode configs\n"); - return 0; -#endif /* ESPIDF_VERSION && (!CONFIG_MBEDTLS_PSK_MODES || !CONFIG_MBEDTLS_KEY_EXCHANGE_PSK) */ - - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - m_context->setup_data = *setup_data; - m_context->psk_pki_enabled |= IS_PKI; - return 1; -} - -int coap_dtls_context_set_pki_root_cas(struct coap_context_t *c_context, - const char *ca_file, - const char *ca_path) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - if (!m_context) { - coap_log(LOG_WARNING, - "coap_context_set_pki_root_cas: (D)TLS environment " - "not set up\n"); - return 0; - } - - if (ca_file == NULL && ca_path == NULL) { - coap_log(LOG_WARNING, - "coap_context_set_pki_root_cas: ca_file and/or ca_path " - "not defined\n"); - return 0; - } - if (m_context->root_ca_file) { - free(m_context->root_ca_file); - m_context->root_ca_file = NULL; - } - - if (ca_file) { - m_context->root_ca_file = mbedtls_strdup(ca_file); - } - - if (m_context->root_ca_path) { - free(m_context->root_ca_path); - m_context->root_ca_path = NULL; - } - - if (ca_path) { - m_context->root_ca_path = mbedtls_strdup(ca_path); - } - return 1; -} - -int coap_dtls_context_check_keys_enabled(struct coap_context_t *c_context) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - return m_context->psk_pki_enabled ? 1 : 0; -} - -void coap_dtls_free_context(void *dtls_context) -{ - coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context; - unsigned int i; - - for (i = 0; i < m_context->pki_sni_count; i++) { - mbedtls_free(m_context->pki_sni_entry_list[i].sni); - - mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert); - - mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key); - - mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert); - } -#ifdef PSK2_PR - for (i = 0; i < m_context->psk_sni_count; i++) { - mbedtls_free(m_context->psk_sni_entry_list[i].sni.s); - } - if (m_context->psk_sni_entry_list) - mbedtls_free(m_context->pki_sni_entry_list); - -#endif /* PSK2_PR */ - - free(m_context); -} - -void *coap_dtls_new_client_session(coap_session_t *c_session) -{ -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_CLIENT) - (void)c_session; - coap_log(LOG_EMERG, "coap_dtls_new_client_session:" - " libcoap not compiled for Client Mode for MbedTLS" - " - update MbedTLS to include Client Mode\n"); - return NULL; -#else /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_CLIENT */ - coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session, - COAP_DTLS_ROLE_CLIENT); - int ret; - - if (m_env) { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == -1) { - coap_dtls_free_mbedtls_env(m_env); - return NULL; - } - } - return m_env; -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_CLIENT */ -} - -void *coap_dtls_new_server_session(coap_session_t *c_session) -{ - coap_mbedtls_env_t *m_env = - (coap_mbedtls_env_t *)c_session->tls; - if (m_env) { - m_env->seen_client_hello = 1; -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - } - return m_env; -} - -void coap_dtls_free_session(coap_session_t *c_session) -{ - if (c_session && c_session->context) { - coap_dtls_free_mbedtls_env(c_session->tls); - c_session->tls = NULL; - } - return; -} - -void coap_dtls_session_update_mtu(coap_session_t *c_session) -{ -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - coap_mbedtls_env_t *m_env = - (coap_mbedtls_env_t *)c_session->tls; - if (m_env) { - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -} - -int coap_dtls_send(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ - int ret; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - char buf[128]; - - assert(m_env != NULL); - - if (!m_env) { - return -1; - } - c_session->dtls_event = -1; - if (m_env->established) { - ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len); - if (ret <= 0) { - switch (ret) { - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - ret = 0; - break; - case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - ret = -1; - break; - default: - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "coap_dtls_send: " - "returned -0x%x: '%s'\n", - -ret, buf); - ret = -1; - break; - } - if (ret == -1) { - coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n"); - } - } - } else { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - return coap_dtls_send(c_session, data, data_len); - } - ret = -1; - } - - if (c_session->dtls_event >= 0) { - coap_handle_event(c_session->context, c_session->dtls_event, c_session); - if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || - c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - ret = -1; - } - } - return ret; -} - -int coap_dtls_is_context_timeout(void) -{ - return 0; -} - -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED) -{ - return 0; -} - -coap_tick_t coap_dtls_get_timeout(coap_session_t *c_session, coap_tick_t now) -{ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - int ret = mbedtls_timing_get_delay(&m_env->timer); - - switch (ret) { - case 0: - case 1: - /* int_ms has timed out, but not fin_ms */ - return now + 1; - case 2: - /* fin_ms has timed out - time for a retry */ - return now; - default: - break; - } - - return 0; -} - -void coap_dtls_handle_timeout(coap_session_t *c_session) -{ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - - assert(m_env != NULL); - if (((c_session->state == COAP_SESSION_STATE_HANDSHAKE) && - (++c_session->dtls_timeout_count > c_session->max_retransmit)) || - (do_mbedtls_handshake(c_session, m_env) < 0)) { - /* Too many retries */ - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - } - return; -} - -int coap_dtls_receive(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ - int ret = 1; - - c_session->dtls_event = -1; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - assert(m_env != NULL); - - coap_ssl_t *ssl_data = &m_env->coap_ssl_data; - if (ssl_data->pdu_len) { - coap_log(LOG_INFO, "** %s: Previous data not read %u bytes\n", - coap_session_str(c_session), ssl_data->pdu_len); - } - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - - if (m_env->established) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t b_static_mutex = COAP_MUTEX_INITIALIZER; - static uint8_t pdu[COAP_RXBUFFER_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - uint8_t pdu[COAP_RXBUFFER_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) { - coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, - c_session); - coap_session_connected(c_session); - } - - ret = mbedtls_ssl_read(&m_env->ssl, pdu, (int)sizeof(pdu)); - if (ret > 0) { - ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret); -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return ret; - } - else if (ret == 0 || ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - } - else if (ret != MBEDTLS_ERR_SSL_WANT_READ) { - char buf[128]; - - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "coap_dtls_receive: " - "returned -0x%x: '%s' (length %zd)\n", - -ret, buf, data_len); - } -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - ret = -1; - } - else { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - coap_session_connected(c_session); - } else { - if (ssl_data->pdu_len) { - /* Do the handshake again incase of internal timeout */ - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - coap_session_connected(c_session); - } else { - ret = -1; - } - } - ret = -1; - } - } - if (c_session->dtls_event >= 0) { - coap_handle_event(c_session->context, c_session->dtls_event, c_session); - if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || - c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - ret = -1; - } - } - return ret; -} - -int coap_dtls_hello(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) || !defined(CONFIG_MBEDTLS_TLS_SERVER)) - (void)c_session; - (void)data; - (void)data_len; - coap_log(LOG_EMERG, "coap_dtls_hello:" - " libcoap not compiled for DTLS or Server Mode for MbedTLS" - " - update MbedTLS to include DTLS and Server Mode\n"); - return -1; -#else /* !ESPIDF_VERSION) || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - coap_ssl_t *ssl_data = m_env ? &m_env->coap_ssl_data : NULL; - int ret; - - if (m_env) { - char *str = get_ip_addr(&c_session->remote_addr); - if (!str) { - return -1; - } - if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl, - (unsigned char *)str, strlen(str))) != 0) { - coap_log(LOG_ERR, - "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", - -ret); - free(str); - return -1; - } - free(str); - } - - if (!m_env) { - m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER); - if (m_env) { - c_session->tls = m_env; - ssl_data = &m_env->coap_ssl_data; - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - char *str = get_ip_addr(&c_session->remote_addr); - if (!str) { - return -1; - } - if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl, - (unsigned char *)str, strlen(str)) ) != 0) { - coap_log(LOG_ERR, - "mbedtls_ssl_set_client_transport_id() returned -0x%x\n", - -ret); - free(str); - return -1; - } - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 0 || m_env->seen_client_hello) { - m_env->seen_client_hello = 0; - free(str); - return 1; - } - free(str); - } - return 0; - } - - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 0 || m_env->seen_client_hello) { - /* The test for seen_client_hello gives the ability to setup a new - c_session to continue the do_mbedtls_handshake past the client hello - and safely allow updating of the m_env and separately - letting a new session cleanly start up. - */ - m_env->seen_client_hello = 0; - return 1; - } - return 0; -#endif /* !ESPIDF_VERSION) || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ -} - -unsigned int coap_dtls_get_overhead(coap_session_t *c_session UNUSED) -{ - return 13 + 8 + 8; -} - -void *coap_tls_new_client_session(coap_session_t *c_session UNUSED, int *connected UNUSED) -{ - return NULL; -} - -void *coap_tls_new_server_session(coap_session_t *c_session UNUSED, int *connected UNUSED) -{ - return NULL; -} - -void coap_tls_free_session( coap_session_t *c_session UNUSED) -{ - return; -} - -ssize_t coap_tls_write(coap_session_t *c_session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED - ) -{ - return 0; -} - -ssize_t coap_tls_read(coap_session_t *c_session UNUSED, - uint8_t *data UNUSED, - size_t data_len UNUSED - ) -{ - return 0; -} - -void coap_dtls_startup(void) -{ - return; -} - -static int keep_log_level = 0; - -void coap_dtls_set_log_level(int level) -{ -#if !defined(ESPIDF_VERSION) - int use_level; - /* - * MbedTLS debug levels filter - * 0 No debug - * 1 Error - * 2 State change - * 3 Informational - * 4 Verbose - */ - - if (level <= LOG_ERR) { - use_level = 1; - } - else { - use_level = (level >= LOG_DEBUG) ? level - LOG_DEBUG + 2 : 0; - } - mbedtls_debug_set_threshold(use_level); -#endif /* !ESPIDF_VERSION) */ - keep_log_level = level; - return; -} - -int coap_dtls_get_log_level(void) -{ - return keep_log_level; -} - -coap_tls_version_t * coap_get_tls_library_version(void) -{ - static coap_tls_version_t version; - version.version = mbedtls_version_get_number(); - version.built_version = MBEDTLS_VERSION_NUMBER; - version.type = COAP_TLS_LIBRARY_MBEDTLS; - return &version; -} - -#else /* !HAVE_MBEDTLS */ - -#ifdef __clang__ -/* Make compilers happy that do not like empty modules. As this function is - * never used, we ignore -Wunused-function at the end of compiling this file - */ -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -static inline void dummy(void) { -} - -#endif /* HAVE_MBEDTLS */ diff --git a/components/coap/port/coap_notls.c b/components/coap/port/coap_notls.c deleted file mode 100644 index aa2c27c688..0000000000 --- a/components/coap/port/coap_notls.c +++ /dev/null @@ -1,190 +0,0 @@ -/* -* coap_notls.c -- Stub Datagram Transport Layer Support for libcoap -* -* Copyright (C) 2016 Olaf Bergmann -* -* This file is part of the CoAP library libcoap. Please see README for terms -* of use. -*/ - -#include "coap_config.h" - -#if !defined(HAVE_LIBTINYDTLS) && !defined(HAVE_OPENSSL) && !defined(HAVE_LIBGNUTLS) && !defined(HAVE_MBEDTLS) - -#include "net.h" - -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else /* __GNUC__ */ -#define UNUSED -#endif /* __GNUC__ */ - -int -coap_dtls_is_supported(void) { - return 0; -} - -int -coap_tls_is_supported(void) { - return 0; -} - -coap_tls_version_t * -coap_get_tls_library_version(void) { - static coap_tls_version_t version; - version.version = 0; - version.type = COAP_TLS_LIBRARY_NOTLS; - return &version; -} - -int -coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, - coap_dtls_pki_t* setup_data UNUSED, - coap_dtls_role_t role UNUSED -) { - return 0; -} - -int -coap_dtls_context_set_pki_root_cas(struct coap_context_t *ctx UNUSED, - const char *ca_file UNUSED, - const char *ca_path UNUSED -) { - return 0; -} - -int -coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, - const char *hint UNUSED, - coap_dtls_role_t role UNUSED -) { - return 0; -} - -int -coap_dtls_context_check_keys_enabled(coap_context_t *ctx UNUSED) -{ - return 0; -} - -static int dtls_log_level = 0; - -void coap_dtls_startup(void) { -} - -void -coap_dtls_set_log_level(int level) { - dtls_log_level = level; -} - -int -coap_dtls_get_log_level(void) { - return dtls_log_level; -} - -void * -coap_dtls_new_context(struct coap_context_t *coap_context UNUSED) { - return NULL; -} - -void -coap_dtls_free_context(void *handle UNUSED) { -} - -void *coap_dtls_new_server_session(coap_session_t *session UNUSED) { - return NULL; -} - -void *coap_dtls_new_client_session(coap_session_t *session UNUSED) { - return NULL; -} - -void coap_dtls_free_session(coap_session_t *coap_session UNUSED) { -} - -void coap_dtls_session_update_mtu(coap_session_t *session UNUSED) { -} - -int -coap_dtls_send(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -int coap_dtls_is_context_timeout(void) { - return 1; -} - -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED) { - return 0; -} - -coap_tick_t -coap_dtls_get_timeout(coap_session_t *session UNUSED, coap_tick_t now UNUSED) { - return 0; -} - -void coap_dtls_handle_timeout(coap_session_t *session UNUSED) { -} - -int -coap_dtls_receive(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -int -coap_dtls_hello(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return 0; -} - -unsigned int coap_dtls_get_overhead(coap_session_t *session UNUSED) { - return 0; -} - -void *coap_tls_new_client_session(coap_session_t *session UNUSED, int *connected UNUSED) { - return NULL; -} - -void *coap_tls_new_server_session(coap_session_t *session UNUSED, int *connected UNUSED) { - return NULL; -} - -void coap_tls_free_session(coap_session_t *coap_session UNUSED) { -} - -ssize_t coap_tls_write(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -ssize_t coap_tls_read(coap_session_t *session UNUSED, - uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -#undef UNUSED - -#else /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS */ - -#ifdef __clang__ -/* Make compilers happy that do not like empty modules. As this function is - * never used, we ignore -Wunused-function at the end of compiling this file - */ -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -static inline void dummy(void) { -} - -#endif /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS */ diff --git a/components/coap/port/include/coap/coap_dtls.h b/components/coap/port/include/coap/coap_dtls.h deleted file mode 100644 index 2dd0e88d2e..0000000000 --- a/components/coap/port/include/coap/coap_dtls.h +++ /dev/null @@ -1,631 +0,0 @@ -/* - * coap_dtls.h -- (Datagram) Transport Layer Support for libcoap - * - * Copyright (C) 2016 Olaf Bergmann - * Copyright (C) 2017 Jean-Claude Michelou - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef COAP_DTLS_H_ -#define COAP_DTLS_H_ - -#include "coap_time.h" -#include "str.h" - -struct coap_context_t; -struct coap_session_t; -struct coap_dtls_pki_t; - -/** - * @defgroup dtls DTLS Support - * API functions for interfacing with DTLS libraries. - * @{ - */ - -/** - * Check whether DTLS is available. - * - * @return @c 1 if support for DTLS is enabled, or @c 0 otherwise. - */ -int coap_dtls_is_supported(void); - -/** - * Check whether TLS is available. - * - * @return @c 1 if support for TLS is enabled, or @c 0 otherwise. - */ -int coap_tls_is_supported(void); - -typedef enum coap_tls_library_t { - COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */ - COAP_TLS_LIBRARY_TINYDTLS, /**< Using TinyDTLS library */ - COAP_TLS_LIBRARY_OPENSSL, /**< Using OpenSSL library */ - COAP_TLS_LIBRARY_GNUTLS, /**< Using GnuTLS library */ - COAP_TLS_LIBRARY_MBEDTLS, /**< Using MbedTLS library */ -} coap_tls_library_t; - -/** - * The structure used for returning the underlying (D)TLS library - * information. - */ -typedef struct coap_tls_version_t { - uint64_t version; /**< (D)TLS runtime Library Version */ - coap_tls_library_t type; /**< Library type. One of COAP_TLS_LIBRARY_* */ - uint64_t built_version; /**< (D)TLS Built against Library Version */ -} coap_tls_version_t; - -/** - * Determine the type and version of the underlying (D)TLS library. - * - * @return The version and type of library libcoap was compiled against. - */ -coap_tls_version_t *coap_get_tls_library_version(void); - -/** - * Additional Security setup handler that can be set up by - * coap_context_set_pki(). - * Invoked when libcoap has done the validation checks at the TLS level, - * but the application needs to do some additional checks/changes/updates. - * - * @param tls_session The security session definition - e.g. SSL * for OpenSSL. - * NULL if server call-back. - * This will be dependent on the underlying TLS library - - * see coap_get_tls_library_version() - * @param setup_data A structure containing setup data originally passed into - * coap_context_set_pki() or coap_new_client_session_pki(). - * - * @return @c 1 if successful, else @c 0. - */ -typedef int (*coap_dtls_security_setup_t)(void* tls_session, - struct coap_dtls_pki_t *setup_data); - -/** - * CN Validation call-back that can be set up by coap_context_set_pki(). - * Invoked when libcoap has done the validation checks at the TLS level, - * but the application needs to check that the CN is allowed. - * CN is the SubjectAltName in the cert, if not present, then the leftmost - * Common Name (CN) component of the subject name. - * - * @param cn The determined CN from the certificate - * @param asn1_public_cert The ASN.1 DER encoded X.509 certificate - * @param asn1_length The ASN.1 length - * @param coap_session The CoAP session associated with the certificate update - * @param depth Depth in cert chain. If 0, then client cert, else a CA - * @param validated TLS layer can find no issues if 1 - * @param arg The same as was passed into coap_context_set_pki() - * in setup_data->cn_call_back_arg - * - * @return @c 1 if accepted, else @c 0 if to be rejected. - */ -typedef int (*coap_dtls_cn_callback_t)(const char *cn, - const uint8_t *asn1_public_cert, - size_t asn1_length, - struct coap_session_t *coap_session, - unsigned depth, - int validated, - void *arg); - -/** - * The enum used for determining the provided PKI ASN.1 (DER) Private Key - * formats. - */ -typedef enum coap_asn1_privatekey_type_t { - COAP_ASN1_PKEY_NONE, /**< NONE */ - COAP_ASN1_PKEY_RSA, /**< RSA type */ - COAP_ASN1_PKEY_RSA2, /**< RSA2 type */ - COAP_ASN1_PKEY_DSA, /**< DSA type */ - COAP_ASN1_PKEY_DSA1, /**< DSA1 type */ - COAP_ASN1_PKEY_DSA2, /**< DSA2 type */ - COAP_ASN1_PKEY_DSA3, /**< DSA3 type */ - COAP_ASN1_PKEY_DSA4, /**< DSA4 type */ - COAP_ASN1_PKEY_DH, /**< DH type */ - COAP_ASN1_PKEY_DHX, /**< DHX type */ - COAP_ASN1_PKEY_EC, /**< EC type */ - COAP_ASN1_PKEY_HMAC, /**< HMAC type */ - COAP_ASN1_PKEY_CMAC, /**< CMAC type */ - COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */ - COAP_ASN1_PKEY_HKDF /**< HKDF type */ -} coap_asn1_privatekey_type_t; - -/** - * The enum used for determining the PKI key formats. - */ -typedef enum coap_pki_key_t { - COAP_PKI_KEY_PEM = 0, /**< The PKI key type is PEM file */ - COAP_PKI_KEY_ASN1, /**< The PKI key type is ASN.1 (DER) */ - COAP_PKI_KEY_PEM_BUF, /**< The PKI key type is PEM buffer */ -} coap_pki_key_t; - -/** - * The structure that holds the PKI PEM definitions. - */ -typedef struct coap_pki_key_pem_t { - const char *ca_file; /**< File location of Common CA in PEM format */ - const char *public_cert; /**< File location of Public Cert in PEM format */ - const char *private_key; /**< File location of Private Key in PEM format */ -} coap_pki_key_pem_t; - -/** - * The structure that holds the PKI PEM buffer definitions. - */ -typedef struct coap_pki_key_pem_buf_t { - const uint8_t *ca_cert; /**< PEM buffer Common CA Cert */ - const uint8_t *public_cert; /**< PEM buffer Public Cert */ - const uint8_t *private_key; /**< PEM buffer Private Key */ - size_t ca_cert_len; /**< PEM buffer CA Cert length */ - size_t public_cert_len; /**< PEM buffer Public Cert length */ - size_t private_key_len; /**< PEM buffer Private Key length */ -} coap_pki_key_pem_buf_t; - -/** - * The structure that holds the PKI ASN.1 (DER) definitions. - */ -typedef struct coap_pki_key_asn1_t { - const uint8_t *ca_cert; /**< ASN1 (DER) Common CA Cert */ - const uint8_t *public_cert; /**< ASN1 (DER) Public Cert */ - const uint8_t *private_key; /**< ASN1 (DER) Private Key */ - size_t ca_cert_len; /**< ASN1 CA Cert length */ - size_t public_cert_len; /**< ASN1 Public Cert length */ - size_t private_key_len; /**< ASN1 Private Key length */ - coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */ -} coap_pki_key_asn1_t; - -/** - * The structure that holds the PKI key information. - */ -typedef struct coap_dtls_key_t { - coap_pki_key_t key_type; /**< key format type */ - union { - coap_pki_key_pem_t pem; /**< for PEM file keys */ - coap_pki_key_pem_buf_t pem_buf; /**< for PEM memory keys */ - coap_pki_key_asn1_t asn1; /**< for ASN.1 (DER) file keys */ - } key; -} coap_dtls_key_t; - -/** - * Server Name Indication (SNI) Validation call-back that can be set up by - * coap_context_set_pki(). - * Invoked if the SNI is not previously seen and prior to sending a certificate - * set back to the client so that the appropriate certificate set can be used - * based on the requesting SNI. - * - * @param sni The requested SNI - * @param arg The same as was passed into coap_context_set_pki() - * in setup_data->sni_call_back_arg - * - * @return New set of certificates to use, or @c NULL if SNI is to be rejected. - */ -typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni, - void* arg); - - -#define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */ - -/** - * The structure used for defining the PKI setup data to be used. - */ -typedef struct coap_dtls_pki_t { - uint8_t version; /** Set to 1 to support this version of the struct */ - - /* Options to enable different TLS functionality in libcoap */ - uint8_t verify_peer_cert; /**< 1 if peer cert is to be verified */ - uint8_t require_peer_cert; /**< 1 if peer cert is required */ - uint8_t allow_self_signed; /**< 1 if self signed certs are allowed */ - uint8_t allow_expired_certs; /**< 1 if expired certs are allowed */ - uint8_t cert_chain_validation; /**< 1 if to check cert_chain_verify_depth */ - uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */ - uint8_t check_cert_revocation; /**< 1 if revocation checks wanted */ - uint8_t allow_no_crl; /**< 1 ignore if CRL not there */ - uint8_t allow_expired_crl; /**< 1 if expired crl is allowed */ - uint8_t allow_bad_md_hash; /**< 1 if expired certs are allowed */ - uint8_t allow_short_rsa_length; /**< 1 if expired certs are allowed */ - uint8_t reserved[4]; /**< Reserved - must be set to 0 for - future compatibility */ - /* Size of 4 chosen to align to next - * parameter, so if newly defined option - * it can use one of the reserverd slot so - * no need to change - * COAP_DTLS_PKI_SETUP_VERSION and just - * decrement the reserved[] count. - */ - - /** CN check call-back function. - * If not NULL, is called when the TLS connection has passed the configured - * TLS options above for the application to verify if the CN is valid. - */ - coap_dtls_cn_callback_t validate_cn_call_back; - void *cn_call_back_arg; /**< Passed in to the CN call-back function */ - - /** SNI check call-back function. - * If not @p NULL, called if the SNI is not previously seen and prior to - * sending a certificate set back to the client so that the appropriate - * certificate set can be used based on the requesting SNI. - */ - coap_dtls_sni_callback_t validate_sni_call_back; - void *sni_call_back_arg; /**< Passed in to the sni call-back function */ - - /** Additional Security call-back handler that is invoked when libcoap has - * done the standerd, defined validation checks at the TLS level, - * If not @p NULL, called from within the TLS Client Hello connection - * setup. - */ - coap_dtls_security_setup_t additional_tls_setup_call_back; - - char* client_sni; /**< If not NULL, SNI to use in client TLS setup. - Owned by the client app and must remain valid - during the call to coap_new_client_session_pki() */ - - coap_dtls_key_t pki_key; /**< PKI key definition */ -} coap_dtls_pki_t; - -/** @} */ - -/** - * @defgroup dtls_internal DTLS Support (Internal) - * Internal API functions for interfacing with DTLS libraries. - * @{ - */ - -/** - * Creates a new DTLS context for the given @p coap_context. This function - * returns a pointer to a new DTLS context object or @c NULL on error. - * - * Internal function. - * - * @param coap_context The CoAP context where the DTLS object shall be used. - * - * @return A DTLS context object or @c NULL on error. - */ -void * -coap_dtls_new_context(struct coap_context_t *coap_context); - -typedef enum coap_dtls_role_t { - COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */ - COAP_DTLS_ROLE_SERVER /**< Internal function invoked for server */ -} coap_dtls_role_t; - -/** - * Set the DTLS context's default PSK information. - * This does the PSK specifics following coap_dtls_new_context(). - * If @p COAP_DTLS_ROLE_SERVER, then identity hint will also get set. - * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the - * TLS library's context (from which sessions are derived). - * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the - * TLS library's session. - * - * Internal function. - * - * @param coap_context The CoAP context. - * @param identity_hint The default PSK server identity hint sent to a client. - * Required parameter. If @p NULL, will be set to "". - * Empty string is a valid hint. - * This parameter is ignored if COAP_DTLS_ROLE_CLIENT - * @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_psk(struct coap_context_t *coap_context, - const char *identity_hint, - coap_dtls_role_t role); - -/** - * Set the DTLS context's default server PKI information. - * This does the PKI specifics following coap_dtls_new_context(). - * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the - * TLS library's context (from which sessions are derived). - * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the - * TLS library's session. - * - * Internal function. - * - * @param coap_context The CoAP context. - * @param setup_data Setup information defining how PKI is to be setup. - * Required parameter. If @p NULL, PKI will not be - * set up. - * @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_pki(struct coap_context_t *coap_context, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role); - -/** - * Set the dtls context's default Root CA information for a client or server. - * - * Internal function. - * - * @param coap_context The current coap_context_t object. - * @param ca_file If not @p NULL, is the full path name of a PEM encoded - * file containing all the Root CAs to be used. - * @param ca_dir If not @p NULL, points to a directory containing PEM - * encoded files containing all the Root CAs to be used. - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_pki_root_cas(struct coap_context_t *coap_context, - const char *ca_file, - const char *ca_dir); - -/** - * Check whether one of the coap_dtls_context_set_{psk|pki}() functions have - * been called. - * - * Internal function. - * - * @param coap_context The current coap_context_t object. - * - * @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0. - */ - -int coap_dtls_context_check_keys_enabled(struct coap_context_t *coap_context); - -/** - * Releases the storage allocated for @p dtls_context. - * - * Internal function. - * - * @param dtls_context The DTLS context as returned by coap_dtls_new_context(). - */ -void coap_dtls_free_context(void *dtls_context); - -/** - * Create a new client-side session. This should send a HELLO to the server. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. -*/ -void *coap_dtls_new_client_session(struct coap_session_t *coap_session); - -/** - * Create a new DTLS server-side session. - * Called after coap_dtls_hello() has returned @c 1, signalling that a validated - * HELLO was received from a client. - * This should send a HELLO to the server. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the DTLS session. - */ -void *coap_dtls_new_server_session(struct coap_session_t *coap_session); - -/** - * Terminates the DTLS session (may send an ALERT if necessary) then frees the - * underlying TLS library object containing security parameters for the session. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_free_session(struct coap_session_t *coap_session); - -/** - * Notify of a change in the CoAP session's MTU, for example after - * a PMTU update. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_session_update_mtu(struct coap_session_t *coap_session); - -/** - * Send data to a DTLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data pointer to data. - * @param data_len Number of bytes to send. - * - * @return @c 0 if this would be blocking, @c -1 if there is an error or the - * number of cleartext bytes sent. - */ -int coap_dtls_send(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Check if timeout is handled per CoAP session or per CoAP context. - * - * Internal function. - * - * @return @c 1 of timeout and retransmit is per context, @c 0 if it is - * per session. - */ -int coap_dtls_is_context_timeout(void); - -/** - * Do all pending retransmits and get next timeout - * - * Internal function. - * - * @param dtls_context The DTLS context. - * - * @return @c 0 if no event is pending or date of the next retransmit. - */ -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context); - -/** - * Get next timeout for this session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param now The current time in ticks. - * - * @return @c 0 If no event is pending or ticks time of the next retransmit. - */ -coap_tick_t coap_dtls_get_timeout(struct coap_session_t *coap_session, - coap_tick_t now); - -/** - * Handle a DTLS timeout expiration. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_handle_timeout(struct coap_session_t *coap_session); - -/** - * Handling incoming data from a DTLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Encrypted datagram. - * @param data_len Encrypted datagram size. - * - * @return Result of coap_handle_dgram on the decrypted CoAP PDU - * or @c -1 for error. - */ -int coap_dtls_receive(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Handling client HELLO messages from a new candiate peer. - * Note that session->tls is empty. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Encrypted datagram. - * @param data_len Encrypted datagram size. - * - * @return @c 0 if a cookie verification message has been sent, @c 1 if the - * HELLO contains a valid cookie and a server session should be created, - * @c -1 if the message is invalid. - */ -int coap_dtls_hello(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Get DTLS overhead over cleartext PDUs. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Maximum number of bytes added by DTLS layer. - */ -unsigned int coap_dtls_get_overhead(struct coap_session_t *coap_session); - -/** - * Create a new TLS client-side session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param connected Updated with whether the connection is connected yet or not. - * @c 0 is not connected, @c 1 is connected. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. -*/ -void *coap_tls_new_client_session(struct coap_session_t *coap_session, int *connected); - -/** - * Create a TLS new server-side session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param connected Updated with whether the connection is connected yet or not. - * @c 0 is not connected, @c 1 is connected. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. - */ -void *coap_tls_new_server_session(struct coap_session_t *coap_session, int *connected); - -/** - * Terminates the TLS session (may send an ALERT if necessary) then frees the - * underlying TLS library object containing security parameters for the session. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_tls_free_session( struct coap_session_t *coap_session ); - -/** - * Send data to a TLS peer, with implicit flush. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Pointer to data. - * @param data_len Number of bytes to send. - * - * @return @c 0 if this should be retried, @c -1 if there is an error - * or the number of cleartext bytes sent. - */ -ssize_t coap_tls_write(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len - ); - -/** - * Read some data from a TLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Pointer to data. - * @param data_len Maximum number of bytes to read. - * - * @return @c 0 if this should be retried, @c -1 if there is an error - * or the number of cleartext bytes read. - */ -ssize_t coap_tls_read(struct coap_session_t *coap_session, - uint8_t *data, - size_t data_len - ); - -/** - * Initialize the underlying (D)TLS Library layer. - * - * Internal function. - * - */ -void coap_dtls_startup(void); - -/** @} */ - -/** - * @ingroup logging - * Sets the (D)TLS logging level to the specified @p level. - * Note: coap_log_level() will influence output if at a specified level. - * - * @param level The logging level to use - LOG_* - */ -void coap_dtls_set_log_level(int level); - -/** - * @ingroup logging - * Get the current (D)TLS logging. - * - * @return The current log level (one of LOG_*). - */ -int coap_dtls_get_log_level(void); - - -#endif /* COAP_DTLS_H */ diff --git a/components/coap/port/include/coap/coap.h b/components/coap/port/include/coap3/coap.h similarity index 53% rename from components/coap/port/include/coap/coap.h rename to components/coap/port/include/coap3/coap.h index f048ca8571..c69d2734b3 100644 --- a/components/coap/port/include/coap/coap.h +++ b/components/coap/port/include/coap3/coap.h @@ -21,27 +21,28 @@ extern "C" { #endif -#include "libcoap.h" +#include "coap3/libcoap.h" -#include "address.h" -#include "async.h" -#include "bits.h" -#include "block.h" -#include "coap_dtls.h" -#include "coap_event.h" -#include "coap_io.h" -#include "coap_time.h" -#include "coap_debug.h" -#include "encode.h" -#include "mem.h" -#include "net.h" -#include "option.h" -#include "pdu.h" -#include "prng.h" -#include "resource.h" -#include "str.h" -#include "subscribe.h" -#include "uri.h" +#include "coap3/coap_forward_decls.h" +#include "coap3/address.h" +#include "coap3/async.h" +#include "coap3/block.h" +#include "coap3/coap_cache.h" +#include "coap3/coap_dtls.h" +#include "coap3/coap_event.h" +#include "coap3/coap_io.h" +#include "coap3/coap_time.h" +#include "coap3/coap_debug.h" +#include "coap3/encode.h" +#include "coap3/mem.h" +#include "coap3/net.h" +#include "coap3/option.h" +#include "coap3/pdu.h" +#include "coap3/coap_prng.h" +#include "coap3/resource.h" +#include "coap3/str.h" +#include "coap3/subscribe.h" +#include "coap3/uri.h" #ifdef __cplusplus } diff --git a/components/coap/port/include/coap_config_posix.h b/components/coap/port/include/coap_config_posix.h index 3f6b7c605f..b24335ad15 100644 --- a/components/coap/port/include/coap_config_posix.h +++ b/components/coap/port/include/coap_config_posix.h @@ -30,6 +30,7 @@ #define HAVE_NETDB_H #define HAVE_NETINET_IN_H #define HAVE_STRUCT_CMSGHDR +#define COAP_DISABLE_TCP 0 #define ipi_spec_dst ipi_addr struct in6_pktinfo { @@ -53,8 +54,6 @@ struct in6_pktinfo { #define COAP_CONSTRAINED_STACK 1 #define ESPIDF_VERSION -#define _POSIX_TIMERS 1 - #define gai_strerror(x) "gai_strerror() not supported" #endif /* WITH_POSIX */ diff --git a/examples/protocols/coap_client/README.md b/examples/protocols/coap_client/README.md index f2f024585e..1db75c611f 100644 --- a/examples/protocols/coap_client/README.md +++ b/examples/protocols/coap_client/README.md @@ -43,6 +43,8 @@ Component config ---> CoAP Configuration ---> * Set encryption method definition, PSK (default) or PKI * Enable CoAP debugging if required + High resolution timer (esp_timer) ---> + * Hardware timer to use for esp_timer - change if required (FRC2 for QEMU) ### Build and Flash @@ -59,20 +61,24 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output Prerequisite: we startup a CoAP server on coap server example, -or use the default of coaps://californium.eclipseprojects.io. +or use the default of coap://californium.eclipseprojects.io. and you could receive data from CoAP server if succeed, such as the following log: ``` ... -I (5104) esp_netif_handlers: example_connect: sta ip: 192.168.0.103, mask: 255.255.255.0, gw: 192.168.0.1 -I (5104) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.0.103 -I (5604) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:32ae:a4ff:fec5:3234, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (5604) example_connect: Connected to example_connect: sta -I (5614) example_connect: - IPv4 address: 192.168.0.103 -I (5614) example_connect: - IPv6 address: fe80:0000:0000:0000:32ae:a4ff:fec5:3234, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (6004) CoAP_client: DNS lookup succeeded. IP=35.185.40.182 +I (332) wifi: mode : sta (30:ae:a4:04:1b:7c) +I (1672) wifi: n:11 0, o:1 0, ap:255 255, sta:11 0, prof:1 +I (1672) wifi: state: init -> auth (b0) +I (1682) wifi: state: auth -> assoc (0) +I (1692) wifi: state: assoc -> run (10) +I (1692) wifi: connected with huawei_cw, channel 11 +I (1692) wifi: pm start, type: 1 + +I (2582) event: sta ip: 192.168.3.89, mask: 255.255.255.0, gw: 192.168.3.1 +I (2582) CoAP_client: Connected to AP +I (2582) CoAP_client: DNS lookup succeeded. IP=35.185.40.182 Received: **************************************************************** CoAP RFC 7252 Cf 3.0.0-SNAPSHOT @@ -86,7 +92,11 @@ published under EPL+EDL: http://www.eclipse.org/californium/ ``` ## libcoap Documentation -This can be found at https://libcoap.net/doc/reference/4.2.0/ +This can be found at [libcoap Documentation](https://libcoap.net/documentation.html). +The current API is 4.3.0. + +## libcoap Specific Issues +These can be raised at [libcoap Issues](https://github.com/obgm/libcoap/issues). ## Troubleshooting * Please make sure Target Url includes valid `host`, optional `port`, diff --git a/examples/protocols/coap_client/main/certs/coap_ca.pem b/examples/protocols/coap_client/main/certs/coap_ca.pem index 1bdf23d94b..07900ec471 100644 --- a/examples/protocols/coap_client/main/certs/coap_ca.pem +++ b/examples/protocols/coap_client/main/certs/coap_ca.pem @@ -1,23 +1,27 @@ -----BEGIN CERTIFICATE----- -MIID3DCCA0WgAwIBAgIJAMnlgL1czsmjMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD -VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT -BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs -ZS5jb20xJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X -DTE3MDYwNzA4MDY0OVoXDTI3MDYwNTA4MDY0OVowgZMxCzAJBgNVBAYTAkZSMQ8w -DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh -bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG -A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBALpWR23fn/TmHxsXsHdrydzPSd17fZkc71WsaicgQR66 -1tIVYb22UWGfj9KPM8THMsV74ew4ZkaQ39qvU0iuQIRrKARFHFok+vbaecgWMeWe -vGIqdnmyB9gJYaFOKgtSkfXsu2ddsqdvLYwcDbczrq8X9yEXpN6mnxXeCcPG4F0p -AgMBAAGjggE0MIIBMDAdBgNVHQ4EFgQUgigpdAUpONoDq0pQ3yfxrslCSpcwgcgG -A1UdIwSBwDCBvYAUgigpdAUpONoDq0pQ3yfxrslCSpehgZmkgZYwgZMxCzAJBgNV -BAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMG -A1UECgwMRXhhbXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxl -LmNvbTEmMCQGA1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDJ -5YC9XM7JozAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93 -d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADgYEA -euxOBPInSJRKAIseMxPmAabtAqKNslZSmpG4He3lkKt+HM3jfznUt3psmD7j1hFW -S4l7KXzzajvaGYybDq5N9MqrDjhGn3VXZqOLMUNDL7OQq96TzgqsTBT1dmVSbNlt -PQgiAeKAk3tmH4lRRi9MTBSyJ6I92JYcS5H6Bs4ZwCc= +MIICDzCCAbSgAwIBAgIIAbOUoVFDz/QwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMzWhcNMjExMTExMTAzMDMzWjBaMQ4wDAYDVQQDEwVjZi1jYTEUMBIGA1UECxML +Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh +d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7/3EXOZn +GZXNEIj7LuQAMZ8lfRYSCnpME1TBjKjZPtVeztLtGWgkkLvIX11pAJcBh51cpi7Z +fQtGpVE9CLOh6aNgMF4wHQYDVR0OBBYEFEvf57UcJhYYkx14twkeitd691fVMAsG +A1UdDwQEAwIBBjAPBgNVHRMECDAGAQH/AgEBMB8GA1UdIwQYMBaAFAsi3KbVERiK +JzFCfC/GVrYksGzEMAwGCCqGSM49BAMCBQADRwAwRAIgc5nVF/5Pip0XB17IZXqi +V84FXanWdn9Z0SiPdpOgvZMCIH13vL9tkCCjPN3tg3TYRY/bzyGohFGBcTrrEtUr +rVIm +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB4DCCAYWgAwIBAgIIQR8ro8AQ02AwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMyWhcNMjExMTExMTAzMDMyWjBcMRAwDgYDVQQDEwdjZi1yb290MRQwEgYDVQQL +EwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBzZSBJb1QxDzANBgNVBAcTBk90 +dGF3YTELMAkGA1UEBhMCQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZ1BRM +T1//Fzh9sneRZNwS4kgCxN1PvgwT271qCpYqyxnjLEa38AP1IAanhpiD/OkVc0Zd +7NgDPCw7n94EULMyoy8wLTAdBgNVHQ4EFgQUCyLcptURGIonMUJ8L8ZWtiSwbMQw +DAYDVR0TBAUwAwEB/zAMBggqhkjOPQQDAgUAA0cAMEQCIAdLEgcUWdpAl9jwdJiz +/cHW7/CBIWEvqiQfzE+XLyLOAiAvuxSdOtSDjh2aC5qEjUCH8CSKCxWB74j23tmp +aqPH4A== -----END CERTIFICATE----- diff --git a/examples/protocols/coap_client/main/certs/coap_client.crt b/examples/protocols/coap_client/main/certs/coap_client.crt index 12dbfc8f55..e774231cb3 100644 --- a/examples/protocols/coap_client/main/certs/coap_client.crt +++ b/examples/protocols/coap_client/main/certs/coap_client.crt @@ -1,70 +1,13 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 48 (0x30) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FR, ST=Radius, L=Somewhere, O=Example Inc./emailAddress=admin@example.com, CN=Example Certificate Authority - Validity - Not Before: Jun 7 08:06:49 2017 GMT - Not After : Jun 5 08:06:49 2027 GMT - Subject: C=FR, ST=Radius, O=Example Inc., CN=user@example.com/emailAddress=user@example.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:d2:f6:be:72:a5:ab:2e:56:0c:dd:f2:3b:2c:7c: - e0:5d:05:40:af:0c:8c:f3:82:0c:d0:18:34:b4:e3: - 7d:5f:8d:0a:3e:aa:79:02:f9:96:ad:10:00:ec:51: - e9:dc:3f:fb:ea:b0:57:eb:48:c7:ca:ef:e8:05:ab: - ee:3f:66:ba:5c:9e:7f:40:85:9f:25:a0:e0:e3:7c: - cf:b6:e6:31:f5:fd:24:03:c8:f4:fb:d8:a4:f3:92: - 29:05:aa:55:43:80:f7:3e:13:10:43:3a:89:24:be: - d8:01:86:d1:69:73:44:7d:f8:b9:46:2b:6b:51:d0: - 11:31:4b:06:ae:9f:45:fa:12:17:0c:ef:6a:fa:d0: - f7:36:46:eb:2e:db:4e:20:46:01:33:ac:b1:f7:4a: - e6:18:3d:53:22:dc:e8:4a:12:78:11:2f:e4:3b:92: - bd:d7:07:5a:c9:81:5d:48:58:c8:0f:9b:e9:a4:0f: - bb:89:b1:ad:38:07:6f:93:d0:a6:12:56:f9:07:48: - d2:23:2f:a3:a9:93:b0:11:0a:27:4c:48:0a:8d:70: - 41:68:76:7a:dd:bc:54:c3:42:33:b0:7b:f6:ae:1f: - e7:95:5e:11:ca:f2:b4:4b:5c:ba:47:64:f0:f3:d7: - 87:95:7f:93:06:a1:72:c9:81:12:a5:b7:8f:9d:7e: - d1:ef - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Extended Key Usage: - TLS Web Client Authentication - X509v3 CRL Distribution Points: - - Full Name: - URI:http://www.example.com/example_ca.crl - - Signature Algorithm: sha1WithRSAEncryption - 2d:02:bc:7b:88:b8:5c:e1:07:b8:bb:ba:b2:f3:98:14:8f:cb: - b0:21:13:b5:e5:6f:05:4f:92:fa:ac:c0:53:a7:b0:cd:7e:ba: - 87:36:85:25:d7:41:c5:29:84:22:74:af:bf:3e:34:36:d5:24: - 7a:81:e2:1b:54:52:85:6f:76:de:dc:63:98:45:fc:2c:31:fa: - 22:a4:72:3a:8d:d4:6a:2e:de:33:10:41:eb:94:1d:e3:59:cd: - b2:be:ab:f0:b6:20:86:9c:b8:46:ee:c5:64:ba:b6:6c:cc:53: - 44:7a:80:12:77:7c:e7:51:67:91:32:2f:88:9d:93:a8:ef:d6: - cd:de -----BEGIN CERTIFICATE----- -MIIDTjCCAregAwIBAgIBMDANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCRlIx -DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRUwEwYDVQQKDAxF -eGFtcGxlIEluYy4xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMSYw -JAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA2MDcw -ODA2NDlaFw0yNzA2MDUwODA2NDlaMHExCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZS -YWRpdXMxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEZMBcGA1UEAwwQdXNlckBleGFt -cGxlLmNvbTEfMB0GCSqGSIb3DQEJARYQdXNlckBleGFtcGxlLmNvbTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBANL2vnKlqy5WDN3yOyx84F0FQK8MjPOC -DNAYNLTjfV+NCj6qeQL5lq0QAOxR6dw/++qwV+tIx8rv6AWr7j9mulyef0CFnyWg -4ON8z7bmMfX9JAPI9PvYpPOSKQWqVUOA9z4TEEM6iSS+2AGG0WlzRH34uUYra1HQ -ETFLBq6fRfoSFwzvavrQ9zZG6y7bTiBGATOssfdK5hg9UyLc6EoSeBEv5DuSvdcH -WsmBXUhYyA+b6aQPu4mxrTgHb5PQphJW+QdI0iMvo6mTsBEKJ0xICo1wQWh2et28 -VMNCM7B79q4f55VeEcrytEtcukdk8PPXh5V/kwahcsmBEqW3j51+0e8CAwEAAaNP -ME0wEwYDVR0lBAwwCgYIKwYBBQUHAwIwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDov -L3d3dy5leGFtcGxlLmNvbS9leGFtcGxlX2NhLmNybDANBgkqhkiG9w0BAQUFAAOB -gQAtArx7iLhc4Qe4u7qy85gUj8uwIRO15W8FT5L6rMBTp7DNfrqHNoUl10HFKYQi -dK+/PjQ21SR6geIbVFKFb3be3GOYRfwsMfoipHI6jdRqLt4zEEHrlB3jWc2yvqvw -tiCGnLhG7sVkurZszFNEeoASd3znUWeRMi+InZOo79bN3g== +MIICAzCCAaagAwIBAgIJAJnE6sMNQNAoMAwGCCqGSM49BAMCBQAwWjEOMAwGA1UE +AxMFY2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNl +IElvVDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMDExMTExMDMw +NDVaFw0yMTExMTExMDMwNDVaMF4xEjAQBgNVBAMTCWNmLWNsaWVudDEUMBIGA1UE +CxMLQ2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZP +dHRhd2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFGno +107kFgJ4AvABQviE9hTJlEeB4wfS3L58Q5J8srWxSunEgniIbfr0p8Shw+C1XAcz +FxJrn8SjFCVqOKjrrqNPME0wHQYDVR0OBBYEFIwAAdmpYSm184Jx1ycc3BQGybhN +MAsGA1UdDwQEAwIHgDAfBgNVHSMEGDAWgBRL3+e1HCYWGJMdeLcJHorXevdX1TAM +BggqhkjOPQQDAgUAA0kAMEYCIQC+w/hm8TfTCqUV6midHAvmNxJN7MfMcpAiyi4e +6NBrPAIhAPeMUrnOlykTMcpYMRZs4YnyM6ihgU/F8UjknhDpkywm -----END CERTIFICATE----- diff --git a/examples/protocols/coap_client/main/certs/coap_client.key b/examples/protocols/coap_client/main/certs/coap_client.key index 99936e25b7..dca2e92167 100644 --- a/examples/protocols/coap_client/main/certs/coap_client.key +++ b/examples/protocols/coap_client/main/certs/coap_client.key @@ -1,27 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA0va+cqWrLlYM3fI7LHzgXQVArwyM84IM0Bg0tON9X40KPqp5 -AvmWrRAA7FHp3D/76rBX60jHyu/oBavuP2a6XJ5/QIWfJaDg43zPtuYx9f0kA8j0 -+9ik85IpBapVQ4D3PhMQQzqJJL7YAYbRaXNEffi5RitrUdARMUsGrp9F+hIXDO9q -+tD3NkbrLttOIEYBM6yx90rmGD1TItzoShJ4ES/kO5K91wdayYFdSFjID5vppA+7 -ibGtOAdvk9CmElb5B0jSIy+jqZOwEQonTEgKjXBBaHZ63bxUw0IzsHv2rh/nlV4R -yvK0S1y6R2Tw89eHlX+TBqFyyYESpbePnX7R7wIDAQABAoIBAQC5PncO3tBIeMEF -pu007FZq9/DLhP7D2B9+HrMxX0y4uXUUf8aQyS74ukPFP0xV3U1M0BnzfU4KscyQ -Jl+nBoKAT6C3vF15wiGXQAJ4vPuD4Ate03fjKWH2ixJAakhCZR01QbIXBnBkdrvf -401BBjlPUDcIGZo8FbLzEMlGTo84vE9v3Qmkbi+PzPCh2YC+NDmsOcIW1zpmwyYC -ZYCpoWgl4++kqXXn0NGhuaOgB0JLsJOBpx/hOOjBU/wXCKaXZ1vchYqfbvvx2gf2 -WX4P0CiTH1z7MEAHanaZkcnNyxV/oF1EIMY5p0vDDzgrKtppvPOqspjydje03+CE -t0wKGPi5AoGBAPAG2Y4efgwLcoWdPjKZtsHLhDhLJnvxkqnNkzdPnLZojNi8pKkV -/Yu++pPemJZZa4YAp+OnqyEfhcha+HYqKMwRC8t3YrEVOlRQTfW/OoSrp059JIRV -jTvq/u7DdYGJRRgMLUJiEI+7xj1WbTc2EceJAgn0qfKvbvBtVJP0LH1TAoGBAOEA -xZB7SwyX+zDGRTugqMYg+sYobbQHJ7utLyoX+ckeG+sPEjEYLpQQfshET/gwF8ZK -4aILkACx/tna799xCjQdmyyc338NO9WULlY1xF+65WfeaxrtTAsqVikX3p19McRI -ijX8k7Msy3gYWJXev3MCtPT2+g68IgbL/W2wY+l1AoGAT7xGy0Jv5vpqid5pig+s -OYatHrJAT445hXUIQaiNy77Bg0JvhMgMWT8RKMwabl+4K2TOYP8TB0bcf2lQ/pgU -w22qOGYpf+AoZ1fh/hAPlYEcbCOAXQG6kDwJgjGmOGjsbgelhVbkX4smWLv8PgoV -L+7goYQIbNlAhlgbb6b+nIcCgYBB7Zr2Cdpkt0en9ACnRx0M6O7yDziNzqbqzAUM -3XeYYZUmnATlk8NaKTcs8S9JdrYQqTJR6/dm7MDTDt7IZvPpb19fhBvMu5DztPaa -1ihTMI01kStq+WsVvnL+mXrmRJ/HdsXgqcCReKep6eBTEbChP4LMYG3G0YNa4HzC -njO4XQKBgQDRnbqqg2CNTnS94BN2D3uzzELtwsIG6aVCtl09ZsLnGaBKVVDtP6BI -j2hGD7xw4g5JeSPIJU5J03nALTY3hz1JyI7AJCX7+JRtUTX2A8C4mlbeul7ilGaU -A7MFT8GqhjYYa84GzNcA1mK8ynlixpL8+yzTT/8lWInWRBa69SkktA== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCBgNuyqKuRW0RxU1DVs +aEpBPtVRVLRZYq6hZRzvZ6igBw== +-----END PRIVATE KEY----- diff --git a/examples/protocols/coap_client/main/coap_client_example_main.c b/examples/protocols/coap_client/main/coap_client_example_main.c index f44112e916..1a59e37b27 100644 --- a/examples/protocols/coap_client/main/coap_client_example_main.c +++ b/examples/protocols/coap_client/main/coap_client_example_main.c @@ -31,17 +31,12 @@ #include "protocol_examples_common.h" -#if 1 -/* Needed until coap_dtls.h becomes a part of libcoap proper */ -#include "libcoap.h" -#include "coap_dtls.h" -#endif -#include "coap.h" +#include "coap3/coap.h" -#define COAP_DEFAULT_TIME_SEC 5 +#define COAP_DEFAULT_TIME_SEC 60 /* The examples use simple Pre-Shared-Key configuration that you can set via - 'make menuconfig'. + 'idf.py menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_COAP_PSK_KEY "some-agreed-preshared-key" @@ -54,7 +49,7 @@ #define EXAMPLE_COAP_PSK_IDENTITY CONFIG_EXAMPLE_COAP_PSK_IDENTITY /* The examples use uri Logging Level that - you can set via 'make menuconfig'. + you can set via 'idf.py menuconfig'. If you'd rather not, just change the below entry to a value that is between 0 and 7 with @@ -62,11 +57,11 @@ */ #define EXAMPLE_COAP_LOG_DEFAULT_LEVEL CONFIG_COAP_LOG_DEFAULT_LEVEL -/* The examples use uri "coap://californium.eclipse.org" that +/* The examples use uri "coap://californium.eclipseprojects.io" that you can set via the project configuration (idf.py menuconfig) If you'd rather not, just change the below entries to strings with - the config you want - ie #define COAP_DEFAULT_DEMO_URI "coaps://californium.eclipse.org" + the config you want - ie #define COAP_DEFAULT_DEMO_URI "coaps://californium.eclipseprojects.io" */ #define COAP_DEFAULT_DEMO_URI CONFIG_EXAMPLE_TARGET_DOMAIN_URI @@ -81,8 +76,9 @@ static int wait_ms; Client cert, taken from coap_client.crt Client key, taken from coap_client.key - The PEM, CRT and KEY file are examples taken from the wpa2 enterprise - example. + The PEM, CRT and KEY file are examples taken from + https://github.com/eclipse/californium/tree/master/demo-certs/src/main/resources + as the Certificate test (by default) is against the californium server. To embed it in the app binary, the PEM, CRT and KEY file is named in the component.mk COMPONENT_EMBED_TXTFILES variable. @@ -95,84 +91,39 @@ extern uint8_t client_key_start[] asm("_binary_coap_client_key_start"); extern uint8_t client_key_end[] asm("_binary_coap_client_key_end"); #endif /* CONFIG_COAP_MBEDTLS_PKI */ -static void message_handler(coap_context_t *ctx, coap_session_t *session, - coap_pdu_t *sent, coap_pdu_t *received, - const coap_tid_t id) +static coap_response_t +message_handler(coap_session_t *session, + const coap_pdu_t *sent, + const coap_pdu_t *received, + const coap_mid_t mid) { - unsigned char *data = NULL; + const unsigned char *data = NULL; size_t data_len; - coap_pdu_t *pdu = NULL; - coap_opt_t *block_opt; - coap_opt_iterator_t opt_iter; - unsigned char buf[4]; - coap_optlist_t *option; - coap_tid_t tid; + size_t offset; + size_t total; + coap_pdu_code_t rcvd_code = coap_pdu_get_code(received); - if (COAP_RESPONSE_CLASS(received->code) == 2) { - /* Need to see if blocked response */ - block_opt = coap_check_option(received, COAP_OPTION_BLOCK2, &opt_iter); - if (block_opt) { - uint16_t blktype = opt_iter.type; - - if (coap_opt_block_num(block_opt) == 0) { - printf("Received:\n"); - } - if (coap_get_data(received, &data_len, &data)) { - printf("%.*s", (int)data_len, data); - } - if (COAP_OPT_BLOCK_MORE(block_opt)) { - /* more bit is set */ - - /* create pdu with request for next block */ - pdu = coap_new_pdu(session); - if (!pdu) { - ESP_LOGE(TAG, "coap_new_pdu() failed"); - goto clean_up; - } - pdu->type = COAP_MESSAGE_CON; - pdu->tid = coap_new_message_id(session); - pdu->code = COAP_REQUEST_GET; - - /* add URI components from optlist */ - for (option = optlist; option; option = option->next ) { - switch (option->number) { - case COAP_OPTION_URI_HOST : - case COAP_OPTION_URI_PORT : - case COAP_OPTION_URI_PATH : - case COAP_OPTION_URI_QUERY : - coap_add_option(pdu, option->number, option->length, - option->data); - break; - default: - ; /* skip other options */ - } - } - - /* finally add updated block option from response, clear M bit */ - /* blocknr = (blocknr & 0xfffffff7) + 0x10; */ - coap_add_option(pdu, - blktype, - coap_encode_var_safe(buf, sizeof(buf), - ((coap_opt_block_num(block_opt) + 1) << 4) | - COAP_OPT_BLOCK_SZX(block_opt)), buf); - - tid = coap_send(session, pdu); - - if (tid != COAP_INVALID_TID) { - resp_wait = 1; - wait_ms = COAP_DEFAULT_TIME_SEC * 1000; - return; - } - } - printf("\n"); - } else { - if (coap_get_data(received, &data_len, &data)) { - printf("Received: %.*s\n", (int)data_len, data); + if (COAP_RESPONSE_CLASS(rcvd_code) == 2) { + if (coap_get_data_large(received, &data_len, &data, &offset, &total)) { + if (data_len != total) { + printf("Unexpected partial data received offset %u, length %u\n", offset, data_len); } + printf("Received:\n%.*s\n", (int)data_len, data); + resp_wait = 0; + } + return COAP_RESPONSE_OK; + } + printf("%d.%02d", (rcvd_code >> 5), rcvd_code & 0x1F); + if (coap_get_data_large(received, &data_len, &data, &offset, &total)) { + printf(": "); + while(data_len--) { + printf("%c", isprint(*data) ? *data : '.'); + data++; } } -clean_up: + printf("\n"); resp_wait = 0; + return COAP_RESPONSE_OK; } #ifdef CONFIG_COAP_MBEDTLS_PKI @@ -193,210 +144,303 @@ verify_cn_callback(const char *cn, } #endif /* CONFIG_COAP_MBEDTLS_PKI */ -static void coap_example_client(void *p) +static void +coap_log_handler (coap_log_t level, const char *message) { - struct hostent *hp; - coap_address_t dst_addr; - static coap_uri_t uri; - const char *server_uri = COAP_DEFAULT_DEMO_URI; + uint32_t esp_level = ESP_LOG_INFO; + char *cp = strchr(message, '\n'); + + if (cp) + ESP_LOG_LEVEL(esp_level, TAG, "%.*s", (int)(cp-message), message); + else + ESP_LOG_LEVEL(esp_level, TAG, "%s", message); +} + +static coap_address_t * +coap_get_address(coap_uri_t *uri) +{ + static coap_address_t dst_addr; char *phostname = NULL; + struct addrinfo hints; + struct addrinfo *addrres; + int error; + char tmpbuf[INET6_ADDRSTRLEN]; - coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); + phostname = (char *)calloc(1, uri->host.length + 1); + if (phostname == NULL) { + ESP_LOGE(TAG, "calloc failed"); + return NULL; + } + memcpy(phostname, uri->host.s, uri->host.length); - while (1) { -#define BUFSIZE 40 - unsigned char _buf[BUFSIZE]; - unsigned char *buf; - size_t buflen; - int res; - coap_context_t *ctx = NULL; - coap_session_t *session = NULL; - coap_pdu_t *request = NULL; + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; - optlist = NULL; - if (coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri) == -1) { - ESP_LOGE(TAG, "CoAP server uri error"); - break; - } - - if (uri.scheme == COAP_URI_SCHEME_COAPS && !coap_dtls_is_supported()) { - ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); - break; - } - if (uri.scheme == COAP_URI_SCHEME_COAPS_TCP && !coap_tls_is_supported()) { - ESP_LOGE(TAG, "CoAP server uri coaps+tcp:// scheme is not supported"); - break; - } - - phostname = (char *)calloc(1, uri.host.length + 1); - if (phostname == NULL) { - ESP_LOGE(TAG, "calloc failed"); - break; - } - - memcpy(phostname, uri.host.s, uri.host.length); - hp = gethostbyname(phostname); + error = getaddrinfo(phostname, NULL, &hints, &addrres); + if (error != 0) { + ESP_LOGE(TAG, "DNS lookup failed for destination address %s. error: %d", phostname, error); free(phostname); + return NULL; + } + if (addrres == NULL) { + ESP_LOGE(TAG, "DNS lookup %s did not return any addresses", phostname); + free(phostname); + return NULL; + } + free(phostname); + coap_address_init(&dst_addr); + switch (addrres->ai_family) { + case AF_INET: + memcpy(&dst_addr.addr.sin, addrres->ai_addr, sizeof(dst_addr.addr.sin)); + dst_addr.addr.sin.sin_port = htons(uri->port); + inet_ntop(AF_INET, &dst_addr.addr.sin.sin_addr, tmpbuf, sizeof(tmpbuf)); + ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); + break; + case AF_INET6: + memcpy(&dst_addr.addr.sin6, addrres->ai_addr, sizeof(dst_addr.addr.sin6)); + dst_addr.addr.sin6.sin6_port = htons(uri->port); + inet_ntop(AF_INET6, &dst_addr.addr.sin6.sin6_addr, tmpbuf, sizeof(tmpbuf)); + ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); + break; + default: + ESP_LOGE(TAG, "DNS lookup response failed"); + return NULL; + } + freeaddrinfo(addrres); - if (hp == NULL) { - ESP_LOGE(TAG, "DNS lookup failed"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - free(phostname); - continue; + return &dst_addr; +} + +static int +coap_build_optlist(coap_uri_t *uri) +{ +#define BUFSIZE 40 + unsigned char _buf[BUFSIZE]; + unsigned char *buf; + size_t buflen; + int res; + + optlist = NULL; + + if (uri->scheme == COAP_URI_SCHEME_COAPS && !coap_dtls_is_supported()) { + ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); + return 0; + } + if (uri->scheme == COAP_URI_SCHEME_COAPS_TCP && !coap_tls_is_supported()) { + ESP_LOGE(TAG, "CoAP server uri->+tcp:// scheme is not supported"); + return 0; + } + + if (uri->path.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_path(uri->path.s, uri->path.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_PATH, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); } - char tmpbuf[INET6_ADDRSTRLEN]; - coap_address_init(&dst_addr); - switch (hp->h_addrtype) { - case AF_INET: - dst_addr.addr.sin.sin_family = AF_INET; - dst_addr.addr.sin.sin_port = htons(uri.port); - memcpy(&dst_addr.addr.sin.sin_addr, hp->h_addr, sizeof(dst_addr.addr.sin.sin_addr)); - inet_ntop(AF_INET, &dst_addr.addr.sin.sin_addr, tmpbuf, sizeof(tmpbuf)); - ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); - break; - case AF_INET6: - dst_addr.addr.sin6.sin6_family = AF_INET6; - dst_addr.addr.sin6.sin6_port = htons(uri.port); - memcpy(&dst_addr.addr.sin6.sin6_addr, hp->h_addr, sizeof(dst_addr.addr.sin6.sin6_addr)); - inet_ntop(AF_INET6, &dst_addr.addr.sin6.sin6_addr, tmpbuf, sizeof(tmpbuf)); - ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); - break; - default: - ESP_LOGE(TAG, "DNS lookup response failed"); - goto clean_up; + } + + if (uri->query.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_query(uri->query.s, uri->query.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_QUERY, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); } - - if (uri.path.length) { - buflen = BUFSIZE; - buf = _buf; - res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); - - while (res--) { - coap_insert_optlist(&optlist, - coap_new_optlist(COAP_OPTION_URI_PATH, - coap_opt_length(buf), - coap_opt_value(buf))); - - buf += coap_opt_size(buf); - } - } - - if (uri.query.length) { - buflen = BUFSIZE; - buf = _buf; - res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); - - while (res--) { - coap_insert_optlist(&optlist, - coap_new_optlist(COAP_OPTION_URI_QUERY, - coap_opt_length(buf), - coap_opt_value(buf))); - - buf += coap_opt_size(buf); - } - } - - ctx = coap_new_context(NULL); - if (!ctx) { - ESP_LOGE(TAG, "coap_new_context() failed"); - goto clean_up; - } - - /* - * Note that if the URI starts with just coap:// (not coaps://) the - * session will still be plain text. - * - * coaps+tcp:// is NOT supported by the libcoap->mbedtls interface - * so COAP_URI_SCHEME_COAPS_TCP will have failed in a test above, - * but the code is left in for completeness. - */ - if (uri.scheme == COAP_URI_SCHEME_COAPS || uri.scheme == COAP_URI_SCHEME_COAPS_TCP) { -#ifndef CONFIG_MBEDTLS_TLS_CLIENT - ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); - goto clean_up; -#endif /* CONFIG_MBEDTLS_TLS_CLIENT */ + } + return 1; +} #ifdef CONFIG_COAP_MBEDTLS_PSK - session = coap_new_client_session_psk(ctx, NULL, &dst_addr, - uri.scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, - EXAMPLE_COAP_PSK_IDENTITY, - (const uint8_t *)EXAMPLE_COAP_PSK_KEY, - sizeof(EXAMPLE_COAP_PSK_KEY) - 1); +static coap_session_t * +coap_start_psk_session(coap_context_t *ctx, coap_address_t *dst_addr, coap_uri_t *uri) +{ + static coap_dtls_cpsk_t dtls_psk; + static char client_sni[256]; + + memset(client_sni, 0, sizeof(client_sni)); + memset (&dtls_psk, 0, sizeof(dtls_psk)); + dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; + dtls_psk.validate_ih_call_back = NULL; + dtls_psk.ih_call_back_arg = NULL; + if (uri->host.length) + memcpy(client_sni, uri->host.s, MIN(uri->host.length, sizeof(client_sni) - 1)); + else + memcpy(client_sni, "localhost", 9); + dtls_psk.client_sni = client_sni; + dtls_psk.psk_info.identity.s = (const uint8_t *)EXAMPLE_COAP_PSK_IDENTITY; + dtls_psk.psk_info.identity.length = sizeof(EXAMPLE_COAP_PSK_IDENTITY)-1; + dtls_psk.psk_info.key.s = (const uint8_t *)EXAMPLE_COAP_PSK_KEY; + dtls_psk.psk_info.key.length = sizeof(EXAMPLE_COAP_PSK_KEY)-1; + return coap_new_client_session_psk2(ctx, NULL, dst_addr, + uri->scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, + &dtls_psk); +} #endif /* CONFIG_COAP_MBEDTLS_PSK */ #ifdef CONFIG_COAP_MBEDTLS_PKI - unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; - unsigned int client_crt_bytes = client_crt_end - client_crt_start; - unsigned int client_key_bytes = client_key_end - client_key_start; - coap_dtls_pki_t dtls_pki; - static char client_sni[256]; +static coap_session_t * +coap_start_pki_session(coap_context_t *ctx, coap_address_t *dst_addr, coap_uri_t *uri) +{ + unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; + unsigned int client_crt_bytes = client_crt_end - client_crt_start; + unsigned int client_key_bytes = client_key_end - client_key_start; + static coap_dtls_pki_t dtls_pki; + static char client_sni[256]; - memset (&dtls_pki, 0, sizeof(dtls_pki)); - dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; - if (ca_pem_bytes) { - /* - * Add in additional certificate checking. - * This list of enabled can be tuned for the specific - * requirements - see 'man coap_encryption'. - * - * Note: A list of root ca file can be setup separately using - * coap_context_set_pki_root_cas(), but the below is used to - * define what checking actually takes place. - */ - dtls_pki.verify_peer_cert = 1; - dtls_pki.require_peer_cert = 1; - dtls_pki.allow_self_signed = 1; - dtls_pki.allow_expired_certs = 1; - dtls_pki.cert_chain_validation = 1; - dtls_pki.cert_chain_verify_depth = 2; - dtls_pki.check_cert_revocation = 1; - dtls_pki.allow_no_crl = 1; - dtls_pki.allow_expired_crl = 1; - dtls_pki.allow_bad_md_hash = 1; - dtls_pki.allow_short_rsa_length = 1; - dtls_pki.validate_cn_call_back = verify_cn_callback; - dtls_pki.cn_call_back_arg = NULL; - dtls_pki.validate_sni_call_back = NULL; - dtls_pki.sni_call_back_arg = NULL; - memset(client_sni, 0, sizeof(client_sni)); - if (uri.host.length) { - memcpy(client_sni, uri.host.s, MIN(uri.host.length, sizeof(client_sni))); - } else { - memcpy(client_sni, "localhost", 9); - } - dtls_pki.client_sni = client_sni; - } - dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM_BUF; - dtls_pki.pki_key.key.pem_buf.public_cert = client_crt_start; - dtls_pki.pki_key.key.pem_buf.public_cert_len = client_crt_bytes; - dtls_pki.pki_key.key.pem_buf.private_key = client_key_start; - dtls_pki.pki_key.key.pem_buf.private_key_len = client_key_bytes; - dtls_pki.pki_key.key.pem_buf.ca_cert = ca_pem_start; - dtls_pki.pki_key.key.pem_buf.ca_cert_len = ca_pem_bytes; - - session = coap_new_client_session_pki(ctx, NULL, &dst_addr, - uri.scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, - &dtls_pki); -#endif /* CONFIG_COAP_MBEDTLS_PKI */ + memset (&dtls_pki, 0, sizeof(dtls_pki)); + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + if (ca_pem_bytes) { + /* + * Add in additional certificate checking. + * This list of enabled can be tuned for the specific + * requirements - see 'man coap_encryption'. + * + * Note: A list of root cas file can be setup separately using + * coap_context_set_pki_root_cas(), but the below is used to + * define what checking actually takes place. + */ + dtls_pki.verify_peer_cert = 1; + dtls_pki.check_common_ca = 1; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 2; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + dtls_pki.allow_bad_md_hash = 1; + dtls_pki.allow_short_rsa_length = 1; + dtls_pki.validate_cn_call_back = verify_cn_callback; + dtls_pki.cn_call_back_arg = NULL; + dtls_pki.validate_sni_call_back = NULL; + dtls_pki.sni_call_back_arg = NULL; + memset(client_sni, 0, sizeof(client_sni)); + if (uri->host.length) { + memcpy(client_sni, uri->host.s, MIN(uri->host.length, sizeof(client_sni))); } else { - session = coap_new_client_session(ctx, NULL, &dst_addr, - uri.scheme == COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP : - COAP_PROTO_UDP); - } - if (!session) { - ESP_LOGE(TAG, "coap_new_client_session() failed"); - goto clean_up; + memcpy(client_sni, "localhost", 9); } + dtls_pki.client_sni = client_sni; + } + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM_BUF; + dtls_pki.pki_key.key.pem_buf.public_cert = client_crt_start; + dtls_pki.pki_key.key.pem_buf.public_cert_len = client_crt_bytes; + dtls_pki.pki_key.key.pem_buf.private_key = client_key_start; + dtls_pki.pki_key.key.pem_buf.private_key_len = client_key_bytes; + dtls_pki.pki_key.key.pem_buf.ca_cert = ca_pem_start; + dtls_pki.pki_key.key.pem_buf.ca_cert_len = ca_pem_bytes; - coap_register_response_handler(ctx, message_handler); + return coap_new_client_session_pki(ctx, NULL, dst_addr, + uri->scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, + &dtls_pki); +} +#endif /* CONFIG_COAP_MBEDTLS_PKI */ - request = coap_new_pdu(session); +static void coap_example_client(void *p) +{ + coap_address_t *dst_addr; + static coap_uri_t uri; + const char *server_uri = COAP_DEFAULT_DEMO_URI; + coap_context_t *ctx = NULL; + coap_session_t *session = NULL; + coap_pdu_t *request = NULL; + unsigned char token[8]; + size_t tokenlength; + + /* Set up the CoAP logging */ + coap_set_log_handler(coap_log_handler); + coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); + + /* Set up the CoAP context */ + ctx = coap_new_context(NULL); + if (!ctx) { + ESP_LOGE(TAG, "coap_new_context() failed"); + goto clean_up; + } + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY); + + coap_register_response_handler(ctx, message_handler); + + if (coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri) == -1) { + ESP_LOGE(TAG, "CoAP server uri error"); + goto clean_up; + } + if (!coap_build_optlist(&uri)) + goto clean_up; + + dst_addr = coap_get_address(&uri); + if (!dst_addr) + goto clean_up; + + /* + * Note that if the URI starts with just coap:// (not coaps://) the + * session will still be plain text. + * + * coaps+tcp:// is NOT yet supported by the libcoap->mbedtls interface + * so COAP_URI_SCHEME_COAPS_TCP will have failed in a test above, + * but the code is left in for completeness. + */ + if (uri.scheme == COAP_URI_SCHEME_COAPS || uri.scheme == COAP_URI_SCHEME_COAPS_TCP) { +#ifndef CONFIG_MBEDTLS_TLS_CLIENT + ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); + goto clean_up; +#endif /* CONFIG_MBEDTLS_TLS_CLIENT */ + +#ifdef CONFIG_COAP_MBEDTLS_PSK + session = coap_start_psk_session(ctx, dst_addr, &uri); +#endif /* CONFIG_COAP_MBEDTLS_PSK */ + +#ifdef CONFIG_COAP_MBEDTLS_PKI + session = coap_start_pki_session(ctx, dst_addr, &uri); +#endif /* CONFIG_COAP_MBEDTLS_PKI */ + } else { + session = coap_new_client_session(ctx, NULL, dst_addr, + uri.scheme == COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP : + COAP_PROTO_UDP); + } + if (!session) { + ESP_LOGE(TAG, "coap_new_client_session() failed"); + goto clean_up; + } + + while (1) { + request = coap_new_pdu(coap_is_mcast(dst_addr) ? COAP_MESSAGE_NON : COAP_MESSAGE_CON, + COAP_REQUEST_CODE_GET, session); if (!request) { ESP_LOGE(TAG, "coap_new_pdu() failed"); goto clean_up; } - request->type = COAP_MESSAGE_CON; - request->tid = coap_new_message_id(session); - request->code = COAP_REQUEST_GET; + /* Add in an unique token */ + coap_session_new_token(session, &tokenlength, token); + coap_add_token(request, tokenlength, token); + + /* + * To make this a POST, you will need to do the following + * Change COAP_REQUEST_CODE_GET to COAP_REQUEST_CODE_POST for coap_new_pdu() + * Add in here a Content-Type Option based on the format of the POST text. E.G. for JSON + * u_char buf[4]; + * coap_insert_optlist(&optlist, + * coap_new_optlist(COAP_OPTION_CONTENT_FORMAT, + * coap_encode_var_safe (buf, sizeof (buf), + * COAP_MEDIATYPE_APPLICATION_JSON)); + * Add in here the POST data of length length. E.G. + * coap_add_data_large_request(session, request length, data, NULL, NULL); + */ + coap_add_optlist_pdu(request, &optlist); resp_wait = 1; @@ -405,35 +449,37 @@ static void coap_example_client(void *p) wait_ms = COAP_DEFAULT_TIME_SEC * 1000; while (resp_wait) { - int result = coap_run_once(ctx, wait_ms > 1000 ? 1000 : wait_ms); + int result = coap_io_process(ctx, wait_ms > 1000 ? 1000 : wait_ms); if (result >= 0) { if (result >= wait_ms) { - ESP_LOGE(TAG, "select timeout"); + ESP_LOGE(TAG, "No response from server"); break; } else { wait_ms -= result; } } } -clean_up: - if (optlist) { - coap_delete_optlist(optlist); - optlist = NULL; + for(int countdown = 10; countdown >= 0; countdown--) { + ESP_LOGI(TAG, "%d... ", countdown); + vTaskDelay(1000 / portTICK_PERIOD_MS); } - if (session) { - coap_session_release(session); - } - if (ctx) { - coap_free_context(ctx); - } - coap_cleanup(); - /* - * change the following line to something like sleep(2) - * if you want the request to continually be sent - */ - break; + ESP_LOGI(TAG, "Starting again!"); } +clean_up: + if (optlist) { + coap_delete_optlist(optlist); + optlist = NULL; + } + if (session) { + coap_session_release(session); + } + if (ctx) { + coap_free_context(ctx); + } + coap_cleanup(); + + ESP_LOGI(TAG, "Finished"); vTaskDelete(NULL); } diff --git a/examples/protocols/coap_client/sdkconfig.defaults b/examples/protocols/coap_client/sdkconfig.defaults index 03171ab264..308ca1c49a 100644 --- a/examples/protocols/coap_client/sdkconfig.defaults +++ b/examples/protocols/coap_client/sdkconfig.defaults @@ -1,3 +1,4 @@ CONFIG_MBEDTLS_SSL_PROTO_DTLS=y CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_LWIP_NETBUF_RECVINFO=y diff --git a/examples/protocols/coap_server/README.md b/examples/protocols/coap_server/README.md index 9be65ad5a6..bb37783ff4 100644 --- a/examples/protocols/coap_server/README.md +++ b/examples/protocols/coap_server/README.md @@ -40,6 +40,9 @@ Component config ---> CoAP Configuration ---> * Set encryption method definition, PSK (default) or PKI * Enable CoAP debugging if required + High resolution timer (esp_timer) ---> + * Hardware timer to use for esp_timer - change if required (FRC2 for QEMU) + ### Build and Flash @@ -77,7 +80,11 @@ If a CoAP client queries the `/Espressif` resource, CoAP server will return `"He until a CoAP client does a PUT with different data. ## libcoap Documentation -This can be found at https://libcoap.net/doc/reference/4.2.0/ +This can be found at [libcoap Documentation](https://libcoap.net/documentation.html). +The current API is 4.3.0. + +## libcoap Specific Issues +These can be raised at [libcoap Issues](https://github.com/obgm/libcoap/issues). ## Troubleshooting * Please make sure CoAP client fetchs or puts data under path: `/Espressif` or diff --git a/examples/protocols/coap_server/main/Kconfig.projbuild b/examples/protocols/coap_server/main/Kconfig.projbuild index 19da8165a6..3c0fbfc230 100644 --- a/examples/protocols/coap_server/main/Kconfig.projbuild +++ b/examples/protocols/coap_server/main/Kconfig.projbuild @@ -8,4 +8,54 @@ menu "Example CoAP Server Configuration" The Preshared Key to use to encrypt the communicatons. The same key must be used at both ends of the CoAP connection, and the CoaP client must request an URI prefixed with coaps:// instead of coap:// for DTLS to be used. + + choice EXAMPLE_COAP_MCAST_IP_MODE + prompt "Receive Multicast IP type" + help + Example can receive multicast IPV4, IPV6, both or none. + + config EXAMPLE_COAP_MCAST_NONE + bool "None" + + config EXAMPLE_COAP_MCAST_IPV4_V6 + bool "IPV4 & IPV6" + select EXAMPLE_COAP_MCAST_IPV4 + select EXAMPLE_COAP_MCAST_IPV6 + + config EXAMPLE_COAP_MCAST_IPV4_ONLY + bool "IPV4" + select EXAMPLE_COAP_MCAST_IPV4 + + config EXAMPLE_COAP_MCAST_IPV6_ONLY + bool "IPV6" + select EXAMPLE_COAP_MCAST_IPV6 + + endchoice + + config EXAMPLE_COAP_MCAST_IPV4 + bool + config EXAMPLE_COAP_MCAST_IPV6 + bool + select EXAMPLE_CONNECT_IPV6 if IDF_TARGET_ESP32 + + config EXAMPLE_COAP_MULTICAST_IPV4_ADDR + string "CoAP Multicast IPV4 Address (receive)" + default "224.0.1.187" + depends on EXAMPLE_COAP_MCAST_IPV4 + help + IPV4 multicast address to receive multicast traffic on. + + The default CoAP IPV4 address is 224.0.1.187. + + config EXAMPLE_COAP_MULTICAST_IPV6_ADDR + string "CoAP Multicast IPV6 Address (receive)" + default "FF02::FD" + depends on EXAMPLE_COAP_MCAST_IPV6 + help + IPV6 multicast address to receive multicast traffic on. + + The default CoAP FF02::FD address is a link-local multicast address. + Consult IPV6 specifications or documentation for information about + meaning of different IPV6 multicast ranges. + endmenu diff --git a/examples/protocols/coap_server/main/certs/coap_ca.pem b/examples/protocols/coap_server/main/certs/coap_ca.pem index 1bdf23d94b..07900ec471 100644 --- a/examples/protocols/coap_server/main/certs/coap_ca.pem +++ b/examples/protocols/coap_server/main/certs/coap_ca.pem @@ -1,23 +1,27 @@ -----BEGIN CERTIFICATE----- -MIID3DCCA0WgAwIBAgIJAMnlgL1czsmjMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD -VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT -BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs -ZS5jb20xJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X -DTE3MDYwNzA4MDY0OVoXDTI3MDYwNTA4MDY0OVowgZMxCzAJBgNVBAYTAkZSMQ8w -DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh -bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG -A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBALpWR23fn/TmHxsXsHdrydzPSd17fZkc71WsaicgQR66 -1tIVYb22UWGfj9KPM8THMsV74ew4ZkaQ39qvU0iuQIRrKARFHFok+vbaecgWMeWe -vGIqdnmyB9gJYaFOKgtSkfXsu2ddsqdvLYwcDbczrq8X9yEXpN6mnxXeCcPG4F0p -AgMBAAGjggE0MIIBMDAdBgNVHQ4EFgQUgigpdAUpONoDq0pQ3yfxrslCSpcwgcgG -A1UdIwSBwDCBvYAUgigpdAUpONoDq0pQ3yfxrslCSpehgZmkgZYwgZMxCzAJBgNV -BAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMG -A1UECgwMRXhhbXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxl -LmNvbTEmMCQGA1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDJ -5YC9XM7JozAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93 -d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADgYEA -euxOBPInSJRKAIseMxPmAabtAqKNslZSmpG4He3lkKt+HM3jfznUt3psmD7j1hFW -S4l7KXzzajvaGYybDq5N9MqrDjhGn3VXZqOLMUNDL7OQq96TzgqsTBT1dmVSbNlt -PQgiAeKAk3tmH4lRRi9MTBSyJ6I92JYcS5H6Bs4ZwCc= +MIICDzCCAbSgAwIBAgIIAbOUoVFDz/QwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMzWhcNMjExMTExMTAzMDMzWjBaMQ4wDAYDVQQDEwVjZi1jYTEUMBIGA1UECxML +Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh +d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7/3EXOZn +GZXNEIj7LuQAMZ8lfRYSCnpME1TBjKjZPtVeztLtGWgkkLvIX11pAJcBh51cpi7Z +fQtGpVE9CLOh6aNgMF4wHQYDVR0OBBYEFEvf57UcJhYYkx14twkeitd691fVMAsG +A1UdDwQEAwIBBjAPBgNVHRMECDAGAQH/AgEBMB8GA1UdIwQYMBaAFAsi3KbVERiK +JzFCfC/GVrYksGzEMAwGCCqGSM49BAMCBQADRwAwRAIgc5nVF/5Pip0XB17IZXqi +V84FXanWdn9Z0SiPdpOgvZMCIH13vL9tkCCjPN3tg3TYRY/bzyGohFGBcTrrEtUr +rVIm +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB4DCCAYWgAwIBAgIIQR8ro8AQ02AwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMyWhcNMjExMTExMTAzMDMyWjBcMRAwDgYDVQQDEwdjZi1yb290MRQwEgYDVQQL +EwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBzZSBJb1QxDzANBgNVBAcTBk90 +dGF3YTELMAkGA1UEBhMCQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZ1BRM +T1//Fzh9sneRZNwS4kgCxN1PvgwT271qCpYqyxnjLEa38AP1IAanhpiD/OkVc0Zd +7NgDPCw7n94EULMyoy8wLTAdBgNVHQ4EFgQUCyLcptURGIonMUJ8L8ZWtiSwbMQw +DAYDVR0TBAUwAwEB/zAMBggqhkjOPQQDAgUAA0cAMEQCIAdLEgcUWdpAl9jwdJiz +/cHW7/CBIWEvqiQfzE+XLyLOAiAvuxSdOtSDjh2aC5qEjUCH8CSKCxWB74j23tmp +aqPH4A== -----END CERTIFICATE----- diff --git a/examples/protocols/coap_server/main/certs/coap_server.crt b/examples/protocols/coap_server/main/certs/coap_server.crt index 0af6f1741f..6522f4e4cd 100644 --- a/examples/protocols/coap_server/main/certs/coap_server.crt +++ b/examples/protocols/coap_server/main/certs/coap_server.crt @@ -1,70 +1,13 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 47 (0x2f) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FR, ST=Radius, L=Somewhere, O=Example Inc./emailAddress=admin@example.com, CN=Example Certificate Authority - Validity - Not Before: Jun 7 08:06:49 2017 GMT - Not After : Jun 5 08:06:49 2027 GMT - Subject: C=FR, ST=Radius, O=Example Inc., CN=Example Server Certificate/emailAddress=admin@example.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c9:d8:e2:e0:75:91:83:87:d8:c8:80:c6:20:4d: - e9:14:24:30:98:33:53:fa:56:0e:ec:9a:43:7f:87: - a9:22:94:26:06:c7:ac:b5:d9:ec:55:06:81:b7:0d: - c9:24:51:49:fa:47:fb:4b:4e:fc:ed:75:8a:e1:28: - 32:bc:c5:e0:4c:45:c4:58:60:15:67:1e:6b:40:19: - 3f:f0:ab:92:61:92:2d:71:10:2e:f2:eb:bc:81:2f: - 5a:3b:74:ca:5f:fd:e0:ee:d1:d9:07:6a:6c:20:c0: - 07:88:b4:8b:0f:ad:1e:c9:4f:7c:11:98:37:89:15: - de:24:b1:11:1a:7c:97:4a:cf:f3:c8:cb:79:9e:9c: - c3:71:da:a6:94:97:f5:95:fd:61:06:44:e2:3f:12: - 43:0b:1d:33:48:91:d2:ce:4f:97:a1:ed:6a:30:c7: - 5d:98:b5:6e:0a:b7:4f:d9:03:ec:80:76:09:b0:40: - a1:a1:af:ab:2a:59:c4:0f:56:22:bc:be:14:be:18: - df:10:7d:5d:22:bf:e5:04:77:7a:75:6b:3e:eb:6d: - 20:a1:a7:60:d4:f1:87:9d:9f:60:b9:d3:db:2c:25: - f4:91:4a:f1:d2:40:e5:a1:10:88:a0:41:5a:98:40: - ca:15:d7:e3:e6:3e:c0:6a:d5:46:b2:b4:90:b4:ae: - 3b:e3 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Extended Key Usage: - TLS Web Server Authentication - X509v3 CRL Distribution Points: - - Full Name: - URI:http://www.example.com/example_ca.crl - - Signature Algorithm: sha1WithRSAEncryption - a4:25:21:51:0b:22:6c:63:8d:a9:c1:4f:04:33:69:79:34:f0: - 36:dd:8f:6a:27:5f:07:a2:1d:ef:8b:f0:96:e6:e7:a3:b8:3b: - 85:5e:3f:26:43:8a:8e:95:58:9c:a6:db:9c:51:bf:ea:53:16: - 3e:c1:a8:11:1a:c6:cf:0e:a1:17:18:64:d2:05:f1:c0:9c:a6: - 2b:16:c4:29:54:03:d2:17:bd:15:74:d6:ad:8a:8f:2d:cc:27: - 3b:88:88:f2:ea:d0:a2:cb:e9:42:57:df:26:9f:8a:a2:02:2f: - 35:b6:19:1d:26:43:44:af:12:4b:bc:b9:84:50:02:fd:1d:fa: - 50:e8 -----BEGIN CERTIFICATE----- -MIIDWTCCAsKgAwIBAgIBLzANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCRlIx -DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRUwEwYDVQQKDAxF -eGFtcGxlIEluYy4xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMSYw -JAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA2MDcw -ODA2NDlaFw0yNzA2MDUwODA2NDlaMHwxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZS -YWRpdXMxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEjMCEGA1UEAwwaRXhhbXBsZSBT -ZXJ2ZXIgQ2VydGlmaWNhdGUxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUu -Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydji4HWRg4fYyIDG -IE3pFCQwmDNT+lYO7JpDf4epIpQmBsestdnsVQaBtw3JJFFJ+kf7S0787XWK4Sgy -vMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSL -D60eyU98EZg3iRXeJLERGnyXSs/zyMt5npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHS -zk+Xoe1qMMddmLVuCrdP2QPsgHYJsEChoa+rKlnED1YivL4UvhjfEH1dIr/lBHd6 -dWs+620goadg1PGHnZ9gudPbLCX0kUrx0kDloRCIoEFamEDKFdfj5j7AatVGsrSQ -tK474wIDAQABo08wTTATBgNVHSUEDDAKBggrBgEFBQcDATA2BgNVHR8ELzAtMCug -KaAnhiVodHRwOi8vd3d3LmV4YW1wbGUuY29tL2V4YW1wbGVfY2EuY3JsMA0GCSqG -SIb3DQEBBQUAA4GBAKQlIVELImxjjanBTwQzaXk08Dbdj2onXweiHe+L8Jbm56O4 -O4VePyZDio6VWJym25xRv+pTFj7BqBEaxs8OoRcYZNIF8cCcpisWxClUA9IXvRV0 -1q2Kjy3MJzuIiPLq0KLL6UJX3yafiqICLzW2GR0mQ0SvEku8uYRQAv0d+lDo +MIICAzCCAaagAwIBAgIJANqCHDjOKHh+MAwGCCqGSM49BAMCBQAwWjEOMAwGA1UE +AxMFY2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNl +IElvVDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMDExMTExMDMw +MzRaFw0yMTExMTExMDMwMzRaMF4xEjAQBgNVBAMTCWNmLXNlcnZlcjEUMBIGA1UE +CxMLQ2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZP +dHRhd2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+obM +gHmMB7zS4KArciXPD7CrvgEYqlnAf7NOTdb54RbTr4qEpPL+OJ6Pg8VhrF4hGEne +T6Aa4qqpmTkxmfT0vqNPME0wHQYDVR0OBBYEFE4XpfFad+F3+RcwI+s1cmJbTZWG +MAsGA1UdDwQEAwIHgDAfBgNVHSMEGDAWgBRL3+e1HCYWGJMdeLcJHorXevdX1TAM +BggqhkjOPQQDAgUAA0kAMEYCIQCEo+O5zqYKdwi/ElB4wfNVIf76P1OhIXAT5CHc +3ebBPQIhAN6UhCgQ0av6kf7INCazV3KmN7HmPXARaY4YKWsRwsg+ -----END CERTIFICATE----- diff --git a/examples/protocols/coap_server/main/certs/coap_server.key b/examples/protocols/coap_server/main/certs/coap_server.key index 9b3433273e..362851524f 100644 --- a/examples/protocols/coap_server/main/certs/coap_server.key +++ b/examples/protocols/coap_server/main/certs/coap_server.key @@ -1,27 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAydji4HWRg4fYyIDGIE3pFCQwmDNT+lYO7JpDf4epIpQmBses -tdnsVQaBtw3JJFFJ+kf7S0787XWK4SgyvMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu -8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSLD60eyU98EZg3iRXeJLERGnyXSs/zyMt5 -npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHSzk+Xoe1qMMddmLVuCrdP2QPsgHYJsECh -oa+rKlnED1YivL4UvhjfEH1dIr/lBHd6dWs+620goadg1PGHnZ9gudPbLCX0kUrx -0kDloRCIoEFamEDKFdfj5j7AatVGsrSQtK474wIDAQABAoIBAQC2kGDEPBJdMSW2 -VCLfXRiPixwYzXQLXIMrJWwfkQg9qlmqkDd6U50aWkRA2UswegW7RhfYSZ0i+cmf -VMhvTVpOIlwwwtcY6b5/v1bBy60eaySGuuh79xQMlFO8qynQIMStvUfbGTqrdIRb -9VBB4YeS9T12fILejtTZwv2BQ2dj1Y1SCay6Ri85UzJqSClRKgHISybvVdLNjPvP -0TRFBr57zyjL6WE8teKiKchzQko2u86No5uBCdKGsrAkrsdcR0YqlM/pZxd3VKNm -+eny0k+dZZlvcPxzkzP4hEp9+Rw5rP9/s3s/cCwvuuC5JO32ATBWKCbTvPv/XPDb -MdSJtOshAoGBAPzk0eswkcbFYtpnpBNmBAr1dtAdW1lfjUI2ucMMwt7Wns0P/tt+ -gq6Hi1wTaGP0l/dIECgeHwjtWj31ZJjQtFJ1y/kafxo4o9cA8vCydpdvSZaldAfg -sbLlDTDYzEpelaDIbNQBBXFoC5U9JlBhBsIFCL5Z8ZuIeFPsb7t5wwuHAoGBAMxT -jyWfNm1uNxp1xgCnrRsLPQPVnURrSFAqcHrECqRu3F7sozTN7q/cZViemxPvVDGQ -p9c+9bHwaYvW4trO5qDHJ++gGwm5L52bMAY1VUfeTt67fqrey43XpdmzcTX1V9Uj -QWawPUCSDzFjL1MjfCIejtyYf5ash53vj+T8r/vFAoGAA/OPVB1uKazr3n3AEo2F -gqZTNO1AgCT+EArK3EFWyiSQVqPpV4SihheYFdg3yVgJB9QYbIgL9BfBUTaEW97m -8mLkzP+c/Mvlw3ZAVYJ0V+llPPVY2saoACOUES9SAdd4fwqiqK1baGo3xB0wfBEI -CgAKIu9E1ylKuAT5ufQtGAECgYEAtP/kU5h5N3El4QupTdU7VDSdZTMqsHw0v8cI -gsf9AXKvRmtrnBA8u46KPHmruHoO5CVXeSZtsaXdaaH+rYQQ6yXg67WxnehtFLlv -TmCaXiLBTS9cYvMf8FOyuGnsBLeEietEOTov2G5KhR5uwsAxa2wUc7endor5S9/2 -YQuyvV0CgYALbiFpILd5l1ip65eE6JdA3hfttUbV2j2NSW12ej69vqbeOfaSgNse -uYCcXFsBbQPhNPwA+4d1oCe8SyXZg1f7gE812z2Tyr/3vdVnNZlitoxhsHmGiyS7 -gZdaTYCb78l9z0EBdaCVvA16owEle4SR6f9eCwzSI0WPOUra+x/hrA== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCLBQT66xp2w4+1K+Ai +/TXEC8tQZBxl9brFyK4F7AQNGw== +-----END PRIVATE KEY----- diff --git a/examples/protocols/coap_server/main/coap_server_example_main.c b/examples/protocols/coap_server/main/coap_server_example_main.c index 58a698d8ae..ed96cc6e21 100644 --- a/examples/protocols/coap_server/main/coap_server_example_main.c +++ b/examples/protocols/coap_server/main/coap_server_example_main.c @@ -29,15 +29,10 @@ #include "protocol_examples_common.h" -#if 1 -/* Needed until coap_dtls.h becomes a part of libcoap proper */ -#include "libcoap.h" -#include "coap_dtls.h" -#endif -#include "coap.h" +#include "coap3/coap.h" /* The examples use simple Pre-Shared-Key configuration that you can set via - 'make menuconfig'. + 'idf.py menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_COAP_PSK_KEY "some-agreed-preshared-key" @@ -49,7 +44,7 @@ #define EXAMPLE_COAP_PSK_KEY CONFIG_EXAMPLE_COAP_PSK_KEY /* The examples use CoAP Logging Level that - you can set via 'make menuconfig'. + you can set via 'idf.py menuconfig'. If you'd rather not, just change the below entry to a value that is between 0 and 7 with @@ -67,8 +62,10 @@ static int espressif_data_len = 0; Server cert, taken from coap_server.crt Server key, taken from coap_server.key - The PEM, CRT and KEY file are examples taken from the wpa2 enterprise - example. + The PEM, CRT and KEY file are examples taken from + https://github.com/eclipse/californium/tree/master/demo-certs/src/main/resources + as the Certificate test (by default) for the coap_client is against the + californium server. To embed it in the app binary, the PEM, CRT and KEY file is named in the component.mk COMPONENT_EMBED_TXTFILES variable. @@ -87,39 +84,42 @@ extern uint8_t server_key_end[] asm("_binary_coap_server_key_end"); * The resource handler */ static void -hnd_espressif_get(coap_context_t *ctx, coap_resource_t *resource, +hnd_espressif_get(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, coap_binary_t *token, - coap_string_t *query, coap_pdu_t *response) + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { - coap_add_data_blocked_response(resource, session, request, response, token, - COAP_MEDIATYPE_TEXT_PLAIN, 0, - (size_t)espressif_data_len, - (const u_char *)espressif_data); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 60, 0, + (size_t)espressif_data_len, + (const u_char *)espressif_data, + NULL, NULL); } static void -hnd_espressif_put(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_put(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { size_t size; - unsigned char *data; + size_t offset; + size_t total; + const unsigned char *data; coap_resource_notify_observers(resource, NULL); if (strcmp (espressif_data, INITIAL_DATA) == 0) { - response->code = COAP_RESPONSE_CODE(201); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); } else { - response->code = COAP_RESPONSE_CODE(204); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); } - /* coap_get_data() sets size to 0 on error */ - (void)coap_get_data(request, &size, &data); + /* coap_get_data_large() sets size to 0 on error */ + (void)coap_get_data_large(request, &size, &data, &offset, &total); if (size == 0) { /* re-init */ snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); @@ -131,18 +131,16 @@ hnd_espressif_put(coap_context_t *ctx, } static void -hnd_espressif_delete(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_delete(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { coap_resource_notify_observers(resource, NULL); snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); - response->code = COAP_RESPONSE_CODE(202); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); } #ifdef CONFIG_COAP_MBEDTLS_PKI @@ -163,6 +161,18 @@ verify_cn_callback(const char *cn, } #endif /* CONFIG_COAP_MBEDTLS_PKI */ +static void +coap_log_handler (coap_log_t level, const char *message) +{ + uint32_t esp_level = ESP_LOG_INFO; + char *cp = strchr(message, '\n'); + + if (cp) + ESP_LOG_LEVEL(esp_level, TAG, "%.*s", (int)(cp-message), message); + else + ESP_LOG_LEVEL(esp_level, TAG, "%s", message); +} + static void coap_example_server(void *p) { coap_context_t *ctx = NULL; @@ -171,6 +181,7 @@ static void coap_example_server(void *p) snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); + coap_set_log_handler(coap_log_handler); coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); while (1) { @@ -179,15 +190,16 @@ static void coap_example_server(void *p) /* Prepare the CoAP server socket */ coap_address_init(&serv_addr); - serv_addr.addr.sin.sin_family = AF_INET; - serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY; - serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_family = AF_INET6; + serv_addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); ctx = coap_new_context(NULL); if (!ctx) { ESP_LOGE(TAG, "coap_new_context() failed"); continue; } + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY); #ifdef CONFIG_COAP_MBEDTLS_PSK /* Need PSK setup before we set up endpoints */ coap_context_set_psk(ctx, "CoAP", @@ -196,6 +208,7 @@ static void coap_example_server(void *p) #endif /* CONFIG_COAP_MBEDTLS_PSK */ #ifdef CONFIG_COAP_MBEDTLS_PKI + /* Need PKI setup before we set up endpoints */ unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; unsigned int server_crt_bytes = server_crt_end - server_crt_start; unsigned int server_key_bytes = server_key_end - server_key_start; @@ -214,7 +227,7 @@ static void coap_example_server(void *p) * define what checking actually takes place. */ dtls_pki.verify_peer_cert = 1; - dtls_pki.require_peer_cert = 1; + dtls_pki.check_common_ca = 1; dtls_pki.allow_self_signed = 1; dtls_pki.allow_expired_certs = 1; dtls_pki.cert_chain_validation = 1; @@ -256,7 +269,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); #else /* CONFIG_MBEDTLS_TLS_SERVER */ - serv_addr.addr.sin.sin_port = htons(COAPS_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_port = htons(COAPS_DEFAULT_PORT); ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_DTLS); if (!ep) { ESP_LOGE(TAG, "dtls: coap_new_endpoint() failed"); @@ -267,7 +280,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); } -#endif /* CONFIG_COAP_MBEDTLS_PSK CONFIG_COAP_MBEDTLS_PKI */ +#endif /* CONFIG_COAP_MBEDTLS_PSK || CONFIG_COAP_MBEDTLS_PKI */ resource = coap_resource_init(coap_make_str_const("Espressif"), 0); if (!resource) { ESP_LOGE(TAG, "coap_resource_init() failed"); @@ -280,10 +293,26 @@ static void coap_example_server(void *p) coap_resource_set_get_observable(resource, 1); coap_add_resource(ctx, resource); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) || defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + esp_netif_t *netif = NULL; + for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) { + char buf[8]; + netif = esp_netif_next(netif); + esp_netif_get_netif_impl_name(netif, buf); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV4_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 */ +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + /* When adding IPV6 esp-idf requires ifname param to be filled in */ + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV6_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + } +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 || CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; while (1) { - int result = coap_run_once(ctx, wait_ms); + int result = coap_io_process(ctx, wait_ms); if (result < 0) { break; } else if (result && (unsigned)result < wait_ms) { diff --git a/examples/protocols/coap_server/sdkconfig.defaults b/examples/protocols/coap_server/sdkconfig.defaults index 03171ab264..308ca1c49a 100644 --- a/examples/protocols/coap_server/sdkconfig.defaults +++ b/examples/protocols/coap_server/sdkconfig.defaults @@ -1,3 +1,4 @@ CONFIG_MBEDTLS_SSL_PROTO_DTLS=y CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_LWIP_NETBUF_RECVINFO=y From a3dc625da6e9634c056b48c3319980dca083f586 Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 13 Aug 2021 11:30:54 +0800 Subject: [PATCH 092/310] mspi: support 120MHz Quad Flash and PSRAM on ESP32S3 --- .../src/bootloader_flash_config_esp32s3.c | 16 +- components/esp32s3/Kconfig | 3 + .../port/esp32s3/opiram_psram.c | 31 ++- .../esp_hw_support/port/esp32s3/spiram.c | 7 +- .../port/esp32s3/spiram_psram.c | 261 +++++------------- .../port/esp32s3/spiram_psram.h | 2 - components/esp_system/port/cpu_start.c | 3 + components/esptool_py/Kconfig.projbuild | 2 +- components/soc/esp32s3/include/soc/rtc.h | 2 +- .../esp32s3/mspi_timing_tuning_configs.h | 26 +- .../spi_flash/esp32s3/spi_timing_config.c | 216 ++++++++++++--- .../spi_flash/esp32s3/spi_timing_config.h | 179 +++++++++--- .../spi_flash/include/spi_flash_private.h | 24 +- components/spi_flash/linker.lf | 1 + .../spi_flash/spi_flash_timing_tuning.c | 108 +++++--- 15 files changed, 525 insertions(+), 356 deletions(-) diff --git a/components/bootloader_support/src/bootloader_flash_config_esp32s3.c b/components/bootloader_support/src/bootloader_flash_config_esp32s3.c index 6266a74e8c..357de775a5 100644 --- a/components/bootloader_support/src/bootloader_flash_config_esp32s3.c +++ b/components/bootloader_support/src/bootloader_flash_config_esp32s3.c @@ -33,18 +33,18 @@ void bootloader_flash_update_id() void IRAM_ATTR bootloader_flash_cs_timing_config() { - // SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH/PSRAM, so we only need to set SPI0 related registers here + //SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH, so we only need to set SPI0 related registers here +#if CONFIG_ESPTOOLPY_OCT_FLASH SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_CS_HOLD_TIME_S); SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_CS_SETUP_TIME_S); - - SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); - - // cs high time + //CS high time SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_CS_HOLD_DELAY_S); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_S); +#else + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); +#endif } void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr) diff --git a/components/esp32s3/Kconfig b/components/esp32s3/Kconfig index 2205b88470..044d7c593c 100644 --- a/components/esp32s3/Kconfig +++ b/components/esp32s3/Kconfig @@ -246,6 +246,9 @@ menu "ESP32S3-Specific" help Select the speed for the SPI RAM chip. + config SPIRAM_SPEED_120M + depends on SPIRAM_MODE_QUAD + bool "120MHz clock speed" config SPIRAM_SPEED_80M bool "80MHz clock speed" config SPIRAM_SPEED_40M diff --git a/components/esp_hw_support/port/esp32s3/opiram_psram.c b/components/esp_hw_support/port/esp32s3/opiram_psram.c index 6c45cb4f1f..584f45ce3a 100644 --- a/components/esp_hw_support/port/esp32s3/opiram_psram.c +++ b/components/esp_hw_support/port/esp32s3/opiram_psram.c @@ -40,6 +40,10 @@ #define OCT_PSRAM_WR_DUMMY_BITLEN (2*(5-1)) #define OCT_PSRAM_CS1_IO 26 +#define OCT_PSRAM_CS_SETUP_TIME 3 +#define OCT_PSRAM_CS_HOLD_TIME 3 +#define OCT_PSRAM_CS_HOLD_DELAY 2 + typedef struct { union { struct { @@ -96,7 +100,7 @@ typedef struct { static const char* TAG = "opi psram"; static DRAM_ATTR psram_size_t s_psram_size; -static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); +static void IRAM_ATTR s_config_psram_spi_phases(void); /** * Initialise mode registers of the PSRAM @@ -205,6 +209,16 @@ static void IRAM_ATTR s_print_psram_info(opi_psram_mode_reg_t *reg_val) reg_val->mr0.drive_str == 0x02 ? 4 : 8); } +static void psram_set_cs_timing(void) +{ + //SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for PSRAM, so we only need to set SPI0 related registers here + SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, OCT_PSRAM_CS_HOLD_TIME, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, OCT_PSRAM_CS_SETUP_TIME, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); + //CS1 high time + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_V, OCT_PSRAM_CS_HOLD_DELAY, SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_S); +} + static void IRAM_ATTR s_init_psram_pins(void) { //Set cs1 pin function @@ -218,9 +232,10 @@ static void IRAM_ATTR s_init_psram_pins(void) esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) { s_init_psram_pins(); + psram_set_cs_timing(); //enter MSPI slow mode to init PSRAM device registers - spi_timing_enter_mspi_low_speed_mode(); + spi_timing_enter_mspi_low_speed_mode(true); //set to variable dummy mode SET_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); @@ -245,10 +260,10 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad #if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC && CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR esp_rom_spi_set_dtr_swap_mode(1, true, true); #endif - + //Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly spi_timing_psram_tuning(); - - spi_timing_enter_mspi_high_speed_mode(); + ////Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly + spi_timing_enter_mspi_high_speed_mode(true); /** * Tuning may change SPI1 regs, whereas legacy spi_flash APIs rely on these regs. @@ -256,12 +271,12 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad */ spi_flash_set_rom_required_regs(); - psram_cache_init(mode, vaddrmode); + s_config_psram_spi_phases(); return ESP_OK; } -//register initialization for sram cache params and r/w commands -static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode) +//Configure PSRAM SPI0 phase related registers here according to the PSRAM chip requirement +static void IRAM_ATTR s_config_psram_spi_phases(void) { //Config Write CMD phase for SPI0 to access PSRAM SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_WCMD_M); diff --git a/components/esp_hw_support/port/esp32s3/spiram.c b/components/esp_hw_support/port/esp32s3/spiram.c index f554cb096c..e713fab3e3 100644 --- a/components/esp_hw_support/port/esp32s3/spiram.c +++ b/components/esp_hw_support/port/esp32s3/spiram.c @@ -36,10 +36,8 @@ static const char *TAG = "spiram"; #if CONFIG_SPIRAM_SPEED_40M #define PSRAM_SPEED PSRAM_CACHE_S40M -#elif CONFIG_SPIRAM_SPEED_80M +#else //#if CONFIG_SPIRAM_SPEED_80M #define PSRAM_SPEED PSRAM_CACHE_S80M -#else -#define PSRAM_SPEED PSRAM_CACHE_S20M #endif static bool s_spiram_inited = false; @@ -247,8 +245,7 @@ esp_err_t esp_spiram_init(void) ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device", (esp_spiram_get_size() * 8) / (1024 * 1024)); - ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_S40M ? "sram 40m" : \ - PSRAM_SPEED == PSRAM_CACHE_S80M ? "sram 80m" : "sram 20m"); + ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_S40M ? "sram 40m" : "sram 80m"); ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \ (PSRAM_MODE == PSRAM_VADDR_MODE_EVENODD) ? "even/odd (2-core)" : \ (PSRAM_MODE == PSRAM_VADDR_MODE_LOWHIGH) ? "low/high (2-core)" : \ diff --git a/components/esp_hw_support/port/esp32s3/spiram_psram.c b/components/esp_hw_support/port/esp32s3/spiram_psram.c index 45214a7da8..b0e07abd19 100644 --- a/components/esp_hw_support/port/esp32s3/spiram_psram.c +++ b/components/esp_hw_support/port/esp32s3/spiram_psram.c @@ -39,15 +39,14 @@ #if CONFIG_SPIRAM_MODE_QUAD #include "soc/rtc.h" +#include "spi_flash_private.h" static const char* TAG = "psram"; //Commands for PSRAM chip #define PSRAM_READ 0x03 #define PSRAM_FAST_READ 0x0B -#define PSRAM_FAST_READ_DUMMY 0x3 #define PSRAM_FAST_READ_QUAD 0xEB -#define PSRAM_FAST_READ_QUAD_DUMMY 0x5 #define PSRAM_WRITE 0x02 #define PSRAM_QUAD_WRITE 0x38 #define PSRAM_ENTER_QMODE 0x35 @@ -56,6 +55,10 @@ static const char* TAG = "psram"; #define PSRAM_RESET 0x99 #define PSRAM_SET_BURST_LEN 0xC0 #define PSRAM_DEVICE_ID 0x9F + +#define PSRAM_FAST_READ_DUMMY 4 +#define PSRAM_FAST_READ_QUAD_DUMMY 6 + // ID #define PSRAM_ID_KGD_M 0xff #define PSRAM_ID_KGD_S 8 @@ -78,8 +81,6 @@ static const char* TAG = "psram"; #define PSRAM_SIZE_ID(id) ((PSRAM_EID(id) >> PSRAM_EID_SIZE_S) & PSRAM_EID_SIZE_M) #define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD) -// For the old version 32Mbit psram, using the spicial driver */ -#define PSRAM_IS_32MBIT_VER0(id) (PSRAM_EID(id) == 0x20) #define PSRAM_IS_64MBIT_TRIAL(id) (PSRAM_EID(id) == 0x26) // IO-pins for PSRAM. @@ -99,22 +100,8 @@ static const char* TAG = "psram"; #define CS_PSRAM_SEL SPI_MEM_CS1_DIS_M #define CS_FLASH_SEL SPI_MEM_CS0_DIS_M -#define PSRAM_IO_MATRIX_DUMMY_20M 0 -#define PSRAM_IO_MATRIX_DUMMY_40M 0 -#define PSRAM_IO_MATRIX_DUMMY_80M 0 -#define _SPI_CACHE_PORT 0 -#define _SPI_FLASH_PORT 1 -#define _SPI_80M_CLK_DIV 1 -#define _SPI_40M_CLK_DIV 2 -#define _SPI_20M_CLK_DIV 4 - -typedef enum { - PSRAM_CLK_MODE_NORM = 0, /*!< Normal SPI mode */ - PSRAM_CLK_MODE_A1C, /*!< ONE extra clock cycles after CS is set high level */ - PSRAM_CLK_MODE_A2C, /*!< Two extra clock cycles after CS is set high level */ - PSRAM_CLK_MODE_ALON, /*!< clock always on */ - PSRAM_CLK_MODE_MAX, -} psram_clk_mode_t; +#define SPI1_NUM 1 +#define SPI0_NUM 0 typedef enum { @@ -123,35 +110,6 @@ typedef enum { PSRAM_EID_SIZE_64MBITS = 2, } psram_eid_size_t; -typedef struct { - uint8_t flash_clk_io; - uint8_t flash_cs_io; - uint8_t psram_clk_io; - uint8_t psram_cs_io; - uint8_t psram_spiq_sd0_io; - uint8_t psram_spid_sd1_io; - uint8_t psram_spiwp_sd3_io; - uint8_t psram_spihd_sd2_io; -} psram_io_t; - -#define PSRAM_IO_CONF_DEFAULT() { \ - .flash_clk_io = FLASH_CLK_IO, \ - .flash_cs_io = FLASH_CS_IO, \ - .psram_clk_io = PSRAM_CLK_IO, \ - .psram_cs_io = PSRAM_CS_IO, \ - .psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO, \ - .psram_spid_sd1_io = PSRAM_SPID_SD1_IO, \ - .psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO, \ - .psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO, \ -} - -typedef enum { - PSRAM_SPI_1 = 0x1, - /* PSRAM_SPI_2, */ - /* PSRAM_SPI_3, */ - PSRAM_SPI_MAX , -} psram_spi_num_t; - typedef enum { PSRAM_CMD_QPI, PSRAM_CMD_SPI, @@ -160,7 +118,7 @@ typedef enum { typedef esp_rom_spi_cmd_t psram_cmd_t; static uint32_t s_psram_id = 0; -static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); +static void IRAM_ATTR config_psram_spi_phases(void); extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); static void psram_set_op_mode(int spi_num, psram_cmd_mode_t mode) @@ -275,7 +233,7 @@ esp_err_t psram_enable_wrap(uint32_t wrap_size) switch (wrap_size) { case 32: case 0: - psram_set_wrap_burst_length(PSRAM_SPI_1, PSRAM_CMD_QPI); + psram_set_wrap_burst_length(1, PSRAM_CMD_QPI); current_wrap_size = wrap_size; return ESP_OK; case 16: @@ -299,7 +257,7 @@ bool psram_support_wrap_size(uint32_t wrap_size) } -//read psram id, should issue `psram_disable_qio_mode` before calling this +//Read ID operation only supports SPI CMD and mode, should issue `psram_disable_qio_mode` before calling this static void psram_read_id(int spi_num, uint32_t* dev_id) { psram_exec_cmd(spi_num, PSRAM_CMD_SPI, @@ -325,58 +283,36 @@ static void IRAM_ATTR psram_enable_qio_mode(int spi_num) false); /* whether is program/erase operation */ } -static void psram_set_spi1_cmd_cs_timing(psram_clk_mode_t clk_mode) +static void psram_set_cs_timing(void) { - if (clk_mode == PSRAM_CLK_MODE_NORM) { - // SPI1 Flash Operation port - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); - SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); - } else { - SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); - } + //SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time registers for PSRAM, so we only need to set SPI0 related registers here + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); } -static void psram_set_spi0_cache_cs_timing(psram_clk_mode_t clk_mode) +static void IRAM_ATTR psram_gpio_config(void) { - if (clk_mode == PSRAM_CLK_MODE_NORM) { - // SPI0 SRAM Cache port - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, 1, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); - SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); - // SPI0 Flash Cache port - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); - SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); + //CS1 + uint8_t cs1_io = PSRAM_CS_IO; + if (cs1_io == SPI_CS1_GPIO_NUM) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs1_io], FUNC_SPICS1_SPICS1); } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_CS_HOLD_M | SPI_CS_SETUP_M); + esp_rom_gpio_connect_out_signal(cs1_io, SPICS1_OUT_IDX, 0, 0); + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs1_io], PIN_FUNC_GPIO); } -} -//psram gpio init , different working frequency we have different solutions -static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) -{ - psram_io_t psram_io = PSRAM_IO_CONF_DEFAULT(); + //WP HD + uint8_t wp_io = PSRAM_SPIWP_SD3_IO; const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { - /* FLASH pins(except wp / hd) are all configured via IO_MUX in rom. */ + // MSPI pins (except wp / hd) are all configured via IO_MUX in 1st bootloader. } else { - // FLASH pins are all configured via GPIO matrix in ROM. - psram_io.flash_clk_io = EFUSE_SPICONFIG_RET_SPICLK(spiconfig); - psram_io.flash_cs_io = EFUSE_SPICONFIG_RET_SPICS0(spiconfig); - psram_io.psram_spiq_sd0_io = EFUSE_SPICONFIG_RET_SPIQ(spiconfig); - psram_io.psram_spid_sd1_io = EFUSE_SPICONFIG_RET_SPID(spiconfig); - psram_io.psram_spihd_sd2_io = EFUSE_SPICONFIG_RET_SPIHD(spiconfig); - psram_io.psram_spiwp_sd3_io = esp_rom_efuse_get_flash_wp_gpio(); - } - esp_rom_spiflash_select_qio_pins(psram_io.psram_spiwp_sd3_io, spiconfig); - - if (psram_io.psram_cs_io == SPI_CS1_GPIO_NUM) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], FUNC_SPICS1_SPICS1); - } else { - esp_rom_gpio_connect_out_signal(psram_io.psram_cs_io, SPICS1_OUT_IDX, 0, 0); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], PIN_FUNC_GPIO); + // MSPI pins (except wp / hd) are all configured via GPIO matrix in 1st bootloader. + wp_io = esp_rom_efuse_get_flash_wp_gpio(); } + //This ROM function will init both WP and HD pins. + esp_rom_spiflash_select_qio_pins(wp_io, spiconfig); } psram_size_t psram_get_size(void) @@ -393,21 +329,6 @@ psram_size_t psram_get_size(void) return PSRAM_SIZE_MAX; } -//used in UT only -bool psram_is_32mbit_ver0(void) -{ - return PSRAM_IS_32MBIT_VER0(s_psram_id); -} - -static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode) -{ - if (spi_num == _SPI_CACHE_PORT) { - REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, clk_mode); - } else if (spi_num == _SPI_FLASH_PORT) { - REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, clk_mode); - } -} - /* * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA. * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode. @@ -415,119 +336,67 @@ static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode) esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init { assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now."); - // GPIO related settings - psram_gpio_config(mode); - /* SPI1: set spi1 clk mode, in order to send commands on SPI1 */ - /* SPI1: set cs timing(hold time) in order to send commands on SPI1 */ - psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_A1C); - psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_A1C); + psram_gpio_config(); + psram_set_cs_timing(); - int spi_num = PSRAM_SPI_1; - psram_disable_qio_mode(spi_num); - psram_read_id(spi_num, &s_psram_id); + //enter MSPI slow mode to init PSRAM device registers + spi_timing_enter_mspi_low_speed_mode(true); + + //We use SPI1 to init PSRAM + psram_disable_qio_mode(SPI1_NUM); + psram_read_id(SPI1_NUM, &s_psram_id); if (!PSRAM_IS_VALID(s_psram_id)) { /* 16Mbit psram ID read error workaround: * treat the first read id as a dummy one as the pre-condition, * Send Read ID command again */ - psram_read_id(spi_num, &s_psram_id); + psram_read_id(SPI1_NUM, &s_psram_id); if (!PSRAM_IS_VALID(s_psram_id)) { ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x", s_psram_id); return ESP_FAIL; } } - psram_clk_mode_t clk_mode = PSRAM_CLK_MODE_MAX; - if (psram_is_32mbit_ver0()) { - clk_mode = PSRAM_CLK_MODE_A1C; - // SPI1: keep clock mode and cs timing for spi1 - } else { - // For other psram, we don't need any extra clock cycles after cs get back to high level - clk_mode = PSRAM_CLK_MODE_NORM; - // SPI1: set clock mode and cs timing to normal mode - psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM); - psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM); - } + //SPI1: send psram reset command + psram_reset_mode(SPI1_NUM); + //SPI1: send QPI enable command + psram_enable_qio_mode(SPI1_NUM); - /* SPI1: send psram reset command */ - /* SPI1: send QPI enable command */ - psram_reset_mode(PSRAM_SPI_1); - psram_enable_qio_mode(PSRAM_SPI_1); + //Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly + spi_timing_psram_tuning(); - // after sending commands, set spi1 clock mode and cs timing to normal mode. - // since all the operations are sent via SPI0 Cache - /* SPI1: set clock mode to normal mode. */ - /* SPI1: set cs timing to normal */ - psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM); - psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM); - - /* SPI0: set spi0 clock mode */ - /* SPI0: set spi0 flash/cache cs timing */ - psram_set_clk_mode(_SPI_CACHE_PORT, clk_mode); - psram_set_spi0_cache_cs_timing(clk_mode); - - // SPI0: init SPI commands for Cache - psram_cache_init(mode, vaddrmode); + //Configure SPI0 PSRAM related SPI Phases + config_psram_spi_phases(); + //Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly + spi_timing_enter_mspi_high_speed_mode(true); return ESP_OK; } -static void IRAM_ATTR psram_clock_set(int spi_num, int8_t freqdiv) +//Configure PSRAM SPI0 phase related registers here according to the PSRAM chip requirement +static void IRAM_ATTR config_psram_spi_phases(void) { - uint32_t freqbits; - if (1 >= freqdiv) { - WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); - } else { - freqbits = (((freqdiv-1)< 0); if (freqdiv == 1) { @@ -76,7 +86,43 @@ void IRAM_ATTR spi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqd } } -void IRAM_ATTR spi_timing_config_flash_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num) +void spi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv) +{ + if (freqdiv == 1) { + WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); + } else { + uint32_t freqbits = (((freqdiv-1)< 0) { SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M); SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, @@ -101,20 +148,50 @@ void IRAM_ATTR spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0, SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); } -} - -//-------------------------------------PSRAM timing tuning-------------------------------------// -void IRAM_ATTR spi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv) -{ - if (freqdiv == 1) { - WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); - } else { - uint32_t freqbits = (((freqdiv-1)< 0) { SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M); SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, @@ -139,10 +217,14 @@ void IRAM_ATTR spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0, SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); } +#elif CONFIG_SPIRAM_MODE_QUAD + SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(spi_num), SPI_MEM_USR_RD_SRAM_DUMMY_M); + SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(spi_num), SPI_MEM_SRAM_RDUMMY_CYCLELEN_V, (QPI_PSRAM_FAST_READ_DUMMY + extra_dummy - 1), SPI_MEM_SRAM_RDUMMY_CYCLELEN_S); +#endif } //-------------------------------------------FLASH/PSRAM Read/Write------------------------------------------// -void IRAM_ATTR spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +void spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { #if CONFIG_ESPTOOLPY_OCT_FLASH // note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state. @@ -153,27 +235,34 @@ void IRAM_ATTR spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, } esp_rom_opiflash_read_raw(addr, buf, len); #else - abort(); + esp_rom_spiflash_read(addr, (uint32_t *)buf, len); #endif } -static void IRAM_ATTR s_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +static void s_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { #if CONFIG_SPIRAM_MODE_OCT esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_OPI_DTR_MODE, OPI_PSRAM_SYNC_WRITE, 16, addr, 32, OCT_PSRAM_WR_DUMMY_NUM, - buf, 8 * len, + buf, len * 8, NULL, 0, BIT(1), false); -#else - abort(); +#elif CONFIG_SPIRAM_MODE_QUAD + psram_exec_cmd(spi_num, 0, + QPI_PSRAM_WRITE, 8, + addr, 24, + 0, + buf, len * 8, + NULL, 0, + SPI_MEM_CS1_DIS_M, + false); #endif } -static void IRAM_ATTR s_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +static void s_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { #if CONFIG_SPIRAM_MODE_OCT for (int i = 0; i < 16; i++) { @@ -184,15 +273,22 @@ static void IRAM_ATTR s_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, 32, OCT_PSRAM_RD_DUMMY_NUM, NULL, 0, - buf, 8 * len, + buf, len * 8, BIT(1), false); -#else - abort(); +#elif CONFIG_SPIRAM_MODE_QUAD + psram_exec_cmd(spi_num, 0, + QPI_PSRAM_FAST_READ, 8, + addr, 24, + QPI_PSRAM_FAST_READ_DUMMY + s_psram_extra_dummy, + NULL, 0, + buf, len * 8, + SPI_MEM_CS1_DIS_M, + false); #endif } -static void IRAM_ATTR s_psram_execution(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len, bool is_read) +static void s_psram_execution(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len, bool is_read) { while (len) { uint32_t length = MIN(len, 32); @@ -207,14 +303,58 @@ static void IRAM_ATTR s_psram_execution(uint8_t spi_num, uint8_t *buf, uint32_t } } -void IRAM_ATTR spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +void spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { s_psram_execution(spi_num, buf, addr, len, false); } -void IRAM_ATTR spi_timing_config_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +void spi_timing_config_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { s_psram_execution(spi_num, buf, addr, len, true); } + +/*------------------------------------------------------------------------------------------------- + * SPI1 Timing Tuning APIs + * These APIs are only used in `spi_flash_timing_tuning.c/sweep_for_success_sample_points()` for + * configuring SPI1 timing tuning related registers to find best tuning parameter + *-------------------------------------------------------------------------------------------------*/ +void spi_timing_config_flash_tune_din_num_mode(uint8_t din_mode, uint8_t din_num) +{ + /** + * 1. SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless + * SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning + * 2. We use SPI1 to get the best Flash timing tuning (mode and num) config + */ + spi_timing_config_flash_set_din_mode_num(0, din_mode, din_num); +} + +void spi_timing_config_flash_tune_dummy(uint8_t extra_dummy) +{ + spi_timing_config_flash_set_extra_dummy(1, extra_dummy); +} + +void spi_timing_config_psram_tune_din_num_mode(uint8_t din_mode, uint8_t din_num) +{ + /** + * 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless + * SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning + * 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config + */ + spi_timing_config_psram_set_din_mode_num(0, din_mode, din_num); +} + +void spi_timing_config_psram_tune_dummy(uint8_t extra_dummy) +{ +#if CONFIG_SPIRAM_MODE_OCT + //On 728, for SPI1, flash and psram share the extra dummy register + spi_timing_config_flash_set_extra_dummy(1, extra_dummy); +#elif CONFIG_SPIRAM_MODE_QUAD + //Update this `s_psram_extra_dummy`, the `s_psram_read_data` will set dummy according to this `s_psram_extra_dummy` + s_psram_extra_dummy = extra_dummy; + SET_PERI_REG_MASK(SPI_MEM_USER_REG(1), SPI_MEM_USR_DUMMY); // dummy en + SET_PERI_REG_BITS(SPI_MEM_USER1_REG(1), SPI_MEM_USR_DUMMY_CYCLELEN_V, extra_dummy - 1, SPI_MEM_USR_DUMMY_CYCLELEN_S); +#endif +} + #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING diff --git a/components/spi_flash/esp32s3/spi_timing_config.h b/components/spi_flash/esp32s3/spi_timing_config.h index 6883c28c18..404b51f46c 100644 --- a/components/spi_flash/esp32s3/spi_timing_config.h +++ b/components/spi_flash/esp32s3/spi_timing_config.h @@ -18,81 +18,163 @@ extern "C" { #define SPI_TIMING_CONFIG_NUM_DEFAULT 20 //This should be larger than the max available timing config num #define SPI_TIMING_TEST_DATA_LEN 64 - #define SPI_TIMING_PSRAM_TEST_DATA_ADDR 0 #define SPI_TIMING_FLASH_TEST_DATA_ADDR ESP_BOOTLOADER_OFFSET +/** + * @note BACKGOURND: + * + * The SPI FLASH module clock and SPI PSRAM module clock is divided from the SPI core clock, core clock is from system clock: + * + * PLL ----| |---- FLASH Module Clock + * XTAL ----|----> Core Clock ---->| + * RTC8M ----| |---- PSRAM Module Clock + * + * + * DDR stands for double data rate, MSPI samples at both posedge and negedge. So the real spped will be doubled. + * Speed from high to low: 120M DDR > 80M DDR > 120 SDR > 80M SDR > ... + * + * Module with speed lower than 120M SDR doesn't need to be tuned + * + * @note LIMITATION: + * How to determine the core clock on 728. There are 2 limitations. + * + * 1. MSPI FLASH and PSRAM share the core clock register. Therefore: + * SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ == SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ + * + * 2. DDR mode requires the core clock divider (core_clk / div = module_clk) to be power of 2. + */ +//--------------------------------------FLASH Sampling Mode --------------------------------------// +#define SPI_TIMING_FLASH_DTR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_DTR) +#define SPI_TIMING_FLASH_STR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR || !CONFIG_ESPTOOLPY_OCT_FLASH) +//--------------------------------------FLASH Module Clock --------------------------------------// +#if CONFIG_ESPTOOLPY_FLASHFREQ_20M +#define SPI_TIMING_FLASH_MODULE_CLOCK 20 +#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M +#define SPI_TIMING_FLASH_MODULE_CLOCK 40 +#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M +#define SPI_TIMING_FLASH_MODULE_CLOCK 80 +#else //CONFIG_ESPTOOLPY_FLASHFREQ_120M +#define SPI_TIMING_FLASH_MODULE_CLOCK 120 +#endif +//------------------------------------FLASH Needs Tuning or not-------------------------------------// +#if SPI_TIMING_FLASH_DTR_MODE +#define SPI_TIMING_FLASH_NEEDS_TUNING (SPI_TIMING_FLASH_MODULE_CLOCK > 40) +#elif SPI_TIMING_FLASH_STR_MODE +#define SPI_TIMING_FLASH_NEEDS_TUNING (SPI_TIMING_FLASH_MODULE_CLOCK > 80) +#endif -//-------------------------------------------FLASH Operation Mode and Corresponding Timing Tuning Parameter Table --------------------------------------// -#define SPI_TIMING_FLASH_DTR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_DTR) -#define SPI_TIMING_FLASH_STR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR || !CONFIG_ESPTOOLPY_OCT_FLASH) +//--------------------------------------PSRAM Sampling Mode --------------------------------------// +#define SPI_TIMING_PSRAM_DTR_MODE CONFIG_SPIRAM_MODE_OCT +#define SPI_TIMING_PSRAM_STR_MODE !CONFIG_SPIRAM_MODE_OCT +//--------------------------------------PSRAM Module Clock --------------------------------------// +#if CONFIG_ESP32S3_SPIRAM_SUPPORT +#if CONFIG_SPIRAM_SPEED_40M +#define SPI_TIMING_PSRAM_MODULE_CLOCK 40 +#elif CONFIG_SPIRAM_SPEED_80M +#define SPI_TIMING_PSRAM_MODULE_CLOCK 80 +#else //CONFIG_SPIRAM_SPEED_120M +#define SPI_TIMING_PSRAM_MODULE_CLOCK 120 +#endif +#else //Disable PSRAM +#define SPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz, because we rely on `SPI_TIMING_PSRAM_MODULE_CLOCK` macro for calculation and check below, see `Determine the Core Clock` chapter +#endif +//------------------------------------PSRAM Needs Tuning or not-------------------------------------// +#if SPI_TIMING_PSRAM_DTR_MODE +#define SPI_TIMING_PSRAM_NEEDS_TUNING (SPI_TIMING_PSRAM_MODULE_CLOCK > 40) +#elif SPI_TIMING_PSRAM_STR_MODE +#define SPI_TIMING_PSRAM_NEEDS_TUNING (SPI_TIMING_PSRAM_MODULE_CLOCK > 80) +#endif -/* Determine A feasible core clock below: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ and SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ*/ -//OCTAL FLASH -#if CONFIG_ESPTOOLPY_OCT_FLASH -//OCT FLASH 80M DTR +/** + * @note Define A feasible core clock below: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ and SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ + */ +/** + * Due to MSPI core clock is used by both MSPI Flash and PSRAM clock, + * define the STR/DTR mode here for selecting the core clock: + * @note If either Flash or PSRAM, or both of them are set to DTR mode, then we use DIV 2 + */ +#if (SPI_TIMING_FLASH_DTR_MODE || SPI_TIMING_PSRAM_DTR_MODE) +#define SPI_TIMING_CORE_CLOCK_DIV 2 +#else //#if (SPI_TIMING_FLASH_STR_MODE && (SPI_TIMING_PSRAM_STR_MODE || !CONFIG_ESP32S3_SPIRAM_SUPPORT)) +#define SPI_TIMING_CORE_CLOCK_DIV 1 +#endif + +///////////////////////////////////// FLASH CORE CLOCK ///////////////////////////////////// +//FLASH 80M DTR #if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 #endif -//OCT FLASH 120M DTR +//FLASH 120M DTR #if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 #endif -//OCT FLASH 120M STR +//FLASH 120M STR #if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 +#if (SPI_TIMING_CORE_CLOCK_DIV == 2) +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 +#elif (SPI_TIMING_CORE_CLOCK_DIV == 1) +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 120 #endif +#endif //FLASH 120M STR -#endif //#if CONFIG_ESPTOOLPY_OCT_FLASH -/* QUAD FLASH Operation Mode should be added here if needed */ - - -//---------------------------------------PSRAM Operation Mode and Corresponding Timing Tuning Parameter Table--------------------------------------// -#define SPI_TIMING_PSRAM_DTR_MODE 1 //Currently we only support DTR Octal PSRAM -#define SPI_TIMING_PSRAM_STR_MODE 0 - -//OCTAL PSRAM -#if CONFIG_SPIRAM_MODE_OCT - -//OCT 80M PSRAM +///////////////////////////////////// PSRAM CORE CLOCK ///////////////////////////////////// +//PSRAM 80M DTR #if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_80M -#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 160 +#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 160 #endif -#endif //#if CONFIG_SPIRAM_MODE_OCT -/* QUAD PSRAM Operation Mode should be added here if needed */ - - -//------------------------------------------Get the timing tuning config-----------------------------------------------// -#ifdef SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -//FLASH needs tuning, and it expects this core clock: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -#define SPI_TIMING_FLASH_NEEDS_TUNING 1 +//PSRAM 120M STR +#if SPI_TIMING_PSRAM_STR_MODE && CONFIG_SPIRAM_SPEED_120M +#if (SPI_TIMING_CORE_CLOCK_DIV == 2) +#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 240 +#elif (SPI_TIMING_CORE_CLOCK_DIV == 1) +#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 120 #endif +#endif //PSRAM 120M STR -#ifdef SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ -//PSRAM needs tuning, and it expects this core clock: SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ -#define SPI_TIMING_PSRAM_NEEDS_TUNING 1 -#endif -//If both FLASH and PSRAM need tuning, the core clock should be same +//------------------------------------------Determine the Core Clock-----------------------------------------------// +/** + * @note + * Limitation 1: + * On 728, MSPI FLASH and PSRAM share the core clock register. Therefore, + * the expected CORE CLOCK frequencies should be the same. + */ #if SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING _Static_assert(SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ == SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ, "FLASH and PSRAM Mode configuration are not supported"); -#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ +#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -//If only FLASH needs tuning, the core clock could be as FLASH expected +//If only FLASH needs tuning, the core clock COULD be as FLASH expected #elif SPI_TIMING_FLASH_NEEDS_TUNING && !SPI_TIMING_PSRAM_NEEDS_TUNING -#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ +_Static_assert(SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ % SPI_TIMING_PSRAM_MODULE_CLOCK == 0, "FLASH and PSRAM Mode configuration are not supported"); +#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -//If only PSRAM needs tuning, the core clock could be as PSRAM expected +//If only PSRAM needs tuning, the core clock COULD be as PSRAM expected #elif !SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING -#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ +_Static_assert(SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ % SPI_TIMING_FLASH_MODULE_CLOCK == 0, "FLASH and PSRAM Mode configuration are not supported"); +#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ #else #define SPI_TIMING_CORE_CLOCK_MHZ 80 #endif +/** + * @note + * Limitation 2: DDR mode requires the core clock divider (core_clk / div = module_clk) to be power of 2. + */ +#define CHECK_POWER_OF_2(n) ((((n) & ((~(n)) + 1))) == (n)) + +#if SPI_TIMING_FLASH_DTR_MODE +_Static_assert(CHECK_POWER_OF_2(SPI_TIMING_CORE_CLOCK_MHZ / SPI_TIMING_FLASH_MODULE_CLOCK), "FLASH and PSRAM Mode configuration are not supported"); +#endif +#if SPI_TIMING_PSRAM_DTR_MODE +_Static_assert(CHECK_POWER_OF_2(SPI_TIMING_CORE_CLOCK_MHZ / SPI_TIMING_PSRAM_MODULE_CLOCK), "FLASH and PSRAM Mode configuration are not supported"); +#endif + + //------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------// #define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \ (spi_timing_config_t) { .tuning_config_table = MSPI_TIMING_##type##_CONFIG_TABLE_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \ @@ -151,6 +233,15 @@ void spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t extra_dumm void spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len); void spi_timing_config_psram_read_data(uint8_t spi_num,uint8_t *buf, uint32_t addr, uint32_t len); +/*------------------------------------------------------------------------------------------------- + * SPI1 Timing Tuning APIs + * These APIs are only used in `spi_flash_timing_tuning.c/sweep_for_success_sample_points()` for + * configuring SPI1 timing tuning related registers to find best tuning parameter + *-------------------------------------------------------------------------------------------------*/ +void spi_timing_config_flash_tune_din_num_mode(uint8_t din_mode, uint8_t din_num); +void spi_timing_config_flash_tune_dummy(uint8_t extra_dummy); +void spi_timing_config_psram_tune_din_num_mode(uint8_t din_mode, uint8_t din_num); +void spi_timing_config_psram_tune_dummy(uint8_t extra_dummy); #ifdef __cplusplus } #endif diff --git a/components/spi_flash/include/spi_flash_private.h b/components/spi_flash/include/spi_flash_private.h index 7435359f3e..1a8ad6f231 100644 --- a/components/spi_flash/include/spi_flash_private.h +++ b/components/spi_flash/include/spi_flash_private.h @@ -31,6 +31,18 @@ extern "C" { #endif +/** + * This struct provide MSPI Flash necessary timing related config + */ +typedef struct { + uint8_t flash_clk_div; /*!< clock divider of Flash module. */ + uint8_t flash_extra_dummy; /*!< timing required extra dummy length for Flash */ + bool flash_setup_en; /*!< SPI0/1 Flash setup enable or not */ + uint8_t flash_setup_time; /*!< SPI0/1 Flash setup time. This value should be set to register directly */ + bool flash_hold_en; /*!< SPI0/1 Flash hold enable or not */ + uint8_t flash_hold_time; /*!< SPI0/1 Flash hold time. This value should be set to register directly */ +} spi_timing_flash_config_t; + /** * @brief Register ROM functions and init flash device registers to make use of octal flash */ @@ -38,13 +50,15 @@ esp_err_t esp_opiflash_init(void); /** * @brief Make MSPI work under 20Mhz + * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 */ -void spi_timing_enter_mspi_low_speed_mode(void); +void spi_timing_enter_mspi_low_speed_mode(bool control_spi1); /** * @brief Make MSPI work under the frequency as users set + * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 */ -void spi_timing_enter_mspi_high_speed_mode(void); +void spi_timing_enter_mspi_high_speed_mode(bool control_spi1); /** * @brief Tune MSPI flash timing to make it work under high frequency @@ -67,6 +81,12 @@ void esp_mspi_pin_init(void); */ void spi_flash_set_rom_required_regs(void); +/** + * @brief Get MSPI Flash necessary timing related config + * @param config see `spi_timing_flash_config_t` + */ +void spi_timing_get_flash_regs(spi_timing_flash_config_t *config); + #ifdef __cplusplus } #endif diff --git a/components/spi_flash/linker.lf b/components/spi_flash/linker.lf index ae285a1c2c..ee60692de1 100644 --- a/components/spi_flash/linker.lf +++ b/components/spi_flash/linker.lf @@ -14,6 +14,7 @@ entries: if IDF_TARGET_ESP32S3 = y: spi_flash_timing_tuning (noflash) + spi_timing_config (noflash) if IDF_TARGET_ESP32S3 = y && ESPTOOLPY_OCT_FLASH = y: spi_flash_oct_flash_init (noflash) diff --git a/components/spi_flash/spi_flash_timing_tuning.c b/components/spi_flash/spi_flash_timing_tuning.c index 03e055ffcc..0c46788e0a 100644 --- a/components/spi_flash/spi_flash_timing_tuning.c +++ b/components/spi_flash/spi_flash_timing_tuning.c @@ -20,6 +20,12 @@ #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr))) +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING +const static char *TAG = "MSPI Timing"; +static spi_timing_tuning_param_t s_flash_best_timing_tuning_config; +static spi_timing_tuning_param_t s_psram_best_timing_tuning_config; +#endif + /*------------------------------------------------------------------------------ * Common settings *----------------------------------------------------------------------------*/ @@ -41,11 +47,6 @@ void spi_timing_set_pin_drive_strength(void) } } -#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -static char *TAG = "MSPI Timing"; -static spi_timing_tuning_param_t s_flash_best_timing_tuning_config; -static spi_timing_tuning_param_t s_psram_best_timing_tuning_config; - /*------------------------------------------------------------------------------ * Static functions to get clock configs *----------------------------------------------------------------------------*/ @@ -75,12 +76,15 @@ static uint32_t get_psram_clock_divider(void) return SPI_TIMING_CORE_CLOCK_MHZ / 40; #elif CONFIG_SPIRAM_SPEED_80M return SPI_TIMING_CORE_CLOCK_MHZ / 80; +#elif CONFIG_SPIRAM_SPEED_120M + return SPI_TIMING_CORE_CLOCK_MHZ / 120; #else //Will enter this branch only if PSRAM is not enable return 0; #endif } +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING /*------------------------------------------------------------------------------ * Static functions to do timing tuning *----------------------------------------------------------------------------*/ @@ -121,25 +125,15 @@ static void sweep_for_success_sample_points(uint8_t *reference_data, const spi_t memset(read_data, 0, SPI_TIMING_TEST_DATA_LEN); #if SPI_TIMING_FLASH_NEEDS_TUNING if (is_flash) { - /** - * 1. SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless - * SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning - * 2. We use SPI1 to get the best Flash timing tuning (mode and num) config - */ - spi_timing_config_flash_set_din_mode_num(0, config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); - spi_timing_config_flash_set_extra_dummy(1, config->tuning_config_table[config_idx].extra_dummy_len); + spi_timing_config_flash_tune_din_num_mode(config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); + spi_timing_config_flash_tune_dummy(config->tuning_config_table[config_idx].extra_dummy_len); spi_timing_config_flash_read_data(1, read_data, SPI_TIMING_FLASH_TEST_DATA_ADDR, sizeof(read_data)); } #endif #if SPI_TIMING_PSRAM_NEEDS_TUNING if (!is_flash) { - /** - * 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless - * SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning - * 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config - */ - spi_timing_config_psram_set_din_mode_num(0, config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); - spi_timing_config_flash_set_extra_dummy(1, config->tuning_config_table[config_idx].extra_dummy_len); + spi_timing_config_psram_tune_din_num_mode(config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); + spi_timing_config_psram_tune_dummy(config->tuning_config_table[config_idx].extra_dummy_len); spi_timing_config_psram_read_data(1, read_data, SPI_TIMING_PSRAM_TEST_DATA_ADDR, SPI_TIMING_TEST_DATA_LEN); } #endif @@ -304,9 +298,9 @@ void spi_timing_flash_tuning(void) ESP_EARLY_LOGW("FLASH", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version."); /** * set SPI01 related regs to 20mhz configuration, to get reference data from FLASH - * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode) + * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode`) */ - spi_timing_enter_mspi_low_speed_mode(); + spi_timing_enter_mspi_low_speed_mode(true); //Disable the variable dummy mode when doing timing tuning CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); //GD flash will read error in variable mode with 20MHz @@ -317,7 +311,7 @@ void spi_timing_flash_tuning(void) get_flash_tuning_configs(&timing_configs); do_tuning(reference_data, &timing_configs, true); - spi_timing_enter_mspi_high_speed_mode(); + spi_timing_enter_mspi_high_speed_mode(true); } #else void spi_timing_flash_tuning(void) @@ -343,6 +337,8 @@ static void get_psram_tuning_configs(spi_timing_config_t *config) *config = SPI_TIMING_PSRAM_GET_TUNING_CONFIG(SPI_TIMING_CORE_CLOCK_MHZ, 40, PSRAM_MODE); #elif CONFIG_SPIRAM_SPEED_80M *config = SPI_TIMING_PSRAM_GET_TUNING_CONFIG(SPI_TIMING_CORE_CLOCK_MHZ, 80, PSRAM_MODE); +#elif CONFIG_SPIRAM_SPEED_120M + *config = SPI_TIMING_PSRAM_GET_TUNING_CONFIG(SPI_TIMING_CORE_CLOCK_MHZ, 120, PSRAM_MODE); #endif #undef PSRAM_MODE @@ -353,9 +349,9 @@ void spi_timing_psram_tuning(void) ESP_EARLY_LOGW("PSRAM", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version."); /** * set SPI01 related regs to 20mhz configuration, to write reference data to PSRAM - * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode) + * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode`) */ - spi_timing_enter_mspi_low_speed_mode(); + spi_timing_enter_mspi_low_speed_mode(true); // write data into psram, used to do timing tuning test. uint8_t reference_data[SPI_TIMING_TEST_DATA_LEN]; @@ -370,7 +366,7 @@ void spi_timing_psram_tuning(void) CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); //Get required config, and set them to PSRAM related registers do_tuning(reference_data, &timing_configs, false); - spi_timing_enter_mspi_high_speed_mode(); + spi_timing_enter_mspi_high_speed_mode(true); } #else @@ -381,20 +377,23 @@ void spi_timing_psram_tuning(void) #endif //SPI_TIMING_PSRAM_NEEDS_TUNING /*------------------------------------------------------------------------------ - * APIs to make SPI0 and SPI1 FLASH work for high/low freq + * APIs to make SPI0 (and SPI1) FLASH work for high/low freq *----------------------------------------------------------------------------*/ #if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -static void clear_timing_tuning_regs(void) +static void clear_timing_tuning_regs(bool control_spi1) { spi_timing_config_flash_set_din_mode_num(0, 0, 0); //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg spi_timing_config_flash_set_extra_dummy(0, 0); - spi_timing_config_flash_set_extra_dummy(1, 0); + if (control_spi1) { + spi_timing_config_flash_set_extra_dummy(1, 0); + } else { + //Won't touch SPI1 registers + } } #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -void spi_timing_enter_mspi_low_speed_mode(void) +void spi_timing_enter_mspi_low_speed_mode(bool control_spi1) { -#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING /** * Here we are going to slow the SPI1 frequency to 20Mhz, so we need to set SPI1 din_num and din_mode regs. * @@ -406,22 +405,26 @@ void spi_timing_enter_mspi_low_speed_mode(void) //Switch SPI1 and SPI0 clock as 20MHz, set its SPIMEM core clock as 80M and set clock division as 4 spi_timing_config_set_core_clock(0, SPI_TIMING_CONFIG_CORE_CLOCK_80M); //SPI0 and SPI1 share the register for core clock. So we only set SPI0 here. - spi_timing_config_set_flash_clock(1, 4); spi_timing_config_set_flash_clock(0, 4); + if (control_spi1) { + //After tuning, won't touch SPI1 again + spi_timing_config_set_flash_clock(1, 4); + } - clear_timing_tuning_regs(); -#else - //Empty function for compatibility, therefore upper layer won't need to know that FLASH in which operation mode and frequency config needs to be tuned +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING + clear_timing_tuning_regs(control_spi1); #endif } #if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -static void set_timing_tuning_regs_as_required(void) +static void set_timing_tuning_regs_as_required(bool control_spi1) { //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg spi_timing_config_flash_set_din_mode_num(0, s_flash_best_timing_tuning_config.spi_din_mode, s_flash_best_timing_tuning_config.spi_din_num); spi_timing_config_flash_set_extra_dummy(0, s_flash_best_timing_tuning_config.extra_dummy_len); - spi_timing_config_flash_set_extra_dummy(1, s_flash_best_timing_tuning_config.extra_dummy_len); + if (control_spi1) { + spi_timing_config_flash_set_extra_dummy(1, s_flash_best_timing_tuning_config.extra_dummy_len); + } spi_timing_config_psram_set_din_mode_num(0, s_psram_best_timing_tuning_config.spi_din_mode, s_psram_best_timing_tuning_config.spi_din_num); spi_timing_config_psram_set_extra_dummy(0, s_psram_best_timing_tuning_config.extra_dummy_len); @@ -429,14 +432,14 @@ static void set_timing_tuning_regs_as_required(void) #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING /** - * Set SPI0 and SPI1 flash module clock, din_num, din_mode and extra dummy, + * Set SPI0 FLASH and PSRAM module clock, din_num, din_mode and extra dummy, * according to the configuration got from timing tuning function (`calculate_best_flash_tuning_config`). + * iF control_spi1 == 1, will also update SPI1 timing registers. Should only be set to 1 when do tuning. * * This function should always be called after `spi_timing_flash_tuning` or `calculate_best_flash_tuning_config` */ -void spi_timing_enter_mspi_high_speed_mode(void) +void spi_timing_enter_mspi_high_speed_mode(bool control_spi1) { -#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING spi_timing_config_core_clock_t core_clock = get_mspi_core_clock(); uint32_t flash_div = get_flash_clock_divider(); uint32_t psram_div = get_psram_clock_divider(); @@ -445,12 +448,31 @@ void spi_timing_enter_mspi_high_speed_mode(void) spi_timing_config_set_core_clock(0, core_clock); //SPI0 and SPI1 share the register for core clock. So we only set SPI0 here. //Set FLASH module clock spi_timing_config_set_flash_clock(0, flash_div); - spi_timing_config_set_flash_clock(1, flash_div); + if (control_spi1) { + spi_timing_config_set_flash_clock(1, flash_div); + } //Set PSRAM module clock spi_timing_config_set_psram_clock(0, psram_div); - set_timing_tuning_regs_as_required(); -#else - //Empty function for compatibility, therefore upper layer won't need to know that FLASH in which operation mode and frequency config needs to be tuned +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING + set_timing_tuning_regs_as_required(true); #endif } + +/** + * Should be only used by SPI1 Flash driver to know the necessary timing registers + */ +void spi_timing_get_flash_regs(spi_timing_flash_config_t *config) +{ + config->flash_clk_div = get_flash_clock_divider(); +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING + config->flash_extra_dummy = s_flash_best_timing_tuning_config.extra_dummy_len; +#else + config->flash_extra_dummy = 0; +#endif + config->flash_setup_en = REG_GET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_CS_SETUP); + config->flash_setup_time = REG_GET_FIELD(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME); + + config->flash_hold_en = REG_GET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD); + config->flash_hold_time = REG_GET_FIELD(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME); +} From a06357ab62e479ee29eab4cad134b9a2fc43f65c Mon Sep 17 00:00:00 2001 From: Suren Gabrielyan Date: Fri, 2 Jul 2021 08:58:47 +0400 Subject: [PATCH 093/310] examples: Asio tests consolidation to use loopback interface Closes IDF-3072 --- .../{chat_client => asio_chat}/CMakeLists.txt | 2 +- .../asio/{chat_server => asio_chat}/Makefile | 2 +- examples/protocols/asio/asio_chat/README.md | 62 ++++++ .../protocols/asio/asio_chat/example_test.py | 29 +++ .../asio/asio_chat/main/CMakeLists.txt | 2 + .../asio/asio_chat/main/Kconfig.projbuild | 39 ++++ .../asio/asio_chat/main/asio_chat.cpp | 119 ++++++++++++ .../main/chat_message.hpp | 0 .../protocols/asio/asio_chat/main/client.hpp | 126 ++++++++++++ .../main/component.mk | 0 .../main/server.hpp} | 169 +++++++--------- .../protocols/asio/asio_chat/sdkconfig.ci | 6 + .../asio/asio_chat/sdkconfig.defaults | 2 + examples/protocols/asio/chat_client/Makefile | 9 - examples/protocols/asio/chat_client/README.md | 20 -- .../asio/chat_client/asio_chat_client_test.py | 94 --------- .../asio/chat_client/main/CMakeLists.txt | 2 - .../asio/chat_client/main/Kconfig.projbuild | 16 -- .../asio/chat_client/main/chat_client.cpp | 183 ------------------ .../asio/chat_client/sdkconfig.defaults | 7 - .../protocols/asio/chat_server/CMakeLists.txt | 10 - examples/protocols/asio/chat_server/README.md | 23 --- .../asio/chat_server/asio_chat_server_test.py | 44 ----- .../asio/chat_server/main/CMakeLists.txt | 2 - .../asio/chat_server/main/Kconfig.projbuild | 9 - .../asio/chat_server/main/chat_message.hpp | 91 --------- .../asio/chat_server/main/component.mk | 8 - .../asio/chat_server/sdkconfig.defaults | 7 - 28 files changed, 457 insertions(+), 626 deletions(-) rename examples/protocols/asio/{chat_client => asio_chat}/CMakeLists.txt (94%) rename examples/protocols/asio/{chat_server => asio_chat}/Makefile (87%) create mode 100644 examples/protocols/asio/asio_chat/README.md create mode 100644 examples/protocols/asio/asio_chat/example_test.py create mode 100644 examples/protocols/asio/asio_chat/main/CMakeLists.txt create mode 100644 examples/protocols/asio/asio_chat/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/asio_chat/main/asio_chat.cpp rename examples/protocols/asio/{chat_client => asio_chat}/main/chat_message.hpp (100%) create mode 100644 examples/protocols/asio/asio_chat/main/client.hpp rename examples/protocols/asio/{chat_client => asio_chat}/main/component.mk (100%) rename examples/protocols/asio/{chat_server/main/chat_server.cpp => asio_chat/main/server.hpp} (52%) create mode 100644 examples/protocols/asio/asio_chat/sdkconfig.ci create mode 100644 examples/protocols/asio/asio_chat/sdkconfig.defaults delete mode 100644 examples/protocols/asio/chat_client/Makefile delete mode 100644 examples/protocols/asio/chat_client/README.md delete mode 100644 examples/protocols/asio/chat_client/asio_chat_client_test.py delete mode 100644 examples/protocols/asio/chat_client/main/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_client/main/Kconfig.projbuild delete mode 100644 examples/protocols/asio/chat_client/main/chat_client.cpp delete mode 100644 examples/protocols/asio/chat_client/sdkconfig.defaults delete mode 100644 examples/protocols/asio/chat_server/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_server/README.md delete mode 100644 examples/protocols/asio/chat_server/asio_chat_server_test.py delete mode 100644 examples/protocols/asio/chat_server/main/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_server/main/Kconfig.projbuild delete mode 100644 examples/protocols/asio/chat_server/main/chat_message.hpp delete mode 100644 examples/protocols/asio/chat_server/main/component.mk delete mode 100644 examples/protocols/asio/chat_server/sdkconfig.defaults diff --git a/examples/protocols/asio/chat_client/CMakeLists.txt b/examples/protocols/asio/asio_chat/CMakeLists.txt similarity index 94% rename from examples/protocols/asio/chat_client/CMakeLists.txt rename to examples/protocols/asio/asio_chat/CMakeLists.txt index ddcc068ba8..483b43d703 100644 --- a/examples/protocols/asio/chat_client/CMakeLists.txt +++ b/examples/protocols/asio/asio_chat/CMakeLists.txt @@ -7,4 +7,4 @@ cmake_minimum_required(VERSION 3.5) set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(asio_chat_client) +project(asio_chat) diff --git a/examples/protocols/asio/chat_server/Makefile b/examples/protocols/asio/asio_chat/Makefile similarity index 87% rename from examples/protocols/asio/chat_server/Makefile rename to examples/protocols/asio/asio_chat/Makefile index a7656889fd..93950cb9a9 100644 --- a/examples/protocols/asio/chat_server/Makefile +++ b/examples/protocols/asio/asio_chat/Makefile @@ -2,7 +2,7 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -PROJECT_NAME := asio_chat_server +PROJECT_NAME := asio_chat EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common diff --git a/examples/protocols/asio/asio_chat/README.md b/examples/protocols/asio/asio_chat/README.md new file mode 100644 index 0000000000..4848b457b8 --- /dev/null +++ b/examples/protocols/asio/asio_chat/README.md @@ -0,0 +1,62 @@ + +# Asio chat client and server examples + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +The application aims to demonstrate a simple use of Asio library in different modes. +In project settings it could be configured to run either a Asio chat server, a Asio chat client, or both. + +## How to use example + +The example is configured by default as an Asio chat client. + +Note that the example uses string representation of IP addresses and ports. + +You can find the upstream asio chat implementation [here] https://github.com/chriskohlhoff/asio/tree/master/asio/src/examples/cpp11/chat + +### Asio Client + +In the client mode, the example connects to the configured address, sends the message, which was inserted as an input in the terminal, and receives a response. + +### Asio Server + +In the server mode, Asio chat server with a specified port number is created and being polled till a connection request from the client arrives. +Chat server echoes a message (received from any client) to all connected clients. + +## Configure the project + +``` +idf.py menuconfig +``` + +Set following parameters under Example Configuration Options: + +* Set `EXAMPLE_CHAT_SERVER` to use the example as an ASIO chat server + * Configure `EXAMPLE_CHAT_SERVER_BIND_PORT` to the port number. + +* Set `EXAMPLE_CHAT_CLIENT` to use the example as an ASIO chat client + * Configure `EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS` to a string representation of the address to connect the client to. + * Configure `EXAMPLE_CHAT_CLIENT_CONNECT_PORT` to the port number. + +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more d etails. + +## Running the example in server mode + +- Configure the example according "Configure the project" section. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet (note the IP address). +- Connect to the server using multiple clients, for example using any option below. + - build and run asio chat client on your host machine + - run chat_client asio example on ESP platform + - since chat messages consists of ASCII size and message, it is possible to + netcat `nc IP PORT` and type for example ` 4ABC` to transmit 'ABC\n' + +## Running the example in client mode + +- Configure the example according "Configure the project" section. +- Start chat server either on host machine or as another ESP device running chat_server example. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet. +- Receive and send messages to/from other clients on stdin/stdout via serial terminal. + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/asio_chat/example_test.py b/examples/protocols/asio/asio_chat/example_test.py new file mode 100644 index 0000000000..7dc5c7c2b7 --- /dev/null +++ b/examples/protocols/asio/asio_chat/example_test.py @@ -0,0 +1,29 @@ +# This example code is in the Public Domain (or CC0 licensed, at your option.) + +# Unless required by applicable law or agreed to in writing, this +# software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. + +# -*- coding: utf-8 -*- + +from __future__ import print_function, unicode_literals + +import re + +import ttfw_idf + + +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC') +def test_examples_asio_chat(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + msg = 'asio-chat: received hi' + dut = env.get_dut('asio_chat', 'examples/protocols/asio/asio_chat') + # start the test and expect the client to receive back it's original data + dut.start_app() + dut.expect(re.compile(r'{}'.format('Waiting for input')), timeout=30) + dut.write(msg) + dut.write('exit') + dut.expect(re.compile(r'{}'.format(msg)), timeout=30) + + +if __name__ == '__main__': + test_examples_asio_chat() diff --git a/examples/protocols/asio/asio_chat/main/CMakeLists.txt b/examples/protocols/asio/asio_chat/main/CMakeLists.txt new file mode 100644 index 0000000000..8f19544237 --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "asio_chat.cpp" + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/asio_chat/main/Kconfig.projbuild b/examples/protocols/asio/asio_chat/main/Kconfig.projbuild new file mode 100644 index 0000000000..99f08cdbd3 --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + config EXAMPLE_CHAT_SERVER + bool "Asio example chat server" + default n + help + This example will setup a chat server, binds it to the specified address + and starts listening. + + if EXAMPLE_CHAT_SERVER + config EXAMPLE_CHAT_SERVER_BIND_PORT + string "Asio example server bind port" + default "3344" + help + Server listener's socket would be bound to this port. + endif + + config EXAMPLE_CHAT_CLIENT + bool "Asio example chat client" + default y + help + This example will setup an asio chat client. + and sends the data. + + if EXAMPLE_CHAT_CLIENT + config EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS + string "Client connection address" + default "192.168.0.1" + help + Client's socket would connect to this address/host. + + config EXAMPLE_CHAT_CLIENT_CONNECT_PORT + string "Client connection port" + default "3344" + help + Client's connection port. + endif + +endmenu diff --git a/examples/protocols/asio/asio_chat/main/asio_chat.cpp b/examples/protocols/asio/asio_chat/main/asio_chat.cpp new file mode 100644 index 0000000000..be2329d151 --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/asio_chat.cpp @@ -0,0 +1,119 @@ +/* ASIO chat server client example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "protocol_examples_common.h" +#include "esp_log.h" +#include "esp_event.h" +#include "nvs_flash.h" +#include "server.hpp" +#include "client.hpp" +#include +#include + +using asio::ip::tcp; + +static const char *TAG = "asio-chat"; + +// This variable is necessary for `python test` execution, it provides synchronisation between server/client(as server should be started before client) +std::mutex server_ready; + +#ifdef CONFIG_EXAMPLE_CHAT_CLIENT +static void get_string(char *line, size_t size) +{ + int count = 0; + while (count < size) { + int c = fgetc(stdin); + if (c == '\n') { + line[count] = '\0'; + break; + } else if (c > 0 && c < 127) { + line[count] = c; + ++count; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + } +} + +void start_client(void) +{ + const std::string port(CONFIG_EXAMPLE_CHAT_CLIENT_CONNECT_PORT); + const std::string name(CONFIG_EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS); + asio::io_context io_context; + char line[128]; + + tcp::resolver resolver(io_context); + auto endpoints = resolver.resolve(name, port); + chat_client c(io_context, endpoints); +#ifdef CONFIG_EXAMPLE_CHAT_SERVER + std::lock_guard guard(server_ready); +#endif + std::thread t([&io_context]() { try { + io_context.run(); + } catch (const std::exception &e) { + ESP_LOGE(TAG, "Exception occured during client thread execution %s", e.what()); + } + catch (...) { + ESP_LOGE(TAG, "Unknown exception"); + }}); + do { + ESP_LOGI(TAG, "CLIENT: Waiting for input"); + get_string(line, sizeof(line)); + + chat_message msg; + msg.body_length(std::strlen(line)); + std::memcpy(msg.body(), line, msg.body_length()); + msg.encode_header(); + c.write(msg); + sleep(1); + } while (strcmp(line, "exit") != 0); + + c.close(); + t.join(); +} +#endif // CONFIG_EXAMPLE_CHAT_CLIENT + +extern "C" void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + esp_netif_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + try { +#ifdef CONFIG_EXAMPLE_CHAT_SERVER + asio::io_context io_context; + chat_server server(io_context, tcp::endpoint(tcp::v4(), std::atoi(CONFIG_EXAMPLE_CHAT_SERVER_BIND_PORT))); + std::thread t = std::thread([&io_context]() { // Chat server starting here + try { + io_context.run(); + } catch (const std::exception &e) { + ESP_LOGE(TAG, "Exception occured during server thread execution %s", e.what()); + } + catch (...) { + ESP_LOGE(TAG, "Unknown exception"); + }});; +#endif +#ifdef CONFIG_EXAMPLE_CHAT_CLIENT + start_client(); +#endif +#ifdef CONFIG_EXAMPLE_CHAT_SERVER + t.join(); +#endif + } catch (const std::exception &e) { + ESP_LOGE(TAG, "Exception occured during run %s", e.what()); + } catch (...) { + ESP_LOGE(TAG, "Unknown exception"); + } + ESP_ERROR_CHECK(example_disconnect()); +} diff --git a/examples/protocols/asio/chat_client/main/chat_message.hpp b/examples/protocols/asio/asio_chat/main/chat_message.hpp similarity index 100% rename from examples/protocols/asio/chat_client/main/chat_message.hpp rename to examples/protocols/asio/asio_chat/main/chat_message.hpp diff --git a/examples/protocols/asio/asio_chat/main/client.hpp b/examples/protocols/asio/asio_chat/main/client.hpp new file mode 100644 index 0000000000..09baece986 --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/client.hpp @@ -0,0 +1,126 @@ +// +// client.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CHAT_CLIENT_HPP +#define CHAT_CLIENT_HPP + +#include +#include "asio.hpp" +#include "chat_message.hpp" + +typedef std::deque chat_message_queue; + +class chat_client +{ +public: + chat_client(asio::io_context& io_context, + const asio::ip::tcp::resolver::results_type& endpoints) + : io_context_(io_context), + socket_(io_context) + { + do_connect(endpoints); + } + + void write(const chat_message& msg) + { + asio::post(io_context_, + [this, msg]() + { + bool write_in_progress = !write_msgs_.empty(); + write_msgs_.push_back(msg); + if (!write_in_progress) + { + do_write(); + } + }); + } + + void close() + { + asio::post(io_context_, [this]() { socket_.close(); }); + } + +private: +void do_connect(const asio::ip::tcp::resolver::results_type& endpoints) + { + asio::async_connect(socket_, endpoints, + [this](std::error_code ec, asio::ip::tcp::endpoint) + { + if (!ec) + { + do_read_header(); + } + }); + } + + void do_read_header() + { + asio::async_read(socket_, + asio::buffer(read_msg_.data(), chat_message::header_length), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec && read_msg_.decode_header()) + { + do_read_body(); + } + else + { + socket_.close(); + } + }); + } + + void do_read_body() + { + asio::async_read(socket_, + asio::buffer(read_msg_.body(), read_msg_.body_length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + do_read_header(); + } + else + { + socket_.close(); + } + }); + } + + void do_write() + { + asio::async_write(socket_, + asio::buffer(write_msgs_.front().data(), + write_msgs_.front().length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + write_msgs_.pop_front(); + if (!write_msgs_.empty()) + { + do_write(); + } + } + else + { + socket_.close(); + } + }); + } + +private: + asio::io_context& io_context_; + asio::ip::tcp::socket socket_; + chat_message read_msg_; + chat_message_queue write_msgs_; +}; + +#endif // CHAT_CLIENT_HPP diff --git a/examples/protocols/asio/chat_client/main/component.mk b/examples/protocols/asio/asio_chat/main/component.mk similarity index 100% rename from examples/protocols/asio/chat_client/main/component.mk rename to examples/protocols/asio/asio_chat/main/component.mk diff --git a/examples/protocols/asio/chat_server/main/chat_server.cpp b/examples/protocols/asio/asio_chat/main/server.hpp similarity index 52% rename from examples/protocols/asio/chat_server/main/chat_server.cpp rename to examples/protocols/asio/asio_chat/main/server.hpp index 6ea7c7be47..450e255a47 100644 --- a/examples/protocols/asio/chat_server/main/chat_server.cpp +++ b/examples/protocols/asio/asio_chat/main/server.hpp @@ -1,5 +1,5 @@ // -// chat_server.cpp +// server.hpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) @@ -8,28 +8,25 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include -#include -#include +#ifndef CHAT_SERVER_HPP +#define CHAT_SERVER_HPP + #include -#include #include +#include #include #include "asio.hpp" #include "chat_message.hpp" -#include "protocol_examples_common.h" -#include "esp_event.h" -#include "nvs_flash.h" - - -using asio::ip::tcp; //---------------------------------------------------------------------- typedef std::deque chat_message_queue; +extern std::mutex server_ready; + //---------------------------------------------------------------------- + class chat_participant { public: @@ -74,12 +71,13 @@ private: //---------------------------------------------------------------------- + class chat_session : public chat_participant, public std::enable_shared_from_this { public: - chat_session(tcp::socket socket, chat_room& room) + chat_session(asio::ip::tcp::socket socket, chat_room& room) : socket_(std::move(socket)), room_(room) { @@ -117,56 +115,57 @@ private: { room_.leave(shared_from_this()); } - }); - } + }); + } - void do_read_body() - { - auto self(shared_from_this()); - asio::async_read(socket_, - asio::buffer(read_msg_.body(), read_msg_.body_length()), - [this, self](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - room_.deliver(read_msg_); - do_read_header(); - } - else - { - room_.leave(shared_from_this()); - } - }); - } + void do_read_body() + { + auto self(shared_from_this()); + asio::async_read(socket_, + asio::buffer(read_msg_.body(), read_msg_.body_length()), + [this, self](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + ESP_LOGD("asio-chat:", "%s", read_msg_.body()); + room_.deliver(read_msg_); + do_read_header(); + } + else + { + room_.leave(shared_from_this()); + } + }); + } - void do_write() - { - auto self(shared_from_this()); - asio::async_write(socket_, - asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - [this, self](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - do_write(); - } - } - else - { - room_.leave(shared_from_this()); - } - }); - } + void do_write() + { + auto self(shared_from_this()); + asio::async_write(socket_, + asio::buffer(write_msgs_.front().data(), + write_msgs_.front().length()), + [this, self](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + write_msgs_.pop_front(); + if (!write_msgs_.empty()) + { + do_write(); + } + } + else + { + room_.leave(shared_from_this()); + } + }); + } - tcp::socket socket_; - chat_room& room_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; + asio::ip::tcp::socket socket_; + chat_room& room_; + chat_message read_msg_; + chat_message_queue write_msgs_; + }; //---------------------------------------------------------------------- @@ -174,7 +173,7 @@ class chat_server { public: chat_server(asio::io_context& io_context, - const tcp::endpoint& endpoint) + const asio::ip::tcp::endpoint& endpoint) : acceptor_(io_context, endpoint) { do_accept(); @@ -183,49 +182,21 @@ public: private: void do_accept() { + std::lock_guard guard(server_ready); acceptor_.async_accept( - [this](std::error_code ec, tcp::socket socket) - { - if (!ec) - { - std::make_shared(std::move(socket), room_)->start(); - } + [this](std::error_code ec, asio::ip::tcp::socket socket) + { + if (!ec) + { + std::make_shared(std::move(socket), room_)->start(); + } - do_accept(); - }); + do_accept(); + }); } - tcp::acceptor acceptor_; + asio::ip::tcp::acceptor acceptor_; chat_room room_; }; -//---------------------------------------------------------------------- - -extern "C" void app_main(void) -{ - ESP_ERROR_CHECK(nvs_flash_init()); - esp_netif_init(); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - /* This helper function configures blocking UART I/O */ - ESP_ERROR_CHECK(example_configure_stdin_stdout()); - - asio::io_context io_context; - - std::list servers; - - { - tcp::endpoint endpoint(tcp::v4(), std::atoi(CONFIG_EXAMPLE_PORT)); - servers.emplace_back(io_context, endpoint); - } - - std::cout << "ASIO engine is up and running" << std::endl; - - io_context.run(); -} +#endif // CHAT_SERVER_HPP diff --git a/examples/protocols/asio/asio_chat/sdkconfig.ci b/examples/protocols/asio/asio_chat/sdkconfig.ci new file mode 100644 index 0000000000..4829992d03 --- /dev/null +++ b/examples/protocols/asio/asio_chat/sdkconfig.ci @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=n +CONFIG_EXAMPLE_CHAT_CLIENT=y +CONFIG_EXAMPLE_CHAT_SERVER=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y +CONFIG_EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS="localhost" diff --git a/examples/protocols/asio/asio_chat/sdkconfig.defaults b/examples/protocols/asio/asio_chat/sdkconfig.defaults new file mode 100644 index 0000000000..3a66e33fd0 --- /dev/null +++ b/examples/protocols/asio/asio_chat/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 +CONFIG_COMPILER_CXX_EXCEPTIONS=y diff --git a/examples/protocols/asio/chat_client/Makefile b/examples/protocols/asio/chat_client/Makefile deleted file mode 100644 index 90197676aa..0000000000 --- a/examples/protocols/asio/chat_client/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# -PROJECT_NAME := asio_chat_client - -EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_client/README.md b/examples/protocols/asio/chat_client/README.md deleted file mode 100644 index bcc2bd4d5e..0000000000 --- a/examples/protocols/asio/chat_client/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Asio chat client example - -Simple Asio chat client using WiFi STA or Ethernet. - -## Example workflow - -- Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio chat client connects to the corresponding server whose port number and IP are defined through the project configuration menu. -- Chat client receives all messages from other chat clients, also it sends message received from stdin using `idf.py -p PORT monitor`. - -## Running the example - -- Open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. -- Set server IP address and port number in menuconfig, "Example configuration". -- Start chat server either on host machine or as another ESP device running chat_server example. -- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. -- Wait for the board to connect to WiFi or Ethernet. -- Receive and send messages to/from other clients on stdin/stdout via serial terminal. - -See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py deleted file mode 100644 index eab7254332..0000000000 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ /dev/null @@ -1,94 +0,0 @@ -import os -import re -import socket -import time -from threading import Thread - -import ttfw_idf - -global g_client_response -global g_msg_to_client - -g_client_response = b'' -g_msg_to_client = b' 3XYZ' - - -def get_my_ip(): - s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s1.connect(('8.8.8.8', 80)) - my_ip = s1.getsockname()[0] - s1.close() - return my_ip - - -def chat_server_sketch(my_ip): - global g_client_response - print('Starting the server on {}'.format(my_ip)) - port = 2222 - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(600) - s.bind((my_ip, port)) - s.listen(1) - q,addr = s.accept() - print('connection accepted') - q.settimeout(30) - q.send(g_msg_to_client) - data = q.recv(1024) - # check if received initial empty message - if (len(data) > 4): - g_client_response = data - else: - g_client_response = q.recv(1024) - print('received from client {}'.format(g_client_response)) - s.close() - print('server closed') - - -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') -def test_examples_protocol_asio_chat_client(env, extra_data): - """ - steps: | - 1. Test to start simple tcp server - 2. `dut1` joins AP - 3. Test injects server IP to `dut1`via stdin - 4. Test evaluates `dut1` receives a message server placed - 5. Test injects a message to `dut1` to be sent as chat_client message - 6. Test evaluates received test message in host server - """ - global g_client_response - global g_msg_to_client - test_msg = 'ABC' - dut1 = env.get_dut('chat_client', 'examples/protocols/asio/chat_client', dut_class=ttfw_idf.ESP32DUT) - # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, 'asio_chat_client.bin') - bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance('asio_chat_client_size', '{}KB'.format(bin_size // 1024)) - # 1. start a tcp server on the host - host_ip = get_my_ip() - thread1 = Thread(target=chat_server_sketch, args=(host_ip,)) - thread1.start() - # 2. start the dut test and wait till client gets IP address - dut1.start_app() - dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) - # 3. send host's IP to the client i.e. the `dut1` - dut1.write(host_ip) - # 4. client `dut1` should receive a message - dut1.expect(g_msg_to_client[4:].decode()) # Strip out the front 4 bytes of message len (see chat_message protocol) - # 5. write test message from `dut1` chat_client to the server - dut1.write(test_msg) - while len(g_client_response) == 0: - time.sleep(1) - g_client_response = g_client_response.decode() - print(g_client_response) - # 6. evaluate host_server received this message - if (g_client_response[4:7] == test_msg): - print('PASS: Received correct message') - pass - else: - print('Failure!') - raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(g_client_response[4:7], test_msg)) - thread1.join() - - -if __name__ == '__main__': - test_examples_protocol_asio_chat_client() diff --git a/examples/protocols/asio/chat_client/main/CMakeLists.txt b/examples/protocols/asio/chat_client/main/CMakeLists.txt deleted file mode 100644 index 02529cb541..0000000000 --- a/examples/protocols/asio/chat_client/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "chat_client.cpp" - INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/chat_client/main/Kconfig.projbuild b/examples/protocols/asio/chat_client/main/Kconfig.projbuild deleted file mode 100644 index 34d9e93cfa..0000000000 --- a/examples/protocols/asio/chat_client/main/Kconfig.projbuild +++ /dev/null @@ -1,16 +0,0 @@ -menu "Example Configuration" - - config EXAMPLE_PORT - string "Asio example server port number" - default "2222" - help - Port number used by Asio example. - - config EXAMPLE_SERVER_IP - string "Asio example server ip" - default "FROM_STDIN" - help - Asio example server ip for this client to connect to. - Leave default "FROM_STDIN" to enter the server address via serial terminal. - -endmenu diff --git a/examples/protocols/asio/chat_client/main/chat_client.cpp b/examples/protocols/asio/chat_client/main/chat_client.cpp deleted file mode 100644 index 10ab860c9d..0000000000 --- a/examples/protocols/asio/chat_client/main/chat_client.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// -// chat_client.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include -#include -#include -#include "asio.hpp" -#include "chat_message.hpp" -#include "protocol_examples_common.h" -#include "esp_event.h" -#include "nvs_flash.h" - -using asio::ip::tcp; - -typedef std::deque chat_message_queue; - -class chat_client -{ -public: - chat_client(asio::io_context& io_context, - const tcp::resolver::results_type& endpoints) - : io_context_(io_context), - socket_(io_context) - { - do_connect(endpoints); - } - - void write(const chat_message& msg) - { - asio::post(io_context_, - [this, msg]() - { - bool write_in_progress = !write_msgs_.empty(); - write_msgs_.push_back(msg); - if (!write_in_progress) - { - do_write(); - } - }); - } - - void close() - { - asio::post(io_context_, [this]() { socket_.close(); }); - } - -private: - void do_connect(const tcp::resolver::results_type& endpoints) - { - asio::async_connect(socket_, endpoints, - [this](std::error_code ec, tcp::endpoint) - { - if (!ec) - { - do_read_header(); - } - }); - } - - void do_read_header() - { - asio::async_read(socket_, - asio::buffer(read_msg_.data(), chat_message::header_length), - [this](std::error_code ec, std::size_t /*length*/) - { - if (!ec && read_msg_.decode_header()) - { - do_read_body(); - } - else - { - socket_.close(); - } - }); - } - - void do_read_body() - { - asio::async_read(socket_, - asio::buffer(read_msg_.body(), read_msg_.body_length()), - [this](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - std::cout.write(read_msg_.body(), read_msg_.body_length()); - std::cout << "\n"; - do_read_header(); - } - else - { - socket_.close(); - } - }); - } - - void do_write() - { - asio::async_write(socket_, - asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - [this](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - do_write(); - } - } - else - { - socket_.close(); - } - }); - } - -private: - asio::io_context& io_context_; - tcp::socket socket_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; - -void read_line(char * line, int max_chars); - - -extern "C" void app_main(void) -{ - ESP_ERROR_CHECK(nvs_flash_init()); - esp_netif_init(); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - /* This helper function configures blocking UART I/O */ - ESP_ERROR_CHECK(example_configure_stdin_stdout()); - - std::string name(CONFIG_EXAMPLE_SERVER_IP); - std::string port(CONFIG_EXAMPLE_PORT); - char line[chat_message::max_body_length + 1] = { 0 }; - - if (name == "FROM_STDIN") { - std::cout << "Please enter ip address of chat server" << std::endl; - if (std::cin.getline(line, chat_message::max_body_length + 1)) { - name = line; - std::cout << "Chat server IP:" << name << std::endl; - } - } - - asio::io_context io_context; - tcp::resolver resolver(io_context); - auto endpoints = resolver.resolve(name, port); - - chat_client c(io_context, endpoints); - - std::thread t([&io_context](){ io_context.run(); }); - - while (std::cin.getline(line, chat_message::max_body_length + 1) && std::string(line) != "exit") { - chat_message msg; - msg.body_length(std::strlen(line)); - std::memcpy(msg.body(), line, msg.body_length()); - msg.encode_header(); - c.write(msg); - } - - c.close(); - t.join(); - - ESP_ERROR_CHECK(example_disconnect()); -} diff --git a/examples/protocols/asio/chat_client/sdkconfig.defaults b/examples/protocols/asio/chat_client/sdkconfig.defaults deleted file mode 100644 index b02a3a3ef6..0000000000 --- a/examples/protocols/asio/chat_client/sdkconfig.defaults +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 - -# -# Partition Table -# -# Leave some room for larger apps without needing to reduce other features -CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/asio/chat_server/CMakeLists.txt b/examples/protocols/asio/chat_server/CMakeLists.txt deleted file mode 100644 index 182f8d4024..0000000000 --- a/examples/protocols/asio/chat_server/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# The following 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) - -# (Not part of the boilerplate) -# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(asio_chat_server) diff --git a/examples/protocols/asio/chat_server/README.md b/examples/protocols/asio/chat_server/README.md deleted file mode 100644 index ec8b3e76e3..0000000000 --- a/examples/protocols/asio/chat_server/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Asio chat server example - -Simple Asio chat server using WiFi STA or Ethernet. - -## Example workflow - -- Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio chat server is started on port number defined through the project configuration. -- Chat server echoes a message (received from any client) to all connected clients. - -## Running the example - -- Open project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. -- Set server port number in menuconfig, "Example configuration". -- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. -- Wait for the board to connect to WiFi or Ethernet (note the IP address). -- Connect to the server using multiple clients, for example using any option below. - - build and run asi chat client on your host machine - - run chat_client asio example on ESP platform - - since chat message consist of ascii size and message, it is possible to - netcat `nc IP PORT` and type for example ` 4ABC` to transmit 'ABC\n' - -See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py deleted file mode 100644 index 5e92ea00eb..0000000000 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ /dev/null @@ -1,44 +0,0 @@ -import os -import re -import socket - -import ttfw_idf - - -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') -def test_examples_protocol_asio_chat_server(env, extra_data): - """ - steps: | - 1. join AP - 2. Start server - 3. Test connects to server and sends a test message - 4. Test evaluates received test message from server - """ - test_msg = b' 4ABC\n' - dut1 = env.get_dut('chat_server', 'examples/protocols/asio/chat_server', dut_class=ttfw_idf.ESP32DUT) - # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, 'asio_chat_server.bin') - bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance('asio_chat_server_bin_size', '{}KB'.format(bin_size // 1024)) - # 1. start test - dut1.start_app() - # 2. get the server IP address - data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) - # 3. create tcp client and connect to server - dut1.expect('ASIO engine is up and running', timeout=1) - cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - cli.settimeout(30) - cli.connect((data[0], 2222)) - cli.send(test_msg) - data = cli.recv(1024) - # 4. check the message received back from the server - if (data == test_msg): - print('PASS: Received correct message {}'.format(data)) - pass - else: - print('Failure!') - raise ValueError('Wrong data received from asi tcp server: {} (expoected:{})'.format(data, test_msg)) - - -if __name__ == '__main__': - test_examples_protocol_asio_chat_server() diff --git a/examples/protocols/asio/chat_server/main/CMakeLists.txt b/examples/protocols/asio/chat_server/main/CMakeLists.txt deleted file mode 100644 index c16daff3da..0000000000 --- a/examples/protocols/asio/chat_server/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "chat_server.cpp" - INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/chat_server/main/Kconfig.projbuild b/examples/protocols/asio/chat_server/main/Kconfig.projbuild deleted file mode 100644 index c1f397b9cd..0000000000 --- a/examples/protocols/asio/chat_server/main/Kconfig.projbuild +++ /dev/null @@ -1,9 +0,0 @@ -menu "Example Configuration" - - config EXAMPLE_PORT - string "Asio example server port number" - default "2222" - help - Port number used by Asio example - -endmenu diff --git a/examples/protocols/asio/chat_server/main/chat_message.hpp b/examples/protocols/asio/chat_server/main/chat_message.hpp deleted file mode 100644 index 629105b05b..0000000000 --- a/examples/protocols/asio/chat_server/main/chat_message.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// chat_message.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef CHAT_MESSAGE_HPP -#define CHAT_MESSAGE_HPP - -#include -#include -#include - -class chat_message -{ -public: - enum { header_length = 4 }; - enum { max_body_length = 512 }; - - chat_message() - : body_length_(0) - { - } - - const char* data() const - { - return data_; - } - - char* data() - { - return data_; - } - - std::size_t length() const - { - return header_length + body_length_; - } - - const char* body() const - { - return data_ + header_length; - } - - char* body() - { - return data_ + header_length; - } - - std::size_t body_length() const - { - return body_length_; - } - - void body_length(std::size_t new_length) - { - body_length_ = new_length; - if (body_length_ > max_body_length) - body_length_ = max_body_length; - } - - bool decode_header() - { - char header[header_length + 1] = ""; - std::strncat(header, data_, header_length); - body_length_ = std::atoi(header); - if (body_length_ > max_body_length) - { - body_length_ = 0; - return false; - } - return true; - } - - void encode_header() - { - char header[header_length + 1] = ""; - std::sprintf(header, "%4d", static_cast(body_length_)); - std::memcpy(data_, header, header_length); - } - -private: - char data_[header_length + max_body_length]; - std::size_t body_length_; -}; - -#endif // CHAT_MESSAGE_HPP diff --git a/examples/protocols/asio/chat_server/main/component.mk b/examples/protocols/asio/chat_server/main/component.mk deleted file mode 100644 index 0adf45649a..0000000000 --- a/examples/protocols/asio/chat_server/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# diff --git a/examples/protocols/asio/chat_server/sdkconfig.defaults b/examples/protocols/asio/chat_server/sdkconfig.defaults deleted file mode 100644 index b02a3a3ef6..0000000000 --- a/examples/protocols/asio/chat_server/sdkconfig.defaults +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 - -# -# Partition Table -# -# Leave some room for larger apps without needing to reduce other features -CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y From 6af8d2edeef79d82344bb1aa25b5971cea8bc279 Mon Sep 17 00:00:00 2001 From: SalimTerryLi Date: Wed, 1 Sep 2021 13:58:47 +0800 Subject: [PATCH 094/310] hal: remove usages of esp_log in HAL --- components/hal/esp32s2/adc_hal.c | 1 - components/hal/platform_port/include/hal/log.h | 6 ++++++ components/hal/sdio_slave_hal.c | 14 +++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/components/hal/esp32s2/adc_hal.c b/components/hal/esp32s2/adc_hal.c index b11de2776f..d1196c61e3 100644 --- a/components/hal/esp32s2/adc_hal.c +++ b/components/hal/esp32s2/adc_hal.c @@ -18,7 +18,6 @@ #include "hal/adc_hal.h" #include "hal/adc_types.h" #include "hal/adc_hal_conf.h" -#include "esp_log.h" /*--------------------------------------------------------------- Digital controller setting diff --git a/components/hal/platform_port/include/hal/log.h b/components/hal/platform_port/include/hal/log.h index 28bde429d4..6d5cbda381 100644 --- a/components/hal/platform_port/include/hal/log.h +++ b/components/hal/platform_port/include/hal/log.h @@ -21,3 +21,9 @@ #define HAL_LOGI(...) ESP_LOGI(__VA_ARGS__) #define HAL_LOGD(...) ESP_LOGD(__VA_ARGS__) #define HAL_LOGV(...) ESP_LOGV(__VA_ARGS__) + +#define HAL_EARLY_LOGE(...) ESP_EARLY_LOGE(__VA_ARGS__) +#define HAL_EARLY_LOGW(...) ESP_EARLY_LOGW(__VA_ARGS__) +#define HAL_EARLY_LOGI(...) ESP_EARLY_LOGI(__VA_ARGS__) +#define HAL_EARLY_LOGD(...) ESP_EARLY_LOGD(__VA_ARGS__) +#define HAL_EARLY_LOGV(...) ESP_EARLY_LOGV(__VA_ARGS__) diff --git a/components/hal/sdio_slave_hal.c b/components/hal/sdio_slave_hal.c index 457d4b9a1a..aa7568ee39 100644 --- a/components/hal/sdio_slave_hal.c +++ b/components/hal/sdio_slave_hal.c @@ -325,11 +325,11 @@ static void send_new_packet(sdio_slave_context_t *hal) // update pkt_len register to allow host reading. sdio_slave_ll_send_write_len(hal->slc, end_desc->pkt_len); - ESP_EARLY_LOGV(TAG, "send_length_write: %d, last_len: %08X", end_desc->pkt_len, sdio_slave_ll_send_read_len(hal->host)); + HAL_EARLY_LOGV(TAG, "send_length_write: %d, last_len: %08X", end_desc->pkt_len, sdio_slave_ll_send_read_len(hal->host)); send_set_state(hal, STATE_SENDING); - ESP_EARLY_LOGD(TAG, "restart new send: %p->%p, pkt_len: %d", start_desc, end_desc, end_desc->pkt_len); + HAL_EARLY_LOGD(TAG, "restart new send: %p->%p, pkt_len: %d", start_desc, end_desc, end_desc->pkt_len); } static esp_err_t send_check_new_packet(sdio_slave_context_t *hal) @@ -374,7 +374,7 @@ esp_err_t sdio_slave_hal_send_reset_counter(sdio_slave_context_t* hal) "reset counter when transmission started", ESP_ERR_INVALID_STATE); sdio_slave_ll_send_write_len(hal->slc, 0); - ESP_EARLY_LOGV(TAG, "last_len: %08X", sdio_slave_ll_send_read_len(hal->host)); + HAL_EARLY_LOGV(TAG, "last_len: %08X", sdio_slave_ll_send_read_len(hal->host)); hal->tail_pkt_len = 0; sdio_slave_hal_send_desc_t *desc = hal->in_flight_head; @@ -674,20 +674,20 @@ void sdio_slave_hal_load_buf(sdio_slave_context_t *hal, lldesc_t *desc) static inline void show_queue_item(lldesc_t *item) { - ESP_EARLY_LOGI(TAG, "=> %p: size: %d(%d), eof: %d, owner: %d", item, item->size, item->length, item->eof, item->owner); - ESP_EARLY_LOGI(TAG, " buf: %p, stqe_next: %p", item->buf, item->qe.stqe_next); + HAL_EARLY_LOGI(TAG, "=> %p: size: %d(%d), eof: %d, owner: %d", item, item->size, item->length, item->eof, item->owner); + HAL_EARLY_LOGI(TAG, " buf: %p, stqe_next: %p", item->buf, item->qe.stqe_next); } static void __attribute((unused)) dump_queue(sdio_slave_hal_recv_stailq_t *queue) { int cnt = 0; lldesc_t *item = NULL; - ESP_EARLY_LOGI(TAG, ">>>>> first: %p, last: %p <<<<<", queue->stqh_first, queue->stqh_last); + HAL_EARLY_LOGI(TAG, ">>>>> first: %p, last: %p <<<<<", queue->stqh_first, queue->stqh_last); STAILQ_FOREACH(item, queue, qe) { cnt++; show_queue_item(item); } - ESP_EARLY_LOGI(TAG, "total: %d", cnt); + HAL_EARLY_LOGI(TAG, "total: %d", cnt); } /*--------------------------------------------------------------------------- From 23e23b697ca4796d62c017736a131f2c15f44ada Mon Sep 17 00:00:00 2001 From: SalimTerryLi Date: Fri, 27 Aug 2021 15:28:48 +0800 Subject: [PATCH 095/310] rom/tjpgd: unify library & add rom patch remove external tjpgd library inside example enable tjpgd decoding on all chips --- components/esp_rom/CMakeLists.txt | 3 +- components/esp_rom/esp32/ld/esp32.rom.api.ld | 5 + .../esp_rom/esp32c3/ld/esp32c3.rom.api.ld | 6 + components/esp_rom/esp32c3/ld/esp32c3.rom.ld | 4 +- .../esp_rom/esp32h2/ld/esp32h2.rom.api.ld | 3 + components/esp_rom/esp32h2/ld/esp32h2.rom.ld | 4 +- .../esp_rom/esp32s3/ld/esp32s3.rom.api.ld | 5 + components/esp_rom/esp32s3/ld/esp32s3.rom.ld | 4 +- components/esp_rom/include/esp_rom_tjpgd.h | 152 ++++++++++++ .../esp_rom/patches/esp_rom_tjpgd.c | 219 ++++++++++-------- components/esp_rom/test/CMakeLists.txt | 14 +- components/esp_rom/test/test_tjpgd.c | 20 +- .../lcd/tjpgd/components/tjpgd/CMakeLists.txt | 4 - .../lcd/tjpgd/components/tjpgd/component.mk | 3 - .../tjpgd/components/tjpgd/include/tjpgd.h | 88 ------- .../peripherals/lcd/tjpgd/main/CMakeLists.txt | 6 +- .../peripherals/lcd/tjpgd/main/decode_image.c | 12 +- .../lcd/tjpgd/main/pretty_effect.c | 17 -- 18 files changed, 319 insertions(+), 250 deletions(-) create mode 100644 components/esp_rom/include/esp_rom_tjpgd.h rename examples/peripherals/lcd/tjpgd/components/tjpgd/src/tjpgd.c => components/esp_rom/patches/esp_rom_tjpgd.c (84%) delete mode 100644 examples/peripherals/lcd/tjpgd/components/tjpgd/CMakeLists.txt delete mode 100644 examples/peripherals/lcd/tjpgd/components/tjpgd/component.mk delete mode 100644 examples/peripherals/lcd/tjpgd/components/tjpgd/include/tjpgd.h diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index b8584fe51d..47a8a284d1 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -15,7 +15,8 @@ else() list(APPEND include_dirs "${target}") list(APPEND sources "patches/esp_rom_crc.c" "patches/esp_rom_sys.c" - "patches/esp_rom_uart.c") + "patches/esp_rom_uart.c" + "patches/esp_rom_tjpgd.c") list(APPEND private_required_comp soc hal) endif() diff --git a/components/esp_rom/esp32/ld/esp32.rom.api.ld b/components/esp_rom/esp32/ld/esp32.rom.api.ld index be023b85d3..afd3cc04eb 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.api.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.api.ld @@ -2,6 +2,11 @@ * ROM APIs */ +/* user may provide newer version of tjpgd */ +/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x400613e8 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40060fa8 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld index 5530bf0dce..e05d9b8aa4 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld @@ -1,5 +1,11 @@ /** ROM APIs */ + +/* user may provide newer version of tjpgd */ +/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x40000108 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40000104 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index a146d8f39d..4b42f866e5 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld @@ -89,8 +89,8 @@ tinfl_decompress_mem_to_mem = 0x40000100; ***************************************/ /* Functions */ -jd_prepare = 0x40000104; -jd_decomp = 0x40000108; +PROVIDE( jd_prepare = 0x40000104 ); +PROVIDE( jd_decomp = 0x40000108 ); /*************************************** diff --git a/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld b/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld index 5530bf0dce..588ac6b179 100644 --- a/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld +++ b/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld @@ -1,5 +1,8 @@ /** ROM APIs */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x40000104 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40000100 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32h2/ld/esp32h2.rom.ld b/components/esp_rom/esp32h2/ld/esp32h2.rom.ld index acd5821d5a..fefad99c3d 100644 --- a/components/esp_rom/esp32h2/ld/esp32h2.rom.ld +++ b/components/esp_rom/esp32h2/ld/esp32h2.rom.ld @@ -88,8 +88,8 @@ tinfl_decompress_mem_to_mem = 0x400000fc; ***************************************/ /* Functions */ -jd_prepare = 0x40000100; -jd_decomp = 0x40000104; +PROVIDE( jd_prepare = 0x40000100 ); +PROVIDE( jd_decomp = 0x40000104 ); /*************************************** diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld index 6d3b6d1b9f..4d45188393 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld @@ -2,6 +2,11 @@ * ROM APIs */ +/* user may provide newer version of tjpgd */ +/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x40000864 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40000858 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld index 556b3eecc0..f78625b3b8 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld @@ -91,8 +91,8 @@ tinfl_decompress_mem_to_mem = 0x4000084c; ***************************************/ /* Functions */ -jd_prepare = 0x40000858; -jd_decomp = 0x40000864; +PROVIDE( jd_prepare = 0x40000858 ); +PROVIDE (jd_decomp = 0x40000864 ); /*************************************** diff --git a/components/esp_rom/include/esp_rom_tjpgd.h b/components/esp_rom/include/esp_rom_tjpgd.h new file mode 100644 index 0000000000..318519ba74 --- /dev/null +++ b/components/esp_rom/include/esp_rom_tjpgd.h @@ -0,0 +1,152 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/*-----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 +/-----------------------------------------------------------------------------/ +/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2012, ChaN, all right reserved. +/ +/ * The TJpgDec module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be damaged data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} esp_rom_tjpgd_result_t; + +/* Rectangular structure */ +typedef struct { + uint16_t left; /* Left end */ + uint16_t right; /* Right end */ + uint16_t top; /* Top end */ + uint16_t bottom;/* Bottom end */ +} esp_rom_tjpgd_rect_t; + +typedef struct JDEC_s esp_rom_tjpgd_dec_t; + +/** + * @brief Type of user defined input function to read data from input stream + * @param dec Specifies the decompression object of the decompression session + * @param buffer Specifies the pointer to the read buffer to store the read data. A NULL specifies to remove the data from input stream + * @param ndata Specifies number of bytes to read/remove from the input stream + * + * @return number of bytes read/removed. When a zero is returned, the esp_rom_tjpgd_prepare and esp_rom_tjpgd_decomp function aborts with JDR_INP + */ +typedef uint32_t (*esp_rom_tjpgd_input_function_t)(esp_rom_tjpgd_dec_t *dec, uint8_t *buffer, uint32_t ndata); + +/** + * @brief User defined output function to write decompressed pixels to the output device + * + * This function is the data output interface of the TJpgDec module. + * The corresponding decompression session can be identified by the pointer to the device identifier jdec->device passed to the 5th argument of jd_prepare function. + * The bitmap is sent to the frame buffer or display device in this function. + * The first pixel in the bitmap is the left-top of the rectangular, the second one is next right and last pixel is the bottom-right of the rectangular. + * The size of rectangular varies from 1x1 to 16x16 depends on clipping, scaling and sampling factor of the image. + * If the rectangular is out of the frame buffer, it should be clipped in this function. + * + * The pixel format is currently configured to RGB888 + * + * @param dec Specifies the decompression object of the decompression session + * @param bitmap Specifies the RGB bitmap to be output + * @param rect Specifies rectangular region in the image to output the RGB bitmap + * + * @return Normally returns 1. It lets TJpgDec to continue the decompressing process. + * When a 0 is returned, the esp_rom_tjpgd_decomp function aborts with JDR_INTR. + * This is useful to interrupt the decompression process + */ +typedef uint32_t (*esp_rom_tjpgd_output_function_t)(esp_rom_tjpgd_dec_t *dec, void *bitmap, esp_rom_tjpgd_rect_t *rect); + +struct JDEC_s { + uint32_t dctr; /* Number of bytes available in the input buffer */ + uint8_t *dptr; /* Current data read ptr */ + uint8_t *inbuf; /* Bit stream input buffer */ + uint8_t dmsk; /* Current bit in the current read byte */ + uint8_t scale; /* Output scaling ratio */ + uint8_t msx, msy; /* MCU size in unit of block (width, height) */ + uint8_t qtid[3]; /* Quantization table ID of each component */ + int16_t dcv[3]; /* Previous DC element of each component */ + uint16_t nrst; /* Restart inverval */ + uint32_t width, height; /* Size of the input image (pixel) */ + uint8_t *huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + uint16_t *huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + uint8_t *huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + int32_t *qttbl[4]; /* Dequaitizer tables [id] */ + void *workbuf; /* Working buffer for IDCT and RGB output */ + uint8_t *mcubuf; /* Working buffer for the MCU */ + void *pool; /* Pointer to available memory pool */ + uint32_t sz_pool; /* Size of momory pool (bytes available) */ + esp_rom_tjpgd_input_function_t infunc; /* Pointer to jpeg stream input function */ + void *device; /* Pointer to I/O device identifiler for the session */ +}; + +/* TJpgDec API functions */ + +/** + * @brief Analyzes the JPEG data and create a decompression object for subsequent decompression process. + * @param dec Specifies the decompression object to be initialized. The decompression object is used for subsequent decompression process. + * @param infunc Specifies the user defined data input function. + * @param work Specifies pointer to the work area for this session. It should be aligned to word boundary or it can result an exception. + * @param sz_work Specifies size of the work area in unit of byte. + * TJpgDec requires upto 3092 bytes of work area depends on the built-in parameter tables of the JPEG image. + * Thus 3092 bytes of work area is sufficient for most case. + * @param dev Specifies pointer to the user defined device identifier for this session. + * It is stored to the member device in the decompression object. It can be referred by I/O functions to identify the current session. + * When I/O device is fixed in the project or this feature is not needed, set NULL and do not care about this. + * + * @return + * - JDR_OK Function succeeded and decompression object is valid. + * - JDR_INP An error occurred in input function due to hard error or wrong stream termination. + * - JDR_MEM1 Insufficient work area for this JPEG image. + * - JDR_MEM2 Insufficient input buffer for this JPEG image. JD_SZBUF may be too small. + * - JDR_PAR Parameter error. Given pointer to the work area is NULL. + * - JDR_FMT1 Data format error. The JPEG data can be collapsed. + * - JDR_FMT2 Right format but not supported. May be a grayscale image. + * - JDR_FMT3 Not supported JPEG standard. May be a progressive JPEG image. + */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_prepare(esp_rom_tjpgd_dec_t *dec, esp_rom_tjpgd_input_function_t infunc, void *work, uint32_t sz_work, void *dev); + +/** + * @brief Decompress the JPEG image and output it as RGB data. + * @param dec Specifies the valid decompressor object. + * @param outfunc Specifies the user defined data output function. The esp_rom_tjpgd_decomp function calls this function to output the decompressed JPEG image in RGB form. + * @param scale Specifies scaling factor N for output. The output image is descaled to 1 / 2 ^ N (N = 0 to 3). + * + * @return + * - JDR_OK Function succeeded. + * - JDR_INTR The decompression process is interrupted by output function. + * - JDR_INP An error occured in input function due to hard error or wrong stream termination. + * - JDR_PAR Parameter error. Given scale factor is invalid. + * - JDR_FMT1 Data format error. The JPEG data can be collapted. + */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_decomp(esp_rom_tjpgd_dec_t *dec, esp_rom_tjpgd_output_function_t outfunc, uint8_t scale); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/lcd/tjpgd/components/tjpgd/src/tjpgd.c b/components/esp_rom/patches/esp_rom_tjpgd.c similarity index 84% rename from examples/peripherals/lcd/tjpgd/components/tjpgd/src/tjpgd.c rename to components/esp_rom/patches/esp_rom_tjpgd.c index 276dc1932c..8e0b8d2713 100644 --- a/examples/peripherals/lcd/tjpgd/components/tjpgd/src/tjpgd.c +++ b/components/esp_rom/patches/esp_rom_tjpgd.c @@ -1,11 +1,11 @@ /*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor R0.01c (C)ChaN, 2019 +/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 /-----------------------------------------------------------------------------/ / The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following terms. / -/ Copyright (C) 2019, ChaN, all right reserved. +/ Copyright (C) 2012, ChaN, all right reserved. / / * The TJpgDec module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -13,13 +13,21 @@ / * Redistributions of source code must retain the above copyright notice. / /-----------------------------------------------------------------------------/ -/ Oct 04, 2011 R0.01 First release. -/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq. -/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option. -/ Mar 16, 2019 R0.01c Supprted stdint.h. +/ Oct 04,'11 R0.01 First release. +/ Feb 19,'12 R0.01a Fixed decompression fails when scan starts with an escape seq. +/ Sep 03,'12 R0.01b Added JD_TBLCLIP option. /----------------------------------------------------------------------------*/ -#include "tjpgd.h" +#include "esp_rom_caps.h" + +#if !ESP_ROM_HAS_JPEG_DECODE + +#include "esp_rom_tjpgd.h" + +#define JD_SZBUF 512 /* Size of stream input buffer */ +#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ +#define JD_USE_SCALE 1 /* Use descaling feature for output */ +#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ /*-----------------------------------------------*/ @@ -28,7 +36,8 @@ #define ZIG(n) Zig[n] -static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ +static +const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, @@ -44,7 +53,8 @@ static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion tabl #define IPSF(n) Ipsf[n] -static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ +static +const uint16_t Ipsf[64] = { /* See also aa_idct.png */ (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192), @@ -63,9 +73,10 @@ static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ #if JD_TBLCLIP -#define BYTECLIP(v) Clip8[(uint16_t)(v) & 0x3FF] +#define BYTECLIP(v) Clip8[(uint32_t)(v) & 0x3FF] -static const uint8_t Clip8[1024] = { +static +const uint8_t Clip8[1024] = { /* 0..255 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, @@ -106,8 +117,9 @@ static const uint8_t Clip8[1024] = { #else /* JD_TBLCLIP */ -inline uint8_t BYTECLIP ( - int16_t val +inline +uint8_t BYTECLIP ( + int32_t val ) { if (val < 0) val = 0; @@ -124,9 +136,10 @@ inline uint8_t BYTECLIP ( /* Allocate a memory block from memory pool */ /*-----------------------------------------------------------------------*/ -static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ - JDEC* jd, /* Pointer to the decompressor object */ - uint16_t nd /* Number of bytes to allocate */ +static +void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ + uint32_t nd /* Number of bytes to allocate */ ) { char *rp = 0; @@ -150,13 +163,14 @@ static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory a /* Create de-quantization and prescaling tables with a DQT segment */ /*-----------------------------------------------------------------------*/ -static int create_qt_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ +static +uint32_t create_qt_tbl ( /* 0:OK, !0:Failed */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ const uint8_t* data, /* Pointer to the quantizer tables */ - uint16_t ndata /* Size of input data */ + uint32_t ndata /* Size of input data */ ) { - uint16_t i; + uint32_t i; uint8_t d, z; int32_t *pb; @@ -186,13 +200,14 @@ static int create_qt_tbl ( /* 0:OK, !0:Failed */ /* Create huffman code tables with a DHT segment */ /*-----------------------------------------------------------------------*/ -static int create_huffman_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ +static +uint32_t create_huffman_tbl ( /* 0:OK, !0:Failed */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ const uint8_t* data, /* Pointer to the packed huffman tables */ - uint16_t ndata /* Size of input data */ + uint32_t ndata /* Size of input data */ ) { - uint16_t i, j, b, np, cls, num; + uint32_t i, j, b, np, cls, num; uint8_t d, *pb, *pd; uint16_t hc, *ph; @@ -201,15 +216,17 @@ static int create_huffman_tbl ( /* 0:OK, !0:Failed */ if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ ndata -= 17; d = *data++; /* Get table number and class */ + cls = (d >> 4); num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ - cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ if (!pb) return JDR_MEM1; /* Err: not enough memory */ jd->huffbits[num][cls] = pb; for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ - np += (pb[i] = *data++); /* Get sum of code words for each code */ + pb[i] = b = *data++; + np += b; /* Get sum of code words for each code */ } - ph = alloc_pool(jd, (uint16_t)(np * sizeof (uint16_t)));/* Allocate a memory block for the code word table */ + + ph = alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */ if (!ph) return JDR_MEM1; /* Err: not enough memory */ jd->huffcode[num][cls] = ph; hc = 0; @@ -241,13 +258,14 @@ static int create_huffman_tbl ( /* 0:OK, !0:Failed */ /* Extract N bits from input stream */ /*-----------------------------------------------------------------------*/ -static int bitext ( /* >=0: extracted data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - int nbit /* Number of bits to extract (1 to 11) */ +static +int32_t bitext ( /* >=0: extracted data, <0: error code */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ + uint32_t nbit /* Number of bits to extract (1 to 11) */ ) { uint8_t msk, s, *dp; - uint16_t dc, v, f; + uint32_t dc, v, f; msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ @@ -257,14 +275,14 @@ static int bitext ( /* >=0: extracted data, <0: error code */ if (!dc) { /* No input data is available, re-fill input buffer */ dp = jd->inbuf; /* Top of input buffer */ dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */ + if (!dc) return 0 - (int32_t)JDR_INP; /* Err: read error or wrong stream termination */ } else { dp++; /* Next data ptr */ } dc--; /* Decrement number of available bytes */ if (f) { /* In flag sequence? */ f = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + if (*dp != 0) return 0 - (int32_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ *dp = s = 0xFF; /* The flag is a data 0xFF */ } else { s = *dp; /* Get next data byte */ @@ -281,7 +299,7 @@ static int bitext ( /* >=0: extracted data, <0: error code */ } while (nbit); jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; - return (int)v; + return (int32_t)v; } @@ -291,15 +309,16 @@ static int bitext ( /* >=0: extracted data, <0: error code */ /* Extract a huffman decoded data from input stream */ /*-----------------------------------------------------------------------*/ -static int16_t huffext ( /* >=0: decoded data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ +static +int32_t huffext ( /* >=0: decoded data, <0: error code */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ const uint8_t* hbits, /* Pointer to the bit distribution table */ const uint16_t* hcode, /* Pointer to the code word table */ const uint8_t* hdata /* Pointer to the data table */ ) { uint8_t msk, s, *dp; - uint16_t dc, v, f, bl, nd; + uint32_t dc, v, f, bl, nd; msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ @@ -310,14 +329,15 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */ if (!dc) { /* No input data is available, re-fill input buffer */ dp = jd->inbuf; /* Top of input buffer */ dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */ + if (!dc) return 0 - (int32_t)JDR_INP; /* Err: read error or wrong stream termination */ } else { dp++; /* Next data ptr */ } dc--; /* Decrement number of available bytes */ if (f) { /* In flag sequence? */ f = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + if (*dp != 0) + return 0 - (int32_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ *dp = s = 0xFF; /* The flag is a data 0xFF */ } else { s = *dp; /* Get next data byte */ @@ -341,7 +361,7 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */ bl--; } while (bl); - return 0 - (int16_t)JDR_FMT1; /* Err: code not found (may be collapted data) */ + return 0 - (int32_t)JDR_FMT1; /* Err: code not found (may be collapted data) */ } @@ -351,7 +371,8 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */ /* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ /*-----------------------------------------------------------------------*/ -static void block_idct ( +static +void block_idct ( int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ uint8_t* dst /* Pointer to the destination to store the block as byte array */ ) @@ -359,7 +380,7 @@ static void block_idct ( const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096); int32_t v0, v1, v2, v3, v4, v5, v6, v7; int32_t t10, t11, t12, t13; - uint16_t i; + uint32_t i; /* Process columns */ for (i = 0; i < 8; i++) { @@ -463,13 +484,14 @@ static void block_idct ( /* Load all blocks in the MCU into working buffer */ /*-----------------------------------------------------------------------*/ -static JRESULT mcu_load ( - JDEC* jd /* Pointer to the decompressor object */ +static +esp_rom_tjpgd_result_t mcu_load ( + esp_rom_tjpgd_dec_t* jd /* Pointer to the decompressor object */ ) { int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ - int b, d, e; - uint16_t blk, nby, nbc, i, z, id, cmp; + uint32_t blk, nby, nbc, i, z, id, cmp; + int32_t b, d, e; uint8_t *bp; const uint8_t *hb, *hd; const uint16_t *hc; @@ -503,7 +525,7 @@ static JRESULT mcu_load ( tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ /* Extract following 63 AC elements from input stream */ - for (i = 1; i < 64; tmp[i++] = 0) ; /* Clear rest of elements */ + for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */ hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */ hc = jd->huffcode[id][1]; hd = jd->huffdata[id][1]; @@ -512,7 +534,7 @@ static JRESULT mcu_load ( b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */ if (b == 0) break; /* EOB? */ if (b < 0) return 0 - b; /* Err: invalid code or input error */ - z = (uint16_t)b >> 4; /* Number of leading zero elements */ + z = (uint32_t)b >> 4; /* Number of leading zero elements */ if (z) { i += z; /* Skip zero elements */ if (i >= 64) return JDR_FMT1; /* Too long zero run */ @@ -527,11 +549,10 @@ static JRESULT mcu_load ( } } while (++i < 64); /* Next AC element */ - if (JD_USE_SCALE && jd->scale == 3) { - *bp = (uint8_t)((*tmp / 256) + 128); /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ - } else { + if (JD_USE_SCALE && jd->scale == 3) + *bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ + else block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ - } bp += 64; /* Next block */ } @@ -546,18 +567,19 @@ static JRESULT mcu_load ( /* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ /*-----------------------------------------------------------------------*/ -static JRESULT mcu_output ( - JDEC* jd, /* Pointer to the decompressor object */ - uint16_t (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - uint16_t x, /* MCU position in the image (left of the MCU) */ - uint16_t y /* MCU position in the image (top of the MCU) */ +static +esp_rom_tjpgd_result_t mcu_output ( + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ + uint32_t (*outfunc)(esp_rom_tjpgd_dec_t*, void*, esp_rom_tjpgd_rect_t*), /* RGB output function */ + uint32_t x, /* MCU position in the image (left of the MCU) */ + uint32_t y /* MCU position in the image (top of the MCU) */ ) { - const int16_t CVACC = (sizeof (int16_t) > 2) ? 1024 : 128; - uint16_t ix, iy, mx, my, rx, ry; - int16_t yy, cb, cr; + const int32_t CVACC = (sizeof (int32_t) > 2) ? 1024 : 128; + uint32_t ix, iy, mx, my, rx, ry; + int32_t yy, cb, cr; uint8_t *py, *pc, *rgb24; - JRECT rect; + esp_rom_tjpgd_rect_t rect; mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ @@ -597,15 +619,15 @@ static JRESULT mcu_output ( yy = *py++; /* Get Y component */ /* Convert YCbCr to RGB */ - *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr) / CVACC); - *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC); - *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb) / CVACC); + *rgb24++ = /* R */ BYTECLIP(yy + ((int32_t)(1.402 * CVACC) * cr) / CVACC); + *rgb24++ = /* G */ BYTECLIP(yy - ((int32_t)(0.344 * CVACC) * cb + (int32_t)(0.714 * CVACC) * cr) / CVACC); + *rgb24++ = /* B */ BYTECLIP(yy + ((int32_t)(1.772 * CVACC) * cb) / CVACC); } } /* Descale the MCU rectangular if needed */ if (JD_USE_SCALE && jd->scale) { - uint16_t x, y, r, g, b, s, w, a; + uint32_t x, y, r, g, b, s, w, a; uint8_t *op; /* Get averaged RGB value of each square correcponds to a pixel */ @@ -647,9 +669,9 @@ static JRESULT mcu_output ( py += 64; /* Convert YCbCr to RGB */ - *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr / CVACC)); - *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC); - *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb / CVACC)); + *rgb24++ = /* R */ BYTECLIP(yy + ((int32_t)(1.402 * CVACC) * cr / CVACC)); + *rgb24++ = /* G */ BYTECLIP(yy - ((int32_t)(0.344 * CVACC) * cb + (int32_t)(0.714 * CVACC) * cr) / CVACC); + *rgb24++ = /* B */ BYTECLIP(yy + ((int32_t)(1.772 * CVACC) * cb / CVACC)); } } } @@ -658,7 +680,7 @@ static JRESULT mcu_output ( mx >>= jd->scale; if (rx < mx) { uint8_t *s, *d; - uint16_t x, y; + uint32_t x, y; s = d = (uint8_t*)jd->workbuf; for (y = 0; y < ry; y++) { @@ -675,7 +697,7 @@ static JRESULT mcu_output ( if (JD_FORMAT == 1) { uint8_t *s = (uint8_t*)jd->workbuf; uint16_t w, *d = (uint16_t*)s; - uint16_t n = rx * ry; + uint32_t n = rx * ry; do { w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ @@ -696,12 +718,13 @@ static JRESULT mcu_output ( /* Process restart interval */ /*-----------------------------------------------------------------------*/ -static JRESULT restart ( - JDEC* jd, /* Pointer to the decompressor object */ +static +esp_rom_tjpgd_result_t restart ( + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ uint16_t rstn /* Expected restert sequense number */ ) { - uint16_t i, dc; + uint32_t i, dc; uint16_t d; uint8_t *dp; @@ -723,9 +746,8 @@ static JRESULT restart ( jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0; /* Check the marker */ - if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) { + if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ - } /* Reset DC offset */ jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; @@ -743,19 +765,19 @@ static JRESULT restart ( #define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1)) -JRESULT jd_prepare ( - JDEC* jd, /* Blank decompressor object */ - uint16_t (*infunc)(JDEC*, uint8_t*, uint16_t), /* JPEG strem input function */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_prepare ( + esp_rom_tjpgd_dec_t* jd, /* Blank decompressor object */ + uint32_t (*infunc)(esp_rom_tjpgd_dec_t*, uint8_t*, uint32_t), /* JPEG strem input function */ void* pool, /* Working buffer for the decompression session */ - uint16_t sz_pool, /* Size of working buffer */ + uint32_t sz_pool, /* Size of working buffer */ void* dev /* I/O device identifier for the session */ ) { uint8_t *seg, b; uint16_t marker; uint32_t ofs; - uint16_t n, i, j, len; - JRESULT rc; + uint32_t n, i, j, len; + esp_rom_tjpgd_result_t rc; if (!pool) return JDR_PAR; @@ -773,7 +795,7 @@ JRESULT jd_prepare ( jd->huffdata[i][j] = 0; } } - for (i = 0; i < 4; jd->qttbl[i++] = 0) ; + for (i = 0; i < 4; i++) jd->qttbl[i] = 0; jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ if (!seg) return JDR_MEM1; @@ -805,9 +827,8 @@ JRESULT jd_prepare ( for (i = 0; i < 3; i++) { b = seg[7 + 3 * i]; /* Get sampling factor */ if (!i) { /* Y component */ - if (b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */ + if (b != 0x11 && b != 0x22 && b != 0x21)/* Check sampling factor */ return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ - } jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ } else { /* Cb/Cr component */ if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */ @@ -861,12 +882,9 @@ JRESULT jd_prepare ( b = seg[2 + 2 * i]; /* Get huffman table ID */ if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ b = i ? 1 : 0; - if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) { /* Check dc/ac huffman table for this component */ - return JDR_FMT1; /* Err: Nnot loaded */ - } - if (!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */ - return JDR_FMT1; /* Err: Not loaded */ - } + if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) /* Check huffman table for this component */ + return JDR_FMT1; /* Err: Huffman table not loaded */ + if (!jd->qttbl[jd->qtid[i]]) return JDR_FMT1; /* Err: Dequantizer table not loaded */ } /* Allocate working buffer for MCU and RGB */ @@ -876,13 +894,13 @@ JRESULT jd_prepare ( if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ - jd->mcubuf = (uint8_t*)alloc_pool(jd, (uint16_t)((n + 2) * 64)); /* Allocate MCU working buffer */ + jd->mcubuf = alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */ if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ /* Pre-load the JPEG data to extract it from the bit stream */ jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */ if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */ - jd->dctr = jd->infunc(jd, seg + ofs, (uint16_t)(JD_SZBUF - ofs)); + jd->dctr = jd->infunc(jd, seg + ofs, JD_SZBUF - (uint32_t)ofs); jd->dptr = seg + ofs - 1; } @@ -905,9 +923,8 @@ JRESULT jd_prepare ( default: /* Unknown segment (comment, exif or etc..) */ /* Skip segment data */ - if (jd->infunc(jd, 0, len) != len) { /* Null pointer specifies to skip bytes of stream */ + if (jd->infunc(jd, 0, len) != len) /* Null pointer specifies to skip bytes of stream */ return JDR_INP; - } } } } @@ -919,15 +936,15 @@ JRESULT jd_prepare ( /* Start to decompress the JPEG picture */ /*-----------------------------------------------------------------------*/ -JRESULT jd_decomp ( - JDEC* jd, /* Initialized decompression object */ - uint16_t (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - uint8_t scale /* Output de-scaling factor (0 to 3) */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_decomp ( + esp_rom_tjpgd_dec_t* jd, /* Initialized decompression object */ + uint32_t (*outfunc)(esp_rom_tjpgd_dec_t*, void*, esp_rom_tjpgd_rect_t*), /* RGB output function */ + uint8_t scale /* Output de-scaling factor (0 to 3) */ ) { - uint16_t x, y, mx, my; + uint32_t x, y, mx, my; uint16_t rst, rsc; - JRESULT rc; + esp_rom_tjpgd_result_t rc; if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; @@ -955,3 +972,5 @@ JRESULT jd_decomp ( return rc; } + +#endif // ESP_ROM_HAS_JPEG_DECODE diff --git a/components/esp_rom/test/CMakeLists.txt b/components/esp_rom/test/CMakeLists.txt index 82049b5644..00ab63e913 100644 --- a/components/esp_rom/test/CMakeLists.txt +++ b/components/esp_rom/test/CMakeLists.txt @@ -2,11 +2,9 @@ idf_component_register(SRC_DIRS . PRIV_INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR} PRIV_REQUIRES cmock test_utils) -if(IDF_TARGET STREQUAL "esp32") - add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" - COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" - WORKING_DIRECTORY ${COMPONENT_DIR} - DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg") - add_custom_target(test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h") - add_dependencies(${COMPONENT_LIB} test_logo) -endif() +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" + COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" + WORKING_DIRECTORY ${COMPONENT_DIR} + DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg") +add_custom_target(test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h") +add_dependencies(${COMPONENT_LIB} test_logo) diff --git a/components/esp_rom/test/test_tjpgd.c b/components/esp_rom/test/test_tjpgd.c index 7a0439c0d0..673d91a358 100644 --- a/components/esp_rom/test/test_tjpgd.c +++ b/components/esp_rom/test/test_tjpgd.c @@ -5,9 +5,7 @@ #include "sdkconfig.h" #include "unity.h" -#if CONFIG_IDF_TARGET_ESP32 - -#include "esp32/rom/tjpgd.h" +#include "esp_rom_tjpgd.h" #include "test_tjpgd_logo.h" typedef struct { @@ -18,7 +16,7 @@ typedef struct { int outH; } JpegDev; -static UINT infunc(JDEC *decoder, BYTE *buf, UINT len) +static uint32_t infunc(esp_rom_tjpgd_dec_t *decoder, uint8_t *buf, uint32_t len) { JpegDev *jd = (JpegDev *)decoder->device; printf("Reading %d bytes from pos %d\n", len, jd->inPos); @@ -29,7 +27,7 @@ static UINT infunc(JDEC *decoder, BYTE *buf, UINT len) return len; } -static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect) +static uint32_t outfunc(esp_rom_tjpgd_dec_t *decoder, void *bitmap, esp_rom_tjpgd_rect_t *rect) { unsigned char *in = (unsigned char *)bitmap; unsigned char *out; @@ -55,10 +53,10 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]") char *work; int r; int x, y, v; - JDEC decoder; + esp_rom_tjpgd_dec_t decoder; JpegDev jd; - decoded = malloc(48 * 48 * 3); - for (x = 0; x < 48 * 48 * 3; x += 2) { + decoded = malloc(TESTW * TESTH * 3); + for (x = 0; x < TESTW * TESTH * 3; x += 2) { decoded[x] = 0; decoded[x + 1] = 0xff; } @@ -71,9 +69,9 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]") jd.outW = TESTW; jd.outH = TESTH; - r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd); + r = esp_rom_tjpgd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd); TEST_ASSERT_EQUAL(r, JDR_OK); - r = jd_decomp(&decoder, outfunc, 0); + r = esp_rom_tjpgd_decomp(&decoder, outfunc, 0); TEST_ASSERT_EQUAL(r, JDR_OK); p = decoded + 2; @@ -89,5 +87,3 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]") free(work); free(decoded); } - -#endif // #if CONFIG_IDF_TARGET_ESP32 diff --git a/examples/peripherals/lcd/tjpgd/components/tjpgd/CMakeLists.txt b/examples/peripherals/lcd/tjpgd/components/tjpgd/CMakeLists.txt deleted file mode 100644 index cde4d0eed4..0000000000 --- a/examples/peripherals/lcd/tjpgd/components/tjpgd/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -set(tjpgd_srcs "src/tjpgd.c") - -idf_component_register(SRCS "${tjpgd_srcs}" - INCLUDE_DIRS "include") diff --git a/examples/peripherals/lcd/tjpgd/components/tjpgd/component.mk b/examples/peripherals/lcd/tjpgd/components/tjpgd/component.mk deleted file mode 100644 index 24cab8b637..0000000000 --- a/examples/peripherals/lcd/tjpgd/components/tjpgd/component.mk +++ /dev/null @@ -1,3 +0,0 @@ -COMPONENT_ADD_INCLUDEDIRS := include - -COMPONENT_SRCDIRS := src diff --git a/examples/peripherals/lcd/tjpgd/components/tjpgd/include/tjpgd.h b/examples/peripherals/lcd/tjpgd/components/tjpgd/include/tjpgd.h deleted file mode 100644 index abb9dd4803..0000000000 --- a/examples/peripherals/lcd/tjpgd/components/tjpgd/include/tjpgd.h +++ /dev/null @@ -1,88 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2019 -/----------------------------------------------------------------------------*/ -#ifndef DEF_TJPGDEC -#define DEF_TJPGDEC -/*---------------------------------------------------------------------------*/ -/* System Configurations */ - -#define JD_SZBUF 512 /* Size of stream input buffer */ -#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ -#define JD_USE_SCALE 1 /* Use descaling feature for output */ -#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ - -/*---------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(_WIN32) /* Main development platform */ -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef short int16_t; -typedef unsigned long uint32_t; -typedef long int32_t; -#else -#include "stdint.h" -#endif - -/* Error code */ -typedef enum { - JDR_OK = 0, /* 0: Succeeded */ - JDR_INTR, /* 1: Interrupted by output function */ - JDR_INP, /* 2: Device error or wrong termination of input stream */ - JDR_MEM1, /* 3: Insufficient memory pool for the image */ - JDR_MEM2, /* 4: Insufficient stream input buffer */ - JDR_PAR, /* 5: Parameter error */ - JDR_FMT1, /* 6: Data format error (may be damaged data) */ - JDR_FMT2, /* 7: Right format but not supported */ - JDR_FMT3 /* 8: Not supported JPEG standard */ -} JRESULT; - - - -/* Rectangular structure */ -typedef struct { - uint16_t left, right, top, bottom; -} JRECT; - - - -/* Decompressor object structure */ -typedef struct JDEC JDEC; -struct JDEC { - uint16_t dctr; /* Number of bytes available in the input buffer */ - uint8_t* dptr; /* Current data read ptr */ - uint8_t* inbuf; /* Bit stream input buffer */ - uint8_t dmsk; /* Current bit in the current read byte */ - uint8_t scale; /* Output scaling ratio */ - uint8_t msx, msy; /* MCU size in unit of block (width, height) */ - uint8_t qtid[3]; /* Quantization table ID of each component */ - int16_t dcv[3]; /* Previous DC element of each component */ - uint16_t nrst; /* Restart inverval */ - uint16_t width, height; /* Size of the input image (pixel) */ - uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ - uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ - uint8_t* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ - int32_t* qttbl[4]; /* Dequantizer tables [id] */ - void* workbuf; /* Working buffer for IDCT and RGB output */ - uint8_t* mcubuf; /* Working buffer for the MCU */ - void* pool; /* Pointer to available memory pool */ - uint16_t sz_pool; /* Size of momory pool (bytes available) */ - uint16_t (*infunc)(JDEC*, uint8_t*, uint16_t);/* Pointer to jpeg stream input function */ - void* device; /* Pointer to I/O device identifiler for the session */ -}; - - - -/* TJpgDec API functions */ -JRESULT jd_prepare (JDEC*, uint16_t(*)(JDEC*,uint8_t*,uint16_t), void*, uint16_t, void*); -JRESULT jd_decomp (JDEC*, uint16_t(*)(JDEC*,void*,JRECT*), uint8_t); - - -#ifdef __cplusplus -} -#endif - -#endif /* _TJPGDEC */ diff --git a/examples/peripherals/lcd/tjpgd/main/CMakeLists.txt b/examples/peripherals/lcd/tjpgd/main/CMakeLists.txt index f48fb7da8b..8abed53131 100644 --- a/examples/peripherals/lcd/tjpgd/main/CMakeLists.txt +++ b/examples/peripherals/lcd/tjpgd/main/CMakeLists.txt @@ -1,12 +1,8 @@ set(srcs "pretty_effect.c" "lcd_tjpgd_example_main.c" + "decode_image.c" ) -# Only ESP32 has enough memory to do jpeg decoding -if(IDF_TARGET STREQUAL "esp32") - list(APPEND srcs "decode_image.c") -endif() - idf_component_register(SRCS ${srcs} INCLUDE_DIRS "." EMBED_FILES image.jpg) diff --git a/examples/peripherals/lcd/tjpgd/main/decode_image.c b/examples/peripherals/lcd/tjpgd/main/decode_image.c index 179c3deb7a..a9a460bc39 100644 --- a/examples/peripherals/lcd/tjpgd/main/decode_image.c +++ b/examples/peripherals/lcd/tjpgd/main/decode_image.c @@ -18,7 +18,7 @@ format if you want to use a different image file. */ #include "decode_image.h" -#include "tjpgd.h" +#include "esp_rom_tjpgd.h" #include "esp_log.h" #include @@ -42,7 +42,7 @@ typedef struct { } JpegDev; //Input function for jpeg decoder. Just returns bytes from the inData field of the JpegDev structure. -static uint16_t infunc(JDEC *decoder, uint8_t *buf, uint16_t len) +static uint32_t infunc(esp_rom_tjpgd_dec_t *decoder, uint8_t *buf, uint32_t len) { //Read bytes from input file JpegDev *jd = (JpegDev *)decoder->device; @@ -55,7 +55,7 @@ static uint16_t infunc(JDEC *decoder, uint8_t *buf, uint16_t len) //Output function. Re-encodes the RGB888 data from the decoder as big-endian RGB565 and //stores it in the outData array of the JpegDev structure. -static uint16_t outfunc(JDEC *decoder, void *bitmap, JRECT *rect) +static uint32_t outfunc(esp_rom_tjpgd_dec_t *decoder, void *bitmap, esp_rom_tjpgd_rect_t *rect) { JpegDev *jd = (JpegDev *)decoder->device; uint8_t *in = (uint8_t *)bitmap; @@ -83,7 +83,7 @@ esp_err_t decode_image(uint16_t ***pixels) { char *work = NULL; int r; - JDEC decoder; + esp_rom_tjpgd_dec_t decoder; JpegDev jd; *pixels = NULL; esp_err_t ret = ESP_OK; @@ -120,13 +120,13 @@ esp_err_t decode_image(uint16_t ***pixels) jd.outH = IMAGE_H; //Prepare and decode the jpeg. - r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd); + r = esp_rom_tjpgd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd); if (r != JDR_OK) { ESP_LOGE(TAG, "Image decoder: jd_prepare failed (%d)", r); ret = ESP_ERR_NOT_SUPPORTED; goto err; } - r = jd_decomp(&decoder, outfunc, 0); + r = esp_rom_tjpgd_decomp(&decoder, outfunc, 0); if (r != JDR_OK && r != JDR_FMT1) { ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", r); ret = ESP_ERR_NOT_SUPPORTED; diff --git a/examples/peripherals/lcd/tjpgd/main/pretty_effect.c b/examples/peripherals/lcd/tjpgd/main/pretty_effect.c index 4d1c43bbee..89fea666b4 100644 --- a/examples/peripherals/lcd/tjpgd/main/pretty_effect.c +++ b/examples/peripherals/lcd/tjpgd/main/pretty_effect.c @@ -12,8 +12,6 @@ #include #include "pretty_effect.h" #include "sdkconfig.h" - -#ifdef CONFIG_IDF_TARGET_ESP32 #include "decode_image.h" uint16_t **pixels; @@ -26,15 +24,6 @@ static inline uint16_t get_bgnd_pixel(int x, int y) y+=8; return pixels[y][x]; } -#else -//esp32s2/c3 doesn't have enough memory to hold the decoded image, calculate instead -//TODO: add support for esp32s3 (IDF-3615) -static inline uint16_t get_bgnd_pixel(int x, int y) -{ - return ((x<<3)^(y<<3)^(x*y)); -} -#endif - //This variable is used to detect the next frame. static int prev_frame=-1; @@ -68,11 +57,5 @@ void pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect) esp_err_t pretty_effect_init(void) { -#ifdef CONFIG_IDF_TARGET_ESP32 return decode_image(&pixels); -#else - //esp32s2/c3 doesn't have enough memory to hold the decoded image, calculate instead - //TODO: add support for esp32s3 (IDF-3615) - return ESP_OK; -#endif } From 92cf32167761d37c5dca7af1649fbf9dde061d4c Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Thu, 19 Aug 2021 16:45:58 +0800 Subject: [PATCH 096/310] freertos: add kconfig options for task snapshot functions Task snapshots is required by other modules that don't use gdbstub or core dump. Add a Kconfig option to manage these possibilities. --- components/esp_gdbstub/Kconfig | 1 + components/espcoredump/Kconfig | 2 ++ components/freertos/Kconfig | 14 ++++++++++++++ .../freertos/include/freertos/FreeRTOSConfig.h | 2 +- components/freertos/linker.lf | 2 +- docs/en/api-guides/performance/ram-usage.rst | 1 + 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/components/esp_gdbstub/Kconfig b/components/esp_gdbstub/Kconfig index 14e7d859c2..e380c34880 100644 --- a/components/esp_gdbstub/Kconfig +++ b/components/esp_gdbstub/Kconfig @@ -4,6 +4,7 @@ menu "GDB Stub" # menu in the target component. config ESP_GDBSTUB_ENABLED bool + select FREERTOS_ENABLE_TASK_SNAPSHOT config ESP_GDBSTUB_SUPPORT_TASKS bool "Enable listing FreeRTOS tasks through GDB Stub" diff --git a/components/espcoredump/Kconfig b/components/espcoredump/Kconfig index 28a54a02a6..a9d7843e50 100644 --- a/components/espcoredump/Kconfig +++ b/components/espcoredump/Kconfig @@ -15,9 +15,11 @@ menu "Core dump" config ESP_COREDUMP_ENABLE_TO_FLASH bool "Flash" depends on !SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY + select FREERTOS_ENABLE_TASK_SNAPSHOT select ESP_COREDUMP_ENABLE config ESP_COREDUMP_ENABLE_TO_UART bool "UART" + select FREERTOS_ENABLE_TASK_SNAPSHOT select ESP_COREDUMP_ENABLE config ESP_COREDUMP_ENABLE_TO_NONE bool "None" diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 3c8b0c1951..0c66f9af8f 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -465,4 +465,18 @@ menu "FreeRTOS" When enabled, the usage of float type is allowed inside Level 1 ISRs. + config FREERTOS_ENABLE_TASK_SNAPSHOT + bool "Enable task snapshot functions" + default y + help + When enabled, the functions related to snapshots, such as vTaskGetSnapshot or uxTaskGetSnapshotAll, + are compiled and linked. + + config FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH + bool "Place task snapshot functions into flash" + default n + depends on FREERTOS_ENABLE_TASK_SNAPSHOT && !ESP_PANIC_HANDLER_IRAM + help + When enabled, the functions related to snapshots, such as vTaskGetSnapshot or uxTaskGetSnapshotAll, + will be placed in flash. Note that if enabled, these functions cannot be called when cache is disabled. endmenu diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 51a030d523..c1dcd1cd48 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -277,7 +277,7 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #endif //configUSE_TICKLESS_IDLE -#if CONFIG_ESP_COREDUMP_ENABLE || CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +#if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT #define configENABLE_TASK_SNAPSHOT 1 #endif #ifndef configENABLE_TASK_SNAPSHOT diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index 23de74c1e7..ee3d8dc02b 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -2,7 +2,7 @@ archive: libfreertos.a entries: * (noflash_text) - if ESP_PANIC_HANDLER_IRAM != y: + if FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH = y: task_snapshot (default) if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y: port: pxPortInitialiseStack (default) diff --git a/docs/en/api-guides/performance/ram-usage.rst b/docs/en/api-guides/performance/ram-usage.rst index 96d3560170..b106cbf6bf 100644 --- a/docs/en/api-guides/performance/ram-usage.rst +++ b/docs/en/api-guides/performance/ram-usage.rst @@ -129,6 +129,7 @@ The following options will reduce IRAM usage of some ESP-IDF features: .. list:: - Enable :ref:`CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH`. Provided these functions are not (incorrectly) used from ISRs, this option is safe to enable in all configurations. + - Enable :ref:`CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH`. Enabling this option will place snapshot-related functions, such as ``vTaskGetSnapshot`` or ``uxTaskGetSnapshotAll``, in flash. - Disable Wi-Fi options :ref:`CONFIG_ESP32_WIFI_IRAM_OPT` and/or :ref:`CONFIG_ESP32_WIFI_RX_IRAM_OPT`. Disabling these options will free available IRAM at the cost of Wi-Fi performance. :esp32c3 or esp32s3: - :ref:`CONFIG_SPI_FLASH_ROM_IMPL` enabling this option will free some IRAM but will mean that esp_flash bugfixes and new flash chip support is not available. :esp32: - :ref:`CONFIG_SPI_FLASH_ROM_DRIVER_PATCH` disabling this option will free some IRAM but is only available in some flash configurations (see the configuration item help text). From 37d549916bd74f2128f6ce35f842914dfb8b9ba1 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Wed, 1 Sep 2021 16:53:07 +0800 Subject: [PATCH 097/310] docs: update asio docs with new example paths after refactor. --- docs/en/api-reference/protocols/asio.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index 559759e9e0..0306a5ae1c 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -36,8 +36,7 @@ ESP examples are based on standard asio :example:`protocols/asio`: - :example:`protocols/asio/udp_echo_server` - :example:`protocols/asio/tcp_echo_server` -- :example:`protocols/asio/chat_client` -- :example:`protocols/asio/chat_server` +- :example:`protocols/asio/asio_chat` - :example:`protocols/asio/ssl_client_server` Please refer to the specific example README.md for details From 8d18a9c614934c7de01f710960c71b46c41b80ee Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 14 Jul 2021 20:03:54 +0800 Subject: [PATCH 098/310] emac: optimise iperf performane --- components/esp_eth/include/esp_eth_mac.h | 2 +- components/esp_eth/src/esp_eth_mac_esp.c | 2 +- components/hal/emac_hal.c | 8 ++++---- components/hal/esp32/include/hal/emac_ll.h | 4 ++-- examples/ethernet/iperf/sdkconfig.defaults | 2 ++ 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/components/esp_eth/include/esp_eth_mac.h b/components/esp_eth/include/esp_eth_mac.h index f1e790c756..db462728a1 100644 --- a/components/esp_eth/include/esp_eth_mac.h +++ b/components/esp_eth/include/esp_eth_mac.h @@ -391,7 +391,7 @@ typedef struct { #define ETH_MAC_DEFAULT_CONFIG() \ { \ .sw_reset_timeout_ms = 100, \ - .rx_task_stack_size = 4096, \ + .rx_task_stack_size = 2048, \ .rx_task_prio = 15, \ .smi_mdc_gpio_num = 23, \ .smi_mdio_gpio_num = 18, \ diff --git a/components/esp_eth/src/esp_eth_mac_esp.c b/components/esp_eth/src/esp_eth_mac_esp.c index 1de969d7a6..bc4e414c6b 100644 --- a/components/esp_eth/src/esp_eth_mac_esp.c +++ b/components/esp_eth/src/esp_eth_mac_esp.c @@ -353,7 +353,7 @@ static esp_err_t emac_esp32_init(esp_eth_mac_t *mac) } ESP_GOTO_ON_FALSE(to < emac->sw_reset_timeout_ms / 10, ESP_ERR_TIMEOUT, err, TAG, "reset timeout"); /* set smi clock */ - emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq()); + emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq() / 1e6); /* reset descriptor chain */ emac_hal_reset_desc_chain(&emac->hal); /* init mac registers by default */ diff --git a/components/hal/emac_hal.c b/components/hal/emac_hal.c index bd202edb34..652e83e753 100644 --- a/components/hal/emac_hal.c +++ b/components/hal/emac_hal.c @@ -141,7 +141,7 @@ void emac_hal_init(emac_hal_context_t *hal, void *descriptors, void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq) { - /* Tell MAC system clock Frequency, which will determine the frequency range of MDC(1MHz~2.5MHz) */ + /* Tell MAC system clock Frequency in MHz, which will determine the frequency range of MDC(1MHz~2.5MHz) */ if (freq >= 20 && freq < 35) { emac_ll_set_csr_clock_division(hal->mac_regs, 2); // CSR clock/16 } else if (freq >= 35 && freq < 60) { @@ -150,7 +150,7 @@ void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq) emac_ll_set_csr_clock_division(hal->mac_regs, 0); // CSR clock/42 } else if (freq >= 100 && freq < 150) { emac_ll_set_csr_clock_division(hal->mac_regs, 1); // CSR clock/62 - } else if (freq > 150 && freq < 250) { + } else if (freq >= 150 && freq < 250) { emac_ll_set_csr_clock_division(hal->mac_regs, 4); // CSR clock/102 } else { emac_ll_set_csr_clock_division(hal->mac_regs, 5); // CSR clock/124 @@ -281,8 +281,8 @@ void emac_hal_init_dma_default(emac_hal_context_t *hal) emac_ll_recv_store_forward_enable(hal->dma_regs, true); /* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */ emac_ll_flush_recv_frame_enable(hal->dma_regs, true); - /* Enable Transmit Store Forward */ - emac_ll_trans_store_forward_enable(hal->dma_regs, true); + /* Disable Transmit Store Forward */ + emac_ll_trans_store_forward_enable(hal->dma_regs, false); /* Flush Transmit FIFO */ emac_ll_flush_trans_fifo_enable(hal->dma_regs, true); /* Transmit Threshold Control */ diff --git a/components/hal/esp32/include/hal/emac_ll.h b/components/hal/esp32/include/hal/emac_ll.h index dff803b5a9..625687b6a0 100644 --- a/components/hal/esp32/include/hal/emac_ll.h +++ b/components/hal/esp32/include/hal/emac_ll.h @@ -137,7 +137,7 @@ extern "C" { #define EMAC_LL_INTR_OVERFLOW_ENABLE 0x00000010U #define EMAC_LL_INTR_UNDERFLOW_ENABLE 0x00000020U #define EMAC_LL_INTR_RECEIVE_ENABLE 0x00000040U -#define EMAC_LL_INTR_REVEIVE_BUFF_UNAVAILABLE_ENABLE 0x00000080U +#define EMAC_LL_INTR_RECEIVE_BUFF_UNAVAILABLE_ENABLE 0x00000080U #define EMAC_LL_INTR_RECEIVE_STOP_ENABLE 0x00000100U #define EMAC_LL_INTR_RECEIVE_TIMEOUT_ENABLE 0x00000200U #define EMAC_LL_INTR_TRANSMIT_FIRST_BYTE_ENABLE 0x00000400U @@ -406,7 +406,7 @@ static inline void emac_ll_flush_recv_frame_enable(emac_dma_dev_t *dma_regs, boo static inline void emac_ll_trans_store_forward_enable(emac_dma_dev_t *dma_regs, bool enable) { - dma_regs->dmaoperation_mode.tx_str_fwd = !enable; + dma_regs->dmaoperation_mode.tx_str_fwd = enable; } static inline void emac_ll_flush_trans_fifo_enable(emac_dma_dev_t *dma_regs, bool enable) diff --git a/examples/ethernet/iperf/sdkconfig.defaults b/examples/ethernet/iperf/sdkconfig.defaults index 9ef48f281a..d478e33a60 100644 --- a/examples/ethernet/iperf/sdkconfig.defaults +++ b/examples/ethernet/iperf/sdkconfig.defaults @@ -12,4 +12,6 @@ CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESP_TASK_WDT=n + CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n From 04970fe4873ac94ce5c12954be3c03ad29bf4ba1 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 25 Aug 2021 13:31:34 +0800 Subject: [PATCH 099/310] iperfUtility: add udp rx bandwidth scan --- .gitlab/ci/target-test.yml | 2 +- components/esp_eth/src/esp_eth_mac_esp.c | 2 +- components/hal/emac_hal.c | 10 +++--- examples/ethernet/iperf/sdkconfig.defaults | 5 +++ .../idf_iperf_test_util/IperfUtility.py | 33 +++++++++++-------- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 8b4ecfaba9..8138264e11 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -129,7 +129,7 @@ example_test_002: - ESP32 - Example_ShieldBox_Basic -example_test_enternet: +example_test_ethernet: extends: .example_test_esp32_template tags: - ESP32 diff --git a/components/esp_eth/src/esp_eth_mac_esp.c b/components/esp_eth/src/esp_eth_mac_esp.c index bc4e414c6b..1de969d7a6 100644 --- a/components/esp_eth/src/esp_eth_mac_esp.c +++ b/components/esp_eth/src/esp_eth_mac_esp.c @@ -353,7 +353,7 @@ static esp_err_t emac_esp32_init(esp_eth_mac_t *mac) } ESP_GOTO_ON_FALSE(to < emac->sw_reset_timeout_ms / 10, ESP_ERR_TIMEOUT, err, TAG, "reset timeout"); /* set smi clock */ - emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq() / 1e6); + emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq()); /* reset descriptor chain */ emac_hal_reset_desc_chain(&emac->hal); /* init mac registers by default */ diff --git a/components/hal/emac_hal.c b/components/hal/emac_hal.c index 652e83e753..ef6318ff7e 100644 --- a/components/hal/emac_hal.c +++ b/components/hal/emac_hal.c @@ -142,15 +142,15 @@ void emac_hal_init(emac_hal_context_t *hal, void *descriptors, void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq) { /* Tell MAC system clock Frequency in MHz, which will determine the frequency range of MDC(1MHz~2.5MHz) */ - if (freq >= 20 && freq < 35) { + if (freq >= 20000000 && freq < 35000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 2); // CSR clock/16 - } else if (freq >= 35 && freq < 60) { + } else if (freq >= 35000000 && freq < 60000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 3); // CSR clock/26 - } else if (freq >= 60 && freq < 100) { + } else if (freq >= 60000000 && freq < 100000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 0); // CSR clock/42 - } else if (freq >= 100 && freq < 150) { + } else if (freq >= 100000000 && freq < 150000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 1); // CSR clock/62 - } else if (freq >= 150 && freq < 250) { + } else if (freq >= 150000000 && freq < 250000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 4); // CSR clock/102 } else { emac_ll_set_csr_clock_division(hal->mac_regs, 5); // CSR clock/124 diff --git a/examples/ethernet/iperf/sdkconfig.defaults b/examples/ethernet/iperf/sdkconfig.defaults index d478e33a60..3b0e1692f9 100644 --- a/examples/ethernet/iperf/sdkconfig.defaults +++ b/examples/ethernet/iperf/sdkconfig.defaults @@ -10,8 +10,13 @@ CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" CONFIG_FREERTOS_USE_TRACE_FACILITY=y CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# Run FreeRTOS only on the first core +CONFIG_FREERTOS_UNICORE=y + CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# Disable watch dog +CONFIG_ESP_INT_WDT=n CONFIG_ESP_TASK_WDT=n CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n diff --git a/tools/ci/python_packages/idf_iperf_test_util/IperfUtility.py b/tools/ci/python_packages/idf_iperf_test_util/IperfUtility.py index 165c232140..3ff645124e 100644 --- a/tools/ci/python_packages/idf_iperf_test_util/IperfUtility.py +++ b/tools/ci/python_packages/idf_iperf_test_util/IperfUtility.py @@ -14,7 +14,7 @@ except ImportError: pass # configurations -TEST_TIME = TEST_TIMEOUT = 60 +TEST_TIME = TEST_TIMEOUT = 66 WAIT_AP_POWER_ON_TIMEOUT = 90 SCAN_TIMEOUT = 3 SCAN_RETRY_COUNT = 3 @@ -96,6 +96,7 @@ class TestResult(object): """ fall_to_0_recorded = 0 throughput_list = [] + throughput = 0.0 result_list = self.PC_BANDWIDTH_LOG_PATTERN.findall(raw_data) if not result_list: # failed to find raw data by PC pattern, it might be DUT pattern @@ -106,6 +107,7 @@ class TestResult(object): # this could be summary, ignore this continue throughput_list.append(float(result[2])) + throughput = (throughput if (throughput > float(result[2])) else float(result[2])) if float(result[2]) == 0 and rssi > self.ZERO_POINT_THRESHOLD \ and fall_to_0_recorded < 1: # throughput fall to 0 error. we only record 1 records for one test @@ -113,9 +115,7 @@ class TestResult(object): .format(ap_ssid, att, rssi, result[0], result[1])) fall_to_0_recorded += 1 - if len(throughput_list) > self.THROUGHPUT_QUALIFY_COUNT: - throughput = sum(throughput_list) / len(throughput_list) - else: + if len(throughput_list) < self.THROUGHPUT_QUALIFY_COUNT: throughput = 0.0 if throughput == 0 and rssi > self.ZERO_THROUGHPUT_THRESHOLD: @@ -330,6 +330,12 @@ class IperfTestUtility(object): process = subprocess.Popen(['iperf', '-c', dut_ip, '-t', str(TEST_TIME), '-f', 'm'], stdout=f, stderr=f) + for _ in range(TEST_TIMEOUT): + if process.poll() is not None: + break + time.sleep(1) + else: + process.terminate() else: self.dut.write('iperf -s -u -i 1 -t {}'.format(TEST_TIME)) # wait until DUT TCP server created @@ -338,16 +344,15 @@ class IperfTestUtility(object): except DUT.ExpectTimeout: # compatible with old iperf example binary Utility.console_log('create iperf udp server fail') - process = subprocess.Popen(['iperf', '-c', dut_ip, '-u', '-b', '100M', - '-t', str(TEST_TIME), '-f', 'm'], - stdout=f, stderr=f) - - for _ in range(TEST_TIMEOUT): - if process.poll() is not None: - break - time.sleep(1) - else: - process.terminate() + for bandwidth in range(50, 101, 5): + process = subprocess.Popen(['iperf', '-c', dut_ip, '-u', '-b', str(bandwidth) + 'm', + '-t', str(TEST_TIME / 11), '-f', 'm'], stdout=f, stderr=f) + for _ in range(TEST_TIMEOUT): + if process.poll() is not None: + break + time.sleep(1) + else: + process.terminate() server_raw_data = self.dut.read() with open(PC_IPERF_TEMP_LOG_FILE, 'r') as f: From 461f2bd186ec2032c7dbe965dc81addd8f8d6a58 Mon Sep 17 00:00:00 2001 From: XieWenxiang Date: Tue, 17 Aug 2021 11:22:28 +0800 Subject: [PATCH 100/310] component/bt: fix some ble document description error --- components/bt/host/bluedroid/api/include/api/esp_gattc_api.h | 2 +- .../ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md | 2 +- .../ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h b/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h index 077cca3850..4071909634 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h @@ -380,7 +380,7 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, /** * @brief Find all the service with the given service uuid in the gattc cache, if the svc_uuid is NULL, find all the service. * Note: It just get service from local cache, won't get from remote devices. If want to get it from remote device, need - * to used the esp_ble_gattc_search_service. + * to used the esp_ble_gattc_cache_refresh, then call esp_ble_gattc_get_service again. * * @param[in] gattc_if: Gatt client access interface. * @param[in] conn_id: connection ID which identify the server. diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md index 68acc482b9..ba40fdc5f9 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md @@ -209,7 +209,7 @@ static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = { }; ``` -The initialization of the Application Profile table array includes defining the callback functions for each Profile. These are `gattc_profile_a_event_handler()` and `gattc_profile_a_event_handler()` respectively. In addition, the GATT interface is initialized to the default value of `ESP_GATT_IF_NONE`. Later on, when the Application Profile is registered, the BLE stack returns a GATT interface instance to use with that Application Profile. +The initialization of the Application Profile table array includes defining the callback function for Profile. It is `gattc_profile_event_handler()`. In addition, the GATT interface is initialized to the default value of `ESP_GATT_IF_NONE`. Later on, when the Application Profile is registered, the BLE stack returns a GATT interface instance to use with that Application Profile. The profile registration triggers an `ESP_GATTC_REG_EVT` event, which is handled by the `esp_gattc_cb()` event handler. The handler takes the GATT interface returned by the event and stores it in the profile table: diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md index 89dea52147..2f7ccdba80 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md @@ -430,7 +430,7 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_ ## Creating Services -The register event is also used to create a profile attributes table by using the `esp_ble_gatts_create_attr_tab()` function, which takes an `esp_gatts_attr_db_t` type structure that has all the information of the service table. The way to create this table is: +The register event is also used to create a service by using the `esp_ble_gatts_create_service()`. When service creation is done, a callback event ESP_GATTS_CREATE_EVT is called to report status and service ID to the profile. The way to create service is: ```c … From 359670e080bb05a9fec98848d9cd1fec242afff9 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 31 Aug 2021 11:13:07 +0200 Subject: [PATCH 101/310] Docs: Use badges instead of emojis in the support table of the README Closes https://github.com/espressif/esp-idf/pull/7497 --- README.md | 19 +++++++++++-------- README_CN.md | 19 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 903560c080..73b855e398 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,18 @@ ESP-IDF is the development framework for Espressif SoCs supported on Windows, Li # ESP-IDF Release and SoC Compatibility -The following table shows ESP-IDF support of Espressif SoCs where :yellow_circle: and :green_circle: denote preview status and support, respectively. In preview status the build is not yet enabled and some crucial parts could be missing (like documentation, datasheet). Please use an ESP-IDF release where the desired SoC is already supported. +The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. In preview status the build is not yet enabled and some crucial parts could be missing (like documentation, datasheet). Please use an ESP-IDF release where the desired SoC is already supported. -|Chip | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | -|:----------- |:-------------: | :-------------:| :-------------:| :-------------:| :-------------:| :-------------:|:---------------------------------------------------------- | -|ESP32 | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | | -|ESP32-S2 | | | | :green_circle: | :green_circle: | :green_circle: | | -|ESP32-C3 | | | | | :green_circle: | :green_circle: | | -|ESP32-S3 | | | | | :yellow_circle:| :green_circle: | [Announcement](https://www.espressif.com/en/news/ESP32_S3) | -|ESP32-H2 | | | | | | :yellow_circle:| [Announcement](https://www.espressif.com/en/news/ESP32_H2) | +|Chip | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | +|:----------- |:---------------------: | :---------------------:| :---------------------:| :---------------------:| :---------------------:| :---------------------:|:---------------------------------------------------------- | +|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S2 | | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-C3 | | | | | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S3 | | | | | ![alt text][preview] | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32_S3) | +|ESP32-H2 | | | | | | ![alt text][preview] | [Announcement](https://www.espressif.com/en/news/ESP32_H2) | + +[supported]: https://img.shields.io/badge/-supported-green "supported" +[preview]: https://img.shields.io/badge/-preview-orange "preview" Espressif SoCs released before 2016 (ESP8266 and ESP8285) are supported by [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead. diff --git a/README_CN.md b/README_CN.md index 97b26ec620..123bea47ba 100644 --- a/README_CN.md +++ b/README_CN.md @@ -6,15 +6,18 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux # ESP-IDF 与乐鑫芯片 -下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 :green_circle: 代表已支持,:yellow_circle: 代表目前处于预览支持状态。在预览支持阶段,因为新芯片尚未完全添加到构建系统目录,所以一些重要的内容(如文档和技术规格书等)可能会缺失。请确保使用与芯片相匹配的 ESP-IDF 版本。 +下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。在预览支持阶段,因为新芯片尚未完全添加到构建系统目录,所以一些重要的内容(如文档和技术规格书等)可能会缺失。请确保使用与芯片相匹配的 ESP-IDF 版本。 -| 芯片 | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | -|:----------- |:-------------: | :-------------:| :-------------:| :-------------:| :-------------:| :-------------:|:---------------------------------------------------------- | -|ESP32 | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | :green_circle: | | -|ESP32-S2 | | | | :green_circle: | :green_circle: | :green_circle: | | -|ESP32-C3 | | | | | :green_circle: | :green_circle: | | -|ESP32-S3 | | | | | :yellow_circle:| :green_circle: | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) | -|ESP32-H2 | | | | | | :yellow_circle:| [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) | +| 芯片 | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | +|:----------- |:---------------------: | :---------------------:| :---------------------:| :---------------------:| :---------------------:| :---------------------:|:---------------------------------------------------------- | +|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S2 | | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | +|ESP32-C3 | | | | | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S3 | | | | | ![alt text][preview] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/en/news/ESP32_S3) | +|ESP32-H2 | | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/en/news/ESP32_H2) | + +[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported" +[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview" 对于 2016 年之前发布的乐鑫芯片(包括 ESP8266 和 ESP8285),请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。 From 036aae0a2c4c54e3df0171ea2acd87a79e44843f Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 1 Sep 2021 19:39:17 +0200 Subject: [PATCH 102/310] github: remove lint jobs for unsupported python versions --- .github/workflows/python_lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_lint.yml b/.github/workflows/python_lint.yml index b62552fe87..5e36177855 100644 --- a/.github/workflows/python_lint.yml +++ b/.github/workflows/python_lint.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8] steps: - name: Checkout From f7137254e94def968a4c91379a0f7542eb9082f7 Mon Sep 17 00:00:00 2001 From: jiangguangming Date: Mon, 28 Sep 2020 10:19:56 +0800 Subject: [PATCH 103/310] flash_mmap: register flash2spiram info to ROM --- components/esp_system/port/cpu_start.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index b51efe895e..0e5498ee64 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -359,9 +359,11 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 /* Configure the Cache MMU size for instruction and rodata in flash. */ extern uint32_t Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size); - extern int _rodata_reserved_start; + extern int _rodata_reserved_start, _rodata_reserved_end; uint32_t rodata_reserved_start_align = (uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1); uint32_t cache_mmu_irom_size = ((rodata_reserved_start_align - SOC_DROM_LOW) / MMU_PAGE_SIZE) * sizeof(uint32_t); + uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE)*sizeof(uint32_t); + Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); #endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 @@ -437,6 +439,8 @@ void IRAM_ATTR call_start_cpu0(void) } #endif + static int s_instr_flash2spiram_off = 0; + static int s_rodata_flash2spiram_off = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS extern void instruction_flash_page_info_init(void); instruction_flash_page_info_init(); @@ -449,10 +453,22 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS extern void esp_spiram_enable_instruction_access(void); esp_spiram_enable_instruction_access(); + s_instr_flash2spiram_off = instruction_flash2spiram_offset(); #endif #if CONFIG_SPIRAM_RODATA extern void esp_spiram_enable_rodata_access(void); esp_spiram_enable_rodata_access(); + s_rodata_flash2spiram_off = rodata_flash2spiram_offset(); +#endif + +#if CONFIG_IDF_TARGET_ESP32S3 + extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off); + Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size/sizeof(uint32_t), \ + cache_mmu_drom_size/sizeof(uint32_t), \ + (uint32_t)&_rodata_reserved_start, \ + (uint32_t)&_rodata_reserved_end, \ + s_instr_flash2spiram_off, \ + s_rodata_flash2spiram_off); #endif #if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP From 191a494e08f6779b96743ee722a3c03da19173dd Mon Sep 17 00:00:00 2001 From: gaoxiaojie Date: Sat, 10 Oct 2020 16:22:49 +0800 Subject: [PATCH 104/310] support dcache 64Byte and 16k --- components/esp32s3/Kconfig | 6 +++- components/esp_system/port/cpu_start.c | 31 +++++++++++++++----- components/heap/port/esp32s3/memory_layout.c | 9 ++++-- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/components/esp32s3/Kconfig b/components/esp32s3/Kconfig index 044d7c593c..b59910fae4 100644 --- a/components/esp32s3/Kconfig +++ b/components/esp32s3/Kconfig @@ -108,7 +108,8 @@ menu "ESP32S3-Specific" config ESP32S3_DATA_CACHE_SIZE hex - default 0x4000 if ESP32S3_DATA_CACHE_16KB + # For 16KB the actual configuration is 32kb cache, but 16kb will be reserved for heap at startup + default 0x8000 if ESP32S3_DATA_CACHE_16KB default 0x8000 if ESP32S3_DATA_CACHE_32KB default 0x10000 if ESP32S3_DATA_CACHE_64KB @@ -140,12 +141,15 @@ menu "ESP32S3-Specific" depends on ESP32S3_DATA_CACHE_16KB || ESP32S3_DATA_CACHE_32KB config ESP32S3_DATA_CACHE_LINE_32B bool "32 Bytes" + config ESP32S3_DATA_CACHE_LINE_64B + bool "64 Bytes" endchoice config ESP32S3_DATA_CACHE_LINE_SIZE int default 16 if ESP32S3_DATA_CACHE_LINE_16B default 32 if ESP32S3_DATA_CACHE_LINE_32B + default 64 if ESP32S3_DATA_CACHE_LINE_64B config ESP32S3_DATA_CACHE_WRAP bool "Enable data cache wrap mode" diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 0e5498ee64..5b76be681c 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -359,10 +359,14 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 /* Configure the Cache MMU size for instruction and rodata in flash. */ extern uint32_t Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size); - extern int _rodata_reserved_start, _rodata_reserved_end; + extern int _rodata_reserved_start; uint32_t rodata_reserved_start_align = (uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1); uint32_t cache_mmu_irom_size = ((rodata_reserved_start_align - SOC_DROM_LOW) / MMU_PAGE_SIZE) * sizeof(uint32_t); + +#if CONFIG_IDF_TARGET_ESP32S3 + extern int _rodata_reserved_end; uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE)*sizeof(uint32_t); +#endif Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); #endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 @@ -439,8 +443,6 @@ void IRAM_ATTR call_start_cpu0(void) } #endif - static int s_instr_flash2spiram_off = 0; - static int s_rodata_flash2spiram_off = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS extern void instruction_flash_page_info_init(void); instruction_flash_page_info_init(); @@ -453,15 +455,22 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS extern void esp_spiram_enable_instruction_access(void); esp_spiram_enable_instruction_access(); - s_instr_flash2spiram_off = instruction_flash2spiram_offset(); #endif #if CONFIG_SPIRAM_RODATA extern void esp_spiram_enable_rodata_access(void); esp_spiram_enable_rodata_access(); - s_rodata_flash2spiram_off = rodata_flash2spiram_offset(); #endif #if CONFIG_IDF_TARGET_ESP32S3 + int s_instr_flash2spiram_off = 0; + int s_rodata_flash2spiram_off = 0; +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + s_instr_flash2spiram_off = instruction_flash2spiram_offset(); +#endif +#if CONFIG_SPIRAM_RODATA + s_rodata_flash2spiram_off = rodata_flash2spiram_offset(); +#endif + extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off); Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size/sizeof(uint32_t), \ cache_mmu_drom_size/sizeof(uint32_t), \ @@ -471,18 +480,24 @@ void IRAM_ATTR call_start_cpu0(void) s_rodata_flash2spiram_off); #endif -#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP +#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP || \ + CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S3_DATA_CACHE_WRAP uint32_t icache_wrap_enable = 0, dcache_wrap_enable = 0; -#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP +#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP icache_wrap_enable = 1; #endif -#if CONFIG_ESP32S2_DATA_CACHE_WRAP +#if CONFIG_ESP32S2_DATA_CACHE_WRAP || CONFIG_ESP32S3_DATA_CACHE_WRAP dcache_wrap_enable = 1; #endif extern void esp_enable_cache_wrap(uint32_t icache_wrap_enable, uint32_t dcache_wrap_enable); esp_enable_cache_wrap(icache_wrap_enable, dcache_wrap_enable); #endif +#if CONFIG_ESP32S3_DATA_CACHE_16KB + Cache_Invalidate_DCache_All(); + Cache_Occupy_Addr(SOC_DROM_LOW, 0x4000); +#endif + #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY memset(&_ext_ram_bss_start, 0, (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start)); #endif diff --git a/components/heap/port/esp32s3/memory_layout.c b/components/heap/port/esp32s3/memory_layout.c index 6a7cfc4869..1bd6ad62fc 100644 --- a/components/heap/port/esp32s3/memory_layout.c +++ b/components/heap/port/esp32s3/memory_layout.c @@ -44,6 +44,8 @@ const soc_memory_type_desc_t soc_memory_types[] = { { "IRAM", { MALLOC_CAP_EXEC | MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, 0, 0 }, false, false}, // Type 4: SPI SRAM data { "SPIRAM", { MALLOC_CAP_SPIRAM | MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT}, false, false}, + // Type 5: DRAM which is not DMA accesible + { "NON_DMA_DRAM", { MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT, 0 }, false, false}, }; const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memory_type_desc_t); @@ -69,11 +71,12 @@ const soc_memory_region_t soc_memory_regions[] = { { 0x3FCC0000, 0x10000, 2, 0x403B0000}, //Level 6, IDRAM, can be used as trace memroy { 0x3FCD0000, 0x10000, 2, 0x403C0000}, //Level 7, IDRAM, can be used as trace memroy { 0x3FCE0000, 0x10000, 1, 0}, //Level 8, IDRAM, can be used as trace memroy, contains stacks used by startup flow, recycled by heap allocator in app_main task -#if CONFIG_ESP32S3_DATA_CACHE_16KB - { 0x3FCF0000, 0xC000, 0, 0}, //Level 9, DRAM -#elif CONFIG_ESP32S3_DATA_CACHE_32KB +#if CONFIG_ESP32S3_DATA_CACHE_16KB || CONFIG_ESP32S3_DATA_CACHE_32KB { 0x3FCF0000, 0x8000, 0, 0}, //Level 9, DRAM #endif +#if CONFIG_ESP32S3_DATA_CACHE_16KB + { 0x3C000000, 0x4000, 5, 0} +#endif #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP { 0x50000000, 0x2000, 4, 0}, //Fast RTC memory #endif From c3abbe38668d71997b8b721926f21345de881858 Mon Sep 17 00:00:00 2001 From: wanglei Date: Fri, 30 Jul 2021 11:43:40 +0800 Subject: [PATCH 105/310] cache: Update cache.h and autoload api --- .../esp_rom/include/esp32s3/rom/cache.h | 115 +++++++++++++++--- 1 file changed, 98 insertions(+), 17 deletions(-) diff --git a/components/esp_rom/include/esp32s3/rom/cache.h b/components/esp_rom/include/esp32s3/rom/cache.h index 0ec6308f7c..27780446fe 100644 --- a/components/esp_rom/include/esp32s3/rom/cache.h +++ b/components/esp_rom/include/esp32s3/rom/cache.h @@ -103,6 +103,11 @@ typedef enum { CACHE_AUTOLOAD_NEGATIVE = 1, /*!< cache autoload step is negative */ } cache_autoload_order_t; +typedef enum { + CACHE_AUTOLOAD_REGION0 = 0, /*!< cache autoload region0 */ + CACHE_AUTOLOAD_REGION1 = 1, /*!< cache autoload region1 */ +} cache_autoload_region_t; + #define CACHE_AUTOLOAD_STEP(i) ((i) - 1) typedef enum { @@ -144,14 +149,17 @@ struct dcache_tag_item { }; struct autoload_config { + uint8_t ena; /*!< autoload enable */ uint8_t order; /*!< autoload step is positive or negative */ uint8_t trigger; /*!< autoload trigger */ - uint8_t ena0; /*!< autoload region0 enable */ - uint8_t ena1; /*!< autoload region1 enable */ - uint32_t addr0; /*!< autoload region0 start address */ - uint32_t size0; /*!< autoload region0 size */ - uint32_t addr1; /*!< autoload region1 start address */ - uint32_t size1; /*!< autoload region1 size */ + uint8_t size; /*!< autoload size */ +}; + +struct autoload_region_config { + uint8_t region; /*!< autoload region*/ + uint8_t ena; /*!< autoload region enable */ + uint32_t addr; /*!< autoload region start address */ + uint32_t size; /*!< autoload region size */ }; struct tag_group_info { @@ -160,6 +168,7 @@ struct tag_group_info { uint32_t vaddr_offset; /*!< virtual address offset of the cache ways */ uint32_t tag_addr[MAX_CACHE_WAYS]; /*!< tag memory address, only [0~mode.ways-1] is valid to use */ uint32_t cache_memory_offset[MAX_CACHE_WAYS]; /*!< cache memory address, only [0~mode.ways-1] is valid to use */ + uint8_t use_legacy; /*!< 1 for using legacy tag api, 0 for using 2rd tag api */ }; struct lock_config { @@ -168,6 +177,39 @@ struct lock_config { uint16_t group; /*!< manual lock group, 0 or 1*/ }; +struct cache_internal_stub_table { + uint32_t (* icache_line_size)(void); + uint32_t (* dcache_line_size)(void); + uint32_t (* icache_addr)(uint32_t addr); + uint32_t (* dcache_addr)(uint32_t addr); + void (* invalidate_icache_items)(uint32_t addr, uint32_t items); + void (* invalidate_dcache_items)(uint32_t addr, uint32_t items); + void (* clean_items)(uint32_t addr, uint32_t items); + void (* writeback_items)(uint32_t addr, uint32_t items); + void (* lock_icache_items)(uint32_t addr, uint32_t items); + void (* lock_dcache_items)(uint32_t addr, uint32_t items); + void (* unlock_icache_items)(uint32_t addr, uint32_t items); + void (* unlock_dcache_items)(uint32_t addr, uint32_t items); + void (* occupy_items)(uint32_t addr, uint32_t items); + uint32_t (* suspend_icache_autoload)(void); + void (* resume_icache_autoload)(uint32_t autoload); + uint32_t (* suspend_dcache_autoload)(void); + void (* resume_dcache_autoload)(uint32_t autoload); + void (* freeze_icache_enable)(cache_freeze_mode_t mode); + void (* freeze_icache_disable)(void); + void (* freeze_dcache_enable)(cache_freeze_mode_t mode); + void (* freeze_dcache_disable)(void); + int (* op_addr)(uint32_t op_icache, uint32_t start_addr, uint32_t size, uint32_t cache_line_size, uint32_t max_sync_num, void(* cache_Iop)(uint32_t, uint32_t), void(* cache_Dop)(uint32_t, uint32_t)); +}; + +typedef void (* cache_op_start)(void); +typedef void (* cache_op_end)(void); + +typedef struct { + cache_op_start start; + cache_op_end end; +} cache_op_cb_t; + #define ESP_ROM_ERR_INVALID_ARG 1 #define MMU_SET_ADDR_ALIGNED_ERROR 2 #define MMU_SET_PASE_SIZE_ERROR 3 @@ -190,7 +232,7 @@ void Cache_MMU_Init(void); * @brief Set ICache mmu mapping. * Please do not call this function in your SDK application. * - * @param uint32_t ext_ram : DPORT_MMU_ACCESS_FLASH for flash, DPORT_MMU_ACCESS_SPIRAM for spiram, DPORT_MMU_INVALID for invalid. + * @param uint32_t ext_ram : MMU_ACCESS_FLASH for flash, MMU_ACCESS_SPIRAM for spiram, MMU_INVALID for invalid. * * @param uint32_t vaddr : virtual address in CPU address space. * Can be Iram0,Iram1,Irom0,Drom0 and AHB buses address. @@ -217,7 +259,7 @@ int Cache_Ibus_MMU_Set(uint32_t ext_ram, uint32_t vaddr, uint32_t paddr, uint32 * @brief Set DCache mmu mapping. * Please do not call this function in your SDK application. * - * @param uint32_t ext_ram : DPORT_MMU_ACCESS_FLASH for flash, DPORT_MMU_ACCESS_SPIRAM for spiram, DPORT_MMU_INVALID for invalid. + * @param uint32_t ext_ram : MMU_ACCESS_FLASH for flash, MMU_ACCESS_SPIRAM for spiram, MMU_INVALID for invalid. * * @param uint32_t vaddr : virtual address in CPU address space. * Can be DRam0, DRam1, DRom0, DPort and AHB buses address. @@ -272,9 +314,9 @@ uint32_t Cache_Flash_To_SPIRAM_Copy(uint32_t bus, uint32_t bus_start_addr, uint3 * @brief allocate memory to used by ICache. * Please do not call this function in your SDK application. * - * @param cache_array_t icache_low : the data array bank used by icache low part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_IBANK0, CACHE_MEMORY_IBANK1 + * @param cache_array_t icache_low : the data array bank used by icache low part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, CACHE_MEMORY_IBANK0 * - * @param cache_array_t icache_high : the data array bank used by icache high part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_IBANK0, CACHE_MEMORY_IBANK1 only if icache_low and icache_high is not CACHE_MEMORY_INVALID + * @param cache_array_t icache_high : the data array bank used by icache high part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, or CACHE_MEMORY_IBANK1 only if icache_low and icache_high is CACHE_MEMORY_IBANK0 * * return none */ @@ -284,9 +326,9 @@ void Cache_Occupy_ICache_MEMORY(cache_array_t icache_low, cache_array_t icache_h * @brief allocate memory to used by DCache. * Please do not call this function in your SDK application. * - * @param cache_array_t dcache_low : the data array bank used by dcache low part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_DBANK0, CACHE_MEMORY_DBANK1 + * @param cache_array_t dcache_low : the data array bank used by dcache low part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, CACHE_MEMORY_DBANK1 * - * @param cache_array_t dcache1_high : the data array bank used by dcache high part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_DBANK0, CACHE_MEMORY_DBANK1 only if dcache_low0 and dcache_low1 is not CACHE_MEMORY_INVALID + * @param cache_array_t dcache1_high : the data array bank used by dcache high part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, or CACHE_MEMORY_DBANK0 only if dcache_low0 and dcache_low1 is CACHE_MEMORY_DBANK1 * * return none */ @@ -310,7 +352,7 @@ void Cache_Get_Mode(struct cache_mode *mode); * * @param cache_ways_t ways : the associate ways of cache, can be CACHE_4WAYS_ASSOC and CACHE_8WAYS_ASSOC * - * @param cache_line_size_t cache_line_size : the cache line size, can be CACHE_LINE_SIZE_16B, CACHE_LINE_SIZE_32B and CACHE_LINE_SIZE_64B + * @param cache_line_size_t cache_line_size : the cache line size, can be CACHE_LINE_SIZE_16B and CACHE_LINE_SIZE_32B * * return none */ @@ -320,9 +362,9 @@ void Cache_Set_ICache_Mode(cache_size_t cache_size, cache_ways_t ways, cache_lin * @brief set DCache modes: cache size, associate ways and cache line size. * Please do not call this function in your SDK application. * - * @param cache_size_t cache_size : the cache size, can be CACHE_SIZE_8KB and CACHE_SIZE_16KB + * @param cache_size_t cache_size : the cache size, can be CACHE_SIZE_HALF and CACHE_SIZE_FULL * - * @param cache_ways_t ways : the associate ways of cache, can be CACHE_4WAYS_ASSOC and CACHE_8WAYS_ASSOC + * @param cache_ways_t ways : the associate ways of cache, can be CACHE_4WAYS_ASSOC and CACHE_8WAYS_ASSOC, only CACHE_4WAYS_ASSOC works * * @param cache_line_size_t cache_line_size : the cache line size, can be CACHE_LINE_SIZE_16B, CACHE_LINE_SIZE_32B and CACHE_LINE_SIZE_64B * @@ -351,7 +393,7 @@ uint32_t Cache_Address_Through_ICache(uint32_t addr); uint32_t Cache_Address_Through_DCache(uint32_t addr); /** - * @brief Init mmu owner register to make i/d cache use half mmu entries. + * @brief Init Cache for ROM boot, including resetting the Dcache, initializing Owner, MMU, setting DCache mode, Enabling DCache, unmasking bus. * * @param None * @@ -636,6 +678,16 @@ void Cache_End_DCache_Preload(uint32_t autoload); */ void Cache_Config_ICache_Autoload(const struct autoload_config *config); +/** + * @brief Config region autoload parameters of ICache. + * Please do not call this function in your SDK application. + * + * @param struct autoload_region_config * config : region autoload parameters. + * + * @return ESP_ROM_ERR_INVALID_ARG : invalid param, 0 : success + */ +int Cache_Config_ICache_Region_Autoload(const struct autoload_region_config *config); + /** * @brief Enable auto preload for ICache. * Please do not call this function in your SDK application. @@ -666,6 +718,16 @@ void Cache_Disable_ICache_Autoload(void); */ void Cache_Config_DCache_Autoload(const struct autoload_config *config); +/** + * @brief Config region autoload parameters of DCache. + * Please do not call this function in your SDK application. + * + * @param struct autoload_region_config * config : region autoload parameters. + * + * @return ESP_ROM_ERR_INVALID_ARG : invalid param, 0 : success + */ +int Cache_Config_DCache_Region_Autoload(const struct autoload_region_config *config); + /** * @brief Enable auto preload for DCache. * Please do not call this function in your SDK application. @@ -1008,7 +1070,24 @@ void Cache_Freeze_DCache_Disable(void); * * @return None */ -void Cache_Travel_Tag_Memory(struct cache_mode *mode, uint32_t filter_addr, void (* process)(struct tag_group_info *)); +void Cache_Travel_Tag_Memory(struct cache_mode * mode, uint32_t filter_addr, void (* process)(struct tag_group_info *)); + +/** + * @brief Travel tag memory to run a call back function, using 2nd tag registers. + * ICache and DCache are suspend when doing this. + * The callback will get the parameter tag_group_info, which will include a group of tag memory addresses and cache memory addresses. + * Please do not call this function in your SDK application. + * + * @param struct cache_mode * mode : the cache to check and the cache mode. + * + * @param uint32_t filter_addr : only the cache lines which may include the filter_address will be returned to the call back function. + * 0 for do not filter, all cache lines will be returned. + * + * @param void (* process)(struct tag_group_info *) : call back function, which may be called many times, a group(the addresses in the group are in the same position in the cache ways) a time. + * + * @return None + */ +void Cache_Travel_Tag_Memory2(struct cache_mode * mode, uint32_t filter_addr, void (* process)(struct tag_group_info *)); /** * @brief Get the virtual address from cache mode, cache tag and the virtual address offset of cache ways. @@ -1092,6 +1171,8 @@ int flash2spiram_rodata_offset(void); uint32_t flash_instr_rodata_start_page(uint32_t bus); uint32_t flash_instr_rodata_end_page(uint32_t bus); +extern struct cache_internal_stub_table* rom_cache_internal_table_ptr; +extern cache_op_cb_t rom_cache_op_cb; #ifdef __cplusplus } #endif From 4869b3cd4a167f25b849f9d4f32003f0808e81ca Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Mon, 30 Aug 2021 11:30:12 +0800 Subject: [PATCH 106/310] WDT: Add support for XTAL32K Watchdog timer --- components/esp32/Kconfig | 1 + components/esp32c3/Kconfig | 1 + components/esp32h2/Kconfig | 1 + components/esp32s2/Kconfig | 1 + components/esp32s3/Kconfig | 1 + .../esp_hw_support/port/esp32c3/rtc_time.c | 4 + .../esp_hw_support/port/esp32s2/rtc_time.c | 3 + .../esp_hw_support/port/esp32s3/rtc_time.c | 3 + components/esp_system/CMakeLists.txt | 3 +- components/esp_system/Kconfig | 31 ++++++ components/esp_system/include/esp_xt_wdt.h | 63 +++++++++++ components/esp_system/startup.c | 10 ++ components/esp_system/xt_wdt.c | 95 ++++++++++++++++ components/hal/CMakeLists.txt | 3 + components/hal/component.mk | 2 +- .../hal/esp32c3/include/hal/xt_wdt_ll.h | 101 ++++++++++++++++++ .../hal/esp32s2/include/hal/xt_wdt_ll.h | 101 ++++++++++++++++++ .../hal/esp32s3/include/hal/xt_wdt_ll.h | 101 ++++++++++++++++++ components/hal/include/hal/xt_wdt_hal.h | 61 +++++++++++ components/hal/xt_wdt_hal.c | 78 ++++++++++++++ components/soc/esp32c3/include/soc/rtc.h | 3 +- components/soc/esp32c3/include/soc/soc_caps.h | 4 +- components/soc/esp32s2/include/soc/rtc.h | 3 +- components/soc/esp32s2/include/soc/soc_caps.h | 1 + components/soc/esp32s3/include/soc/rtc.h | 3 +- components/soc/esp32s3/include/soc/soc_caps.h | 2 + docs/en/api-reference/system/wdts.rst | 26 ++++- 27 files changed, 697 insertions(+), 9 deletions(-) create mode 100644 components/esp_system/include/esp_xt_wdt.h create mode 100644 components/esp_system/xt_wdt.c create mode 100644 components/hal/esp32c3/include/hal/xt_wdt_ll.h create mode 100644 components/hal/esp32s2/include/hal/xt_wdt_ll.h create mode 100644 components/hal/esp32s3/include/hal/xt_wdt_ll.h create mode 100644 components/hal/include/hal/xt_wdt_hal.h create mode 100644 components/hal/xt_wdt_hal.c diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index b166fcdc7b..1d25417fec 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -646,6 +646,7 @@ menu "ESP32-specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XN pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32_RTC_CLK_SRC_INT_8MD256 bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)" endchoice diff --git a/components/esp32c3/Kconfig b/components/esp32c3/Kconfig index bb583c732e..dd6e5543bc 100644 --- a/components/esp32c3/Kconfig +++ b/components/esp32c3/Kconfig @@ -157,6 +157,7 @@ menu "ESP32C3-Specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32C3_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32C3_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp32h2/Kconfig b/components/esp32h2/Kconfig index 4413c4b0e5..987a78108d 100644 --- a/components/esp32h2/Kconfig +++ b/components/esp32h2/Kconfig @@ -150,6 +150,7 @@ menu "ESP32H2-Specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32H2_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32H2_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp32s2/Kconfig b/components/esp32s2/Kconfig index 9c8805dacf..997c553ddc 100644 --- a/components/esp32s2/Kconfig +++ b/components/esp32s2/Kconfig @@ -382,6 +382,7 @@ menu "ESP32S2-specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32S2_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XN pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32S2_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp32s3/Kconfig b/components/esp32s3/Kconfig index 2205b88470..9b7c047e69 100644 --- a/components/esp32s3/Kconfig +++ b/components/esp32s3/Kconfig @@ -430,6 +430,7 @@ menu "ESP32S3-Specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32S3_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32S3_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp_hw_support/port/esp32c3/rtc_time.c b/components/esp_hw_support/port/esp32c3/rtc_time.c index 3378a84bda..59f8a68d38 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_time.c +++ b/components/esp_hw_support/port/esp32c3/rtc_time.c @@ -43,7 +43,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { cal_clk = RTC_CAL_8MD256; } + } else if (cal_clk == RTC_CAL_INTERNAL_OSC) { + cal_clk = RTC_CAL_RTC_MUX; } + + /* Enable requested clock (150k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { diff --git a/components/esp_hw_support/port/esp32s2/rtc_time.c b/components/esp_hw_support/port/esp32s2/rtc_time.c index ee75ecd1a8..a18f36981b 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_time.c +++ b/components/esp_hw_support/port/esp32s2/rtc_time.c @@ -141,7 +141,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { cal_clk = RTC_CAL_8MD256; } + } else if (cal_clk == RTC_CAL_INTERNAL_OSC) { + cal_clk = RTC_CAL_RTC_MUX; } + /* Enable requested clock (90k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { diff --git a/components/esp_hw_support/port/esp32s3/rtc_time.c b/components/esp_hw_support/port/esp32s3/rtc_time.c index b54e4af3ca..3668a9eaa1 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_time.c +++ b/components/esp_hw_support/port/esp32s3/rtc_time.c @@ -42,7 +42,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { cal_clk = RTC_CAL_8MD256; } + } else if (cal_clk == RTC_CAL_INTERNAL_OSC) { + cal_clk = RTC_CAL_RTC_MUX; } + /* Enable requested clock (150k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index a8a9d9e5c5..0aa60f72a7 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -21,7 +21,8 @@ else() "system_time.c" "stack_check.c" "task_wdt.c" - "ubsan.c") + "ubsan.c" + "xt_wdt.c") if(NOT (${target} STREQUAL "esp32c3") AND NOT (${target} STREQUAL "esp32h2")) list(APPEND srcs "dbg_stubs.c") diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index bb3988c495..7a03588903 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -53,6 +53,12 @@ menu "ESP System Settings" bool default n + config ESP_SYSTEM_RTC_EXT_OSC + # This is a High Layer Kconfig option, invisible, can be selected by other Kconfig option + # e.g. It will be selected on when ESPX_RTC_CLK_SRC_EXT_OSC is on + bool + default n + config ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES int "Bootstrap cycles for external 32kHz crystal" depends on ESP_SYSTEM_RTC_EXT_XTAL @@ -389,6 +395,31 @@ menu "ESP System Settings" If this option is enabled, the Task Wtachdog Timer will wach the CPU1 Idle Task. + config ESP_XT_WDT + bool "Initialize XTAL32K watchdog timer on startup" + depends on !IDF_TARGET_ESP32 && (ESP_SYSTEM_RTC_EXT_OSC || ESP_SYSTEM_RTC_EXT_XTAL) + default n + help + This watchdog timer can detect oscillation failure of the XTAL32K_CLK. When such a failure + is detected the hardware can be set up to automatically switch to BACKUP32K_CLK and generate + an interrupt. + + config ESP_XT_WDT_TIMEOUT + int "XTAL32K watchdog timeout period" + depends on ESP_XT_WDT + range 1 255 + default 200 + help + Timeout period configuration for the XTAL32K watchdog timer based on RTC_CLK. + + config ESP_XT_WDT_BACKUP_CLK_ENABLE + bool "Automatically switch to BACKUP32K_CLK when timer expires" + depends on ESP_XT_WDT + default y + help + Enable this to automatically switch to BACKUP32K_CLK as the source of RTC_SLOW_CLK when + the watchdog timer expires. + config ESP_PANIC_HANDLER_IRAM bool "Place panic handler code in IRAM" default n diff --git a/components/esp_system/include/esp_xt_wdt.h b/components/esp_system/include/esp_xt_wdt.h new file mode 100644 index 0000000000..3b39d8056d --- /dev/null +++ b/components/esp_system/include/esp_xt_wdt.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "esp_err.h" +#include "esp_intr_alloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief esp_xt_wdt configuration struct + * + */ +typedef struct { + uint8_t timeout; /*!< Watchdog timeout */ + bool auto_backup_clk_enable; /*!< Enable automatic switch to backup clock at timeout */ +} esp_xt_wdt_config_t; + +/* Callback function for WDT interrupt*/ +typedef void (*esp_xt_callback_t)(void *arg); + +/** + * @brief Initializes the xtal32k watchdog timer + * + * @param cfg Pointer to configuration struct + * @return esp_err_t + * - ESP_OK: XTWDT was successfully enabled + * - ESP_ERR_NO_MEM: Failed to allocate ISR + */ +esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg); + +/** + * @brief Register a callback function that will be called when the watchdog + * times out. + * + * @note This function will be called from an interrupt context where the cache might be disabled. + * Thus the function should be placed in IRAM and must not perform any blocking operations. + * + * Only one callback function can be registered, any call to esp_xt_wdt_register_callback + * will override the previous callback function. + * + * @param func The callback function to register + * @param arg Pointer to argument that will be passed to the callback function + */ +void esp_xt_wdt_register_callback(esp_xt_callback_t func, void *arg); + +/** + * @brief Restores the xtal32k clock and re-enables the WDT + * + */ +void esp_xt_wdt_restore_clk(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 8afc43087f..ddf6c82b77 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -41,6 +41,7 @@ #include "esp_flash_encrypt.h" #include "esp_secure_boot.h" #include "esp_sleep.h" +#include "esp_xt_wdt.h" /***********************************************/ // Headers for other components init functions @@ -344,6 +345,15 @@ static void do_core_init(void) // Note: in some configs this may read flash, so placed after flash init esp_secure_boot_init_checks(); #endif + +#if CONFIG_ESP_XT_WDT + esp_xt_wdt_config_t cfg = { + .timeout = CONFIG_ESP_XT_WDT_TIMEOUT, + .auto_backup_clk_enable = CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE, + }; + err = esp_xt_wdt_init(&cfg); + assert(err == ESP_OK && "Failed to init xtwdt"); +#endif } static void do_secondary_init(void) diff --git a/components/esp_system/xt_wdt.c b/components/esp_system/xt_wdt.c new file mode 100644 index 0000000000..d3828df47c --- /dev/null +++ b/components/esp_system/xt_wdt.c @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_xt_wdt.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#include "esp_log.h" +#include "esp_check.h" +#include "esp_attr.h" +#include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#if SOC_XT_WDT_SUPPORTED + +#include "driver/rtc_cntl.h" +#include "hal/xt_wdt_hal.h" +#include "hal/xt_wdt_ll.h" +#include "soc/rtc.h" + +#define RTC_CLK_CAL_CYCLES 500 + +const static char *TAG = "esp_xt_wdt"; + +static xt_wdt_hal_context_t s_hal_ctx; + +static esp_xt_callback_t s_callback_func; +static void *s_callback_arg; + +portMUX_TYPE s_xt_wdt_lock = portMUX_INITIALIZER_UNLOCKED; + +static IRAM_ATTR void rtc_xt_wdt_default_isr_handler(void *arg) +{ + ESP_EARLY_LOGE(TAG, "XTAL32K watchdog timer got triggered"); + + portENTER_CRITICAL_ISR(&s_xt_wdt_lock); + if (s_callback_func) { + (*s_callback_func)(s_callback_arg); + } + portEXIT_CRITICAL_ISR(&s_xt_wdt_lock); +} + +esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg) +{ + esp_err_t ret = ESP_OK; + + xt_wdt_hal_config_t hal_config = { + .timeout = cfg->timeout, + }; + + xt_wdt_hal_init(&s_hal_ctx, &hal_config); + + if (cfg->auto_backup_clk_enable) { + /* Estimate frequency of internal RTC oscillator */ + uint32_t rtc_clk_frequency_khz = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_INTERNAL_OSC, RTC_CLK_CAL_CYCLES)) / 1000; + ESP_LOGD(TAG, "Calibrating backup clock from rtc clock with frequency %d", rtc_clk_frequency_khz); + + xt_wdt_hal_enable_backup_clk(&s_hal_ctx, rtc_clk_frequency_khz); + } + + ESP_GOTO_ON_ERROR(rtc_isr_register(rtc_xt_wdt_default_isr_handler, NULL, XT_WDT_LL_XTAL32_DEAD_INTR_MASK), err, TAG, "Failed to register isr"); + + xt_wdt_hal_enable(&s_hal_ctx, 1); + + return ESP_OK; +err: + return ret; +} + +void esp_xt_wdt_restore_clk(void) +{ + xt_wdt_hal_enable(&s_hal_ctx, false); + + REG_CLR_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + REG_SET_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + + /* Needs some time after switching to 32khz XTAL before turning on WDT again */ + esp_rom_delay_us(300); + + xt_wdt_hal_enable(&s_hal_ctx, true); +} + +void esp_xt_wdt_register_callback(esp_xt_callback_t func, void *arg) +{ + portENTER_CRITICAL(&s_xt_wdt_lock); + s_callback_func = func; + s_callback_arg = arg; + portEXIT_CRITICAL(&s_xt_wdt_lock); +} + +#endif //SOC_XT_WDT_SUPPORTED diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index ba6e51db8b..b5d8de8a9b 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -61,6 +61,7 @@ if(NOT BOOTLOADER_BUILD) "systimer_hal.c" "touch_sensor_hal.c" "usb_hal.c" + "xt_wdt_hal.c" "esp32s2/adc_hal.c" "esp32s2/brownout_hal.c" "esp32s2/cp_dma_hal.c" @@ -81,6 +82,7 @@ if(NOT BOOTLOADER_BUILD) "systimer_hal.c" "touch_sensor_hal.c" "usb_hal.c" + "xt_wdt_hal.c" "esp32s3/brownout_hal.c" "esp32s3/hmac_hal.c" "esp32s3/interrupt_descriptor_table.c" @@ -95,6 +97,7 @@ if(NOT BOOTLOADER_BUILD) "spi_flash_hal_gpspi.c" "spi_slave_hd_hal.c" "systimer_hal.c" + "xt_wdt_hal.c" "esp32c3/adc_hal.c" "esp32c3/brownout_hal.c" "esp32c3/hmac_hal.c" diff --git a/components/hal/component.mk b/components/hal/component.mk index 66d5054f62..d979fa78b8 100644 --- a/components/hal/component.mk +++ b/components/hal/component.mk @@ -2,7 +2,7 @@ COMPONENT_SRCDIRS := . esp32 COMPONENT_ADD_INCLUDEDIRS := esp32/include include platform_port/include COMPONENT_ADD_LDFRAGMENTS += linker.lf -COMPONENT_OBJEXCLUDE += ./spi_slave_hd_hal.o ./spi_flash_hal_gpspi.o ./spi_slave_hd_hal.o ./ds_hal.o ./gdma_hal.o ./lcd_hal.o ./systimer_hal.o ./usb_hal.o ./usbh_hal.o +COMPONENT_OBJEXCLUDE += ./spi_slave_hd_hal.o ./spi_flash_hal_gpspi.o ./spi_slave_hd_hal.o ./ds_hal.o ./gdma_hal.o ./lcd_hal.o ./systimer_hal.o ./usb_hal.o ./usbh_hal.o ./xt_wdt_hal.o ifndef CONFIG_ETH_USE_ESP32_EMAC COMPONENT_OBJEXCLUDE += ./emac_hal.o diff --git a/components/hal/esp32c3/include/hal/xt_wdt_ll.h b/components/hal/esp32c3/include/hal/xt_wdt_ll.h new file mode 100644 index 0000000000..65b36253e5 --- /dev/null +++ b/components/hal/esp32c3/include/hal/xt_wdt_ll.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for xtal32k WDT register operations. +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "soc/rtc_cntl_periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M + +/** + * @brief Enable the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_wdt_en = enable; +} + +/** + * @brief Check if the XT_WDT is enabled + * + * @param hw Start address of the peripheral registers. + * @return True if XT WDT is enabled + */ +inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw) +{ + return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false; +} + +/** + * @brief Set the watchdog timeout value + * + * @param hw Start address of the peripheral registers. + * @param timeout timeout value in RTC_CLK cycles + */ +inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout) +{ + hw->xtal32k_conf.xtal32k_wdt_timeout = timeout; +} + + +/** + * @brief Reset the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw) +{ + hw->ext_xtl_conf.xtal32k_wdt_reset = 1; + hw->ext_xtl_conf.xtal32k_wdt_reset = 0; +} + + +/** + * @brief Set the backup clock value + * + * @param hw Start address of the peripheral registers. + * @param backup_clk_val Backup clock value, see TRM for definition + */ +inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val) +{ + hw->xtal32k_clk_factor = backup_clk_val; +} + +/** + * @brief Enable the auto-backup clock feature + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_auto_backup = enable; +} + +/** + * @brief Enable the timeout interrupt + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->int_ena.rtc_xtal32k_dead = enable; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/xt_wdt_ll.h b/components/hal/esp32s2/include/hal/xt_wdt_ll.h new file mode 100644 index 0000000000..65b36253e5 --- /dev/null +++ b/components/hal/esp32s2/include/hal/xt_wdt_ll.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for xtal32k WDT register operations. +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "soc/rtc_cntl_periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M + +/** + * @brief Enable the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_wdt_en = enable; +} + +/** + * @brief Check if the XT_WDT is enabled + * + * @param hw Start address of the peripheral registers. + * @return True if XT WDT is enabled + */ +inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw) +{ + return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false; +} + +/** + * @brief Set the watchdog timeout value + * + * @param hw Start address of the peripheral registers. + * @param timeout timeout value in RTC_CLK cycles + */ +inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout) +{ + hw->xtal32k_conf.xtal32k_wdt_timeout = timeout; +} + + +/** + * @brief Reset the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw) +{ + hw->ext_xtl_conf.xtal32k_wdt_reset = 1; + hw->ext_xtl_conf.xtal32k_wdt_reset = 0; +} + + +/** + * @brief Set the backup clock value + * + * @param hw Start address of the peripheral registers. + * @param backup_clk_val Backup clock value, see TRM for definition + */ +inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val) +{ + hw->xtal32k_clk_factor = backup_clk_val; +} + +/** + * @brief Enable the auto-backup clock feature + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_auto_backup = enable; +} + +/** + * @brief Enable the timeout interrupt + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->int_ena.rtc_xtal32k_dead = enable; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/xt_wdt_ll.h b/components/hal/esp32s3/include/hal/xt_wdt_ll.h new file mode 100644 index 0000000000..65b36253e5 --- /dev/null +++ b/components/hal/esp32s3/include/hal/xt_wdt_ll.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for xtal32k WDT register operations. +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "soc/rtc_cntl_periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M + +/** + * @brief Enable the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_wdt_en = enable; +} + +/** + * @brief Check if the XT_WDT is enabled + * + * @param hw Start address of the peripheral registers. + * @return True if XT WDT is enabled + */ +inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw) +{ + return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false; +} + +/** + * @brief Set the watchdog timeout value + * + * @param hw Start address of the peripheral registers. + * @param timeout timeout value in RTC_CLK cycles + */ +inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout) +{ + hw->xtal32k_conf.xtal32k_wdt_timeout = timeout; +} + + +/** + * @brief Reset the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw) +{ + hw->ext_xtl_conf.xtal32k_wdt_reset = 1; + hw->ext_xtl_conf.xtal32k_wdt_reset = 0; +} + + +/** + * @brief Set the backup clock value + * + * @param hw Start address of the peripheral registers. + * @param backup_clk_val Backup clock value, see TRM for definition + */ +inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val) +{ + hw->xtal32k_clk_factor = backup_clk_val; +} + +/** + * @brief Enable the auto-backup clock feature + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_auto_backup = enable; +} + +/** + * @brief Enable the timeout interrupt + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->int_ena.rtc_xtal32k_dead = enable; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/xt_wdt_hal.h b/components/hal/include/hal/xt_wdt_hal.h new file mode 100644 index 0000000000..bd08f2a989 --- /dev/null +++ b/components/hal/include/hal/xt_wdt_hal.h @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "hal/xt_wdt_ll.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + rtc_cntl_dev_t *dev; /* Pointer to the RTC register struct */ +} xt_wdt_hal_context_t; /* HAL context struct */ + +typedef struct { + uint32_t timeout; /* Watchdog timer timeout in RTC_CLK cycles*/ +} xt_wdt_hal_config_t; /* HAL config parameter struct */ + +/* ---------------------------- Init and Config ----------------------------- */ + +/** + * @brief Initialize the WDTs associated HAL context + * + * Prepares the register for enabling the WDT and sets the timeout value + * + * @param hal Pointer to the HAL layer context + * @param config Pointer to config struct + */ +void xt_wdt_hal_init(xt_wdt_hal_context_t *hal, const xt_wdt_hal_config_t *config); + + +/** + * @brief Enable or disable the WDT + * + * @param hal Pointer to the HAL layer context + * @param enable true for enable WDT, false for disable + */ +void xt_wdt_hal_enable(xt_wdt_hal_context_t *hal, bool enable); + +/** + * @brief Enable the automatic RTC backup clock with the given frequency + * + * Calculates and sets the necessary hardware parameters to meet the desired + * backup clock frequency + * + * @param hal Pointer to the HAL layer context + * @param rtc_clk_frequency_khz desired frequency for the backup clock + * @return uint32_t the calculated clock factor value + */ +uint32_t xt_wdt_hal_enable_backup_clk(xt_wdt_hal_context_t *hal, uint32_t rtc_clk_frequency_khz); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/xt_wdt_hal.c b/components/hal/xt_wdt_hal.c new file mode 100644 index 0000000000..29ebb710a3 --- /dev/null +++ b/components/hal/xt_wdt_hal.c @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "soc/soc_caps.h" + +#include "hal/xt_wdt_hal.h" +#include "hal/xt_wdt_ll.h" +#include "hal/assert.h" + +#define DIV_COMP_N_MAX 8 + +static uint32_t xt_wdt_hal_calculate(uint32_t rtc_clk_frequency_khz) +{ + uint32_t xtal32k_clk_factor = 0; + uint8_t divisor_comps[DIV_COMP_N_MAX]; + + /* From the TRM: + + Define the frequency of RTC_CLK as f_rtc_clk (unit: kHz), and the eight divisor components as + x0, x1, x2, x3, x4, x5, x6, and x7, respectively. S = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7. + The following conditions should be fulfilled: + S = f_rtc_clk * (4/32) + M + 1 >= xn >= M(0 <= n <= 7) + M = f_rtc_clk/32/2 + xn should be an integer. M and S are rounded up or down. Each divisor component (x0 ~x7) is 4-bit long, and + corresponds to the value of RTC_CNTL_XTAL32K_CLK_FACTOR (32-bit) in order. + */ + + uint8_t M = ((rtc_clk_frequency_khz / 32) / 2); + uint32_t S = ((4 * rtc_clk_frequency_khz) / 32); + + memset(divisor_comps, M, DIV_COMP_N_MAX); + + /* Calculate how far we are away from satisfying S = SUM(x_n) */ + uint8_t off = S - DIV_COMP_N_MAX * M; + + /* Offset should never be this big */ + HAL_ASSERT(off <= DIV_COMP_N_MAX); + + for (int i = 0; i < DIV_COMP_N_MAX; i++) { + if (off) { + divisor_comps[i]++; + off--; + } + /* Sum up all divisors */ + xtal32k_clk_factor |= (divisor_comps[i] << 4 * i); + } + + return xtal32k_clk_factor; +} + +void xt_wdt_hal_init(xt_wdt_hal_context_t *hal, const xt_wdt_hal_config_t *config) +{ + hal->dev = &RTCCNTL; + + xt_wdt_ll_enable(hal->dev, false); + xt_wdt_ll_set_timeout(hal->dev, config->timeout); +} + +uint32_t xt_wdt_hal_enable_backup_clk(xt_wdt_hal_context_t *hal, uint32_t rtc_clk_frequency_khz) +{ + uint32_t xtal32k_clk_factor = xt_wdt_hal_calculate(rtc_clk_frequency_khz); + + xt_wdt_ll_set_backup_clk_factor(hal->dev, xtal32k_clk_factor); + xt_wdt_ll_auto_backup_enable(hal->dev, true); + + return xtal32k_clk_factor; +} + +void xt_wdt_hal_enable(xt_wdt_hal_context_t *hal, bool enable) +{ + xt_wdt_ll_enable(hal->dev, enable); + xt_wdt_ll_intr_enable(hal->dev, enable); +} diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 3fda6cb8a7..40e6ec81d1 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -206,7 +206,8 @@ typedef enum { typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 - RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL + RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL + RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator } rtc_cal_sel_t; /** diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index b30d095498..5ad734e6d0 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -14,7 +14,9 @@ #define SOC_ASYNC_MEMCPY_SUPPORTED 1 #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 #define SOC_TEMP_SENSOR_SUPPORTED 1 -#define SOC_FLASH_ENCRYPTION_XTS_AES 1 +#define SOC_FLASH_ENCRYPTION_XTS_AES 1 +#define SOC_XT_WDT_SUPPORTED 1 + /*-------------------------- COMMON CAPS ---------------------------------------*/ #define SOC_SUPPORTS_SECURE_DL_MODE 1 diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 52322db983..1877bb1cfe 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -215,7 +215,8 @@ typedef enum { typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 - RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL + RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL + RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator } rtc_cal_sel_t; /** diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 29cefdee80..aa5705d86e 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -59,6 +59,7 @@ #define SOC_FLASH_ENCRYPTION_XTS_AES 1 #define SOC_FLASH_ENCRYPTION_XTS_AES_256 1 #define SOC_PSRAM_DMA_CAPABLE 1 +#define SOC_XT_WDT_SUPPORTED 1 /*-------------------------- ADC CAPS ----------------------------------------*/ #define SOC_ADC_PERIPH_NUM (2) diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index ac186e5e93..3c81e0f304 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -202,7 +202,8 @@ typedef enum { typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 - RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL + RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL + RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator } rtc_cal_sel_t; /** diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 59ee736f69..0ad56c7791 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -28,6 +28,8 @@ #define SOC_FLASH_ENCRYPTION_XTS_AES 1 #define SOC_FLASH_ENCRYPTION_XTS_AES_256 1 #define SOC_PSRAM_DMA_CAPABLE 1 +#define SOC_XT_WDT_SUPPORTED 1 + /*-------------------------- SOC CAPS ----------------------------------------*/ #define SOC_APPCPU_HAS_CLOCK_GATING_BUG (1) diff --git a/docs/en/api-reference/system/wdts.rst b/docs/en/api-reference/system/wdts.rst index 894c70d740..372a6bde4c 100644 --- a/docs/en/api-reference/system/wdts.rst +++ b/docs/en/api-reference/system/wdts.rst @@ -4,7 +4,7 @@ Watchdogs Overview -------- -The ESP-IDF has support for two types of watchdogs: The Interrupt Watchdog Timer +The ESP-IDF has support for multiple types of watchdogs, with the two main ones being: The Interrupt Watchdog Timer and the Task Watchdog Timer (TWDT). The Interrupt Watchdog Timer and the TWDT can both be enabled using :ref:`project-configuration-menu`, however the TWDT can also be enabled during runtime. The Interrupt Watchdog is responsible for detecting @@ -101,13 +101,13 @@ timeout at runtime by calling :cpp:func:`esp_task_wdt_init`. The following config options control TWDT configuration at startup. They are all enabled by default: -{IDF_TARGET_IDLE_TASK:default="Idle task", esp32="CPU0 Idle task"} +{IDF_TARGET_IDLE_TASK:default="Idle task", esp32="CPU0 Idle task", esp32s3="CPU0 Idle task"} .. list:: - :ref:`CONFIG_ESP_TASK_WDT` - the TWDT is initialized automatically during startup. If this option is disabled, it is still possible to initialize the Task WDT at runtime by calling :cpp:func:`esp_task_wdt_init`. - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0` - {IDF_TARGET_IDLE_TASK} is subscribed to the TWDT during startup. If this option is disabled, it is still possible to subscribe the idle task by calling :cpp:func:`esp_task_wdt_add` at any time. - :esp32: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 Idle task is subscribed to the TWDT during startup. + :not CONFIG_FREERTOS_UNICORE: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 Idle task is subscribed to the TWDT during startup. JTAG and watchdogs @@ -124,6 +124,26 @@ panics from either watchdogs will be generated when the {IDF_TARGET_NAME} is con OpenOCD via JTAG. +.. only:: SOC_XT_WDT_SUPPORTED + + XTAL32K Watchdog Timer (XTWDT) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + The XTAL32K watchdog makes sure the (optional) external 32 KHz crystal or oscillator is functioning correctly. + + When `XTAL32K_CLK` works as the clock source of `RTC_SLOW_CLK` and stops oscillating, the XTAL32K watchdog timer will detect this and generate an interrupt. + It also provides functionality for automatically switching over to the internal, but less accurate oscillator as the `RTC_SLOW_CLK` source. + + Since the switch to the backup clock is done in hardware it can also happen during deep sleep. This means that even if `XTAL32K_CLK` stops functioning while the chip in deep sleep, waiting for a timer to expire, it will still be able to wake-up as planned. + + If the `XTAL32K_CLK` starts functioning normally again, you can call `esp_xt_wdt_restore_clk` to switch back to this clock source and re-enable the watchdog timer. + + Configuration + @@@@@@@@@@@@@ + + When the external 32KHz crystal or oscillator is selected (:ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_RTC_CLK_SRC`) the XTAL32K watchdog can be enabled via the :ref:`CONFIG_ESP_XT_WDT` configuration + flag. The timeout is configured by setting :ref:`CONFIG_ESP_XT_WDT_TIMEOUT`. The automatic backup clock functionality is enabled via the ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` configuration. + Interrupt Watchdog API Reference -------------------------------- From 701c4fb2e3bde9ce65d9b018f10c4f726b7978ff Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Tue, 24 Aug 2021 12:06:21 +0800 Subject: [PATCH 107/310] upgrade freertos version and history --- components/freertos/History.txt | 188 +++++++++++++++--- components/freertos/croutine.c | 2 +- components/freertos/event_groups.c | 2 +- .../freertos/include/freertos/FreeRTOS.h | 2 +- components/freertos/include/freertos/atomic.h | 2 +- .../freertos/include/freertos/croutine.h | 2 +- .../include/freertos/deprecated_definitions.h | 2 +- .../freertos/include/freertos/event_groups.h | 2 +- components/freertos/include/freertos/list.h | 2 +- .../include/freertos/message_buffer.h | 2 +- .../freertos/include/freertos/mpu_wrappers.h | 2 +- .../freertos/include/freertos/portable.h | 2 +- .../freertos/include/freertos/projdefs.h | 2 +- components/freertos/include/freertos/queue.h | 2 +- components/freertos/include/freertos/semphr.h | 2 +- .../freertos/include/freertos/stack_macros.h | 2 +- .../freertos/include/freertos/stream_buffer.h | 2 +- components/freertos/include/freertos/task.h | 8 +- components/freertos/include/freertos/timers.h | 2 +- .../port/riscv/include/freertos/portmacro.h | 2 +- .../port/xtensa/include/freertos/portmacro.h | 2 +- components/freertos/queue.c | 2 +- components/freertos/tasks.c | 2 +- components/freertos/timers.c | 2 +- .../mocks/include/freertos/portmacro.h | 2 +- 25 files changed, 191 insertions(+), 51 deletions(-) diff --git a/components/freertos/History.txt b/components/freertos/History.txt index 8caaf23ffe..32d391cea9 100644 --- a/components/freertos/History.txt +++ b/components/freertos/History.txt @@ -1,4 +1,4 @@ -Documentation and download available at http://www.FreeRTOS.org/ +Documentation and download available at https://www.FreeRTOS.org/ Changes since the last release: + Added xTaskCatchUpTicks() which corrects the tick count value after the @@ -19,6 +19,147 @@ Changes since the last release: configISR_STACK_SIZE_WORDS is defined to a non zero value. +Changes between FreeRTOS V10.4.2 and FreeRTOS V10.4.3 released December 14 2020 + + V10.4.3 is included in the 202012.00 LTS release. Learn more at https:/freertos.org/lts-libraries.html + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + + Changes to improve robustness and consistency for buffer allocation in + the heap, queue and stream buffer. + + The following functions can no longer be called from unprivileged code. + - xTaskCreateRestricted + - xTaskCreateRestrictedStatic + - vTaskAllocateMPURegions + + +Changes between FreeRTOS V10.4.1 and FreeRTOS V10.4.2 released November 10 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + + Fix an issue in the ARMv8-M ports that caused BASEPRI to be masked + between the first task starting to execute and that task making + a FreeRTOS API call. + + Introduced xTaskDelayUntil(), which is functionally equivalent to + vTaskDelayUntil(), with the addition of returning a value to + indicating whether or not the function placed the calling task into + the Blocked state or not. + + Update WolfSSL to 4.5.0 and add the FIPS ready demo. + + Add support for ESP IDF 4.2 to ThirdParty Xtensa port. + + Re-introduce uxTopUsedPriority to support OpenOCD debugging. + + Convert most dependent libraries in FreeRTOS/FreeRTOS to submodules. + + Various general maintenance and improvements to MISRA compliance. + + +Changes between FreeRTOS V10.4.0 and FreeRTOS V10.4.1 released September 17 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + + Fixed an incorrectly named parameter that prevented the + ulTaskNotifyTakeIndexed macro compiling, and the name space clash in the + test code that prevented this error causing test failures. + + +Changes between FreeRTOS V10.3.1 and FreeRTOS V10.4.0 released September 10 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + Major enhancements: + + + Task notifications: Prior to FreeRTOS V10.4.0 each created task had a + single direct to task notification. From FreeRTOS V10.4.0 each task has + an array of notifications. The direct to task notification API has been + extended with API functions postfixed with "Indexed" to enable the API to + operate on a task notification at any array index. See + https://www.freertos.org/RTOS-task-notifications.html for more information. + + Kernel ports that support memory protection units (MPUs): The ARMv7-M and + ARMv8-M MPU ports now support a privilege access only heap. The ARMv7-M + MPU ports now support devices that have 16 MPU regions, have the ability + to override default memory attributes for privileged code and data + regions, and have the ability to place the FreeRTOS kernel code outside of + the Flash memory. The ARMv8-M MPU ports now support tickless idle mode. + See https://www.freertos.org/FreeRTOS-MPU-memory-protection-unit.html + for more information. + + Additional noteworthy updates: + + + Code formatting is now automated to facilitate the increase in + collaborative development in Git. The auto-formated code is not identical + to the original formatting conventions. Most notably spaces are now used + in place of tabs. + + The prototypes for callback functions (those that start with "Application", + such as vApplicationStackOverflowHook()) are now in the FreeRTOS header + files, removing the need for application writers to add prototypes into + the C files in which they define the functions. + + New Renesas RXv3 port layer. + + Updates to the Synopsys ARC code, including support for EM and HS cores, + and updated BSP. + + Added new POSIX port layer that allows FreeRTOS to run on Linux hosts in + the same way the Windows port layer enables FreeRTOS to run on Windows + hosts. + + Many other minor optimisations and enhancements. For full details + see https://github.com/FreeRTOS/FreeRTOS-Kernel/commits/master + + +Changes between FreeRTOS V10.3.0 and FreeRTOS V10.3.1 released February 18 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.3.x.html + + + ./FreeRTOS-Labs directory was removed from this file. The libraries it + contained are now available as a separate download. + +Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released February 7 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.3.x.html + + New and updated kernel ports: + + + Added RISC-V port for the IAR compiler. + + Update the Windows simulator port to use a synchronous object to prevent + a user reported error whereby a task continues to run for a short time + after being moved to the Blocked state. Note we were not able to + replicate the reported issue and it likely depends on your CPU model. + + Correct alignment of stack top in RISC-V port when + configISR_STACK_SIZE_WORDS is defined to a non zero value, which causes + the interrupt stack to be statically allocated. + + The RISC-V machine timer compare register can now be for any HART, whereas + previously it was always assumed FreeRTOS was running on HART 0. + + Update the sequence used to update the 64-bit machine timer + compare register on 32-bit cores to match that suggested in RISC-V + documentation. + + Added tickless low power modes into the ARM, IAR and GCC Cortex-M0 compiler + ports. + + Updated the behaviour of the ARMv7-M MPU (Memory Protection Unit) ports to + match that of the ARMv8-M ports whereby privilege escalations can only + originate from within the kernel's own memory segment. Added + configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY configuration constant. + + Update existing MPU ports to correctly disable the MPU before it is + updated. + + Added contributed port and demo application for a T-Head (formally C-SKY) + microcontroller. + + New API functions: + + + Added the vPortGetHeapStats() API function which returns information on + the heap_4 and heap_5 state. + + Added xTaskCatchUpTicks(), which corrects the tick count value after the + application code has held interrupts disabled for an extended period. + + Added xTaskNotifyValueClear() API function. + + Added uxTimerGetReloadMode() API function. + + Other miscellaneous changes: + + Change type of uxPendedTicks from UBaseType_t to TickType_t to ensure it + has the same type as variables with which it is compared to, and therefore + also renamed the variable xPendingTicks. + + Update Keil projects that use the MPU so memory regions come from linker + script (scatter file) variables instead of being hard coded. + + Added LPC51U68 Cortex-M0+ demos for GCC (MCUXpresso), Keil and IAR + compilers. + + Added CORTEX_MPU_STM32L4_Discovery_Keil_STM32Cube demo. + + Added LPC54018 MPU demo. + + Rename xTaskGetIdleRunTimeCounter() to ulTaskGetIdleRunTimeCounter(). + + Changes between FreeRTOS V10.2.1 and FreeRTOS V10.2.0 released May 13 2019: + Added ARM Cortex-M23 port layer to complement the pre-existing ARM @@ -163,8 +304,8 @@ Changes between FreeRTOS V9.0.1 and FreeRTOS V10.0.0: New Features and components: - + Stream Buffers - see http://www.FreeRTOS.org/RTOS-stream-buffer-example.html - + Message Buffers - see http://www.FreeRTOS.org//RTOS-message-buffer-example.html + + Stream Buffers - see https://www.FreeRTOS.org/RTOS-stream-buffer-example.html + + Message Buffers - see https://www.FreeRTOS.org//RTOS-message-buffer-example.html + Move FreeRTOS+TCP into the main repository, along with the basic Win32 TCP demo FreeRTOS_Plus_TCP_Minimal_Windows_Simulator. @@ -266,7 +407,7 @@ Changes since FreeRTOS V9.0.0: Changes between FreeRTOS V9.0.0 and FreeRTOS V9.0.0rc2 released May 25 2016: - See http://www.FreeRTOS.org/FreeRTOS-V9.html + See https://www.FreeRTOS.org/FreeRTOS-V9.html RTOS kernel updates: @@ -275,7 +416,7 @@ Changes between FreeRTOS V9.0.0 and FreeRTOS V9.0.0rc2 released May 25 2016: "CreateStatic()" API functions. The stack size parameter in xTaskCreateStatic() is now uint32_t, which changes the prototype of the callback functions. See the following URL: - http://www.freertos.org/xTaskCreateStatic.html + https://www.FreeRTOS.org/xTaskCreateStatic.html + GCC ARM Cortex-A port: Introduced the configUSE_TASK_FPU_SUPPORT constant. When configUSE_TASK_FPU_SUPPORT is set to 2 every task is automatically given a floating point (FPU) context. @@ -324,7 +465,7 @@ Changes between FreeRTOS V9.0.0 and FreeRTOS V9.0.0rc2 released May 25 2016: Changes between FreeRTOS V9.0.0rc1 and FreeRTOS V9.0.0rc2 (release candidate 2) released March 30 2016: - NOTE - See http://www.FreeRTOS.org/FreeRTOS-V9.html for details + NOTE - See https://www.FreeRTOS.org/FreeRTOS-V9.html for details + The functions that create RTOS objects using static memory allocation have been simplified and will not revert to using dynamic allocation if a @@ -515,6 +656,8 @@ Changes between V8.2.0 and V8.2.1 released 24th March 2015. Windows port. + Update the PIC32 port to remove deprecation warnings output by the latest XC32 compilers. + + Fix bug when xQueueOverwrite() and xQueueOverwrite() from ISR are used to + overwrite items in two queues that are part of the same set. Demo application updates: @@ -535,7 +678,7 @@ Changes between V8.1.2 and V8.2.0 released 16th January 2015 Significant RTOS kernel updates: + MAJOR NEW FEATURE! Task notifications. Please see the following URL for - details: http://www.FreeRTOS.org/RTOS-task-notifications.html + details: https://www.FreeRTOS.org/RTOS-task-notifications.html + NEW HEADER FILE REQUIRED! Obsolete definitions have been separated into a new header file called FreeRTOS/Source/include/deprecated_definitions.h. This header file must be present to build. Note some of the obsolete @@ -699,21 +842,21 @@ Changes between V8.0.0 and V8.0.1 released 2nd May 2014 Changes between V7.6.0 and V8.0.0 released 19th Feb 2014 - http://www.freertos.org/upgrading-to-FreeRTOS-V8.html + https://www.FreeRTOS.org/upgrading-to-FreeRTOS-V8.html FreeRTOS V8.x.x is a drop-in compatible replacement for FreeRTOS V7.x.x, although a change to the type used to reference character strings may result in application code generating a few (easily clearable) compiler warnings after the upgrade, and an updated typedef naming convention means use of the old typedef names is now discouraged. - See http://www.freertos.org/upgrading-to-FreeRTOS-V8.html for full + See https://www.FreeRTOS.org/upgrading-to-FreeRTOS-V8.html for full information. New features and functionality: - + Event groups - see http://www.freertos.org/FreeRTOS-Event-Groups.html + + Event groups - see https://www.FreeRTOS.org/FreeRTOS-Event-Groups.html + Centralised deferred interrupt processing - see - http://www.freertos.org/xTimerPendFunctionCallFromISR.html + https://www.FreeRTOS.org/xTimerPendFunctionCallFromISR.html Other updates: @@ -724,7 +867,7 @@ Changes between V7.6.0 and V8.0.0 released 19th Feb 2014 priority of the Running task. + New low power tickless demonstration project that targets the ST STM32L microcontroller - see - http://www.freertos.org/STM32L-discovery-low-power-tickless-RTOS-demo.html + https://www.FreeRTOS.org/STM32L-discovery-low-power-tickless-RTOS-demo.html + Add xPortGetMinimumEverFreeHeapSize() to heap_4.c. + Small change to the tickless low power implementation on the SAM4L to ensure the alarm value (compare match value) cannot be set to zero when a @@ -874,8 +1017,8 @@ Changes between V7.4.2 and V7.5.0 released July 19 2013 New API functions: - + uxTaskGetSystemState() http://www.freertos.org/uxTaskGetSystemState.html - + xQueueOverwrite() http://www.freertos.org/xQueueOverwrite.html + + uxTaskGetSystemState() https://www.FreeRTOS.org/uxTaskGetSystemState.html + + xQueueOverwrite() https://www.FreeRTOS.org/xQueueOverwrite.html + xQueueOverwriteFromISR() + xQueuePeekFromISR() @@ -888,7 +1031,7 @@ Changes between V7.4.2 and V7.5.0 released July 19 2013 + Microsemi SmartFusion2 New FreeRTOSConfig.h settings - http://shop.freertos.org/FreeRTOS_API_and_Configuration_Reference_s/1822.htm + https://freertos.org/a00110.html + configUSE_TIME_SLICING + configUSE_NEWLIB_REENTRANT @@ -925,7 +1068,7 @@ Changes between V7.4.1 and V7.4.2 released May 1 2013 + Added FreeRTOS+FAT SL source code and demo project. The demo project runs in the FreeRTOS Windows simulator for easy and hardware independent - experimentation and evaluation. See http://www.FreeRTOS.org/fat_sl + experimentation and evaluation. See https://www.FreeRTOS.org/fat_sl Changes between V7.4.0 and V7.4.1 released April 18 2013 @@ -954,7 +1097,7 @@ Changes between V7.4.0 and V7.4.1 released April 18 2013 Changes between V7.3.0 and V7.4.0 released February 20 2013 + New feature: Queue sets. See: - http://www.FreeRTOS.org/Pend-on-multiple-rtos-objects.html + https://www.FreeRTOS.org/Pend-on-multiple-rtos-objects.html + Overhauled the default tickless idle mode implementation provided with the ARM Cortex-M3 port layers. + Enhanced tickless support in the core kernel code with the introduction of @@ -1101,7 +1244,7 @@ Changes between V7.1.0 and V7.1.1 released May 1 2012 + Introduced the portSETUP_TCB() macro to remove the requirement for the Windows simulator to use the traceTASK_CREATE() macro, leaving the trace - macro available for use by FreeRTOS+Trace (http://www.FreeRTOS.org/trace). + macro available for use by FreeRTOS+Trace (https://www.FreeRTOS.org/trace). + Added a new trace macro, traceMOVE_TASK_TO_READY_STATE(), to allow future FreeRTOS+Trace versions to provide even more information to users. + Updated the FreeRTOS MPU port to be correct for changes that were @@ -1129,7 +1272,7 @@ Changes between V7.1.0 and V7.1.1 released May 1 2012 + The command interpreter has now been formally released as FreeRTOS+CLI, and been moved out of the main FreeRTOS download, to instead be available - from the FreeRTOS+ Ecosystem site http://www.FreeRTOS.org/plus. + from the FreeRTOS+ Ecosystem site https://www.FreeRTOS.org/plus. + flash_timer.c/h has been added to the list of standard demo tasks. This performs the same functionality as the flash.c tasks, but using software timers in place of tasks. @@ -1411,7 +1554,7 @@ Changes between V6.0.3 and V6.0.4 released March 14 2010 + All the contributed files that were located in the Demo/Unsupported_Demos directory have been removed. These files are instead now available in the new Community Contributions section of the FreeRTOS website. See - http://www.freertos.org/RTOS-contributed-ports.html + https://www.FreeRTOS.org/RTOS-contributed-ports.html + The project file located in the Demo/CORTEX_STM32F107_GCC_Rowley directory has been upgraded to use V2.x of the Rowley Crossworks STM32 support package. @@ -1704,9 +1847,6 @@ Changes between V4.8.0 and V5.0.0 released April 15, 2008 compiler might not issue any type mismatch warnings! - See http://www.FreeRTOS.org/upgrading.html for full information. - - Other changes: + Support added for the new Luminary Micro LM3S3768 and LM3S3748 Cortex-M3 @@ -1960,7 +2100,7 @@ Changes between V4.0.1 and V4.0.2 released May 28, 2006 it was also called when the tick function was called during the scheduler unlocking process. + The EMAC driver in the SAM7X lwIP demo has been made more robust as per - the thread: http://sourceforge.net/forum/message.php?msg_id=3714405 + the thread: https://sourceforge.net/forum/message.php?msg_id=3714405 + In the PC ports: Add function prvSetTickFrequencyDefault() to set the DOS tick back to its proper value when the scheduler exits. Thanks Raynald! diff --git a/components/freertos/croutine.c b/components/freertos/croutine.c index 8be115f78c..c4c0fab422 100644 --- a/components/freertos/croutine.c +++ b/components/freertos/croutine.c @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/event_groups.c b/components/freertos/event_groups.c index f4be8973ae..2a63b0fa4f 100644 --- a/components/freertos/event_groups.c +++ b/components/freertos/event_groups.c @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h index 0b0fce99dc..afd00fad3e 100644 --- a/components/freertos/include/freertos/FreeRTOS.h +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/atomic.h b/components/freertos/include/freertos/atomic.h index d392e4193c..a47b96723c 100644 --- a/components/freertos/include/freertos/atomic.h +++ b/components/freertos/include/freertos/atomic.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/croutine.h b/components/freertos/include/freertos/croutine.h index 9b0a47de87..99322d219f 100644 --- a/components/freertos/include/freertos/croutine.h +++ b/components/freertos/include/freertos/croutine.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/deprecated_definitions.h b/components/freertos/include/freertos/deprecated_definitions.h index 40c4b4ee17..d3b942666d 100644 --- a/components/freertos/include/freertos/deprecated_definitions.h +++ b/components/freertos/include/freertos/deprecated_definitions.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/event_groups.h b/components/freertos/include/freertos/event_groups.h index 9b7d2fd923..84505ddaaa 100644 --- a/components/freertos/include/freertos/event_groups.h +++ b/components/freertos/include/freertos/event_groups.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/list.h b/components/freertos/include/freertos/list.h index c91ecb9b06..f76328f8e0 100644 --- a/components/freertos/include/freertos/list.h +++ b/components/freertos/include/freertos/list.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/message_buffer.h b/components/freertos/include/freertos/message_buffer.h index a2f56fe868..913c311df6 100644 --- a/components/freertos/include/freertos/message_buffer.h +++ b/components/freertos/include/freertos/message_buffer.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/mpu_wrappers.h b/components/freertos/include/freertos/mpu_wrappers.h index b881448a5d..c02dcd0c41 100644 --- a/components/freertos/include/freertos/mpu_wrappers.h +++ b/components/freertos/include/freertos/mpu_wrappers.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index ce832f6c26..58b24b829c 100644 --- a/components/freertos/include/freertos/portable.h +++ b/components/freertos/include/freertos/portable.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/projdefs.h b/components/freertos/include/freertos/projdefs.h index 04f7b12343..b7cb4f9641 100644 --- a/components/freertos/include/freertos/projdefs.h +++ b/components/freertos/include/freertos/projdefs.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/queue.h b/components/freertos/include/freertos/queue.h index 9ff31d7eb8..ab6280fd09 100644 --- a/components/freertos/include/freertos/queue.h +++ b/components/freertos/include/freertos/queue.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/semphr.h b/components/freertos/include/freertos/semphr.h index d692375e65..08d52556e5 100644 --- a/components/freertos/include/freertos/semphr.h +++ b/components/freertos/include/freertos/semphr.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/stack_macros.h b/components/freertos/include/freertos/stack_macros.h index 27a01ccf04..ab5452fc85 100644 --- a/components/freertos/include/freertos/stack_macros.h +++ b/components/freertos/include/freertos/stack_macros.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/stream_buffer.h b/components/freertos/include/freertos/stream_buffer.h index ba8282ce73..9e58cff120 100644 --- a/components/freertos/include/freertos/stream_buffer.h +++ b/components/freertos/include/freertos/stream_buffer.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 8d525f244b..81e078c10e 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -47,10 +47,10 @@ * MACROS AND DEFINITIONS *----------------------------------------------------------*/ -#define tskKERNEL_VERSION_NUMBER "V10.2.1" +#define tskKERNEL_VERSION_NUMBER "V10.4.3" #define tskKERNEL_VERSION_MAJOR 10 -#define tskKERNEL_VERSION_MINOR 2 -#define tskKERNEL_VERSION_BUILD 1 +#define tskKERNEL_VERSION_MINOR 4 +#define tskKERNEL_VERSION_BUILD 3 /* MPU region parameters passed in ulParameters * of MemoryRegion_t struct. */ diff --git a/components/freertos/include/freertos/timers.h b/components/freertos/include/freertos/timers.h index 21cd63f80c..a8bc4f38c7 100644 --- a/components/freertos/include/freertos/timers.h +++ b/components/freertos/include/freertos/timers.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/port/riscv/include/freertos/portmacro.h b/components/freertos/port/riscv/include/freertos/portmacro.h index 9ead3fea26..cb58b42265 100644 --- a/components/freertos/port/riscv/include/freertos/portmacro.h +++ b/components/freertos/port/riscv/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/port/xtensa/include/freertos/portmacro.h b/components/freertos/port/xtensa/include/freertos/portmacro.h index eeabdf786a..248c86d15c 100644 --- a/components/freertos/port/xtensa/include/freertos/portmacro.h +++ b/components/freertos/port/xtensa/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/queue.c b/components/freertos/queue.c index 712fbd2119..486dd2d07e 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 4b02759566..dd34f19471 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/freertos/timers.c b/components/freertos/timers.c index 76fc364fb6..2a97723496 100644 --- a/components/freertos/timers.c +++ b/components/freertos/timers.c @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/mqtt/host_test/mocks/include/freertos/portmacro.h b/components/mqtt/host_test/mocks/include/freertos/portmacro.h index 67ce5f06d5..1ff7b7c953 100644 --- a/components/mqtt/host_test/mocks/include/freertos/portmacro.h +++ b/components/mqtt/host_test/mocks/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of From c098dce1e54b2050936bcb5f6baa21315c20a5d1 Mon Sep 17 00:00:00 2001 From: boarchuz <46267286+boarchuz@users.noreply.github.com> Date: Thu, 2 Sep 2021 01:56:31 +1000 Subject: [PATCH 108/310] check_sizes.py: Fix bootloader size message in build log Closes https://github.com/espressif/esp-idf/pull/7506 --- components/partition_table/check_sizes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/partition_table/check_sizes.py b/components/partition_table/check_sizes.py index d47b9d2838..c53e8c0725 100755 --- a/components/partition_table/check_sizes.py +++ b/components/partition_table/check_sizes.py @@ -64,7 +64,7 @@ def check_bootloader(partition_table_offset, bootloader_offset, binary_file): # _fail(msg) free_size = max_size - bootloader_size print('Bootloader binary size {:#x} bytes. {:#x} bytes ({}%) free.'.format( - bootloader_size, free_size, round(free_size * 100 / bootloader_size))) + bootloader_size, free_size, round(free_size * 100 / max_size))) def check_partition(ptype, subtype, partition_table_file, bin_file): # type: (str, str, io.IOBase, IO) -> None From 5671039154585048372d5b94ca1be2cd031e01c4 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Mon, 30 Aug 2021 17:39:40 +0800 Subject: [PATCH 109/310] ci(sonarqube): pass "sonar.exclusions" in CI also increase the jvm size --- .gitlab/ci/static-code-analysis.yml | 11 +++++++++++ sonar-project.properties | 11 ----------- tools/ci/sonar_exclude_list.txt | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.gitlab/ci/static-code-analysis.yml b/.gitlab/ci/static-code-analysis.yml index 3239dddc56..cdcabfd758 100644 --- a/.gitlab/ci/static-code-analysis.yml +++ b/.gitlab/ci/static-code-analysis.yml @@ -67,6 +67,14 @@ check_pylint: - source tools/ci/utils.sh - export PYTHONPATH="$CI_PROJECT_DIR/tools:$CI_PROJECT_DIR/tools/ci/python_packages:$PYTHONPATH" - fetch_submodules + # Exclude the submodules, all paths ends with /** + - submodules=$(get_all_submodules) + # get all exclude paths specified in tools/ci/sonar_exclude_list.txt | ignore lines start with # | xargs | replace all to + - custom_excludes=$(cat $CI_PROJECT_DIR/tools/ci/sonar_exclude_list.txt | grep -v '^#' | xargs | sed -e 's/ /,/g') + # Exclude the report dir as well + - export EXCLUSIONS="$custom_excludes,$submodules" + - export SONAR_SCANNER_OPTS="-Xmx2048m" + variables: GIT_DEPTH: 0 REPORT_PATTERN: clang_tidy_reports/*.txt @@ -95,8 +103,10 @@ code_quality_check: -Dsonar.analysis.mode=preview -Dsonar.branch.name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME -Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN + -Dsonar.exclusions=$EXCLUSIONS -Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID -Dsonar.gitlab.commit_sha=$CI_MERGE_REQUEST_COMMITS + -Dsonar.gitlab.merge_request_discussion=true -Dsonar.gitlab.ref_name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN @@ -112,6 +122,7 @@ code_quality_report: - sonar-scanner -Dsonar.branch.name=$CI_COMMIT_REF_NAME -Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN + -Dsonar.exclusions=$EXCLUSIONS -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME -Dsonar.host.url=$SONAR_HOST_URL diff --git a/sonar-project.properties b/sonar-project.properties index 4dfd721db6..e7dddab4ed 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -5,16 +5,6 @@ sonar.projectVersion=4.4 sonar.sources=. sonar.sourceEncoding=UTF-8 -# exclude list for sonarqube -# Here're some examples: (relative with the idf_path) -# test/**/* -# test/*/*.c -sonar.exclusion=\ - components/freertos/*.c,\ - components/freertos/include/freertos/*.h,\ - components/wpa_supplicant/src/**/*,\ - components/wpa_supplicant/include/**/* - sonar.inclusions=\ **/*.c,**/*.cpp,**/*.h,**/*.hpp,\ **/*.py @@ -33,5 +23,4 @@ sonar.cxx.file.suffixes=.cxx,.cpp,.cc,.c,.hxx,.hpp,.hh,.h ####################### sonar.gitlab.failure_notification_mode=exit-code -sonar.gitlab.merge_request_discussion=true sonar.gitlab.project_id=103 diff --git a/tools/ci/sonar_exclude_list.txt b/tools/ci/sonar_exclude_list.txt index e69de29bb2..a91e445f52 100644 --- a/tools/ci/sonar_exclude_list.txt +++ b/tools/ci/sonar_exclude_list.txt @@ -0,0 +1,15 @@ +# exclude list for sonarqube +# Here're some examples: (relative with the idf_path) +# test/** +# test/*/*.c +# test.c +# +# lines start with # will be ignored + +# FreeRTOS upstream code (don't include our port files here) +components/freertos/*.c +components/freertos/include/freertos/*.h + +# wpa_supplicant upstream code +components/wpa_supplicant/src/** +components/wpa_supplicant/include/** From f80d6f8c212ab31a0e6cc242d58bcb27db9b0d8e Mon Sep 17 00:00:00 2001 From: Sachin Billore Date: Tue, 24 Aug 2021 21:23:45 +0530 Subject: [PATCH 110/310] Digital Signature support for S3 Closes IDF-1791 --- .../include/soc/esp32s3/esp_crypto_lock.h | 14 ++ .../include/soc/esp32s3/esp_ds.h | 192 +++++++++++++++ .../port/esp32s3/CMakeLists.txt | 13 +- .../port/esp32s3/esp_crypto_lock.c | 10 + .../esp_hw_support/port/esp32s3/esp_ds.c | 228 ++++++++++++++++++ components/esp_hw_support/test/test_ds.c | 68 +++--- components/hal/CMakeLists.txt | 97 ++++---- .../hal/esp32s3/include/hal/clk_gate_ll.h | 4 + components/hal/esp32s3/include/hal/ds_ll.h | 162 +++++++++++++ components/hal/include/hal/ds_hal.h | 2 +- .../soc/esp32s3/include/soc/hwcrypto_reg.h | 23 +- components/soc/esp32s3/include/soc/soc_caps.h | 13 +- docs/doxygen/Doxyfile_esp32s3 | 1 + 13 files changed, 727 insertions(+), 100 deletions(-) create mode 100644 components/esp_hw_support/include/soc/esp32s3/esp_ds.h create mode 100644 components/esp_hw_support/port/esp32s3/esp_ds.c create mode 100644 components/hal/esp32s3/include/hal/ds_ll.h diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.h index d45cc2e322..074754a86b 100644 --- a/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.h @@ -18,6 +18,20 @@ extern "C" { * Other unrelated components must not use it. */ +/** + * @brief Acquire lock for Digital Signature(DS) cryptography peripheral + * + * Internally also takes the HMAC lock, as the DS depends on the HMAC peripheral + */ +void esp_crypto_ds_lock_acquire(void); + +/** + * @brief Release lock for Digital Signature(DS) cryptography peripheral + * + * Internally also releases the HMAC lock, as the DS depends on the HMAC peripheral + */ +void esp_crypto_ds_lock_release(void); + /** * @brief Acquire lock for HMAC cryptography peripheral * diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_ds.h b/components/esp_hw_support/include/soc/esp32s3/esp_ds.h new file mode 100644 index 0000000000..46a1d22a54 --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32s3/esp_ds.h @@ -0,0 +1,192 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include + +#include "esp_hmac.h" +#include "esp_err.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP32S3_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */ +#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct, + HMAC peripheral problem */ +#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed, + result is invalid */ +#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result + is produced anyway and can be read*/ + +#define ESP_DS_IV_LEN 16 + +/* Length of parameter 'C' stored in flash */ +#define ESP_DS_C_LEN (12672 / 8) + +typedef struct esp_ds_context esp_ds_context_t; + +typedef enum { + ESP_DS_RSA_1024 = (1024 / 32) - 1, + ESP_DS_RSA_2048 = (2048 / 32) - 1, + ESP_DS_RSA_3072 = (3072 / 32) - 1, + ESP_DS_RSA_4096 = (4096 / 32) - 1 +} esp_digital_signature_length_t; + +/** + * Encrypted private key data. Recommended to store in flash in this format. + * + * @note This struct has to match to one from the ROM code! This documentation is mostly taken from there. + */ +typedef struct esp_digital_signature_data { + /** + * RSA LENGTH register parameters + * (number of words in RSA key & operands, minus one). + * + * Max value 127 (for RSA 4096). + * + * This value must match the length field encrypted and stored in 'c', + * or invalid results will be returned. (The DS peripheral will + * always use the value in 'c', not this value, so an attacker can't + * alter the DS peripheral results this way, it will just truncate or + * extend the message and the resulting signature in software.) + * + * @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably. + * See the ROM code for the original declaration of struct \c ets_ds_data_t. + */ + esp_digital_signature_length_t rsa_length; + + /** + * IV value used to encrypt 'c' + */ + uint8_t iv[ESP_DS_IV_LEN]; + + /** + * Encrypted Digital Signature parameters. Result of AES-CBC encryption + * of plaintext values. Includes an encrypted message digest. + */ + uint8_t c[ESP_DS_C_LEN]; +} esp_ds_data_t; + +/** Plaintext parameters used by Digital Signature. + * + * Not used for signing with DS peripheral, but can be encrypted + * in-device by calling esp_ds_encrypt_params() + * + * @note This documentation is mostly taken from the ROM code. + */ +typedef struct { + uint32_t Y[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA exponent + uint32_t M[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA modulus + uint32_t Rb[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA r inverse operand + uint32_t M_prime; //!< RSA M prime operand + esp_digital_signature_length_t length; //!< RSA length +} esp_ds_p_data_t; + +/** + * Sign the message. + * + * This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them + * in parallel. + * It blocks until the signing is finished and then returns the signature. + * + * @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time. + * + * @param message the message to be signed; its length is determined by data->rsa_length + * @param data the encrypted signing key data (AES encrypted RSA key + IV) + * @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the + * signing key data + * @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long + * + * @return + * - ESP_OK if successful, the signature was written to the parameter \c signature. + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0 + * - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key + * - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object + * - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component + * - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid. + * - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though + * since the message digest matches. + */ +esp_err_t esp_ds_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + void *signature); + +/** + * Start the signing process. + * + * This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing + * process. + * + * @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call + * \c esp_ds_finish_sign() in a timely manner. + * + * @param message the message to be signed; its length is determined by data->rsa_length + * @param data the encrypted signing key data (AES encrypted RSA key + IV) + * @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the + * signing key data + * @param esp_ds_ctx the context object which is needed for finishing the signing process later + * + * @return + * - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign() + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0 + * - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key + * - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object + * - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component + */ +esp_err_t esp_ds_start_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + esp_ds_context_t **esp_ds_ctx); + +/** + * Return true if the DS peripheral is busy, otherwise false. + * + * @note Only valid if \c esp_ds_start_sign() was called before. + */ +bool esp_ds_is_busy(void); + +/** + * Finish the signing process. + * + * @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long + * @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign() + * + * @return + * - ESP_OK if successful, the ds operation has been finished and the result is written to signature. + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL + * - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid. + * - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though + * since the message digest matches. + */ +esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx); + +/** + * Encrypt the private key parameters. + * + * @param data Output buffer to store encrypted data, suitable for later use generating signatures. + * The allocated memory must be in internal memory and word aligned since it's filled by DMA. Both is asserted + * at run time. + * @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time. + * @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process + * is done and 'data' is stored. + * @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the + * corresponding HMAC key will be stored to efuse and then permanently erased. + * + * @return + * - ESP_OK if successful, the ds operation has been finished and the result is written to signature. + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long + */ +esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32s3/CMakeLists.txt b/components/esp_hw_support/port/esp32s3/CMakeLists.txt index e607f84f04..e375c6df6d 100644 --- a/components/esp_hw_support/port/esp32s3/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32s3/CMakeLists.txt @@ -10,15 +10,16 @@ set(srcs "rtc_time.c" "rtc_wdt.c" "chip_info.c" - ) + ) if(NOT BOOTLOADER_BUILD) list(APPEND srcs "../async_memcpy_impl_gdma.c" - "dport_access.c" - "esp_hmac.c" - "esp_crypto_lock.c" - "memprot.c" - "spiram.c") + "dport_access.c" + "esp_hmac.c" + "esp_ds.c" + "esp_crypto_lock.c" + "memprot.c" + "spiram.c") if(CONFIG_SPIRAM_MODE_QUAD) list(APPEND srcs "spiram_psram.c") diff --git a/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c b/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c index 3e99a08ea4..a8ca5212f1 100644 --- a/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c @@ -26,6 +26,16 @@ static _lock_t s_crypto_sha_aes_hmac_ds_lock; /* Lock for the MPI/RSA peripheral, also used by the DS peripheral */ static _lock_t s_crypto_mpi_lock; +void esp_crypto_ds_lock_acquire(void) +{ + _lock_acquire_recursive(&s_crypto_sha_aes_hmac_ds_lock); +} + +void esp_crypto_ds_lock_release(void) +{ + _lock_release_recursive(&s_crypto_sha_aes_hmac_ds_lock); +} + void esp_crypto_hmac_lock_acquire(void) { _lock_acquire_recursive(&s_crypto_sha_aes_hmac_ds_lock); diff --git a/components/esp_hw_support/port/esp32s3/esp_ds.c b/components/esp_hw_support/port/esp32s3/esp_ds.c new file mode 100644 index 0000000000..90385de752 --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/esp_ds.c @@ -0,0 +1,228 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/periph_ctrl.h" +#include "esp_crypto_lock.h" +#include "hal/ds_hal.h" +#include "hal/ds_ll.h" +#include "hal/hmac_hal.h" +#include "esp32s3/rom/digital_signature.h" +#include "esp_timer.h" +#include "esp_ds.h" + +struct esp_ds_context { + const esp_ds_data_t *data; +}; + +/** + * The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation. + */ +#define ESP_DS_SIGN_TASK_DELAY_MS 10 + +#define RSA_LEN_MAX 127 + +/* + * esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used. + * Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts. + */ +_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned), + "The size of esp_digital_signature_length_t and unsigned has to be the same"); + +/* + * esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t. + * Check esp_ds_data_t's width here because it's converted using raw casts. + */ +_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t), + "The size of esp_ds_data_t and ets_ds_data_t has to be the same"); + +static void ds_acquire_enable(void) +{ + esp_crypto_ds_lock_acquire(); + esp_crypto_mpi_lock_acquire(); + + // We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS. + periph_module_enable(PERIPH_HMAC_MODULE); + periph_module_enable(PERIPH_SHA_MODULE); + periph_module_enable(PERIPH_DS_MODULE); + + hmac_hal_start(); +} + +static void ds_disable_release(void) +{ + ds_hal_finish(); + + periph_module_disable(PERIPH_DS_MODULE); + periph_module_disable(PERIPH_SHA_MODULE); + periph_module_disable(PERIPH_HMAC_MODULE); + + esp_crypto_mpi_lock_release(); + esp_crypto_ds_lock_release(); +} + +esp_err_t esp_ds_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + void *signature) +{ + // Need to check signature here, otherwise the signature is only checked when the signing has finished and fails + // but the signing isn't uninitialized and the mutex is still locked. + if (!signature) { + return ESP_ERR_INVALID_ARG; + } + + esp_ds_context_t *context; + esp_err_t result = esp_ds_start_sign(message, data, key_id, &context); + if (result != ESP_OK) { + return result; + } + + while (esp_ds_is_busy()) { + vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS); + } + + return esp_ds_finish_sign(signature, context); +} + +esp_err_t esp_ds_start_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + esp_ds_context_t **esp_ds_ctx) +{ + if (!message || !data || !esp_ds_ctx) { + return ESP_ERR_INVALID_ARG; + } + + if (key_id >= HMAC_KEY_MAX) { + return ESP_ERR_INVALID_ARG; + } + + if (!(data->rsa_length == ESP_DS_RSA_1024 + || data->rsa_length == ESP_DS_RSA_2048 + || data->rsa_length == ESP_DS_RSA_3072 + || data->rsa_length == ESP_DS_RSA_4096)) { + return ESP_ERR_INVALID_ARG; + } + + ds_acquire_enable(); + + // initiate hmac + uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id); + if (conf_error) { + ds_disable_release(); + return ESP32S3_ERR_HW_CRYPTO_DS_HMAC_FAIL; + } + + ds_hal_start(); + + // check encryption key from HMAC + int64_t start_time = esp_timer_get_time(); + while (ds_ll_busy() != 0) { + if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) { + ds_disable_release(); + return ESP32S3_ERR_HW_CRYPTO_DS_INVALID_KEY; + } + } + + esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t)); + if (!context) { + ds_disable_release(); + return ESP_ERR_NO_MEM; + } + + size_t rsa_len = (data->rsa_length + 1) * 4; + ds_hal_write_private_key_params(data->c); + ds_hal_configure_iv((uint32_t *)data->iv); + ds_hal_write_message(message, rsa_len); + + // initiate signing + ds_hal_start_sign(); + + context->data = data; + *esp_ds_ctx = context; + + return ESP_OK; +} + +bool esp_ds_is_busy(void) +{ + return ds_hal_busy(); +} + +esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx) +{ + if (!signature || !esp_ds_ctx) { + return ESP_ERR_INVALID_ARG; + } + + const esp_ds_data_t *data = esp_ds_ctx->data; + unsigned rsa_len = (data->rsa_length + 1) * 4; + + while (ds_hal_busy()) { } + + ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t *) signature, (size_t) rsa_len); + + esp_err_t return_value = ESP_OK; + + if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) { + return_value = ESP32S3_ERR_HW_CRYPTO_DS_INVALID_DIGEST; + } + + if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) { + return_value = ESP32S3_ERR_HW_CRYPTO_DS_INVALID_PADDING; + } + + free(esp_ds_ctx); + + hmac_hal_clean(); + + ds_disable_release(); + + return return_value; +} + +esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key) +{ + if (!p_data) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t result = ESP_OK; + + esp_crypto_ds_lock_acquire(); + periph_module_enable(PERIPH_AES_MODULE); + periph_module_enable(PERIPH_DS_MODULE); + periph_module_enable(PERIPH_SHA_MODULE); + periph_module_enable(PERIPH_HMAC_MODULE); + periph_module_enable(PERIPH_RSA_MODULE); + + ets_ds_data_t *ds_data = (ets_ds_data_t *) data; + const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data; + + ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC); + + if (ets_result == ETS_DS_INVALID_PARAM) { + result = ESP_ERR_INVALID_ARG; + } + + periph_module_disable(PERIPH_RSA_MODULE); + periph_module_disable(PERIPH_HMAC_MODULE); + periph_module_disable(PERIPH_SHA_MODULE); + periph_module_disable(PERIPH_DS_MODULE); + periph_module_disable(PERIPH_AES_MODULE); + esp_crypto_ds_lock_release(); + + return result; +} diff --git a/components/esp_hw_support/test/test_ds.c b/components/esp_hw_support/test/test_ds.c index cd08702f26..2a69e1e8dc 100644 --- a/components/esp_hw_support/test/test_ds.c +++ b/components/esp_hw_support/test/test_ds.c @@ -19,13 +19,18 @@ #include "esp32c3/rom/efuse.h" #include "esp32c3/rom/digital_signature.h" #include "esp32c3/rom/hmac.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/efuse.h" +#include "esp32s3/rom/digital_signature.h" +#include "esp32s3/rom/aes.h" +#include "esp32s3/rom/sha.h" #endif #include "esp_ds.h" #define NUM_RESULTS 10 -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #define DS_MAX_BITS (4096) #elif CONFIG_IDF_TARGET_ESP32C3 #define DS_MAX_BITS (ETS_DS_MAX_BITS) @@ -36,17 +41,17 @@ typedef struct { ets_ds_p_data_t p_data; uint8_t expected_c[ETS_DS_C_LEN]; uint8_t hmac_key_idx; - uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS/32]; + uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS / 32]; } encrypt_testcase_t; // Generated header digital_signature_test_cases_.h (by gen_digital_signature_tests.py) defines // NUM_HMAC_KEYS, test_hmac_keys, NUM_MESSAGES, NUM_CASES, test_messages[], test_cases[] // Some adaptations were made: removed the 512 bit case and changed RSA lengths to the enums from esp_ds.h #if DS_MAX_BITS == 4096 -#define RSA_LEN (ESP_DS_RSA_4096) +#define RSA_LEN (ESP_DS_RSA_4096) #include "digital_signature_test_cases_4096.h" #elif DS_MAX_BITS == 3072 -#define RSA_LEN (ESP_DS_RSA_3072) +#define RSA_LEN (ESP_DS_RSA_3072) #include "digital_signature_test_cases_3072.h" #endif @@ -96,14 +101,14 @@ TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]") esp_ds_data_t result = { }; esp_ds_p_data_t p_data; - memcpy(p_data.Y, t->p_data.Y, DS_MAX_BITS/8); - memcpy(p_data.M, t->p_data.M, DS_MAX_BITS/8); - memcpy(p_data.Rb, t->p_data.Rb, DS_MAX_BITS/8); + memcpy(p_data.Y, t->p_data.Y, DS_MAX_BITS / 8); + memcpy(p_data.M, t->p_data.M, DS_MAX_BITS / 8); + memcpy(p_data.Rb, t->p_data.Rb, DS_MAX_BITS / 8); p_data.M_prime = t->p_data.M_prime; p_data.length = t->p_data.length; esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data, - test_hmac_keys[t->hmac_key_idx]); + test_hmac_keys[t->hmac_key_idx]); printf("Encrypting test case %d done\n", i); TEST_ASSERT_EQUAL(ESP_OK, r); TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length); @@ -249,9 +254,10 @@ static void burn_hmac_keys(void) // starting from block 1, block 0 occupied with HMAC upstream test key int __attribute__((unused)) ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY1 + i, - purpose, - test_hmac_keys[i], 32); -#if CONFIG_IDF_TARGET_ESP32S2 + purpose, + test_hmac_keys[i], 32); + +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (ets_status == ESP_OK) { printf("written DS test key to block [%d]!\n", ETS_EFUSE_BLOCK_KEY1 + i); } else { @@ -280,7 +286,7 @@ TEST_CASE("Digital Signature wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ const char *message = "test"; // HMAC fails in that case because it checks for the correct purpose -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx)); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx)); @@ -297,7 +303,7 @@ TEST_CASE("Digital Signature Blocking wrong HMAC key purpose (FPGA only)", "[hw_ uint8_t signature_data [128 * 4]; // HMAC fails in that case because it checks for the correct purpose -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data)); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data)); @@ -319,15 +325,15 @@ TEST_CASE("Digital Signature Operation (FPGA only)", "[hw_crypto] [ds]") ds_data.rsa_length = t->p_data.length; for (int j = 0; j < NUM_MESSAGES; j++) { - uint8_t signature[DS_MAX_BITS/8] = { 0 }; + uint8_t signature[DS_MAX_BITS / 8] = { 0 }; printf(" ... message %d\n", j); esp_ds_context_t *esp_ds_ctx; esp_err_t ds_r = esp_ds_start_sign(test_messages[j], - &ds_data, - t->hmac_key_idx + 1, - &esp_ds_ctx); + &ds_data, + t->hmac_key_idx + 1, + &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); @@ -355,23 +361,23 @@ TEST_CASE("Digital Signature Blocking Operation (FPGA only)", "[hw_crypto] [ds]" memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN); ds_data.rsa_length = t->p_data.length; - uint8_t signature[DS_MAX_BITS/8] = { 0 }; -#if CONFIG_IDF_TARGET_ESP32S2 + uint8_t signature[DS_MAX_BITS / 8] = { 0 }; +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 esp_ds_context_t *esp_ds_ctx; esp_err_t ds_r = esp_ds_start_sign(test_messages[0], - &ds_data, - t->hmac_key_idx + 1, - &esp_ds_ctx); + &ds_data, + t->hmac_key_idx + 1, + &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); #elif CONFIG_IDF_TARGET_ESP32C3 esp_err_t ds_r = esp_ds_sign(test_messages[0], - &ds_data, - t->hmac_key_idx + 1, - signature); + &ds_data, + t->hmac_key_idx + 1, + signature); TEST_ASSERT_EQUAL(ESP_OK, ds_r); #endif @@ -390,8 +396,8 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]") memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN); ds_data.rsa_length = t->p_data.length; - uint8_t signature[DS_MAX_BITS/8] = { 0 }; - const uint8_t zero[DS_MAX_BITS/8] = { 0 }; + uint8_t signature[DS_MAX_BITS / 8] = { 0 }; + const uint8_t zero[DS_MAX_BITS / 8] = { 0 }; // Corrupt the IV one bit at a time, rerun and expect failure for (int bit = 0; bit < 128; bit++) { @@ -402,12 +408,12 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]") esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #endif - TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8); + TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8); ds_data.iv[bit / 8] ^= 1 << (bit % 8); } @@ -422,12 +428,12 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]") esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #endif - TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8); + TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8); ds_data.c[bit / 8] ^= 1 << (bit % 8); } diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index b5d8de8a9b..ecee471ee7 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -1,52 +1,52 @@ idf_build_get_property(target IDF_TARGET) -set(srcs "wdt_hal_iram.c" - "mpu_hal.c" - "cpu_hal.c") +set(srcs "wdt_hal_iram.c" + "mpu_hal.c" + "cpu_hal.c") set(includes "${target}/include" "include" "platform_port/include") if(NOT BOOTLOADER_BUILD) list(APPEND srcs - "rmt_hal.c" - "rtc_io_hal.c" - "spi_hal.c" - "spi_hal_iram.c" - "spi_slave_hal.c" - "spi_slave_hal_iram.c" - "i2s_hal.c" - "sigmadelta_hal.c" - "timer_hal.c" - "ledc_hal.c" - "ledc_hal_iram.c" - "i2c_hal.c" - "i2c_hal_iram.c" - "gpio_hal.c" - "uart_hal.c" - "uart_hal_iram.c" - "spi_flash_hal.c" - "spi_flash_hal_iram.c" - "spi_flash_encrypt_hal_iram.c" - "soc_hal.c" - "interrupt_controller_hal.c" - "sha_hal.c" - "aes_hal.c" - "twai_hal.c" - "twai_hal_iram.c" - "adc_hal.c") + "rmt_hal.c" + "rtc_io_hal.c" + "spi_hal.c" + "spi_hal_iram.c" + "spi_slave_hal.c" + "spi_slave_hal_iram.c" + "i2s_hal.c" + "sigmadelta_hal.c" + "timer_hal.c" + "ledc_hal.c" + "ledc_hal_iram.c" + "i2c_hal.c" + "i2c_hal_iram.c" + "gpio_hal.c" + "uart_hal.c" + "uart_hal_iram.c" + "spi_flash_hal.c" + "spi_flash_hal_iram.c" + "spi_flash_encrypt_hal_iram.c" + "soc_hal.c" + "interrupt_controller_hal.c" + "sha_hal.c" + "aes_hal.c" + "twai_hal.c" + "twai_hal_iram.c" + "adc_hal.c") if(${target} STREQUAL "esp32") list(APPEND srcs - "dac_hal.c" - "mcpwm_hal.c" - "pcnt_hal.c" - "sdio_slave_hal.c" - "touch_sensor_hal.c" - "esp32/adc_hal.c" - "esp32/brownout_hal.c" - "esp32/interrupt_descriptor_table.c" - "esp32/touch_sensor_hal.c" - "esp32/gpio_hal_workaround.c") + "dac_hal.c" + "mcpwm_hal.c" + "pcnt_hal.c" + "sdio_slave_hal.c" + "touch_sensor_hal.c" + "esp32/adc_hal.c" + "esp32/brownout_hal.c" + "esp32/interrupt_descriptor_table.c" + "esp32/touch_sensor_hal.c" + "esp32/gpio_hal_workaround.c") if(NOT BOOTLOADER_BUILD AND CONFIG_ETH_USE_ESP32_EMAC) list(APPEND srcs "emac_hal.c") endif() @@ -73,6 +73,7 @@ if(NOT BOOTLOADER_BUILD) if(${target} STREQUAL "esp32s3") list(APPEND srcs + "ds_hal.c" "gdma_hal.c" "lcd_hal.c" "mcpwm_hal.c" @@ -106,15 +107,15 @@ if(NOT BOOTLOADER_BUILD) if(${target} STREQUAL "esp32h2") list(APPEND srcs - "ds_hal.c" - "gdma_hal.c" - "spi_flash_hal_gpspi.c" - "spi_slave_hd_hal.c" - "systimer_hal.c" - "esp32h2/adc_hal.c" - "esp32h2/brownout_hal.c" - "esp32h2/hmac_hal.c" - "esp32h2/rtc_cntl_hal.c") + "ds_hal.c" + "gdma_hal.c" + "spi_flash_hal_gpspi.c" + "spi_slave_hd_hal.c" + "systimer_hal.c" + "esp32h2/adc_hal.c" + "esp32h2/brownout_hal.c" + "esp32h2/hmac_hal.c" + "esp32h2/rtc_cntl_hal.c") endif() endif() diff --git a/components/hal/esp32s3/include/hal/clk_gate_ll.h b/components/hal/esp32s3/include/hal/clk_gate_ll.h index 3f3fe70fd6..01f684732f 100644 --- a/components/hal/esp32s3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32s3/include/hal/clk_gate_ll.h @@ -157,6 +157,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return SYSTEM_DMA_RST; case PERIPH_HMAC_MODULE: return SYSTEM_CRYPTO_HMAC_RST; + case PERIPH_DS_MODULE: + return SYSTEM_CRYPTO_DS_RST; case PERIPH_AES_MODULE: if (enable == true) { // Clear reset on digital signature, otherwise AES unit is held in reset also. @@ -203,6 +205,7 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) case PERIPH_LCD_CAM_MODULE: case PERIPH_GDMA_MODULE: case PERIPH_HMAC_MODULE: + case PERIPH_DS_MODULE: case PERIPH_AES_MODULE: case PERIPH_SHA_MODULE: case PERIPH_RSA_MODULE: @@ -229,6 +232,7 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) case PERIPH_LCD_CAM_MODULE: case PERIPH_GDMA_MODULE: case PERIPH_HMAC_MODULE: + case PERIPH_DS_MODULE: case PERIPH_AES_MODULE: case PERIPH_SHA_MODULE: case PERIPH_RSA_MODULE: diff --git a/components/hal/esp32s3/include/hal/ds_ll.h b/components/hal/esp32s3/include/hal/ds_ll.h new file mode 100644 index 0000000000..f5ae99074c --- /dev/null +++ b/components/hal/esp32s3/include/hal/ds_ll.h @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#include "soc/hwcrypto_reg.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void ds_ll_start(void) +{ + REG_WRITE(DS_SET_START_REG, 1); +} + +/** + * @brief Wait until DS peripheral has finished any outstanding operation. + */ +static inline bool ds_ll_busy(void) +{ + return (REG_READ(DS_QUERY_BUSY_REG) > 0) ? true : false; +} + +/** + * @brief Busy wait until the hardware is ready. + */ +static inline void ds_ll_wait_busy(void) +{ + while (ds_ll_busy()); +} + +/** + * @brief In case of a key error, check what caused it. + */ +static inline ds_key_check_t ds_ll_key_error_source(void) +{ + uint32_t key_error = REG_READ(DS_QUERY_KEY_WRONG_REG); + if (key_error == 0) { + return DS_NO_KEY_INPUT; + } else { + return DS_OTHER_WRONG; + } +} + +/** + * @brief Write the initialization vector to the corresponding register field. + */ +static inline void ds_ll_configure_iv(const uint32_t *iv) +{ + for (size_t i = 0; i < (SOC_DS_KEY_PARAM_MD_IV_LENGTH / sizeof(uint32_t)); i++) { + REG_WRITE(DS_IV_BASE + (i * 4), iv[i]); + } +} + +/** + * @brief Write the message which should be signed. + * + * @param msg Pointer to the message. + * @param size Length of msg in bytes. It is the RSA signature length in bytes. + */ +static inline void ds_ll_write_message(const uint8_t *msg, size_t size) +{ + memcpy((uint8_t *) DS_X_BASE, msg, size); +} + +/** + * @brief Write the encrypted private key parameters. + */ +static inline void ds_ll_write_private_key_params(const uint8_t *encrypted_key_params) +{ + /* Note: as the internal peripheral still has RSA 4096 structure, + but C is encrypted based on the actual max RSA length (ETS_DS_MAX_BITS), need to fragment it + when copying to hardware... + + (note if ETS_DS_MAX_BITS == 4096, this should be the same as copying data->c to hardware in one fragment) + */ + typedef struct { + uint32_t addr; + size_t len; + } frag_t; + const frag_t frags[] = { + {DS_C_Y_BASE, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8}, + {DS_C_M_BASE, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8}, + {DS_C_RB_BASE, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8}, + {DS_C_BOX_BASE, DS_IV_BASE - DS_C_BOX_BASE}, + }; + const size_t NUM_FRAGS = sizeof(frags) / sizeof(frag_t); + const uint8_t *from = encrypted_key_params; + + for (int i = 0; i < NUM_FRAGS; i++) { + memcpy((uint8_t *)frags[i].addr, from, frags[i].len); + from += frags[i].len; + } +} + +/** + * @brief Begin signing procedure. + */ +static inline void ds_ll_start_sign(void) +{ + REG_WRITE(DS_SET_ME_REG, 1); +} + +/** + * @brief check the calculated signature. + * + * @return + * - DS_SIGNATURE_OK if no issue is detected with the signature. + * - DS_SIGNATURE_PADDING_FAIL if the padding of the private key parameters is wrong. + * - DS_SIGNATURE_MD_FAIL if the message digest check failed. This means that the message digest calculated using + * the private key parameters fails, i.e., the integrity of the private key parameters is not protected. + * - DS_SIGNATURE_PADDING_AND_MD_FAIL if both padding and message digest check fail. + */ +static inline ds_signature_check_t ds_ll_check_signature(void) +{ + uint32_t result = REG_READ(DS_QUERY_CHECK_REG); + switch (result) { + case 0: + return DS_SIGNATURE_OK; + case 1: + return DS_SIGNATURE_MD_FAIL; + case 2: + return DS_SIGNATURE_PADDING_FAIL; + default: + return DS_SIGNATURE_PADDING_AND_MD_FAIL; + } +} + +/** + * @brief Read the signature from the hardware. + * + * @param result The signature result. + * @param size Length of signature result in bytes. It is the RSA signature length in bytes. + */ +static inline void ds_ll_read_result(uint8_t *result, size_t size) +{ + memcpy(result, (uint8_t *) DS_Z_BASE, size); +} + +/** + * @brief Exit the signature operation. + * + * @note This does not deactivate the module. Corresponding clock/reset bits have to be triggered for deactivation. + */ +static inline void ds_ll_finish(void) +{ + REG_WRITE(DS_SET_FINISH_REG, 1); + ds_ll_wait_busy(); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/ds_hal.h b/components/hal/include/hal/ds_hal.h index 253fab9f96..40d5c35893 100644 --- a/components/hal/include/hal/ds_hal.h +++ b/components/hal/include/hal/ds_hal.h @@ -21,7 +21,7 @@ #pragma once #if CONFIG_IDF_TARGET_ESP32 - #error "ESP32 doesn't have a DS peripheral" +#error "ESP32 doesn't have a DS peripheral" #endif #include diff --git a/components/soc/esp32s3/include/soc/hwcrypto_reg.h b/components/soc/esp32s3/include/soc/hwcrypto_reg.h index 9e16b742e7..09011285fd 100644 --- a/components/soc/esp32s3/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32s3/include/soc/hwcrypto_reg.h @@ -1,16 +1,9 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include "soc.h" @@ -129,6 +122,10 @@ /* Digital Signature registers*/ #define DS_C_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x000 ) +#define DS_C_Y_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x000 ) +#define DS_C_M_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x200 ) +#define DS_C_RB_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x400 ) +#define DS_C_BOX_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x600 ) #define DS_IV_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x630 ) #define DS_X_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x800 ) #define DS_Z_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0xA00 ) diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 0ad56c7791..2260b176c6 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -18,7 +18,7 @@ #define SOC_USB_OTG_SUPPORTED 1 #define SOC_RTC_SLOW_MEM_SUPPORTED 1 #define SOC_CCOMP_TIMER_SUPPORTED 1 -#define SOC_DIG_SIGN_SUPPORTED 0 +#define SOC_DIG_SIGN_SUPPORTED 1 #define SOC_HMAC_SUPPORTED 1 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 #define SOC_SUPPORTS_SECURE_DL_MODE 1 @@ -51,6 +51,17 @@ /*-------------------------- CPU CAPS ----------------------------------------*/ #include "cpu_caps.h" +/*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ +/** The maximum length of a Digital Signature in bits. */ +#define SOC_DS_SIGNATURE_MAX_BIT_LEN (4096) + +/** Initialization vector (IV) length for the RSA key parameter message digest (MD) in bytes. */ +#define SOC_DS_KEY_PARAM_MD_IV_LENGTH (16) + +/** Maximum wait time for DS parameter decryption key. If overdue, then key error. + See TRM DS chapter for more details */ +#define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100) + /*-------------------------- GDMA CAPS ---------------------------------------*/ #define SOC_GDMA_GROUPS (1) // Number of GDMA groups #define SOC_GDMA_PAIRS_PER_GROUP (5) // Number of GDMA pairs in each group diff --git a/docs/doxygen/Doxyfile_esp32s3 b/docs/doxygen/Doxyfile_esp32s3 index 021e46ae76..54152bd320 100644 --- a/docs/doxygen/Doxyfile_esp32s3 +++ b/docs/doxygen/Doxyfile_esp32s3 @@ -1,6 +1,7 @@ INPUT += \ $(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_hmac.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \ $(PROJECT_PATH)/components/hal/include/hal/mcpwm_types.h \ $(PROJECT_PATH)/components/driver/include/driver/mcpwm.h \ $(PROJECT_PATH)/components/hal/include/hal/pcnt_types.h \ From b26da6f11563101d40ef6c23b54471aa2c06880f Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 2 Aug 2021 19:17:29 +0800 Subject: [PATCH 111/310] driver/i2s: refactor for i2s driver layer --- components/driver/i2s.c | 1815 +++++++++++++++-------- components/driver/include/driver/i2s.h | 2 +- components/hal/i2s_hal.c | 130 +- components/hal/include/hal/i2s_hal.h | 113 +- components/hal/include/hal/i2s_types.h | 12 +- components/soc/esp32/i2s_periph.c | 32 +- components/soc/esp32c3/i2s_periph.c | 16 +- components/soc/esp32s2/i2s_periph.c | 16 +- components/soc/esp32s3/i2s_periph.c | 32 +- components/soc/include/soc/i2s_periph.h | 16 +- 10 files changed, 1480 insertions(+), 704 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index f2085bc5ee..b91172819b 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -47,8 +47,8 @@ static const char *TAG = "I2S"; #define I2S_EXIT_CRITICAL_ISR(i2s_num) portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) #define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) -#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE) -#define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER) + +#define I2S_DMA_BUFFER_MAX_SIZE 4092 #if !SOC_GDMA_SUPPORTED #define I2S_INTR_IN_SUC_EOF BIT(9) @@ -82,6 +82,7 @@ typedef struct { QueueHandle_t i2s_queue; /*!< I2S queue handler*/ int dma_buf_count; /*!< DMA buffer count, number of buffer*/ int dma_buf_len; /*!< DMA buffer length, length of each buffer*/ + uint32_t last_buf_size; /*!< DMA last buffer size */ i2s_dma_t *tx; /*!< DMA Tx buffer*/ i2s_dma_t *rx; /*!< DMA Rx buffer*/ #if SOC_GDMA_SUPPORTED @@ -90,16 +91,11 @@ typedef struct { #else i2s_isr_handle_t i2s_isr_handle; /*!< I2S Interrupt handle*/ #endif - int channel_num; /*!< Number of channels*/ - int bytes_per_sample; /*!< Bytes per sample*/ - int bits_per_sample; /*!< Bits per sample*/ - i2s_comm_format_t communication_format; /*!bck_io_num == -1 || GPIO_IS_VALID_GPIO(pin->bck_io_num)), ESP_ERR_INVALID_ARG, TAG, "bck_io_num invalid"); ESP_RETURN_ON_FALSE((pin->ws_io_num == -1 || GPIO_IS_VALID_GPIO(pin->ws_io_num)), @@ -197,45 +225,61 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) ESP_RETURN_ON_FALSE((pin->data_in_num == -1 || GPIO_IS_VALID_GPIO(pin->data_in_num)), ESP_ERR_INVALID_ARG, TAG, "data_in_num invalid"); - if (p_i2s[i2s_num]->mode & I2S_MODE_SLAVE) { - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].tx_ws_sig, 0); - gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].tx_bck_sig, 0); + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_SLAVE) { + /* For "tx + rx + slave" or "rx + slave" mode, we should select RX signal index for ws and bck */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].s_rx_ws_sig, 0); + gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].s_rx_bck_sig, 0); + /* For "tx + slave" mode, we should select TX signal index for ws and bck */ } else { - gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].rx_ws_sig, 0); - gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].rx_bck_sig, 0); + gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].s_tx_ws_sig, 0); + gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].s_tx_bck_sig, 0); } } else { + /* mclk only available in master mode */ ESP_RETURN_ON_ERROR(i2s_check_set_mclk(i2s_num, pin->mck_io_num), TAG, "mclk config failed"); - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].tx_ws_sig, 0, 0); - gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].tx_bck_sig, 0, 0); + /* For "tx + rx + master" or "tx + master" mode, we should select TX signal index for ws and bck */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].m_tx_ws_sig, 0, 0); + gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].m_tx_bck_sig, 0, 0); + /* For "rx + master" mode, we should select RX signal index for ws and bck */ } else { - gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].rx_ws_sig, 0, 0); - gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].rx_bck_sig, 0, 0); + gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].m_rx_ws_sig, 0, 0); + gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].m_rx_bck_sig, 0, 0); } } + /* Set data input/ouput GPIO */ gpio_matrix_out_check_and_set(pin->data_out_num, i2s_periph_signal[i2s_num].data_out_sig, 0, 0); gpio_matrix_in_check_and_set(pin->data_in_num, i2s_periph_signal[i2s_num].data_in_sig, 0); return ESP_OK; } - -/************************************************************** - * I2S DMA operation * - * - i2s_dma_rx_callback * - * - i2s_dma_tx_callback * - * - i2s_intr_handler_default * - * - i2s_tx_reset * - * - i2s_rx_reset * - * - i2s_tx_start * - * - i2s_rx_start * - * - i2s_tx_stop * - * - i2s_rx_stop * - **************************************************************/ - +/*------------------------------------------------------------- + I2S DMA operation + ------------------------------------------------------------- + - [intr] i2s_dma_rx_callback + - [intr] i2s_dma_tx_callback + - [intr] i2s_intr_handler_default + - [helper] i2s_dma_intr_init + - [helper] i2s_tx_reset + - [helper] i2s_rx_reset + - [helper] i2s_tx_start + - [helper] i2s_rx_start + - [helper] i2s_tx_stop + - [helper] i2s_rx_stop + -------------------------------------------------------------*/ #if SOC_GDMA_SUPPORTED +/** + * @brief GDMA rx callback function + * @note This function is called by GDMA default ISR handler + * + * @param dma_chan GDMA channel handler + * @param event_data GDMA rx event data + * @param user_data GDMA user data + * @return + * - whether need yield + */ static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { i2s_obj_t *p_i2s = (i2s_obj_t *) user_data; @@ -262,6 +306,16 @@ static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_e return high_priority_task_awoken; } +/** + * @brief GDMA tx callback function + * @note This function is called by GDMA default ISR handler + * + * @param dma_chan GDMA channel handler + * @param event_data GDMA tx event data + * @param user_data GDMA user data + * @return + * - whether need yield + */ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { i2s_obj_t *p_i2s = (i2s_obj_t *) user_data; @@ -291,6 +345,13 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e } #else + +/** + * @brief I2S defalut interrupt handler + * @note This function is triggered by I2S dedicated DMA interrupt + * + * @param arg Argument transport to ISR, here is the pointer to I2S object + */ static void IRAM_ATTR i2s_intr_handler_default(void *arg) { i2s_obj_t *p_i2s = (i2s_obj_t *) arg; @@ -360,40 +421,97 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) } #endif + +/** + * @brief I2S DMA interrupt initialization + * @note I2S will use GDMA if chip supports, and the interrupt is triggered by GDMA. + * + * @param i2s_num I2S device number + * @return + * - ESP_OK I2S DMA interrupt initialize success + * - ESP_ERR_NOT_FOUND GDMA channel not found + * - ESP_ERR_INVALID_ARG Invalid arguments + * - ESP_ERR_INVALID_STATE GDMA state error + */ +static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num) +{ +#if SOC_GDMA_SUPPORTED + /* Set GDMA trigger module */ + gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S}; +#if SOC_I2S_NUM > 1 + /* Set GDMA trigger instance */ + trig.instance_id = (i2s_num == I2S_NUM_0) ? SOC_GDMA_TRIG_PERIPH_I2S0 : SOC_GDMA_TRIG_PERIPH_I2S1; +#else + trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0; +#endif // SOC_I2S_NUM + /* Set GDMA config */ + gdma_channel_alloc_config_t dma_cfg = {.flags.reserve_sibling = 1}; + if ( p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX; + /* Register a new GDMA tx channel */ + ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &p_i2s[i2s_num]->tx_dma_chan), TAG, "Register tx dma channel error"); + ESP_RETURN_ON_ERROR(gdma_connect(p_i2s[i2s_num]->tx_dma_chan, trig), TAG, "Connect tx dma channel error"); + gdma_tx_event_callbacks_t cb = {.on_trans_eof = i2s_dma_tx_callback}; + /* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */ + gdma_register_tx_event_callbacks(p_i2s[i2s_num]->tx_dma_chan, &cb, p_i2s[i2s_num]); + } + if ( p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + dma_cfg.direction = GDMA_CHANNEL_DIRECTION_RX; + /* Register a new GDMA rx channel */ + ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &p_i2s[i2s_num]->rx_dma_chan), TAG, "Register rx dma channel error"); + ESP_RETURN_ON_ERROR(gdma_connect(p_i2s[i2s_num]->rx_dma_chan, trig), TAG, "Connect rx dma channel error"); + gdma_rx_event_callbacks_t cb = {.on_recv_eof = i2s_dma_rx_callback}; + /* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */ + gdma_register_rx_event_callbacks(p_i2s[i2s_num]->rx_dma_chan, &cb, p_i2s[i2s_num]); + } +#else + /* Initial I2S module interrupt */ + ESP_RETURN_ON_ERROR(esp_intr_alloc(i2s_periph_signal[i2s_num].irq, p_i2s[i2s_num]->intr_alloc_flags, i2s_intr_handler_default, p_i2s[i2s_num], &p_i2s[i2s_num]->i2s_isr_handle), TAG, "Register I2S Interrupt error"); +#endif // SOC_GDMA_SUPPORTED + return ESP_OK; +} + +/** + * @brief I2S tx reset + * + * @param i2s_num I2S device number + */ static void i2s_tx_reset(i2s_port_t i2s_num) { p_i2s[i2s_num]->tx->curr_ptr = NULL; p_i2s[i2s_num]->tx->rw_pos = 0; + i2s_hal_reset_tx(&(p_i2s[i2s_num]->hal)); #if SOC_GDMA_SUPPORTED - // gdma_stop(p_i2s[i2s_num]->tx_dma_chan); - i2s_hal_reset_tx(&(p_i2s[i2s_num]->hal)); gdma_reset(p_i2s[i2s_num]->tx_dma_chan); - i2s_hal_reset_tx_fifo(&(p_i2s[i2s_num]->hal)); #else - // Reset I2S TX module first, and then, reset DMA and FIFO. - i2s_hal_reset_tx(&(p_i2s[i2s_num]->hal)); i2s_hal_reset_txdma(&(p_i2s[i2s_num]->hal)); - i2s_hal_reset_tx_fifo(&(p_i2s[i2s_num]->hal)); #endif + i2s_hal_reset_tx_fifo(&(p_i2s[i2s_num]->hal)); } +/** + * @brief I2S rx reset + * + * @param i2s_num I2S device number + */ static void i2s_rx_reset(i2s_port_t i2s_num) { p_i2s[i2s_num]->rx->curr_ptr = NULL; p_i2s[i2s_num]->rx->rw_pos = 0; + i2s_hal_reset_rx(&(p_i2s[i2s_num]->hal)); #if SOC_GDMA_SUPPORTED - i2s_hal_reset_rx(&(p_i2s[i2s_num]->hal)); gdma_reset(p_i2s[i2s_num]->rx_dma_chan); - i2s_hal_reset_rx_fifo(&(p_i2s[i2s_num]->hal)); #else - - // Reset I2S RX module first, and then, reset DMA and FIFO. - i2s_hal_reset_rx(&(p_i2s[i2s_num]->hal)); i2s_hal_reset_rxdma(&(p_i2s[i2s_num]->hal)); - i2s_hal_reset_rx_fifo(&(p_i2s[i2s_num]->hal)); #endif + i2s_hal_reset_rx_fifo(&(p_i2s[i2s_num]->hal)); } +/** + * @brief I2S tx start + * + * @param i2s_num I2S device number + */ static void i2s_tx_start(i2s_port_t i2s_num) { #if SOC_GDMA_SUPPORTED @@ -406,6 +524,11 @@ static void i2s_tx_start(i2s_port_t i2s_num) i2s_hal_start_tx(&(p_i2s[i2s_num]->hal)); } +/** + * @brief I2S rx start + * + * @param i2s_num I2S device number + */ static void i2s_rx_start(i2s_port_t i2s_num) { #if SOC_GDMA_SUPPORTED @@ -418,6 +541,11 @@ static void i2s_rx_start(i2s_port_t i2s_num) i2s_hal_start_rx(&(p_i2s[i2s_num]->hal)); } +/** + * @brief I2S tx stop + * + * @param i2s_num I2S device number + */ static void i2s_tx_stop(i2s_port_t i2s_num) { #if SOC_GDMA_SUPPORTED @@ -430,6 +558,11 @@ static void i2s_tx_stop(i2s_port_t i2s_num) #endif } +/** + * @brief I2S rx stop + * + * @param i2s_num I2S device number + */ static void i2s_rx_stop(i2s_port_t i2s_num) { #if SOC_GDMA_SUPPORTED @@ -442,169 +575,239 @@ static void i2s_rx_stop(i2s_port_t i2s_num) #endif } -/************************************************************** - * I2S buffer operation * - * - i2s_alloc_dma_buffer * - * - i2s_destroy_dma_queue * - * - i2s_create_dma_queue * - * - i2s_zero_dma_buffer * - **************************************************************/ -static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, int data_bits, int ch) +/*------------------------------------------------------------- + I2S buffer operation + ------------------------------------------------------------- + - [helper] i2s_get_buf_size + - [helper] i2s_delete_dma_buffer + - [helper] i2s_alloc_dma_buffer + - [main] i2s_realloc_dma_buffer + - [main] i2s_destroy_dma_object + - [main] i2s_create_dma_object + - [main] i2s_zero_dma_buffer + -------------------------------------------------------------*/ +/** + * @brief I2S get DMA buffer size + * + * @param i2s_num I2S device number + * @return + * - DMA buffer size + */ +static inline uint32_t i2s_get_buf_size(i2s_port_t i2s_num) { - if (p_i2s[i2s_num]->channel_num != ch) { - p_i2s[i2s_num]->channel_num = (ch == 2) ? 2 : 1; - } + /* Calculate bytes per sample, align to 16 bit */ + uint32_t bytes_per_sample = ((p_i2s[i2s_num]->hal_cfg.sample_bits + 15) / 16) * 2; + /* The DMA buffer limitation is 4092 bytes */ + uint32_t bytes_per_frame = bytes_per_sample * p_i2s[i2s_num]->hal_cfg.active_chan; + p_i2s[i2s_num]->dma_buf_len = (p_i2s[i2s_num]->dma_buf_len * bytes_per_frame > I2S_DMA_BUFFER_MAX_SIZE) ? + I2S_DMA_BUFFER_MAX_SIZE / bytes_per_frame : p_i2s[i2s_num]->dma_buf_len; + return p_i2s[i2s_num]->dma_buf_len * bytes_per_frame; +} - i2s_dma_t *save_tx = NULL, *save_rx = NULL; - - if (data_bits != p_i2s[i2s_num]->bits_per_sample) { - p_i2s[i2s_num]->bits_per_sample = data_bits; - - // Round bytes_per_sample up to next multiple of 16 bits - int halfwords_per_sample = (data_bits + 15) / 16; - p_i2s[i2s_num]->bytes_per_sample = halfwords_per_sample * 2; - - // Because limited of DMA buffer is 4092 bytes - if (p_i2s[i2s_num]->dma_buf_len * p_i2s[i2s_num]->bytes_per_sample * p_i2s[i2s_num]->channel_num > 4092) { - p_i2s[i2s_num]->dma_buf_len = 4092 / p_i2s[i2s_num]->bytes_per_sample / p_i2s[i2s_num]->channel_num; +/** + * @brief Delete DMA buffer and descriptor + * + * @param i2s_num I2S device number + * @param dma_obj DMA object + * @return + * - ESP_OK DMA buffer delete success + * - ESP_ERR_INVALID_ARG dma_obj is NULL + */ +static esp_err_t i2s_delete_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj) +{ + ESP_RETURN_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, TAG, "I2S DMA object can't be NULL"); + /* Loop to destroy every descriptor and buffer */ + for (int cnt = 0; cnt < p_i2s[i2s_num]->dma_buf_count; cnt++) { + if (dma_obj->desc && dma_obj->desc[cnt]) { + free(dma_obj->desc[cnt]); + dma_obj->desc[cnt] = NULL; } - - // Re-create TX DMA buffer - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - save_tx = p_i2s[i2s_num]->tx; - //destroy old tx dma if exist - if (save_tx) { - i2s_destroy_dma_queue(i2s_num, save_tx); - } - p_i2s[i2s_num]->tx = i2s_create_dma_queue(i2s_num, p_i2s[i2s_num]->dma_buf_count, p_i2s[i2s_num]->dma_buf_len); - if (p_i2s[i2s_num]->tx == NULL) { - ESP_LOGE(TAG, "Failed to create tx dma buffer"); - i2s_driver_uninstall(i2s_num); - return ESP_ERR_NO_MEM; - } - } - // Re-create RX DMA buffer - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { - save_rx = p_i2s[i2s_num]->rx; - //destroy old rx dma if exist - if (save_rx) { - i2s_destroy_dma_queue(i2s_num, save_rx); - } - p_i2s[i2s_num]->rx = i2s_create_dma_queue(i2s_num, p_i2s[i2s_num]->dma_buf_count, p_i2s[i2s_num]->dma_buf_len); - if (p_i2s[i2s_num]->rx == NULL) { - ESP_LOGE(TAG, "Failed to create rx dma buffer"); - i2s_driver_uninstall(i2s_num); - return ESP_ERR_NO_MEM; - } - i2s_hal_set_rx_eof_num(&(p_i2s[i2s_num]->hal), p_i2s[i2s_num]->dma_buf_len * p_i2s[i2s_num]->channel_num * p_i2s[i2s_num]->bytes_per_sample); + if (dma_obj->buf && dma_obj->buf[cnt]) { + free(dma_obj->buf[cnt]); + dma_obj->buf[cnt] = NULL; } } return ESP_OK; } -static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma) +/** + * @brief Allocate memory for DMA buffer and descriptor + * + * @param i2s_num I2S device number + * @param dma_obj DMA object + * @return + * - ESP_OK Allocate success + * - ESP_ERR_NO_MEM No memory for DMA buffer + */ +static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj) { - int bux_idx; - if (p_i2s[i2s_num] == NULL) { - ESP_LOGE(TAG, "Not initialized yet"); - return ESP_ERR_INVALID_ARG; + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, err, TAG, "I2S DMA object can't be NULL"); + + uint32_t buf_cnt = p_i2s[i2s_num]->dma_buf_count; + for (int cnt = 0; cnt < buf_cnt; cnt++) { + /* Allocate DMA buffer */ + dma_obj->buf[cnt] = (char *) heap_caps_calloc(1, dma_obj->buf_size, MALLOC_CAP_DMA); + ESP_GOTO_ON_FALSE(dma_obj->buf[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma buffer"); + /* Initialize DMA buffer to 0 */ + memset(dma_obj->buf[cnt], 0, dma_obj->buf_size); + ESP_LOGD(TAG, "Addr[%d] = %d", cnt, (int)dma_obj->buf[cnt]); + + /* Allocate DMA descpriptor */ + dma_obj->desc[cnt] = (lldesc_t *) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); + ESP_GOTO_ON_FALSE(dma_obj->desc[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma description entry"); } - if (dma == NULL) { - ESP_LOGE(TAG, "dma is NULL"); - return ESP_ERR_INVALID_ARG; + /* DMA descriptor must be initialize after all descriptor has been created, otherwise they can't be linked together as a chain */ + for (int cnt = 0; cnt < buf_cnt; cnt++) { + /* Initialize DMA descriptor */ + dma_obj->desc[cnt]->owner = 1; + dma_obj->desc[cnt]->eof = 1; + dma_obj->desc[cnt]->sosf = 0; + dma_obj->desc[cnt]->length = dma_obj->buf_size; + dma_obj->desc[cnt]->size = dma_obj->buf_size; + dma_obj->desc[cnt]->buf = (uint8_t *) dma_obj->buf[cnt]; + dma_obj->desc[cnt]->offset = 0; + /* Link to the next descriptor */ + dma_obj->desc[cnt]->empty = (uint32_t)((cnt < (buf_cnt - 1)) ? (dma_obj->desc[cnt + 1]) : dma_obj->desc[0]); } - for (bux_idx = 0; bux_idx < p_i2s[i2s_num]->dma_buf_count; bux_idx++) { - if (dma->desc && dma->desc[bux_idx]) { - free(dma->desc[bux_idx]); - } - if (dma->buf && dma->buf[bux_idx]) { - free(dma->buf[bux_idx]); - } + ESP_LOGI(TAG, "DMA Malloc info, datalen=blocksize=%d, dma_buf_count=%d", dma_obj->buf_size, buf_cnt); + return ESP_OK; +err: + /* Delete DMA buffer if failed to allocate memory */ + i2s_delete_dma_buffer(i2s_num, dma_obj); + return ret; +} + +/** + * @brief Realloc I2S dma buffer + * + * @param i2s_num I2S device number + * @param dma_obj DMA object + * + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM No memory for I2S tx dma buffer + */ +static esp_err_t i2s_realloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj) +{ + ESP_RETURN_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, TAG, "I2S DMA object can't be NULL"); + + /* Destroy old dma descriptor and buffer */ + i2s_delete_dma_buffer(i2s_num, dma_obj); + /* Alloc new dma descriptor and buffer */ + ESP_RETURN_ON_ERROR(i2s_alloc_dma_buffer(i2s_num, dma_obj), TAG, "Failed to allocate dma buffer"); + + return ESP_OK; +} + +/** + * @brief I2S destroy the whole DMA object + * + * @param i2s_num I2S device number + * @param dma Secondary pointer to the DMA object + * @return + * - ESP_OK I2S DMA buffer has been destroyed successfully + * - ESP_ERR_INVALID_ARG I2S driver has not installed yet + */ +static esp_err_t i2s_destroy_dma_object(i2s_port_t i2s_num, i2s_dma_t **dma) +{ + /* Check if DMA truely need destroy */ + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_ARG, TAG, "I2S not initialized yet"); + if (!(*dma)) { + return ESP_OK; } - if (dma->buf) { - free(dma->buf); + /* Destroy every descriptor and buffer */ + i2s_delete_dma_buffer(i2s_num, (*dma)); + /* Destroy descriptor pointer */ + if ((*dma)->desc) { + free((*dma)->desc); + (*dma)->desc = NULL; } - if (dma->desc) { - free(dma->desc); + /* Destroy buffer pointer */ + if ((*dma)->buf) { + free((*dma)->buf); + (*dma)->buf = NULL; } + /* Delete DMA mux */ + vSemaphoreDelete((*dma)->mux); + /* Delete DMA queue */ + vQueueDelete((*dma)->queue); + /* Free DMA structure */ + free(*dma); + *dma = NULL; ESP_LOGI(TAG, "DMA queue destroyed"); - vQueueDelete(dma->queue); - vSemaphoreDelete(dma->mux); - free(dma); return ESP_OK; } -static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len) +/** + * @brief Create I2S DMA object + * @note This function only create I2S DMA object but will not allocate memory + * for DMA descriptor and buffer, call 'i2s_alloc_dma_buffer' additionally to + * allocate DMA buffer + * + * @param i2s_num I2S device number + * @param dma The secondary pointer of DMA object + * @return + * - ESP_OK The pointer of DMA object + * - ESP_ERR_INVALID_ARG NULL pointer error or DMA object has been created + * - ESP_ERR_NO_MEM No memory for new DMA object + */ +static esp_err_t i2s_create_dma_object(i2s_port_t i2s_num, i2s_dma_t **dma) { - int bux_idx; - int sample_size = p_i2s[i2s_num]->bytes_per_sample * p_i2s[i2s_num]->channel_num; - i2s_dma_t *dma = (i2s_dma_t *) malloc(sizeof(i2s_dma_t)); - if (dma == NULL) { - ESP_LOGE(TAG, "Error malloc i2s_dma_t"); - return NULL; + ESP_RETURN_ON_FALSE(dma, ESP_ERR_INVALID_ARG, TAG, "DMA object secondary pointer is NULL"); + ESP_RETURN_ON_FALSE((*dma == NULL), ESP_ERR_INVALID_ARG, TAG, "DMA object has been created"); + uint32_t buf_cnt = p_i2s[i2s_num]->dma_buf_count; + /* Allocate new DMA structure */ + *dma = (i2s_dma_t *) malloc(sizeof(i2s_dma_t)); + ESP_RETURN_ON_FALSE(dma, ESP_ERR_NO_MEM, TAG, "DMA object secondary pointer is NULL"); + /* Allocate DMA buffer poiter */ + (*dma)->buf = (char **)malloc(sizeof(char *) * buf_cnt); + if (!(*dma)->buf) { + goto err; } - memset(dma, 0, sizeof(i2s_dma_t)); + memset((*dma)->buf, 0, sizeof(char *) * buf_cnt); + /* Allocate DMA descriptor poiter */ + (*dma)->desc = (lldesc_t **) malloc(sizeof(lldesc_t *) * buf_cnt); + if (!(*dma)->desc) { + goto err; + } + memset((*dma)->desc, 0, sizeof(lldesc_t *) * buf_cnt); + /* Create queue and mutex */ + (*dma)->queue = xQueueCreate(buf_cnt - 1, sizeof(char *)); + (*dma)->mux = xSemaphoreCreateMutex(); - dma->buf = (char **)malloc(sizeof(char *) * dma_buf_count); - if (dma->buf == NULL) { - ESP_LOGE(TAG, "Error malloc dma buffer pointer"); - free(dma); - return NULL; - } - memset(dma->buf, 0, sizeof(char *) * dma_buf_count); - - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->buf[bux_idx] = (char *) heap_caps_calloc(1, dma_buf_len * sample_size, MALLOC_CAP_DMA); - if (dma->buf[bux_idx] == NULL) { - ESP_LOGE(TAG, "Error malloc dma buffer"); - i2s_destroy_dma_queue(i2s_num, dma); - return NULL; - } - ESP_LOGD(TAG, "Addr[%d] = %d", bux_idx, (int)dma->buf[bux_idx]); - } - - dma->desc = (lldesc_t **) malloc(sizeof(lldesc_t *) * dma_buf_count); - if (dma->desc == NULL) { - ESP_LOGE(TAG, "Error malloc dma description"); - i2s_destroy_dma_queue(i2s_num, dma); - return NULL; - } - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->desc[bux_idx] = (lldesc_t *) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); - if (dma->desc[bux_idx] == NULL) { - ESP_LOGE(TAG, "Error malloc dma description entry"); - i2s_destroy_dma_queue(i2s_num, dma); - return NULL; - } - } - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->desc[bux_idx]->owner = 1; - dma->desc[bux_idx]->eof = 1; - dma->desc[bux_idx]->sosf = 0; - dma->desc[bux_idx]->length = dma_buf_len * sample_size; - dma->desc[bux_idx]->size = dma_buf_len * sample_size; - dma->desc[bux_idx]->buf = (uint8_t *) dma->buf[bux_idx]; - dma->desc[bux_idx]->offset = 0; - dma->desc[bux_idx]->empty = (uint32_t)((bux_idx < (dma_buf_count - 1)) ? (dma->desc[bux_idx + 1]) : dma->desc[0]); - } - dma->queue = xQueueCreate(dma_buf_count - 1, sizeof(char *)); - dma->mux = xSemaphoreCreateMutex(); - dma->buf_size = dma_buf_len * sample_size; - ESP_LOGI(TAG, "DMA Malloc info, datalen=blocksize=%d, dma_buf_count=%d", dma_buf_len * sample_size, dma_buf_count); - return dma; + return ESP_OK; +err: + ESP_LOGE(TAG, "I2S DMA object create failed, preparing to uninstall"); + /* Destroy DMA queue if failed to allocate memory */ + i2s_destroy_dma_object(i2s_num, dma); + return ESP_ERR_NO_MEM; } +/** + * @brief Zero the contents of the TX DMA buffer. + * @note Pushes zero-byte samples into the TX DMA buffer, until it is full. + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + + /* Clear I2S RX DMA buffer */ if (p_i2s[i2s_num]->rx && p_i2s[i2s_num]->rx->buf != NULL && p_i2s[i2s_num]->rx->buf_size != 0) { for (int i = 0; i < p_i2s[i2s_num]->dma_buf_count; i++) { memset(p_i2s[i2s_num]->rx->buf[i], 0, p_i2s[i2s_num]->rx->buf_size); } } + + /* Clear I2S TX DMA buffer */ if (p_i2s[i2s_num]->tx && p_i2s[i2s_num]->tx->buf != NULL && p_i2s[i2s_num]->tx->buf_size != 0) { - int bytes_left = 0; - bytes_left = (p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos) % 4; + /* Finish to write all tx data */ + int bytes_left = (p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos) % 4; if (bytes_left) { size_t zero_bytes = 0, bytes_written; i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); @@ -616,23 +819,51 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) return ESP_OK; } -/************************************************************** - * I2S clock operation * - * - i2s_get_clk * - * - i2s_apll_get_fi2s * - * - i2s_apll_calculate_fi2s * - * - i2s_fbclk_cal * - **************************************************************/ - -float i2s_get_clk(i2s_port_t i2s_num) -{ - ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - return (float)p_i2s[i2s_num]->sample_rate; -} - - +/*------------------------------------------------------------- + I2S clock operation + ------------------------------------------------------------- + - [helper] i2s_get_source_clock + - [helper] i2s_calculate_adc_dac_clock + - [helper] i2s_calculate_pdm_tx_clock + - [helper] i2s_calculate_pdm_rx_clock + - [helper] i2s_calculate_common_clock + - [main] i2s_calculate_clock + -------------------------------------------------------------*/ #if SOC_I2S_SUPPORTS_APLL -static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) +/** + * @brief APLL calculate function, was described by following: + * APLL Output frequency is given by the formula: + * + * apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) + * apll_freq = fout / ((o_div + 2) * 2) + * + * The dividend in this expression should be in the range of 240 - 600 MHz. + * In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0. + * * sdm0 frequency adjustment parameter, 0..255 + * * sdm1 frequency adjustment parameter, 0..255 + * * sdm2 frequency adjustment parameter, 0..63 + * * o_div frequency divider, 0..31 + * + * The most accurate way to find the sdm0..2 and odir parameters is to loop through them all, + * then apply the above formula, finding the closest frequency to the desired one. + * But 256*256*64*32 = 134,217,728 loops are too slow with ESP32 + * 1. We will choose the parameters with the highest level of change, + * With 350MHzmclk_multiple ? p_i2s[i2s_num]->mclk_multiple : I2S_MCLK_MULTIPLE_256; - uint32_t _bck_div = rate * multi / _fbck; - i2s_clock_src_t clk_src = I2S_CLK_D2CLK; - -//ADC mode only support on ESP32, -#if SOC_I2S_SUPPORTS_ADC_DAC - if ( p_i2s[i2s_num]->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { - _fbck = rate * I2S_LL_AD_BCK_FACTOR * 2; - _bck_div = I2S_LL_AD_BCK_FACTOR; +#if SOC_I2S_SUPPORTS_APLL + if (use_apll) { + int sdm0 = 0; + int sdm1 = 0; + int sdm2 = 0; + int odir = 0; + if (fixed_mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / 16 < SOC_I2S_APLL_MIN_RATE) { + ESP_LOGW(TAG, "i2s sample rate is too small, use I2S_CLK_D2CLK as default clock source"); + goto err; + } + ESP_LOGD(TAG, "APLL coefficient: sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); + rtc_clk_apll_enable(true, sdm0, sdm1, sdm2, odir); + return fixed_mclk; } +err: + /* Set I2S_D2CLK (160M) as default I2S module clock source */ + i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK); + return I2S_LL_BASE_CLK; +#else + if (use_apll) { + ESP_LOGW(TAG, "APLL not supported on current chip, use I2S_CLK_D2CLK as default clock source"); + } + /* Set I2S_D2CLK (160M) as I2S module clock source */ + i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK); + return I2S_LL_BASE_CLK; +#endif +} + +#if SOC_I2S_SUPPORTS_ADC_DAC +/** + * @brief I2S calculate clock for built-in ADC/DAC mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_adc_dac_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_ARG, TAG, "current mode is not built-in ADC/DAC"); + + /* Set I2S module clock */ + clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk); + /* Set I2S bit clock default division */ + clk_cfg->bclk_div = I2S_LL_AD_BCK_FACTOR; + /* Set I2S bit clock */ + clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_AD_BCK_FACTOR * 2; + /* Get I2S master clock, mclk = bclk * bclk_div */ + clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div; + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; + + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module get clock failed"); + ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + + return ESP_OK; +} #endif // SOC_I2S_SUPPORTS_ADC_DAC - if ( p_i2s[i2s_num]->mode & I2S_MODE_PDM) { #if SOC_I2S_SUPPORTS_PDM_TX - if ( p_i2s[i2s_num]->mode & I2S_MODE_TX) { - int fp = i2s_hal_get_tx_pdm_fp(&(p_i2s[i2s_num]->hal)); - int fs = i2s_hal_get_tx_pdm_fs(&(p_i2s[i2s_num]->hal)); - _fbck = rate * I2S_LL_PDM_BCK_FACTOR * fp / fs; - } -#endif //SOC_I2S_SUPPORTS_PDM_TX -#if SOC_I2S_SUPPORTS_PDM_RX - if ( p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_pdm_dsr_t dsr; - i2s_hal_get_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), &dsr); - _fbck = rate * I2S_LL_PDM_BCK_FACTOR * (dsr == I2S_PDM_DSR_16S ? 2 : 1); - } -#endif // SOC_I2S_SUPPORTS_PDM_RX - _bck_div = 8; - } +/** + * @brief I2S calculate clock for PDM tx mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_pdm_tx_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode == I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); + + /* Set I2S module clock */ + clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk); + /* Set I2S bit clock default division */ + clk_cfg->bclk_div = 8; + + int fp = i2s_hal_get_tx_pdm_fp(&(p_i2s[i2s_num]->hal)); + int fs = i2s_hal_get_tx_pdm_fs(&(p_i2s[i2s_num]->hal)); + /* Set I2S bit clock */ + clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_PDM_BCK_FACTOR * fp / fs; + /* Get I2S master clock, mclk = bclk * bclk_div */ + clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div; + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; + + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module clock is 0"); + ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + + return ESP_OK; +} +#endif // SOC_I2S_SUPPORTS_PDM_TX + +#if SOC_I2S_SUPPORTS_PDM_RX +/** + * @brief I2S calculate clock for PDM rx mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_pdm_rx_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode == I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); + + /* Set I2S module clock */ + clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk); + /* Set I2S bit clock default division */ + clk_cfg->bclk_div = 8; + + i2s_pdm_dsr_t dsr; + i2s_hal_get_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), &dsr); + /* Set I2S bit clock */ + clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_PDM_BCK_FACTOR * (dsr == I2S_PDM_DSR_16S ? 2 : 1); + /* Get I2S master clock, mclk = bclk * bclk_div */ + clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div; + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; + + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module clock is 0"); + ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + + return ESP_OK; +} +#endif // SOC_I2S_SUPPORTS_PDM_RX + +/** + * @brief I2S calculate clock for common mode (philip, MSB, PCM) + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_common_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); + + /* Temp value for simplification */ + uint32_t rate = p_i2s[i2s_num]->hal_cfg.sample_rate; + uint32_t chan_num = p_i2s[i2s_num]->hal_cfg.total_chan; + uint32_t chan_bit = p_i2s[i2s_num]->hal_cfg.chan_bits; + i2s_mclk_multiple_t multi = p_i2s[i2s_num]->mclk_multiple ? p_i2s[i2s_num]->mclk_multiple : I2S_MCLK_MULTIPLE_256; + + /* Set I2S module clock */ + clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk); + /* Set I2S bit clock */ + clk_cfg->bclk = rate * chan_num * chan_bit; + /* Set I2S bit clock division according to the sample rate and multiple of mclk */ + clk_cfg->bclk_div = rate * multi / clk_cfg->bclk; + /* Get I2S master clock, mclk = bclk * bclk_div */ + clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div; + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; + + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module clock is 0"); + ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); -#if SOC_I2S_SUPPORTS_APLL - int sdm0 = 0; - int sdm1 = 0; - int sdm2 = 0; - int odir = 0; - //If APLL is specified, try to calculate in APLL - if (p_i2s[i2s_num]->use_apll && i2s_apll_calculate_fi2s(p_i2s[i2s_num]->fixed_mclk, channel_bit, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) { - _sclk = p_i2s[i2s_num]->fixed_mclk; - clk_src = I2S_CLK_APLL; - ESP_LOGD(TAG, "sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); - rtc_clk_apll_enable(1, sdm0, sdm1, sdm2, odir); - } -#endif // SOC_I2S_SUPPORTS_APLL - if ((_fbck * _bck_div) > _sclk) { - ESP_LOGE(TAG, "sample rate is too large\r\n"); - return ESP_ERR_INVALID_ARG; - } - i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), clk_src); - *sclk = _sclk; - *fbck = _fbck; - *bck_div = _bck_div; return ESP_OK; } -/************************************************************** - * I2S configuration * - * - i2s_get_active_chan_num * - * - i2s_set_dac_mode * - * - _i2s_adc_mode_recover * - * - i2s_set_adc_mode * - * - i2s_adc_enable * - * - i2s_adc_disable * - * - i2s_set_sample_rates * - * - i2s_pcm_config * - * - i2s_set_pdm_rx_down_sample * - * - i2s_set_pdm_tx_up_sample * - * - i2s_check_cfg_static * - * - i2s_param_config * - * - i2s_set_clk * - * - i2s_set_mode * - **************************************************************/ +/** + * @brief I2S calculate clocks according to the selected I2S mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Claculate clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_clock(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ +#if SOC_I2S_SUPPORTS_ADC_DAC + if (p_i2s[i2s_num]->hal_cfg.mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { + ESP_RETURN_ON_ERROR(i2s_calculate_adc_dac_clock(i2s_num, clk_cfg), TAG, "ADC/DAC clock calculate failed"); + return ESP_OK; + } +#endif +#if SOC_I2S_SUPPORTS_PDM_TX + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM && p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + ESP_RETURN_ON_ERROR(i2s_calculate_pdm_tx_clock(i2s_num, clk_cfg), TAG, "PDM TX clock calculate failed"); + return ESP_OK; + } +#endif +#if SOC_I2S_SUPPORTS_PDM_RX + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM && p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + ESP_RETURN_ON_ERROR(i2s_calculate_pdm_rx_clock(i2s_num, clk_cfg), TAG, "PDM RX clock calculate failed"); + return ESP_OK; + } +#endif + ESP_RETURN_ON_ERROR(i2s_calculate_common_clock(i2s_num, clk_cfg), TAG, "Common clock calculate failed"); + return ESP_OK; +} -static uint32_t i2s_get_active_chan_num(i2s_hal_config_t *hal_cfg) +/*------------------------------------------------------------- + I2S configuration + ------------------------------------------------------------- + - [helper] i2s_get_max_channel_num + - [helper] i2s_get_active_channel_num + - [helper] i2s_set_dac_mode + - [helper] _i2s_adc_mode_recover + - [main] i2s_set_adc_mode + - [main] i2s_adc_enable + - [main] i2s_adc_disable + - [helper] i2s_set_sample_rates + - [main] i2s_pcm_config + - [helper] i2s_set_pdm_rx_down_sample + - [helper] i2s_set_pdm_tx_up_sample + - [helper] i2s_check_cfg_validity + - [helper] i2s_tx_set_clk_and_channel + - [helper] i2s_rx_set_clk_and_channel + - [main] i2s_get_clk + - [main] i2s_set_clk + -------------------------------------------------------------*/ +#if SOC_I2S_SUPPORTS_TDM +/** + * @brief Get max actived channel number + * + * @param chan_mask I2S channel mask that indicates which channels are actived + * @return + * - max actived channel number + */ +static uint32_t i2s_get_max_channel_num(i2s_channel_t chan_mask) +{ + uint32_t max_chan = 0; + uint32_t channel = chan_mask & 0xFFFF; + for (int i = 0; channel && i < 16; i++, channel >>= 1) { + if (chan_mask & 0x01) { + max_chan = i + 1; + } + } + return max_chan; +} +#endif + +/** + * @brief Get active channel number according to channel format + * @note In 'I2S_CHANNEL_FMT_MULTIPLE' format, this function will check + * 'total_chan' and fix it if it is not correct. + * + * @param hal_cfg [input/output] I2S hal configuration structer + * @return + * - active channel number + */ +static uint32_t i2s_get_active_channel_num(const i2s_hal_config_t *hal_cfg) { switch (hal_cfg->chan_fmt) { case I2S_CHANNEL_FMT_RIGHT_LEFT: //fall through @@ -843,18 +1229,12 @@ static uint32_t i2s_get_active_chan_num(i2s_hal_config_t *hal_cfg) #if SOC_I2S_SUPPORTS_TDM case I2S_CHANNEL_FMT_MULTIPLE: { uint32_t num = 0; - uint32_t max_chan = 0; - uint32_t chan_mask = hal_cfg->chan_mask; - + uint32_t chan_mask = hal_cfg->chan_mask & 0xFFFF; for (int i = 0; chan_mask && i < 16; i++, chan_mask >>= 1) { - if ((chan_mask & 0x01) == 1) { + if (chan_mask & 0x01) { num++; - max_chan = i + 1; } } - if (max_chan > hal_cfg->total_chan) { - hal_cfg->total_chan = max_chan; - } return num; } #endif @@ -864,6 +1244,14 @@ static uint32_t i2s_get_active_chan_num(i2s_hal_config_t *hal_cfg) } #if SOC_I2S_SUPPORTS_ADC_DAC +/** + * @brief I2S set built-in DAC mode + * + * @param dac_mode DAC mode + * @return + * - ESP_OK Set DAC success + * - ESP_ERR_INVALID_ARG Wrong DAC mode + */ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) { ESP_RETURN_ON_FALSE((dac_mode < I2S_DAC_CHANNEL_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s dac mode error"); @@ -886,12 +1274,28 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) return ESP_OK; } +/** + * @brief ADC mode recover + * + * @return + * - ESP_OK ADC Recover success + * - ESP_ERR_INVALID_ARG ADC not initialized yet + */ static esp_err_t _i2s_adc_mode_recover(void) { ESP_RETURN_ON_FALSE(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), ESP_ERR_INVALID_ARG, TAG, "i2s ADC recover error, not initialized..."); return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel); } +/** + * @brief I2S set adc mode + * + * @param adc_unit ADC unit number + * @param adc_channel ADC channel + * @return + * - ESP_OK ADC Recover success + * - ESP_ERR_INVALID_ARG ADC not initialized yet + */ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel) { ESP_RETURN_ON_FALSE((adc_unit < ADC_UNIT_2), ESP_ERR_INVALID_ARG, TAG, "i2s ADC unit error, only support ADC1 for now"); @@ -901,23 +1305,41 @@ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel) return adc_i2s_mode_init(adc_unit, adc_channel); } +/** + * @brief I2S enable ADC mode + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Enable ADC success + * - ESP_ERR_INVALID_ARG Invalid argument + * - ESP_ERR_INVALID_STATE Current I2S mode is not built-in ADC + */ esp_err_t i2s_adc_enable(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_STATE, TAG, "Not initialized yet"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled"); adc1_dma_mode_acquire(); _i2s_adc_mode_recover(); i2s_rx_reset(i2s_num); - return i2s_set_clk(i2s_num, p_i2s[i2s_num]->sample_rate, p_i2s[i2s_num]->bits_per_sample, p_i2s[i2s_num]->channel_num); + return i2s_set_clk(i2s_num, p_i2s[i2s_num]->hal_cfg.sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); } +/** + * @brief I2S disable ADC + * + * @param i2s_num I2S device number + * @return + * - ESP_OK I2S ADC mode successfully disabled + * - ESP_ERR_INVALID_ARG Invalid argument + * - ESP_ERR_INVALID_STATE Current I2S mode is not built-in ADC + */ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_STATE, TAG, "Not initialized yet"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled"); i2s_hal_stop_rx(&(p_i2s[i2s_num]->hal)); adc1_lock_release(); @@ -925,25 +1347,47 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) } #endif - +/** + * @brief Set sample rate used for I2S RX and TX. + * @note The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample). + * `bit_clock = rate * (number of channels) * bits_per_sample` + * + * @param i2s_num I2S device number + * @param rate I2S sample rate (ex: 8000, 44100...) + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->bytes_per_sample > 0), ESP_ERR_INVALID_ARG, TAG, "bits_per_sample not set"); - return i2s_set_clk(i2s_num, rate, p_i2s[i2s_num]->bits_per_sample, p_i2s[i2s_num]->channel_num); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.sample_bits > 0), ESP_ERR_INVALID_ARG, TAG, "sample bits not set"); + return i2s_set_clk(i2s_num, rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); } #if SOC_I2S_SUPPORTS_PCM +/** + * @brief Configure I2S a/u-law decompress or compress + * @note This function should be called after i2s driver installed + * Only take effecttive when the i2s 'communication_format' is set to 'I2S_COMM_FORMAT_STAND_PCM_SHORT' or 'I2S_COMM_FORMAT_STAND_PCM_LONG' + * + * @param i2s_num I2S_NUM_0 + * @param pcm_cfg Including mode selection and a/u-law decompress or compress configuration paramater + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg) { ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->communication_format & I2S_COMM_FORMAT_STAND_PCM_SHORT), + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.comm_fmt & I2S_COMM_FORMAT_STAND_PCM_SHORT), ESP_ERR_INVALID_ARG, TAG, "i2s communication mode is not PCM mode"); i2s_stop(i2s_num); I2S_ENTER_CRITICAL(i2s_num); - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { i2s_hal_tx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg->pcm_type); - } else if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { + } else if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { i2s_hal_rx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg->pcm_type); } I2S_EXIT_CRITICAL(i2s_num); @@ -953,198 +1397,282 @@ esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg) #endif #if SOC_I2S_SUPPORTS_PDM_RX +/** + * @brief Set PDM mode down-sample rate + * In PDM RX mode, there would be 2 rounds of downsample process in hardware. + * In the first downsample process, the sampling number can be 16 or 8. + * In the second downsample process, the sampling number is fixed as 8. + * So the clock frequency in PDM RX mode would be (fpcm * 64) or (fpcm * 128) accordingly. + * @note After calling this function, it would call i2s_set_clk inside to update the clock frequency. + * Please call this function after I2S driver has been initialized. + * + * @param i2s_num I2S device number + * @param downsample i2s RX down sample rate for PDM mode. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t downsample) { ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); i2s_stop(i2s_num); i2s_hal_set_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), downsample); // i2s will start in 'i2s_set_clk' - return i2s_set_clk(i2s_num, p_i2s[i2s_num]->sample_rate, p_i2s[i2s_num]->bits_per_sample, p_i2s[i2s_num]->channel_num); + return i2s_set_clk(i2s_num, p_i2s[i2s_num]->hal_cfg.sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); } #endif #if SOC_I2S_SUPPORTS_PDM_TX +/** + * @brief Set TX PDM mode up-sample rate + * @note If you have set PDM mode while calling 'i2s_driver_install', + * default PDM TX upsample parameters have already been set, + * no need to call this function again if you don't have to change the default configuration + * + * @param i2s_num I2S device number + * @param upsample_cfg Set I2S PDM up-sample rate configuration + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, const i2s_pdm_tx_upsample_cfg_t *upsample_cfg) { ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); i2s_stop(i2s_num); i2s_hal_set_tx_pdm_fpfs(&(p_i2s[i2s_num]->hal), upsample_cfg->fp, upsample_cfg->fs); // i2s will start in 'i2s_set_clk' - return i2s_set_clk(i2s_num, upsample_cfg->sample_rate, p_i2s[i2s_num]->bits_per_sample, p_i2s[i2s_num]->channel_num); + return i2s_set_clk(i2s_num, upsample_cfg->sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); } #endif -static esp_err_t i2s_check_cfg_static(i2s_port_t i2s_num) +/** + * @brief I2S check the validity of configuration + * + * @param i2s_num I2S device number + * @param cfg I2S HAL configuration + * @return + * - ESP_OK I2S configuration is valid + * - ESP_ERR_INVALID_ARG I2S configuration is invalid + */ +static esp_err_t i2s_check_cfg_validity(i2s_port_t i2s_num, i2s_hal_config_t *cfg) { - i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg; -#if SOC_I2S_SUPPORTS_ADC_DAC - //We only check if the I2S number is invalid when set to build in ADC and DAC mode. - ESP_RETURN_ON_FALSE(!((cfg->mode & I2S_MODE_ADC_BUILT_IN) && (i2s_num != I2S_NUM_0)), ESP_ERR_INVALID_ARG, TAG, "I2S ADC built-in only support on I2S0"); - ESP_RETURN_ON_FALSE(!((cfg->mode & I2S_MODE_DAC_BUILT_IN) && (i2s_num != I2S_NUM_0)), ESP_ERR_INVALID_ARG, TAG, "I2S DAC built-in only support on I2S0"); - return ESP_OK; -#endif - //We only check if the I2S number is invalid when set to PDM mode. - ESP_RETURN_ON_FALSE(!((cfg->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), ESP_ERR_INVALID_ARG, TAG, "I2S DAC PDM only support on I2S0"); - return ESP_OK; +#if SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX + /* Check PDM mode */ + if (cfg->mode & I2S_MODE_PDM) { + ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode only support on I2S0"); +#if !SOC_I2S_SUPPORTS_PDM_TX + ESP_RETURN_ON_FALSE(cfg->mode & I2S_MODE_TX, ESP_ERR_INVALID_ARG, TAG, "PDM does not support TX on this chip"); +#endif // SOC_I2S_SUPPORTS_PDM_TX +#if !SOC_I2S_SUPPORTS_PDM_RX + ESP_RETURN_ON_FALSE(cfg->mode & I2S_MODE_RX, ESP_ERR_INVALID_ARG, TAG, "PDM does not support RX on this chip"); +#endif // SOC_I2S_SUPPORTS_PDM_RX + } +#else + ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode not supported on current chip"); +#endif // SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX +#if SOC_I2S_SUPPORTS_ADC_DAC + /* Check built-in ADC/DAC mode */ + if (cfg->mode & (I2S_MODE_ADC_BUILT_IN | I2S_MODE_DAC_BUILT_IN)) { + ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S built-in ADC/DAC only support on I2S0"); + } +#else + /* Check the transmit/receive mode */ + ESP_RETURN_ON_FALSE((cfg->mode & I2S_MODE_TX) || (cfg->mode & I2S_MODE_RX), ESP_ERR_INVALID_ARG, TAG, "I2S no TX/RX mode selected"); + /* Check communication format */ ESP_RETURN_ON_FALSE(cfg->comm_fmt && (cfg->comm_fmt < I2S_COMM_FORMAT_STAND_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid communication formats"); - ESP_RETURN_ON_FALSE(!((cfg->comm_fmt & I2S_COMM_FORMAT_STAND_MSB) && (cfg->comm_fmt & I2S_COMM_FORMAT_STAND_PCM_LONG)), ESP_ERR_INVALID_ARG, TAG, "multiple communication formats specified"); +#endif // SOC_I2S_SUPPORTS_ADC_DAC + return ESP_OK; } -static esp_err_t i2s_param_config(i2s_port_t i2s_num) +static void i2s_tx_set_clk_and_channel(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + i2s_hal_tx_clock_config(&(p_i2s[i2s_num]->hal), clk_cfg); + i2s_hal_set_tx_sample_bit(&(p_i2s[i2s_num]->hal), p_i2s[i2s_num]->hal_cfg.chan_bits, p_i2s[i2s_num]->hal_cfg.sample_bits); + i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); +} + +static void i2s_rx_set_clk_and_channel(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + i2s_hal_rx_clock_config(&(p_i2s[i2s_num]->hal), clk_cfg); + i2s_hal_set_rx_sample_bit(&(p_i2s[i2s_num]->hal), p_i2s[i2s_num]->hal_cfg.chan_bits, p_i2s[i2s_num]->hal_cfg.sample_bits); + i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); +} + +/** + * @brief Get clock set on particular port number. + * + * @param i2s_num I2S device number + * @return + * - sample rate + */ +float i2s_get_clk(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - ESP_RETURN_ON_FALSE((i2s_check_cfg_static(i2s_num) == ESP_OK), ESP_ERR_INVALID_ARG, TAG, "param check error"); - - i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg; - p_i2s[i2s_num]->communication_format = cfg->comm_fmt; -#if SOC_I2S_SUPPORTS_ADC_DAC - if ((cfg->mode & I2S_MODE_DAC_BUILT_IN) || (cfg->mode & I2S_MODE_ADC_BUILT_IN)) { - if (cfg->mode & I2S_MODE_DAC_BUILT_IN) { - i2s_hal_enable_builtin_dac(&(p_i2s[i2s_num]->hal)); - } - if (cfg->mode & I2S_MODE_ADC_BUILT_IN) { - //in ADC built-in mode, we need to call i2s_set_adc_mode to - //initialize the specific ADC channel. - //in the current stage, we only support ADC1 and single channel mode. - //In default data mode, the ADC data is in 12-bit resolution mode. - adc_power_acquire(); - i2s_hal_enable_builtin_adc(&(p_i2s[i2s_num]->hal)); - } - } else { - i2s_hal_disable_builtin_dac(&(p_i2s[i2s_num]->hal)); - i2s_hal_disable_builtin_adc(&(p_i2s[i2s_num]->hal)); -#endif - // configure I2S data port interface. - i2s_hal_config_param(&(p_i2s[i2s_num]->hal), cfg); -#if SOC_I2S_SUPPORTS_ADC_DAC - } -#endif - if ((p_i2s[i2s_num]->mode & I2S_MODE_RX) && (p_i2s[i2s_num]->mode & I2S_MODE_TX)) { - i2s_hal_enable_sig_loopback(&(p_i2s[i2s_num]->hal)); - if (p_i2s[i2s_num]->mode & I2S_MODE_MASTER) { - i2s_hal_enable_master_fd_mode(&(p_i2s[i2s_num]->hal)); - } else { - i2s_hal_enable_slave_fd_mode(&(p_i2s[i2s_num]->hal)); - } - } - return ESP_OK; + return (float)p_i2s[i2s_num]->hal_cfg.sample_rate; } +/** + * @brief Set clock & bit width used for I2S RX and TX. + * Similar to i2s_set_sample_rates(), but also sets bit width. + * + * 1. stop i2s + * 2. calculate mclk, bck, bck_factor + * 3. set clock configurations + * 4. realloc dma buffer if DMA buffer size changed + * 5. start i2s + * + * @param i2s_num I2S device number + * @param rate I2S sample rate (ex: 8000, 44100...) + * @param bits_cfg I2S bits configuration + * the low 16 bits is for data bits per sample in one channel (see 'i2s_bits_per_sample_t') + * the high 16 bits is for total bits in one channel (see 'i2s_bits_per_chan_t') + * high 16bits =0 means same as the bits per sample. + * @param ch I2S channel, (I2S_CHANNEL_MONO, I2S_CHANNEL_STEREO or specific channel in TDM mode) + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_channel_t ch) { + esp_err_t ret = ESP_OK; + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_ARG, TAG, "Not initialized yet"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_ARG, TAG, "I2S%d has not installed yet", i2s_num); i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg; - int data_bits = 0; - int chan_bits = 0; - int active_chan_num = 0; - int chan_num = 0; - - cfg->ch = ch; - cfg->sample_rate = rate; - cfg->bits_cfg.val = bits_cfg; - - cfg->bits_cfg.chan_bits = cfg->bits_cfg.chan_bits < cfg->bits_cfg.sample_bits ? - cfg->bits_cfg.sample_bits : cfg->bits_cfg.chan_bits; - chan_bits = cfg->bits_cfg.chan_bits; - data_bits = cfg->bits_cfg.sample_bits; - + /* If not the first time, update configuration */ + if (p_i2s[i2s_num]->last_buf_size) { + cfg->sample_rate = rate; + cfg->sample_bits = bits_cfg & 0xFFFF; + cfg->chan_bits = (bits_cfg >> 16) ? (bits_cfg >> 16) : cfg->sample_bits; #if SOC_I2S_SUPPORTS_TDM - cfg->chan_mask = ch & 0xFFFF; - active_chan_num = i2s_get_active_chan_num(cfg); - chan_num = cfg->total_chan; -#else - active_chan_num = i2s_get_active_chan_num(cfg); - chan_num = ch == I2S_CHANNEL_MONO ? 2 : active_chan_num; + cfg->chan_mask = ch; + cfg->active_chan = i2s_get_active_channel_num(cfg); + uint32_t max_channel = i2s_get_max_channel_num(cfg->chan_mask); + /* If total channel is smaller than max actived channel number then set it to the max active channel number */ + cfg->total_chan = p_i2s[i2s_num]->hal_cfg.total_chan < max_channel ? max_channel : p_i2s[i2s_num]->hal_cfg.total_chan; +#endif +#if !SOC_I2S_SUPPORTS_TDM + cfg->active_chan = i2s_get_active_channel_num(cfg); + cfg->total_chan = ch == I2S_CHANNEL_MONO ? 2 : cfg->active_chan; #endif - ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - - if ((data_bits % 8 != 0) || (data_bits > I2S_BITS_PER_SAMPLE_32BIT)) { - ESP_LOGE(TAG, "Invalid bits per sample"); - return ESP_ERR_INVALID_ARG; } - //Stop I2S + uint32_t data_bits = cfg->sample_bits; + + /* Check the validity of sample bits */ + ESP_RETURN_ON_FALSE((data_bits % 8 == 0), ESP_ERR_INVALID_ARG, TAG, "Invalid bits per sample"); + ESP_RETURN_ON_FALSE((data_bits <= I2S_BITS_PER_SAMPLE_32BIT), ESP_ERR_INVALID_ARG, TAG, "Invalid bits per sample"); + + /* Stop I2S */ i2s_stop(i2s_num); - // wait all on-going writing finish - if ((p_i2s[i2s_num]->mode & I2S_MODE_TX) && p_i2s[i2s_num]->tx) { + + i2s_hal_clock_cfg_t clk_cfg; + i2s_hal_clock_cfg_t *p_clk_cfg = NULL; + + /* If uising chips like ESP32 and ESP32S2 + * Only need to calculate clock for MASTER mode + * Because BCK and WS clock are provide by external codec in SLAVE mode + * In SLAVE mode, the mclk_div and bck_div will be set to 1 + * So that we can get a high module clock which could detect the edges of externel clock more accurately + * Otherwise the data we receive or send would get a large latency and go wrong due to the slow module clock + * But ESP32 and ESP32S2 have to calculate and set the clock to guarantee the function in slave mode + * Here use 'SOC_I2S_SUPPORTS_TDM' to differentialize ESP32 and ESP32S2 with other chips + */ +#if SOC_I2S_SUPPORTS_TDM + if (cfg->mode & I2S_MODE_MASTER) { +#endif + p_clk_cfg = &clk_cfg; + /* To get sclk, mclk, mclk_div bclk and bclk_div */ + i2s_calculate_clock(i2s_num, p_clk_cfg); +#if SOC_I2S_SUPPORTS_TDM + } +#endif + + uint32_t buf_size = i2s_get_buf_size(i2s_num); + bool need_realloc = p_i2s[i2s_num]->last_buf_size != buf_size; + p_i2s[i2s_num]->last_buf_size = buf_size; + + /* TX mode clock reset */ + if (cfg->mode & I2S_MODE_TX) { + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->tx, ESP_ERR_INVALID_ARG, TAG, "I2S TX DMA object has not initialized yet"); + /* Waiting for transmit finish */ xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); - } - if ((p_i2s[i2s_num]->mode & I2S_MODE_RX) && p_i2s[i2s_num]->rx) { - xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); - } - //malloc DMA buffer - if (i2s_alloc_dma_buffer(i2s_num, data_bits, active_chan_num) != ESP_OK ) { - return ESP_ERR_NO_MEM; - } - - uint32_t i2s_clk = 0; // I2S source clock - uint32_t i2s_bck = 0; // I2S back clock - uint32_t bck_div = 0; // I2S bck div - //calculate bck_div, f_bck and select source clock - if (i2s_fbclk_cal(i2s_num, rate, chan_num, chan_bits, &i2s_clk, &i2s_bck, &bck_div) != ESP_OK) { - return ESP_FAIL; - } - //configure i2s clock - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - i2s_hal_tx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div); - i2s_hal_set_tx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits); - // wait all writing on-going finish - if (p_i2s[i2s_num]->tx) { - xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + i2s_tx_set_clk_and_channel(i2s_num, p_clk_cfg); + /* If buffer size changed, the DMA buffer need realloc */ + if (need_realloc) { + p_i2s[i2s_num]->tx->buf_size = buf_size; + ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->tx); } - i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); - } - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_hal_rx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div); - i2s_hal_set_rx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits); - // wait all writing on-going finish - if (p_i2s[i2s_num]->rx) { - xSemaphoreGive(p_i2s[i2s_num]->rx->mux); - } - i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); - } - // Reset message queue to avoid receiving unavailable values because the old dma queque has been destroyed - if (p_i2s[i2s_num]->tx) { + /* Reset the queue to avoid receive invalid data */ xQueueReset(p_i2s[i2s_num]->tx->queue); + xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d tx DMA buffer malloc failed", i2s_num); } - if (p_i2s[i2s_num]->rx) { + /* RX mode clock reset */ + if (cfg->mode & I2S_MODE_RX) { + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->rx, ESP_ERR_INVALID_ARG, TAG, "I2S TX DMA object has not initialized yet"); + /* Waiting for receive finish */ + xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + i2s_rx_set_clk_and_channel(i2s_num, p_clk_cfg); + /* If buffer size changed, the DMA buffer need realloc */ + if (need_realloc) { + p_i2s[i2s_num]->rx->buf_size = buf_size; + ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->rx); + /* Reset the end-of-frame number */ + i2s_hal_set_rx_eof_num(&(p_i2s[i2s_num]->hal), buf_size); + } + /* Reset the queue to avoid receive invalid data */ xQueueReset(p_i2s[i2s_num]->rx->queue); + xSemaphoreGive(p_i2s[i2s_num]->rx->mux); + ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d rx DMA buffer malloc failed", i2s_num); } - //I2S start + /* I2S start */ i2s_start(i2s_num); - p_i2s[i2s_num]->sample_rate = rate; + return ESP_OK; } - - -/************************************************************** - * I2S driver operation * - * - i2s_start * - * - i2s_stop * - * - i2s_driver_install * - * - i2s_write * - * - i2s_write_expand * - * - i2s_read * - **************************************************************/ - +/*------------------------------------------------------------- + I2S driver operation + ------------------------------------------------------------- + - [main] i2s_start + - [main] i2s_stop + - [helper] i2s_driver_init + - [helper] i2s_dma_object_init + - [main] i2s_driver_install + - [main] i2s_driver_uninstall + - [main] i2s_write + - [main] i2s_write_expand + - [main] i2s_read + -------------------------------------------------------------*/ +/** + * @brief Start I2S driver + * @note It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop(). + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_start(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); //start DMA link I2S_ENTER_CRITICAL(i2s_num); - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { i2s_tx_reset(i2s_num); i2s_tx_start(i2s_num); } - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { i2s_rx_reset(i2s_num); i2s_rx_start(i2s_num); } @@ -1155,6 +1683,17 @@ esp_err_t i2s_start(i2s_port_t i2s_num) return ESP_OK; } +/** + * @brief Stop I2S driver + * @note There is no need to call i2s_stop() before calling i2s_driver_uninstall(). + * Disables I2S TX/RX, until i2s_start() is called. + * + * @param i2s_num I2S device number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_stop(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); @@ -1162,10 +1701,10 @@ esp_err_t i2s_stop(i2s_port_t i2s_num) #if !SOC_GDMA_SUPPORTED esp_intr_disable(p_i2s[i2s_num]->i2s_isr_handle); #endif - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { i2s_tx_stop(i2s_num); } - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { i2s_rx_stop(i2s_num); } #if !SOC_GDMA_SUPPORTED @@ -1175,16 +1714,135 @@ esp_err_t i2s_stop(i2s_port_t i2s_num) return ESP_OK; } +/** + * @brief Initialize I2S driver configurations + * + * @param i2s_num I2S device number + * @param i2s_config I2S configurations - see i2s_config_t struct + * @return + * - ESP_OK I2S initialize success + * - ESP_ERR_INVALID_ARG No channel enabled in multiple channel format + */ +static esp_err_t i2s_driver_init(i2s_port_t i2s_num, const i2s_config_t *i2s_config) +{ + ESP_RETURN_ON_FALSE(i2s_config, ESP_ERR_INVALID_ARG, TAG, "The pointer of I2S configuration structure is NULL"); + + /* I2S driver configuration assignment */ + p_i2s[i2s_num]->i2s_num = i2s_num; + p_i2s[i2s_num]->dma_buf_count = i2s_config->dma_buf_count; + p_i2s[i2s_num]->dma_buf_len = i2s_config->dma_buf_len; + p_i2s[i2s_num]->last_buf_size = 0; + p_i2s[i2s_num]->intr_alloc_flags = i2s_config->intr_alloc_flags; + p_i2s[i2s_num]->use_apll = i2s_config->use_apll; + p_i2s[i2s_num]->fixed_mclk = i2s_config->fixed_mclk; + p_i2s[i2s_num]->mclk_multiple = i2s_config->mclk_multiple; + p_i2s[i2s_num]->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear; + + /* I2S HAL configuration assignment */ + p_i2s[i2s_num]->hal_cfg.mode = i2s_config->mode; + p_i2s[i2s_num]->hal_cfg.sample_rate = i2s_config->sample_rate; + p_i2s[i2s_num]->hal_cfg.comm_fmt = i2s_config->communication_format; + p_i2s[i2s_num]->hal_cfg.chan_fmt = i2s_config->channel_format; + p_i2s[i2s_num]->hal_cfg.sample_bits = i2s_config->bits_per_sample; + p_i2s[i2s_num]->hal_cfg.chan_bits = (uint32_t)i2s_config->bits_per_chan < (uint32_t)i2s_config->bits_per_sample ? + (uint32_t)i2s_config->bits_per_sample : (uint32_t)i2s_config->bits_per_chan; + +#if SOC_I2S_SUPPORTS_TDM + /* I2S HAL TDM configuration assignment */ + p_i2s[i2s_num]->hal_cfg.left_align = i2s_config->left_align; + p_i2s[i2s_num]->hal_cfg.big_edin = i2s_config->big_edin; + p_i2s[i2s_num]->hal_cfg.bit_order_msb = i2s_config->bit_order_msb; + p_i2s[i2s_num]->hal_cfg.skip_msk = i2s_config->skip_msk; + + /* Set chan_mask according to channel format */ + switch (i2s_config->channel_format) { + case I2S_CHANNEL_FMT_RIGHT_LEFT: + case I2S_CHANNEL_FMT_ALL_RIGHT: + case I2S_CHANNEL_FMT_ALL_LEFT: + p_i2s[i2s_num]->hal_cfg.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1; + break; + case I2S_CHANNEL_FMT_ONLY_RIGHT: + p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->left_align ? I2S_TDM_ACTIVE_CH1 : I2S_TDM_ACTIVE_CH0; + break; + case I2S_CHANNEL_FMT_ONLY_LEFT: + p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->left_align ? I2S_TDM_ACTIVE_CH0 : I2S_TDM_ACTIVE_CH1; + break; + case I2S_CHANNEL_FMT_MULTIPLE: + ESP_RETURN_ON_FALSE(i2s_config->chan_mask, ESP_ERR_INVALID_ARG, TAG, "i2s all channel are disabled"); + p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->chan_mask; + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "wrong i2s channel format, going to uninstall i2s"); + } + + /* Calculate actived channel number in channel mask */ + p_i2s[i2s_num]->hal_cfg.active_chan = i2s_get_active_channel_num(&p_i2s[i2s_num]->hal_cfg); + /* Get the max actived channel number */ + uint32_t max_channel = i2s_get_max_channel_num(p_i2s[i2s_num]->hal_cfg.chan_mask); + /* If total channel is smaller than max actived channel number then set it to the max active channel number */ + p_i2s[i2s_num]->hal_cfg.total_chan = p_i2s[i2s_num]->hal_cfg.total_chan < max_channel ? max_channel : + p_i2s[i2s_num]->hal_cfg.total_chan; +#else + /* Calculate actived channel number in channel mask */ + p_i2s[i2s_num]->hal_cfg.active_chan = i2s_get_active_channel_num(&p_i2s[i2s_num]->hal_cfg); + /* Total channel number is equal to the actived channel number in non-TDM mode */ + p_i2s[i2s_num]->hal_cfg.total_chan = p_i2s[i2s_num]->hal_cfg.active_chan; +#endif + return ESP_OK; +} + +/** + * @brief Initialize I2S DMA object + * + * @param i2s_num I2S device number + * @return + * - ESP_OK DMA object initialize success + * - ESP_ERR_NO_MEM No memory for DMA object + */ +static esp_err_t i2s_dma_object_init(i2s_port_t i2s_num) +{ + uint32_t buf_size = i2s_get_buf_size(i2s_num); + /* Create DMA object */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + ESP_RETURN_ON_ERROR(i2s_create_dma_object(i2s_num, &p_i2s[i2s_num]->tx), TAG, "I2S TX DMA object create failed"); + p_i2s[i2s_num]->tx->buf_size = buf_size; + } + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + ESP_RETURN_ON_ERROR(i2s_create_dma_object(i2s_num, &p_i2s[i2s_num]->rx), TAG, "I2S RX DMA object create failed"); + p_i2s[i2s_num]->rx->buf_size = buf_size; + } + return ESP_OK; +} + +/** + * @brief Install and start I2S driver. + * @note This function must be called before any I2S driver read/write operations. + * + * + * @param i2s_num I2S device number + * @param i2s_config I2S configurations - see i2s_config_t struct + * @param queue_size I2S event queue size/depth. + * @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue) { - esp_err_t ret = ESP_FAIL; + esp_err_t ret = ESP_OK; i2s_obj_t *pre_alloc_i2s_obj = NULL; + + /* Step 1: Check the validity of input parameters */ + /* Check the validity of i2s device number */ ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - ESP_RETURN_ON_FALSE((i2s_config != NULL), ESP_ERR_INVALID_ARG, TAG, "I2S configuration must not NULL"); + ESP_RETURN_ON_FALSE(i2s_config, ESP_ERR_INVALID_ARG, TAG, "I2S configuration must not be NULL"); + /* Check the size of DMA buffer */ ESP_RETURN_ON_FALSE((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), ESP_ERR_INVALID_ARG, TAG, "I2S buffer count less than 128 and more than 2"); ESP_RETURN_ON_FALSE((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), ESP_ERR_INVALID_ARG, TAG, "I2S buffer length at most 1024 and more than 8"); - // alloc driver object and register to platform + /* Step 2: Allocate driver object and register to platform */ pre_alloc_i2s_obj = calloc(1, sizeof(i2s_obj_t)); ESP_RETURN_ON_FALSE(pre_alloc_i2s_obj, ESP_ERR_NO_MEM, TAG, "no mem for I2S driver"); ret = i2s_priv_register_object(pre_alloc_i2s_obj, i2s_num); @@ -1193,106 +1851,42 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, ESP_LOGE(TAG, "register I2S object to platform failed"); return ret; } - // initialize HAL layer - i2s_hal_init(&(pre_alloc_i2s_obj->hal), i2s_num); - // Set I2S HAL configurations - pre_alloc_i2s_obj->hal_cfg.mode = i2s_config->mode; - pre_alloc_i2s_obj->hal_cfg.sample_rate = i2s_config->sample_rate; - pre_alloc_i2s_obj->hal_cfg.comm_fmt = i2s_config->communication_format; - pre_alloc_i2s_obj->hal_cfg.chan_fmt = i2s_config->channel_format; - pre_alloc_i2s_obj->hal_cfg.bits_cfg.sample_bits = i2s_config->bits_per_sample; - pre_alloc_i2s_obj->hal_cfg.bits_cfg.chan_bits = i2s_config->bits_per_chan; -#if SOC_I2S_SUPPORTS_TDM - int active_chan = 0; - switch (i2s_config->channel_format) { - case I2S_CHANNEL_FMT_RIGHT_LEFT: - case I2S_CHANNEL_FMT_ALL_RIGHT: - case I2S_CHANNEL_FMT_ALL_LEFT: - pre_alloc_i2s_obj->hal_cfg.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1; - pre_alloc_i2s_obj->hal_cfg.total_chan = 2; - active_chan = 2; - break; - case I2S_CHANNEL_FMT_ONLY_RIGHT: - pre_alloc_i2s_obj->hal_cfg.chan_mask = i2s_config->left_align ? I2S_TDM_ACTIVE_CH1 : I2S_TDM_ACTIVE_CH0; - pre_alloc_i2s_obj->hal_cfg.total_chan = 1; - active_chan = 1; - break; - case I2S_CHANNEL_FMT_ONLY_LEFT: - pre_alloc_i2s_obj->hal_cfg.chan_mask = i2s_config->left_align ? I2S_TDM_ACTIVE_CH0 : I2S_TDM_ACTIVE_CH1; - pre_alloc_i2s_obj->hal_cfg.total_chan = 1; - active_chan = 1; - break; - case I2S_CHANNEL_FMT_MULTIPLE: - ESP_GOTO_ON_FALSE(i2s_config->chan_mask != 0, ESP_ERR_INVALID_ARG, err, TAG, "i2s all channel are disabled"); - pre_alloc_i2s_obj->hal_cfg.chan_mask = i2s_config->chan_mask; - i2s_get_active_chan_num(&pre_alloc_i2s_obj->hal_cfg); - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid I2S channel format:%d", i2s_config->channel_format); - } - pre_alloc_i2s_obj->hal_cfg.left_align = i2s_config->left_align; - pre_alloc_i2s_obj->hal_cfg.big_edin = i2s_config->big_edin; - pre_alloc_i2s_obj->hal_cfg.bit_order_msb = i2s_config->bit_order_msb; - pre_alloc_i2s_obj->hal_cfg.skip_msk = i2s_config->skip_msk; -#endif + /* Step 3: Initialize I2S object, assign configarations */ + ESP_GOTO_ON_ERROR(i2s_driver_init(i2s_num, i2s_config), err, TAG, "I2S init failed"); + /* Check the validity of I2S configuration */ + ESP_GOTO_ON_ERROR(i2s_check_cfg_validity(i2s_num, &(p_i2s[i2s_num]->hal_cfg)), err, TAG, "I2S configuration is invalid"); - // Set I2S driver configurations - pre_alloc_i2s_obj->i2s_num = i2s_num; - pre_alloc_i2s_obj->mode = i2s_config->mode; - pre_alloc_i2s_obj->channel_num = i2s_get_active_chan_num(&pre_alloc_i2s_obj->hal_cfg); - pre_alloc_i2s_obj->i2s_queue = i2s_queue; - pre_alloc_i2s_obj->bits_per_sample = 0; - pre_alloc_i2s_obj->bytes_per_sample = 0; // Not initialized yet - pre_alloc_i2s_obj->dma_buf_count = i2s_config->dma_buf_count; - pre_alloc_i2s_obj->dma_buf_len = i2s_config->dma_buf_len; - pre_alloc_i2s_obj->mclk_multiple = i2s_config->mclk_multiple; + /* Get device instance */ + i2s_hal_get_instance(&(p_i2s[i2s_num]->hal), i2s_num); #ifdef CONFIG_PM_ENABLE + esp_pm_lock_type_t pm_lock = ESP_PM_NO_LIGHT_SLEEP; #if SOC_I2S_SUPPORTS_APLL if (i2s_config->use_apll) { - ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &pre_alloc_i2s_obj->pm_lock); - } else + pm_lock = ESP_PM_NO_LIGHT_SLEEP; + } #endif // SOC_I2S_SUPPORTS_APLL - { - ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_driver", &pre_alloc_i2s_obj->pm_lock); - } - ESP_GOTO_ON_ERROR(ret, err, TAG, "create PM lock failed"); + ESP_GOTO_ON_ERROR(esp_pm_lock_create(pm_lock, 0, "i2s_driver", &p_i2s[i2s_num]->pm_lock), err, TAG, "I2S pm lock error"); #endif //CONFIG_PM_ENABLE -#if SOC_GDMA_SUPPORTED - ret = ESP_OK; - gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S}; -#if SOC_I2S_NUM > 1 - trig.instance_id = (i2s_num == I2S_NUM_0) ? SOC_GDMA_TRIG_PERIPH_I2S0 : SOC_GDMA_TRIG_PERIPH_I2S1; -#else - trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0; + + /* Step 4: Initialize I2S DMA interrupt and DMA object */ + ESP_GOTO_ON_ERROR(i2s_dma_intr_init(i2s_num), err, TAG, "I2S interrupt initailze failed"); + /* Initialize I2S DMA object */ + ESP_GOTO_ON_ERROR(i2s_dma_object_init(i2s_num), err, TAG, "I2S dma object create failed"); + +#if SOC_I2S_SUPPORTS_ADC_DAC + /* If using built-in ADC, we need to enable ADC power manerge*/ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) { + printf("ADC power on\n"); + adc_power_acquire(); + } #endif - gdma_channel_alloc_config_t dma_cfg = {.flags.reserve_sibling = 1}; - if (pre_alloc_i2s_obj->mode & I2S_MODE_RX) { - dma_cfg.direction = GDMA_CHANNEL_DIRECTION_RX; - ESP_GOTO_ON_ERROR(gdma_new_channel(&dma_cfg, &pre_alloc_i2s_obj->rx_dma_chan), err, TAG, "Register rx dma channel error"); - ESP_GOTO_ON_ERROR(gdma_connect(pre_alloc_i2s_obj->rx_dma_chan, trig), err, TAG, "Connect rx dma channel error"); - gdma_rx_event_callbacks_t cb = {.on_recv_eof = i2s_dma_rx_callback}; - gdma_register_rx_event_callbacks(pre_alloc_i2s_obj->rx_dma_chan, &cb, pre_alloc_i2s_obj); - } - if (pre_alloc_i2s_obj->mode & I2S_MODE_TX) { - dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX; - ESP_GOTO_ON_ERROR(gdma_new_channel(&dma_cfg, &pre_alloc_i2s_obj->tx_dma_chan), err, TAG, "Register tx dma channel error"); - ESP_GOTO_ON_ERROR(gdma_connect(pre_alloc_i2s_obj->tx_dma_chan, trig), err, TAG, "Connect tx dma channel error"); - gdma_tx_event_callbacks_t cb = {.on_trans_eof = i2s_dma_tx_callback}; - gdma_register_tx_event_callbacks(pre_alloc_i2s_obj->tx_dma_chan, &cb, pre_alloc_i2s_obj); - } -#else - //initial interrupt - ret = esp_intr_alloc(i2s_periph_signal[i2s_num].irq, i2s_config->intr_alloc_flags, i2s_intr_handler_default, pre_alloc_i2s_obj, &pre_alloc_i2s_obj->i2s_isr_handle); - ESP_GOTO_ON_ERROR(ret, err, TAG, "Register I2S Interrupt error"); -#endif // SOC_GDMA_SUPPORTED - i2s_stop(i2s_num); - pre_alloc_i2s_obj->use_apll = i2s_config->use_apll; - pre_alloc_i2s_obj->fixed_mclk = i2s_config->fixed_mclk; - pre_alloc_i2s_obj->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear; - ret = i2s_param_config(i2s_num); - ESP_GOTO_ON_ERROR(ret, err, TAG, "I2S param configure error"); + + /* Step 5: Initialize I2S configuration and set the configurations to register */ + i2s_hal_init(&(p_i2s[i2s_num]->hal), &p_i2s[i2s_num]->hal_cfg); + + /* Step 6: Initialise i2s event queue if user needs */ if (i2s_queue) { pre_alloc_i2s_obj->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); ESP_GOTO_ON_ERROR((pre_alloc_i2s_obj->i2s_queue != NULL), err, TAG, "I2S queue create failed"); @@ -1302,23 +1896,24 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, pre_alloc_i2s_obj->i2s_queue = NULL; } - //set clock and start -#if SOC_I2S_SUPPORTS_TDM - ret = i2s_set_clk(i2s_num, i2s_config->sample_rate, - pre_alloc_i2s_obj->hal_cfg.bits_cfg.val, - (i2s_channel_t)active_chan); -#else - ret = i2s_set_clk(i2s_num, i2s_config->sample_rate, - pre_alloc_i2s_obj->hal_cfg.bits_cfg.val, - I2S_CHANNEL_STEREO); -#endif - ESP_GOTO_ON_ERROR(ret, err, TAG, "I2S set clock failed"); - return ret; + /* Step 7: Set I2S clocks and start. No need to give parameters since configurations has been set in 'i2s_driver_init' */ + ESP_GOTO_ON_ERROR(i2s_set_clk(i2s_num, 0, 0, 0), err, TAG, "I2S set clock failed"); + return ESP_OK; + err: + /* I2S install failed, prepare to uninstall */ i2s_driver_uninstall(i2s_num); return ret; } +/** + * @brief Uninstall I2S driver. + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE(i2s_num < I2S_NUM_MAX, ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); @@ -1342,14 +1937,9 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) esp_intr_free(p_i2s[i2s_num]->i2s_isr_handle); } #endif - if (p_i2s[i2s_num]->tx != NULL && p_i2s[i2s_num]->mode & I2S_MODE_TX) { - i2s_destroy_dma_queue(i2s_num, p_i2s[i2s_num]->tx); - p_i2s[i2s_num]->tx = NULL; - } - if (p_i2s[i2s_num]->rx != NULL && p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_destroy_dma_queue(i2s_num, p_i2s[i2s_num]->rx); - p_i2s[i2s_num]->rx = NULL; - } + /* Destroy dma object if exist */ + i2s_destroy_dma_object(i2s_num, &p_i2s[i2s_num]->tx); + i2s_destroy_dma_object(i2s_num, &p_i2s[i2s_num]->rx); if (p_i2s[i2s_num]->i2s_queue) { vQueueDelete(p_i2s[i2s_num]->i2s_queue); @@ -1367,6 +1957,7 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) #ifdef CONFIG_PM_ENABLE if (p_i2s[i2s_num]->pm_lock) { esp_pm_lock_delete(p_i2s[i2s_num]->pm_lock); + p_i2s[i2s_num]->pm_lock = NULL; } #endif i2s_priv_deregister_object(i2s_num); @@ -1374,13 +1965,31 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) return ESP_OK; } +/** + * @brief Write data to I2S DMA transmit buffer. + * @note Many ticks pass without space becoming available in the DMA + * transmit buffer, then the function will return (note that if the + * data is written to the DMA buffer in pieces, the overall operation + * may still take longer than this timeout.) Pass portMAX_DELAY for no + * timeout. + * + * @param i2s_num I2S device number + * @param src Source address to write from + * @param size Size of data in bytes + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait) { + esp_err_t ret = ESP_OK; char *data_ptr, *src_byte; size_t bytes_can_write; *bytes_written = 0; ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "tx NULL"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "TX mode is not enabled"); xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); #ifdef CONFIG_PM_ENABLE esp_pm_lock_acquire(p_i2s[i2s_num]->pm_lock); @@ -1389,6 +1998,7 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by while (size > 0) { if (p_i2s[i2s_num]->tx->rw_pos == p_i2s[i2s_num]->tx->buf_size || p_i2s[i2s_num]->tx->curr_ptr == NULL) { if (xQueueReceive(p_i2s[i2s_num]->tx->queue, &p_i2s[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { + ret = ESP_ERR_TIMEOUT; break; } p_i2s[i2s_num]->tx->rw_pos = 0; @@ -1409,13 +2019,33 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by #ifdef CONFIG_PM_ENABLE esp_pm_lock_release(p_i2s[i2s_num]->pm_lock); #endif - xSemaphoreGive(p_i2s[i2s_num]->tx->mux); - return ESP_OK; + return ret; } +/** + * @brief Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM. + * @note Many ticks pass without space becoming available in the DMA + * transmit buffer, then the function will return (note that if the + * data is written to the DMA buffer in pieces, the overall operation + * may still take longer than this timeout.) Pass portMAX_DELAY for no + * timeout. + * Format of the data in source buffer is determined by the I2S configuration (see i2s_config_t). + * + * @param i2s_num I2S device number + * @param src Source address to write from + * @param size Size of data in bytes + * @param src_bits Source audio bit + * @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait) { + esp_err_t ret = ESP_OK; char *data_ptr; int bytes_can_write, tail; int src_bytes, aim_bytes, zero_bytes; @@ -1423,7 +2053,7 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); ESP_RETURN_ON_FALSE((size > 0), ESP_ERR_INVALID_ARG, TAG, "size must greater than zero"); ESP_RETURN_ON_FALSE((aim_bits >= src_bits), ESP_ERR_INVALID_ARG, TAG, "aim_bits mustn't be less than src_bits"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "tx NULL"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "TX mode is not enabled"); if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) { ESP_LOGE(TAG, "bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); return ESP_ERR_INVALID_ARG; @@ -1450,6 +2080,7 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz while (size > 0) { if (p_i2s[i2s_num]->tx->rw_pos == p_i2s[i2s_num]->tx->buf_size || p_i2s[i2s_num]->tx->curr_ptr == NULL) { if (xQueueReceive(p_i2s[i2s_num]->tx->queue, &p_i2s[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { + ret = ESP_ERR_TIMEOUT; break; } p_i2s[i2s_num]->tx->rw_pos = 0; @@ -1473,9 +2104,23 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz p_i2s[i2s_num]->tx->rw_pos += bytes_can_write; } xSemaphoreGive(p_i2s[i2s_num]->tx->mux); - return ESP_OK; + return ret; } +/** + * @brief Read data from I2S DMA receive buffer + * @note If the built-in ADC mode is enabled, we should call i2s_adc_enable and i2s_adc_disable around the whole reading process, + * to prevent the data getting corrupted. + * + * @param i2s_num I2S device number + * @param dest Destination address to read into + * @param size Size of data in bytes + * @param[out] bytes_read Number of bytes read, if timeout, bytes read will be less than the size passed in. + * @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait) { esp_err_t ret = ESP_OK; @@ -1484,7 +2129,7 @@ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_re *bytes_read = 0; dest_byte = (char *)dest; ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->rx), ESP_ERR_INVALID_ARG, TAG, "rx NULL"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->rx), ESP_ERR_INVALID_ARG, TAG, "RX mode is not enabled"); xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); #ifdef CONFIG_PM_ENABLE esp_pm_lock_acquire(p_i2s[i2s_num]->pm_lock); diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 0c8a43db0d..53dd2799a7 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -355,7 +355,7 @@ esp_err_t i2s_stop(i2s_port_t i2s_num); * * @param i2s_num I2S port number * -* @return + * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index c0ff7a6f2b..46d6936359 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -19,35 +19,27 @@ #include "soc/soc_caps.h" #include "hal/i2s_hal.h" -#define I2S_MODE_I2S (I2S_MODE_MASTER|I2S_MODE_SLAVE|I2S_MODE_TX|I2S_MODE_RX) /*!< I2S normal mode*/ - /** * @brief Calculate the closest sample rate clock configuration. * clock relationship: * Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a) * - * @param fsclk I2S source clock freq. - * @param fbck BCK freuency. - * @param bck_div The BCK devider of bck. Generally, set bck_div to 8. - * @param cal Point to `i2s_ll_clk_cal_t` structure. + * @param clk_cfg I2S clock configuration(input) + * @param cal Point to `i2s_ll_clk_cal_t` structure(output). */ -static void i2s_hal_clk_cal(uint32_t fsclk, uint32_t fbck, int bck_div, i2s_ll_clk_cal_t *cal) +static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_clk_cal_t *cal) { int ma = 0; int mb = 0; - uint32_t mclk = fbck * bck_div; - cal->mclk_div = fsclk / mclk; + cal->mclk_div = clk_cfg->mclk_div; cal->a = 1; cal->b = 0; - uint32_t freq_diff = fsclk - mclk * cal->mclk_div; + uint32_t freq_diff = clk_cfg->sclk - clk_cfg->mclk * cal->mclk_div; uint32_t min = ~0; - if (freq_diff == 0) { - return; - } for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) { for (int b = 1; b < a; b++) { ma = freq_diff * a; - mb = mclk * b; + mb = clk_cfg->mclk * b; if (ma == mb) { cal->a = a; cal->b = b; @@ -68,44 +60,67 @@ void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel) i2s_ll_rx_clk_set_src(hal->dev, sel); } -void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor) +void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg) { - i2s_ll_clk_cal_t clk_set = {0}; - i2s_hal_clk_cal(sclk, fbck, factor, &clk_set); - i2s_ll_tx_set_clk(hal->dev, &clk_set); - i2s_ll_tx_set_bck_div_num(hal->dev, factor); + i2s_ll_clk_cal_t mclk_set; + i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set); + i2s_ll_tx_set_clk(hal->dev, &mclk_set); + i2s_ll_tx_set_bck_div_num(hal->dev, clk_cfg->bclk_div); } -void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor) +void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg) { - i2s_ll_clk_cal_t clk_set = {0}; - i2s_hal_clk_cal(sclk, fbck, factor, &clk_set); - i2s_ll_rx_set_clk(hal->dev, &clk_set); - i2s_ll_rx_set_bck_div_num(hal->dev, factor); + i2s_ll_clk_cal_t mclk_set; + i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set); + i2s_ll_rx_set_clk(hal->dev, &mclk_set); + i2s_ll_rx_set_bck_div_num(hal->dev, clk_cfg->bclk_div); } void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal) { - i2s_ll_tx_set_slave_mod(hal->dev, 0); //TX master - i2s_ll_rx_set_slave_mod(hal->dev, 1); //RX Slave + i2s_ll_tx_set_slave_mod(hal->dev, false); //TX master + i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave } void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal) { - i2s_ll_tx_set_slave_mod(hal->dev, 1); //TX Slave - i2s_ll_rx_set_slave_mod(hal->dev, 1); //RX Slave + i2s_ll_tx_set_slave_mod(hal->dev, true); //TX Slave + i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave } -void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num) +void i2s_hal_get_instance(i2s_hal_context_t *hal, int i2s_num) { - //Get hardware instance. + /* Get hardware instance */ hal->dev = I2S_LL_GET_HW(i2s_num); + /* Enable I2S module clock */ i2s_ll_enable_clock(hal->dev); } +#if SOC_I2S_SUPPORTS_ADC_DAC +void i2s_hal_enable_adc_dac_mode(i2s_hal_context_t *hal, i2s_mode_t mode) +{ + if (mode & I2S_MODE_DAC_BUILT_IN) { + i2s_ll_enable_builtin_dac(hal->dev, true); + } + /* In ADC built-in mode, we need to call i2s_set_adc_mode to initialize the specific ADC channel. + * In the current stage, we only support ADC1 and single channel mode. + * In default data mode, the ADC data is in 12-bit resolution mode. + */ + if (mode & I2S_MODE_ADC_BUILT_IN) { + i2s_ll_enable_builtin_adc(hal->dev, true); + } +} + +void i2s_hal_disable_adc_dac_mode(i2s_hal_context_t *hal) +{ + i2s_ll_enable_builtin_dac(hal->dev, false); + i2s_ll_enable_builtin_adc(hal->dev, false); +} +#endif + +#if SOC_I2S_SUPPORTS_PDM_TX void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate) { -#if SOC_I2S_SUPPORTS_PDM_TX /* enable pdm tx mode */ i2s_ll_tx_enable_pdm(hal->dev, true); /* set pdm tx default presacle */ @@ -134,23 +149,23 @@ void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rat i2s_ll_tx_set_pdm_sd_dither2(hal->dev, 0); #endif // SOC_I2S_SUPPORTS_PDM_CODEC -#endif // SOC_I2S_SUPPORTS_PDM_TX } +#endif // SOC_I2S_SUPPORTS_PDM_TX +#if SOC_I2S_SUPPORTS_PDM_RX void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal) { -#if SOC_I2S_SUPPORTS_PDM_RX /* enable pdm rx mode */ i2s_ll_rx_enable_pdm(hal->dev, true); /* set pdm rx downsample number */ i2s_ll_rx_set_pdm_dsr(hal->dev, I2S_PDM_DSR_8S); -#endif // SOC_I2S_SUPPORTS_PDM_RX } +#endif // SOC_I2S_SUPPORTS_PDM_RX void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { - /* disable pdm tx mode */ + /* Disable PDM tx mode and enable TDM mode (if support) */ i2s_ll_tx_enable_pdm(hal->dev, false); #if SOC_I2S_SUPPORTS_TDM @@ -172,7 +187,7 @@ void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t * void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { - /* disable pdm rx mode */ + /* Disable PDM rx mode and enable TDM rx mode (if support)*/ i2s_ll_rx_enable_pdm(hal->dev, false); #if SOC_I2S_SUPPORTS_TDM @@ -208,8 +223,8 @@ static uint32_t i2s_hal_get_ws_bit(i2s_comm_format_t fmt, uint32_t chan_num, uin void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { uint32_t chan_num = 2; - uint32_t chan_bits = hal_cfg->bits_cfg.chan_bits; - uint32_t data_bits = hal_cfg->bits_cfg.sample_bits; + uint32_t chan_bits = hal_cfg->chan_bits; + uint32_t data_bits = hal_cfg->sample_bits; /* Set channel number and valid data bits */ #if SOC_I2S_SUPPORTS_TDM @@ -231,8 +246,8 @@ void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { uint32_t chan_num = 2; - uint32_t chan_bits = hal_cfg->bits_cfg.chan_bits; - uint32_t data_bits = hal_cfg->bits_cfg.sample_bits; + uint32_t chan_bits = hal_cfg->chan_bits; + uint32_t data_bits = hal_cfg->sample_bits; #if SOC_I2S_SUPPORTS_TDM chan_num = hal_cfg->total_chan; @@ -250,32 +265,61 @@ void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t #endif } -void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +void i2s_hal_init(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { +#if SOC_I2S_SUPPORTS_ADC_DAC + if (hal_cfg->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { + i2s_hal_enable_adc_dac_mode(hal, hal_cfg->mode); + /* Return directly if using ADC/DAC mode, no need to set othet configurations */ + return; + } + /* If not using built-in ADC/DAC, disable them */ + i2s_hal_disable_adc_dac_mode(hal); +#endif + + /* Set configurations for TX mode */ if (hal_cfg->mode & I2S_MODE_TX) { i2s_ll_tx_stop(hal->dev); i2s_ll_tx_reset(hal->dev); i2s_ll_tx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //TX Slave +#if SOC_I2S_SUPPORTS_PDM_TX if (hal_cfg->mode & I2S_MODE_PDM) { /* Set tx pdm mode */ i2s_hal_tx_set_pdm_mode_default(hal, hal_cfg->sample_rate); - } else { + } else +#endif + { /* Set tx common mode */ i2s_hal_tx_set_common_mode(hal, hal_cfg); i2s_hal_tx_set_channel_style(hal, hal_cfg); } } + + /* Set configurations for RX mode */ if (hal_cfg->mode & I2S_MODE_RX) { i2s_ll_rx_stop(hal->dev); i2s_ll_rx_reset(hal->dev); i2s_ll_rx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //RX Slave +#if SOC_I2S_SUPPORTS_PDM_RX if (hal_cfg->mode & I2S_MODE_PDM) { /* Set rx pdm mode */ i2s_hal_rx_set_pdm_mode_default(hal); - } else { + } else +#endif + { /* Set rx common mode */ i2s_hal_rx_set_common_mode(hal, hal_cfg); i2s_hal_rx_set_channel_style(hal, hal_cfg); } } + + /* Set configurations for full-duplex mode */ + if ((hal_cfg->mode & I2S_MODE_RX) && (hal_cfg->mode & I2S_MODE_TX)) { + i2s_ll_enable_loop_back(hal->dev, true); + if (hal_cfg->mode & I2S_MODE_MASTER) { + i2s_hal_enable_master_fd_mode(hal); + } else { + i2s_hal_enable_slave_fd_mode(hal); + } + } } diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index d0446f7a47..3c436db179 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -33,16 +33,16 @@ extern "C" { #endif /** - * @brief I2S channel bits configurations - * + * @brief I2S clock configuration */ -typedef union { - struct { - uint32_t sample_bits : 16; /*!< I2S sample bits in one channel */ - uint32_t chan_bits : 16; /*!< I2S total bits in one channel. Should not be smaller than 'sample_bits', default '0' means equal to 'sample_bits' */ - }; - uint32_t val; /*!< I2S cannel bits configiration value */ -} i2s_hal_bits_cfg_t; +typedef struct { + uint32_t sclk; /*!< I2S module clock */ + uint32_t mclk; /*!< I2S master clock */ + uint32_t bclk; /*!< I2S bit clock */ + uint16_t mclk_div; /*!< I2S master clock division */ + uint16_t bclk_div; /*!< I2S bit clock division*/ +} i2s_hal_clock_cfg_t; + /** * @brief I2S HAL configurations @@ -50,17 +50,19 @@ typedef union { typedef struct { i2s_mode_t mode; /*!< I2S work mode, using ored mask of `i2s_mode_t`*/ uint32_t sample_rate; /*!< I2S sample rate*/ - i2s_channel_t ch; /*!< I2S channels*/ i2s_comm_format_t comm_fmt; /*!< I2S communication format */ i2s_channel_fmt_t chan_fmt; /*!< I2S channel format, there are total 16 channels in TDM mode.*/ - i2s_hal_bits_cfg_t bits_cfg; /*!< Channel bits configuration*/ -#if SOC_I2S_SUPPORTS_TDM + uint32_t sample_bits; /*!< I2S sample bits in one channel */ + uint32_t chan_bits; /*!< I2S total bits in one channel. Should not be smaller than 'sample_bits', default '0' means equal to 'sample_bits' */ + uint32_t active_chan; /*!< I2S active channel number */ uint32_t total_chan; /*!< Total number of I2S channels */ + +#if SOC_I2S_SUPPORTS_TDM uint32_t chan_mask; /*!< Active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<dev) /** - * @brief Init the I2S hal. This function should be called first before other hal layer function is called + * @brief Get I2S hardware instance and enable I2S module clock + * @note This function should be called first before other hal layer function is called * * @param hal Context of the HAL layer * @param i2s_num The uart port number, the max port number is (I2S_NUM_MAX -1) */ -void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num); +void i2s_hal_get_instance(i2s_hal_context_t *hal, int i2s_num); /** * @brief Configure I2S source clock @@ -133,12 +136,12 @@ void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); /** - * @brief Config I2S param + * @brief Initialize I2S hardware * * @param hal Context of the HAL layer * @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t` */ -void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); +void i2s_hal_init(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); /** * @brief Enable I2S master full-duplex mode @@ -212,39 +215,49 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal); * @brief Configure I2S TX module clock devider * * @param hal Context of the HAL layer - * @param sclk I2S source clock freq - * @param fbck I2S bck freq - * @param factor bck factor, factor=sclk/fbck + * @param clk_cfg I2S clock configuration */ -void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor); +void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg); /** * @brief Configure I2S RX module clock devider * * @param hal Context of the HAL layer - * @param sclk I2S source clock freq - * @param fbck I2S bck freq - * @param factor bck factor, factor=sclk/fbck + * @param clk_cfg I2S clock configuration */ -void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor); - -#if SOC_I2S_SUPPORTS_PCM -/** - * @brief Configure I2S TX PCM encoder or decoder. - * - * @param hal Context of the HAL layer - * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` - */ -#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_set_pcm_type((hal)->dev, cfg) +void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg); /** - * @brief Configure I2S RX PCM encoder or decoder. + * @brief Set I2S tx clock source * * @param hal Context of the HAL layer - * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` + * @param clk_src i2s tx clock source (see 'i2s_clock_src_t') */ -#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_set_pcm_type((hal)->dev, cfg) -#endif +#define i2s_hal_tx_set_clock_source(hal, clk_src) i2s_ll_tx_clk_set_src((hal)->dev, clk_src) + +/** + * @brief Set I2S rx clock source + * + * @param hal Context of the HAL layer + * @param clk_src i2s rx clock source (see 'i2s_clock_src_t') + */ +#define i2s_hal_rx_set_clock_source(hal, clk_src) i2s_ll_rx_clk_set_src((hal)->dev, clk_src) + +/** + * @brief Enable I2S tx slave mode + * + * @param hal Context of the HAL layer + * @param enable set 'true' to enable tx slave mode + */ +#define i2s_hal_tx_enable_slave_mode(hal, enable) i2s_ll_tx_set_slave_mod((hal)->dev, enable) + +/** + * @brief Enable I2S rx slave mode + * + * @param hal Context of the HAL layer + * @param enable set 'true' to enable rx slave mode + */ +#define i2s_hal_rx_enable_slave_mode(hal, enable) i2s_ll_rx_set_slave_mod((hal)->dev, enable) /** * @brief Enable loopback mode @@ -271,6 +284,24 @@ void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t * */ void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); +#if SOC_I2S_SUPPORTS_PCM +/** + * @brief Configure I2S TX PCM encoder or decoder. + * + * @param hal Context of the HAL layer + * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` + */ +#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_set_pcm_type((hal)->dev, cfg) + +/** + * @brief Configure I2S RX PCM encoder or decoder. + * + * @param hal Context of the HAL layer + * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` + */ +#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_set_pcm_type((hal)->dev, cfg) +#endif + #if SOC_I2S_SUPPORTS_PDM_TX /** * @brief Configure I2S TX PDM sample rate diff --git a/components/hal/include/hal/i2s_types.h b/components/hal/include/hal/i2s_types.h index 630aedb149..98a2c76bdf 100644 --- a/components/hal/include/hal/i2s_types.h +++ b/components/hal/include/hal/i2s_types.h @@ -92,12 +92,12 @@ typedef enum { I2S_COMM_FORMAT_STAND_MAX, /*!< standard max*/ //old definition will be removed in the future. - I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ - I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ - I2S_COMM_FORMAT_I2S_LSB __attribute__((deprecated)) = 0x02, /*!< I2S format LSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_LSB) correspond to `I2S_COMM_FORMAT_STAND_MSB`*/ - I2S_COMM_FORMAT_PCM __attribute__((deprecated)) = 0x04, /*!< I2S communication format PCM, correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ - I2S_COMM_FORMAT_PCM_SHORT __attribute__((deprecated)) = 0x04, /*!< PCM Short, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_SHORT) correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ - I2S_COMM_FORMAT_PCM_LONG __attribute__((deprecated)) = 0x08, /*!< PCM Long, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG) correspond to `I2S_COMM_FORMAT_STAND_PCM_LONG`*/ + // I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ + // I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ + // I2S_COMM_FORMAT_I2S_LSB __attribute__((deprecated)) = 0x02, /*!< I2S format LSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_LSB) correspond to `I2S_COMM_FORMAT_STAND_MSB`*/ + // I2S_COMM_FORMAT_PCM __attribute__((deprecated)) = 0x04, /*!< I2S communication format PCM, correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ + // I2S_COMM_FORMAT_PCM_SHORT __attribute__((deprecated)) = 0x04, /*!< PCM Short, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_SHORT) correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ + // I2S_COMM_FORMAT_PCM_LONG __attribute__((deprecated)) = 0x08, /*!< PCM Long, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG) correspond to `I2S_COMM_FORMAT_STAND_PCM_LONG`*/ } i2s_comm_format_t; /** diff --git a/components/soc/esp32/i2s_periph.c b/components/soc/esp32/i2s_periph.c index cf6d4ba992..b65dc9602d 100644 --- a/components/soc/esp32/i2s_periph.c +++ b/components/soc/esp32/i2s_periph.c @@ -21,23 +21,39 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { .mck_out_sig = -1, // Unavailable - .rx_bck_sig = I2S0I_BCK_IN_IDX, - .tx_bck_sig = I2S0O_BCK_OUT_IDX, - .tx_ws_sig = I2S0O_WS_OUT_IDX, - .rx_ws_sig = I2S0I_WS_IN_IDX, + + .m_tx_bck_sig = I2S0O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S0I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S0O_WS_OUT_IDX, + .m_rx_ws_sig = I2S0I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S0O_BCK_IN_IDX, + .s_rx_bck_sig = I2S0I_BCK_IN_IDX, + .s_tx_ws_sig = I2S0O_WS_IN_IDX, + .s_rx_ws_sig = I2S0I_WS_IN_IDX, + .data_out_sig = I2S0O_DATA_OUT23_IDX, .data_in_sig = I2S0I_DATA_IN15_IDX, + .irq = ETS_I2S0_INTR_SOURCE, .module = PERIPH_I2S0_MODULE, }, { .mck_out_sig = -1, // Unavailable - .rx_bck_sig = I2S1I_BCK_IN_IDX, - .tx_bck_sig = I2S1O_BCK_OUT_IDX, - .tx_ws_sig = I2S1O_WS_OUT_IDX, - .rx_ws_sig = I2S1I_WS_IN_IDX, + + .m_tx_bck_sig = I2S1O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S1I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S1O_WS_OUT_IDX, + .m_rx_ws_sig = I2S1I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S1O_BCK_IN_IDX, + .s_rx_bck_sig = I2S1I_BCK_IN_IDX, + .s_tx_ws_sig = I2S1O_WS_IN_IDX, + .s_rx_ws_sig = I2S1I_WS_IN_IDX, + .data_out_sig = I2S1O_DATA_OUT23_IDX, .data_in_sig = I2S1I_DATA_IN15_IDX, + .irq = ETS_I2S1_INTR_SOURCE, .module = PERIPH_I2S1_MODULE, } diff --git a/components/soc/esp32c3/i2s_periph.c b/components/soc/esp32c3/i2s_periph.c index e654a0c62e..e852a8e56d 100644 --- a/components/soc/esp32c3/i2s_periph.c +++ b/components/soc/esp32c3/i2s_periph.c @@ -21,12 +21,20 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { .mck_out_sig = I2S_MCLK_OUT_IDX, - .rx_bck_sig = I2SI_BCK_IN_IDX, - .tx_bck_sig = I2SO_BCK_OUT_IDX, - .tx_ws_sig = I2SO_WS_OUT_IDX, - .rx_ws_sig = I2SI_WS_IN_IDX, + + .m_tx_bck_sig = I2SO_BCK_OUT_IDX, + .m_rx_bck_sig = I2SI_BCK_OUT_IDX, + .m_tx_ws_sig = I2SO_WS_OUT_IDX, + .m_rx_ws_sig = I2SI_WS_OUT_IDX, + + .s_tx_bck_sig = I2SO_BCK_IN_IDX, + .s_rx_bck_sig = I2SI_BCK_IN_IDX, + .s_tx_ws_sig = I2SO_WS_IN_IDX, + .s_rx_ws_sig = I2SI_WS_IN_IDX, + .data_out_sig = I2SO_SD_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, + .irq = -1, .module = PERIPH_I2S1_MODULE, } diff --git a/components/soc/esp32s2/i2s_periph.c b/components/soc/esp32s2/i2s_periph.c index 83700ed886..48c6161d20 100644 --- a/components/soc/esp32s2/i2s_periph.c +++ b/components/soc/esp32s2/i2s_periph.c @@ -21,12 +21,20 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { .mck_out_sig = CLK_I2S_MUX_IDX, - .rx_bck_sig = I2S0I_BCK_IN_IDX, - .tx_bck_sig = I2S0O_BCK_OUT_IDX, - .tx_ws_sig = I2S0O_WS_OUT_IDX, - .rx_ws_sig = I2S0I_WS_IN_IDX, + + .m_tx_bck_sig = I2S0O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S0I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S0O_WS_OUT_IDX, + .m_rx_ws_sig = I2S0I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S0O_BCK_IN_IDX, + .s_rx_bck_sig = I2S0I_BCK_IN_IDX, + .s_tx_ws_sig = I2S0O_WS_IN_IDX, + .s_rx_ws_sig = I2S0I_WS_IN_IDX, + .data_out_sig = I2S0O_DATA_OUT23_IDX, .data_in_sig = I2S0I_DATA_IN15_IDX, + .irq = ETS_I2S0_INTR_SOURCE, .module = PERIPH_I2S0_MODULE, } diff --git a/components/soc/esp32s3/i2s_periph.c b/components/soc/esp32s3/i2s_periph.c index 39ddfff5a5..79a8308e21 100644 --- a/components/soc/esp32s3/i2s_periph.c +++ b/components/soc/esp32s3/i2s_periph.c @@ -21,23 +21,39 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { .mck_out_sig = I2S0_MCLK_OUT_IDX, - .rx_bck_sig = I2S0I_BCK_IN_IDX, - .tx_bck_sig = I2S0O_BCK_OUT_IDX, - .tx_ws_sig = I2S0O_WS_OUT_IDX, - .rx_ws_sig = I2S0I_WS_IN_IDX, + + .m_tx_bck_sig = I2S0O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S0I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S0O_WS_OUT_IDX, + .m_rx_ws_sig = I2S0I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S0O_BCK_IN_IDX, + .s_rx_bck_sig = I2S0I_BCK_IN_IDX, + .s_tx_ws_sig = I2S0O_WS_IN_IDX, + .s_rx_ws_sig = I2S0I_WS_IN_IDX, + .data_out_sig = I2S0O_SD_OUT_IDX, .data_in_sig = I2S0I_SD_IN_IDX, + .irq = -1, .module = PERIPH_I2S0_MODULE, }, { .mck_out_sig = I2S1_MCLK_OUT_IDX, - .rx_bck_sig = I2S1I_BCK_IN_IDX, - .tx_bck_sig = I2S1O_BCK_OUT_IDX, - .tx_ws_sig = I2S1O_WS_OUT_IDX, - .rx_ws_sig = I2S1I_WS_IN_IDX, + + .m_tx_bck_sig = I2S1O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S1I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S1O_WS_OUT_IDX, + .m_rx_ws_sig = I2S1I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S1O_BCK_IN_IDX, + .s_rx_bck_sig = I2S1I_BCK_IN_IDX, + .s_tx_ws_sig = I2S1O_WS_IN_IDX, + .s_rx_ws_sig = I2S1I_WS_IN_IDX, + .data_out_sig = I2S1O_SD_OUT_IDX, .data_in_sig = I2S1I_SD_IN_IDX, + .irq = -1, .module = PERIPH_I2S1_MODULE, } diff --git a/components/soc/include/soc/i2s_periph.h b/components/soc/include/soc/i2s_periph.h index 59e31674d5..167c84700f 100644 --- a/components/soc/include/soc/i2s_periph.h +++ b/components/soc/include/soc/i2s_periph.h @@ -28,12 +28,20 @@ extern "C" { */ typedef struct { const uint8_t mck_out_sig; - const uint8_t tx_bck_sig; - const uint8_t rx_bck_sig; - const uint8_t tx_ws_sig; - const uint8_t rx_ws_sig; + + const uint8_t m_tx_bck_sig; + const uint8_t m_rx_bck_sig; + const uint8_t m_tx_ws_sig; + const uint8_t m_rx_ws_sig; + + const uint8_t s_tx_bck_sig; + const uint8_t s_rx_bck_sig; + const uint8_t s_tx_ws_sig; + const uint8_t s_rx_ws_sig; + const uint8_t data_out_sig; const uint8_t data_in_sig; + const uint8_t irq; const periph_module_t module; } i2s_signal_conn_t; From 0ff3dd97780a4c779907d5494100d45eaf9f27a4 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 16 Aug 2021 13:32:22 +0800 Subject: [PATCH 112/310] i2s: fix mono support issue --- components/driver/i2s.c | 42 +++++++++++---------- components/hal/esp32c3/include/hal/i2s_ll.h | 24 ++++++++++++ components/hal/esp32h2/include/hal/i2s_ll.h | 22 +++++++++++ components/hal/esp32s3/include/hal/i2s_ll.h | 24 ++++++++++++ components/hal/i2s_hal.c | 6 +++ components/hal/include/hal/i2s_types.h | 4 +- 6 files changed, 101 insertions(+), 21 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index b91172819b..bffea378d9 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -885,7 +885,7 @@ float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int o /** * @brief Calculate APLL parameters to get a closest frequency */ -void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir) +static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir) { int _odir, _sdm0, _sdm1, _sdm2; float avg; @@ -966,11 +966,13 @@ static uint32_t i2s_get_source_clock(i2s_port_t i2s_num, bool use_apll, uint32_t int sdm1 = 0; int sdm2 = 0; int odir = 0; - if (fixed_mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / 16 < SOC_I2S_APLL_MIN_RATE) { - ESP_LOGW(TAG, "i2s sample rate is too small, use I2S_CLK_D2CLK as default clock source"); + if ((fixed_mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / 16) < SOC_I2S_APLL_MIN_RATE) { + ESP_LOGW(TAG, "fixed_mclk is too small, use I2S_CLK_D2CLK as default clock source"); goto err; } - ESP_LOGD(TAG, "APLL coefficient: sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); + i2s_apll_calculate_fi2s(p_i2s[i2s_num]->hal_cfg.sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits, + &sdm0, &sdm1, &sdm2, &odir); + ESP_LOGI(TAG, "APLL Enabled, coefficient: sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); rtc_clk_apll_enable(true, sdm0, sdm1, sdm2, odir); return fixed_mclk; } @@ -1199,7 +1201,7 @@ static uint32_t i2s_get_max_channel_num(i2s_channel_t chan_mask) uint32_t max_chan = 0; uint32_t channel = chan_mask & 0xFFFF; for (int i = 0; channel && i < 16; i++, channel >>= 1) { - if (chan_mask & 0x01) { + if (channel & 0x01) { max_chan = i + 1; } } @@ -1562,6 +1564,8 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ #if !SOC_I2S_SUPPORTS_TDM cfg->active_chan = i2s_get_active_channel_num(cfg); cfg->total_chan = ch == I2S_CHANNEL_MONO ? 2 : cfg->active_chan; + /* Default */ + cfg->chan_fmt = cfg->chan_fmt < I2S_CHANNEL_FMT_ONLY_RIGHT ? I2S_CHANNEL_FMT_ONLY_RIGHT : cfg->chan_fmt; #endif } uint32_t data_bits = cfg->sample_bits; @@ -1578,7 +1582,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ /* If uising chips like ESP32 and ESP32S2 * Only need to calculate clock for MASTER mode - * Because BCK and WS clock are provide by external codec in SLAVE mode + * Because BCK and WS clock are provided by the external codec in SLAVE mode * In SLAVE mode, the mclk_div and bck_div will be set to 1 * So that we can get a high module clock which could detect the edges of externel clock more accurately * Otherwise the data we receive or send would get a large latency and go wrong due to the slow module clock @@ -1628,7 +1632,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ /* Reset the end-of-frame number */ i2s_hal_set_rx_eof_num(&(p_i2s[i2s_num]->hal), buf_size); } - /* Reset the queue to avoid receive invalid data */ + /* Reset the queue to avoid receiving invalid data */ xQueueReset(p_i2s[i2s_num]->rx->queue); xSemaphoreGive(p_i2s[i2s_num]->rx->mux); ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d rx DMA buffer malloc failed", i2s_num); @@ -1756,20 +1760,25 @@ static esp_err_t i2s_driver_init(i2s_port_t i2s_num, const i2s_config_t *i2s_con /* Set chan_mask according to channel format */ switch (i2s_config->channel_format) { - case I2S_CHANNEL_FMT_RIGHT_LEFT: - case I2S_CHANNEL_FMT_ALL_RIGHT: + case I2S_CHANNEL_FMT_RIGHT_LEFT: // fall through + case I2S_CHANNEL_FMT_ALL_RIGHT: // fall through case I2S_CHANNEL_FMT_ALL_LEFT: p_i2s[i2s_num]->hal_cfg.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1; + p_i2s[i2s_num]->hal_cfg.total_chan = 2; break; - case I2S_CHANNEL_FMT_ONLY_RIGHT: - p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->left_align ? I2S_TDM_ACTIVE_CH1 : I2S_TDM_ACTIVE_CH0; - break; + case I2S_CHANNEL_FMT_ONLY_RIGHT: // fall through case I2S_CHANNEL_FMT_ONLY_LEFT: - p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->left_align ? I2S_TDM_ACTIVE_CH0 : I2S_TDM_ACTIVE_CH1; + p_i2s[i2s_num]->hal_cfg.chan_mask = I2S_TDM_ACTIVE_CH0; + p_i2s[i2s_num]->hal_cfg.total_chan = 2; break; case I2S_CHANNEL_FMT_MULTIPLE: ESP_RETURN_ON_FALSE(i2s_config->chan_mask, ESP_ERR_INVALID_ARG, TAG, "i2s all channel are disabled"); p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->chan_mask; + /* Get the max actived channel number */ + uint32_t max_channel = i2s_get_max_channel_num(p_i2s[i2s_num]->hal_cfg.chan_mask); + /* If total channel is smaller than max actived channel number then set it to the max active channel number */ + p_i2s[i2s_num]->hal_cfg.total_chan = p_i2s[i2s_num]->hal_cfg.total_chan < max_channel ? max_channel : + p_i2s[i2s_num]->hal_cfg.total_chan; break; default: ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "wrong i2s channel format, going to uninstall i2s"); @@ -1777,11 +1786,7 @@ static esp_err_t i2s_driver_init(i2s_port_t i2s_num, const i2s_config_t *i2s_con /* Calculate actived channel number in channel mask */ p_i2s[i2s_num]->hal_cfg.active_chan = i2s_get_active_channel_num(&p_i2s[i2s_num]->hal_cfg); - /* Get the max actived channel number */ - uint32_t max_channel = i2s_get_max_channel_num(p_i2s[i2s_num]->hal_cfg.chan_mask); - /* If total channel is smaller than max actived channel number then set it to the max active channel number */ - p_i2s[i2s_num]->hal_cfg.total_chan = p_i2s[i2s_num]->hal_cfg.total_chan < max_channel ? max_channel : - p_i2s[i2s_num]->hal_cfg.total_chan; + #else /* Calculate actived channel number in channel mask */ p_i2s[i2s_num]->hal_cfg.active_chan = i2s_get_active_channel_num(&p_i2s[i2s_num]->hal_cfg); @@ -1878,7 +1883,6 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, #if SOC_I2S_SUPPORTS_ADC_DAC /* If using built-in ADC, we need to enable ADC power manerge*/ if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) { - printf("ADC power on\n"); adc_power_acquire(); } #endif diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 30fbfb7e51..44f9142c1a 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -781,6 +781,30 @@ static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) hw->conf_single_data = data; } +/** + * @brief Enable TX mono mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + hw->tx_conf.tx_mono = mono_ena; + hw->tx_conf.tx_chan_equal = mono_ena; +} + +/** + * @brief Enable RX mono mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + hw->rx_conf.rx_mono = mono_ena; + hw->rx_conf.rx_mono_fst_vld = mono_ena; +} + /** * @brief Enable loopback mode * diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 9819a8ed4b..d9c70cd130 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -804,6 +804,28 @@ static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) } +/** + * @brief Enable TX mono mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + abort(); +} + +/** + * @brief Enable RX mono mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + abort(); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 791918fae0..8f5de0f56d 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -806,6 +806,30 @@ static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) hw->conf_single_data = data; } +/** + * @brief Enable TX mono mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + hw->tx_conf.tx_mono = mono_ena; + hw->tx_conf.tx_chan_equal = mono_ena; +} + +/** + * @brief Enable RX mono mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mono_ena Set true to enable mono mde. + */ +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) +{ + hw->rx_conf.rx_mono = mono_ena; + hw->rx_conf.rx_mono_fst_vld = mono_ena; +} + /** * @brief Enable loopback mode * diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 46d6936359..431a887484 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -225,6 +225,8 @@ void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t uint32_t chan_num = 2; uint32_t chan_bits = hal_cfg->chan_bits; uint32_t data_bits = hal_cfg->sample_bits; + bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) || + (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT); /* Set channel number and valid data bits */ #if SOC_I2S_SUPPORTS_TDM @@ -232,6 +234,7 @@ void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t i2s_ll_tx_set_chan_num(hal->dev, chan_num); #endif i2s_ll_tx_set_sample_bit(hal->dev, chan_bits, data_bits); + i2s_ll_tx_enable_mono_mode(hal->dev, is_mono); /* Set communication format */ bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false; @@ -248,12 +251,15 @@ void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t uint32_t chan_num = 2; uint32_t chan_bits = hal_cfg->chan_bits; uint32_t data_bits = hal_cfg->sample_bits; + bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) || + (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT); #if SOC_I2S_SUPPORTS_TDM chan_num = hal_cfg->total_chan; i2s_ll_rx_set_chan_num(hal->dev, chan_num); #endif i2s_ll_rx_set_sample_bit(hal->dev, chan_bits, data_bits); + i2s_ll_rx_enable_mono_mode(hal->dev, is_mono); /* Set communication format */ bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false; diff --git a/components/hal/include/hal/i2s_types.h b/components/hal/include/hal/i2s_types.h index 98a2c76bdf..d22dfc5c0e 100644 --- a/components/hal/include/hal/i2s_types.h +++ b/components/hal/include/hal/i2s_types.h @@ -107,8 +107,8 @@ typedef enum { I2S_CHANNEL_FMT_RIGHT_LEFT, /*!< Separated left and right channel */ I2S_CHANNEL_FMT_ALL_RIGHT, /*!< Load right channel data in both two channels */ I2S_CHANNEL_FMT_ALL_LEFT, /*!< Load left channel data in both two channels */ - I2S_CHANNEL_FMT_ONLY_RIGHT, /*!< Only load data in right channel */ - I2S_CHANNEL_FMT_ONLY_LEFT, /*!< Only load data in left channel */ + I2S_CHANNEL_FMT_ONLY_RIGHT, /*!< Only load data in right channel (mono mode) */ + I2S_CHANNEL_FMT_ONLY_LEFT, /*!< Only load data in left channel (mono mode) */ #if SOC_I2S_SUPPORTS_TDM // Multiple channels are available with TDM feature I2S_CHANNEL_FMT_MULTIPLE, /*!< More than two channels are used */ From b09194308cd20664d7283cf4ade5a070791b1ac2 Mon Sep 17 00:00:00 2001 From: Sachin Billore Date: Thu, 2 Sep 2021 11:49:09 +0530 Subject: [PATCH 113/310] CI increase parallel count for assing_test failure fix --- .gitlab/ci/target-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 8138264e11..14301c1d87 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -684,7 +684,7 @@ UT_C3_FLASH_SUSPEND: UT_S3: extends: .unit_test_esp32s3_template - parallel: 27 + parallel: 29 tags: - ESP32S3_IDF - UT_T1_1 From 87b958c814c8824145b47f1dc12ccc284ed2d944 Mon Sep 17 00:00:00 2001 From: Yuriy Shestakov Date: Wed, 18 Aug 2021 23:12:01 +0300 Subject: [PATCH 114/310] Fixed GLITCH_RTC_RST for esp32-c3 revision 3 * Issue: https://github.com/espressif/esp-idf/issues/7082 Signed-off-by: Yuriy Shestakov Closes https://github.com/espressif/esp-idf/issues/7082 Closes https://github.com/espressif/esp-idf/pull/7441 --- components/bootloader_support/src/esp32c3/bootloader_esp32c3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c b/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c index 7f022f6560..e561f83fb4 100644 --- a/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c +++ b/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c @@ -273,7 +273,8 @@ static inline void bootloader_glitch_reset_disable(void) uint8_t chip_version = bootloader_common_get_chip_revision(); if (chip_version < 2) { REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST); - } else if (chip_version == 2) { + } else { + // checked on ESP32-C3 revisions 2 and 3 REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST); } } From bf1dde723331f3a8d0af68d2222cdc98d9b50f04 Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Fri, 27 Aug 2021 09:37:52 +0530 Subject: [PATCH 115/310] bootloader: Enable clock glitch detection Reset the device when clock glitch detected. Clock glitch detection is only active in bootloader --- .../subproject/main/ld/esp32/bootloader.ld | 1 + .../subproject/main/ld/esp32c3/bootloader.ld | 1 + .../subproject/main/ld/esp32h2/bootloader.ld | 1 + .../subproject/main/ld/esp32s2/bootloader.ld | 1 + .../subproject/main/ld/esp32s3/bootloader.ld | 1 + components/bootloader_support/CMakeLists.txt | 1 + .../include_bootloader/bootloader_soc.h | 27 ++++++++++++ .../src/bootloader_utility.c | 7 ++++ .../src/esp32/bootloader_soc.c | 21 ++++++++++ .../src/esp32c3/bootloader_esp32c3.c | 31 ++++++++++---- .../src/esp32c3/bootloader_soc.c | 41 +++++++++++++++++++ .../src/esp32h2/bootloader_esp32h2.c | 20 ++++----- .../src/esp32h2/bootloader_soc.c | 41 +++++++++++++++++++ .../src/esp32s2/bootloader_soc.c | 21 ++++++++++ .../src/esp32s3/bootloader_esp32s3.c | 10 +++++ .../src/esp32s3/bootloader_soc.c | 41 +++++++++++++++++++ .../soc/esp32s3/include/soc/rtc_cntl_reg.h | 4 ++ 17 files changed, 250 insertions(+), 20 deletions(-) create mode 100644 components/bootloader_support/include_bootloader/bootloader_soc.h create mode 100644 components/bootloader_support/src/esp32/bootloader_soc.c create mode 100644 components/bootloader_support/src/esp32c3/bootloader_soc.c create mode 100644 components/bootloader_support/src/esp32h2/bootloader_soc.c create mode 100644 components/bootloader_support/src/esp32s2/bootloader_soc.c create mode 100644 components/bootloader_support/src/esp32s3/bootloader_soc.c diff --git a/components/bootloader/subproject/main/ld/esp32/bootloader.ld b/components/bootloader/subproject/main/ld/esp32/bootloader.ld index 0c065d2c0c..30e5a79c45 100644 --- a/components/bootloader/subproject/main/ld/esp32/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32/bootloader.ld @@ -49,6 +49,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld index 4da19b44de..c9b2da7612 100644 --- a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld @@ -36,6 +36,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld index dc49e09123..c5648b815e 100644 --- a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld @@ -36,6 +36,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld index 6ba052d6aa..92e0126cf0 100644 --- a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld @@ -36,6 +36,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld index 85daecd512..244482f823 100644 --- a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld @@ -37,6 +37,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index f2da1dbb2e..664a59817d 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -26,6 +26,7 @@ if(BOOTLOADER_BUILD) "src/bootloader_console_loader.c" "src/bootloader_panic.c" "src/${IDF_TARGET}/bootloader_sha.c" + "src/${IDF_TARGET}/bootloader_soc.c" "src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c" ) list(APPEND priv_requires hal) diff --git a/components/bootloader_support/include_bootloader/bootloader_soc.h b/components/bootloader_support/include_bootloader/bootloader_soc.h new file mode 100644 index 0000000000..a7414fd3f3 --- /dev/null +++ b/components/bootloader_support/include_bootloader/bootloader_soc.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +/** + * @brief Configure analog super WDT reset + * + * @param enable Boolean to enable or disable super WDT reset + */ +void bootloader_ana_super_wdt_reset_config(bool enable); + +/** + * @brief Configure analog brownout reset + * + * @param enable Boolean to enable or disable brownout reset + */ +void bootloader_ana_bod_reset_config(bool enable); + +/** + * @brief Configure analog clock glitch reset + * + * @param enable Boolean to enable or disable clock glitch reset + */ +void bootloader_ana_clock_glitch_reset_config(bool enable); diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index dddf93f3a8..8533f2b3ce 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -76,6 +76,7 @@ #include "bootloader_utility.h" #include "bootloader_sha.h" #include "bootloader_console.h" +#include "bootloader_soc.h" #include "esp_efuse.h" static const char *TAG = "boot"; @@ -636,6 +637,12 @@ static void load_image(const esp_image_metadata_t *image_data) ESP_LOGI(TAG, "Disabling RNG early entropy source..."); bootloader_random_disable(); + /* Disable glitch reset after all the security checks are completed. + * Glitch detection can be falsely triggered by EMI interference (high RF TX power, etc) + * and to avoid such false alarms, disable it. + */ + bootloader_ana_clock_glitch_reset_config(false); + // copy loaded segments to RAM, set up caches for mapped segments, and start application unpack_load_app(image_data); } diff --git a/components/bootloader_support/src/esp32/bootloader_soc.c b/components/bootloader_support/src/esp32/bootloader_soc.c new file mode 100644 index 0000000000..242a575508 --- /dev/null +++ b/components/bootloader_support/src/esp32/bootloader_soc.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + (void)enable; +} diff --git a/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c b/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c index e561f83fb4..608654e091 100644 --- a/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c +++ b/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c @@ -36,6 +36,7 @@ #include "regi2c_ctrl.h" #include "bootloader_console.h" #include "bootloader_flash_priv.h" +#include "bootloader_soc.h" #include "esp_efuse.h" static const char *TAG = "boot.esp32c3"; @@ -263,7 +264,7 @@ static inline void bootloader_hardware_init(void) } } -static inline void bootloader_glitch_reset_disable(void) +static inline void bootloader_ana_reset_config(void) { /* For origin chip & ECO1: only support swt reset; @@ -271,11 +272,27 @@ static inline void bootloader_glitch_reset_disable(void) For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset. */ uint8_t chip_version = bootloader_common_get_chip_revision(); - if (chip_version < 2) { - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST); - } else { - // checked on ESP32-C3 revisions 2 and 3 - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST); + switch (chip_version) { + case 0: + case 1: + //Enable WDT reset. Disable BOR and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(false); + bootloader_ana_clock_glitch_reset_config(false); + break; + case 2: + //Enable WDT and BOR reset. Disable GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(false); + break; + case 3: + default: + //Enable WDT, BOR, and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(true); + break; } } @@ -284,7 +301,7 @@ esp_err_t bootloader_init(void) esp_err_t ret = ESP_OK; bootloader_hardware_init(); - bootloader_glitch_reset_disable(); + bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); // protect memory region bootloader_init_mem(); diff --git a/components/bootloader_support/src/esp32c3/bootloader_soc.c b/components/bootloader_support/src/esp32c3/bootloader_soc.c new file mode 100644 index 0000000000..7104528a58 --- /dev/null +++ b/components/bootloader_support/src/esp32c3/bootloader_soc.c @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } else { + REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } +} diff --git a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c index a483b34ceb..7ff27dd693 100644 --- a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c +++ b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c @@ -36,6 +36,7 @@ #include "regi2c_ctrl.h" #include "bootloader_console.h" #include "bootloader_flash_priv.h" +#include "bootloader_soc.h" static const char *TAG = "boot.esp32h2"; @@ -257,19 +258,12 @@ static inline void bootloader_hardware_init(void) } -static inline void bootloader_glitch_reset_disable(void) +static inline void bootloader_ana_reset_config(void) { - /* - For origin chip & ECO1: only support swt reset; - For ECO2: fix brownout reset bug, support swt & brownout reset; - For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset. - */ - uint8_t chip_version = bootloader_common_get_chip_revision(); - if (chip_version < 2) { - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST); - } else if (chip_version == 2) { - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST); - } + //Enable WDT, BOR, and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(true); } esp_err_t bootloader_init(void) @@ -277,7 +271,7 @@ esp_err_t bootloader_init(void) esp_err_t ret = ESP_OK; bootloader_hardware_init(); - bootloader_glitch_reset_disable(); + bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); // protect memory region bootloader_init_mem(); diff --git a/components/bootloader_support/src/esp32h2/bootloader_soc.c b/components/bootloader_support/src/esp32h2/bootloader_soc.c new file mode 100644 index 0000000000..7104528a58 --- /dev/null +++ b/components/bootloader_support/src/esp32h2/bootloader_soc.c @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } else { + REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } +} diff --git a/components/bootloader_support/src/esp32s2/bootloader_soc.c b/components/bootloader_support/src/esp32s2/bootloader_soc.c new file mode 100644 index 0000000000..242a575508 --- /dev/null +++ b/components/bootloader_support/src/esp32s2/bootloader_soc.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + (void)enable; +} diff --git a/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c index f4aae147b2..8346b00d02 100644 --- a/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c +++ b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c @@ -34,6 +34,7 @@ #include "bootloader_mem.h" #include "bootloader_console.h" #include "bootloader_flash_priv.h" +#include "bootloader_soc.h" #include "esp_efuse.h" @@ -296,9 +297,18 @@ static void bootloader_super_wdt_auto_feed(void) REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0); } +static inline void bootloader_ana_reset_config(void) +{ + //Enable WDT, BOR, and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(true); +} + esp_err_t bootloader_init(void) { esp_err_t ret = ESP_OK; + bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); // protect memory region bootloader_init_mem(); diff --git a/components/bootloader_support/src/esp32s3/bootloader_soc.c b/components/bootloader_support/src/esp32s3/bootloader_soc.c new file mode 100644 index 0000000000..7104528a58 --- /dev/null +++ b/components/bootloader_support/src/esp32s3/bootloader_soc.c @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } else { + REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } +} diff --git a/components/soc/esp32s3/include/soc/rtc_cntl_reg.h b/components/soc/esp32s3/include/soc/rtc_cntl_reg.h index 353c0a53e2..4f15782f5b 100644 --- a/components/soc/esp32s3/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32s3/include/soc/rtc_cntl_reg.h @@ -3584,6 +3584,10 @@ ork.*/ #define RTC_CNTL_FIB_SEL_V 0x7 #define RTC_CNTL_FIB_SEL_S 0 +#define RTC_CNTL_FIB_GLITCH_RST BIT(0) +#define RTC_CNTL_FIB_BOR_RST BIT(1) +#define RTC_CNTL_FIB_SUPER_WDT_RST BIT(2) + #define RTC_CNTL_TOUCH_DAC_REG (DR_REG_RTCCNTL_BASE + 0x14C) /* RTC_CNTL_TOUCH_PAD0_DAC : R/W ;bitpos:[31:29] ;default: 3'd0 ; */ /*description: .*/ From 07bd686471b3d57b01f7be006035b331459670e3 Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Thu, 2 Sep 2021 15:19:49 +0800 Subject: [PATCH 116/310] marking vTaskSuspendAll and a few other small cleanups (cherry picked from commit dc61510249fe441189ea1ca557deb9f003bbd374) --- components/freertos/event_groups.c | 54 ++++++++ .../freertos/include/freertos/portable.h | 15 +++ components/freertos/include/freertos/semphr.h | 15 ++- .../freertos/include/freertos/stdint.readme | 27 +++- components/freertos/include/freertos/task.h | 118 ++++++++++++++---- components/freertos/queue.c | 102 ++++++++++++++- components/freertos/stream_buffer.c | 64 +++++++++- components/freertos/tasks.c | 90 ++++++++++--- components/freertos/timers.c | 40 ++++-- 9 files changed, 472 insertions(+), 53 deletions(-) diff --git a/components/freertos/event_groups.c b/components/freertos/event_groups.c index f4be8973ae..d5f6ddba60 100644 --- a/components/freertos/event_groups.c +++ b/components/freertos/event_groups.c @@ -217,6 +217,9 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, { EventBits_t uxOriginalBitValue, uxReturn; EventGroup_t * pxEventBits = xEventGroup; +#ifndef ESP_PLATFORM + BaseType_t xAlreadyYielded; +#endif // ESP_PLATFORM BaseType_t xTimeoutOccurred = pdFALSE; configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); @@ -227,7 +230,11 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, } #endif +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { uxOriginalBitValue = pxEventBits->uxEventBits; @@ -270,11 +277,26 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, } } } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM if( xTicksToWait != ( TickType_t ) 0 ) { +#ifdef ESP_PLATFORM portYIELD_WITHIN_API(); +#else + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM /* The task blocked to wait for its required bits to be set - at this * point either the required bits were set or the block time expired. If @@ -333,7 +355,11 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, { EventGroup_t * pxEventBits = xEventGroup; EventBits_t uxReturn, uxControlBits = 0; +#ifdef ESP_PLATFORM BaseType_t xWaitConditionMet; +#else + BaseType_t xWaitConditionMet, xAlreadyYielded; +#endif // ESP_PLATFORM BaseType_t xTimeoutOccurred = pdFALSE; /* Check the user is not attempting to wait on the bits used by the kernel @@ -347,7 +373,11 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, } #endif +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; @@ -415,11 +445,26 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); } } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM if( xTicksToWait != ( TickType_t ) 0 ) { +#ifdef ESP_PLATFORM portYIELD_WITHIN_API(); +#else + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM /* The task blocked to wait for its required bits to be set - at this * point either the required bits were set or the block time expired. If @@ -551,7 +596,11 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, pxList = &( pxEventBits->xTasksWaitingForBits ); pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); @@ -623,7 +672,11 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, * bit was set in the control word. */ pxEventBits->uxEventBits &= ~uxBitsToClear; } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM return pxEventBits->uxEventBits; } @@ -636,6 +689,7 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) traceEVENT_GROUP_DELETE( xEventGroup ); + // IDF-3755 taskENTER_CRITICAL(); { while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index ce832f6c26..1d9a5cd842 100644 --- a/components/freertos/include/freertos/portable.h +++ b/components/freertos/include/freertos/portable.h @@ -210,6 +210,21 @@ BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; */ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if ( portUSING_MPU_WRAPPERS == 1 ) + struct xMEMORY_REGION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; +#endif + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/components/freertos/include/freertos/semphr.h b/components/freertos/include/freertos/semphr.h index d692375e65..18a051419c 100644 --- a/components/freertos/include/freertos/semphr.h +++ b/components/freertos/include/freertos/semphr.h @@ -312,6 +312,16 @@ typedef QueueHandle_t SemaphoreHandle_t; #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) ) /** + * @cond + * semphr. h + * @code{c} + * xSemaphoreTakeRecursive( + * SemaphoreHandle_t xMutex, + * TickType_t xBlockTime + * ); + * @endcode + * @endcond + * * Macro to recursively obtain, or 'take', a mutex type semaphore. * The mutex must have previously been created using a call to * xSemaphoreCreateRecursiveMutex(); @@ -400,6 +410,7 @@ typedef QueueHandle_t SemaphoreHandle_t; */ #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) +#ifdef ESP_PLATFORM // IDF-3814 /** @cond */ /* * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). @@ -415,7 +426,7 @@ typedef QueueHandle_t SemaphoreHandle_t; */ #define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) /** @endcond */ - +#endif // ESP_PLATFORM /** * Macro to release a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or @@ -568,6 +579,7 @@ typedef QueueHandle_t SemaphoreHandle_t; */ #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) +#ifdef ESP_PLATFORM // IDF-3814 /** @cond */ /* * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). @@ -584,6 +596,7 @@ typedef QueueHandle_t SemaphoreHandle_t; #define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) /** @endcond */ +#endif // ESP_PLATFORM /** * Macro to release a semaphore. The semaphore must have previously been diff --git a/components/freertos/include/freertos/stdint.readme b/components/freertos/include/freertos/stdint.readme index 4414c29ed2..20a8d663ef 100644 --- a/components/freertos/include/freertos/stdint.readme +++ b/components/freertos/include/freertos/stdint.readme @@ -1,3 +1,28 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ #ifndef FREERTOS_STDINT #define FREERTOS_STDINT @@ -10,7 +35,7 @@ * To use this file: * * 1) Copy this file into the directory that contains your FreeRTOSConfig.h - * header file, as that directory will already be in the compilers include + * header file, as that directory will already be in the compiler's include * path. * * 2) Rename the copied file stdint.h. diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 8d525f244b..22b84f053c 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -605,7 +605,16 @@ typedef enum } #endif /* configSUPPORT_STATIC_ALLOCATION */ -/* +/** + * @cond + * task. h + * @code{c} + * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask ); + * @endcode + * @endcond + * + * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. + * * xTaskCreateRestricted() should only be used in systems that include an MPU * implementation. * @@ -678,12 +687,19 @@ typedef enum TaskHandle_t * pxCreatedTask ); #endif -/* - * xTaskCreateRestrictedStatic() should only be used in systems that include an - * MPU implementation. +/** + * @cond + * task. h + * @code{c} + * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask ); + * @endcode + * @endcond * * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. * + * xTaskCreateRestrictedStatic() should only be used in systems that include an + * MPU implementation. + * * Internally, within the FreeRTOS implementation, tasks use two blocks of * memory. The first block is used to hold the task's data structures. The * second block is used by the task as its stack. If a task is created using @@ -762,7 +778,7 @@ typedef enum */ #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ); + TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; #endif /** @@ -820,8 +836,12 @@ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; /** - * Remove a task from the RTOS real time kernel's management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. + * @cond + * task. h + * @code{c} + * void vTaskDelete( TaskHandle_t xTask ); + * @endcode + * @endcond * * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. * See the configuration section for more information. @@ -1215,7 +1235,12 @@ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; /** - * Suspend a task. + * @cond + * task. h + * @code{c} + * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); + * @endcode + * @endcond * * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * See the configuration section for more information. @@ -1322,11 +1347,18 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; /** - * An implementation of vTaskResume() that can be called from within an ISR. + * @cond + * task. h + * @code{c} + * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); + * @endcode + * @endcond * * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be * available. See the configuration section for more information. * + * An implementation of vTaskResume() that can be called from within an ISR. + * * A task that has been suspended by one or more calls to vTaskSuspend () * will be made available for running again by a single call to * xTaskResumeFromISR (). @@ -1354,14 +1386,20 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; *----------------------------------------------------------*/ /** @cond */ /** - * Starts the real time kernel tick processing. + * @cond + * task. h + * @code{c} + * void vTaskStartScheduler( void ); + * @endcode + * @endcond * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. + * NOTE: In ESP-IDF the scheduler is started automatically during * application startup, vTaskStartScheduler() should not be called from * ESP-IDF applications. * - * After calling the kernel has control over which tasks are executed and when. - * * See the demo application file main.c for an example of creating * tasks and starting the kernel. * @@ -1387,7 +1425,12 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; /** - * Stops the real time kernel tick. + * @cond + * task. h + * @code{c} + * void vTaskEndScheduler( void ); + * @endcode + * @endcond * * NOTE: At the time of writing only the x86 real mode port, which runs on a PC * in place of DOS, implements this function. @@ -1446,9 +1489,15 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; /** @endcond */ /** - * Suspends the scheduler without disabling interrupts. + * @cond + * task. h + * @code{c} + * void vTaskSuspendAll( void ); + * @endcode + * @endcond * - * Context switches will not occur while the scheduler is suspended. + * Suspends the scheduler without disabling interrupts. Context switches will + * not occur while the scheduler is suspended. * * After calling vTaskSuspendAll () the calling task will continue to execute * without risk of being swapped out until a call to xTaskResumeAll () has been @@ -1561,7 +1610,12 @@ BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; *----------------------------------------------------------*/ /** - * Get tick count + * @cond + * task. h + * @code{c} + * TickType_t xTaskGetTickCount( void ); + * @endcode + * @endcond * * @return The count of ticks since vTaskStartScheduler was called. * @@ -1573,7 +1627,12 @@ BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; /** - * Get tick count from ISR + * @cond + * task. h + * @code{c} + * TickType_t xTaskGetTickCountFromISR( void ); + * @endcode + * @endcond * * @return The count of ticks since vTaskStartScheduler was called. * @@ -1590,7 +1649,12 @@ TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; /** - * Get current number of tasks + * @cond + * task. h + * @code{c} + * uint16_t uxTaskGetNumberOfTasks( void ); + * @endcode + * @endcond * * @return The number of tasks that the real time kernel is currently managing. * This includes all ready, blocked and suspended tasks. A task that @@ -1605,7 +1669,12 @@ TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; /** - * Get task name + * @cond + * task. h + * @code{c} + * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); + * @endcode + * @endcond * * @return The text (human readable) name of the task referenced by the handle * xTaskToQuery. A task can query its own name by either passing in its own @@ -1616,10 +1685,17 @@ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; * @endcond * \ingroup TaskUtils */ -char *pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** - * @note This function takes a relatively long time to complete and should be + * @cond + * task. h + * @code{c} + * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); + * @endcode + * @endcond + * + * NOTE: This function takes a relatively long time to complete and should be * used sparingly. * * @return The handle of the task that has the human readable name pcNameToQuery. diff --git a/components/freertos/queue.c b/components/freertos/queue.c index 712fbd2119..299b15118b 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -975,7 +975,11 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -998,22 +1002,36 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, * task is already in the ready list before it yields - in which * case the yield will not cause a context switch unless there * is also a higher priority task in the pending ready list. */ +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); - portYIELD_WITHIN_API(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } } else { /* Try again. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM } } else { /* The timeout has expired. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM traceQUEUE_SEND_FAILED( pxQueue ); return errQUEUE_FULL; @@ -1440,7 +1458,11 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -1453,15 +1475,31 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); - portYIELD_WITHIN_API(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM } else { /* The queue contains data again. Loop back to try and read the * data. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM } } else @@ -1469,7 +1507,11 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /* Timed out. If there is no data in the queue exit, otherwise loop * back and attempt to read the data. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { @@ -1605,7 +1647,11 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, /* Interrupts and other tasks can give to and take from the semaphore * now the critical section has been exited. */ +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -1627,7 +1673,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, { xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); } - taskEXIT_CRITICAL(); + taskEXIT_CRITICAL(); } else { @@ -1638,22 +1684,42 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); - portYIELD_WITHIN_API(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM } else { /* There was no timeout and the semaphore count was not 0, so * attempt to take the semaphore again. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM } } else { /* Timed out. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM /* If the semaphore count is 0 exit now as the timeout has * expired. Otherwise return to attempt to take the semaphore that is @@ -1772,7 +1838,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, { /* The queue was empty and no block time is specified (or * the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); + taskEXIT_CRITICAL(); traceQUEUE_PEEK_FAILED( pxQueue ); return errQUEUE_EMPTY; } @@ -1796,7 +1862,11 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /* Interrupts and other tasks can send to and receive from the queue * now the critical section has been exited. */ +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ @@ -1809,15 +1879,31 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, traceBLOCKING_ON_QUEUE_PEEK( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); - portYIELD_WITHIN_API(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM } else { /* There is data in the queue now, so don't enter the blocked * state, instead return to try and obtain the data. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM } } else @@ -1825,7 +1911,11 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /* The timeout has expired. If there is still no data in the queue * exit, otherwise go back and try to read the data again. */ prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { diff --git a/components/freertos/stream_buffer.c b/components/freertos/stream_buffer.c index 00ea670238..e989643033 100644 --- a/components/freertos/stream_buffer.c +++ b/components/freertos/stream_buffer.c @@ -64,7 +64,9 @@ * or #defined the notification macros away, then provide default implementations * that uses task notifications. */ /*lint -save -e9026 Function like macros allowed and needed here so they can be overridden. */ + #ifndef sbRECEIVE_COMPLETED +#ifdef ESP_PLATFORM // IDF-3775 #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ taskENTER_CRITICAL(); \ { \ @@ -77,6 +79,20 @@ } \ } \ taskEXIT_CRITICAL(); +#else + #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ + vTaskSuspendAll(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ + } \ + } \ + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM #endif /* sbRECEIVE_COMPLETED */ #ifndef sbRECEIVE_COMPLETED_FROM_ISR @@ -104,6 +120,7 @@ * or #defined the notification macro away, them provide a default implementation * that uses task notifications. */ #ifndef sbSEND_COMPLETED +#ifdef ESP_PLATFORM // IDF-3755 #define sbSEND_COMPLETED( pxStreamBuffer ) \ taskENTER_CRITICAL(); \ { \ @@ -116,6 +133,20 @@ } \ } \ taskEXIT_CRITICAL(); +#else + #define sbSEND_COMPLETED( pxStreamBuffer ) \ + vTaskSuspendAll(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ + } \ + } \ + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM #endif /* sbSEND_COMPLETED */ #ifndef sbSEND_COMPLETE_FROM_ISR @@ -163,7 +194,9 @@ typedef struct StreamBufferDef_t /*lint !e9058 Style convention #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */ #endif +#ifdef ESP_PLATFORM portMUX_TYPE xStreamBufferMux; //Mutex required due to SMP +#endif // ESP_PLATFORM } StreamBuffer_t; /* @@ -539,6 +572,10 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, size_t xRequiredSpace = xDataLengthBytes; TimeOut_t xTimeOut; + /* The maximum amount of space a stream buffer will ever report is its length + * minus 1. */ + const size_t xMaxReportedSpace = pxStreamBuffer->xLength - ( size_t ) 1; + configASSERT( pvTxData ); configASSERT( pxStreamBuffer ); @@ -552,10 +589,33 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, /* Overflow? */ configASSERT( xRequiredSpace > xDataLengthBytes ); + + /* If this is a message buffer then it must be possible to write the + * whole message. */ + if( xRequiredSpace > xMaxReportedSpace ) + { + /* The message would not fit even if the entire buffer was empty, + * so don't wait for space. */ + xTicksToWait = ( TickType_t ) 0; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { - mtCOVERAGE_TEST_MARKER(); + /* If this is a stream buffer then it is acceptable to write only part + * of the message to the buffer. Cap the length to the total length of + * the buffer. */ + if( xRequiredSpace > xMaxReportedSpace ) + { + xRequiredSpace = xMaxReportedSpace; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } if( xTicksToWait != ( TickType_t ) 0 ) @@ -1266,7 +1326,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, pxStreamBuffer->xLength = xBufferSizeBytes; pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes; pxStreamBuffer->ucFlags = ucFlags; +#ifdef ESP_PLATFORM vPortCPUInitializeMutex( &pxStreamBuffer->xStreamBufferMux ); +#endif // ESP_PLATFORM } #if ( configUSE_TRACE_FACILITY == 1 ) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 4b02759566..bebd18f90b 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -576,7 +576,7 @@ static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, * Set xNextTaskUnblockTime to the time at which the next Blocked state task * will exit the Blocked state. */ -static void prvResetNextTaskUnblockTime( void ); +static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION; #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) @@ -671,15 +671,15 @@ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) configASSERT( portVALID_STACK_MEM(pxStackBuffer) ); configASSERT( (xCoreID>=0 && xCoreID ( TickType_t ) 0U ) { configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { traceTASK_DELAY(); @@ -1538,7 +1543,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * executing task. */ prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToDelay ); } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM } else { @@ -2716,7 +2725,11 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { /* Search the ready lists. */ do @@ -2762,7 +2775,11 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char } #endif } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM return pxTCB; } @@ -2778,7 +2795,11 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char { UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) @@ -2837,7 +2858,11 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char mtCOVERAGE_TEST_MARKER(); } } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM return uxTask; } @@ -2887,7 +2912,11 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) { +#ifdef ESP_PLATFORM BaseType_t xYieldRequired = pdFALSE; +#else + BaseType_t xYieldOccurred; +#endif // ESP_PLATFORM /* Must not be called with the scheduler suspended as the implementation * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */ @@ -2895,11 +2924,20 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */ +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM xPendedTicks += xTicksToCatchUp; +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); - return xYieldRequired; +#else + xYieldOccurred = xTaskResumeAll(); + + return xYieldOccurred; +#endif // ESP_PLATFORM } /*----------------------------------------------------------*/ @@ -2912,7 +2950,11 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) configASSERT( pxTCB ); +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { /* A task can only be prematurely removed from the Blocked state if * it is actually in the Blocked state. */ @@ -2975,7 +3017,11 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) xReturn = pdFAIL; } } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM return xReturn; } @@ -3889,7 +3935,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { +#ifdef ESP_PLATFORM // IDF-3755 taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { /* Now the scheduler is suspended, the expected idle * time can be sampled again, and this time its value can @@ -3913,7 +3963,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) mtCOVERAGE_TEST_MARKER(); } } +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM } else { @@ -4214,14 +4268,22 @@ static void prvCheckTasksWaitingTermination( void ) * it should be reported as being in the Blocked state. */ if( eState == eSuspended ) { - taskENTER_CRITICAL(); +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { pxTaskStatus->eCurrentState = eBlocked; } } - taskEXIT_CRITICAL(); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM } } #endif /* INCLUDE_vTaskSuspend */ diff --git a/components/freertos/timers.c b/components/freertos/timers.c index 76fc364fb6..da338c286e 100644 --- a/components/freertos/timers.c +++ b/components/freertos/timers.c @@ -608,7 +608,11 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; TickType_t xTimeNow; BaseType_t xTimerListsWereSwitched; +#ifdef ESP_PLATFORM taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { /* Obtain the time now to make an assessment as to whether the timer * has expired or not. If obtaining the time causes the lists to switch @@ -622,7 +626,11 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; /* The tick count has not overflowed, has the timer expired? */ if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) { +#ifdef ESP_PLATFORM taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); } else @@ -642,19 +650,33 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty ); +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); - - /* Yield to wait for either a command to arrive, or the - * block time to expire. If a command arrived between the - * critical section being exited and this yield then the yield - * will not cause the task to block. */ - portYIELD_WITHIN_API(); - +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + /* Yield to wait for either a command to arrive, or the + * block time to expire. If a command arrived between the + * critical section being exited and this yield then the yield + * will not cause the task to block. */ + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM // IDF-3755 + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM } } else { +#ifdef ESP_PLATFORM // IDF-3755 taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM } } } @@ -986,8 +1008,8 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; { /* The timer queue is allocated statically in case * configSUPPORT_DYNAMIC_ALLOCATION is 0. */ - static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ - static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ + PRIVILEGED_DATA static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ + PRIVILEGED_DATA static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue ); } From e0d29d4adadf79f9594b1ce84b4ec87b76a27daa Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 6 Aug 2021 20:48:19 +0530 Subject: [PATCH 117/310] esp_system: create ld template to abstract few common settings PMS aware chips require prefetch padding size for instruction fetch, or some memory alignment considerations. These settings are now exposed through kconfig options (hidden) and used through common ld template. This shall help to add and manage future chips support easily for these considerations. Closes IDF-3624 --- components/esp_system/Kconfig | 22 ++++++++++++++++- components/esp_system/component.mk | 2 +- components/esp_system/ld/esp32/memory.ld.in | 1 + components/esp_system/ld/esp32/sections.ld.in | 2 +- components/esp_system/ld/esp32c3/memory.ld.in | 7 ++++++ .../esp_system/ld/esp32c3/sections.ld.in | 14 +++++++---- components/esp_system/ld/esp32h2/memory.ld.in | 7 ++++++ .../esp_system/ld/esp32h2/sections.ld.in | 11 +++++++-- components/esp_system/ld/esp32s2/memory.ld.in | 1 + .../esp_system/ld/esp32s2/sections.ld.in | 10 ++++++-- components/esp_system/ld/esp32s3/memory.ld.in | 1 + .../esp_system/ld/esp32s3/sections.ld.in | 14 +++++++++-- components/esp_system/ld/ld.cmake | 3 ++- components/esp_system/ld/ld.common | 24 +++++++++++++++++++ 14 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 components/esp_system/ld/ld.common diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 7a03588903..27ce305750 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -113,9 +113,15 @@ menu "ESP System Settings" menu "Memory protection" + config ESP_SYSTEM_MEMPROT_DEPCHECK + bool + default y if IDF_TARGET_ESP32S2 + default y if IDF_TARGET_ESP32C3 + default y if IDF_TARGET_ESP32H2 + config ESP_SYSTEM_MEMPROT_FEATURE bool "Enable memory protection" - depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2 + depends on ESP_SYSTEM_MEMPROT_DEPCHECK default "y" help If enabled, the permission control module watches all the memory access and fires the panic handler @@ -133,6 +139,20 @@ menu "ESP System Settings" Once locked, memory protection settings cannot be changed anymore. The lock is reset only on the chip startup. + config ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE + # Hidden option for linker script usage + int + depends on ESP_SYSTEM_MEMPROT_DEPCHECK + default 16 + + config ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE + # Hidden option for linker script usage + int + depends on ESP_SYSTEM_MEMPROT_DEPCHECK + default 4 if IDF_TARGET_ESP32S2 + default 256 if IDF_TARGET_ESP32S3 + default 512 + endmenu # Memory protection config ESP_SYSTEM_EVENT_QUEUE_SIZE diff --git a/components/esp_system/component.mk b/components/esp_system/component.mk index 6f603f880b..c67e3064e1 100644 --- a/components/esp_system/component.mk +++ b/components/esp_system/component.mk @@ -53,7 +53,7 @@ $(COMPONENT_LIBRARY): $(ld_output) $(ld_output): $(ld_input) ../include/sdkconfig.h mkdir -p $(COMPONENT_BUILD_DIR)/ld - $(CC) -I ../include -C -P -x c -E $< -o $@ + $(CC) -I ../include -I $(COMPONENT_PATH)/ld -C -P -x c -E $< -o $@ COMPONENT_EXTRA_CLEAN := $(ld_output) $(sections_ld) endif diff --git a/components/esp_system/ld/esp32/memory.ld.in b/components/esp_system/ld/esp32/memory.ld.in index 9a8af9e096..798076ab1c 100644 --- a/components/esp_system/ld/esp32/memory.ld.in +++ b/components/esp_system/ld/esp32/memory.ld.in @@ -20,6 +20,7 @@ to simple macros with numeric values, and/or #if/#endif blocks. */ #include "sdkconfig.h" +#include "ld.common" /* If BT is not built at all */ #ifndef CONFIG_BT_RESERVE_DRAM diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index 2277dec6e1..c2a6c66c5b 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -349,7 +349,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _etext = .; diff --git a/components/esp_system/ld/esp32c3/memory.ld.in b/components/esp_system/ld/esp32c3/memory.ld.in index 66bf5d9ac4..d387915f93 100644 --- a/components/esp_system/ld/esp32c3/memory.ld.in +++ b/components/esp_system/ld/esp32c3/memory.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /** * ESP32-C3 Linker Script Memory Layout * This file describes the memory layout (memory blocks) by virtual memory addresses. @@ -7,6 +13,7 @@ */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index a4e41e7123..96b0bdd346 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point */ ENTRY(call_start_cpu0); @@ -228,7 +234,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _instruction_reserved_end = ABSOLUTE(.); @@ -368,9 +374,9 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - /* C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ - . += 16; - . = ALIGN (0x200); + /* ESP32-C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); /* iram_end_test section exists for use by memprot unit tests only */ *(.iram_end_test) _iram_text_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32h2/memory.ld.in b/components/esp_system/ld/esp32h2/memory.ld.in index 58ab761a0e..03f45cabd9 100644 --- a/components/esp_system/ld/esp32h2/memory.ld.in +++ b/components/esp_system/ld/esp32h2/memory.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /** * ESP32-H2 Linker Script Memory Layout * This file describes the memory layout (memory blocks) by virtual memory addresses. @@ -7,6 +13,7 @@ */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index 65eb17b45c..eaf8a5a41b 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point */ ENTRY(call_start_cpu0); @@ -365,8 +371,9 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - /* C3 memprot requires 512 B alignment for split lines */ - . = ALIGN (0x200); + /* ESP32-H2 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); /* iram_end_test section exists for use by memprot unit tests only */ *(.iram_end_test) _iram_text_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s2/memory.ld.in b/components/esp_system/ld/esp32s2/memory.ld.in index d4c50f4253..f40fca87a4 100644 --- a/components/esp_system/ld/esp32s2/memory.ld.in +++ b/components/esp_system/ld/esp32s2/memory.ld.in @@ -13,6 +13,7 @@ Restrict to simple macros with numeric values, and/or #if/#endif blocks. */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index 3c6bbe87ed..2bbfdad5ce 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point: */ ENTRY(call_start_cpu0); @@ -177,7 +183,7 @@ SECTIONS _coredump_iram_end = 0; /* align + add 16B for CPU dummy speculative instr. fetch */ - . = ALIGN(4) + 16; + . = ALIGN(_esp_memprot_align_size) + _esp_memprot_prefetch_pad_size; /* iram_end_test section exists for use by memprot unit tests only */ *(.iram_end_test) _iram_text_end = ABSOLUTE(.); @@ -363,7 +369,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _instruction_reserved_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s3/memory.ld.in b/components/esp_system/ld/esp32s3/memory.ld.in index 79dcd53487..4f6b70d490 100644 --- a/components/esp_system/ld/esp32s3/memory.ld.in +++ b/components/esp_system/ld/esp32s3/memory.ld.in @@ -12,6 +12,7 @@ */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index 02246b3f9d..7ef4075a31 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point */ ENTRY(call_start_cpu0); @@ -264,7 +270,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _instruction_reserved_end = ABSOLUTE(.); @@ -376,7 +382,11 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN (4); + /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and 256B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); + /* iram_end_test section exists for use by memprot unit tests only */ + *(.iram_end_test) _iram_text_end = ABSOLUTE(.); } > iram0_0_seg diff --git a/components/esp_system/ld/ld.cmake b/components/esp_system/ld/ld.cmake index 93376b69c1..5e80268da7 100644 --- a/components/esp_system/ld/ld.cmake +++ b/components/esp_system/ld/ld.cmake @@ -22,7 +22,8 @@ idf_build_get_property(config_dir CONFIG_DIR) # Preprocess memory.ld.in linker script to include configuration, becomes memory.ld add_custom_command( OUTPUT ${ld_output} - COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o ${ld_output} -I ${config_dir} ${ld_input} + COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o ${ld_output} -I ${config_dir} + -I "${CMAKE_CURRENT_LIST_DIR}" ${ld_input} MAIN_DEPENDENCY ${ld_input} DEPENDS ${sdkconfig_header} COMMENT "Generating memory.ld linker script..." diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common new file mode 100644 index 0000000000..974cafe5d4 --- /dev/null +++ b/components/esp_system/ld/ld.common @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" + +/* CPU instruction prefetch padding size for flash mmap scenario */ +_esp_flash_mmap_prefetch_pad_size = 16; + +/* CPU instruction prefetch padding size for memory protection scenario */ +#ifdef CONFIG_ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE +_esp_memprot_prefetch_pad_size = CONFIG_ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE; +#else +_esp_memprot_prefetch_pad_size = 0; +#endif + +/* Memory alignment size for PMS */ +#ifdef CONFIG_ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE +_esp_memprot_align_size = CONFIG_ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE; +#else +_esp_memprot_align_size = 0; +#endif From 704a09255027bb2983a3ffb1e7792c72a68721f8 Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Thu, 2 Sep 2021 18:01:08 +0800 Subject: [PATCH 118/310] freertos: upgrade to 10.4.3 - xTaskDelayUntil change and a few minor changes --- .../freertos/include/freertos/FreeRTOS.h | 38 +++++++++++---- components/freertos/include/freertos/queue.h | 29 ++++++++++-- components/freertos/include/freertos/task.h | 46 ++++++++++++++----- components/freertos/linker.lf | 1 + components/freertos/tasks.c | 42 +++++++++++++++-- 5 files changed, 128 insertions(+), 28 deletions(-) diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h index 0b0fce99dc..b311f53b1f 100644 --- a/components/freertos/include/freertos/FreeRTOS.h +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -53,12 +53,13 @@ #endif /* *INDENT-ON* */ +#ifdef ESP_PLATFORM /* for likely and unlikely */ #include "esp_compiler.h" +#endif // ESP_PLATFORM /* Application specific configuration options. */ #include "freertos/FreeRTOSConfig.h" - /* Basic FreeRTOS definitions. */ #include "projdefs.h" @@ -129,8 +130,28 @@ #define INCLUDE_vTaskSuspend 0 #endif -#ifndef INCLUDE_vTaskDelayUntil - #define INCLUDE_vTaskDelayUntil 0 +#ifdef INCLUDE_xTaskDelayUntil + #ifdef INCLUDE_vTaskDelayUntil + /* INCLUDE_vTaskDelayUntil was replaced by INCLUDE_xTaskDelayUntil. Backward + * compatibility is maintained if only one or the other is defined, but + * there is a conflict if both are defined. */ + #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed + #endif +#endif + +#ifndef INCLUDE_xTaskDelayUntil + #ifdef INCLUDE_vTaskDelayUntil + /* If INCLUDE_vTaskDelayUntil is set but INCLUDE_xTaskDelayUntil is not then + * the project's FreeRTOSConfig.h probably pre-dates the introduction of + * xTaskDelayUntil and setting INCLUDE_xTaskDelayUntil to whatever + * INCLUDE_vTaskDelayUntil is set to will ensure backward compatibility. + */ + #define INCLUDE_xTaskDelayUntil INCLUDE_vTaskDelayUntil + #endif +#endif + +#ifndef INCLUDE_xTaskDelayUntil + #define INCLUDE_xTaskDelayUntil 0 #endif #ifndef INCLUDE_vTaskDelay @@ -888,12 +909,14 @@ #endif #ifndef configSTACK_DEPTH_TYPE + /* Defaults to uint16_t for backward compatibility, but can be overridden * in FreeRTOSConfig.h if uint16_t is too restrictive. */ #define configSTACK_DEPTH_TYPE uint16_t #endif #ifndef configMESSAGE_BUFFER_LENGTH_TYPE + /* Defaults to size_t for backward compatibility, but can be overridden * in FreeRTOSConfig.h if lengths will always be less than the number of bytes * in a size_t. */ @@ -920,6 +943,7 @@ #endif #if ( portTICK_TYPE_IS_ATOMIC == 0 ) + /* Either variables of tick type cannot be read atomically, or * portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when * the tick count is returned to the standard critical section macros. */ @@ -1005,9 +1029,11 @@ #define pxContainer pvContainer #endif /* configENABLE_BACKWARD_COMPATIBILITY */ +#ifdef ESP_PLATFORM #ifndef configESP32_PER_TASK_DATA #define configESP32_PER_TASK_DATA 1 #endif +#endif // ESP_PLATFORM #if ( configUSE_ALTERNATIVE_API != 0 ) #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 @@ -1246,9 +1272,7 @@ typedef struct xSTATIC_QUEUE UBaseType_t uxDummy8; uint8_t ucDummy9; #endif - portMUX_TYPE xDummy10; - } StaticQueue_t; typedef StaticQueue_t StaticSemaphore_t; @@ -1278,9 +1302,7 @@ typedef struct xSTATIC_EVENT_GROUP #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucDummy4; #endif - portMUX_TYPE xDummy5; - } StaticEventGroup_t; /* @@ -1332,9 +1354,7 @@ typedef struct xSTATIC_STREAM_BUFFER #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxDummy4; #endif - portMUX_TYPE xDummy5; - } StaticStreamBuffer_t; /* Message buffers are built on stream buffers. */ diff --git a/components/freertos/include/freertos/queue.h b/components/freertos/include/freertos/queue.h index 9ff31d7eb8..3464e65b2e 100644 --- a/components/freertos/include/freertos/queue.h +++ b/components/freertos/include/freertos/queue.h @@ -80,8 +80,30 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** @endcond */ /** - * Creates a new queue instance. This allocates the storage required by the - * new queue and returns a handle for the queue. + * @cond + * queue. h + * @code{c} + * QueueHandle_t xQueueCreate( + * UBaseType_t uxQueueLength, + * UBaseType_t uxItemSize + * ); + * @endcode + * @endcond + * + * Creates a new queue instance, and returns a handle by which the new queue + * can be referenced. + * + * Internally, within the FreeRTOS implementation, queues use two blocks of + * memory. The first block is used to hold the queue's data structures. The + * second block is used to hold items placed into the queue. If a queue is + * created using xQueueCreate() then both blocks of memory are automatically + * dynamically allocated inside the xQueueCreate() function. (see + * https://www.FreeRTOS.org/a00111.html). If a queue is created using + * xQueueCreateStatic() then the application writer must provide the memory that + * will get used by the queue. xQueueCreateStatic() therefore allows a queue to + * be created without using any dynamic memory allocation. + * + * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html * * @param uxQueueLength The maximum number of items that the queue can contain. * @@ -1562,7 +1584,8 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * preferably in ROM/Flash), not on the stack. */ #if ( configQUEUE_REGISTRY_SIZE > 0 ) - void vQueueAddToRegistry( QueueHandle_t xQueue, const char * pcQueueName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + void vQueueAddToRegistry( QueueHandle_t xQueue, + const char * pcQueueName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /** diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 8d525f244b..8f8f3545e5 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -867,7 +867,10 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; *----------------------------------------------------------*/ /** - * Delay a task for a given number of ticks. + * task. h + * @code{c} + * void vTaskDelay( const TickType_t xTicksToDelay ); + * @endcode * * Delay a task for a given number of ticks. The actual time that the * task remains blocked depends on the tick rate. The constant @@ -885,7 +888,7 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; * of controlling the frequency of a periodic task as the path taken through the * code, as well as other task and interrupt activity, will effect the frequency * at which vTaskDelay() gets called and therefore the time at which the task - * next executes. See vTaskDelayUntil() for an alternative API function designed + * next executes. See xTaskDelayUntil() for an alternative API function designed * to facilitate fixed frequency execution. It does this by specifying an * absolute time (rather than a relative time) at which the calling task should * unblock. @@ -917,9 +920,12 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; /** - * Delay a task until a specified time. + * task. h + * @code{c} + * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement ); + * @endcode * - * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available. * See the configuration section for more information. * * Delay a task until a specified time. This function can be used by periodic @@ -934,22 +940,26 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; * each time it executes]. * * Whereas vTaskDelay () specifies a wake time relative to the time at which the function - * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * is called, xTaskDelayUntil () specifies the absolute (exact) time at which it wishes to * unblock. * - * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. + * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a + * time specified in milliseconds with a resolution of one tick period. * * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the * task was last unblocked. The variable must be initialised with the current time * prior to its first use (see the example below). Following this the variable is - * automatically updated within vTaskDelayUntil (). + * automatically updated within xTaskDelayUntil (). * * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the * same xTimeIncrement parameter value will cause the task to execute with * a fixed interface period. * + * @return Value which can be used to check whether the task was actually delayed. + * Will be pdTRUE if the task way delayed and pdFALSE otherwise. A task will not + * be delayed if the next expected wake time is in the past. + * * Example usage: * @code{c} * // Perform an action every 10 ticks. @@ -957,15 +967,17 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; * { * TickType_t xLastWakeTime; * const TickType_t xFrequency = 10; + * BaseType_t xWasDelayed; * * // Initialise the xLastWakeTime variable with the current time. * xLastWakeTime = xTaskGetTickCount (); * for( ;; ) * { * // Wait for the next cycle. - * vTaskDelayUntil( &xLastWakeTime, xFrequency ); + * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); * - * // Perform action here. + * // Perform action here. xWasDelayed value can be used to determine + * // whether a deadline was missed if the code here took too long. * } * } * @endcode @@ -974,9 +986,19 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; * @endcond * \ingroup TaskCtrl */ -void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, +BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; +/* + * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not + * return a value. + */ +#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ +{ \ + ( void ) xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); \ +} + + /** * @cond * task. h diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index 23de74c1e7..4ae70fe789 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -34,6 +34,7 @@ entries: tasks: xTaskGetCurrentTaskHandleForCPU (default) tasks: vTaskDelete (default) tasks: vTaskDelayUntil (default) + tasks: xTaskDelayUntil (default) tasks: vTaskDelay (default) tasks: vTaskSuspend (default) tasks: xTaskResumeAll (default) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 4b02759566..011c9ea344 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -1440,19 +1440,36 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, #endif /* INCLUDE_vTaskDelete */ /*-----------------------------------------------------------*/ -#if ( INCLUDE_vTaskDelayUntil == 1 ) - +#if ( INCLUDE_xTaskDelayUntil == 1 ) +#ifdef ESP_PLATFORM + // backward binary compatibility - remove later + #undef vTaskDelayUntil void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) + { + xTaskDelayUntil(pxPreviousWakeTime, xTimeIncrement); + } +#endif // ESP_PLATFORM + + BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) { TickType_t xTimeToWake; +#ifdef ESP_PLATFORM BaseType_t xShouldDelay = pdFALSE; +#else + BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; +#endif // ESP_PLATFORM configASSERT( pxPreviousWakeTime ); configASSERT( ( xTimeIncrement > 0U ) ); configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); +#ifdef ESP_PLATFORM taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM { /* Minor optimisation. The tick count cannot change in this * block. */ @@ -1508,13 +1525,30 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, mtCOVERAGE_TEST_MARKER(); } } +#ifdef ESP_PLATFORM taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM - /* Force a reschedule, we may have put ourselves to sleep. */ + /* Force a reschedule if xTaskResumeAll has not already done so, we may + * have put ourselves to sleep. */ +#ifdef ESP_PLATFORM portYIELD_WITHIN_API(); +#else + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM + return xShouldDelay; } -#endif /* INCLUDE_vTaskDelayUntil */ +#endif /* INCLUDE_xTaskDelayUntil */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelay == 1 ) From 963836f49125427c8f026c7c3732af86be360efb Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 31 Aug 2021 14:14:04 +0800 Subject: [PATCH 119/310] Add USB Host Library API docs - This commit adds the API documentation for the USB Host Library. - Warnings about the beta API are also added. - usb_host_misc.h renamed to usb_helpers.h --- components/usb/CMakeLists.txt | 2 +- .../usb/{usb_host_misc.h => usb_helpers.h} | 24 +-- components/usb/include/usb/usb_host.h | 18 ++- components/usb/include/usb/usb_types_ch9.h | 150 ++++++++++-------- components/usb/include/usb/usb_types_stack.h | 8 +- .../usb/test/usb_host/msc_client_async_seq.c | 6 +- ...est_usb_host_misc.c => test_usb_helpers.c} | 36 ++--- .../usb/{usb_host_misc.c => usb_helpers.c} | 36 ++--- components/usb/usb_host.c | 8 +- components/usb/usbh.c | 2 +- docs/conf_common.py | 1 + docs/doxygen/Doxyfile_esp32s2 | 6 +- docs/doxygen/Doxyfile_esp32s3 | 6 +- docs/en/api-reference/peripherals/index.rst | 1 + .../en/api-reference/peripherals/usb_host.rst | 26 +++ .../zh_CN/api-reference/peripherals/index.rst | 3 +- .../api-reference/peripherals/usb_host.rst | 1 + 17 files changed, 199 insertions(+), 135 deletions(-) rename components/usb/include/usb/{usb_host_misc.h => usb_helpers.h} (80%) rename components/usb/test/usb_host/{test_usb_host_misc.c => test_usb_helpers.c} (91%) rename components/usb/{usb_host_misc.c => usb_helpers.c} (64%) create mode 100644 docs/en/api-reference/peripherals/usb_host.rst create mode 100644 docs/zh_CN/api-reference/peripherals/usb_host.rst diff --git a/components/usb/CMakeLists.txt b/components/usb/CMakeLists.txt index 50c5deb399..76aeb05ee7 100644 --- a/components/usb/CMakeLists.txt +++ b/components/usb/CMakeLists.txt @@ -6,7 +6,7 @@ set(priv_require) if(CONFIG_USB_OTG_SUPPORTED) list(APPEND srcs "hcd.c" "hub.c" - "usb_host_misc.c" + "usb_helpers.c" "usb_host.c" "usb_private.c" "usbh.c") diff --git a/components/usb/include/usb/usb_host_misc.h b/components/usb/include/usb/usb_helpers.h similarity index 80% rename from components/usb/include/usb/usb_host_misc.h rename to components/usb/include/usb/usb_helpers.h index ab04b471e2..d8405dd5fc 100644 --- a/components/usb/include/usb/usb_host_misc.h +++ b/components/usb/include/usb/usb_helpers.h @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + #pragma once #include @@ -28,7 +32,7 @@ extern "C" { * the current descriptor. On output, it is the offset of the returned descriptor. * @return usb_standard_desc_t* Next descriptor, NULL if end of configuration descriptor reached */ -const usb_standard_desc_t *usb_host_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset); +const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset); /** * @brief Get the next descriptor of a particular type @@ -43,7 +47,7 @@ const usb_standard_desc_t *usb_host_parse_next_descriptor(const usb_standard_des * the current descriptor. On output, it is the offset of the returned descriptor. * @return usb_standard_desc_t* Next descriptor, NULL if end descriptor is not found or configuration descriptor reached */ -const usb_standard_desc_t *usb_host_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset); +const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset); /** * @brief Get the number of alternate settings for a bInterfaceNumber @@ -55,7 +59,7 @@ const usb_standard_desc_t *usb_host_parse_next_descriptor_of_type(const usb_stan * @param[in] bInterfaceNumber Interface number * @return int The number of alternate settings that the interface has, -1 if bInterfaceNumber not found */ -int usb_host_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber); +int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber); /** * @brief Get a particular interface descriptor (using bInterfaceNumber and bAlternateSetting) @@ -63,7 +67,7 @@ int usb_host_parse_interface_number_of_alternate(const usb_config_desc_t *config * Given a full configuration descriptor, get a particular interface descriptor. * * @note To get the number of alternate settings for a particular bInterfaceNumber, call - * usb_host_parse_interface_number_of_alternate() + * usb_parse_interface_number_of_alternate() * * @param[in] config_desc Pointer to the start of a full configuration descriptor * @param[in] bInterfaceNumber Interface number @@ -71,7 +75,7 @@ int usb_host_parse_interface_number_of_alternate(const usb_config_desc_t *config * @param[out] offset Byte offset of the interface descriptor relative to the start of the configuration descriptor. Can be NULL. * @return const usb_intf_desc_t* Pointer to interface descriptor, NULL if not found. */ -const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset); +const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset); /** * @brief Get an endpoint descriptor within an interface descriptor @@ -88,10 +92,10 @@ const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_ * of the interface descriptor. On output, it is the offset of the endpoint descriptor. * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found. */ -const usb_ep_desc_t *usb_host_parse_endpoint_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset); +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset); /** - * @brief Get an endpoint descriptor based on the endpoint's address + * @brief Get an endpoint descriptor based on an endpoint's address * * Given a configuration descriptor, get an endpoint descriptor based on it's bEndpointAddress, bAlternateSetting, and * bInterfaceNumber. @@ -103,12 +107,12 @@ const usb_ep_desc_t *usb_host_parse_endpoint_by_index(const usb_intf_desc_t *int * @param[out] offset Byte offset of the endpoint descriptor relative to the start of the configuration descriptor. Can be NULL * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found. */ -const usb_ep_desc_t *usb_host_parse_endpoint_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset); +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset); // ------------------------------------------------------ Misc --------------------------------------------------------- /** - * @brief Round up to an integer multiple of an endpoint's MPS + * @brief Round up to an integer multiple of endpoint's MPS * * This is a convenience function to round up a size/length to an endpoint's MPS (Maximum packet size). This is useful * when calculating transfer or buffer lengths of IN endpoints. @@ -117,7 +121,7 @@ const usb_ep_desc_t *usb_host_parse_endpoint_by_address(const usb_config_desc_t * @param[in] mps MPS * @return int Round up integer multiple of MPS */ -static inline int usb_host_round_up_to_mps(int num_bytes, int mps) +static inline int usb_round_up_to_mps(int num_bytes, int mps) { if (num_bytes < 0 || mps < 0) { return 0; diff --git a/components/usb/include/usb/usb_host.h b/components/usb/include/usb/usb_host.h index dbc38bd385..6c104af6cf 100644 --- a/components/usb/include/usb/usb_host.h +++ b/components/usb/include/usb/usb_host.h @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + #pragma once #include @@ -11,7 +15,7 @@ #include "esp_err.h" #include "esp_intr_alloc.h" //Include the other USB Host Library headers as well -#include "usb/usb_host_misc.h" +#include "usb/usb_helpers.h" #include "usb/usb_types_ch9.h" #include "usb/usb_types_stack.h" @@ -197,7 +201,7 @@ esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_ * @brief Close a device * * - This function allows a client to close a device - * - A client must close a device after it has finished using the device + * - A client must close a device after it has finished using the device (claimed interfaces must also be released) * - A client must close all devices it has opened before deregistering * * @param[in] client_hdl Client handle @@ -225,7 +229,7 @@ esp_err_t usb_host_device_free_all(void); // ------------------- Cached Requests --------------------- /** - * @brief Get a device's information + * @brief Get device's information * * - This function gets some basic information of a device * - The device must be opened first before attempting to get its information @@ -241,7 +245,7 @@ esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *d // ----------------- Cached Descriptors -------------------- /** - * @brief Get a device's device descriptor + * @brief Get device's device descriptor * * - A client must call usb_host_device_open() first * - No control transfer is sent. The device's descriptor is cached on enumeration @@ -255,7 +259,7 @@ esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *d esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc); /** - * @brief Get a device's active configuration descriptor + * @brief Get device's active configuration descriptor * * - A client must call usb_host_device_open() first * - No control transfer is sent. The device's active configuration descriptor is cached on enumeration @@ -271,7 +275,7 @@ esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, con // ----------------------------------------------- Interface Functions ------------------------------------------------- /** - * @brief Function for a client to claim an device's interface + * @brief Function for a client to claim a device's interface * * - A client must claim a device's interface before attempting to communicate with any of its endpoints * - Once an interface is claimed by a client, it cannot be claimed by any other client. @@ -285,7 +289,7 @@ esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, con esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting); /** - * @brief Function for a client to release a device's interface + * @brief Function for a client to release a previously claimed interface * * - A client should release a device's interface after it no longer needs to communicate with the interface * - A client must release all of its interfaces of a device it has claimed before being able to close the device diff --git a/components/usb/include/usb/usb_types_ch9.h b/components/usb/include/usb/usb_types_ch9.h index 4fe31b342f..7d40bc46e0 100644 --- a/components/usb/include/usb/usb_types_ch9.h +++ b/components/usb/include/usb/usb_types_ch9.h @@ -5,12 +5,7 @@ */ /* -Note: This header file contains the types and macros belong/relate to the USB2.0 protocol and are HW implementation -and mode (i.e., Host or Device) agnostic. - -- On the USB Host Stack, this header is only meant to be used on the HCD layer and above. For types and macros on the - Host stack that are HW implementation specific (i.e., HAL layer and below), add them to the "hal/usb_types_private.h" - header instead. +Warning: The USB Host Library API is still a beta version and may be subject to change */ #pragma once @@ -28,15 +23,20 @@ extern "C" /** * @brief USB2.0 device states + * + * See Table 9-1 of USB2.0 specification for more details + * + * @note The USB_DEVICE_STATE_NOT_ATTACHED is not part of the USB2.0 specification, but is a catch all state for devices + * that need to be cleaned up after a sudden disconnection or port error. */ typedef enum { - USB_DEVICE_STATE_NOT_ATTACHED, //Not in the USB spec, but is a catch all state for devices that need to be cleaned up after a sudden disconnection or port error - USB_DEVICE_STATE_ATTACHED, - USB_DEVICE_STATE_POWERED, - USB_DEVICE_STATE_DEFAULT, - USB_DEVICE_STATE_ADDRESS, - USB_DEVICE_STATE_CONFIGURED, - USB_DEVICE_STATE_SUSPENDED, + USB_DEVICE_STATE_NOT_ATTACHED, /**< The device was previously configured or suspended, but is no longer attached (either suddenly disconnected or a port error) */ + USB_DEVICE_STATE_ATTACHED, /**< Device is attached to the USB, but is not powered. */ + USB_DEVICE_STATE_POWERED, /**< Device is attached to the USB and powered, but has not been reset. */ + USB_DEVICE_STATE_DEFAULT, /**< Device is attached to the USB and powered and has been reset, but has not been assigned a unique address. Device responds at the default address. */ + USB_DEVICE_STATE_ADDRESS, /**< Device is attached to the USB, powered, has been reset, and a unique device address has been assigned. Device is not configured. */ + USB_DEVICE_STATE_CONFIGURED, /**< Device is attached to the USB, powered, has been reset, has a unique address, is configured, and is not suspended. The host may now use the function provided by the device. */ + USB_DEVICE_STATE_SUSPENDED, /**< Device is, at minimum, attached to the USB and is powered and has not seen bus activity for 3 ms. It may also have a unique address and be configured for use. However, because the device is suspended, the host may not use the device’s function. */ } usb_device_state_t; /** @@ -85,14 +85,16 @@ typedef enum { /** * @brief Structure representing a USB control transfer setup packet + * + * See Table 9-2 of USB2.0 specification for more details */ typedef union { struct { - uint8_t bmRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; + uint8_t bmRequestType; /**< Characteristics of request */ + uint8_t bRequest; /**< Specific request */ + uint16_t wValue; /**< Word-sized field that varies according to request */ + uint16_t wIndex; /**< Word-sized field that varies according to request; typically used to pass an index or offset */ + uint16_t wLength; /**< Number of bytes to transfer if there is a data stage */ } __attribute__((packed)); uint8_t val[USB_SETUP_PACKET_SIZE]; } usb_setup_packet_t; @@ -220,14 +222,14 @@ _Static_assert(sizeof(usb_setup_packet_t) == USB_SETUP_PACKET_SIZE, "Size of usb #define USB_STANDARD_DESC_SIZE 2 /** - * @brief Dummy USB standard descriptor + * @brief USB standard descriptor * - * All USB standard descriptors start with these two bytes. Use this type traversing over descriptors + * All USB standard descriptors start with these two bytes. Use this type when traversing over configuration descriptors */ typedef union { struct { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< Descriptor Type */ } USB_DESC_ATTR; uint8_t val[USB_STANDARD_DESC_SIZE]; } usb_standard_desc_t; @@ -242,23 +244,25 @@ _Static_assert(sizeof(usb_standard_desc_t) == USB_STANDARD_DESC_SIZE, "Size of u /** * @brief Structure representing a USB device descriptor + * + * See Table 9-8 of USB2.0 specification for more details */ typedef union { struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< DEVICE Descriptor Type */ + uint16_t bcdUSB; /**< USB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H) */ + uint8_t bDeviceClass; /**< Class code (assigned by the USB-IF) */ + uint8_t bDeviceSubClass; /**< Subclass code (assigned by the USB-IF) */ + uint8_t bDeviceProtocol; /**< Protocol code (assigned by the USB-IF) */ + uint8_t bMaxPacketSize0; /**< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid) */ + uint16_t idVendor; /**< Vendor ID (assigned by the USB-IF) */ + uint16_t idProduct; /**< Product ID (assigned by the manufacturer) */ + uint16_t bcdDevice; /**< Device release number in binary-coded decimal */ + uint8_t iManufacturer; /**< Index of string descriptor describing manufacturer */ + uint8_t iProduct; /**< Index of string descriptor describing product */ + uint8_t iSerialNumber; /**< Index of string descriptor describing the device’s serial number */ + uint8_t bNumConfigurations; /**< Number of possible configurations */ } USB_DESC_ATTR; uint8_t val[USB_DEVICE_DESC_SIZE]; } usb_device_desc_t; @@ -307,19 +311,21 @@ _Static_assert(sizeof(usb_device_desc_t) == USB_DEVICE_DESC_SIZE, "Size of usb_d /** * @brief Structure representing a short USB configuration descriptor * + * See Table 9-10 of USB2.0 specification for more details + * * @note The full USB configuration includes all the interface and endpoint * descriptors of that configuration. */ typedef union { struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< CONFIGURATION Descriptor Type */ + uint16_t wTotalLength; /**< Total length of data returned for this configuration */ + uint8_t bNumInterfaces; /**< Number of interfaces supported by this configuration */ + uint8_t bConfigurationValue; /**< Value to use as an argument to the SetConfiguration() request to select this configuration */ + uint8_t iConfiguration; /**< Index of string descriptor describing this configuration */ + uint8_t bmAttributes; /**< Configuration characteristics */ + uint8_t bMaxPower; /**< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. */ } USB_DESC_ATTR; uint8_t val[USB_CONFIG_DESC_SIZE]; } usb_config_desc_t; @@ -345,14 +351,14 @@ _Static_assert(sizeof(usb_config_desc_t) == USB_CONFIG_DESC_SIZE, "Size of usb_c */ typedef union { struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bFirstInterface; - uint8_t bInterfaceCount; - uint8_t bFunctionClass; - uint8_t bFunctionSubClass; - uint8_t bFunctionProtocol; - uint8_t iFunction; + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< INTERFACE ASSOCIATION Descriptor Type */ + uint8_t bFirstInterface; /**< Interface number of the first interface that is associated with this function */ + uint8_t bInterfaceCount; /**< Number of contiguous interfaces that are associated with this function */ + uint8_t bFunctionClass; /**< Class code (assigned by USB-IF) */ + uint8_t bFunctionSubClass; /**< Subclass code (assigned by USB-IF) */ + uint8_t bFunctionProtocol; /**< Protocol code (assigned by USB-IF) */ + uint8_t iFunction; /**< Index of string descriptor describing this function */ } USB_DESC_ATTR; uint8_t val[USB_IAD_DESC_SIZE]; } usb_iad_desc_t; @@ -367,18 +373,20 @@ _Static_assert(sizeof(usb_iad_desc_t) == USB_IAD_DESC_SIZE, "Size of usb_iad_des /** * @brief Structure representing a USB interface descriptor + * + * See Table 9-12 of USB2.0 specification for more details */ typedef union { struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< INTERFACE Descriptor Type */ + uint8_t bInterfaceNumber; /**< Number of this interface. */ + uint8_t bAlternateSetting; /**< Value used to select this alternate setting for the interface identified in the prior field */ + uint8_t bNumEndpoints; /**< Number of endpoints used by this interface (excluding endpoint zero). */ + uint8_t bInterfaceClass; /**< Class code (assigned by the USB-IF) */ + uint8_t bInterfaceSubClass; /**< Subclass code (assigned by the USB-IF) */ + uint8_t bInterfaceProtocol; /**< Protocol code (assigned by the USB) */ + uint8_t iInterface; /**< Index of string descriptor describing this interface */ } USB_DESC_ATTR; uint8_t val[USB_INTF_DESC_SIZE]; } usb_intf_desc_t; @@ -393,15 +401,17 @@ _Static_assert(sizeof(usb_intf_desc_t) == USB_INTF_DESC_SIZE, "Size of usb_intf_ /** * @brief Structure representing a USB endpoint descriptor + * + * See Table 9-13 of USB2.0 specification for more details */ typedef union { struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< ENDPOINT Descriptor Type */ + uint8_t bEndpointAddress; /**< The address of the endpoint on the USB device described by this descriptor */ + uint8_t bmAttributes; /**< This field describes the endpoint’s attributes when it is configured using the bConfigurationValue. */ + uint16_t wMaxPacketSize; /**< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. */ + uint8_t bInterval; /**< Interval for polling Isochronous and Interrupt endpoints. Expressed in frames or microframes depending on the device operating speed (1 ms for Low-Speed and Full-Speed or 125 us for USB High-Speed and above). */ } USB_DESC_ATTR; uint8_t val[USB_EP_DESC_SIZE]; } usb_ep_desc_t; @@ -451,9 +461,9 @@ _Static_assert(sizeof(usb_ep_desc_t) == USB_EP_DESC_SIZE, "Size of usb_ep_desc_t */ typedef union { struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wData[1]; /* UTF-16LE encoded */ + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< STRING Descriptor Type */ + uint16_t wData[1]; /**< UTF-16LE encoded */ } USB_DESC_ATTR; uint8_t val[USB_STR_DESC_SIZE]; } usb_str_desc_t; diff --git a/components/usb/include/usb/usb_types_stack.h b/components/usb/include/usb/usb_types_stack.h index 0db75d3788..438c22d9ef 100644 --- a/components/usb/include/usb/usb_types_stack.h +++ b/components/usb/include/usb/usb_types_stack.h @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + #pragma once #include "usb/usb_types_ch9.h" @@ -101,7 +105,7 @@ typedef struct { * of the endpoint. * * @note For Bulk/Control/Interrupt IN transfers, the num_bytes must be a integer multiple of the endpoint's MPS - * @note This structure should be allocated via __insert_func_name__() + * @note This structure should be allocated via usb_host_transfer_alloc() * @note Once the transfer has be submitted, users should not modify the structure until the transfer has completed */ typedef struct usb_transfer_s usb_transfer_t; @@ -123,7 +127,7 @@ struct usb_transfer_s{ usb_device_handle_t device_handle; /**< Device handle */ uint8_t bEndpointAddress; /**< Endpoint Address */ usb_transfer_status_t status; /**< Status of the transfer */ - uint32_t timeout; /**< Timeout (in milliseconds) of the packet (currently not supported yet) */ + uint32_t timeout_ms; /**< Timeout (in milliseconds) of the packet (currently not supported yet) */ usb_transfer_cb_t callback; /**< Transfer callback */ void *context; /**< Context variable for transfer to associate transfer with something */ const int num_isoc_packets; /**< Only relevant to Isochronous. Number of service periods (i.e., intervals) to transfer data buffer over. */ diff --git a/components/usb/test/usb_host/msc_client_async_seq.c b/components/usb/test/usb_host/msc_client_async_seq.c index 6880e96ec7..7189f4cd61 100644 --- a/components/usb/test/usb_host/msc_client_async_seq.c +++ b/components/usb/test/usb_host/msc_client_async_seq.c @@ -143,7 +143,7 @@ void msc_client_async_seq_task(void *arg) usb_transfer_t *xfer_out = NULL; //Must be large enough to contain CBW and MSC reset control transfer usb_transfer_t *xfer_in = NULL; //Must be large enough to contain CSW and Data size_t out_worst_case_size = MAX(sizeof(mock_msc_bulk_cbw_t), sizeof(usb_setup_packet_t)); - size_t in_worst_case_size = usb_host_round_up_to_mps(MAX(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, sizeof(mock_msc_bulk_csw_t)), MOCK_MSC_SCSI_BULK_EP_MPS); + size_t in_worst_case_size = usb_round_up_to_mps(MAX(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, sizeof(mock_msc_bulk_csw_t)), MOCK_MSC_SCSI_BULK_EP_MPS); TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(out_worst_case_size, 0, &xfer_out)); TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(in_worst_case_size, 0, &xfer_in)); xfer_out->callback = msc_transfer_cb; @@ -207,7 +207,7 @@ void msc_client_async_seq_task(void *arg) } case TEST_STAGE_MSC_DATA: { ESP_LOGD(MSC_CLIENT_TAG, "Data"); - xfer_in->num_bytes = usb_host_round_up_to_mps(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, MOCK_MSC_SCSI_BULK_EP_MPS); + xfer_in->num_bytes = usb_round_up_to_mps(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, MOCK_MSC_SCSI_BULK_EP_MPS); xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); //Next stage set from transfer callback @@ -215,7 +215,7 @@ void msc_client_async_seq_task(void *arg) } case TEST_STAGE_MSC_CSW: { ESP_LOGD(MSC_CLIENT_TAG, "CSW"); - xfer_in->num_bytes = usb_host_round_up_to_mps(sizeof(mock_msc_bulk_csw_t), MOCK_MSC_SCSI_BULK_EP_MPS); + xfer_in->num_bytes = usb_round_up_to_mps(sizeof(mock_msc_bulk_csw_t), MOCK_MSC_SCSI_BULK_EP_MPS); xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); //Next stage set from transfer callback diff --git a/components/usb/test/usb_host/test_usb_host_misc.c b/components/usb/test/usb_host/test_usb_helpers.c similarity index 91% rename from components/usb/test/usb_host/test_usb_host_misc.c rename to components/usb/test/usb_host/test_usb_helpers.c index 465e7ca915..07f905a26c 100644 --- a/components/usb/test/usb_host/test_usb_host_misc.c +++ b/components/usb/test/usb_host/test_usb_helpers.c @@ -346,11 +346,11 @@ static void test_walk_desc(const usb_config_desc_t *config_desc) int offset = 0; const usb_standard_desc_t *cur_desc = (usb_standard_desc_t *)config_desc; for (int i = 0; i < TEST_NUM_INTF_DESC; i++) { - cur_desc = usb_host_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + cur_desc = usb_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); TEST_ASSERT_NOT_EQUAL(NULL, cur_desc); } //Attempting to look for another interface descriptor should result in NULL - cur_desc = usb_host_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + cur_desc = usb_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); TEST_ASSERT_EQUAL(NULL, cur_desc); } @@ -360,11 +360,11 @@ Test if the count of number of alternate descriptors is correct static void test_alt_intf_desc_count(const usb_config_desc_t *config_desc) { //bInterface 0 has no alternate interfaces - TEST_ASSERT_EQUAL(0, usb_host_parse_interface_number_of_alternate(config_desc, 0)); + TEST_ASSERT_EQUAL(0, usb_parse_interface_number_of_alternate(config_desc, 0)); //bInterface 1 has 1 alternate interface - TEST_ASSERT_EQUAL(1, usb_host_parse_interface_number_of_alternate(config_desc, 1)); + TEST_ASSERT_EQUAL(1, usb_parse_interface_number_of_alternate(config_desc, 1)); //Non existent bInterface 2 should return -1 - TEST_ASSERT_EQUAL(-1, usb_host_parse_interface_number_of_alternate(config_desc, 2)); + TEST_ASSERT_EQUAL(-1, usb_parse_interface_number_of_alternate(config_desc, 2)); } static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc) @@ -372,37 +372,37 @@ static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc) int offset_intf = 0; //Get bInterfaceNumber 0 (index 0) - const usb_intf_desc_t *intf_desc = usb_host_parse_interface(config_desc, 0, 0, &offset_intf); + const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, 0, 0, &offset_intf); TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); //Should only have one endpoint int offset_ep = offset_intf; - const usb_ep_desc_t *ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress); offset_ep = offset_intf; - ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); TEST_ASSERT_EQUAL(NULL, ep_desc); //Get bInterfaceNumber 1 alternate setting 0 offset_intf = 0; - intf_desc = usb_host_parse_interface(config_desc, 1, 0, &offset_intf); + intf_desc = usb_parse_interface_descriptor(config_desc, 1, 0, &offset_intf); TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); //Should have no endpoints offset_ep = offset_intf; - ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); TEST_ASSERT_EQUAL(NULL, ep_desc); //Get bInterfaceNumber 1 alternate setting 1 offset_intf = 0; - intf_desc = usb_host_parse_interface(config_desc, 1, 1, &offset_intf); + intf_desc = usb_parse_interface_descriptor(config_desc, 1, 1, &offset_intf); TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); //Should only have one endpoint offset_ep = offset_intf; - ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress); offset_ep = offset_intf; - ep_desc = usb_host_parse_endpoint_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); TEST_ASSERT_EQUAL(NULL, ep_desc); } @@ -410,26 +410,26 @@ static void test_parse_ep_by_address(const usb_config_desc_t *config_desc) { int offset_ep = 0; //Get bInterface 0 bAlternateSetting 0 EP 0x83 - const usb_ep_desc_t *ep_desc = usb_host_parse_endpoint_by_address(config_desc, 0, 0, 0x83, &offset_ep); + const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 0, 0, 0x83, &offset_ep); TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress); //Getting same EP address under different interface should return NULL offset_ep = 0; - ep_desc = usb_host_parse_endpoint_by_address(config_desc, 1, 0, 0x83, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 0, 0x83, &offset_ep); TEST_ASSERT_EQUAL(NULL, ep_desc); //Get bInterface 1 bAlternateSetting 1 EP 0x81 offset_ep = 0; - ep_desc = usb_host_parse_endpoint_by_address(config_desc, 1, 1, 0x81, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 1, 0x81, &offset_ep); TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress); //Getting same EP address under different interface should return NULL offset_ep = 0; - ep_desc = usb_host_parse_endpoint_by_address(config_desc, 1, 0, 0x81, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 0, 0x81, &offset_ep); TEST_ASSERT_EQUAL(NULL, ep_desc); } -TEST_CASE("Test USB Host descriptor parsing", "[usb_host][ignore]") +TEST_CASE("Test USB Helpers descriptor parsing", "[usb_host][ignore]") { const usb_config_desc_t *config_desc = (const usb_config_desc_t *)config_desc_bytes; test_walk_desc(config_desc); diff --git a/components/usb/usb_host_misc.c b/components/usb/usb_helpers.c similarity index 64% rename from components/usb/usb_host_misc.c rename to components/usb/usb_helpers.c index 072b547e31..e657c789b4 100644 --- a/components/usb/usb_host_misc.c +++ b/components/usb/usb_helpers.c @@ -8,12 +8,12 @@ #include #include #include -#include "usb/usb_host_misc.h" +#include "usb/usb_helpers.h" #include "usb/usb_types_ch9.h" // ---------------------------------------- Configuration Descriptor Parsing ------------------------------------------- -const usb_standard_desc_t *usb_host_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset) +const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset) { assert(cur_desc != NULL && offset != NULL); if (*offset >= wTotalLength) { @@ -28,17 +28,17 @@ const usb_standard_desc_t *usb_host_parse_next_descriptor(const usb_standard_des return ret_desc; } -const usb_standard_desc_t *usb_host_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset) +const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset) { assert(cur_desc != NULL && offset != NULL); int offset_temp = *offset; //We only want to update offset if we've actually found a descriptor //Keep stepping over descriptors until we find one of bDescriptorType or until we go out of bounds - const usb_standard_desc_t *ret_desc = usb_host_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp); + const usb_standard_desc_t *ret_desc = usb_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp); while (ret_desc != NULL) { if (ret_desc->bDescriptorType == bDescriptorType) { break; } - ret_desc = usb_host_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp); + ret_desc = usb_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp); } if (ret_desc != NULL) { //We've found a descriptor. Update the offset @@ -47,29 +47,29 @@ const usb_standard_desc_t *usb_host_parse_next_descriptor_of_type(const usb_stan return ret_desc; } -int usb_host_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber) +int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber) { assert(config_desc != NULL); int offset = 0; //Find the first interface descriptor of bInterfaceNumber - const usb_intf_desc_t *first_intf_desc = usb_host_parse_interface(config_desc, bInterfaceNumber, 0, &offset); + const usb_intf_desc_t *first_intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, 0, &offset); if (first_intf_desc == NULL) { return -1; //bInterfaceNumber not found } int num_alt_setting = 0; - const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)first_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)first_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); while (next_intf_desc != NULL) { if (next_intf_desc->bInterfaceNumber != bInterfaceNumber) { break; } num_alt_setting++; - next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); } return num_alt_setting; } -const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset) +const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset) { assert(config_desc != NULL); if (bInterfaceNumber >= config_desc->bNumInterfaces) { @@ -78,12 +78,12 @@ const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_ //Walk to first interface descriptor of bInterfaceNumber int offset_temp = 0; - const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); while (next_intf_desc != NULL) { if (next_intf_desc->bInterfaceNumber == bInterfaceNumber) { break; //We found the first interface descriptor with matching bInterfaceNumber } - next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); } if (next_intf_desc == NULL) { return NULL; //Couldn't find a interface with bInterfaceNumber @@ -101,7 +101,7 @@ const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_ break; } //Get the next interface descriptor - next_intf_desc = (const usb_intf_desc_t *)usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); } if (next_intf_desc != NULL && offset != NULL) { *offset = offset_temp; @@ -109,7 +109,7 @@ const usb_intf_desc_t *usb_host_parse_interface(const usb_config_desc_t *config_ return next_intf_desc; } -const usb_ep_desc_t *usb_host_parse_endpoint_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset) +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset) { assert(intf_desc != NULL && offset != NULL); if (index >= intf_desc->bNumEndpoints) { @@ -120,7 +120,7 @@ const usb_ep_desc_t *usb_host_parse_endpoint_by_index(const usb_intf_desc_t *int bool ep_found = true; const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)intf_desc; for (int i = 0; i <= index; i++) { - next_desc = usb_host_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_desc, wTotalLength, USB_B_DESCRIPTOR_TYPE_ENDPOINT, &offset_temp); + next_desc = usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_desc, wTotalLength, USB_B_DESCRIPTOR_TYPE_ENDPOINT, &offset_temp); if (next_desc == NULL) { ep_found = false; break; @@ -133,13 +133,13 @@ const usb_ep_desc_t *usb_host_parse_endpoint_by_index(const usb_intf_desc_t *int return NULL; } -const usb_ep_desc_t *usb_host_parse_endpoint_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset) +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset) { assert(config_desc != NULL); //Find the interface descriptor int offset_intf; - const usb_intf_desc_t *intf_desc = usb_host_parse_interface(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); + const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); if (intf_desc == NULL) { return NULL; } @@ -150,7 +150,7 @@ const usb_ep_desc_t *usb_host_parse_endpoint_by_address(const usb_config_desc_t const usb_ep_desc_t *ep_desc = NULL; for (int index = 0; index < intf_desc->bNumEndpoints; index++) { offset_ep = offset_intf; - ep_desc = usb_host_parse_endpoint_by_index(intf_desc, index, config_desc->wTotalLength, &offset_ep); + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, index, config_desc->wTotalLength, &offset_ep); if (ep_desc == NULL) { break; } diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c index f745001b22..5759fd6a41 100644 --- a/components/usb/usb_host.c +++ b/components/usb/usb_host.c @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + #include #include #include "freertos/FreeRTOS.h" @@ -921,7 +925,7 @@ static esp_err_t interface_claim(client_t *client_obj, usb_device_handle_t dev_h //We need to walk to configuration descriptor to find the correct interface descriptor, and each of its constituent endpoint descriptors //Find the interface descriptor and allocate the interface object int offset_intf; - const usb_intf_desc_t *intf_desc = usb_host_parse_interface(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); + const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); if (intf_desc == NULL) { ret = ESP_ERR_NOT_FOUND; goto exit; @@ -935,7 +939,7 @@ static esp_err_t interface_claim(client_t *client_obj, usb_device_handle_t dev_h //Find each endpoint descriptor in the interface by index, and allocate those endpoints for (int i = 0; i < intf_desc->bNumEndpoints; i++) { int offset_ep = offset_intf; - const usb_ep_desc_t *ep_desc = usb_host_parse_endpoint_by_index(intf_desc, i, config_desc->wTotalLength, &offset_ep); + const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, i, config_desc->wTotalLength, &offset_ep); if (ep_desc == NULL) { ret = ESP_ERR_NOT_FOUND; goto ep_alloc_err; diff --git a/components/usb/usbh.c b/components/usb/usbh.c index d05cf6a000..b8e8cfd784 100644 --- a/components/usb/usbh.c +++ b/components/usb/usbh.c @@ -17,7 +17,7 @@ #include "esp_heap_caps.h" #include "hcd.h" #include "usbh.h" -#include "usb/usb_host_misc.h" +#include "usb/usb_helpers.h" #include "usb/usb_types_ch9.h" //Device action flags. Listed in the order they should handled in. Some actions are mutually exclusive diff --git a/docs/conf_common.py b/docs/conf_common.py index 46dcddd920..33328995c9 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -49,6 +49,7 @@ LEGACY_DOCS = ['api-guides/build-system-legacy.rst', 'get-started-legacy/**'] USB_DOCS = ['api-reference/peripherals/usb_device.rst', + 'api-reference/peripherals/usb_host.rst', 'api-guides/usb-otg-console.rst', 'api-guides/dfu.rst'] diff --git a/docs/doxygen/Doxyfile_esp32s2 b/docs/doxygen/Doxyfile_esp32s2 index b0264e7274..c1fdf45624 100644 --- a/docs/doxygen/Doxyfile_esp32s2 +++ b/docs/doxygen/Doxyfile_esp32s2 @@ -14,4 +14,8 @@ INPUT += \ $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_element.h \ $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_button.h \ $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_slider.h \ - $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_matrix.h + $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_matrix.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_host.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_stack.h diff --git a/docs/doxygen/Doxyfile_esp32s3 b/docs/doxygen/Doxyfile_esp32s3 index 021e46ae76..88174f2144 100644 --- a/docs/doxygen/Doxyfile_esp32s3 +++ b/docs/doxygen/Doxyfile_esp32s3 @@ -6,4 +6,8 @@ INPUT += \ $(PROJECT_PATH)/components/hal/include/hal/pcnt_types.h \ $(PROJECT_PATH)/components/driver/include/driver/pcnt.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ - $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h + $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_host.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_stack.h diff --git a/docs/en/api-reference/peripherals/index.rst b/docs/en/api-reference/peripherals/index.rst index d52fbd8e7f..29a0bf94da 100644 --- a/docs/en/api-reference/peripherals/index.rst +++ b/docs/en/api-reference/peripherals/index.rst @@ -34,5 +34,6 @@ Peripherals API TWAI UART :SOC_USB_OTG_SUPPORTED: USB Device + :SOC_USB_OTG_SUPPORTED: USB Host Code examples for this API section are provided in the :example:`peripherals` directory of ESP-IDF examples. \ No newline at end of file diff --git a/docs/en/api-reference/peripherals/usb_host.rst b/docs/en/api-reference/peripherals/usb_host.rst new file mode 100644 index 0000000000..91a2ae44d1 --- /dev/null +++ b/docs/en/api-reference/peripherals/usb_host.rst @@ -0,0 +1,26 @@ +USB Host +======== + +.. warning:: + The USB Host Library API is a beta version thus is subject to change. + +The following document lists the API and types of the USB Host Library (that is currently under development). + +API Reference +------------- + +The API of the USB Host Library is separated into the following header files. However, it is sufficient for applications to only ``#include "usb/usb_host.h"`` and all of USB Host Library headers will also be included. + +- :component_file:`usb/include/usb/usb_host.h` contains the functions and types of the USB Host Library +- :component_file:`usb/include/usb/usb_helpers.h` contains various helper functions that are related to the USB protocol such as descriptor parsing. +- :component_file:`usb/include/usb/usb_types_stack.h` contains types that are are used across multiple layers of the USB Host stack. +- :component_file:`usb/include/usb/usb_types_ch9.h` contains types and macros related to Chapter 9 of the USB2.0 specification (i.e., descriptors and standard requests). + + +.. include-build-file:: inc/usb_host.inc + +.. include-build-file:: inc/usb_helpers.inc + +.. include-build-file:: inc/usb_types_stack.inc + +.. include-build-file:: inc/usb_types_ch9.inc diff --git a/docs/zh_CN/api-reference/peripherals/index.rst b/docs/zh_CN/api-reference/peripherals/index.rst index 373b041ed5..0232a33d4a 100644 --- a/docs/zh_CN/api-reference/peripherals/index.rst +++ b/docs/zh_CN/api-reference/peripherals/index.rst @@ -33,6 +33,7 @@ :esp32s2: Touch Element TWAI UART - :SOC_USB_OTG_SUPPORTED: USB Device + :SOC_USB_OTG_SUPPORTED: USB 设备 (Device) + :SOC_USB_OTG_SUPPORTED: USB 主机 (Host) 本部分的 API 示例代码存放在 ESP-IDF 示例项目的 :example:`peripherals` 目录下。 \ No newline at end of file diff --git a/docs/zh_CN/api-reference/peripherals/usb_host.rst b/docs/zh_CN/api-reference/peripherals/usb_host.rst new file mode 100644 index 0000000000..64ba8042f5 --- /dev/null +++ b/docs/zh_CN/api-reference/peripherals/usb_host.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/peripherals/usb_host.rst \ No newline at end of file From d53f0e074ce7e8e35cbb2fac07eb7a23022edc4c Mon Sep 17 00:00:00 2001 From: Euripedes Rocha Filho Date: Tue, 15 Dec 2020 13:10:10 +0000 Subject: [PATCH 120/310] experimental/mqtt_cxx: Adds a C++ Mqtt client wrapper - Base class with separated event handlers for each Mqtt client event. - Topic matcher added to support data events. - Filter class to allow only mqtt valid topic filters. - Initial code for unit test on the host. --- .../components/esp_mqtt_cxx/CMakeLists.txt | 25 ++ .../components/esp_mqtt_cxx/component.mk | 5 + .../components/esp_mqtt_cxx/esp_mqtt_cxx.cpp | 299 ++++++++++++++++++ .../esp_mqtt_cxx/include/esp_mqtt.hpp | 229 ++++++++++++++ .../include/esp_mqtt_client_config.hpp | 221 +++++++++++++ .../esp_mqtt_cxx/ssl/CMakeLists.txt | 14 + .../experimental/esp_mqtt_cxx/ssl/Makefile | 12 + .../esp_mqtt_cxx/ssl/main/CMakeLists.txt | 4 + .../esp_mqtt_cxx/ssl/main/Kconfig.projbuild | 9 + .../esp_mqtt_cxx/ssl/main/component.mk | 1 + .../ssl/main/mqtt_eclipse_org.pem | 27 ++ .../ssl/main/mqtt_eclipseprojects_io.pem | 30 ++ .../ssl/main/mqtt_ssl_example.cpp | 85 +++++ .../esp_mqtt_cxx/ssl/sdkconfig.defaults | 3 + .../esp_mqtt_cxx/tcp/CMakeLists.txt | 12 + .../experimental/esp_mqtt_cxx/tcp/Makefile | 12 + .../esp_mqtt_cxx/tcp/main/CMakeLists.txt | 3 + .../esp_mqtt_cxx/tcp/main/Kconfig.projbuild | 9 + .../esp_mqtt_cxx/tcp/main/component.mk | 0 .../tcp/main/mqtt_tcp_example.cpp | 81 +++++ .../esp_mqtt_cxx/tcp/sdkconfig.defaults | 3 + 21 files changed, 1084 insertions(+) create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/CMakeLists.txt create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/component.mk create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/esp_mqtt_cxx.cpp create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt.hpp create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt_client_config.hpp create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/CMakeLists.txt create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/Makefile create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/main/CMakeLists.txt create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/main/Kconfig.projbuild create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/main/component.mk create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipse_org.pem create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipseprojects_io.pem create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_ssl_example.cpp create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/ssl/sdkconfig.defaults create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/tcp/CMakeLists.txt create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/tcp/Makefile create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/tcp/main/CMakeLists.txt create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/tcp/main/Kconfig.projbuild create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/tcp/main/component.mk create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/tcp/main/mqtt_tcp_example.cpp create mode 100644 examples/cxx/experimental/esp_mqtt_cxx/tcp/sdkconfig.defaults diff --git a/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/CMakeLists.txt b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/CMakeLists.txt new file mode 100644 index 0000000000..5dd0329d08 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/CMakeLists.txt @@ -0,0 +1,25 @@ +idf_build_get_property(target IDF_TARGET) + +idf_component_register(SRCS "esp_mqtt_cxx.cpp" + INCLUDE_DIRS "include" + ) + +target_compile_options(${COMPONENT_LIB} PRIVATE "-std=gnu++17") + +if(TEST_BUILD) + message(STATUS "Test build") + idf_component_get_property(mqtt_dir mqtt COMPONENT_DIR) + idf_component_get_property(experimental_cpp_component_dir experimental_cpp_component COMPONENT_DIR) + idf_component_get_property(esp_common_dir esp_common COMPONENT_DIR) + idf_component_get_property(esp_event_dir esp_event COMPONENT_DIR) + target_include_directories(${COMPONENT_LIB} PUBLIC ${mqtt_dir}/esp-mqtt/include + ${esp_event_dir}/include + ${experimental_cpp_component_dir}/include + ${esp_common_dir}/include) + +else() + idf_component_get_property(mqtt_lib mqtt COMPONENT_LIB) + idf_component_get_property(log_lib log COMPONENT_LIB) + idf_component_get_property(experimental_cpp_component_lib experimental_cpp_component COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${log_lib} ${mqtt_lib} ${experimental_cpp_component_lib}) +endif() diff --git a/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/component.mk b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/component.mk new file mode 100644 index 0000000000..9e4987ab4e --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/component.mk @@ -0,0 +1,5 @@ +COMPONENT_ADD_INCLUDEDIRS := include + +COMPONENT_SRCDIRS := ./ + +CXXFLAGS += -std=gnu++17 diff --git a/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/esp_mqtt_cxx.cpp b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/esp_mqtt_cxx.cpp new file mode 100644 index 0000000000..b5f705b180 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/esp_mqtt_cxx.cpp @@ -0,0 +1,299 @@ +// Copyright 2021 Espressif Systems (Shanghai) CO LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "mqtt_client.h" +#include "esp_log.h" + +#include "esp_mqtt.hpp" +#include "esp_mqtt_client_config.hpp" + +namespace { + +// Helper for static assert. +template +constexpr bool always_false = false; + +template struct overloaded : Ts... { + using Ts::operator()...; +}; +template overloaded(Ts...) -> overloaded; + +using namespace idf::mqtt; + +/* + * This function is responsible for fill in the configurations for the broker related data + * of mqtt_client_config_t + */ +void config_broker(esp_mqtt_client_config_t &mqtt_client_cfg, BrokerConfiguration const &broker) +{ + std::visit(overloaded{ + [&mqtt_client_cfg](Host const & host) + { + mqtt_client_cfg.host = host.address.c_str(); + mqtt_client_cfg.path = host.path.c_str(); + mqtt_client_cfg.transport = host.transport; + }, + [&mqtt_client_cfg](URI const & uri) + { + mqtt_client_cfg.uri = uri.address.c_str(); + }, + []([[maybe_unused ]]auto & unknown) + { + static_assert(always_false, "Missing type handler for variant handler"); + } + }, + broker.address.address); + + std::visit(overloaded{ + []([[maybe_unused]]Insecure const & insecure) {}, + [&mqtt_client_cfg](GlobalCAStore const & use_global_store) + { + mqtt_client_cfg.use_global_ca_store = true; + }, + [&mqtt_client_cfg](CryptographicInformation const & certificates) + { + std::visit(overloaded{ + [&mqtt_client_cfg](PEM const & pem) + { + mqtt_client_cfg.cert_pem = pem.data; + }, [&mqtt_client_cfg](DER const & der) + { + mqtt_client_cfg.cert_pem = der.data; + mqtt_client_cfg.cert_len = der.len; + }}, certificates); + }, + []([[maybe_unused]] PSK const & psk) {}, + []([[maybe_unused]] auto & unknown) + { + static_assert(always_false, "Missing type handler for variant handler"); + } + }, + broker.security); + mqtt_client_cfg.port = broker.address.port; +} + +/* + * This function is responsible for fill in the configurations for the client credentials related data + * of mqtt_client_config_t + */ +void config_client_credentials(esp_mqtt_client_config_t &mqtt_client_cfg, ClientCredentials const &credentials) +{ + mqtt_client_cfg.client_id = credentials.client_id.has_value() ? credentials.client_id.value().c_str() : nullptr ; + mqtt_client_cfg.username = credentials.username.has_value() ? credentials.username.value().c_str() : nullptr ; + std::visit(overloaded{ + [&mqtt_client_cfg](Password const & password) + { + mqtt_client_cfg.password = password.data.c_str(); + }, + [](ClientCertificate const & certificate) {}, + [](SecureElement const & enable_secure_element) {}, + []([[maybe_unused ]]auto & unknown) + { + static_assert(always_false, "Missing type handler for variant handler"); + } + }, credentials.authentication); +} + +esp_mqtt_client_config_t make_config(BrokerConfiguration const &broker, ClientCredentials const &credentials, Configuration const &config) +{ + esp_mqtt_client_config_t mqtt_client_cfg{}; + config_broker(mqtt_client_cfg, broker); + config_client_credentials(mqtt_client_cfg, credentials); + return mqtt_client_cfg; +} +} + +namespace idf::mqtt { + +Client::Client(BrokerConfiguration const &broker, ClientCredentials const &credentials, Configuration const &config): Client(make_config(broker, credentials, config)) {} + +Client::Client(esp_mqtt_client_config_t const &config) : handler(esp_mqtt_client_init(&config)) +{ + if (handler == nullptr) { + throw MQTTException(ESP_FAIL); + }; + CHECK_THROW_SPECIFIC(esp_mqtt_client_register_event(handler.get(), MQTT_EVENT_ANY, mqtt_event_handler, this), mqtt::MQTTException); + CHECK_THROW_SPECIFIC(esp_mqtt_client_start(handler.get()), mqtt::MQTTException); +} + + +void Client::mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) noexcept +{ + ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id); + auto *event = static_cast(event_data); + auto &client = *static_cast(handler_args); + switch (event->event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + client.on_connected(event); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); + client.on_disconnected(event); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + client.on_subscribed(event); + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + client.on_unsubscribed(event); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + client.on_published(event); + break; + case MQTT_EVENT_DATA: + ESP_LOGI(TAG, "MQTT_EVENT_DATA"); + client.on_data(event); + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + client.on_error(event); + break; + case MQTT_EVENT_BEFORE_CONNECT: + ESP_LOGI(TAG, "MQTT_EVENT_BEFORE_CONNECT"); + client.on_before_connect(event); + break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; + } +} + +void Client::on_error(esp_mqtt_event_handle_t const event) +{ + auto log_error_if_nonzero = [](const char *message, int error_code) { + if (error_code != 0) { + ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code); + } + }; + if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { + log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err); + log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err); + log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno); + ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno)); + } +} +void Client::on_disconnected(esp_mqtt_event_handle_t const event) +{ +} +void Client::on_subscribed(esp_mqtt_event_handle_t const event) +{ + printf("Subscribed to %.*s\r\n", event->topic_len, event->topic); +} +void Client::on_unsubscribed(esp_mqtt_event_handle_t const event) +{ +} +void Client::on_published(esp_mqtt_event_handle_t const event) +{ +} +void Client::on_before_connect(esp_mqtt_event_handle_t const event) +{ +} +void Client::on_connected(esp_mqtt_event_handle_t const event) +{ +} +void Client::on_data(esp_mqtt_event_handle_t const event) +{ +} + +std::optional Client::subscribe(std::string const &topic, QoS qos) +{ + auto res = esp_mqtt_client_subscribe(handler.get(), topic.c_str(), + static_cast(qos)); + if (res < 0) { + return std::nullopt; + } + return MessageID{res}; +} + +bool is_valid(std::string::const_iterator first, std::string::const_iterator last) +{ + if (first == last) { + return false; + } + auto number = std::find(first, last, '#'); + if (number != last) { + if (std::next(number) != last) { + return false; + } + if (*std::prev(number) != '/' && number != first) { + return false; + } + } + + auto plus = std::find(first, last, '+'); + if (plus != last) { + if (*(std::prev(plus)) != '/' && plus != first) { + return false; + } + if (std::next(plus) != last && *(std::next(plus)) != '/') { + return false; + } + } + return true; +} + +Filter::Filter(std::string user_filter) : filter(std::move(user_filter)) +{ + if (!is_valid(filter.begin(), filter.end())) { + throw std::domain_error("Forbidden Filter string"); + } +} + +[[nodiscard]] bool Filter::match(std::string::const_iterator topic_begin, std::string::const_iterator topic_end) const noexcept +{ + auto filter_begin = filter.begin(); + auto filter_end = filter.end(); + for (auto mismatch = std::mismatch(filter_begin, filter_end, topic_begin); + mismatch.first != filter.end() and mismatch.second != topic_end; + mismatch = std::mismatch(filter_begin, filter_end, topic_begin)) { + if (*mismatch.first != '#' and * mismatch.first != '+') { + return false; + } + if (*mismatch.first == '#') { + return true; + } + if (*mismatch.first == '+') { + filter_begin = advance(mismatch.first, filter_end); + topic_begin = advance(mismatch.second, topic_end); + if (filter_begin == filter_end and topic_begin != topic_end) { + return false; + } + } + } + return true; +} +const std::string &Filter::get() +{ + return filter; +} + +[[nodiscard]] bool Filter::match(char const *const first, int size) const noexcept +{ + auto it = static_cast(first); + return match(it, it + size); +} +std::string::const_iterator Filter::advance(std::string::const_iterator first, std::string::const_iterator last) const +{ + constexpr auto separator = '/'; + return std::find(first, last, separator); +} + +} diff --git a/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt.hpp b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt.hpp new file mode 100644 index 0000000000..9d071f247a --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt.hpp @@ -0,0 +1,229 @@ +// Copyright 2021 Espressif Systems (Shanghai) CO LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#ifndef __cpp_exceptions +#error MQTT class can only be used when __cpp_exceptions is enabled. Enable CONFIG_COMPILER_CXX_EXCEPTIONS in Kconfig +#endif + +#include +#include +#include +#include +#include +#include "esp_exception.hpp" +#include "esp_mqtt_client_config.hpp" +#include "mqtt_client.h" + +namespace idf::mqtt { + +constexpr auto *TAG = "mqtt_client_cpp"; + +struct MQTTException : ESPException { + using ESPException::ESPException; +}; + +/** + * @brief QoS for publish and subscribe + * + * Sets the QoS as: + * AtMostOnce : Best effort delivery of messages. Message loss can occur. + * AtLeastOnce : Guaranteed delivery of messages. Duplicates can occur. + * ExactlyOnce : Guaranteed delivery of messages exactly once. + * + */ +enum class QoS { AtMostOnce = 0, AtLeastOnce = 1, ExactlyOnce = 2 }; + +/** + * @brief Sets if a message must be retained. + * + * Retained messages are delivered to future subscribers that match the topic name. + * + */ +enum class Retain : bool { NotRetained = false, Retained = true }; + + +/** + * @brief Message class template to publish. + * + */ +template struct Message { + T data; /*!< Data for publish. Should be a contiguous type*/ + QoS qos = QoS::AtLeastOnce; /*!< QoS for the message*/ + Retain retain = Retain::NotRetained; /*!< Retention mark for the message.*/ +}; + +/** + * @brief Message type that holds std::string for data + * + */ +using StringMessage = Message; + +[[nodiscard]] bool filter_is_valid(std::string::const_iterator first, std::string::const_iterator last); + +/** + * @brief Filter for mqtt topic subscription. + * @throws std::domain_error if the filter is invalid. + * + * Topic filter. + * + */ +class Filter { +public: + + explicit Filter(std::string user_filter); + + + /** + * @brief Get the filter string used. + * + */ + const std::string &get(); + + /** + * @brief Checks the filter string against a topic name. + * + * @param first Iterator to the beginning of the sequence. + * @param last Iterator to the end of the sequence. + * + * @return true if the topic name match the filter + */ + [[nodiscard]] bool match(std::string::const_iterator first, + std::string::const_iterator last) const noexcept; + + /** + * @brief Checks the filter string against a topic name. + * + * @param topic topic name + * + * @return true if the topic name match the filter + */ + [[nodiscard]] bool match(const std::string &topic) const noexcept; + + /** + * @brief Checks the filter string against a topic name. + * + * @param first Char array with topic name. + * @param last Size of given topic name. + * + * @return true if the topic name match the filter + */ + [[nodiscard]] bool match(const char *const begin, int size) const noexcept; + + +private: + + /** + * @brief Advance the topic to the next level. + * + * An mqtt topic ends with a /. This function is used to iterate in topic levels. + * + * @return Iterator to the start of the topic. + */ + [[nodiscard]] std::string::const_iterator advance(std::string::const_iterator begin, std::string::const_iterator end) const; + std::string filter; +}; + +/** + * @brief Message identifier to track delivery. + * + */ +enum class MessageID : int {}; + +/** + * @brief Base class for MQTT client + * + * Should be inherited to provide event handlers. + */ +class Client { +public: + + Client(const BrokerConfiguration &broker,const ClientCredentials &credentials,const Configuration &config); + + Client(const esp_mqtt_client_config_t &config); + + /** + * @brief Subscribe to topic + * + * @param filter + * @param qos QoS subscription, defaulted as QoS::AtLeastOnce + * + * @return Optional MessageID. In case of failure std::nullopt is returned. + */ + std::optional subscribe(const std::string &filter, QoS qos = QoS::AtLeastOnce); + + /** + * @brief publish message to topic + * + * @tparam Container Type for data container. Must be a contiguous memory. + * @param topic Topic name + * @param message Message struct containing data, qos and retain configuration. + * + * @return Optional MessageID. In case of failure std::nullopt is returned. + */ + template std::optional publish(const std::string &topic, const Message& message) + { + return publish(topic, std::begin(message.data), std::end(message.data), message.qos, message.retain); + } + + /** + * @brief publish message to topic + * + * @tparam InputIt Input data iterator type. + * @param topic Topic name + * @param first, last Iterator pair of data to publish + * @param message Message struct containing data, qos and retain configuration. + * + * @return Optional MessageID. In case of failure std::nullopt is returned. + */ + template + std::optional publish(const std::string &topic, InputIt first, InputIt last, QoS qos = QoS::AtLeastOnce, Retain retain = Retain::NotRetained) + { + auto size = std::distance(first, last); + auto res = esp_mqtt_client_publish(handler.get(), topic.c_str(), &(*first), size, static_cast(qos), + static_cast(retain)); + if (res < 0) { + return std::nullopt; + } + return MessageID{res}; + } + + virtual ~Client() = default; + +protected: + struct MqttClientDeleter { + void operator()(esp_mqtt_client *client_handler) + { + esp_mqtt_client_destroy(client_handler); + } + }; + + using ClientHandler = std::unique_ptr; + ClientHandler handler; + +private: + static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, + void *event_data) noexcept; + void init(const esp_mqtt_client_config_t &config); + virtual void on_error(const esp_mqtt_event_handle_t event); + virtual void on_disconnected(const esp_mqtt_event_handle_t event); + virtual void on_subscribed(const esp_mqtt_event_handle_t event); + virtual void on_unsubscribed(const esp_mqtt_event_handle_t event); + virtual void on_published(const esp_mqtt_event_handle_t event); + virtual void on_before_connect(const esp_mqtt_event_handle_t event); + virtual void on_connected(const esp_mqtt_event_handle_t event) = 0; + virtual void on_data(const esp_mqtt_event_handle_t event) = 0; +}; +} // namespace idf::mqtt diff --git a/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt_client_config.hpp b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt_client_config.hpp new file mode 100644 index 0000000000..0fbba636fc --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/components/esp_mqtt_cxx/include/esp_mqtt_client_config.hpp @@ -0,0 +1,221 @@ +// Copyright 2021 Espressif Systems (Shanghai) CO LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include +#include + +#include "mqtt_client.h" + +namespace idf::mqtt { + + + +/** + * @brief Broker addresss + * + * Use this to set the broker without parsing the URI string. + * + */ +struct Host { + std::string address; /*!< Host name*/ + std::string path; /*!< Route path of the broker in host*/ + esp_mqtt_transport_t transport; /*!< Transport scheme to use. */ +}; + +/** + * @brief Broker addresss URI + * + * Use this to set the broker address using the URI. + * + */ +struct URI { + std::string address; /*!< Broker adddress URI*/ +}; + + +/** + * @brief Broker addresss. + * + */ +struct BrokerAddress { + std::variant address; /*!< Address, defined by URI or Host struct */ + uint32_t port = 0; /*!< Port used, defaults to 0 to select common port for the scheme used */ +}; + +/** + * @brief PEM formated data + * + * Store certificates, keys and cryptographic data. + * + */ +struct PEM { + const char *data; +}; + +/** + * @brief DER formated data + * + * Store certificates, keys and cryptographic data. + * + */ +struct DER { + const char *data; + size_t len; +}; + +/** + * @brief Holds cryptography related information + * + * Hold PEM or DER formated cryptographic data. + * + */ +using CryptographicInformation = std::variant; + + +/** + * @brief Do not verify broker certificate. + * + * To be used when doing MQTT over TLS connection but not verify broker's certificates. + * + */ +struct Insecure {}; + +/** + * @brief Use global CA store + * + * To be used when client should use the Global CA Store to get trusted certificates for the broker. + * + */ +struct GlobalCAStore {}; + +/** + * @brief Use a pre shared key for broker authentication. + * + * To be used when client should use a PSK to authenticate the broker. + * + */ +struct PSK { + const struct psk_key_hint *hint_key;/* Pointer to PSK struct defined in esp_tls.h to enable PSK authentication */ +}; + + +/** + * @brief Authentication method for Broker + * + * Selects the method for authentication based on the type it holds. + * + */ +using BrokerAuthentication = std::variant; + +/** + * @brief Password related data. + * + */ +struct Password { + std::string data; +}; + +/** + * @brief Data to authenticate client with certificates. + * + */ +struct ClientCertificate { + CryptographicInformation certificate; /*!< Certificate in PEM or DER format.*/ + CryptographicInformation key; /*!< Key data in PEM or DER format.*/ + std::optional key_password = std::nullopt; /*!< Optional password for key */ +}; + +/** + * @brief Used to select usage of Secure Element + * + * Enables the usage of the secure element present in ESP32-WROOM-32SE. + * + */ +struct SecureElement {}; + + +/** + * @brief Used to select usage of Digital Signature Peripheral. + * + * Enables the usage of the Digital Signature hardware accelerator. + * + */ +struct DigitalSignatureData { + void *ds_data; /* carrier of handle for digital signature parameters */ +}; + +using AuthenticationFactor = std::variant; + +struct BrokerConfiguration { + BrokerAddress address; + BrokerAuthentication security; +}; + +struct ClientCredentials { + std::optional username; // MQTT username + AuthenticationFactor authentication; + std::vector alpn_protos; /*!< List of supported application protocols to be used for ALPN */ + /* default is ``ESP32_%CHIPID%`` where %CHIPID% are last 3 bytes of MAC address in hex format */ + std::optional client_id = std::nullopt; +}; + +struct Event { + mqtt_event_callback_t event_handle; /*!< handle for MQTT events as a callback in legacy mode */ + esp_event_loop_handle_t event_loop_handle; /*!< handle for MQTT event loop library */ +}; + +struct LastWill { + const char *lwt_topic; /*!< LWT (Last Will and Testament) message topic (NULL by default) */ + const char *lwt_msg; /*!< LWT message (NULL by default) */ + int lwt_qos; /*!< LWT message qos */ + int lwt_retain; /*!< LWT retained message flag */ + int lwt_msg_len; /*!< LWT message length */ +}; + +struct Session { + LastWill last_will; + int disable_clean_session; /*!< mqtt clean session, default clean_session is true */ + int keepalive; /*!< mqtt keepalive, default is 120 seconds */ + bool disable_keepalive; /*!< Set disable_keepalive=true to turn off keep-alive mechanism, false by default (keepalive is active by default). Note: setting the config value `keepalive` to `0` doesn't disable keepalive feature, but uses a default keepalive period */ + esp_mqtt_protocol_ver_t protocol_ver; /*!< MQTT protocol version used for connection, defaults to value from menuconfig*/ +}; + +struct Task { + int task_prio; /*!< MQTT task priority, default is 5, can be changed in ``make menuconfig`` */ + int task_stack; /*!< MQTT task stack size, default is 6144 bytes, can be changed in ``make menuconfig`` */ +}; + +struct Connection { + esp_mqtt_transport_t transport; /*!< overrides URI transport */ + int reconnect_timeout_ms; /*!< Reconnect to the broker after this value in miliseconds if auto reconnect is not disabled (defaults to 10s) */ + int network_timeout_ms; /*!< Abort network operation if it is not completed after this value, in milliseconds (defaults to 10s) */ + int refresh_connection_after_ms; /*!< Refresh connection after this value (in milliseconds) */ + bool disable_auto_reconnect; /*!< this mqtt client will reconnect to server (when errors/disconnect). Set disable_auto_reconnect=true to disable */ +}; + +struct Configuration { + Event event; + Task task; + Session session; + Connection connection; + void *user_context; /*!< pass user context to this option, then can receive that context in ``event->user_context`` */ + int buffer_size; /*!< size of MQTT send/receive buffer, default is 1024 (only receive buffer size if ``out_buffer_size`` defined) */ + int out_buffer_size; /*!< size of MQTT output buffer. If not defined, both output and input buffers have the same size defined as ``buffer_size`` */ +}; + +} // idf::mqtt diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/CMakeLists.txt b/examples/cxx/experimental/esp_mqtt_cxx/ssl/CMakeLists.txt new file mode 100644 index 0000000000..a5f94f0875 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/CMakeLists.txt @@ -0,0 +1,14 @@ +# The following four 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) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common + $ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component + $ENV{IDF_PATH}/examples/cxx/experimental/esp_mqtt_cxx/components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mqtt_ssl_cxx) + +target_add_binary_data(mqtt_ssl_cxx.elf "main/mqtt_eclipseprojects_io.pem" TEXT) diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/Makefile b/examples/cxx/experimental/esp_mqtt_cxx/ssl/Makefile new file mode 100644 index 0000000000..392ad4a333 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/Makefile @@ -0,0 +1,12 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := mqtt_tcp_cxx + +EXTRA_COMPONENT_DIRS := $(IDF_PATH)/examples/common_components/protocol_examples_common +EXTRA_COMPONENT_DIRS += $(IDF_PATH)/examples/cxx/experimental/esp_mqtt_cxx/components +EXTRA_COMPONENT_DIRS += $(IDF_PATH)/examples/cxx/experimental/experimental_cpp_component + +CXXFLAGS += -std=gnu++17 +include $(IDF_PATH)/make/project.mk diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/CMakeLists.txt b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/CMakeLists.txt new file mode 100644 index 0000000000..9871f4c78f --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "mqtt_ssl_example.cpp" + INCLUDE_DIRS ".") + +target_compile_options(${COMPONENT_LIB} PRIVATE "-std=gnu++17") diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/Kconfig.projbuild b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/Kconfig.projbuild new file mode 100644 index 0000000000..6d8dc0a35b --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "Example Configuration" + + config BROKER_URI + string "Broker URL" + default "mqtts://mqtt.eclipse.org:8883" + help + URL of the broker to connect to + +endmenu diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/component.mk b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/component.mk new file mode 100644 index 0000000000..c0c0f87e68 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/component.mk @@ -0,0 +1 @@ +COMPONENT_EMBED_TXTFILES := mqtt_eclipseprojects_io.pem diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipse_org.pem b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipse_org.pem new file mode 100644 index 0000000000..0002462ce8 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipse_org.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow +SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT +GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF +q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 +SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 +Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA +a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj +/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG +CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv +bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k +c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw +VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC +ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz +MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu +Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF +AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo +uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ +wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu +X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG +PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 +KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== +-----END CERTIFICATE----- diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipseprojects_io.pem b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipseprojects_io.pem new file mode 100644 index 0000000000..43b222a60a --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_eclipseprojects_io.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_ssl_example.cpp b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_ssl_example.cpp new file mode 100644 index 0000000000..8493d52d03 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/main/mqtt_ssl_example.cpp @@ -0,0 +1,85 @@ +/* C++ MQTT (over TCP) Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include "esp_mqtt_client_config.hpp" +#include "nvs_flash.h" +#include "protocol_examples_common.h" + + +#include "esp_log.h" +#include "esp_mqtt.hpp" + +namespace { +constexpr auto *TAG = "MQTT_EXAMPLE"; + +extern const char mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start"); +extern const char mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipseprojects_io_pem_end"); + +class MyClient final : public idf::mqtt::Client { +public: + using idf::mqtt::Client::Client; +private: + void on_connected(esp_mqtt_event_handle_t const event) override + { + using idf::mqtt::QoS; + subscribe(messages.get()); + subscribe(sent_load.get(), QoS::AtMostOnce); + } + void on_data(esp_mqtt_event_handle_t const event) override + { + if (messages.match(event->topic, event->topic_len)) { + ESP_LOGI(TAG, "Received in the messages topic"); + } + } + idf::mqtt::Filter messages{std::string{"$SYS/broker/messages/received"}}; + idf::mqtt::Filter sent_load{std::string{"$SYS/broker/load/+/sent"}}; +}; +} + +namespace mqtt = idf::mqtt; + +extern "C" void app_main(void) +{ + ESP_LOGI(TAG, "[APP] Startup.."); + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); + + esp_log_level_set("*", ESP_LOG_INFO); + esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); + esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); + esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); + + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + mqtt::BrokerConfiguration broker{ + .address = {mqtt::URI{std::string{CONFIG_BROKER_URI}}}, + .security = mqtt::CryptographicInformation{mqtt::PEM{mqtt_eclipse_org_pem_start}} + }; + idf::mqtt::ClientCredentials credentials{}; + idf::mqtt::Configuration config{}; + + MyClient client{broker, credentials, config}; + while (true) { + constexpr TickType_t xDelay = 500 / portTICK_PERIOD_MS; + vTaskDelay( xDelay ); + } +} diff --git a/examples/cxx/experimental/esp_mqtt_cxx/ssl/sdkconfig.defaults b/examples/cxx/experimental/esp_mqtt_cxx/ssl/sdkconfig.defaults new file mode 100644 index 0000000000..a365ac6589 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/ssl/sdkconfig.defaults @@ -0,0 +1,3 @@ +# Enable C++ exceptions and set emergency pool size for exception objects +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=1024 diff --git a/examples/cxx/experimental/esp_mqtt_cxx/tcp/CMakeLists.txt b/examples/cxx/experimental/esp_mqtt_cxx/tcp/CMakeLists.txt new file mode 100644 index 0000000000..29bdec2893 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/tcp/CMakeLists.txt @@ -0,0 +1,12 @@ +# The following four 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) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common + $ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component + $ENV{IDF_PATH}/examples/cxx/experimental/esp_mqtt_cxx/components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mqtt_tcp_cxx) diff --git a/examples/cxx/experimental/esp_mqtt_cxx/tcp/Makefile b/examples/cxx/experimental/esp_mqtt_cxx/tcp/Makefile new file mode 100644 index 0000000000..392ad4a333 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/tcp/Makefile @@ -0,0 +1,12 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := mqtt_tcp_cxx + +EXTRA_COMPONENT_DIRS := $(IDF_PATH)/examples/common_components/protocol_examples_common +EXTRA_COMPONENT_DIRS += $(IDF_PATH)/examples/cxx/experimental/esp_mqtt_cxx/components +EXTRA_COMPONENT_DIRS += $(IDF_PATH)/examples/cxx/experimental/experimental_cpp_component + +CXXFLAGS += -std=gnu++17 +include $(IDF_PATH)/make/project.mk diff --git a/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/CMakeLists.txt b/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/CMakeLists.txt new file mode 100644 index 0000000000..07fa3e75c9 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "mqtt_tcp_example.cpp" + INCLUDE_DIRS ".") +target_compile_options(${COMPONENT_LIB} PRIVATE "-std=gnu++17") diff --git a/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/Kconfig.projbuild b/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/Kconfig.projbuild new file mode 100644 index 0000000000..34c04a02cb --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "Example Configuration" + + config BROKER_URL + string "Broker URL" + default "mqtt://mqtt.eclipse.org" + help + URL of the broker to connect to + +endmenu diff --git a/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/component.mk b/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/component.mk new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/mqtt_tcp_example.cpp b/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/mqtt_tcp_example.cpp new file mode 100644 index 0000000000..edfb535508 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/tcp/main/mqtt_tcp_example.cpp @@ -0,0 +1,81 @@ +/* C++ MQTT (over TCP) Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "nvs_flash.h" +#include "protocol_examples_common.h" + +#include "esp_log.h" +#include "esp_mqtt.hpp" +#include "esp_mqtt_client_config.hpp" + +namespace mqtt = idf::mqtt; + +namespace { +constexpr auto *TAG = "MQTT_EXAMPLE"; + +class MyClient final : public mqtt::Client { +public: + using mqtt::Client::Client; + +private: + void on_connected(esp_mqtt_event_handle_t const event) override + { + using mqtt::QoS; + subscribe(messages.get()); + subscribe(sent_load.get(), QoS::AtMostOnce); + } + void on_data(esp_mqtt_event_handle_t const event) override + { + if (messages.match(event->topic, event->topic_len)) { + ESP_LOGI(TAG, "Received in the messages topic"); + } + } + mqtt::Filter messages{"$SYS/broker/messages/received"}; + mqtt::Filter sent_load{"$SYS/broker/load/+/sent"}; +}; +} + +extern "C" void app_main(void) +{ + ESP_LOGI(TAG, "[APP] Startup.."); + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); + + esp_log_level_set("*", ESP_LOG_INFO); + esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); + esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); + esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); + + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + mqtt::BrokerConfiguration broker{ + .address = {mqtt::URI{std::string{CONFIG_BROKER_URL}}}, + .security = mqtt::Insecure{} + }; + mqtt::ClientCredentials credentials{}; + mqtt::Configuration config{}; + + MyClient client{broker, credentials, config}; + + while (true) { + constexpr TickType_t xDelay = 500 / portTICK_PERIOD_MS; + vTaskDelay(xDelay); + } +} diff --git a/examples/cxx/experimental/esp_mqtt_cxx/tcp/sdkconfig.defaults b/examples/cxx/experimental/esp_mqtt_cxx/tcp/sdkconfig.defaults new file mode 100644 index 0000000000..a365ac6589 --- /dev/null +++ b/examples/cxx/experimental/esp_mqtt_cxx/tcp/sdkconfig.defaults @@ -0,0 +1,3 @@ +# Enable C++ exceptions and set emergency pool size for exception objects +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=1024 From 04fff1586472ecfc9f4e2a8a3a619eefff5957a1 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Fri, 3 Sep 2021 00:17:30 +0300 Subject: [PATCH 121/310] tools: Updates OpenOCD version to 'v0.10.0-esp32-20210902' --- tools/tools.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/tools.json b/tools/tools.json index b109f2d397..f4e5d1d300 100644 --- a/tools/tools.json +++ b/tools/tools.json @@ -464,31 +464,31 @@ "versions": [ { "linux-amd64": { - "sha256": "4a47edaa77c9593856f394a129f5969b786ea0a78a089c11fccb3f2f4cd3ba19", - "size": 1801109, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210721/openocd-esp32-linux64-0.10.0-esp32-20210721.tar.gz" + "sha256": "bd7364b8bf4fa03eebbac7f8aba8632029c34946ee67d451c02182aae8bc38e0", + "size": 1802447, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210902/openocd-esp32-linux64-0.10.0-esp32-20210902.tar.gz" }, "linux-armel": { - "sha256": "5e20031e1df2efd0a4f41925c6a8afda43ddb2327c353e352d5b8eed1e2d836b", - "size": 1833373, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210721/openocd-esp32-armel-0.10.0-esp32-20210721.tar.gz" + "sha256": "32aa83aa815666bdd442751c75d3826132ecd1bf1ac56f8b2a195e28f0ee2128", + "size": 1801394, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210902/openocd-esp32-armel-0.10.0-esp32-20210902.tar.gz" }, "macos": { - "sha256": "2315202693aa35efc78d41bb2db48dd14ae1821a5fd2bb8c2c044908f170648a", - "size": 1909600, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210721/openocd-esp32-macos-0.10.0-esp32-20210721.tar.gz" + "sha256": "0c32e4400edf6c725eb24af8d9ea9395f799c06333db2b87bbd22831467aba54", + "size": 1909909, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210902/openocd-esp32-macos-0.10.0-esp32-20210902.tar.gz" }, - "name": "v0.10.0-esp32-20210721", + "name": "v0.10.0-esp32-20210902", "status": "recommended", "win32": { - "sha256": "ea9859004f49d7a192f65efa3e3c2ca2434454d5a7834485273673086f18e012", - "size": 2280686, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210721/openocd-esp32-win32-0.10.0-esp32-20210721.zip" + "sha256": "9ad2a5031f498bae20291f3a81f2eb2371b79a1e5b81a2119d911b27a8a7a2e5", + "size": 2281243, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210902/openocd-esp32-win32-0.10.0-esp32-20210902.zip" }, "win64": { - "sha256": "ea9859004f49d7a192f65efa3e3c2ca2434454d5a7834485273673086f18e012", - "size": 2280686, - "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210721/openocd-esp32-win32-0.10.0-esp32-20210721.zip" + "sha256": "9ad2a5031f498bae20291f3a81f2eb2371b79a1e5b81a2119d911b27a8a7a2e5", + "size": 2281243, + "url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20210902/openocd-esp32-win32-0.10.0-esp32-20210902.zip" } } ] From be189b1cfd96e68a3c73cdbb9a1296cdb55ec4ff Mon Sep 17 00:00:00 2001 From: Shang Zhou Date: Fri, 27 Aug 2021 15:09:35 +0800 Subject: [PATCH 122/310] updated the TOC of ESP-IDF API Reference to make it consistet with the real section title --- docs/en/api-reference/peripherals/adc.rst | 4 +- docs/en/api-reference/peripherals/dac.rst | 4 +- docs/en/api-reference/peripherals/ds.rst | 4 +- docs/en/api-reference/peripherals/hmac.rst | 4 +- docs/en/api-reference/peripherals/i2c.rst | 4 +- docs/en/api-reference/peripherals/i2s.rst | 4 +- docs/en/api-reference/peripherals/index.rst | 58 +++++++++---------- docs/en/api-reference/peripherals/ledc.rst | 4 +- docs/en/api-reference/peripherals/mcpwm.rst | 4 +- docs/en/api-reference/peripherals/pcnt.rst | 4 +- docs/en/api-reference/peripherals/rmt.rst | 4 +- .../api-reference/peripherals/temp_sensor.rst | 2 +- docs/en/api-reference/peripherals/twai.rst | 4 +- docs/en/api-reference/peripherals/uart.rst | 4 +- .../zh_CN/api-reference/peripherals/index.rst | 58 +++++++++---------- 15 files changed, 83 insertions(+), 83 deletions(-) diff --git a/docs/en/api-reference/peripherals/adc.rst b/docs/en/api-reference/peripherals/adc.rst index 1723b56d55..d9865c47ec 100644 --- a/docs/en/api-reference/peripherals/adc.rst +++ b/docs/en/api-reference/peripherals/adc.rst @@ -1,5 +1,5 @@ -Analog to Digital Converter -=========================== +Analog to Digital Converter (ADC) +================================= {IDF_TARGET_ADC1_CH0: default="GPIO 0", esp32="GPIO 36"} {IDF_TARGET_ADC2_CH7: default="GPIO 0", esp32="GPIO 27"} diff --git a/docs/en/api-reference/peripherals/dac.rst b/docs/en/api-reference/peripherals/dac.rst index 50251ca9a2..06f4005a27 100644 --- a/docs/en/api-reference/peripherals/dac.rst +++ b/docs/en/api-reference/peripherals/dac.rst @@ -1,5 +1,5 @@ -Digital To Analog Converter -=========================== +Digital To Analog Converter (DAC) +================================= {IDF_TARGET_DAC_CH_1: default = "GPIO25", esp32 = "GPIO25", esp32s2 = "GPIO17"} {IDF_TARGET_DAC_CH_2: default = "GPIO26", esp32 = "GPIO26", esp32s2 = "GPIO18"} diff --git a/docs/en/api-reference/peripherals/ds.rst b/docs/en/api-reference/peripherals/ds.rst index 125b9be28e..0e1b506ba8 100644 --- a/docs/en/api-reference/peripherals/ds.rst +++ b/docs/en/api-reference/peripherals/ds.rst @@ -1,5 +1,5 @@ -Digital Signature -================= +Digital Signature (DS) +====================== The Digital Signature (DS) module provides hardware acceleration of signing messages based on RSA. It uses pre-encrypted parameters to calculate a signature. diff --git a/docs/en/api-reference/peripherals/hmac.rst b/docs/en/api-reference/peripherals/hmac.rst index ae594443ef..a431158fa6 100644 --- a/docs/en/api-reference/peripherals/hmac.rst +++ b/docs/en/api-reference/peripherals/hmac.rst @@ -1,5 +1,5 @@ -HMAC -==== +Hash-based Message Authentication Code (HMAC) +============================================= The HMAC (Hash-based Message Authentication Code) module provides hardware acceleration for SHA256-HMAC generation using a key burned into an eFuse block. HMACs work with pre-shared secret keys and provide authenticity and integrity to a message. diff --git a/docs/en/api-reference/peripherals/i2c.rst b/docs/en/api-reference/peripherals/i2c.rst index 7e6022b37b..29e95101a3 100644 --- a/docs/en/api-reference/peripherals/i2c.rst +++ b/docs/en/api-reference/peripherals/i2c.rst @@ -1,5 +1,5 @@ -I2C Driver -========== +Inter-Integrated Circuit (I2C) +============================== :link_to_translation:`zh_CN:[中文]` diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index 6fd3bd2415..c56b732a15 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -1,5 +1,5 @@ -I2S -=== +Inter-IC Sound (I2S) +==================== {IDF_TARGET_I2S_NUM:default="two", esp32s2="one", esp32c3="one"} diff --git a/docs/en/api-reference/peripherals/index.rst b/docs/en/api-reference/peripherals/index.rst index 29a0bf94da..730983ee9d 100644 --- a/docs/en/api-reference/peripherals/index.rst +++ b/docs/en/api-reference/peripherals/index.rst @@ -6,34 +6,34 @@ Peripherals API .. toctree:: :maxdepth: 1 - ADC - :SOC_DAC_SUPPORTED: DAC - General Purpose Timer - GPIO (including RTC low power I/O) - :SOC_DEDICATED_GPIO_SUPPORTED: Dedicated GPIO - :SOC_HMAC_SUPPORTED: HMAC - :SOC_DIG_SIGN_SUPPORTED: Digital Signature - I2C - I2S - LED Control - :SOC_MCPWM_SUPPORTED: MCPWM - :SOC_PCNT_SUPPORTED: Pulse Counter - Remote Control - :esp32 or esp32s3: SD Pull-up Requirements - :SOC_SDMMC_HOST_SUPPORTED: SDMMC Host - SD SPI Host - :SOC_SDIO_SLAVE_SUPPORTED: SDIO Slave - Sigma-delta Modulation - SPI Master - SPI Slave - :esp32: Secure Element - :esp32s2: SPI Slave Half Duplex - :SOC_TEMP_SENSOR_SUPPORTED: Temp sensor - :SOC_TOUCH_SENSOR_NUM: Touch Sensor - :esp32s2: Touch Element - TWAI - UART - :SOC_USB_OTG_SUPPORTED: USB Device - :SOC_USB_OTG_SUPPORTED: USB Host + adc + :SOC_DAC_SUPPORTED: dac + timer + gpio + :SOC_DEDICATED_GPIO_SUPPORTED: dedic_gpio + :SOC_HMAC_SUPPORTED: hmac + :SOC_DIG_SIGN_SUPPORTED: ds + i2c + i2s + ledc + :SOC_MCPWM_SUPPORTED: mcpwm + :SOC_PCNT_SUPPORTED: pcnt + rmt + :esp32 or esp32s3: sd_pullup_requirements + :SOC_SDMMC_HOST_SUPPORTED: sdmmc_host + sdspi_host + :SOC_SDIO_SLAVE_SUPPORTED: sdio_slave + sigmadelta + spi_master + spi_slave + :esp32: secure_element + :esp32s2: spi_slave_hd + :SOC_TEMP_SENSOR_SUPPORTED: temp_sensor + :SOC_TOUCH_SENSOR_NUM: touch_pad + :esp32s2: touch_element + twai + uart + :SOC_USB_OTG_SUPPORTED: usb_device + :SOC_USB_OTG_SUPPORTED: usb_host Code examples for this API section are provided in the :example:`peripherals` directory of ESP-IDF examples. \ No newline at end of file diff --git a/docs/en/api-reference/peripherals/ledc.rst b/docs/en/api-reference/peripherals/ledc.rst index dcda4b7719..6eb16f804f 100644 --- a/docs/en/api-reference/peripherals/ledc.rst +++ b/docs/en/api-reference/peripherals/ledc.rst @@ -1,5 +1,5 @@ -LED Control -=========== +LED Control (LEDC) +================== {IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6"} :link_to_translation:`zh_CN:[中文]` diff --git a/docs/en/api-reference/peripherals/mcpwm.rst b/docs/en/api-reference/peripherals/mcpwm.rst index 7693fe1439..a9d6b94caa 100644 --- a/docs/en/api-reference/peripherals/mcpwm.rst +++ b/docs/en/api-reference/peripherals/mcpwm.rst @@ -1,5 +1,5 @@ -MCPWM -===== +Motor Control Pulse Width Modulator (MCPWM) +=========================================== {IDF_TARGET_NAME} has two MCPWM units which can be used to control different types of motors. Each unit has three pairs of PWM outputs. diff --git a/docs/en/api-reference/peripherals/pcnt.rst b/docs/en/api-reference/peripherals/pcnt.rst index 22433e8358..6cb0e81e2e 100644 --- a/docs/en/api-reference/peripherals/pcnt.rst +++ b/docs/en/api-reference/peripherals/pcnt.rst @@ -1,5 +1,5 @@ -Pulse Counter -============= +Pulse Counter (PCNT) +==================== {IDF_TARGET_PCNT_UNIT_NUM:default="8", esp32s2="4"} {IDF_TARGET_PCNT_MAX_UNIT_NUM:default="7", esp32s2="3"} diff --git a/docs/en/api-reference/peripherals/rmt.rst b/docs/en/api-reference/peripherals/rmt.rst index 35dd8c6f13..b0758e7897 100644 --- a/docs/en/api-reference/peripherals/rmt.rst +++ b/docs/en/api-reference/peripherals/rmt.rst @@ -1,5 +1,5 @@ -RMT -=== +Remote Control (RMT) +==================== The RMT (Remote Control) module driver can be used to send and receive infrared remote control signals. Due to flexibility of RMT module, the driver can also be used to generate or receive many other types of signals. diff --git a/docs/en/api-reference/peripherals/temp_sensor.rst b/docs/en/api-reference/peripherals/temp_sensor.rst index c77de66b57..a9e9fcb1be 100644 --- a/docs/en/api-reference/peripherals/temp_sensor.rst +++ b/docs/en/api-reference/peripherals/temp_sensor.rst @@ -1,5 +1,5 @@ Temperature Sensor -================== +=================== Overview -------- diff --git a/docs/en/api-reference/peripherals/twai.rst b/docs/en/api-reference/peripherals/twai.rst index 31aed19e2a..676106dece 100644 --- a/docs/en/api-reference/peripherals/twai.rst +++ b/docs/en/api-reference/peripherals/twai.rst @@ -1,5 +1,5 @@ -TWAI -==== +Two-Wire Automotive Interface (TWAI) +==================================== .. -------------------------------- Overview ----------------------------------- diff --git a/docs/en/api-reference/peripherals/uart.rst b/docs/en/api-reference/peripherals/uart.rst index fc18adfe42..57016cedbe 100644 --- a/docs/en/api-reference/peripherals/uart.rst +++ b/docs/en/api-reference/peripherals/uart.rst @@ -1,5 +1,5 @@ -UART -==== +Universal Asynchronous Receiver/Transmitter (UART) +================================================== {IDF_TARGET_UART_NUM:default = "UART_NUM_1", esp32 = "UART_NUM_2", esp32s3 = "UART_NUM_2"} diff --git a/docs/zh_CN/api-reference/peripherals/index.rst b/docs/zh_CN/api-reference/peripherals/index.rst index 0232a33d4a..3089a2a45e 100644 --- a/docs/zh_CN/api-reference/peripherals/index.rst +++ b/docs/zh_CN/api-reference/peripherals/index.rst @@ -6,34 +6,34 @@ .. toctree:: :maxdepth: 1 - ADC - :SOC_DAC_SUPPORTED: DAC - 通用定时器 - GPIO (including RTC low power I/O) - :SOC_DEDICATED_GPIO_SUPPORTED: Dedicated GPIO - :SOC_HMAC_SUPPORTED: HMAC - :SOC_DIG_SIGN_SUPPORTED: Digital Signature - I2C - I2S - LED 控制器 - :SOC_MCPWM_SUPPORTED: MCPWM - :SOC_PCNT_SUPPORTED: Pulse Counter - Remote Control - :esp32 or esp32s3: SD Pull-up Requirements - :SOC_SDMMC_HOST_SUPPORTED: SDMMC Host - SD SPI Host - :SOC_SDIO_SLAVE_SUPPORTED: SDIO Slave - Sigma-delta Modulation - SPI Master - SPI Slave - :esp32: Secure Element - :esp32s2: SPI Slave Half Duplex - :SOC_TEMP_SENSOR_SUPPORTED: Temp sensor - :SOC_TOUCH_SENSOR_NUM: 触摸传感器 - :esp32s2: Touch Element - TWAI - UART - :SOC_USB_OTG_SUPPORTED: USB 设备 (Device) - :SOC_USB_OTG_SUPPORTED: USB 主机 (Host) + adc + :SOC_DAC_SUPPORTED: dac + timer + gpio + :SOC_DEDICATED_GPIO_SUPPORTED: dedic_gpio + :SOC_HMAC_SUPPORTED: hmac + :SOC_DIG_SIGN_SUPPORTED: ds + i2c + i2s + ledc + :SOC_MCPWM_SUPPORTED: mcpwm + :SOC_PCNT_SUPPORTED: pcnt + rmt + :esp32 or esp32s3: sd_pullup_requirements + :SOC_SDMMC_HOST_SUPPORTED: sdmmc_host + sdspi_host + :SOC_SDIO_SLAVE_SUPPORTED: sdio_slave + sigmadelta + spi_master + spi_slave + :esp32: secure_element + :esp32s2: spi_slave_hd + :SOC_TEMP_SENSOR_SUPPORTED: temp_sensor + :SOC_TOUCH_SENSOR_NUM: touch_pad + :esp32s2: touch_element + twai + uart + :SOC_USB_OTG_SUPPORTED: usb_device + :SOC_USB_OTG_SUPPORTED: usb_host 本部分的 API 示例代码存放在 ESP-IDF 示例项目的 :example:`peripherals` 目录下。 \ No newline at end of file From fa34cfcc0c592a77649d5b0b4831d97ce1974c03 Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 3 Sep 2021 16:44:19 +0800 Subject: [PATCH 123/310] spi: update spi master / slave programming guide on s3 --- docs/en/api-reference/peripherals/spi_master.rst | 10 +++++----- docs/en/api-reference/peripherals/spi_slave.rst | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 039ec99ffc..ca1cd44e81 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -28,7 +28,7 @@ Overview of {IDF_TARGET_NAME}'s SPI peripherals - SPI2 and SPI3 are general purpose SPI controllers, sometimes referred to as HSPI and VSPI, respectively. They are open to users. SPI2 and SPI3 have independent bus signals with the same respective names. Each bus has three CS lines to drive up to same number of SPI slaves. -.. only:: esp32s2 +.. only:: esp32s2 or esp32s3 - SPI2 and SPI3 are general purpose SPI controllers. They are open to users. SPI2 and SPI3 have independent signal buses with the same respective names. SPI2 has {IDF_TARGET_SPI2_CS_NUM} CS lines. SPI3 has {IDF_TARGET_SPI3_CS_NUM} CS lines. Each CS line can be used to drive one SPI slave. @@ -439,10 +439,10 @@ The main parameter that determines the transfer speed for large transactions is Transaction Duration ^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28"} -{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10"} -{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27"} -{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9"} +{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26"} +{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11"} +{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24"} +{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9"} Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transaction. diff --git a/docs/en/api-reference/peripherals/spi_slave.rst b/docs/en/api-reference/peripherals/spi_slave.rst index f574ec2395..9eac56573e 100644 --- a/docs/en/api-reference/peripherals/spi_slave.rst +++ b/docs/en/api-reference/peripherals/spi_slave.rst @@ -7,7 +7,7 @@ SPI Slave driver is a program that controls {IDF_TARGET_NAME}'s SPI peripherals Overview of {IDF_TARGET_NAME}'s SPI peripherals ----------------------------------------------- -.. only:: esp32 or esp32s2 +.. only:: esp32 or esp32s2 or esp32s3 {IDF_TARGET_NAME} integrates two general purpose SPI controllers which can be used as slave nodes driven by an off-chip SPI master @@ -158,7 +158,7 @@ You can also configure a GPIO pin through which the Device will signal to the Ho SCLK Frequency Requirements ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_MAX_FREQ:default="40", esp32="10", esp32s2="40", esp32c3="60"} +{IDF_TARGET_MAX_FREQ:default="40", esp32="10", esp32s2="40", esp32c3="60", esp32s3="60} The SPI slaves are designed to operate at up to {IDF_TARGET_MAX_FREQ} MHz. The data cannot be recognized or received correctly if the clock is too fast or does not have a 50% duty cycle. @@ -216,4 +216,3 @@ API Reference ------------- .. include-build-file:: inc/spi_slave.inc - From c5afd7ce34fbc64339de6a8aa90ca67c4c1aa0d6 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 18 Aug 2021 10:52:16 +0800 Subject: [PATCH 124/310] i2s: fix write failure on ESP32 in 32bit slave mode --- components/driver/i2s.c | 399 +++++++++++------- components/driver/include/driver/i2s.h | 8 +- components/driver/test/test_i2s.c | 7 +- components/esp_lcd/src/esp_lcd_panel_io_i2s.c | 2 +- components/hal/esp32/include/hal/i2s_ll.h | 22 +- components/hal/esp32c3/include/hal/i2s_ll.h | 24 +- components/hal/esp32h2/include/hal/i2s_ll.h | 30 +- components/hal/esp32s2/include/hal/i2s_ll.h | 22 +- components/hal/esp32s3/include/hal/i2s_ll.h | 24 +- components/hal/i2s_hal.c | 65 ++- components/hal/include/hal/i2s_hal.h | 38 +- components/hal/include/hal/i2s_types.h | 22 +- components/soc/esp32/include/soc/soc_caps.h | 3 +- docs/en/api-reference/peripherals/i2s.rst | 6 +- 14 files changed, 413 insertions(+), 259 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index bffea378d9..e433510012 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -18,10 +18,13 @@ #include "driver/i2s.h" #include "hal/gpio_hal.h" #include "hal/i2s_hal.h" -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC #include "driver/dac.h" +#endif // SOC_I2S_SUPPORTS_DAC + +#if SOC_I2S_SUPPORTS_ADC #include "adc1_private.h" -#endif +#endif // SOC_I2S_SUPPORTS_ADC #if SOC_GDMA_SUPPORTED #include "esp_private/gdma.h" @@ -65,8 +68,8 @@ static const char *TAG = "I2S"; typedef struct { char **buf; int buf_size; - int rw_pos; - void *curr_ptr; + volatile int rw_pos; + volatile void *curr_ptr; SemaphoreHandle_t mux; xQueueHandle queue; lldesc_t **desc; @@ -91,7 +94,6 @@ typedef struct { #else i2s_isr_handle_t i2s_isr_handle; /*!< I2S Interrupt handle*/ #endif - int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */ bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor on underflow */ bool use_apll; /*!< I2S use APLL clock */ int fixed_mclk; /*!< I2S fixed MLCK clock */ @@ -110,18 +112,90 @@ static portMUX_TYPE i2s_spinlock[SOC_I2S_NUM] = { [0 ... SOC_I2S_NUM - 1] = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED, }; -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC static int _i2s_adc_unit = -1; static int _i2s_adc_channel = -1; #endif -/*------------------------------------------------------------- +/* + * This block is an overview of APIs in i2s.c + * Functions with [main] tag are summary functions that provide main i2s service + * Functions with [helper] tag are helper functions that served for summary functions + * Functions with [intr] tag are interrupt handling functions or interrupt callback functions + ------------------------------------------------------------- I2S GPIO operation ------------------------------------------------------------- - [helper] gpio_matrix_out_check_and_set - [helper] gpio_matrix_in_check_and_set - [helper] i2s_check_set_mclk - [main] i2s_set_pin + ------------------------------------------------------------- + I2S DMA operation + ------------------------------------------------------------- + - [intr] i2s_dma_rx_callback + - [intr] i2s_dma_tx_callback + - [intr] i2s_intr_handler_default + - [helper] i2s_dma_intr_init + - [helper] i2s_tx_reset + - [helper] i2s_rx_reset + - [helper] i2s_tx_start + - [helper] i2s_rx_start + - [helper] i2s_tx_stop + - [helper] i2s_rx_stop + ------------------------------------------------------------- + I2S buffer operation + ------------------------------------------------------------- + - [helper] i2s_get_buf_size + - [helper] i2s_delete_dma_buffer + - [helper] i2s_alloc_dma_buffer + - [main] i2s_realloc_dma_buffer + - [main] i2s_destroy_dma_object + - [main] i2s_create_dma_object + - [main] i2s_zero_dma_buffer + ------------------------------------------------------------- + I2S clock operation + ------------------------------------------------------------- + - [helper] i2s_get_source_clock + - [helper] i2s_calculate_adc_dac_clock + - [helper] i2s_calculate_pdm_tx_clock + - [helper] i2s_calculate_pdm_rx_clock + - [helper] i2s_calculate_common_clock + - [main] i2s_calculate_clock + ------------------------------------------------------------- + I2S configuration + ------------------------------------------------------------- + - [helper] i2s_get_max_channel_num + - [helper] i2s_get_active_channel_num + - [helper] i2s_set_dac_mode + - [helper] _i2s_adc_mode_recover + - [main] i2s_set_adc_mode + - [main] i2s_adc_enable + - [main] i2s_adc_disable + - [helper] i2s_set_sample_rates + - [main] i2s_pcm_config + - [helper] i2s_set_pdm_rx_down_sample + - [helper] i2s_set_pdm_tx_up_sample + - [helper] i2s_check_cfg_validity + - [helper] i2s_tx_set_clk_and_channel + - [helper] i2s_rx_set_clk_and_channel + - [main] i2s_get_clk + - [main] i2s_set_clk + ------------------------------------------------------------- + I2S driver operation + ------------------------------------------------------------- + - [main] i2s_start + - [main] i2s_stop + - [helper] i2s_driver_init + - [helper] i2s_dma_object_init + - [main] i2s_driver_install + - [main] i2s_driver_uninstall + - [main] i2s_write + - [main] i2s_write_expand + - [main] i2s_read + -------------------------------------------------------------*/ + +/*------------------------------------------------------------- + I2S GPIO operation -------------------------------------------------------------*/ /** * @brief I2S GPIO matrix set ouput @@ -209,7 +283,7 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); if (pin == NULL) { -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); #else return ESP_ERR_INVALID_ARG; @@ -257,17 +331,6 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) /*------------------------------------------------------------- I2S DMA operation - ------------------------------------------------------------- - - [intr] i2s_dma_rx_callback - - [intr] i2s_dma_tx_callback - - [intr] i2s_intr_handler_default - - [helper] i2s_dma_intr_init - - [helper] i2s_tx_reset - - [helper] i2s_rx_reset - - [helper] i2s_tx_start - - [helper] i2s_rx_start - - [helper] i2s_tx_stop - - [helper] i2s_rx_stop -------------------------------------------------------------*/ #if SOC_GDMA_SUPPORTED /** @@ -278,7 +341,8 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) * @param event_data GDMA rx event data * @param user_data GDMA user data * @return - * - whether need yield + * - true need yield + * - false no need */ static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { @@ -433,19 +497,25 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) * - ESP_ERR_INVALID_ARG Invalid arguments * - ESP_ERR_INVALID_STATE GDMA state error */ -static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num) +static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num, int intr_flag) { #if SOC_GDMA_SUPPORTED /* Set GDMA trigger module */ gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S}; + + switch (i2s_num) { #if SOC_I2S_NUM > 1 - /* Set GDMA trigger instance */ - trig.instance_id = (i2s_num == I2S_NUM_0) ? SOC_GDMA_TRIG_PERIPH_I2S0 : SOC_GDMA_TRIG_PERIPH_I2S1; -#else - trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0; -#endif // SOC_I2S_NUM + case I2S_NUM_1: + trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1; + break; +#endif + default: + trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0; + break; + } + /* Set GDMA config */ - gdma_channel_alloc_config_t dma_cfg = {.flags.reserve_sibling = 1}; + gdma_channel_alloc_config_t dma_cfg = {}; if ( p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX; /* Register a new GDMA tx channel */ @@ -466,7 +536,7 @@ static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num) } #else /* Initial I2S module interrupt */ - ESP_RETURN_ON_ERROR(esp_intr_alloc(i2s_periph_signal[i2s_num].irq, p_i2s[i2s_num]->intr_alloc_flags, i2s_intr_handler_default, p_i2s[i2s_num], &p_i2s[i2s_num]->i2s_isr_handle), TAG, "Register I2S Interrupt error"); + ESP_RETURN_ON_ERROR(esp_intr_alloc(i2s_periph_signal[i2s_num].irq, intr_flag, i2s_intr_handler_default, p_i2s[i2s_num], &p_i2s[i2s_num]->i2s_isr_handle), TAG, "Register I2S Interrupt error"); #endif // SOC_GDMA_SUPPORTED return ESP_OK; } @@ -548,11 +618,11 @@ static void i2s_rx_start(i2s_port_t i2s_num) */ static void i2s_tx_stop(i2s_port_t i2s_num) { + i2s_hal_stop_tx(&(p_i2s[i2s_num]->hal)); #if SOC_GDMA_SUPPORTED gdma_stop(p_i2s[i2s_num]->tx_dma_chan); #else i2s_hal_stop_tx_link(&(p_i2s[i2s_num]->hal)); - i2s_hal_stop_tx(&(p_i2s[i2s_num]->hal)); i2s_hal_disable_tx_intr(&(p_i2s[i2s_num]->hal)); i2s_hal_disable_tx_dma(&(p_i2s[i2s_num]->hal)); #endif @@ -565,11 +635,11 @@ static void i2s_tx_stop(i2s_port_t i2s_num) */ static void i2s_rx_stop(i2s_port_t i2s_num) { + i2s_hal_stop_rx(&(p_i2s[i2s_num]->hal)); #if SOC_GDMA_SUPPORTED gdma_stop(p_i2s[i2s_num]->rx_dma_chan); #else i2s_hal_stop_rx_link(&(p_i2s[i2s_num]->hal)); - i2s_hal_stop_rx(&(p_i2s[i2s_num]->hal)); i2s_hal_disable_rx_intr(&(p_i2s[i2s_num]->hal)); i2s_hal_disable_rx_dma(&(p_i2s[i2s_num]->hal)); #endif @@ -577,14 +647,6 @@ static void i2s_rx_stop(i2s_port_t i2s_num) /*------------------------------------------------------------- I2S buffer operation - ------------------------------------------------------------- - - [helper] i2s_get_buf_size - - [helper] i2s_delete_dma_buffer - - [helper] i2s_alloc_dma_buffer - - [main] i2s_realloc_dma_buffer - - [main] i2s_destroy_dma_object - - [main] i2s_create_dma_object - - [main] i2s_zero_dma_buffer -------------------------------------------------------------*/ /** * @brief I2S get DMA buffer size @@ -647,14 +709,14 @@ static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj) uint32_t buf_cnt = p_i2s[i2s_num]->dma_buf_count; for (int cnt = 0; cnt < buf_cnt; cnt++) { /* Allocate DMA buffer */ - dma_obj->buf[cnt] = (char *) heap_caps_calloc(1, dma_obj->buf_size, MALLOC_CAP_DMA); + dma_obj->buf[cnt] = (char *) heap_caps_calloc(dma_obj->buf_size, sizeof(char), MALLOC_CAP_DMA); ESP_GOTO_ON_FALSE(dma_obj->buf[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma buffer"); /* Initialize DMA buffer to 0 */ memset(dma_obj->buf[cnt], 0, dma_obj->buf_size); ESP_LOGD(TAG, "Addr[%d] = %d", cnt, (int)dma_obj->buf[cnt]); /* Allocate DMA descpriptor */ - dma_obj->desc[cnt] = (lldesc_t *) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); + dma_obj->desc[cnt] = (lldesc_t *) heap_caps_calloc(1, sizeof(lldesc_t), MALLOC_CAP_DMA); ESP_GOTO_ON_FALSE(dma_obj->desc[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma description entry"); } /* DMA descriptor must be initialize after all descriptor has been created, otherwise they can't be linked together as a chain */ @@ -759,22 +821,26 @@ static esp_err_t i2s_create_dma_object(i2s_port_t i2s_num, i2s_dma_t **dma) uint32_t buf_cnt = p_i2s[i2s_num]->dma_buf_count; /* Allocate new DMA structure */ *dma = (i2s_dma_t *) malloc(sizeof(i2s_dma_t)); - ESP_RETURN_ON_FALSE(dma, ESP_ERR_NO_MEM, TAG, "DMA object secondary pointer is NULL"); + ESP_RETURN_ON_FALSE(*dma, ESP_ERR_NO_MEM, TAG, "DMA object allocate failed"); /* Allocate DMA buffer poiter */ - (*dma)->buf = (char **)malloc(sizeof(char *) * buf_cnt); + (*dma)->buf = (char **)heap_caps_calloc(buf_cnt, sizeof(char *), MALLOC_CAP_DMA); if (!(*dma)->buf) { goto err; } - memset((*dma)->buf, 0, sizeof(char *) * buf_cnt); - /* Allocate DMA descriptor poiter */ - (*dma)->desc = (lldesc_t **) malloc(sizeof(lldesc_t *) * buf_cnt); + /* Allocate secondary pointer of DMA descriptor chain */ + (*dma)->desc = (lldesc_t **)heap_caps_calloc(buf_cnt, sizeof(lldesc_t *), MALLOC_CAP_DMA); if (!(*dma)->desc) { goto err; } - memset((*dma)->desc, 0, sizeof(lldesc_t *) * buf_cnt); /* Create queue and mutex */ (*dma)->queue = xQueueCreate(buf_cnt - 1, sizeof(char *)); + if (!(*dma)->queue) { + goto err; + } (*dma)->mux = xSemaphoreCreateMutex(); + if (!(*dma)->mux) { + goto err; + } return ESP_OK; err: @@ -821,13 +887,6 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) /*------------------------------------------------------------- I2S clock operation - ------------------------------------------------------------- - - [helper] i2s_get_source_clock - - [helper] i2s_calculate_adc_dac_clock - - [helper] i2s_calculate_pdm_tx_clock - - [helper] i2s_calculate_pdm_rx_clock - - [helper] i2s_calculate_common_clock - - [main] i2s_calculate_clock -------------------------------------------------------------*/ #if SOC_I2S_SUPPORTS_APLL /** @@ -863,7 +922,7 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) * * @return ESP_ERR_INVALID_ARG or ESP_OK */ -float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) +static float i2s_apll_get_division_coefficient(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) { int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000; @@ -898,8 +957,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in min_diff = SOC_I2S_APLL_MAX_FREQ; for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) { - max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, _sdm2, 0); - min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, _sdm2, 31); + max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, 255, _sdm2, 0); + min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, 0, _sdm2, 31); avg = (max_rate + min_rate) / 2; if (abs(avg - rate) < min_diff) { min_diff = abs(avg - rate); @@ -908,8 +967,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in } min_diff = SOC_I2S_APLL_MAX_FREQ; for (_odir = 0; _odir < 32; _odir ++) { - max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, *sdm2, _odir); - min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, *sdm2, _odir); + max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, 255, *sdm2, _odir); + min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, 0, *sdm2, _odir); avg = (max_rate + min_rate) / 2; if (abs(avg - rate) < min_diff) { min_diff = abs(avg - rate); @@ -918,8 +977,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in } min_diff = SOC_I2S_APLL_MAX_FREQ; for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) { - max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, _sdm2, *odir); - min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, _sdm2, *odir); + max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, 255, _sdm2, *odir); + min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, 0, _sdm2, *odir); avg = (max_rate + min_rate) / 2; if (abs(avg - rate) < min_diff) { min_diff = abs(avg - rate); @@ -929,8 +988,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in min_diff = SOC_I2S_APLL_MAX_FREQ; for (_sdm1 = 0; _sdm1 < 256; _sdm1 ++) { - max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, _sdm1, *sdm2, *odir); - min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, _sdm1, *sdm2, *odir); + max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, _sdm1, *sdm2, *odir); + min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, _sdm1, *sdm2, *odir); avg = (max_rate + min_rate) / 2; if (abs(avg - rate) < min_diff) { min_diff = abs(avg - rate); @@ -940,7 +999,7 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in min_diff = SOC_I2S_APLL_MAX_FREQ; for (_sdm0 = 0; _sdm0 < 256; _sdm0 ++) { - avg = i2s_apll_get_fi2s(bits_per_sample, _sdm0, *sdm1, *sdm2, *odir); + avg = i2s_apll_get_division_coefficient(bits_per_sample, _sdm0, *sdm1, *sdm2, *odir); if (abs(avg - rate) < min_diff) { min_diff = abs(avg - rate); *sdm0 = _sdm0; @@ -966,7 +1025,10 @@ static uint32_t i2s_get_source_clock(i2s_port_t i2s_num, bool use_apll, uint32_t int sdm1 = 0; int sdm2 = 0; int odir = 0; - if ((fixed_mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / 16) < SOC_I2S_APLL_MIN_RATE) { + if (fixed_mclk == 0) { + ESP_LOGI(TAG, "fixed_mclk is not set, set to 128 MHz as default"); + fixed_mclk = 128000000; + }else if ((fixed_mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / 16) < SOC_I2S_APLL_MIN_RATE) { ESP_LOGW(TAG, "fixed_mclk is too small, use I2S_CLK_D2CLK as default clock source"); goto err; } @@ -990,7 +1052,7 @@ err: #endif } -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC /** * @brief I2S calculate clock for built-in ADC/DAC mode * @@ -1022,7 +1084,7 @@ static esp_err_t i2s_calculate_adc_dac_clock(int i2s_num, i2s_hal_clock_cfg_t *c return ESP_OK; } -#endif // SOC_I2S_SUPPORTS_ADC_DAC +#endif // SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC #if SOC_I2S_SUPPORTS_PDM_TX /** @@ -1037,7 +1099,7 @@ static esp_err_t i2s_calculate_adc_dac_clock(int i2s_num, i2s_hal_clock_cfg_t *c static esp_err_t i2s_calculate_pdm_tx_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) { ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); - ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode == I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); /* Set I2S module clock */ clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk); @@ -1074,7 +1136,7 @@ static esp_err_t i2s_calculate_pdm_tx_clock(int i2s_num, i2s_hal_clock_cfg_t *cl static esp_err_t i2s_calculate_pdm_rx_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) { ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); - ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode == I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); /* Set I2S module clock */ clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk); @@ -1111,19 +1173,37 @@ static esp_err_t i2s_calculate_common_clock(int i2s_num, i2s_hal_clock_cfg_t *cl { ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); - /* Temp value for simplification */ uint32_t rate = p_i2s[i2s_num]->hal_cfg.sample_rate; - uint32_t chan_num = p_i2s[i2s_num]->hal_cfg.total_chan; + uint32_t chan_num = p_i2s[i2s_num]->hal_cfg.total_chan < 2 ? 2 : p_i2s[i2s_num]->hal_cfg.total_chan; uint32_t chan_bit = p_i2s[i2s_num]->hal_cfg.chan_bits; - i2s_mclk_multiple_t multi = p_i2s[i2s_num]->mclk_multiple ? p_i2s[i2s_num]->mclk_multiple : I2S_MCLK_MULTIPLE_256; - + uint32_t multi; /* Set I2S module clock */ clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk); + /* Calculate multiple */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_MASTER) { + multi = p_i2s[i2s_num]->mclk_multiple ? p_i2s[i2s_num]->mclk_multiple : I2S_MCLK_MULTIPLE_256; + } else { + /* Only need to set the multiple of mclk to sample rate for MASTER mode, + * because BCK and WS clock are provided by the external codec in SLAVE mode. + * The multiple should be big enough to get a high module clock which could detect the edges of externel clock more accurately, + * otherwise the data we receive or send would get a large latency and go wrong due to the slow module clock. + * But on ESP32 and ESP32S2, due to the different clock work mode in hardware, + * their multiple should be set to an appropriate range according to the sample bits, + * and this particular multiple finally aims at guaranteeing the bclk_div not smaller than 8, + * if not, the I2S may can't send data or send wrong data. + * Here use 'SOC_I2S_SUPPORTS_TDM' to differentialize other chips with ESP32 and ESP32S2. + */ +#if SOC_I2S_SUPPORTS_TDM + multi = clk_cfg->sclk / rate; +#else + multi = 64 * chan_bit; +#endif + } /* Set I2S bit clock */ clk_cfg->bclk = rate * chan_num * chan_bit; /* Set I2S bit clock division according to the sample rate and multiple of mclk */ clk_cfg->bclk_div = rate * multi / clk_cfg->bclk; - /* Get I2S master clock, mclk = bclk * bclk_div */ + /* Get I2S master clock, mclk = bclk * bclk_div = rate * multiple */ clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div; /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; @@ -1146,47 +1226,45 @@ static esp_err_t i2s_calculate_common_clock(int i2s_num, i2s_hal_clock_cfg_t *cl */ static esp_err_t i2s_calculate_clock(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *clk_cfg) { -#if SOC_I2S_SUPPORTS_ADC_DAC - if (p_i2s[i2s_num]->hal_cfg.mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { - ESP_RETURN_ON_ERROR(i2s_calculate_adc_dac_clock(i2s_num, clk_cfg), TAG, "ADC/DAC clock calculate failed"); + /* Calculate clock for ADC mode */ +#if SOC_I2S_SUPPORTS_ADC + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) { + ESP_RETURN_ON_ERROR(i2s_calculate_adc_dac_clock(i2s_num, clk_cfg), TAG, "ADC clock calculate failed"); return ESP_OK; } -#endif +#endif // SOC_I2S_SUPPORTS_ADC + /* Calculate clock for DAC mode */ +#if SOC_I2S_SUPPORTS_DAC + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_DAC_BUILT_IN) { + ESP_RETURN_ON_ERROR(i2s_calculate_adc_dac_clock(i2s_num, clk_cfg), TAG, "DAC clock calculate failed"); + return ESP_OK; + } +#endif // SOC_I2S_SUPPORTS_DAC + + /* Calculate clock for PDM mode */ +#if SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM) { #if SOC_I2S_SUPPORTS_PDM_TX - if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM && p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { - ESP_RETURN_ON_ERROR(i2s_calculate_pdm_tx_clock(i2s_num, clk_cfg), TAG, "PDM TX clock calculate failed"); - return ESP_OK; - } -#endif + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + ESP_RETURN_ON_ERROR(i2s_calculate_pdm_tx_clock(i2s_num, clk_cfg), TAG, "PDM TX clock calculate failed"); + } +#endif // SOC_I2S_SUPPORTS_PDM_TX #if SOC_I2S_SUPPORTS_PDM_RX - if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM && p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { - ESP_RETURN_ON_ERROR(i2s_calculate_pdm_rx_clock(i2s_num, clk_cfg), TAG, "PDM RX clock calculate failed"); + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + ESP_RETURN_ON_ERROR(i2s_calculate_pdm_rx_clock(i2s_num, clk_cfg), TAG, "PDM RX clock calculate failed"); + } +#endif // SOC_I2S_SUPPORTS_PDM_RX return ESP_OK; } -#endif +#endif // SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX + + /* Calculate clock for common mode */ ESP_RETURN_ON_ERROR(i2s_calculate_common_clock(i2s_num, clk_cfg), TAG, "Common clock calculate failed"); return ESP_OK; } /*------------------------------------------------------------- I2S configuration - ------------------------------------------------------------- - - [helper] i2s_get_max_channel_num - - [helper] i2s_get_active_channel_num - - [helper] i2s_set_dac_mode - - [helper] _i2s_adc_mode_recover - - [main] i2s_set_adc_mode - - [main] i2s_adc_enable - - [main] i2s_adc_disable - - [helper] i2s_set_sample_rates - - [main] i2s_pcm_config - - [helper] i2s_set_pdm_rx_down_sample - - [helper] i2s_set_pdm_tx_up_sample - - [helper] i2s_check_cfg_validity - - [helper] i2s_tx_set_clk_and_channel - - [helper] i2s_rx_set_clk_and_channel - - [main] i2s_get_clk - - [main] i2s_set_clk -------------------------------------------------------------*/ #if SOC_I2S_SUPPORTS_TDM /** @@ -1194,7 +1272,7 @@ static esp_err_t i2s_calculate_clock(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *cl * * @param chan_mask I2S channel mask that indicates which channels are actived * @return - * - max actived channel number + * - Max actived channel number */ static uint32_t i2s_get_max_channel_num(i2s_channel_t chan_mask) { @@ -1205,7 +1283,8 @@ static uint32_t i2s_get_max_channel_num(i2s_channel_t chan_mask) max_chan = i + 1; } } - return max_chan; + /* Can't be smaller than 2 */ + return max_chan < 2 ? 2 : max_chan; } #endif @@ -1216,7 +1295,7 @@ static uint32_t i2s_get_max_channel_num(i2s_channel_t chan_mask) * * @param hal_cfg [input/output] I2S hal configuration structer * @return - * - active channel number + * - Active channel number */ static uint32_t i2s_get_active_channel_num(const i2s_hal_config_t *hal_cfg) { @@ -1245,7 +1324,7 @@ static uint32_t i2s_get_active_channel_num(const i2s_hal_config_t *hal_cfg) } } -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC /** * @brief I2S set built-in DAC mode * @@ -1275,7 +1354,9 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) } return ESP_OK; } +#endif // SOC_I2S_SUPPORTS_DAC +#if SOC_I2S_SUPPORTS_ADC /** * @brief ADC mode recover * @@ -1372,7 +1453,7 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) /** * @brief Configure I2S a/u-law decompress or compress * @note This function should be called after i2s driver installed - * Only take effecttive when the i2s 'communication_format' is set to 'I2S_COMM_FORMAT_STAND_PCM_SHORT' or 'I2S_COMM_FORMAT_STAND_PCM_LONG' + * Only take effect when the i2s 'communication_format' is set to 'I2S_COMM_FORMAT_STAND_PCM_SHORT' or 'I2S_COMM_FORMAT_STAND_PCM_LONG' * * @param i2s_num I2S_NUM_0 * @param pcm_cfg Including mode selection and a/u-law decompress or compress configuration paramater @@ -1477,7 +1558,7 @@ static esp_err_t i2s_check_cfg_validity(i2s_port_t i2s_num, i2s_hal_config_t *cf ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode not supported on current chip"); #endif // SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC /* Check built-in ADC/DAC mode */ if (cfg->mode & (I2S_MODE_ADC_BUILT_IN | I2S_MODE_DAC_BUILT_IN)) { ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S built-in ADC/DAC only support on I2S0"); @@ -1487,7 +1568,7 @@ static esp_err_t i2s_check_cfg_validity(i2s_port_t i2s_num, i2s_hal_config_t *cf ESP_RETURN_ON_FALSE((cfg->mode & I2S_MODE_TX) || (cfg->mode & I2S_MODE_RX), ESP_ERR_INVALID_ARG, TAG, "I2S no TX/RX mode selected"); /* Check communication format */ ESP_RETURN_ON_FALSE(cfg->comm_fmt && (cfg->comm_fmt < I2S_COMM_FORMAT_STAND_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid communication formats"); -#endif // SOC_I2S_SUPPORTS_ADC_DAC +#endif // SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC return ESP_OK; } @@ -1553,20 +1634,30 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ if (p_i2s[i2s_num]->last_buf_size) { cfg->sample_rate = rate; cfg->sample_bits = bits_cfg & 0xFFFF; - cfg->chan_bits = (bits_cfg >> 16) ? (bits_cfg >> 16) : cfg->sample_bits; + cfg->chan_bits = (bits_cfg >> 16) > cfg->sample_bits ? (bits_cfg >> 16) : cfg->sample_bits; #if SOC_I2S_SUPPORTS_TDM cfg->chan_mask = ch; + cfg->chan_fmt = ch == I2S_CHANNEL_MONO ? I2S_CHANNEL_FMT_ONLY_RIGHT : cfg->chan_fmt; cfg->active_chan = i2s_get_active_channel_num(cfg); uint32_t max_channel = i2s_get_max_channel_num(cfg->chan_mask); /* If total channel is smaller than max actived channel number then set it to the max active channel number */ cfg->total_chan = p_i2s[i2s_num]->hal_cfg.total_chan < max_channel ? max_channel : p_i2s[i2s_num]->hal_cfg.total_chan; -#endif -#if !SOC_I2S_SUPPORTS_TDM - cfg->active_chan = i2s_get_active_channel_num(cfg); - cfg->total_chan = ch == I2S_CHANNEL_MONO ? 2 : cfg->active_chan; +#else /* Default */ - cfg->chan_fmt = cfg->chan_fmt < I2S_CHANNEL_FMT_ONLY_RIGHT ? I2S_CHANNEL_FMT_ONLY_RIGHT : cfg->chan_fmt; + cfg->chan_fmt = ch == I2S_CHANNEL_MONO ? I2S_CHANNEL_FMT_ONLY_RIGHT : cfg->chan_fmt; + cfg->active_chan = i2s_get_active_channel_num(cfg); + cfg->total_chan = 2; #endif + if (cfg->mode & I2S_MODE_TX) { + xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), cfg); + xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + } + if (cfg->mode & I2S_MODE_RX) { + xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), cfg); + xSemaphoreGive(p_i2s[i2s_num]->rx->mux); + } } uint32_t data_bits = cfg->sample_bits; @@ -1578,42 +1669,27 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ i2s_stop(i2s_num); i2s_hal_clock_cfg_t clk_cfg; - i2s_hal_clock_cfg_t *p_clk_cfg = NULL; - - /* If uising chips like ESP32 and ESP32S2 - * Only need to calculate clock for MASTER mode - * Because BCK and WS clock are provided by the external codec in SLAVE mode - * In SLAVE mode, the mclk_div and bck_div will be set to 1 - * So that we can get a high module clock which could detect the edges of externel clock more accurately - * Otherwise the data we receive or send would get a large latency and go wrong due to the slow module clock - * But ESP32 and ESP32S2 have to calculate and set the clock to guarantee the function in slave mode - * Here use 'SOC_I2S_SUPPORTS_TDM' to differentialize ESP32 and ESP32S2 with other chips - */ -#if SOC_I2S_SUPPORTS_TDM - if (cfg->mode & I2S_MODE_MASTER) { -#endif - p_clk_cfg = &clk_cfg; - /* To get sclk, mclk, mclk_div bclk and bclk_div */ - i2s_calculate_clock(i2s_num, p_clk_cfg); -#if SOC_I2S_SUPPORTS_TDM - } -#endif + /* To get sclk, mclk, mclk_div bclk and bclk_div */ + i2s_calculate_clock(i2s_num, &clk_cfg); uint32_t buf_size = i2s_get_buf_size(i2s_num); bool need_realloc = p_i2s[i2s_num]->last_buf_size != buf_size; - p_i2s[i2s_num]->last_buf_size = buf_size; /* TX mode clock reset */ if (cfg->mode & I2S_MODE_TX) { ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->tx, ESP_ERR_INVALID_ARG, TAG, "I2S TX DMA object has not initialized yet"); /* Waiting for transmit finish */ xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); - i2s_tx_set_clk_and_channel(i2s_num, p_clk_cfg); + i2s_tx_set_clk_and_channel(i2s_num, &clk_cfg); /* If buffer size changed, the DMA buffer need realloc */ if (need_realloc) { p_i2s[i2s_num]->tx->buf_size = buf_size; ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->tx); } + /* If not the first time, update I2S tx channel style */ + if (p_i2s[i2s_num]->last_buf_size) { + i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); + } /* Reset the queue to avoid receive invalid data */ xQueueReset(p_i2s[i2s_num]->tx->queue); xSemaphoreGive(p_i2s[i2s_num]->tx->mux); @@ -1624,7 +1700,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->rx, ESP_ERR_INVALID_ARG, TAG, "I2S TX DMA object has not initialized yet"); /* Waiting for receive finish */ xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); - i2s_rx_set_clk_and_channel(i2s_num, p_clk_cfg); + i2s_rx_set_clk_and_channel(i2s_num, &clk_cfg); /* If buffer size changed, the DMA buffer need realloc */ if (need_realloc) { p_i2s[i2s_num]->rx->buf_size = buf_size; @@ -1632,11 +1708,17 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ /* Reset the end-of-frame number */ i2s_hal_set_rx_eof_num(&(p_i2s[i2s_num]->hal), buf_size); } + /* If not the first time, update I2S rx channel style */ + if (p_i2s[i2s_num]->last_buf_size) { + i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); + } /* Reset the queue to avoid receiving invalid data */ xQueueReset(p_i2s[i2s_num]->rx->queue); xSemaphoreGive(p_i2s[i2s_num]->rx->mux); ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d rx DMA buffer malloc failed", i2s_num); } + /* Update last buffer size */ + p_i2s[i2s_num]->last_buf_size = buf_size; /* I2S start */ i2s_start(i2s_num); @@ -1646,16 +1728,6 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ /*------------------------------------------------------------- I2S driver operation - ------------------------------------------------------------- - - [main] i2s_start - - [main] i2s_stop - - [helper] i2s_driver_init - - [helper] i2s_dma_object_init - - [main] i2s_driver_install - - [main] i2s_driver_uninstall - - [main] i2s_write - - [main] i2s_write_expand - - [main] i2s_read -------------------------------------------------------------*/ /** * @brief Start I2S driver @@ -1736,7 +1808,6 @@ static esp_err_t i2s_driver_init(i2s_port_t i2s_num, const i2s_config_t *i2s_con p_i2s[i2s_num]->dma_buf_count = i2s_config->dma_buf_count; p_i2s[i2s_num]->dma_buf_len = i2s_config->dma_buf_len; p_i2s[i2s_num]->last_buf_size = 0; - p_i2s[i2s_num]->intr_alloc_flags = i2s_config->intr_alloc_flags; p_i2s[i2s_num]->use_apll = i2s_config->use_apll; p_i2s[i2s_num]->fixed_mclk = i2s_config->fixed_mclk; p_i2s[i2s_num]->mclk_multiple = i2s_config->mclk_multiple; @@ -1791,7 +1862,7 @@ static esp_err_t i2s_driver_init(i2s_port_t i2s_num, const i2s_config_t *i2s_con /* Calculate actived channel number in channel mask */ p_i2s[i2s_num]->hal_cfg.active_chan = i2s_get_active_channel_num(&p_i2s[i2s_num]->hal_cfg); /* Total channel number is equal to the actived channel number in non-TDM mode */ - p_i2s[i2s_num]->hal_cfg.total_chan = p_i2s[i2s_num]->hal_cfg.active_chan; + p_i2s[i2s_num]->hal_cfg.total_chan = 2; #endif return ESP_OK; } @@ -1837,7 +1908,6 @@ static esp_err_t i2s_dma_object_init(i2s_port_t i2s_num) esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue) { esp_err_t ret = ESP_OK; - i2s_obj_t *pre_alloc_i2s_obj = NULL; /* Step 1: Check the validity of input parameters */ /* Check the validity of i2s device number */ @@ -1848,7 +1918,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, ESP_RETURN_ON_FALSE((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), ESP_ERR_INVALID_ARG, TAG, "I2S buffer length at most 1024 and more than 8"); /* Step 2: Allocate driver object and register to platform */ - pre_alloc_i2s_obj = calloc(1, sizeof(i2s_obj_t)); + i2s_obj_t *pre_alloc_i2s_obj = calloc(1, sizeof(i2s_obj_t)); ESP_RETURN_ON_FALSE(pre_alloc_i2s_obj, ESP_ERR_NO_MEM, TAG, "no mem for I2S driver"); ret = i2s_priv_register_object(pre_alloc_i2s_obj, i2s_num); if (ret != ESP_OK) { @@ -1860,40 +1930,43 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, /* Step 3: Initialize I2S object, assign configarations */ ESP_GOTO_ON_ERROR(i2s_driver_init(i2s_num, i2s_config), err, TAG, "I2S init failed"); /* Check the validity of I2S configuration */ - ESP_GOTO_ON_ERROR(i2s_check_cfg_validity(i2s_num, &(p_i2s[i2s_num]->hal_cfg)), err, TAG, "I2S configuration is invalid"); + ESP_GOTO_ON_ERROR(i2s_check_cfg_validity(i2s_num, &(pre_alloc_i2s_obj->hal_cfg)), err, TAG, "I2S configuration is invalid"); /* Get device instance */ - i2s_hal_get_instance(&(p_i2s[i2s_num]->hal), i2s_num); + i2s_hal_init(&(pre_alloc_i2s_obj->hal), i2s_num); #ifdef CONFIG_PM_ENABLE - esp_pm_lock_type_t pm_lock = ESP_PM_NO_LIGHT_SLEEP; + esp_pm_lock_type_t pm_lock = ESP_PM_APB_FREQ_MAX; #if SOC_I2S_SUPPORTS_APLL if (i2s_config->use_apll) { pm_lock = ESP_PM_NO_LIGHT_SLEEP; } #endif // SOC_I2S_SUPPORTS_APLL - ESP_GOTO_ON_ERROR(esp_pm_lock_create(pm_lock, 0, "i2s_driver", &p_i2s[i2s_num]->pm_lock), err, TAG, "I2S pm lock error"); + ESP_GOTO_ON_ERROR(esp_pm_lock_create(pm_lock, 0, "i2s_driver", &pre_alloc_i2s_obj->pm_lock), err, TAG, "I2S pm lock error"); #endif //CONFIG_PM_ENABLE /* Step 4: Initialize I2S DMA interrupt and DMA object */ - ESP_GOTO_ON_ERROR(i2s_dma_intr_init(i2s_num), err, TAG, "I2S interrupt initailze failed"); + ESP_GOTO_ON_ERROR(i2s_dma_intr_init(i2s_num, i2s_config->intr_alloc_flags), err, TAG, "I2S interrupt initailze failed"); /* Initialize I2S DMA object */ ESP_GOTO_ON_ERROR(i2s_dma_object_init(i2s_num), err, TAG, "I2S dma object create failed"); -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC /* If using built-in ADC, we need to enable ADC power manerge*/ - if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) { + if (pre_alloc_i2s_obj->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) { adc_power_acquire(); } #endif + /* Enable module clock */ + i2s_hal_enable_module_clock(&p_i2s[i2s_num]->hal); /* Step 5: Initialize I2S configuration and set the configurations to register */ - i2s_hal_init(&(p_i2s[i2s_num]->hal), &p_i2s[i2s_num]->hal_cfg); + i2s_hal_config_param(&(pre_alloc_i2s_obj->hal), &pre_alloc_i2s_obj->hal_cfg); /* Step 6: Initialise i2s event queue if user needs */ if (i2s_queue) { pre_alloc_i2s_obj->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); - ESP_GOTO_ON_ERROR((pre_alloc_i2s_obj->i2s_queue != NULL), err, TAG, "I2S queue create failed"); + printf("queue handle %p\n", pre_alloc_i2s_obj->i2s_queue); + ESP_GOTO_ON_FALSE(pre_alloc_i2s_obj->i2s_queue, ESP_ERR_NO_MEM, err, TAG, "I2S queue create failed"); *((QueueHandle_t *) i2s_queue) = pre_alloc_i2s_obj->i2s_queue; ESP_LOGI(TAG, "queue free spaces: %d", uxQueueSpacesAvailable(pre_alloc_i2s_obj->i2s_queue)); } else { @@ -1924,7 +1997,7 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_STATE, TAG, "I2S port %d has not installed", i2s_num); i2s_obj_t *obj = p_i2s[i2s_num]; i2s_stop(i2s_num); -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE); #endif #if SOC_GDMA_SUPPORTED @@ -1964,6 +2037,8 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) p_i2s[i2s_num]->pm_lock = NULL; } #endif + /* Disable module clock */ + i2s_hal_disable_module_clock(&p_i2s[i2s_num]->hal); i2s_priv_deregister_object(i2s_num); free(obj); return ESP_OK; diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 53dd2799a7..6fffd9311e 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -17,7 +17,7 @@ #include "driver/periph_ctrl.h" #include "esp_intr_alloc.h" -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC #include "driver/adc.h" #endif @@ -430,7 +430,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_ */ float i2s_get_clk(i2s_port_t i2s_num); -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC /** * @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad, * and set ADC parameters. @@ -466,7 +466,9 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num); * - ESP_ERR_INVALID_STATE Driver state error */ esp_err_t i2s_adc_disable(i2s_port_t i2s_num); +#endif // SOC_I2S_SUPPORTS_ADC +#if SOC_I2S_SUPPORTS_DAC /** * @brief Set I2S dac mode, I2S built-in DAC is disabled by default * @@ -481,7 +483,7 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num); * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode); -#endif //SOC_I2S_SUPPORTS_ADC_DAC +#endif //SOC_I2S_SUPPORTS_DAC #ifdef __cplusplus diff --git a/components/driver/test/test_i2s.c b/components/driver/test/test_i2s.c index 2e303b6e3d..5a0e79755d 100644 --- a/components/driver/test/test_i2s.c +++ b/components/driver/test/test_i2s.c @@ -380,11 +380,12 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]") i2s_write(I2S_NUM_1, data_wr, sizeof(uint8_t) * 400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS); printf("write data size: %d\n", i2s_bytes_write); int flag = 0; // break loop flag - int end_position = 0; + volatile int end_position = 0; // write data to slave while (!flag) { TEST_ESP_OK(i2s_read(I2S_NUM_0, i2s_read_buff + length, 10000 - length, &bytes_read, 1000 / portTICK_PERIOD_MS)); if (bytes_read > 0) { + printf("read data size: %d\n", bytes_read); for (int i = length; i < length + bytes_read; i++) { if (i2s_read_buff[i] == 100) { flag = 1; @@ -494,7 +495,7 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]") TEST_ASSERT(initial_size == esp_get_free_heap_size()); } -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC /* Only ESP32 need I2S adc/dac test */ TEST_CASE("I2S adc test", "[i2s]") { @@ -560,7 +561,9 @@ TEST_CASE("I2S adc test", "[i2s]") free(i2sReadBuffer); i2s_driver_uninstall(I2S_NUM_0); } +#endif +#if SOC_I2S_SUPPORTS_DAC TEST_CASE("I2S dac test", "[i2s]") { // dac, adc i2s diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2s.c b/components/esp_lcd/src/esp_lcd_panel_io_i2s.c index f132b3bd29..653a50a016 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i2s.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2s.c @@ -536,7 +536,7 @@ static unsigned long i2s_lcd_select_periph_clock(i2s_hal_context_t *hal) #error "invalid LCD peripheral clock source" #endif i2s_ll_tx_clk_set_src(hal->dev, clock_source); - i2s_ll_clk_cal_t clk_cal_config = { + i2s_ll_mclk_div_t clk_cal_config = { .mclk_div = LCD_PERIPH_CLOCK_PRE_SCALE, .a = 1, .b = 0, diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 159446b41d..fd20c406cb 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -50,7 +50,7 @@ typedef struct { uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) uint16_t a; uint16_t b; // The decimal part of module clock devider, the decimal is: b/a -} i2s_ll_clk_cal_t; +} i2s_ll_mclk_div_t; /** * @brief Enable DMA descriptor owner check @@ -98,6 +98,18 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) } } +/** + * @brief I2S module disable clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + if (hw->clkm_conf.clk_en == 1) { + hw->clkm_conf.clk_en = 0; + } +} + /** * @brief I2S tx msb right enable * @@ -272,7 +284,7 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; @@ -296,7 +308,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; @@ -713,9 +725,9 @@ static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) * @brief Enable I2S loopback mode * * @param hw Peripheral I2S hardware instance address. - * @param loopback_en Set true to enable loopback mode. + * @param loopback_en Set true to share BCK and WS signal for tx module and rx module. */ -static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool loopback_en) +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool loopback_en) { hw->conf.sig_loopback = loopback_en; } diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 44f9142c1a..670db91616 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -44,7 +44,7 @@ typedef struct { uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) uint16_t a; uint16_t b; // The decimal part of module clock devider, the decimal is: b/a -} i2s_ll_clk_cal_t; +} i2s_ll_mclk_div_t; /** * @brief I2S module general init, enable I2S clock. @@ -56,6 +56,16 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) hw->tx_clkm_conf.clk_en = 1; } +/** + * @brief I2S module disable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + hw->tx_clkm_conf.clk_en = 0; +} + /** * @brief Enable I2S tx module clock * @@ -201,7 +211,7 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { if (set->a == 0 || set->b == 0) { hw->tx_clkm_div_conf.tx_clkm_div_x = 0; @@ -240,7 +250,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { if (set->a == 0 || set->b == 0) { hw->rx_clkm_div_conf.rx_clkm_div_x = 0; @@ -783,6 +793,10 @@ static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) /** * @brief Enable TX mono mode + * @note MONO in hardware means only one channel got data, but another doesn't + * MONO in software means two channel share same data + * This function aims to use MONO in software meaning + * so 'tx_mono' and 'tx_chan_equal' should be enabled at the same time * * @param hw Peripheral I2S hardware instance address. * @param mono_ena Set true to enable mono mde. @@ -809,9 +823,9 @@ static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) * @brief Enable loopback mode * * @param hw Peripheral I2S hardware instance address. - * @param ena Set true to enable loopback mode. + * @param ena Set true to share BCK and WS signal for tx module and rx module. */ -static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool ena) { hw->tx_conf.sig_loopback = ena; } diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index d9c70cd130..e241ac2185 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -45,7 +45,7 @@ typedef struct { uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) uint16_t a; uint16_t b; // The decimal part of module clock devider, the decimal is: b/a -} i2s_ll_clk_cal_t; +} i2s_ll_mclk_div_t; /** * @brief I2S module general init, enable I2S clock. @@ -57,6 +57,16 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) hw->tx_clkm_conf.clk_en = 1; } +/** + * @brief I2S module disable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + hw->tx_clkm_conf.clk_en = 0; +} + /** * @brief Enable I2S tx module clock * @@ -202,7 +212,7 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { if (set->a == 0 || set->b == 0) { hw->tx_clkm_div_conf.tx_clkm_div_x = 0; @@ -241,7 +251,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { if (set->a == 0 || set->b == 0) { hw->rx_clkm_div_conf.rx_clkm_div_x = 0; @@ -785,9 +795,9 @@ static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) * @brief Enable loopback mode * * @param hw Peripheral I2S hardware instance address. - * @param ena Set true to enable loopback mode. + * @param ena Set true to share BCK and WS signal for tx module and rx module. */ -static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool ena) { hw->tx_conf.sig_loopback = ena; } @@ -806,13 +816,18 @@ static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) /** * @brief Enable TX mono mode + * @note MONO in hardware means only one channel got data, but another doesn't + * MONO in software means two channel share same data + * This function aims to use MONO in software meaning + * so 'tx_mono' and 'tx_chan_equal' should be enabled at the same time * * @param hw Peripheral I2S hardware instance address. * @param mono_ena Set true to enable mono mde. */ static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { - abort(); + hw->tx_conf.tx_mono = mono_ena; + hw->tx_conf.tx_chan_equal = mono_ena; } /** @@ -823,7 +838,8 @@ static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) */ static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { - abort(); + hw->rx_conf.rx_mono = mono_ena; + hw->rx_conf.rx_mono_fst_vld = mono_ena; } #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 725d4343b2..6f453221ee 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -45,7 +45,7 @@ typedef struct { uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) uint16_t a; uint16_t b; // The decimal part of module clock devider, the decimal is: b/a -} i2s_ll_clk_cal_t; +} i2s_ll_mclk_div_t; #define I2S_LL_EVENT_TX_EOF (1 << 12) #define I2S_LL_BCK_MAX_PRESCALE (64) @@ -97,6 +97,18 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) } } +/** + * @brief I2S module disable clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + if (hw->clkm_conf.clk_en == 1) { + hw->clkm_conf.clk_en = 0; + } +} + /** * @brief I2S tx msb right enable * @@ -268,7 +280,7 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; @@ -292,7 +304,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); hw->clkm_conf.clkm_div_b = set->b; @@ -813,9 +825,9 @@ static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) * @brief Enable I2S loopback mode * * @param hw Peripheral I2S hardware instance address. - * @param loopback_en Set true to enable loopback mode. + * @param loopback_en Set true to share BCK and WS signal for tx module and rx module. */ -static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool loopback_en) +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool loopback_en) { hw->conf.sig_loopback = loopback_en; } diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 8f5de0f56d..5e27b9352e 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -45,7 +45,7 @@ typedef struct { uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) uint16_t a; uint16_t b; // The decimal part of module clock devider, the decimal is: b/a -} i2s_ll_clk_cal_t; +} i2s_ll_mclk_div_t; /** * @brief I2S module general init, enable I2S clock. @@ -57,6 +57,16 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) hw->tx_clkm_conf.clk_en = 1; } +/** + * @brief I2S module disable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + hw->tx_clkm_conf.clk_en = 0; +} + /** * @brief Enable I2S tx module clock * @@ -204,7 +214,7 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { if (set->a == 0 || set->b == 0) { hw->tx_clkm_div_conf.tx_clkm_div_x = 0; @@ -243,7 +253,7 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { if (set->a == 0 || set->b == 0) { hw->rx_clkm_div_conf.rx_clkm_div_x = 0; @@ -808,6 +818,10 @@ static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) /** * @brief Enable TX mono mode + * @note MONO in hardware means only one channel got data, but another doesn't + * MONO in software means two channel share same data + * This function aims to use MONO in software meaning + * so 'tx_mono' and 'tx_chan_equal' should be enabled at the same time * * @param hw Peripheral I2S hardware instance address. * @param mono_ena Set true to enable mono mde. @@ -834,9 +848,9 @@ static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) * @brief Enable loopback mode * * @param hw Peripheral I2S hardware instance address. - * @param ena Set true to enable loopback mode. + * @param ena Set true to share BCK and WS signal for tx module and rx module. */ -static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool ena) { hw->tx_conf.sig_loopback = ena; } diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 431a887484..1f49ac1c65 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -25,15 +25,18 @@ * Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a) * * @param clk_cfg I2S clock configuration(input) - * @param cal Point to `i2s_ll_clk_cal_t` structure(output). + * @param cal Point to `i2s_ll_mclk_div_t` structure(output). */ -static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_clk_cal_t *cal) +static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal) { int ma = 0; int mb = 0; cal->mclk_div = clk_cfg->mclk_div; cal->a = 1; cal->b = 0; + if (!clk_cfg->sclk) { + return; + } uint32_t freq_diff = clk_cfg->sclk - clk_cfg->mclk * cal->mclk_div; uint32_t min = ~0; for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) { @@ -62,7 +65,7 @@ void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel) void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg) { - i2s_ll_clk_cal_t mclk_set; + i2s_ll_mclk_div_t mclk_set; i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set); i2s_ll_tx_set_clk(hal->dev, &mclk_set); i2s_ll_tx_set_bck_div_num(hal->dev, clk_cfg->bclk_div); @@ -70,7 +73,7 @@ void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cf void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg) { - i2s_ll_clk_cal_t mclk_set; + i2s_ll_mclk_div_t mclk_set; i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set); i2s_ll_rx_set_clk(hal->dev, &mclk_set); i2s_ll_rx_set_bck_div_num(hal->dev, clk_cfg->bclk_div); @@ -88,36 +91,12 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal) i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave } -void i2s_hal_get_instance(i2s_hal_context_t *hal, int i2s_num) +void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num) { /* Get hardware instance */ hal->dev = I2S_LL_GET_HW(i2s_num); - /* Enable I2S module clock */ - i2s_ll_enable_clock(hal->dev); } -#if SOC_I2S_SUPPORTS_ADC_DAC -void i2s_hal_enable_adc_dac_mode(i2s_hal_context_t *hal, i2s_mode_t mode) -{ - if (mode & I2S_MODE_DAC_BUILT_IN) { - i2s_ll_enable_builtin_dac(hal->dev, true); - } - /* In ADC built-in mode, we need to call i2s_set_adc_mode to initialize the specific ADC channel. - * In the current stage, we only support ADC1 and single channel mode. - * In default data mode, the ADC data is in 12-bit resolution mode. - */ - if (mode & I2S_MODE_ADC_BUILT_IN) { - i2s_ll_enable_builtin_adc(hal->dev, true); - } -} - -void i2s_hal_disable_adc_dac_mode(i2s_hal_context_t *hal) -{ - i2s_ll_enable_builtin_dac(hal->dev, false); - i2s_ll_enable_builtin_adc(hal->dev, false); -} -#endif - #if SOC_I2S_SUPPORTS_PDM_TX void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate) { @@ -271,18 +250,26 @@ void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t #endif } -void i2s_hal_init(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { -#if SOC_I2S_SUPPORTS_ADC_DAC - if (hal_cfg->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { - i2s_hal_enable_adc_dac_mode(hal, hal_cfg->mode); - /* Return directly if using ADC/DAC mode, no need to set othet configurations */ +#if SOC_I2S_SUPPORTS_ADC + if (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN) { + /* In ADC built-in mode, we need to call i2s_set_adc_mode to initialize the specific ADC channel. + * In the current stage, we only support ADC1 and single channel mode. + * In default data mode, the ADC data is in 12-bit resolution mode. + */ + i2s_ll_enable_builtin_adc(hal->dev, true); return; } - /* If not using built-in ADC/DAC, disable them */ - i2s_hal_disable_adc_dac_mode(hal); + i2s_ll_enable_builtin_adc(hal->dev, false); +#endif +#if SOC_I2S_SUPPORTS_DAC + if (hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) { + i2s_ll_enable_builtin_dac(hal->dev, true); + return; + } + i2s_ll_enable_builtin_dac(hal->dev, false); #endif - /* Set configurations for TX mode */ if (hal_cfg->mode & I2S_MODE_TX) { i2s_ll_tx_stop(hal->dev); @@ -320,8 +307,8 @@ void i2s_hal_init(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) } /* Set configurations for full-duplex mode */ - if ((hal_cfg->mode & I2S_MODE_RX) && (hal_cfg->mode & I2S_MODE_TX)) { - i2s_ll_enable_loop_back(hal->dev, true); + if ((hal_cfg->mode & I2S_MODE_RX) && (hal_cfg->mode & I2S_MODE_TX)) { + i2s_ll_share_bck_ws(hal->dev, true); if (hal_cfg->mode & I2S_MODE_MASTER) { i2s_hal_enable_master_fd_mode(hal); } else { diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index 3c436db179..a08813db80 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -74,6 +74,20 @@ typedef struct { uint32_t version; } i2s_hal_context_t; +/** + * @brief Enable I2S module clock + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_module_clock(hal) i2s_ll_enable_clock((hal)->dev); + +/** + * @brief Disable I2S module clock + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_module_clock(hal) i2s_ll_disable_clock((hal)->dev); + /** * @brief Reset I2S TX channel * @@ -109,7 +123,7 @@ typedef struct { * @param hal Context of the HAL layer * @param i2s_num The uart port number, the max port number is (I2S_NUM_MAX -1) */ -void i2s_hal_get_instance(i2s_hal_context_t *hal, int i2s_num); +void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num); /** * @brief Configure I2S source clock @@ -141,7 +155,7 @@ void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t * @param hal Context of the HAL layer * @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t` */ -void i2s_hal_init(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); +void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); /** * @brief Enable I2S master full-duplex mode @@ -264,7 +278,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cf * * @param hal Context of the HAL layer */ -#define i2s_hal_enable_sig_loopback(hal) i2s_ll_enable_loop_back((hal)->dev, true) +#define i2s_hal_enable_sig_loopback(hal) i2s_ll_share_bck_ws((hal)->dev, true) /** * @brief Set I2S configuration for common TX mode @@ -501,7 +515,7 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal); #define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_rx_get_eof_des_addr((hal)->dev, addr) #endif -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC /** * @brief Enable Builtin DAC * @@ -516,13 +530,6 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal); */ #define i2s_hal_enable_builtin_adc(hal) i2s_ll_enable_builtin_adc((hal)->dev, true); -/** - * @brief Disable Builtin DAC - * - * @param hal Context of the HAL layer - */ -#define i2s_hal_disable_builtin_dac(hal) i2s_ll_enable_builtin_dac((hal)->dev, false); - /** * @brief Disable Builtin ADC * @@ -531,6 +538,15 @@ void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal); #define i2s_hal_disable_builtin_adc(hal) i2s_ll_enable_builtin_adc((hal)->dev, false); #endif +#if SOC_I2S_SUPPORTS_DAC +/** + * @brief Disable Builtin DAC + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_builtin_dac(hal) i2s_ll_enable_builtin_dac((hal)->dev, false); +#endif + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/i2s_types.h b/components/hal/include/hal/i2s_types.h index d22dfc5c0e..48d745eb2f 100644 --- a/components/hal/include/hal/i2s_types.h +++ b/components/hal/include/hal/i2s_types.h @@ -92,12 +92,12 @@ typedef enum { I2S_COMM_FORMAT_STAND_MAX, /*!< standard max*/ //old definition will be removed in the future. - // I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ - // I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ - // I2S_COMM_FORMAT_I2S_LSB __attribute__((deprecated)) = 0x02, /*!< I2S format LSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_LSB) correspond to `I2S_COMM_FORMAT_STAND_MSB`*/ - // I2S_COMM_FORMAT_PCM __attribute__((deprecated)) = 0x04, /*!< I2S communication format PCM, correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ - // I2S_COMM_FORMAT_PCM_SHORT __attribute__((deprecated)) = 0x04, /*!< PCM Short, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_SHORT) correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ - // I2S_COMM_FORMAT_PCM_LONG __attribute__((deprecated)) = 0x08, /*!< PCM Long, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG) correspond to `I2S_COMM_FORMAT_STAND_PCM_LONG`*/ + I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ + I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/ + I2S_COMM_FORMAT_I2S_LSB __attribute__((deprecated)) = 0x02, /*!< I2S format LSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_LSB) correspond to `I2S_COMM_FORMAT_STAND_MSB`*/ + I2S_COMM_FORMAT_PCM __attribute__((deprecated)) = 0x04, /*!< I2S communication format PCM, correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ + I2S_COMM_FORMAT_PCM_SHORT __attribute__((deprecated)) = 0x04, /*!< PCM Short, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_SHORT) correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/ + I2S_COMM_FORMAT_PCM_LONG __attribute__((deprecated)) = 0x08, /*!< PCM Long, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG) correspond to `I2S_COMM_FORMAT_STAND_PCM_LONG`*/ } i2s_comm_format_t; /** @@ -123,11 +123,13 @@ typedef enum { I2S_MODE_SLAVE = (0x1 << 1), /*!< Slave mode*/ I2S_MODE_TX = (0x1 << 2), /*!< TX mode*/ I2S_MODE_RX = (0x1 << 3), /*!< RX mode*/ -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC //built-in DAC functions are only supported on I2S0 for ESP32 chip. I2S_MODE_DAC_BUILT_IN = (0x1 << 4), /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/ +#endif // SOC_I2S_SUPPORTS_DAC +#if SOC_I2S_SUPPORTS_ADC I2S_MODE_ADC_BUILT_IN = (0x1 << 5), /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/ -#endif +#endif // SOC_I2S_SUPPORTS_ADC // PDM functions are only supported on I2S0 (all chips). I2S_MODE_PDM = (0x1 << 6), /*!< I2S PDM mode*/ } i2s_mode_t; @@ -152,7 +154,7 @@ typedef enum { I2S_MCLK_MULTIPLE_384 = 384, /*!< mclk = sample_rate * 384 */ } i2s_mclk_multiple_t; -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC /** * @brief I2S DAC mode for i2s_set_dac_mode. * @@ -165,7 +167,7 @@ typedef enum { I2S_DAC_CHANNEL_BOTH_EN = 0x3, /*!< Enable both of the I2S built-in DAC channels.*/ I2S_DAC_CHANNEL_MAX = 0x4, /*!< I2S built-in DAC mode max index*/ } i2s_dac_mode_t; -#endif //SOC_I2S_SUPPORTS_ADC_DAC +#endif //SOC_I2S_SUPPORTS_DAC #if SOC_I2S_SUPPORTS_PCM /** diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index e2bd1842b4..54dd6b674a 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -137,7 +137,8 @@ #define SOC_I2S_NUM (2) #define SOC_I2S_SUPPORTS_PDM_TX (1) #define SOC_I2S_SUPPORTS_PDM_RX (1) -#define SOC_I2S_SUPPORTS_ADC_DAC (1) // ESP32 support ADC and DAC +#define SOC_I2S_SUPPORTS_ADC (1) // ESP32 support ADC and DAC +#define SOC_I2S_SUPPORTS_DAC (1) #define SOC_I2S_SUPPORTS_APLL (1)// ESP32 support APLL #define SOC_I2S_APLL_MIN_FREQ (250000000) diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index 6fd3bd2415..99e4924105 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -166,11 +166,11 @@ Application Example A code example for the I2S driver can be found in the directory :example:`peripherals/i2s`. -.. only:: SOC_I2S_SUPPORTS_ADC_DAC +.. only:: SOC_I2S_SUPPORTS_ADC or SOC_I2S_SUPPORTS_DAC In addition, there are two short configuration examples for the I2S driver. -.. only:: not SOC_I2S_SUPPORTS_ADC_DAC +.. only:: not SOC_I2S_SUPPORTS_ADC or SOC_I2S_SUPPORTS_DAC In addition, there is a short configuration examples for the I2S driver. @@ -310,7 +310,7 @@ Example for general usage. i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver -.. only:: SOC_I2S_SUPPORTS_ADC_DAC +.. only:: SOC_I2S_SUPPORTS_ADC or SOC_I2S_SUPPORTS_DAC Configuring I2S to use internal DAC for analog output ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 51372704bf389c487df2d0d7f91a2499945b4cb5 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Wed, 1 Sep 2021 20:34:12 +0800 Subject: [PATCH 125/310] openthread: support discovery delegate in border router --- components/openthread/lib | 2 +- .../openthread-core-esp32x-ftd-config.h | 10 ++++++++++ examples/openthread/ot_br/main/esp_ot_br.c | 6 +++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/components/openthread/lib b/components/openthread/lib index 01a326d950..1f6e937b50 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 01a326d9501b2757b4e04a900e6540c048f41b29 +Subproject commit 1f6e937b5035291645265e0fe31fd587cc1f88c0 diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 254672aa88..83be52b03a 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -188,6 +188,16 @@ #define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE + * + * Define to 1 to enable DNS-SD Server support. + * + */ +#ifndef OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE +#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 1 +#endif + #endif // CONFIG_OPENTHREAD_BORDER_ROUTER /** diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index f539db0a2d..53572c7156 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -53,6 +53,8 @@ #define TAG "esp_ot_br" +extern void otAppCliInit(otInstance *aInstance); + static int hex_digit_to_int(char hex) { if ('A' <= hex && hex <= 'F') { @@ -161,6 +163,7 @@ static void ot_task_worker(void *aContext) ESP_ERROR_CHECK(esp_openthread_border_router_init(get_example_netif())); esp_openthread_lock_acquire(portMAX_DELAY); + otAppCliInit(esp_openthread_get_instance()); create_config_network(esp_openthread_get_instance()); esp_openthread_lock_release(); @@ -179,8 +182,9 @@ void app_main(void) // Used eventfds: // * netif // * task queue + // * border router esp_vfs_eventfd_config_t eventfd_config = { - .max_fds = 2, + .max_fds = 3, }; ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); From 559c1ac3f9824dcad30ff9189ab06e5213f4c32f Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Tue, 29 Jun 2021 15:32:50 +0800 Subject: [PATCH 126/310] esp_flash: add support mxic as a main flash under spi mode --- components/esptool_py/Kconfig.projbuild | 9 ++++ components/spi_flash/esp_flash_spi_init.c | 4 ++ components/spi_flash/flash_ops.c | 6 +++ .../spi_flash/include/spi_flash_chip_driver.h | 9 ++++ components/spi_flash/spi_flash_chip_generic.c | 9 ---- components/spi_flash/spi_flash_chip_mxic.c | 41 +++++++++++++++++++ components/spi_flash/test/test_read_write.c | 29 +++++++++++-- 7 files changed, 95 insertions(+), 12 deletions(-) diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index 72e06ebbcd..61f63fda44 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -91,6 +91,7 @@ menu "Serial flasher config" choice ESPTOOLPY_FLASHMODE prompt "Flash SPI mode" default ESPTOOLPY_FLASHMODE_DIO + depends on !ESPTOOLPY_OCT_FLASH help Mode the flash chip is flashed in, as well as the default mode for the binary to run in. @@ -103,6 +104,10 @@ menu "Serial flasher config" bool "DIO" config ESPTOOLPY_FLASHMODE_DOUT bool "DOUT" + config ESPTOOLPY_FLASHMODE_FASTRD + bool "FASTRD" + config ESPTOOLPY_FLASHMODE_SLOWRD + bool "SLOWRD" endchoice # Note: we use esptool.py to flash bootloader in @@ -114,6 +119,10 @@ menu "Serial flasher config" default "dio" if ESPTOOLPY_FLASHMODE_QOUT default "dio" if ESPTOOLPY_FLASHMODE_DIO default "dout" if ESPTOOLPY_FLASHMODE_DOUT + default "dout" if ESPTOOLPY_FLASHMODE_FASTRD + default "dout" if ESPTOOLPY_FLASHMODE_SLOWRD + default "dout" if ESPTOOLPY_FLASHMODE_OPI_STR + default "dout" if ESPTOOLPY_FLASHMODE_OPI_DTR choice ESPTOOLPY_FLASHFREQ prompt "Flash SPI speed" diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 126547c20f..68c26f8102 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -68,6 +68,10 @@ esp_flash_t *esp_flash_default_chip = NULL; #define DEFAULT_FLASH_MODE SPI_FLASH_DIO #elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT) #define DEFAULT_FLASH_MODE SPI_FLASH_DOUT +#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_FASTRD) +#define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD +#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_SLOWRD) +#define DEFAULT_FLASH_MODE SPI_FLASH_SLOWRD #else #define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD #endif diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 53fbe269f6..66dfb38673 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -518,6 +518,7 @@ out: #endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL #if !CONFIG_SPI_FLASH_USE_LEGACY_IMPL +#if !CONFIG_ESPTOOLPY_OCT_FLASH extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode); extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); void IRAM_ATTR flash_rom_init(void) @@ -557,6 +558,10 @@ void IRAM_ATTR flash_rom_init(void) read_mode = ESP_ROM_SPIFLASH_DIO_MODE; #elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT read_mode = ESP_ROM_SPIFLASH_DOUT_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_FASTRD + read_mode = ESP_ROM_SPIFLASH_FASTRD_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_SLOWRD + read_mode = ESP_ROM_SPIFLASH_SLOWRD_MODE; #endif #endif //!CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32 @@ -571,6 +576,7 @@ void IRAM_ATTR flash_rom_init(void) #endif //!CONFIG_IDF_TARGET_ESP32S2 esp_rom_spiflash_config_clk(freqdiv, 1); } +#endif //CONFIG_ESPTOOLPY_OCT_FLASH #else void IRAM_ATTR flash_rom_init(void) { diff --git a/components/spi_flash/include/spi_flash_chip_driver.h b/components/spi_flash/include/spi_flash_chip_driver.h index 9a143d84d2..9d879c9e3e 100644 --- a/components/spi_flash/include/spi_flash_chip_driver.h +++ b/components/spi_flash/include/spi_flash_chip_driver.h @@ -30,6 +30,15 @@ typedef struct { uint32_t page_program_timeout; ///< Timeout for page program operation } flash_chip_op_timeout_t; +typedef struct flash_chip_dummy { + uint8_t dio_dummy_bitlen; + uint8_t qio_dummy_bitlen; + uint8_t qout_dummy_bitlen; + uint8_t dout_dummy_bitlen; + uint8_t fastrd_dummy_bitlen; + uint8_t slowrd_dummy_bitlen; +} flash_chip_dummy_t; + typedef enum { SPI_FLASH_REG_STATUS = 1, } spi_flash_register_t; diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index 0dc3062fd5..13b42c3e63 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -21,15 +21,6 @@ #include "esp_log.h" #include "esp_attr.h" -typedef struct flash_chip_dummy { - uint8_t dio_dummy_bitlen; - uint8_t qio_dummy_bitlen; - uint8_t qout_dummy_bitlen; - uint8_t dout_dummy_bitlen; - uint8_t fastrd_dummy_bitlen; - uint8_t slowrd_dummy_bitlen; -} flash_chip_dummy_t; - // These parameters can be placed in the ROM. For now we use the code in IDF. DRAM_ATTR const static flash_chip_dummy_t default_flash_chip_dummy = { .dio_dummy_bitlen = SPI_FLASH_DIO_DUMMY_BITLEN, diff --git a/components/spi_flash/spi_flash_chip_mxic.c b/components/spi_flash/spi_flash_chip_mxic.c index f88486dfd4..c40e4f5b7b 100644 --- a/components/spi_flash/spi_flash_chip_mxic.c +++ b/components/spi_flash/spi_flash_chip_mxic.c @@ -16,9 +16,13 @@ #include "spi_flash_chip_generic.h" #include "spi_flash_defs.h" #include "esp_log.h" +#include "string.h" +#include // For MIN/MAX /* Driver for MXIC flash chip */ +extern flash_chip_dummy_t *rom_flash_chip_dummy; + esp_err_t spi_flash_chip_mxic_probe(esp_flash_t *chip, uint32_t flash_id) { /* Check manufacturer and product IDs match our desired masks */ @@ -47,6 +51,43 @@ esp_err_t spi_flash_chip_mxic_read_unique_id(esp_flash_t *chip, uint64_t* flash_ return ESP_ERR_NOT_SUPPORTED; } +esp_err_t spi_flash_chip_mxic_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length) +{ + esp_err_t err = ESP_OK; + const uint32_t page_size = chip->chip_drv->page_size; + uint32_t align_address; + uint8_t temp_buffer[64]; //spiflash hal max length of read no longer than 64byte + + // Configure the host, and return + uint32_t addr_bitlen = SPI_FLASH_FASTRD_ADDR_BITLEN; + uint32_t dummy_cyclelen_base = rom_flash_chip_dummy->fastrd_dummy_bitlen;; + uint32_t read_command = CMD_FASTRD; + uint32_t read_mode = SPI_FLASH_FASTRD; + + err = chip->host->driver->configure_host_io_mode(chip->host, read_command, addr_bitlen, dummy_cyclelen_base, read_mode); + + if (err == ESP_ERR_NOT_SUPPORTED) { + ESP_LOGE(chip_name, "configure host io mode failed - unsupported"); + return err; + } + + while (err == ESP_OK && length > 0) { + memset(temp_buffer, 0xFF, sizeof(temp_buffer)); + uint32_t read_len = chip->host->driver->read_data_slicer(chip->host, address, length, &align_address, page_size); + uint32_t left_off = address - align_address; + uint32_t data_len = MIN(align_address + read_len, address + length) - address; + err = chip->host->driver->read(chip->host, temp_buffer, align_address, read_len); + + memcpy(buffer, temp_buffer + left_off, data_len); + + address += data_len; + buffer = (void *)((intptr_t)buffer + data_len); + length = length - data_len; + } + + return err; +} + spi_flash_caps_t spi_flash_chip_mxic_get_caps(esp_flash_t *chip) { spi_flash_caps_t caps_flags = 0; diff --git a/components/spi_flash/test/test_read_write.c b/components/spi_flash/test/test_read_write.c index 57db40dae7..3ca559f083 100644 --- a/components/spi_flash/test/test_read_write.c +++ b/components/spi_flash/test/test_read_write.c @@ -23,15 +23,25 @@ #include #include #include -#include #include "../cache_utils.h" #include "soc/timer_periph.h" #include "esp_heap_caps.h" +#if CONFIG_IDF_TARGET_ESP32 +#include +#elif CONFIG_IDF_TARGET_ESP32S2 +#include +#elif CONFIG_IDF_TARGET_ESP32S3 +#include +#elif CONFIG_IDF_TARGET_ESP32C3 +#include +#endif + #define MIN_BLOCK_SIZE 12 /* Base offset in flash for tests. */ static size_t start; +extern spiflash_legacy_data_t *rom_spiflash_legacy_data; static void setup_tests(void) { @@ -141,11 +151,13 @@ TEST_CASE("Test spi_flash_read", "[spi_flash][esp_flash]") #endif } +#if !CONFIG_ESPTOOLPY_OCT_FLASH extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode); extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); static void IRAM_ATTR fix_rom_func(void) { uint32_t freqdiv = 0; + uint32_t vendor_id = (rom_spiflash_legacy_data->chip.device_id >> 16); #if CONFIG_ESPTOOLPY_FLASHFREQ_80M freqdiv = 1; @@ -182,14 +194,24 @@ static void IRAM_ATTR fix_rom_func(void) read_mode = ESP_ROM_SPIFLASH_DIO_MODE; #elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT read_mode = ESP_ROM_SPIFLASH_DOUT_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_FASTRD + read_mode = ESP_ROM_SPIFLASH_FASTRD_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_SLOWRD + read_mode = ESP_ROM_SPIFLASH_SLOWRD_MODE; #endif #if !CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32 spi_common_set_dummy_output(read_mode); #endif //!CONFIG_IDF_TARGET_ESP32S2 esp_rom_spiflash_config_clk(freqdiv, 1); - esp_rom_spiflash_config_readmode(read_mode); + if (vendor_id == 0xc2) { + // If the flash vendor is mxic, it dones't support the read mode mentioned above. + // So, do nothing + } else { + esp_rom_spiflash_config_readmode(read_mode); + } } +#endif static void IRAM_ATTR test_write(int dst_off, int src_off, int len) { @@ -211,8 +233,9 @@ static void IRAM_ATTR test_write(int dst_off, int src_off, int len) fill(dst_gold + dst_off, src_off, len); } ESP_ERROR_CHECK(spi_flash_write(start + dst_off, src_buf + src_off, len)); - +#if !CONFIG_ESPTOOLPY_OCT_FLASH fix_rom_func(); +#endif spi_flash_disable_interrupts_caches_and_other_cpu(); esp_rom_spiflash_result_t rc = esp_rom_spiflash_read(start, dst_buf, sizeof(dst_buf)); From b9b2cab8f9f02288172b11bb9a2c75ab84b8c0f2 Mon Sep 17 00:00:00 2001 From: aleks Date: Mon, 9 Aug 2021 13:31:45 +0200 Subject: [PATCH 127/310] freemodbus: update the modbus documentation doc-1641 --- docs/_static/modbus-data-mapping.png | Bin 0 -> 49888 bytes docs/_static/modbus-segment.png | Bin 0 -> 23167 bytes docs/en/api-reference/protocols/modbus.rst | 681 ++++++++++++++++++--- 3 files changed, 608 insertions(+), 73 deletions(-) create mode 100644 docs/_static/modbus-data-mapping.png create mode 100644 docs/_static/modbus-segment.png diff --git a/docs/_static/modbus-data-mapping.png b/docs/_static/modbus-data-mapping.png new file mode 100644 index 0000000000000000000000000000000000000000..18fd2cf4fe3132d018be509d37121d2c764f58fa GIT binary patch literal 49888 zcmeAS@N?(olHy`uVBq!ia0y~yU~Xq%V7$%2#=yW(VfWscfq|c;#5JNMw<0YwCzV0f z*crl7H8RM^FD_9vc2PAlN-QYQOUX=3FG|cU*2_yRQ8hABH8RM}PsvQnOih8PF)}bR z)HSfsH8uz_G*&fsG%-^(b~G~5Gc_}af~ZeSPtAiGXsTzRYGj}ho|%`DUtX*Ukxwm2 zOoy12V;)dwR^psr9-L&J<>qBx92x8dQB#&$RGgWg2T^8ds%M~Q43Q|QEJ%fjrlgi- zCZ~c#ja^lZouTelH8RMAx-{LWGQHF?IlCgn$+Oh6Akxbxtq`Q#$RIB<7ivgAVtT5s zAxPBN)jZ5FDcQ`|$SuIcFs~$A)yT=q**7rKBg@ynB*!P$z&zMEBGJe^x!B*SBquk$ z(jdarH>9-4%)-?*BRM0rB^PJwG$cu`hnRGC4pMRK08 zMVND@vtNa;NoJK}u31WyS%86WMq*V}kWXojp}A3^e^k0fcz&Q^P=u#Tp0QzuxtX(* zfvII+Ze?J0h;d+1L20#Pxn)qe zaY0bAbEuPXVQ@f-mqDnPMOu}oMYdb6cSWG3OSq-EcUhThS#nWYSc-90V5WDet5Jlr zu|<@sk&{VDPM(`ddU$41Wtnl6NtCfiRdP}qNJ7=f&84bD)yOHkEX>l)+@#zq*C)!% zFv_*uzr460pwPrQy~?mGB2v}Jtt7zBH_xCrEG4@ts=zPbw4}7m)u^H*Fw3aY*D|#* zCCkXzsWQOZ*(*PyGApyhxH7=k!?@DS)hWOvG{w&)y{y!&JSi5?0($B-svOFU_$lTI2ti;dV%seW$C_JPn zJTuSGu{b={)z8}{Jjt@yA|SKeH9R@PC%-5)-K!)!&rsFKso38uB|p=pD#yF5#4o+v z!cW!6Ei|;)HL9q}%{(j9S=GqR-z_|%pu8e9rNrGSGBLe8(bEFDji zimIF|QcV)Q{Ia~06CI5+eN>IyybHqo-Oc@-J&VeG1C#vBtGt5ELc^<)RgIiXDOkv%u|x`1N@2$b9{qB0}Od?QRevO;{kBf_$( zN?pzU{G%*OQ;dC*bBb~jEz{Cni&Ol4T(Zq8QY{LLql`?=Bhrd3lZ(Qfjm@0Gat%X@ zvc1dPvRvJ~T`QA)ygiaU-E+b-({n;I$~|3Gjhv!9om1SM4V?nK!UG*G(oIa0s|@@q z^4!dll1)Pb{W8mpeM4P~eEl*lUBdz_GQ1)J0#%Ki$}KBg^YVPk!wf?+0-{R8Ju1u! zLJF%goefltoJvi-%Y#$$D~ybN{IXIb4PD$K%EKaZi^@{VL;QV8jU&xm%LAiwvO|K* zO1=FeoFaoV91Y8ziz~c>EF-=1ypod&GD?aJe2c>Ts=|{(qspS(lfv>#!kkK7lJfF% z&0GtEbAwAW{fx58ii(mmRE?YpbN!q$@ zO3Haf0lvX*CdPrr$v%!bC1JrHZceW5hUw)|X6dG-g&CDmQOSYjW|`r6{!v*4UIxXk zjz-Sro^BBV1(oiV;e~~kmVrJ#Ngyv8sT#RCmy~%`1saB!I~jOqnCFKidKE>5dAmjB z8+zq?re_*uhK1$&heZXI27CJEIHfo{I~)0wMmi=NRGDNLnxzD&8o6bLdb?(rTco@C zg38zAjDSS%%1oC6lMJ)`pt6)qpTc~1Kg0Y|Pv6qYs?36HzXE@M*PNuZVwVEb+=^VI z{HnBk123z^Lpj zU$dMrPuCp3FjMDjg((88xm;nHrcC>{MRhWKf#nos$)r=It05RhSuKnpNQxYHsY8lHu$U;uhc- z99C-Sn&O^f;hF6n>=%~d8d{iF>Ski;84#JC78Vrc=xr3~R9q0`7-Ep?SW)KTy zm3fpI2NtDQy7(EFI=dF-I0q#r24n;W2YEWC209i;`C6nFl$RQ3MHQ7~fzn5wK}2wN zMtNkFVUb^@i))FupIL6OYh+Y-pkbatxJ6Z^L4mKUm$RRfYgJ^LVMUgyZ$wz4k4LI^ zNx7v*ZepmvUqzX#k55)adXA58np=fog}HH%S$=w1REe{NSw@&wS-DYeu9KOnkyB=+ zi$Q2eX@F~3nyQhTV{xgOL2zkFfSGGlV!m;Rp`)9ZbC`LSL8fs^X_|XUX>Mx1Z?ZvZ zO0Gp%W`0CTYDkoshhbGzU_o{&sK`q3Px12c&u}zPGVsaE0fkaUh>N$kK~+F#fN@Dl zVNtGWQL15HhMR9;rFWEXvMDHnd~+hRJtI6bauP$GOP%t)N(#IxQqBDQEnOpWssc?w z^-+dpiGOl#Zcc7eQCeYAKxn#UrgvzFhnshfn{#e%RA^CHXkt-*k#ArGs5PZ(bn~1N_uNF|z{gMh5aaOaBfqJr#-5K!F| zS>;n&?2&1a>+IthoEo8O|^j%g%K+C{A^8t8{a# zip(|&^hhf-OGz*AGV)IkcQ4CHw#@Sj1=XmDVea9+seW!j898~8p1G;PReqI8xhck> zNj@o=Wj;PZ1;zm(MFAn@*~NYqmI3aOrs3uVCE5OoW=5(;PQkfJVY%kHszz>RVFj51 zKB1=mDY=D4E-v2T!QS4Hl`cUMRbei^kyWZjZb8{bW|fr%p5|r-Ub#U=ma0Z>ZblaQ zm0oTJ{^qJiATQ*V=aq-M2b=i@x)%lcWcz1ET9^h^m6+!hdqz}Rnk7|LRQaVkd8LMD zmR97Nf#NhQD=)_^$UM@(G9uY5IXpGREVT?&|0E?vMkE^*7A6&0I0hN!f*Nk6C0-U; zMfpWJNm-_jZZ7_21}T~527#p&o@puGp%!NT6;&Q3UXhvUiMcr@g-$^^r5TRt1_eHr zRVl&6-l|4UVeU==20jH@d7wB*40B3~NVo9vDD^N&FLH6t2?2$NZ?TWLnR|GmrB9BV zMM=0(XueNrrbW7MSx{(lu9Kxflu@cnc!aU4k()_bPEm14WVw-VqGSyq^t56HlR#7OhB5}y!*bg!aPP<7!~lIxi6Qx@#uAK-3YQdE`%N&)#r ziRl5VMouoE_P?2`ky}AVc5+5#mSODou)$EBwk_0}Pzf9DNL`y#2Gvj0->sLeg(Mk(ihP6IRKwh0<18FVMEDUm7BYhoR(hVa^oHBi)@-m$*G7~FvO;ggmb3zl7QVNSI{8f#d+>1)0 z40Ef(vn&k_%2Er;$}I~^j7p6IBl7c7LO{7Rup}y@s30iA-=id|G%V58HzMCSCCe?R zETt&Gyttw)r3%#S_YJJd56w=qsBrPfs`4lYbq$SORE{p1f717aX2q_Wvr6z(&zUd1#@DO=J51DCEwizH z>dLIsS;2Aad1tQ7ZJfrGP+4%}K$YkE~}t|8}1DxOm>?d*3Xp=kNV)dEfu4*3&tAuiw6xzV_?Ot>11P zV;~GTI#$f?_$4R+0!CbSE5Da!I=s*a^EdH=xX)bN7#J8D*1R~sd%ZWaQ#~gGgF^JL z&+lGexXH-CaAMXU>)j#>U#2rKFl<_C|9&6e+*qcns;Uzbk9pUoBqc4HmFMs8?|r#U z@pDSg!hQSp#eBYe^=fE&?y+OXica1?a>OOJYTF;i3vFMvZ%aST=2Rb<_3PKKtY6F5 zt71|gi#LlpCpup~#J0Di$il>A%4&n`E~WN6iB5cu?U(K!%F{LG_?x=&Vo^rV%E|nH z+5MO;eO#h`mdDO7V=3Yg`K$Z(Mvj2h?u?|T7bKjMlanjc&Bb#{r=+uov;1^A%Novu6fTnRm-;#VF~^BSi5|mSegCGF<(P5IjWt=w=Kb$Lx6$P5UQgm< zQq||A$2#yaYOws>SyG_s{6gQm_s#Sj`4|2Q%U|yLCsUNcUNnOTtY54=_bb=|Qab`9kum+wpE)iWkt=)7vq<&bNH?rG@u|1Bm-V%`dB!jOZC2}d?b%hc z%_<`$a^+jAn^u<5e~WHP-i}|Dx@)1|K{Mgi8}G6&EY3Nx=hdE**(**znWcKYa(nFj zEtj|Ga&pH$Ubt}Ku9DdOjDOh$1bpjP=xZ^z{M&TpM48KW+nyxQh`9K< z^Kw3yN^LBiaIN;hk)E>(?YZvt#(zV!z%bJ036C4yg6nS(bQqzKw`> zmeyL%d-uRex69XF?s#%)YIywdgO1mugDk&XZPjUB>pY>+y4~%mK}gumpC&>2W;Ne? zdelq!g|D7o$rHIWb8=Pqu64<~ckSB4tabgpG|Nl#T!w}Fbxfo9cIH03Z}govHa6CD zf9c)yU%x(Ikk^cDe)xPdyM^3SGZR_gzE0tS% z8*}P;rWd~0bK-pLW98_*I|_8grxl*4NQq0S-TKLnqZc)zq^3IC`SWY!@-E9MNj;pT z!`tM|m)l%Cb6##`+cbx8FI`>*PDLa>z*3I=j<(BDz$HqxmLST z>~)6&)AG&)CI0;Fsq7oszpd}qx7l0H3hjP%)@;SA7GI&DW%jF_wJbmpl3_XJEvMks zKhJVk^EuT{c+0=}Pk!`mmE$5k>(6f6+U@!D!gaUfdQ-puy?9+UcwKVN$0Miac?1Iam6S3zv_xAQ$%FoH4D$}+^DU73}?vzgZ!d=;Je6_Oq zE8qzfINj~D zc;;_~lQ(#ZZj^mlel63KYvJZ@wJmcT*}@+S?e1)gn=D`TJnBr|(kkhErSF@=H*W6V z=bNgsNoU>MvoSAko4x*cb!qnRoalMZyQjXgXlrYmW1X<;pT&h!cfGn5+SjrF&i!5# zm1(v)dgc1KFYl#f^ACSH{>9z3{X+b-Su@f<UYP*)*G5HUAkYOK2;19e-V~jc+F~` z?<%vKa{NZ!hu(e9FGy_fI5Oqv)V}u-(an;dYi4CH_X@x8b;7f1zS`SyuNS1=3ti`S zzc^#I;I^su{FXdd{ms|6P`rexL?m2s3+z))y#=D@e?lPOeuhT)v+4)Ivrx)Co zim#WelDj85W667do~P;|aq)3ADksw~8SONi#o3#kVi~(cwS8e#{x>@g+4)ZdWdp2! z)&33eRwyaE*dq1d!k7JP4}LaHS@@jQ>9j-6r>C>-ZZ_RzXl-;%E`RpTi@dY))h>p` z-S<(td?Nm4&h?Yq6Z>@bXS;jHn(gCTC>d3IUUjD9wbaa|GPgeEX(!*xyv1g>@UBPg z*GJL6c!Vy>-_;bA07ZGs+umHx_!Vn8-|kp>5nQ!>nE83(!i6vF17804npXD9Ci?fB zlJ|_U?99x}=eC7@Uw!BMtNP!koI~uxF77_p7H2$Vnar(M3TuBKn5JLZ#{xjZS65TZ+V}qT zYj4$9N&V$FFJGRVC6(H;-re8d|Lf*;>-3C{T{v*SVcE-5RokB``?s~Vt@`e*TvA$k z@xq0Gte=@``l$!MN%tO=aE^_Qm3+#x#Te{-1)tMT0=Q2cIKc2^L+ca8cA0wXQw#T; zzck7DpYN96wYPd?KK-4%Y(n!nh9V9I28Nc*nKG~Tf7`slkuTa=E+}pC;YEQemN_9a zPPrKuS(ur%-E_Vn05$ko(T%HDL#MWMc5*7Ml9kzY#P__;F1F?$jYOfMFt*D}@w{gSOe(e?&AGX+VMawT&H5aowvh|%VwaxkY z;i!7+akbcWRU04fO50VluS88vZBNmQ-DP$&3q3b$>u-un`OC}0bLEMnSLT_mUu7S! zvj6wDrLKRD_;i`JbICux&w09e(}KSih4xE5@3}HDFfatUf1ke6Rp;ph_SH5YrfypC z^n&SztDBXJ8eR%{&zAX=zU_1J(+g%hrXEsAPcqroxOSS!%z3MG=CsMU-2QaB@Ysok z(|E2I%1qbI|Fro=I$!EeiOBhL)`_S_|Euxljr~4#?Z2AuU2lzV*JgPiHm}aut)C+G zY2K!#iIY7d-*4NI^L>qojo#{>*^j3@FS2{GbK9reb-U-Zy`A?cTg;f7&w=Ca&7}^g z?hH@~`TSp4ShzIk;QwpP_O=sBJ7XrL^F1|kU6f+n{wIHKn9!G=Wxjl|sgDnC&o$6{ ze9h_IiP7-_c!zG!o0d%;@#uzzSfFrZGLTa+@^R%`mLIxjM+zhjhb`3 z&$s3-3p>4VjrUA`&6T@i3`=bc4HN(NwxyM(?lQbC&CvVqO_0KSB}N7YhLwwdpT44W zt=UI2qln?;GbNVmOe z!Rh7)VdrFa&3n#ua$)u{FD3Tv`_dQwm=WPQxw$axn^2u2}%r)ZECm`H`8%MJv`jpV{SsnBsao*j*3%6u&ddCo=UvP@&3SzuhwbW&$tIQ_+uu59eom{NcE)_Q z@b5DVr)A5Qzld7$_e`R4(Tx*ZuYNrJI&C%k?3|sKuC~mx+!CuSDL?=I)vKv%{i9`1 z{?_!hyz=zH?=$AnIlH&VZt6_O=G)r`^j`K%*1fUqZh7mH-BY``3fpGb{F-O~1y_z)6ri) zRxQx6pKkPQQjgpH;uWV=_rHGqdi6^4@W|Mr6`z$~yIoo%^UCCj-!7y3yZ(F|;O?-f^D?(y9h;W^w_T+6{zKb# z1>KVL=}eX4oD2*M9eS(J8+K6{ACucC!z-p1hOiY$< zd@9n`uQ{z6t=K-tE%G(T6LwgIqoXk4@VTQ?D#F%?7DYV!#rTs6R0lB}0_)yl3n^=P zK&l;XgR3VrDW4?EH}BuOJ2*IGXvo;r>|i}B#qbrZxxs+<=!s>MPB#bR{qEhnJI^~QC@4%(j;VOqD&R6f8)CQ5;i4P&@855F z!^m)pG0*&*#bX{0r4y_t6d4#81lWo=7*5FKnXlXXEz0Wqonpm~1y7-tPjF^%cvi5x z@UpM@#d~|JK{8Ji+bi{-yE%Xyo14+z`(2@(q2bKKvd7D2=Pg?7-oLF?!OzFX!u;OL z*RQiJ?#-JwPoy}~XV

vsNv3JK@b2`<;V{iHXVSck8CUOcnK0L8=u@PXrhyi0HPz zRp`)ZcXoCzyb9@uU}GD{4E#f#&WS-e)3yRdWWKdg2I;ajOB2Polhm+ zWWA`~?lRwW9Wyg?=c5*xH1~N$9sh(F7;Z`Dy}zCK*!F}XgF!|rbA!8e!W^_XJ!`m*Kht~ui$6dIXP>d&1r0G+_iLrQE$M%4!hZc zPm4Z&ud2*=WB5mM`O44Ir=@v1=aWYq~E{%XH>ytWzFCa zR8tfY=E!q$;WY8tXTE&-a)o0_?z0I;{f@7G>iOJznW=%ngDHXGb-6#2A5Q*x@soIU z&ot*){%v~-XD;<{0<~YB^vXP+QW+{D_(Xu=0+UlwgqtJJNkwj+)7`nkV$;m*+)gXj z=X+n@nsW7>TPOZ0EiJv8J7e)uqi+(o&n(nquD^Eqa`1F>F%M8&H|)9ic#aXb z5-7Ya4T~bo9DTIfh4!{wQElJ$!=mNM1+}K213B|sKOOgW%Y9jBv+;O_<&>{W`nO*- zo;H<Z%fQPbUkeQ_O**9-<~{g-n?DESI#xNclmGX2NqD$(d<2ucu_id zzD!wZ>D9A8GBYPJJ5HCm#iF6Y-+NBx*pq(te3|XJV#eQQs1)7M+dcJE<9@sNcN(*= zIfxZS=xmXBW#(l6n%mNc{Y0W!!QQf{>PNf$Z)ZNXy&KQw5AyD$ODkl=b{bw~ww3&{ zX2RPa>(;HaDx7ruM5J-$y&E?o?rN*$yi}Qbc*dWNSAMFfoiubQEYj$oT&N~F1yr>) zWwt#Dh~uxFtJwaweeKx^*B$pshur_)%Ve3OyX}6N^`hI4{j&ULO+2jBpQ*BIKhHb{ zOBM!|rIMC9-pRK(Z^V^fJYkr*VEU>yjY%@M(u{ssUq9e{da$3C)8one%{@KW=q3puelk|l8^b)~VlCsaQC@r7r%PQPCMiZ#1* z{`^_5vwhFIUvd*ZZv7?qAXL~Y@BY`~rxQOPzJ9{ASmKxRv~$U4^5d>8?YUo8zq^ik zo&BR1pKhh`rT+Rf!mQynY*3@ z@V~0qa7bF<<))VhJ8}b-91UPs`k%Ai@ayRc=cET-#?RzFE|stDSuL~fW%ef@6NsVt?}J?f>*cq8`b}ki2hk>zv%IGlp|4+M4|GHjTxK#T+@AN50?TS~d zublS1;q|Xw?`rRVy*w#b*rIm*k(?)wX4P)G+Ib|5f8UoHZ_THB7oC3DWv*5mUY9g& z>ZvmAFh1w~^DlI@1w_B-3O_G!>&b++nwK3YercL>xYe8oEF zwLI!@yuM#&c~5`8q?FVrz5}VUN4(;16-h+b3tj(u^}5N+uaoODHs*et;=)&(B&FPL zRD1hP@C$Q=*O>_k2duiKs-9h#x^MNLh4*Fe3olGpuKk*{yKUjpbDmExl)lY*nHf_r z^5JBn#(zaiokugCx!haL0x4@IZIjuy%Fwpx3CG)ed#%4#IKI9(7gW1`Ik`|S;6-}W zDTCq_A9I%-x-sqKE6MIHPYq7`#QR7-DfJfGzOMc@-yWlXMrUNQCf#9PIP>rgtFpff zTQlAGCZB7&{b|j5$20j2E6RSZoRfO(<1*Fug)^P+=VZP3p0!#zI{L-o()TBK+z-++qTXx!HSYA1O@k{N*ug2}$s#U*9nH2LMIVM~Dw`A|FOTCrP0`yI{bf%rz2kEh)P3!nnQnMBQE4QWdm0B-w4VWiB$$2)%t-9)ccbE14 z%$f7~QMZ2B|F_l8Hmqo>P zuvP1~+xSmcF54ayADL9H{j?^vlK;oL^*z?le%*ZZS$F@{`8(e^#{Wz%)9#(Qllw1Q zN7j4WzwI4vPcMZ2_l!$j_V?+3ML3p8PC9&J?uU-3-}9Uo{c4<)s~)QK zJ3;59_4!}Feyy3Ed*f8j?9NNfZn1qczRMh&a?tEY@zIBe%w}vmTe9QSqSLdUR`Y$` zn0cRh(;S)jGiw&SuC%|M-`QDvKJm!x{;B* zDxE9!0NmM~|AZIrt_h`ev}!o>1Suz(_{iJLi9rcLVd1d*ZxYZ8AmTCy-SoY$NzAym3d z=9y{-*tmk-g%@4LFZ!C_ol?2u+pX-EJ;vu&m@TXR{;qeDQ*=k>>m4;6%XfTSac-Uc zqg&s1@BOg(pOKn9XxMJSU(M6Usts5C69N?|^KUqoggNG!Og5R~S|lpDHy%5an0|b*)$V^C+4tXHIVAj771YgO2rM+em(6lD9@L6_+nl%l z!o63JwOV=0&-CuJeFgefv??`VG;U&p|$7m>}wUvqGO2)TH00dL{0mZTnnj z!6y^m>)t+nTJk>ktl6q3y;n;oCL}C))_UiFufMZ2E%RacuW_Jmc5R zGg~+Pz;S_JdzlVA+50hWRuhLM3&R%Ojc-N07v0&hZ1?Wnt~*)QG8D~N3mQ9{XvkJ1 z!I*!N-!g}{_r$_A?k5yG6yNuLzx2iEZoHegToDI@hLz`SZQIEmHxGYvEHBd(@DVQJ z$SIj6^Njb2z?P;x=J&Lh%GCXOxxD20-119P!{a>D=hv34E9-4&2$)y!?PmIAkXZS> zO7+@bFPC@Tn(KC3dz#A`xo!NQek$j(my?|<`@KCsoK*B~?Qu6YF$pQ|nPNKI;=_T+ zWy?RS_isO#q|saxxb>f%iffU9{^#SV8*87fRu7kbQFLri%xu=KW?zexe?2Rw>drM^ z7k!(1-_xx*OKKD?r+obK^=stQfMd%~pZ?RId}=Q~XW0&_D_?9|e$(yq ziHXWvs=qfTK3NM}3-GS(9P80XM{K949W;q8%HXy!*miPZ?uJ$8l~+v{;?v=el37x- z!Q;oJqKA{6XY-u2xmhsvutajN|FuTB9j}vXo=*PRr@P#6tC6VHvPesxAiMc8yViA| z$v(69!2fCWD<16lX*^q|?Udr$~Soy!3VT>D8AfDTyezd!BwiNn@t^y7-@x-F(M&Kd-dE z{QukC{o9f)YHRNo-t~I9sdm}L{fs|n{_8!Ny*Ax9_OzGtcLs*F%SwuNq@S0w`uSw? zNeO4~X*!LM1ZRCnLB*1n2*%|44UlZ<`?btTgJw#i? z@VwToG?y(rFPBc+2x==BY?*Vx^u%`F9m)3GQxB{9d(Qh>qPw+3ck>k!t@g81{11Iy zwtlUc%KbM=^H2Z$;5m06f6U9!R|oIExdKHr>$zGi*G!+ zVER~MQghl9gDpKh7NMRdSX6ZKIgEb=Qh!Y^gbWPG;9T>+qVY&Mkf0 z1uc7Ss&sVDwVdKTB{p^YU3EinJcJbOsQX)G^lbBU9!3TQ-yc5@e|>$uy1yCb(aWms z+tQD1s(2Pqx6J(3h37BQf9IU%`^9!(8)N~ zXPfUV%lYf(`bulYZw3tn9Z}m>n@`j2 z1h@P(W6V%pI_a?WyB*CvhFdZ&F52>mi-Ez#WlP3IC8J{(WXtb7wB>{QUuE~yUuFiG zW!r;h@7ZAS;^w*=TTHCpnv`k#YPJ9RX&7C#@UBE%Xnf`P0+X6}HaO3kbr?ym8Rb`!8^V%W4 z{l?SDM!wOtSwAl*tvTv`UZd#GwsgM9Q}kbd2aSt;t9?_=muuYg%dSW9nQi-~b-#c8 zdS!M^an*m_lSOUs7#X5iK~)OJTLF(g(75dkwRig;O>~*Zz_8#2sIqLhz}NW1fsYY9 zMiGZ!gn?m;G-yOhVT-eZC5XZBmJMb&ABf?w8(a@LS+h(650qWVLpBgad*!Lb@^bU9 z-@hw^Cx(_t?b^Ltv7LcoLYVcI*N0;xQ}{(D*gO?r1Odg<43;_q>$fZjoHa{d-tt(@_i2^)qNJE#Kb1_iopl zCZ+}8>T~Az_$lDEOIGSBSL5AE%O)H?&pESZTBZ}<qEbAGfB*%D-Ebny)t@=5K{fA7>{gVgnk1J1KdF#@f*RNN1hI6;*$BOIdACr)h zkl1j_M!2=JME5lA>*d=d9p){ZWNaH{ zlygb(@l>W`l@lgO&R*wo&aH6Hr_CETZd_3jyLq{f#`{fctk(asxm~EUzUtdq)mujP zLF;}P+xag~)po!1YsaR#(A4_-e~Qr`%$wiXXirR-C!88bGVGxJKiJaxyT zDW?^ZA79t))?)MZ!p1bknYH*0sk9X=o2SfP-_zS`Dxx2_Hly{^y3?;#G5^fJz3Gy~ z&a9Nk%r!E{t}GV|h~8!O-|+bs?RDRt?%V#Z_|!vl{@TmZ&mTN=d|eqN@x6AB{^20e z?j=P(9u#|LoZO{veg5g=_40Q6t7Im|s%&;BFVmb*IS(|69JcuP=?9z>4o6iOyyFtO z&ZbwTpnvq>x0nTDyw}szW%6@&O-eIc@~|S;I`dVsQ|0y4(yNYVOgDIL?>oL#(KloJ zjSJbDPG47++woqVD)N8H^=+~rw(9S%_%HtD==6ON>XpW2=RO>({CV$mvv=@s{;lQJ zYM#5+Oi5?!w2Rj|^=U`q^;NGv?%5M^?CA58~AD4aA>W;9ya_Gq^Z>ja0Je1lEziPf-xPJZmS@C}N zr~SWR`POSi?a#9x?_UtDUcX}U?(+V)kiwGWcye3tv= zMMkua=hs}1GTD`_sxzj-6{YP!Hui>%HwLZIybtP-?sGphHUezUp*pQB)*r%Hx@ z((UQp^)-dPch>$rd+SK1XJSuem{z*N=|4P+bDtHQo27YeuGiBu3Y$~zPG5c6{rQ@i zL7(R+b}ydidPe93YhzsHwr*ABKLc-tcF=s3#0kX=ZiV)_u9wO( z9>#LNJQS|KaJ}E@<)P{|{-h4lcf6jUE_3-oPc-O+4MaiNL^9=XY z{rEG@Cf|bvJhzhs8n^XwU;Oq$=d|IUMKQ#UQ;%Jj{uBEEc)dv19y z>(blJz`$@QMXkO3P9eKwa>m6)A1pELRANY1T~j;t+=H7IgCYk1wZ zcJ9_W+e~(>+4qZyp}|kV*m6yXR!R@J$*VQhE9xgJLy5&yuU0?Hry@qjSZ<4*SUCSi zr1R}J$v5XE>U7C$O31a{bJgl{*)!(!F#F_{i6=K6G+NR>@#Bfd647^pggUdHPUxRL zDQj|ctlZ{17eM~_Z~OXWq-oIeQ~OuX*=MvVf$y#Cr)j~@FMrE<3i94bbq0nKrkN)d z1q1W*^(B)t-rd=m`9zd~0mMk@S$OZ>y$2g79DcS^W<5*%YC&t}nd+_+4;#x{Y}V2; zo0(L(=W(m`B9_*ro?X4!%91m`mHNkri*L_=7T~qkg?p;MhvdvQ-T!7eOqQ=tMwV`# zzRM@d&GLMZ()pSPXQUc^C+RaVWSARGJ#1V3?ZQd*`98-aqBf;?N`b<`zgP|8 zuQ(^plf5!&<@D^V9OF(a-oHD&6>49ou37h`Gpp6&S+SVk?N1R53@=!WraCJvN2+lp6TliEpzr*W)|253efz zw!1g|^`t9%o=!M=+Whje{@$B+j;e)6&C5Ce@@CrUjuYDL+ji8R_W5euzwP9jX{Gk6a{s-`%a3h; z*`4d|C$?tE?y0Xnr{2;Dh~l&4jg+hPd$TDh+(ywdW#g2mSB(31^*uETKB364;4-MR zyd}0J{AuD6BcZL2UoK+qma1CoCi!H-{EL$}+}SZL{nryO`_JjOGehdu-(R^RoiF!2 z)0Dzf-xa(%uRK5U?0y*krmdci|&DM`JV_FsK1+U zvhd*H=6m5;4t#>QG*A5gDV_aaokg(0%oWrunZ&nEZ|9RquNJ)P(q6Y9eSYn>n>Nf0 zRvrF!KU>W5@A-ts6uNHJ-T7pa_o8#HGE8dRmNNen?);A8J)!7i&01-H-+q@!6Nkg> zNh@XaVs}mHF)X*MQkI1l zX*9|xZ3(_m#No)Y!1kmM-}bz_UdJRrOCm0x(q>=~5WKka`8@Aq61R4huKsRuLNP(1 zorB{n>ueb(0mck_qsgF=u!)9k&(6-C4z0+Zot^D|Od@Jq&P*ir)4}TXjV3$uoMK>z zY%JqYVJ+%txDfNn&jZG#?zdX7OB487o*EGY?-fdUj&+sfZ)Bb%McDe4<(er%z;o$RW z7bca)m(4qUJl?*h?yH5;ZjWcK>Zcy=G5vf($G{~2tj+tvw8n)mxBKR6^uD+K+8>y? zr6h&pOD{zWsjv-lIEp zOiGjofLjV*od%y)V5#7{3?Gg+N#*mx%U_m07iyn3 zZ(deq?AOK9AH1?~dYZGvW{$aJ&dZNK_Z8=y*z`%BE$4fizTbV*FLRF{=jY+Mvc%TV zFfiEew!Bu&_3L5kXYaJ{;&B!B&x`-}{QiH_yF1_gS^x>lJ4PRFd|LhW;OBWaJ_Z=r zM;<9YzRUI6hb!xjFM1UD@4a`{p;zheRN=M^C{y*D=W z^B+aQi^03)7B4Teb&Iasx=(LU`DcDb)`>Osk!6;9 zYVW=+`F1v5W%GdvkqIx}%--*Dzvhdy>G2&;3a(BIE%_L0y!!dKd)K`e?>1+fKK0a( zeLr8AXMF0Nd{W1t&OVhRY~%NQOSb>oWyK$3jWe%K3pKs&$sQ{f$^Yxmj8EsHjo1IO zoc{1z>GpJRsnFH=Mt`x@?oFo@`O7LFteM#SZGy}#CjM1h|J-1Ewyh%KlFGK4f`pk} zp8cvVmlIxoKHIhHlHa5}<)?*L3;q55AH9AwtG8!o-$IMn>jowBL<}XDXq?*9^6F+N zC=S-yJhMz*_wZZlxkK77|J&91PLWx6|7St0jq9|-I*$uaD%R`G7v59%qvrK$4ZY~R zHB2Xr+phD^kN>_Wao*Qtm-O=2i@C*E-_M+{D`8Ui>eFJ^eP@b(T>ZUXW%GdxPo&i^ zhri#y$xW*2{p+u%9iGPxF=7WLET?3ijW#}C_3m{3y9N1nzj{~s)PDV^ z4JrXVm&aCTg-%L(`e949|I(M+eV12eKMOr=zNZadM zCR~14yi}veYLna#3%mKBO@AIcX_9|-PnPWr)@54d3qO4_eSUs_)&HqiUw=63zJFpT zxP+A3wBKYI^OFl|i7s1x=F8YhTThhcld&Q zP*+1vyxor=1U+;8)ALdPooUFxf9TU%dS=r-8Q&Zxe(;qKE5;-97*o}uuxmDTs0 zMrLHv#*HTxxqIS%&2Zs6%M@(>`skuVn@o09E6*)^yRvkV*{wD$1$e%BE^ZM=UchB|P{q4%EFS$u4n{<}OUibH@%$@(4=S}$g z{YJ*%%2CJ4k1simuk+D-%PXgqDmUbE?|JC^W^;GdvGo_feDP5{u5JF{V&$f#x}Bce zCw?-ha?^3+i+!GvQ>1fR<@5V4;}YK3=P!SsnYM1tyyweoy7O^!b5+`eNVBr3#fK%Y zf9~G1=1Zq6|JBy;`x5-qyif1(eGzLEuigIn`MqD8S%1%YxRG^g{{IrkdJn$&x4uSb zKADidF2>QD(R-qptfrBUQdCZa+PQr{yGx(1yR}IxiZA!mqN6Xqm2S6YozSWo#+Q41 z=PAX{w!5kqm+sVQe<&{3H_cgd_QF42mQyMVWzSzX3b}XE+;7{l&!1-B)X{ELU<$CY za^uT2P85=3*}Nk~v3=k3-#I4Q?VoJ)_In?@G{yP4rQy?ykHn0NC9K?qmD?ftFm6`S zi{0Uuckpjj5qr7QIsW&jd++Zpt*_2JVdb#@`N^Y}PsBvPL&ULCQIEQn+C8UFZHv=a z?7vI~snb@=w;6W#TrZ1tdcNaS7Pn3=G?;@ddse1L&owEQ-<76w z+NgL%|L?=b>KC_%*X^@B0ctFWJrxq+1P#U+_?}3tE1Gfb%)(qYEW& zt=+pW&3MiPnO)QNADb2qN)XFHrPV9r$;)G_weJ4V|G!ujRH-Y(gGQ+ro+NMm)+Ik)I98?nVJ~@|%>82e{<>AJmaMLh z<)F#^&1;GzKA%yvm!E#sxZSYm#CcJ@sOs3e8$IV+UfFcy>5Q7kDX%Lp=g;;_zyHTo zs_x;#SH-Q{(%F*dS^jyp`2K>+>uj%T<=AvTKdtY*BwO;;6KVD9w#6$hM{P|FE#+L> z*ZjVH|G($+UZm%2<`8gUh-wCPyr;zSF?uLHUogYuGT+{R_v)nT{{36CnS+b%i9sCS z?7M5PY(2d^_xZWBCjsw{t^7Q*WP8x;8HJWxYBp8eI<@d|=gqZK%&%Q6I{9>R)2rKS zL*}1fe|^GNVdcYB&Qf}}uiF1w{pZPti|7CSo@>6(xqNS>_}%Isal78H{hjgi_UV_u z^Xuo={W!<}^7#9IGp_wh)9np$d$IAm+~RucPx)V-OjLila|U|OpF@YQ zmH#{W{KcgS&YEtYY}^0T9ZY)~;I-_nZF|vXvD?*r=lA{WzIr~%e96YW$rrxOJJkJt zR%Ec*w1C^ye9r3+ZHO(tccJa`()iSg;Rd&ToFCf1|8d@=s>I}X8(V`JLlK7+--*PZ zj@B%bm@IwN+I8Y|*li}isCqu%FZoAnd$w7G6Apjl*~2nv{=v!K#>sKc6T==n{|YLZuhwi>aBN>1(?Pi{GD3pBw=K_V zw#D23D4n%CUk@~p+osFK@D{mmcH8*IJkB$(EiM0^kPX? zv?+TdF}LKBXG+h)hYufa`NYleqM)t4{iKAm`rHyBS?jVh)jDv;%$Jd~E1U5z9N0J4{w}k6y=L#kl3k zgpQ1l2al#~ll-+=w*HyTvZ6gs#ox~!U8BgrXf*wBzum8nbvvKUdbI#NHaN53>(%hf z?((%FSN}QiF&01i=Q%lH7AW+eIrqp237)MfRr@=A`hV{zUp5BW?sxjl>Lyk@|TyFi{)dK6cnat`^>kS`|SLDe`RIm&Reo46chaJcxMXv2!r~uH62qA%kIDJ zc)85ad+FYYpXa=8egC*GN%xQc z&bahL#ppJVuGNMWFMlv-fTrUeZa2YIs}#*(+xA_>Nyt$hG!wr?H)A~mv!#oJMta6p znZ6LWj91;kYu6t*U@hdR&H!H6g{;6x`+j8R)FUhP{g!^@KNdYpoFR%6I;O@1NkNMG zmMLuf{MS4lT@ha%^t3{C`W}W0T%h5KZLDua6QXq6AItY#=gATj5SYbZd1%s&dXB%G z8TkkWs_nn+?zwmK=`8YmJh@2TLs?-ZFDaLWr6sBT8#f9UDfO`Tcl4;_U!HxpeZP@2E~^NuOA$2F1c6vJe0j0 zw06o}uCj$s*6K>mJw}GybN~MS&a9}Ip||VBqAcm6dzH^G9&Bb`d=4_srLw9vvF!W0 zJgJpEPhx@?7#J258cjcZb8|Xq7Uj$g$Ju7NS!SRGOsSWb`I;mj<1spR;mys>i_bO6 zFsW%qz{SYGu!VQ#sfS&n+9xEOm(Q=W+WYU<>&z$O3>OaW`St$UiW2DCauWxC!!Cg1pkH4oiivm5*0pLXsGYui4v0>#?g2Zwe&&X4*iI&0s7 z3vJKqfe>ibJa<2O9}xlA;EHu>_T)Ey-s#TT8r=Ck+b zqpef#huUxZ|6TV#&(+e!PdTS*X5KnGX{OAlLh<;TLa#_xhKBPyemv?H-s(Kz@G+!i z3pb{J)sx=cwNBn{zFu@*#^H6LruX00Bn!uGyK~{|;pf-qnx~%?i83n-ReP$ybz)&G zm%Z@e_*t%LcYK;;m>7~gHq8mJXFoCN*zp_lUQWIrzv~BgSmvYRinIwkGmnP9>YHBp zvC=-uKB8Fe`O$BZ^OJ=w;%}O4G+O#NH85%Bq)M)<{r~EBzM1wqs%xwMx*MNNisV&% zcSjmc2aktlHkYk1-5_&o#^$uH&`%&ImhIbkQmdNZZhOnKH8X?6)x8%_J84pQDzQkj zMTUuC&JQ!CiB1QY79=)qKD+6pr0wmWMP~gkj0-0$z)GJ9pw`FH5yH?8o{lD$g(QBoXKB?^Fm-5^l2`XhSHI}U~{qdyW@VZdYDh})W zKmLfi>a@DJfQA$OT#>U1okLJyo;bHsE=91@R$R6?=HzMvuGBRy(UaPoL z#_q=*p{PyoPM<6O`Qvr_`So({DdH!$6rOsRX1rCab@tgS9FTCjq0&Cx&MR=U?%gd% zk8VzL*=p>z@zdg;w+^&^S^Tvbl!vZ73GP~)Tc)>CrtMUkcDD6t#lYn6j86n2B&DQQ zb%ln9hrjw*-X-(x%a;omE(9zpmYR6j?Gocj2kR?Rlk~Ko&U9RKetOp?o4gxaS5?{Q z>rXBGSQ+_nigU8h6CcGV0t^C2R4xCU;yAX|Wzxn@f%(FlbBYcZ+iyH~>7$xS(PF8Y z?*IHIyYM-uZWdH-kJQ&Lox1*F>e9?R>=9vHYrcH>GQqIz*RNkjGmoB%z7@rIJrT6j z+e$$)qdlrQ-&yLm&wMdY&05fGzg@G&(LnE%Sv_*HYya&J=aW|c`iF_(RKGV@#RUER zzi%CAz2+Miqogu@YEe`W!&5g^o6FBmwfizung`u3ZuER&5Mn0nX|`nI$2PMig;)FS z%tH2UFgfnTIX2mqnCoO*L*lGpRIwou2&M&1qg|i`#Vis>BR=kJ(EscV!p5xa6a! z$-jdZf{uKQ3~LXnTk6CY1+0%xR5(9%ecywp9Z@1N>n%2%v zH{1W&=~7#DJilCWuiRsE->li(#3aO6_*mwNoBNj(y*Rzw&h1*~I_Bvzw@$6uIMuW6 znbzb!^R!6KY4gnZZ!Ns`V3PB{7(4ZfzaM^H3lEIhb|->$LOKs~u=o(?QnQ+i{Xa?yp&L3V~oU(QVP<%|6EJA7)D)ir*E!y6@1T(m7%d^L%r@ zRXWcX`7|kL(W4U&Q}5q)PCK|QOXBwDy2GjGXZ<@K=RfE8%k6K^7`QVqOyJ)$WwNvO z5rg$xN*>+OzDo9;Gk>Z^*RS3%2#i}^hGZYdt<32|E$q*1PZ6=LXBof~d{ z`}f9uzWGFY`{gFn{eCjxf{ijv6YRC`M@D{kH{N{q!WHr5mrj+3J)3JAzywQG2a=L* zt4>)_H(7Xk!ppf1sT)ozPOLr_bZ*tsor=CaGPj!a^<}om6xrprJnCHOJ=gDyrGn+z zEzbM@eh~h3l)F9S#mU&nbm1)=^F@q6i^fAf={+s@m23SvO-Ovr&#j?aPrvJ=rXAcS zWjVX%@wZv3Yi4bC|zpM1$Zo%;0oO1zYH`z=uapZj0BWEpsnt+&}*N(>XZ}1IQw@99|tsy^EKao(t<#uBlON%a2UE z6dvj0;}i1#?JW-X<-(K8HG_=og)DDp`uq?TIlJeSQpogeB~H&9o|s(Xv)%sM;O_q$ zd{GtOHDb%(@4p;9_5N0k?F%?Sp*riFaCeW$%9G}K>rZie_vWWfe0<^fiHawMJ-T_C zoi1C8P8|34ylULKZKm_)1nJmsdu^}Q$A8;vi?mYY--DOsd!AnTxkdN=+`8N6tbVdA z=*jSW;=7BX06d95!C4`-Cw+fXnP+Z`&Lftm>f3669{azu{onqZ<`?ek$NF=>ms{Jm z{22c>jpYjjwT^3FW%P}zf2cP}=2WDXt@4S@#ee(v%BgCY9W1dut&y%NzUF6X?45lx zozG403r1c$vU2{zEmx;c3p}@Z$_bE%1aGMPWLluZBPXY_`K-&@Eevycp9q+=%t@T= znE&FE&IIR#!`Ju8)V!{(D!I(^wZ7iFSD+}utmkIKq9Dt-g%eM4_};c$`z!q2&fm|L z36)QL67Wb^*p@r(uv)_O+Wh{~mrMTCfRe$btDBpnjJ_86_U5VuE?;P0&bfqtZ_CxG zb`yWk^t=8%^_K58jyaa!8IAUyUi+}GJ^qAEZM@ayy!uIcI}%ks+Ze3X&}Uf7P{bkS z*1a%)XWHgW2fjv^?fO%{+b`n1&39q0ecd^&7Nb2M-?3Xhm&*V({i{m0xN%wfNX>Vd z`grQH%Nna>Zl(QzD^(iZOiucaGGrOPFU)=QYt)t?T4T-lK_iW}9vD1{Xv6*p8Vd;vZjOcZm ztY@|g@;;t)ctXUkw69J@D;`hSJlo82%TmEp`;UFwqa3(LrfpvO7FlM?p2Mo`E^7tV zP9*+%^SeUcS8Bcss8f5)RF(@oMZBZ-Xa4`>#4Qs49{ayx?kMlC@z@=|`oeB^yPQHz zho==w^UU{dSvuilG+%7f;-?+0Z`l3!3#)3F?JVM)K1Kbuar>uA_nG41zjpZ$Sa4$R z`Se4Rv|HA+d3L*huYFa1{$1Vbyv$X0@p{R7^NwD=Sajm}&S`sZ?VG-N-nNn-#*xd6 zpW7vz<(}?3{dTy#=jqvEph1kx$>OpRES_%+!0ord&D<|nx4)dNJ&*I$Lu37$=?UBR z{Bb*5xc$!lnPGpvs77smCt6kW+3wb-Ptsp*MN2589X(YZmZsI}bFauFMBiA)w(59* zHYe10_Ba!Y6O z3cE?u%z3qrYnK*rc)qa#yMN*B>HPL~ZuWJbLf6aK?YQ?Z?(oIu@!VZcXO*sJ`TXVG zM1I5HHxweh6oXkTRaV{q;BqeFqj8ncH0kS~eCEfzO#hc--Fxc&S8LI)XBNJVZ7}lt zDd(a&@z?H_*`$8nWxY zJ#Dqkzr20l{+n7A@$qT(=`W^DzrUdRdf#Q;@3+rKSA5s_n{ws<9g)DbDYw$(%lC&Z zykA?QGxbyR6A@Rw?jF!e9mOwa6wmL-Y`o}gmU`hlYu3X(j~|M^*d^*8Jv~P)Htdzv z^>2SmwdeKO*}L)OZeFzRSH_Y(kqOmmHLtpZHzxYd2CXKX!WaMh)5(qgFBkIeUOVag zpLM_X`(@v={iK+C|F>Cg;v+bcAuv1j6$GQkrU7cXA9w@ryx zp?&L%rBhuBrEfAQY}D0$n*R97nTN9c`ybTE`5#lAZ#=~~^{qzxzF!($GDe_5xX%xp z+u5V%*=6X0`lT;BGULnsyprAZZr$eeRpKL z^ZjM}|Gb`^#qxH$eBGqVe>t1`zps<+pVb)i@$&R0;|Ye7Zf0!}Ii>31dgF)!zh%!| zPjSYDJ`Wf2?q2XW63QzMToF^Ch#OFsW zHt&Bp*Ijz*;egtL%ILj{ybLZA4qtiTxGR6b{dFcv?Y6eIzMONXEeq>j*}ZV#!mN3_ zcJ0dASA24z?=Pq0r$2rB@}=aCyy~QF&i8-Vf4}tq@59YoKD-MAH5j6%oIbXr{B1=+ zftdEpwKHn(eE(>-T4Yvk+phA`%Rks3uUvYS2Rs&c*wown(xKh<;x6}B>uhllyt;pv z<2>#7uLn*CZB;P+t<^ot%<<$xzxea7UOrcN`ty^dlk~cpU#|{_#_f#R-VxFlzM?wZ z95ix!FOrd$$xD{3poZ0_HFXTPP_yCjw3@7ZT{`B%xT7m4GNJfXSHRtXG}?1 z_v5Aay_?5f*~LVoxFjJnO_A4k-?!<5tRq|fzC?eajsO zPxprk#tvst!(XBOtH;g_wab|Ke=JQosZe?cm=|m@>3?f{+cJnDLhnhBB>%6U#+pV!DlsolJkIr&iA*W6+Gpd< zIdT5ZX;WXRE->_Vaz1`z-}b4B%l=e7o6xalbH5^E^2C%cMgI4HZp)tK!uR=>h=%?J zzO8*To~9a3+L?A&d*{17tH67SI4vP-)!whGUB|jV>Ou2yUXG(&phb80w!2-HxEjyq ze_+8Hx$6mW=dC;&FQ1l4o!~9^(^yj^ilye|h6OM76#kksO;@&8TW|V|7n1uVEKBA- zwmPTQzKO^1>GrdKUj6zwb@GXQI$`nr@v^7iI~{tzn*T&%^6|zht>fBP>Q~rX{H{3t zclP2(pHHgh&zbzxTCOyGI#cJVIo}V+F)qBR@c#M7y`sO~-Fp7weO~>Xb^AVhMpcx* z)mx@e9h1!0^2hlm>%|qIlWy2jzqX`RZP~-i%Uk)>;LDs@-a$DpLC4gI3xg+#gH0?; zbYq_;%q~sc!t?58B4_>cRS<`qUn#Tx!h?qgUvc+4&*nUG=HK4xCx;)rNnVp;X7zgo zB8(P16=<5Fzt51}>EFULO&KAOzEV|EdexGG9ZOsfn@9G@+`8nsYt0q)cC&*MrFZo7 z_C_xCTE6tC-ZL5BH8N_kVOgu4kA=VgRpSfBTKFysP zs`o*sj_<7y>z^j^8r%9hnbfzz z7XE*=baAoxJzxZ~A2sp;E4oV%De zJ0h<5`-^?8&5M<<^YpFTQ}yyi%n3!NL(dPYw+kG(rhJ^W{`dBJZbzK}jok`qdhO=- zYl@>PbxnSmvN3Go+N+(VUhw&>xieqzqfdLMi^p*#KjYE@aZWL8OhAKUMd|{!pz>%g_BkrWMA`2rUr(+VkzFhLYd@B3l%Plvh19&Q) zZJNB}%O&rV63)uX%J&{Cv?p3Uof~XgWMN^I`|uL)Uyx&CD!#vXVOrk*?sCzO@6C&w z6)o?4`XqfWUHbDjlIcsPUO#kr zbNk#+N<|aw_bk~mIgPio19bG3(Xk7S%0t+@W;=^vdW4?g$# z^}4TYCrof|DdX5!#Nn93Yi8M^Af`VhP{4Syv(h5X;AImG+rrkz&2@`oWM~LmALn~a zVwO>=*M}Q^(+^)Mb z87F~m@l$FYL{0$g3w{b(0{%7f(8R9#m%5*)ukKu?zrB6;ymJ<6R_bpK0 z@@#cNf5U|w53Tl8u_M>-Rn4z6+SQ)7C%*^O?yjo&yzfQ%s%>2JW#p_%I-Z@G$qb6~ z$qH#&?Jh2x)6c6V^PHVw*ld=2>q-u2ukop6zOyrq^+=}lEWEin-F@!m%p!}bk}06M zz0IFrY?*s`(Ye2;ue$vIkn;C=x$WPXJN~{nI>mT(hPdSv@S0>3rS?=2muXJ7xf(!C zQGd7ZB2FUCMI4SgaT?vAl*Z04x8(CV>-ABB;;|)yy!`x^|NZ?v`>Zv?g0naG*V}^x zT*YHUa-Gjvzqhff_>ger=UgSw{M6+|%-tE6ek|D)9#r!FRbLmVH|4VVx{z*#&QYG| z1{oy<5o;5z_O&8Ml=uIgVQ2R(Gq~`@*(EuNzwd1iK2`Ym$O&+I;c1$&Q^u%UTz}n4 z9u^jsmL-WFA06$yHP>%~^K3-3>V6z|mz-Ka|VMu0AKU@7uNCCcpkB-3}w{LrIzf;7WduNAX;q1$tMJwWy=7(_2R5|UHzW%R{fqm7+ZxXsyR(<

xuHe{x z8;9vNub+Rpa_)Q7r0>;ox9^7Rjr;3={?gU|Uvl1EcW6(0YLM;t=la>-84vF+_C2jA zXgR$%@BVMIUc3LZzFMDsJo~%l{oS+JHm&D52@cy6kg|BL!3`#cE$nkI#Px=_&6?zN zY`bEwh_jgE*{0)m+~*^X`PxkWu~_`=^UvQwZdE$1_*}PBChpVP`IqNZn_X=+{`U+t ze6TY6pR=yuk+dfpA~&8fTB6t<$@$1z_0P$%bGX5!=XxsK=5isn>Zzg%DOY4ds035Wl%tm#m? z)FJb$?`d+Eg|fP{`iaC_O%+eJ%U?F1X8(4o^UmKHwbwi#eQ8e%&e_ghk^Rs4>K45}zs|q- z{rdZL+3#1*eSa}2|L>kTBh0tB=q7XwDzgpJ(J_n{;0GUc6Q%ZhH^c9tr4|z;hA^W zwLrO{}r?pd$Pzx2q5&rZl6gj|N$MJ-YHLZ`!kWvu{t@5?ge_NPYk8z1!-( z^`~>?e$oI<929YCnJv+rCj+wd!phCzm)5-Rx#rPpGtISS|Ks$3PxebsJZ$+rXH|9I zhDggNCTX?HzeUA-T08$b$J;gUd%~XjcU=#*zQ5Y*>Xz*G>`y1=|2}2)+Iq3+^K-w> zWo(_dZ{M%VTYsMw{`&Rm`Rbn!AIshQl=jv7^6ooTz9};;-Ug?yUo-9Hq4ocJ=H2=! z2M&r&UYgUcubNtPqetP?bDq?Q-HF?SxuU$;K)66WRq&EclX6$>-&p?)7LKv zPG8S+O7*zxBP37CQ-!qT;$A6mk z`IPiOOHoUkk{1E*m|89@EZTuqhF7O5D=3Iq`^>YMSyf&Aa$0oW!d_`}wY=gky>=HD z?fa3OnmLT>?^c>{E(5vPGxFlo0Quj4zy4l(o7sv0^R{xIOuSSDN^@VnUOj)gHU59(-Or77mOQ$iy`Hm~^8=L2<9V-^u6}YswPW9N zp4!AOmB+80Qf)1_|C=Aqe`)@|>-!aw724l=K%Fp&ZyTSSjmPu3<#AgZh+cT1-!0Sh zrcowMy?xtUz1Z_IuXtl)il#rS=8HVE<<3W*S<~G7=EsL_{C)QE)w|KTAKT|y{`vRo z@3rgIZ|XjOz8h34{r$tFklSzW+4jF(2Fks1?gTD&vbfQ zP6dw#PsjY z41QO3>d}$H6xH@UzgLLqOk2dg|KH|aHXlEC*+f6TwL(2@dr)NA^}NL~{`>BFef{ZK z-ug88>*l_gZ5J+Gs(D(Vth=XriroD@>sJ;$*)G3*!PZRP35UNe%Y9mKwCn%=z2EuQ zz1s8n_xyK$R%^@mKJGJGyCltQR-pOZWpA%IpE1d0U+lO1YLA=e7QRnvOILcl-LU#> z8Shr}C6S7M{+5-md{pze_xi_mA*VO>h|jz+QR0Zc^aLKE87EkJ1Sc7aF}ZR$_oRwQ zHWhyU`Hyk_>0qSec(SvY=Fd6KmfkDu zr^Md>;>y)`udn|5+P4dBo(I(XEzpawS)EaJZsFUHGJ6*G?9;jOzRhG=I?pV*)PwxX z(=)HgA6J}T{Nj7%q+deOdd>ZcFBa=O;wq3nk+{oqtxQ;W_~f9js_N>wnT!kv`1kJJ zyJX6uSFf_tZzY|2_~DR&>E6pJH7cy{)O+MlB$gDN*mQVO$nRd=W4sA*bAKp!@2j}E zY~{Idb-NR{I*z`sv$ii*L2 zV4MTrSqHw$zFJQU5)vAw1YNmsK_Dy|ylq=bO3Fjim6@4&-pfVP4*%?b-WwEAzKSm> zBFTa8aDUOH!@K|Qn4h(OqiTBF+3a9B7YjzqGf#hgt<1`4ky$n~DVH(tUu(m;AR=J(w@)&DAl zKE#vlc zsmCmtYuB#_$H&K?oHDmx#;ua)soR3O7uE-VDNb{`m$B^m-g!*X++K_)6qzQT(MY$P za@r%l>Sf-ndHZ$>&bIT@3AN10&Hbt~{dka<=Bl-8d6)X>^&gM^`t|FQDU160`T|br zi%mFebX+a#PgQnywvVnh?~iub)`+LkWdW8wpCnER?*Dsw`mX&hS-bbwd3Y_{_gllm zZh|w5(#*hfMHPR4+2r1fakjNBzqrsj`^B%Xx6hyPT_p1=dBMt+E7yEiXuk>ZM_*5m zM7_ZuSM%CTAE84}Uz`r{Ev@?75&QMlix)3WoKkkZeuXb~Ps-dHy&v~C)$E;9bJ}d- z|I*cq7c0B-{gioqPG7)TEpJ48 zWE)=IXg;wpeD){Z=p<|NUq3%q*}pJ+VCQCD_iK9f{axReJ=yzc?m3lK)BI}=T)}O7 zZnQRR_B)}-6j(83x6G{z$9b3PwcGGrIv)8)uK)BCi8H1<9i~|SUctTGlke-t8F#K9 zHeq{g_9EB#Z=!uy^p-_GY?!XS{h!2c$s@mBfBL_9nQRmG@Awt(@?`qSFHbL>zFHr1 zhb`9V@3qy7r?32f;Yt6sk~c+R=S-we{rvLFQhxum{F_!)>Ia^_Sbx*SZ`$j0(9(!s z$FJ`Hb8)BrF5T+ty}uWRUS7Rv+5{)A%biGWb>KVu!NNt=fiF5b+W4`)<;_GPgWK{? zznTQ`q@MUVUDHSV)t)C8R-fC@xhZFU>F@nF9Qh8n+t*B&IkkV$i-rGPUFU12octVh zE^}7ym5O- ze*H38vVmuU_-=uMYn+xY3S9kLPCfkj`S6!dr+q7*Uq8<4Il;L$=hURo`1twC3BTUR z_irrGe9XyEn{(>L`k7BATzvh&aM7AzegAE~(?jI=+ic6aks|ns_>_s?WvV=9>FNLK z@2l?#O8R2OJ<&OOUeRRdn{xKX?dxm~^sTL*`8Q+QzlYNQ4WjwJFP3KlrS+8)%`ErS z)z0ISjhcM3@ymsUrj=6{_aB|4(Ecl>b>A-^t{L;(+b@5tI8&ytDBt{gp0j4@ob%p% zPbXbUvMJI#b6z>&?mzvq35P#CzGkSaJ@u)Frm5`mHOKws5{_TnU-R&bc+orgki{?B89;?c))G&? z^Yi7Got>S%NzVV`<>K&bdQ0ja8a8`%$b8zdVcRw{W3@}i18l;!o}4ph>u2rS#8V6Z z&Fb0ky&E~*`@|dFo_=VXVUGw`Y=X~s)=$;zcr$mz?Em`ehS`#fs+Z5F>8oA*TDPI+I8VPu(0c8vl*h`3+r*|YeM%B%I%lQW&f)TK zA{!{!?4HkTojbRSjs0~-VxrZ0qpyX|LQf`Wl<~()$mQ^5e>Wk254eB zuEx1df7YMEn<-8Azi;N&n)o|VtnT&I!nbCs`R__?)tpW(oU+E?l-a|oDXn$yqN1aX zpMLr{>s8@X#XyDW9L-`zb8laSmu;E@d z>z6xIjiW1Gh4?!@ef4|8MSJ>gxYGm&+8bvDwF`R{qCu+>U+L>Jx||$X~X=*5=W8D{lU&`spJ3U-_z{N z@t;-OWd8rVvVZx>?8$}lOd3XzP<<@tp)8Qutx^Onc=h*|nEU#-Z*Ov)-oE6-!c2Rv z+h?LT&M)?uve)a(mdRSeTP03eb@4tCP!T$jSb6xb_u=^_EJDtG`|H2Fzr6Xqt@QWA z1|=p-7lldko~en6R#R>|%~d&}ctZY!A_D_U!|&<)H~)HnLA~x5=dWt_|8jqiUA({G zzSXzrFZ_LfnSVWzp1-8N7Te3wBdEigc2m{T)LFXqJig-?#= z)$hw~m02bYc0a>k0S>Mw0xF!-oP}qbg$CCDx1D$`zC-5N*(XmfU%9#R)3n1$K_1bH z?Jq%-)(nge_AE_ImMor!y!pBn?I#?5#9+x{23n&g!0^RcL1TjR1eK;!iu;dk%nnZu zn-{xVs(9M+S3jQ`g-w4`xpaD^dG4xB*IsA+Ze(7)a{vE%K9Yat>Gs$BJu#7Y-?{$2 zml1q25xFtfPQSf;e!bo5Y^(l1v(~O%_xUK;>jsS)rN0~Jd~%#y^}*TB_r*`26YbSn zqJJD`$K^g|Z~5fx{FK@4YkT7_&0zO>ft9aq8a_N^Kfg>Aen?dUnH+7ns|8P#EBlajwgrx-0<6? z^YiBk*S*u(cuwWE!0rAUz|{qhAtKQ1$YQb6TK?#4a0iyj{GNDEW&t>E3^Xt2j@ z$;9V7_Wz%!Q>nP?uk7xE#3LHtcbA!_oicoSf9vXtTB_^5fE?KVvNq57bohkFrkvBm zt2#aTp8nqT=j8XVzqqG5>whr}vpliT?xjHJ%?XFs?D`x3#z1579DM=q88RKOlgvy_ zr+%GhSCM`(sl@Q|(!l?T9y7NjX3t(T-F511&GdgI2d~C&UV8CpxM~RBPh+jJbiuH_ zeoP2HCV#mebE&1Gtva{hk)vg-Qz%8L`{ zXU@|2UdO@W9{0vcp+LIgLHUCNS+9FK=A1RqU48jsB+ohR>DwziSJ*Y5EPYXWa~l7w zQ%`>Re)pW&a>W0)@9|fmV&?^3em^*~?{Y|c<}y9MoYP*uZ|`qedFt2S3#TvHi`OpG z_p+SwcFNlm;e31huB)`iz1;gsXPeBa$6t2650K|y;>h>3rP=P-L}9U_p66fXl#k~v zJ1M@`&vKitSz(>rr>d7{0^T(n$rZe2uF{{mdGGRi&Zj~Sn%%7r%AW;zt+$)JqTbRn z*4^Db?B*|>sc~TemL?}B-t)U$JL6NkoC}}t#fujcr<&}Hxwcx_DDl;UFYhO>jk{iH z`0(pqAFHSL_!}Rb=#J$Oxgs}NMkw|E`XfP)rEF$jI`R8bO6{^uPmf9Lk}0aHouHe} zibr-7{o;&Xxr$1NnRBb@oEKVM+_FV~vyJB1w+qXTi`f}5* zl7CTM|I&Z|e{FoZIpo)W_NmUb$Aacb@2!jN+97-A-h!fx)wj3oxojrw zb><(*-IrcJ*}Nv?zu&EY7Y@vy`8H7gPT2LINnbuXdwY8?dU_$7pZi$p`Gqp`KmIuP z<#=g$T(oqT=bZWNd*ZB&r~F=^vqHw};^!!_lgyRt^^3Bzvo*fU%$ne>mO48!z^5s7 zx4d3%k;dgyk4qnZz4_VDk?-!5YI~L@W&JY6fPm^fOFGy;*O`@n+*N*2WSgYyF>gNK z)M{PhueUgkWN&w0|M*J(L6hQ)sB2l=c6FE491G9OG^IS4^g`q3Vf#Oa16Tv~wfS;{ z)q8yTa+6m%JvCVO`M{Bze3g4k(low1Movgw8W((1?O-zFhPPf)&+?Y4J?VG8|HL(Z z{n^~3VWo4hvw0ZKyey{pD(fRVMy?WV!Nqf(5Ekj6Lfhm=C1s->v=%evO5!w zg@kW})~anq@>6EY>Am~D&+fXB{Z8W*o-I!t?0qa%cKv1kI*WDd)Lbv&5I*1IvR?wl zT%M_J`nB`Ba=XjT`n{h%YjE2if1d8SYGvH|&q=Go@7rkPqNEG6?1{6Ze^l;iUMX|A zZ%$D%&;H$0PyMO7`|Gjb7pt9om(w)j_$|#7wU4W||9b2!Vfk3&{Kl6T`5C4dC2}m9 zxBteCe+BFM6Q9VRj1|^g#``DbM5O2SuC+-*&z~!B6|uk0_K5(C5@*qg?=N0%xN~D#dezCPd!C=)a(Ts_kR#d8 zE_~5(*y~e!nLk!(uNl)v?e=B9-cNj%=S~ZdTb}zp=x?okzaZnu$4jTbTNb>$>QSDX ziilQ6;VF)Zl~egBSsxppn=wXWkQ{@=eW&Z@L8lMU|nL>-y(X8Y&u zs(I$bhoIw2CT#h}wlt)#-}-pagew{u85s&oMR<95DwZ|NFfF_CWP`}W{t5;Lm2M{% z!#qotn@fWD($msBG+n1ootn6H>yiii0~i9jKEz+Y`1J65e;?WyUyckkZBEustzpc&OEK_RiRZ+*ByTUQOle@1{7`)R%3 zTi$c8`hCQmvl^101YJ%fW=@Q{;`OBT#uYrcEu3Rn_kKJ!4Uq0EZZ9x- z)sEoc=$hrW^>s7is$RZZbMyVfhoKXk5x}>C~SMJ?Ax2>&>>AU3w=L2_s`L%X} zhIEvC7uL^@|NpUeA=jf$VfzK={9L2A|BKF^_4@kr;(0SIEh5~xxi7O`kLTOL5?Id< zw=7`;D}x8u3-AtF1upKtziWOySiF$)(bjDH^E!fmZ}0z`dwz?1pUo`OXpW|bsvQ#! zUt$7vngkpEfp_mN+Hhh2dG2C%C*dQ^>~;3W!Z)sd%|7?#@Zr@4(Gd)0jx93N#6W$k z4u&t`4UIBN01Qo_WLf`8mJMhgps;Q`|(PSuI%@ zmP{>rzuqi&l@Z@QD{E0%%T0=(eszcT%fq|ynOxIl*aVLpZvTJemU$r$Z!NF%d67;F zmXG#zzqTh&U$?|%V<2edZItHse_5B8X;~E{l%9L--j@T4qsfyW+8(&Y@h64SFF&UW~rj|>iz!qvbR}1Tk1|I zJ`tEW?}K)`p5vXpzq|K6o$%P*{@3#z;)bj-drKxBGuv|Uov8239X54J@6s3>LDl~g z>l;zq^J3pH`?4@id;?455BL3qr*CXospTyeX`C{ujQ!{_Off*5S$-zW0mw z>S`MY?bx2GdY12f_wL98PEU$%+_~f9r5UxWM63XV5MNG}j zf1hHu+>-CHxLdJ%LCW=YZnw6sHq2(5_;BWtlP8z={`^@Bj)cAw?tG<=cQ*cOYR{(9-Cj-kzu6H&XWUMAf+%fzQN_3*1#SwUWb`T6-0xvUHfuim~@T`Ce9 z9&UZviLZG2)K7aGew}$ZQCYgDNd5Gs_r_P!*%aH;6xusXTopkpmE!gK=P$UcJu4%} zS^Ay6568rl56_(8(OkM>()M<;ypT7 zw$w~{@$JkazUP)jDa_NRMro8<&av5c&no$k&v#jq9bbz}YI4>Z=BF=T^iSMg`nTba z&gFx#11wt)^cPtN@Nc&5{2n^&j3cIwrFR!VsG$=F@4W&gVW z$IUf2zT8pIfA3|zB=05szoqcH5?H`%-JA>>K^dE?0C4^Y3@3qjp(=!ZGpH%QfGv ztwr~4t4~$CJ8hr;~^a1g+bR5nFct!oO=*XQqok5)^&O zSQNo@}>Q?`Y;tlGD4-mhQ3xU`htC7*gO@oC~=gL9%gIDaV$OwoAq;nvj5UkTqr zciHT1zBjjG8VJ{YyL|k`n}_Z%&%D?kq};Ak7gu!S|D*KcC+)2%-uIUq|4-ADzVmD6 znv(Tz<7cX->9jA~w(-x2-wHn~zHIXK*3tK|oog(tse0yo&MaTP%43(Wro~SBTK2(m z((~*6GPn9}ZoBg3$Bn3}Wxx62zfW;fZ5KH5q_FZ2%iG+@nO_rr-+WkGXwKcj@?-EAAR^ZlLUe7Pu=Z{E|#k2$>gmQG>s)Bpvu%(=Y# z)0Er9kMkYBs{>9D2f!y2ESa+C)~%@QD8I$+A`?KZ<=?v+KK(b=G5J(_xw=Yv@28)Z zb$jPlS?=oim@O+S8=3i~IHSsUy4CvR2?ciRf=?}cS^VO~iw`#8ag`0`FWMPCe{}Eu za`CEn$=g#VwG}^AYD>OOGMrnt(R%0Of9|nHVd*5|J>oYm!zB9r6(CY2Ytf7Y6Q#`oQ?y>ioK;&vPPKJWiO z0h9#w{NFD)ec3wW;a$UDA3k~RDoeF8Eqd{Mp0k)st+SMvVC~68@gIv$F4X>WVqv(5 zQv0$!OBLFSoTdIoJpFWQ#}k33h+Q&oZ_H3_OP0P>Fh9|&QDz#$&r=IC(*oV6yPrG1 zxlpI^&px~4qfcK+Kl;Ekcb=c#)GxEozc(zByIeTq*4anL*YA9Cp@c`Mw(Pt~bhfZ% z&;MR_&iyVw`$pye18Xb(r2V-!OSoD4RZP(fCEcPE zhnDM0em%9lAW>RYK6q$WW%g*C3w*J-LZ1zo46ckr# zzt%iV@i)I45!18VQ$b0gUDaV%{*o?beu>cw|^ubCfb>%TC3bzC$3 zRmqOJb=o|ZTjo07wrww(cA;P9)+Yw*)-TTC=lU=FIdgBt>=|5k|1u_m@VeNU%d*3l zWj?&SaSm^Up8xxTX`4U1i?|o`T#3n%R>#-IESWZq@7LZ+?)QBcw`yNLXA|f(w`X(v-RoWb_EBeaZvJ`kO7+(d z<^T0Nr-5fpXO>u|1RCYuOPb_-xy?kUQYT5L`_o6U%fkJsxigX`J4fx<`+4~t!7E!% zFTb9*boRX8DbsRZ_Mb4gDm_)^ly8#H^Al=Y{?xc!H~eh7aMQY0?%OYBzO!DlDb}cH z$Kz}7IT!>iK?Ac4mOS#4j|kiq6R5p*cG|RytS7g~1amE4X=5McIYryJ?(@z*`wp2| z)20?xTkt-=Xud-;C32;XyVuIN?Y?|}pD>m+eQ~b;F1+9E@7=XC9oyc{+hX$Z;nT@8 zQ)k<3p4NY*w&G_>M$q!}CUpkCv)n$di=BDyOn@6?hWgx+6N>iU0sMa%zXm<=5jyf| zp}qNpqpo=u4h1c-XP+>A_NJJslMfHI=FU4WbcJ7}4H zNBhT_{l9t^)vZ^}U$Xh-PJgNCt+)Cj?WBwDzx#E@aJCu0mZs&C`+^J#MWBW;W08cN z4(m39rB~lunzT+4y8Sz-M&kA{qg^{*r0zCb@=-|cCR_0AoT3+{`~KvpBwMj{u9n%k zde!UV6>HaioyvaW~^+&v;W_^=HO9%@pED;ryl(I;+5)aF~?W|(kE_l*Si^0QLdBDEOvWufmKoaX{RNA kPt}jvk(0vx zKqK)MuXRc-U5-e{%|4@$$Npr4g^thsgKEYN9SZFV3umwhP2u16@9F=0JG|ce*<_2Z z)-GN=@98YFgpbC?&)i@6@z-CDJa=4Pw=K+X-}h%rMNcR$y24cSLSLc%Vlkw$_Dq(( z^(c=^gHfSfVWI=yY3bnqpZ=YZtEzr)z9#7Fw+r%5rhLA5)qCFgGmj* zXX9;e|2OH}-pUDk4mHRqdFd*&|6?kW&`sZ-5ALY+ueA91M7YqL^9T=gigodKefhX~ z3pTgQm!7)0bbI^>O?97@k5y-<^V@rY;`SJCghP!3pWsrl3C{J5mOXrbZ-OhYd()l)zkHk-8Bhd0v&zd+5CHYY4(1%biTUV(`EeL{nDx}`5NRG`RlQWLltO1;3Ut9 z#2wJiXKLre8*OGeZp=nttTx;pZD9p6gl$w`23!oPZjhO+BsZ|n2RLz)aTVG zdGn}O?^0}2;0Ddw7T)+ZUHZEHg73?=U9$dtJ%aV4`1HP`SF!}uL5n74GFtLXm+tP~ zvcJ^yZEmFJ=EJ`q?&ms`!Bbz?)SW1^{?UHz3;zgG9G(s-0YgAsUZq=8;3(-qYM*+ko&&B7ucV> zzqsT7FTU#a)BjH9>-NU?ENc>i8O$Ieeqtf>Qjx9OwjI0Mv**Q&7ak?Q4>z4}4(iIv z&OZHX&z5c5Ce6QJxiUDzzU1vG$*TWv-f7I{@Ztflu4<5B3W!l?m;2yQm6D=zrO4gQ zZN;{2W><`SpJ+QKZqc7_w8%m~I5=3+FvKgcwzhWB(+wAjO^l2t-AKN!xx9{}g&DMJ zBh7)Yxv=n!f!QoZRz}M&4tHl|atX`L5qIYMtl0DIX|P+!^P?eoK~D|V6o*7d&;D`q zaM7!F2Mf>uTngKh3--{&m-)R*EysfS6I)Tn!u9LVYY2S(`ZdxxuxP9?ltXyU9;$gS|ugnadTlBKsp#oAu zw19@Q*q>Yg*;%qBIeD5yUv9?X=C_XbAhSd~rz*rerYm30US{*lw#z0W{f`dsmDJXY zPa9us>v$pI-FBN?q^M z-*+d@`{&Po8y9(bP5LE`>2(|}?U3bBKYM&xm;xgja-bcU$RvxKmw63YSiu9}PmMH; zd9V3yw%)~a;`^5ePv<#42{CXYyNASim8g}yY@V}aQK(E3DAwzfT?Q(lT3;F$nzJt905yj+raR8e{B~~3;-z*G+jF%R@jrWd z>8OU;lEi}=E_{1$J-6atX7nXC{O_}m#dgj2>@!XYZ^`{LuMQMISI^b#x8BB^x#!i^ zvp(vb@U(HH)`Nke;WxMA3s_3X;pZ;5U3cL8Ca1kT*B9%2*|O~5o+(WG`!`K^yVZ6Q zXk~6rs>jT^vu2%I^3ZJdtJ1mW4W3-^zx}0b%eHM&@}-YT{rb0)zs%vi;>r8O||K;mf z*Shy}a!;mDc<*L->m~airUaQ78$X^2x}g$Oc5B{=h*@%SUf!+Sn}lYc zZCE5cQ$|QI6t+b9aE3MmLqLAMzUI;uyLR20DOSWG0n)_@(zRGt+PHt^jr+T--l;Vj zDF+cXEdg3#qfrXYHj;**blg{#bL3M{K!_6PMxSTT(t^A$URvs%SyHm)0%)!Fl#3Sw zL4$spOIPgNc{5xNe7OcgL(sENKR9pQ-ely>8-)6kGVdk&5J0!-)z|bKD zijJ)d_A~ito_J`@9(O{>>F4_;#veXBS8P9U>UD1Jm6aiWJlC$a#$7*iZtj(pB75!a z=2fl@)_nZ>eSd%O@}MtO(a~X&&84L#cP=IA+<(2dX2Nr~ZLJ*{i#A{WyyxTZn0wD= z&AM>wdHaU*oE`kgwjDS;f4Qx6c*@>w>5sdvaELw;s7MqRo6RHIH08j|xz@%;TX!yN zODlVKX35+aZd0V?tS`NDP%o?b?rSrzkH88WhEUtZI12! zSHY3q5vtSg$(^p6fBR7B$<(Dbmov2{zkYt9-?9Gh&(Qgw?$%x2ST)u3!-waaFUh>A zI#Dranbnh`_{%?;S`#NXJ)Ab}LOTCanSJ-JO`Ev(;k0QoACopd`eHMC#pxNnPASJt zCa>K8Zfe_$WiFd09Mx^F(|o$EaW<$;vXb?$Xu_ju&SD}vTc)&jr@s0bI{(xO?&pao z4G$WrTz>KN#mkiHFEzVVgi=o{F2AlCdQN0k8lSav=(U`e^Ln*6Ejf3s?sj37tTOkq zx<23Inzu7|Z7+K8@ci==>KZ)zi&p4wobs}gt=Cyx?XRunWwVIz=`(fbym)hFRerHA zFDND_x&+U9IBlBGOqoYu{>)4FPlxk8-MI7C`uXX8?o(`wPZXV9 zIRCoBbMI|u!}K^n7YQkVlg*u?jNSVKPAUHX-78;zefok8CNGncZ+kog`NZSW!FBCL zr@qayobonhNkAp1=Hly#S^GIBJG{HOLn-}Rklf@cfq9$%McV9t6>NFB_U|_CAIHyc z3bJfo-mR?vKcz(S;?a)#mrq~3pM3Da|Lae?P8*-qJM}5|wAbD~$3veUw}wmAwrv!! zG|~0nTFX{->#V7%o8^`1PhRDkY(2Z$?xxxLBF74NI8Rb)ce#05J$Clh87ybYClE;kHy{nd-Bh2 zT{21akoNq#{R`)P|NHTyj^Y*9!168`umrquio=syZUq1 z+mfs4S<=&%xbZ&`V3-hfA)Zk!&+^OeH6i}5(~HF?$9Ps6-CdqOOIKOR-_m62+pT9p z?tRYK_5S>NnOBF-98Z{KX`-9Gl~sQKp8Emo`HLjv)=4Tax@}x%bWdLXd}NSCMELZr zCwuHJFXuk?IycwyG=HV%ihWb2oW7VY_VtV7lM7`$>xvgGzOSD-yOJk6a;1$~^l$dp zuX>(G&J$jAdvjM&`c;MJr%hgGX^XeG2R<#x$mqCr`}WF>8z-(>wJNFpfEiPx#@iLE zRxLVq%q=TFfBC|N3lG%tJrOY2zArdYXb0~)-b{(u13A(c4Um^zZ2B_#9evf3w?@y^oiQu>QRtx7lB(#!9E{lkGHDP1)8nGF6GQLsJ~*-rQ;Y`oC&o zj>qF!mRCMn7i(Oc&c|*UzwT_;q8l&8L<0G)uZqMNmXZfK?-_h{oRNoyXl}2}qSKNQUV*Ams{Zq^;b(a19+p%fs#eSJv)1GXa zGpq0XYtu!yon8p}pGd5@(Q;J9;@29<)9rd(IzFG`ENYo&`7M3%=Gxk0R+VBt`;I4N z%*x!tIc1OdrPmTZH{?bQ^2n8IWv0t)iU19B z$vm~ZHhrcO-{He*IyTkI&g;yami+3pS0vXHH}xX%v&zzD5$Q{pG`uW5G1Erh@`=s1 zyXLvxUa3E~{Wg%SUG9H*l9y)tvZb@sCK{bRSGo267VR}}=gjC+Kk;)??q@CW7WXGa z&7Xmst{C|4Z|<&~kG54-I_BG+&WtNkegD(=t;wqW`tw(6r1SZnXS#Cw%KT=H*6Uju zdshEl_Ibhm%^K-extm))S>*1X{_6ej${r4er+sr+Szam-*DP2T@?^u5jk&X!85mr4 z8dom689t!~{|p%;v*j5#y|pTzwol|`Sg_|}Irq^uiB_FH$m=ph85lY`R-iO`W+a_{ z_)@o4Rlat0oqD!q>it#sJNNo_TsU!IlfN+{=ff4!be(P z8iV@6XZez!i7c6Y;;BHh5re}G$m(V#frsupIUYUzD7IQ4qAN z#^yluu@fgc40E%yvwhaGF8JbT&(b8cU1s0c=J%KN`{jB}9P$_#grhxO977xxge3F- zKKLDZ|M|h+`#f&H|DCjo_2aQeO1|Gp(q+H@yLNSkDa%Usq6n5fPXaVuWo2b8Gre8; zpdH|MX(=6>Y!j!<^_N^));E~}G}i&@FxSs`Qm|m9;nt=K=xBx2Gf-auGFri)1Trq? z&~op`SFVKktleyEWaQ+va+2V5joZR*H-AnE%zAF22@9Q{?Nbh4|Mw(ODkIBht%6)l zO769fa&K>R%=L1-$zZ9&6t}q%vZZO?KD+EFzr%{INm*H^e(j5s+kf78s*c(x=*&i? z;_1t+H%ji**48eWvgp^Zs_g17HCwlCo%#Js(I?&8EpIn}&~kqE@P4Go^Bpmu_25dN z(c(z?Cjt|fO(^>D?7P*AC-MIcwl-B%{&9I$;g@gN&(7eX4eB#BI7Sxic@nTs{r_6; zxpIH@c^X7iefji7LQ?YNiHSV3EjI1g@oDCSPgn7p0<)*|GPu$;+Fcy62Lv zp1W@4NzKVi15c&MfI9jW*VrvxmT2w)&(!Xk02-6zIn@;W!nWOIXVM`f!B&}~NXMf` zueEJCvG9zxJ-7Ya&&I_w&Rgo4A9~SVXIQMa>e*DAxFU>{KV0y70N7uJ+Z| z%VG1pwK~r{dZa#I<;12STi)wa--EX3d~5y}SmxIAy>}oL^hpz=#s9^yM0T<=b~Q+ckS}AQrhfsjP;2?;|cpeClV*IeEjr-GirvN zaJeyqhNnWi>w*c-WoDJ_GCA4$wsybqM5FmDbJm{?+OypFeqbEoN zZIDXo%j&&rb&L5I>GcIEJ$3^PPi(e3p{V35=)&h6De(0Dr;OvrB5pG~Xexmg8%}Tz z@cI$i#(k-Mb$z6bz4v6>yIVH@+_$Fjz&lajl3%T7UGs8ZCeE_F6BC?#XJyEI$&|L} zD5KNv=GU*J+)Y36NF!bFF79L#G`K8$qTGH|;7EV{Pj9K}lD+A(q`SL8V_0FokDF~t z^weY!Q)pMX=)iYc_~!mIy)p~tZ>c}7)hc7G|GsbM)1{5Rd_PP7+8sQ&%j)rB4Xdd} zTngtU_^w@@dggDN%LHeZMH5bh^DP!TvibJ*i`wy#j$c;COWu#4VdwliIy`-A?WX0@ zNgNIApjAQG z=;A4;e0H0rf!0M`?CX{M2wJ3c^I`3|qC6cvv8VdC;)+fb9skaE zYg*gBd)LxL9d7^aE@ZOwiI>U$&6gWrr*FGd#CEAj>HSJ|5O442aDS1IcMI9&7c8H0 zO6$4i(iQ*boj+Q4rqFd^kwmM)zTcB?|NTC*Q9k-|Z*B%?NdM)d8xQxqVq9?Ir{b$N!cO&0TySAsMPAi#rFX^6V`14mw zyGttnxTvj*+vO3iAFK0vX~=}bUyl5lH~nSn`I@$QL0$7!uUi(r|CgxMmj}#WPKisc z{C&>)rRLHX6}QVj>B$$(kWM_2c%#YUm%ZGnC;wj_v){gK_r@I^z3B`b44|%vMGyb> z`p*`+SiWT(xeOmHRs`-V=!yMH15#;w+7){&nB-|JQu(w@M5Q+adl9|6f%1f3?Y{?&Za02ZS@zp3-g{PB`}d3YrcGTr)wy=2uJ@0dZ*O-M z<*Pq2kS*Nv*80nope?mO_g*u3|L3akmnlJC4yD@(N9~<(_`?$e9!Hy-U$0yKy*1VN zl?GJ~vw27+0=L~+uhFNX=sBiQ(QPT8m+A_sM(+)ead|Vu_bK&&&=XQs`&7EHN zWJ=W^v{<%}X!=P3zedgPXeZ7&7UZ&rC zd-Lt>Ij2+At9L2uy6?a7Hs<1%V-w2jzE7XMth|0_X4UtuWy#jzCTj~%K0NeAa+gJ! zg>m#AgIYD^&&%i4^A$-Hoq1nrSv)_{?q}qah(~dMUxoL4*Z4K@aA$A*#LUy66zt4z zH$n6NRDF|Ub?XlGX*@BAceJ_uKl%0h|7Z9A@_v18DFZ{j17C0-*GtKUig^!wqoSiv zo`28c;(ej+#qRt6%=Ui#@jc^vmzq@E-}_xxybj!nh&dCPcKVX#&C9;(^J)%V&s!&W zdSTD;*rFH9Z6_T5&@{dK+2%cyTm8FkpE16BrS|z;5H{KW{OOu4aYZ-k&p+SvsbJ5C znde(}&Dk2Fq-A-=UEq8D=kIg(Z~uG$53^PMgR4!ybQw;Go=EIUoG2+Nskvj#j;94F zDJ@yq*~;f1FZb~%`t#&AxXS$H`FsAQ^WXLb^`td%JebQ~IdiSv+|7r7zxecnGkKqk zRR#i!g_^WWlPMCUSMAR;zsiS+4pQ~G>*w} zG(2Ij^wF%Xt+g~-&V6q!|2!)ztBx1jd`@2Xt(^Jm*RM4;fBtUll=QxO4lJKL0zw2zwXosXNf%Zqc%7?b<4JGQLg7#*G0?OAAfmO z?DkHEqwIeLIJ!WyBI&gg4rd&CpSN^<&BBSl-v5kIixnw4VYvT!>Z}_-#6e}8vGkpm zpFKx|I5gYYum35p`dlqL@kn<4Cj;Jl-(98lyzk!f`E>lLD?cZ1`=2@GU^D;vg_Hk3 z&(C;wpw8xvT!R3#1vrWEeBH~<(Ypd>UV8Oi?No`L;-t;3bLJiO{&)Lo*!oR>ml!_% zSUhLlHi5hIrkZx@Y4CwUNum8Ehy8iWIrl#oxn24p=WPF7X5YUH^67tXd-LV?pL+0Z z>D!57L41#U4%h$6wc7eJa+k$7;a?ewk^O2+3Y-pn!Cjs$IZel#Qn=>*-28Ov<`SLc z;NakS#+_EnByD5Q?Rjz`Y`Pz3}uihTC z&Nd`aa zUt+$pPj%k8c=cM{s+$uI{{Zz#Kt=ltrXMk-rh9)~U4LOAyZni$YnfHo5=72hzS;Nr zoX_9e)9=sLw0~DDQg%eQU8Zi{YAyy1o)d{)AEUywo=!;rx<{^3@$)8=lQUf>A1M5} zOm(T*mrr|L&cpoD%5mDun-RP+@^HyfQ0?`#{h!5W4^FYIZ%@D9`cBGf|MOH(4K`DC z*&dtFd-5;7&pTZH?^S1yz@`;)RUa51U%I;Fc(nbGI-SBF58D;m8AK#cBzhU%eVjho z`L>&`+Qr9vbfV%aD>7G3(eBK=9ys|$;g_#pEnk~MqVUE!T@5|tpi~lQZJ)ETMTSYh z7TVP^GO%59H#=Bzed?5Dd(=KAZ@i>BA-?$Rrk!%~3-{l@e*O9Cx|zq%7yioRexD&# z!Y0(h4(eZlT4JDU*8^&lrXT+L`g;4-Fad$te?){YE1OQ@J0I2b1G-Cvsi?z2MIYqw z`6r$rpK9XhP_a#aoupoE+4*ftOfo<8)#>NI(aLdRH+E5L;pt{RH zrO3kA*x5^S)tWUttJf;$h){g1T0%UOhJxauu1tNzf$xQFY=5T0m`GsE0hB zPUu*%bLY${L0d{*21&`v>TUt8a!xHNnKDf;*2_yXD=+WcRCe%`57R_=aNWEa8MP_J z^Vz@6si&ub)`HKqE?;+H8#6=Dxt+z&SM1+Ef0}Oew3p7)bRwNLZ{ED`lQSQ3NIWSz zu_k)^xgQ0Epjj2^*C?|p^S*-Gl7~QxP(Ffk1IaTfAJ_1M&-$3)%+S>jnv_G?XE6yJ z8St@OL|B0KxhsH%!+Ah6^N_FywUV83@o83x)>JW_Oq;7#J7|;I09!iGa3az^;eP zJMx0sk)R=M(EJwz!w!(DAnsq<2SCO$Fo1UEJ3#%6r)SDsFcjg__i^Q(OBNRvOOU_+OxP|1+V~U1RK$^2D}G4joiiwSoZLbE)JO9;9TWsQYM7>g zJix$kz&8P`X%c7z4H_s66F`x|00}XMhAW_ef(9qU5;@S30TAypD11eP1p~uMcF+bK zNI)@o*djua!QmAs@E92Kik=8Gf~=q7HseUG4hIWUql1gkfBSz1R)=HHy|QNj#iFa9 J%Q~loCIHv1NvQw; literal 0 HcmV?d00001 diff --git a/docs/_static/modbus-segment.png b/docs/_static/modbus-segment.png new file mode 100644 index 0000000000000000000000000000000000000000..80fb6bfe6ab5572423ce46e81bf56ceb5864d90a GIT binary patch literal 23167 zcmeAS@N?(olHy`uVBq!ia0y~yU~*+(VEoF##=yYvBc@A}fq^r(#5JNMw<0YwCzV0f z*crl7H8RM^FD_9vc2PAlDlaeBODRe$*UQXTH8N5)GRVzO$xO>kO@T-o85kMr8d&HW z8ip8Hsv0{Q8L1jO8XM^u8JR~x)F-B==0VLe)iY2vGSCRm%uC5HFV=*}rOi$G{ z1c@5EnuisXB&!-Zc^bI}m>5?11g1p>R64t)Wk-6t=Y^Ohh8hP|d7Gw{=6i;hNBJdr zmWEWMlv%18ITe~_SEgl#1v+|q<(LHdmb(>rc^l;!8%2c~nMOrgX8A>_8oBwp1gE7X zx~dvEx#X0FnC2%@=i1ftjI9& zF0>5vFe&qo3NJ_sGqUtiHFB$P4>U8V^iML+4oh^c^hgQ!HptEmc26tH^UPK?axyE( zajD473GguTHq7=-b}q>&C`}BpEXpV;EH=rm@Cfj;^e-zvpn0|z$mP^)G^5?)g>&;!_guy(=Q;$E!EL8Jl(*= z(ACo`#ILB#BG}i&I3laO*w8o6(a9ymIl$K_Ffp;v(KMwX(Allr+cdn=y|5_6EVV4r z$3NL8!_dVw%EQ^fB`B*bD6}fTIm64N(#J5OFd)>iywImIy~NYmupqR=$*;h}G%c{) zBP7qvEI+(FpgcFTJh-r;(k(Hv#I?AHAHN&Mc zHz>{D*u~Yu(lMl}G(D@TB;3TJ&@VU7%s($r)yT;|zr@foILRE8Rw7FLOG3j{joeg? z+@k!7O3F;5jEVwPjhyl#Qc_Gn>CZ5=%qz+$$vDl-&{NgODZ|{<+}yCND7@4nqQEl1 zz|AYDvdYrTGSR5Yz&PA8s>s_v)5y!+0;JV6Ez`p>JIBW$$SW|bydc0L$RsDKG9vXU^rR=_aLF>A|5{?v)1Fi4lhRL8?Y>RaM4$so8D?Mh4lT#aSk*Mou1X zd0|=3d0DmC?@yf}F@HUL{4Y$lo3Gy?~ zF;B^GbIYg6x6_9P5ZkZAiR_W_znrGr$ z7HVh~9_dr4YUJjg6rN-O$p9Yit{x^i0cA`4o zRe@RQE{Rb5QD7Jz=QI#3~t{#=9&Y3=8UZz#9UX^J@hRMEeUaCfJNls3=sjkJYh5o^YnL)`eMIkv= z9z}sk&VfNrk$HJ3rA9sxe%S@3RfV8})i1p$+alGs)XB8O!!gk^CC4$+!pS?&DLg2n z43zE-LJhK`GBeWyqdYzHU2{BL0z)D_bE`s~jhzh2vwQ-B(!3n=BQm`5jXgr0gF~|e zz1;JPB8rnd%{(G1yj6|dj2(+X9!U1La4kqoHYs&4G%fKqamy~wOEw8IN;XJLFDy(B zNiy@w$ucd8LM4UekIO-u=}sIc(LOifBODhdoM2=j^b zE{~`z3<|Xj56rSO%?b8)^A1aODX8)(FZD~ew6F+H@(U|=$ukeJ@G~ySPcjTHD)P-O zC<-!6D)KDNji|6FQ8jW)tF){r$N*JcVM&SJX(6gcPDx=#C6T^W;51ZZ99)@aoLiEb zUzHbJ7^G_C1aj(hRC1srE%L}B`HoN=O-*=d{J8xT5j8D3*)bw56 z_t`_APTajZ3Y;6V{a1_p)>j%6GS3=9q~2Cg7cr6x@#1_lNJK_5W| z28M=?gf5V%3kyW2(vZ=*qx|l3+nMRLcOs-V?#g7+pI`gv#S0I%=0=<9Z#uhtR~+9K86V%jZMs@t>~pIZ%D-;C z+bH}8*d)FC$8JX_1?dSO=~Y_9RBz!#$o55%%o)} ztmDp!L>tn~> ztvkMK+q&6$aqDL&xz4p_vHcX3E?@g5(s!cxoLxy>F8ki-+?H^CQT5>DMf2d0@+l>8 zSN8J#;#jugenQu-+B+gMlw5DvT`zEcURqKTa@ynOo-;{ZO%FHxd^1Ut>uIs<3%-kf zKP!K3x!ktPCOj(f=4FaA_4I}vw&*IYeaUDw-d*RjuTvvrSl+qq-;<8|+Zi%KV+^1rd)OQ-Yb zYKhQWD^EOKs=RP-<;Fv=<@fBrS=_NzapL;?MPEGDm+x)6e|wka0TIbpVQ!(pPb6C- zeJ7rn-s}JWnriTr-P)Vd4rpzg&%5f|oVSI071l84-iRxAGxN<3Syi&@-p_XKyVD#! z!rAYBFrQr?o7X7t!X|ma>*Lq9|J{Dp|6O@)obP(&)zz|Rx^nv$_7z>9k=|7@xAJoR zwFS5RF0a0!kbert@H@W|E|D4&naKbV>`|3LZ^H*N{^qMU= zB_b+nmss$V+;Y+2CGTyLGPkC7t?JuxRrMNUbh2RI>!%ml0(bZFvc*Z2zrW{uZD;s4 zvk6si&#+?)!LME(*<99W? z{M(IfYgTXZ)tB{N!}qqs=bX=zTRnDuYvz?yf7^EPxwyCU@y;7tXT2)14Nf_)eck_v z&qVV{>G=nAc7B_ay?o>BkiEUS-qQMg{r&oP8(uzD2)#Ao`n#`%wv%tL%}_dAI#cQW zj&MWQhxZo>PEF|g;?Y_DaEaTBHx~*IOj~(<;mzcu|K26GpYHGPU;K3O`+G^pKP)?+ zV|(n@hJV#r8;hpi-)m#;3Q9~#ZRujcPb3v$)4t{3vwX2-)wZ*9CT{$BwSsN+sV#wP z&Mx8EGOw&Nwm)(A6^}`OcgrnYDb;Ti{KQxHd{S4AT*=H^+eAD5-t|6wTRn}ZnCu9SxV;K zGWCo5)3f$1XQqy>?#YiIKYk7`ydhB*8oZ=8@b;HWB1e5X-g>;6rIi26^)&aE&jzj= z9g=w$l&`sP!KvXzljbSkm1nZdbbjd_er9aCCGWG?In`}#%k$dbv-+GDxw&VlRf9ul za7g*YMdtV8pMGCAW6_n;2f69ito`d|Ddlb|ep)9QoN{_+-tJAgZrkr(nc|nzJLBy6 zHNo3=R^?w7Is55Ko@nrt*NgXjzLKjmB|Jh$_TOt+|Hb`tja(n@SSfKuWUsO7O7+=q z=K974o1FIEz3QE?^dTSK-dl>dZfyK=B|zLKaB}~X<4n0)FK&GkK6Q1Pr|9QL52yN` zSRQvd`SgkC;3urR=V;D4+OYha_uqNZ@ujj?_VT5rh6O*-eK!B7NM&|c(cG=m{mz{@ zlkGdPT~EJu&JEKP@pG?Da_Uyyvxq3V{@%uC;$FQ~GZsbcJ}0Yv-7lEmGve~=wUu0p zot5IJx4+%~YK^AX%tcz=H`dR-H&aRQ|Dlg!o30wVZo9n7>+bUNN!biV+)cs9FF8-h zovn1fxCtve)9(Q9QCp4r>u|77BLQ3X%=!+q&3;B zcJb1eOErZ)KKIOR?iSr~_xx*(*H0E_u`X-cdbWFd+N+3MpZS%mW<6VT^MU&R!<& zer+#b+ETA{;cb^wP0qhGzHOKEeD9Tt868m%&q5luoe3z71 z!47Kotn<0v+qzVLnTCYi`_B>&T@P&h-nR9l1+gkGF4a z{M!vH`?9KKr!u@nos;diWql4(<=x$1-nVk1(s`dNlBJw%mwzXe`jonrtg7*}`}Q&0 z17hqUjy~0^o!vg=N8+Ro&d3OU(%W%Euy5(orO)TqojFr+J3~0#UHe&TSCVYykG)w^ z*RDhePd9Qkbe?5pZW~n=dw=^C<%XRr_h}vD)Y~kuEW<|b^uvb>-@JKq;@PuhclOmv zFI-|~Zl0Q+?#{>0pK2qw{ccO*!HdC`a)y_e{C_u-HUHNcV+XU`zuRwYnecCSI@h|> zBCQwK-3ST2`f_u_+-+Y@9e9_2{o|8m=l0mdsxN$#yx3vk-j5$Y{`zuD#J28F#I|kQ zQu6ctby^_odVrO(Vo6P8!bRGN7Dbz{)wt~jZx{~L1WPE?xs z^5QbB%K^SUBAH2UI&-Wqr)|FI9b8gZr?-3eZX+4Kr%#?N`RXV3HC|m^-AINnwY)t1 z-1+mj^B!$@z+x=S(~};fb3L=Gh`VF9nd__zC)t}Pc`K(Wyq>kl!0L(Z->HvxT^H%B ziPYOBbI3BOBW-#4vKL>zgqWF`JvrFSzP5Zx#zzyW-jw8IXFq@c+j*}xJa}==w(NTT z*=|$wg9b52MUGxGez|4Uj73_{4qE$H^U0O%(x2M4y~B2nzijZ5-t4=}&*eykE2c^1 z?rTy^I`t;&%PEn$^XH#FcC78r?(+3t&k5_Udv|xYy0o-(kHo<{AH=L*XD&=I*t2|{ zQ+mYLmz#Gj(|F?gKE2;mKRD&`RsZ8J1LgL5+_H0>>V0_HTD{X&%QSK>w@ws~wl6yy zaH9V9&lr}f)ULAfa!Ey}-V76|lkeW;-S(9eX z4kx~ztE%OG_+fyYeche1%j_LOR>eEy(kc^`zs$ZjW6|2Rx?-V=-Aap!l%k`fbIofR z1Uvl?emwT*^}<)tixW4#Xw{VJKmO_6?)Tg7c`o|2W&8Hy)jbQ0Z>$vLx%gFJ*-MuuClVS6r-72?l~^{WHQqyB|UxlTWZ4l5}uQ=2_|c5XZq1H%P|y#}t^^Y2gV?(V*3?GZ9hPfzd3x3{-p zl7_Ci<$Wt+61x}}PB8?x1h~ymVrVcrAfh-$a2W@~0v-cbj?@-SCI$^=A3-O{L9c8< zMevso51k|9;-+ogy7fuf>C>k-?cH1Z^zquYYi;erEWRCX=Z}8*=J?}{I{NzlnWd#y zb?0yUG(+q7-@kv|`dT3#y%;|C->X+ySH7%SyH>S+{q33M2Sr+w+!yUM}CC_rQyRq2V=4@R!i#`}gjx&7AV&^ZETUzL74$TefWzvz5=a z*p=2579KvoKdbbh$lp)X_fNF{y?OtX>v6w5o5NWc7-HCGC|!M7J@@~=fBR%)WOgje zsIRZjdUdjI7t3eCI{vm3vy^7{opaWSzb5kHafl(0m3-)F^*?VPJa}+vOZ1PkeI_sW zXJ5{|ydtUKkY&~L`&%@BJ=L#QUcaYEqxs-}<>rI&+Y3S&7!K??D6-P;e)RH9yLM?k z{`g~(CfD5m6*kk(+yAes?K9Q7RnbzrM)T53mdye_9-_f1yzWyk%H|$9v~l%}MHB4z z`b&6TemddQdfVfXK7P^5USu18x&Em)U*>eehy5w3PgfjW&CI~?jCGku>960ve@{Q- zYG80nq_yvU9}nx|g_pOs9X56~o2wO^b4%pNvO_^>?z6XC>FBks%Q~VXb3QNm^dWC$ ziKXjiEjpd{qLYWs|B3YdiaXz)GBPj}GX*cPsETcr272ZB7gth|G&8A_wD@p)Ruqu zpQo)@U-htcV$JJl_fLD@%bv(y|JTLtSH`7pPk9+GNE*1F^YD0)le}0u*4VXb_l?D0 zOHV7$$EKp4Qujm9ID5GI5<>|L?2E#rc14#-B>~a6MS$i{JL?~3?*yP z=e>7AOkEFN2{CnzvsHEZozQ`gJSUeuqi|I`1s_S2ii z{c1&@pDnzzqcHy8pY#9SZ{K8O$Po3J_;ShD>h6-|)~{zNoj(&287v~b^5Sv-nN2se z*@Avv|6O&w|82VX+}E2vd1^7CtEUO0a3a-?Ex?V77suX-)c2z>DDtn;!<3=1+0T>CUPr5!VN-Bs+rw*BIJ z{#*C%l`UWP#%k`3Ein`7_D?)F|K74w-D-Qk^FFovoM_K06c_nm=9GeW_ks()-6)Ok zxhWbf647EFRsZFp3tO|g&OWw=B+Yvwic^9;@7r%)~M3=KjD zMHHt5dMfiS|>&Rep$Z!(;@D~+cq;YT;PHU{`>x4tNGw$ zuiNwfegEGg;IubT6jTC+OwtsZ7`4p9uDVIUX|DJ(j)j(-!B3hsojAU_&QNN3rs6Y^ ze;J4374gI_fmxFcT)!C*qV|9ki5 zOTT8XKb>H(qo~08*MoCcHcpGH^SpMyX7ASpx0m$U?ND}?zmxf<;e)~nP7O2y zzDk^bqwq`qyleMsYG3VXI+VY%_)_K9Whr0&{i+Fi`gH1K+hymnPlepv^ySp~dCoto z4TQ~VbB$~^Cw$I7ty^BVv25|}lOT^xjb884FL;T!a_iIl{_NMzvsZ-FmCD&%PPskh zdRu_4?i|fsJ9cF3Ep~bO^3fxvV3C8yu8FhGu>DY2|9Q*Y*7OjkH*p6+|c${H44zEZjQWt4E@>63jtmCCLQ=LEfuU$y4)UjF@V-{pIZxBJxY+`WD7YFXLFz}71w zv#)#Jc8Dr}xZ~}IL-%u@=Uu+arqJVX^wXo#WA}dEEdF%rJe*47T@_R+@nlqbr&k{Q&^7hS} z6DdZSdz)RJW*W^raqgVo?dcASV~&d4WT^l1@b`IZ+1r7~tPXA1pS~e!?p)vF#^IX5 zOO`vXT6guMmFxKzmGzsCfAMk82~jsIN;!S<-`-QZ7R*q*{QKCpi}l+px1>2-Pt^Ip z@$-qlwpac3m>I0r{M46vdxE*rGfBC><+f5)Q@{FTL~*BfftvOvQd_~TBB|adA3kgV zhfG#iNke@7=dUkbI8OJOXvd#l+p#>-ccPu!iS2XeeY&>l$houY>Nk2#Z7lb*3{JUz zIOFA~3(sYv_kVr!^6#6bXRDs4hn8=-us9QXr!L>SH?QaT<8AtlZaY_LUYgsv*Lz)3*PDRU8v8*aJ6e9p^-mUpTBzTtIo0&?^c{FovpN9X4Q;E zcbMw@=Vdy5-4d|O!zCp<+uP62FY3KYprw_i<;1mX*KV6#_c-RNNNYWN>;AL5mYsNg zA}3uuI#}d%yhYur=2NA|HqTJXm*1Usd~&+R*2phB%g)w|20vLVzUgPTq;>VXD*NcZ z(CZ>sE%)EqdBxQAp2yOEwp-7gl)83B=~cw;6IZ!cEpIh;?U%Qo_OReam3!x@iv<=_ zz}=WH(&=)`G)h{&y*;qYcr2 zef8)uUz>h?UxmNz&62lUVyBk#-u$~~`FS?x|D_D~n3Am5F5B*JTf6M^!c#vZW4CK= zdV4r}dYW(GiFUhXvazdnHOODRd}yYU;KaLkW3P!Vbo=t)AoI<;cXM~2+a*KXyi$3~>#{w|m#w+E;c3XzSYN}N zo7Q}qr<57%w*4zpZZV%q_Vr&LyR~OEj(Q z?Wgzl^6o5uANP8$T2##4-R1tEF4CVrd)}(u=c*A9Q{0jfnF;?SKXc1@(S#xiNk?%mplA5J)WJwp!^mk$dxcJJPOv`>K5z?Ea6>t(0e ziw-Py?*~Qsw{PE4Or%bx7){)~+1QS=Y0|D8J0@)2Y&_FP%}A;j)cxGHZCh7N$Xkf{ zT?Vd=A1id)+uJv7-mE-(_UxkH-*Q_ffr^j0b7d_pEHvKPx>$m32@YJw!SIZI8HeJQ zj6))f2Yf(vRkxatAj26Jgy5O1u2nVstNnNVJ{LW8--LTx`s{1=3;$f9z5Y+1eNFwk zx5uixf0fo})?Ir)^Q&j*{_^Fow`S*x1hX(08+L21k~Z1BF4ErVR?DuWbI&He2bJr& z&o70@PD|)|7I;0E8>FsL^N@(?)b~@P*T+OlCU@-$g^CAW7rFV~!nV39zRzyQ=ReWG z-){SUs}8iPc-42NPX0`p%g*-+H{Z{=X|gAGp6%ZHmp2r1^)D>n=P$ZXGHw6O)ct~K zpC`OJl6-vg@e`#UD}QZFef?BDv^_5FaQV|cpSWK>-FJ1F{e@NbYBGHbUu%T5ho0BJ z?)SxRo~GAS|5bad?#Fg-m0s^xQh9@4g}u^T|J&~Rg|;vEy!iX(+qdMSo3~t?8ol0U zsdU};)R(cxXDBi3FneYgB*K)iZt>=Lj_Y%0@*eos{c79hD+e#J#r|%*wW0r>Tm6)) z(y142xBuOH?%K24b%pn&T;{fYzj!C+`O8{IyK5hxy*fUxIh=2&)t65aR%Y1^&Q=E< zZdrY`3a$0IeeiX1MdkXUx_LJ}u1+*{-T7(b^Ht|{w-ny?+r$5&>gSf*6>n|Q3J%rX z+EeknqVi);{HtG|w{fZkFAfAA9K7@Y+#&)s~TaM-a<&tGKUorx9I*xz4e*4BbxB2luqTie|7yVK!8!+|U;nnizV{Uy~7t|iNe7$>F z$*yZWulp=ZCV@?eTRHcLPvF$g-BZg~^_4`gxO{AFBzI+ps5N+T{^8FYsJ5Q z?kmCV8|Is52^+h{{k>)OdS=q>@_dt1(uJSh6b)S&E=YVfaozYJwf#%5Y}?xzU*_iM zS=`E;B9Krl>vK+|((ztd-aO0AbL(H!yjpYoRBzi8tIrXCZ}@3_{~jTG?9{c_8oBOL zpLQ3$p6Y$8lg7?YyV<=SpwWdoyc!i1qgC({#UwSiR2QC#QS-&MYPUw>LZ{?ls(a z$?b;myfWQOYxqkNx)>7F)}0nPdhPU?q^>P*eoekIRM@1^<=4UM|5e*iZ ztuGwT+Eq=|rqTFlQ=Ak^R%#WstFL}<>eYSY2S=Q^t zud;2^YX2TTG;7hwgTfk9YY@ z+`hxy$MlM!>qgd@Wi7|}o>$AJz2TfWM|0KZFOh4MKYS91cE~wj8s|U%X5V$a4O=VM z1hwD$`1W$Tp|H@l&Ciqmn{{ihDyj<$eRU!_W3IM*Y<`@r&fY(lLZsK<(tBf=#C>OP zS=85;#=G~I`-WvME=#P)={i@f>->sMQ_bgM_!6Iq#}f=DEM2bwYS)&x2?i6U zPMzxYo4I6Sq|e0Inwh(9Uo{s@lu~86xk}mfo2;JMj9d2)o3xq+e_Q79{JP$TuT2~8 zU9a{J%v*9IT6$_VfA>3|!}rrF{U?UoZ?sw!+#Ywc<#Fp*$Ca+9&1AC$(lXV{s#f_` zK7Vzh??H&}{0Vt$boQ9dIhCH%a`Bn{wvOA|=Fialbk6YFx8U3@=T?Nx-6ku%?1lEL zS&P!o&#R40oGCbe!n=JC5#vo2P7FUUN_E+P7$(=BiKC%d;I` z!PWwF&4^@r!97E%ZKu1KGYYl0IJU-g>0UPuSmGazToGI2dGK8^8J2=nwR`rVoQJN zys_W`7=^G^vXuz~BHsEFVx(VLC=gHzmR2eo`zZFh|SLMhm&%ZFwyN^t7y z>$`LR?c*<-?Iz{BHwRT76ga2^sr|sUtL>y@_wGG{^Q@L>NGw{V#_r70%>gktBUt6r zSCd)OzF!Hyd%h+_Qn5?6ep(5`E~vE?!7L2dnZZhN*N2Eo(nU77MZl>xaO;nDO(q7{ z&|nsZ4H=+Z%jF};FokOw2g9-hB8(0z$rjRS(Uj^xUQ|(`VQp=_Y3EMO?fLiJG*+HH z>wEL&&54H(J4^N-&ozJO*QhzG?MKtAt{<1;t8%;K?CW%*qoX%%->%LtXEWhsic)%d z`lp}I=PQd`J$kft&fK}6#>B-8mG}F8ugl5JJ-OJu|5o0mxeUQyRF8<8ba&|gT{eB$ zi$8y2%F4@AEo4reJn8vboblCuKR>?|3z<{z-mRN6fByEnN1~UO1iREYeir+<)c(sk zk-78cojP``&8FhRg0F3TV*ZOSdVrcpU%qU4yX>Bn>TIP)+`Ie)<9GS5_qq7<=gyp* zoD+MizenZY$tWy+f6w;jjT;)@`qqVjjPzac<;SH`$UyGSX6Ih`K<++KFH_ee;#a14 z_36hhH(&PR;$n9r8NTTJGb?0x+np=_{3yKbyT8!O1f*z-S1(vmMs{|$YyXPCxpU^6 zxOOcJU4i&A(6qts_xo;FDZ4$*%+FuH<9pAPw5|^Q6}nR;;&=J!`&@kZP_g*$3ejFS zWlI~IoZmtjQ!e=keq`OcROqqy^_Q)hw{G5?crxWu6|)<1PYBJBXV28~C%LYD@#c+> znYsDxeJoN-O+dcQU3moL+r+NC`}=go#l_c}Cm;{i_6E(;RNA*-TS!vPORK$xuDRxM zA?v)jqf}=t+ICw)D}3qE>Fb&`oir9-Y7$$Bd>a=-62?)i4h|JFITWP$jA*;=~$O6ETDy?D5tKee(l^4hg)lWyzk>!1Gi z?c3D;?c26}`xEi-2EV*r&eJ5B{^OhW?6FyT^=jz$np>w9Upsiv(P;hkrI(tnfrcRW zec#)>ZSzG5-lTNt9?LXjZnLcxIP#_}mt9=H;M{8FlPkS0{Cb_Y1n!zL4fBfYA^w97} zVWNp$yI7aKSlz82v*(`c?v7;{xw*Pkc2*5#syixv@+!w(pSwNe!ml@*^`E%gTTOoW zA)Gf(@cQ|+(e6c`pC#VDxx?uGzi;s;_x~_wP?1JlL4s<@A8_Q(MRNYuD!em*bge>S`uC zw>@HC&V&$8;F2XDqsM;ZG^++Vgh5owjYapPFCy zIeBN{!*Z=E|fRgz~OC_MiC=>NYwyKk0>>+j#c*Ev@F_^>c1 zKY#bK6{of)C3~C^S$gT?zqH3KzRKdxhkmw5WYx#V#`+%H5mM88bkBsi34ON}?J753 z(_XITBf4xwbVAn^)|afSuU@_S+^8d1vu+ z`RF}X>-z2gfBvs%o_A;ZY;*o<+o|8)=KsH1ocv_w;$^;p25!H$zkQo)X<@OWM7RC* zl{jrHu}J16zEkeGOLObTJ@uJb{`UF0+XZ$HE2{1b6z{D_y}b2$mEN<;%&J}Ic;TStl5F1g^sYVD3+{-_=9AjEa>JCH7af&K zzi0H%monr&zWMfzO&>0CIIj1*+nV@Ot!bL6bA0)R`pe&*7QVf+t5l`=;N<82OZWc$ z=KksO{CVGAvG(5*i7dXdMe|dVbH?v&o4>E~%=QaftYJ0xM(J#;X??C{c43{yziPt5 z!ZVzOyyqP+B#l7yaKm8-GxQ=(=Y`v1Lb z|5rXT?%(=PkGkuX_4j-*-d^nb_nP^>kNcng`@4Vtw{!mSn{O$!2r5;tU9xWPg@fUp zidDZO-faHqeRTD%>zNkv(!#}t=j1l~o$2l^xc&Cc{dCEV`&Jpa-en4Y($mt?tz@?A zqG|9G*8WKG>{qSNS3X$8JV{n_Q+cY@db9aqq1V`Bj~_Y{bAgL{RsNkH6|0>8PPYG9 zd3*Ztt)Cyu&p(;)!KLoU;ra;=KZF}e{dH5DTt88N-;eFvHit=`=h^$?QK7c7>q6dk ziw)bhecN-l{HDmuEqi7!ys4OIyi%jkuW69s8FZwxYvA^NVKy#nKn+aWK zjxH8wdzBDyROIGLi}&Z2tkOKidhE(k>2EVjvouX>pUYmKr4$>tZOyu0As#ctGCr*o z+P%zU_G0@V&GS#j|2djuTPgPA!{Pg<%J=^+|I{pRGuhwnXYB2pGbMK~)0nZ)L3)|T z`iY&rtB$P`t-U<4%3;YWO)tr&JIslQ@!-U-E)tCQe9w5 z z#j-Y`Z{N?e^H0kEdzfTb`|a-ge{*y4>u;5rt@AmoyKIb;eJ5^T zrcu7;&aS;Tc$41Le5vkEGWVJ%$bCDcx3bJ?Uti@Bk*U1PGz?2#_tw1NzA)QplmGmi z4G(52)dp5A)-zks+OYh(dWG|ym8{Jh1;wkszwp(6mHhIh$=vk6+uqzbG0Cn>??=_| z62*+#Z#Tt1eY?FsX2-=v^8bJM)O~19&rN@P>d)``|KS(iKQiaeTvWjOYIe_Ro7%Mb z30vpxO&9vIF?SEw%eL2-s_(kJV_mf|yzoV~t=X#N;hy=F-)GwYnsn6NF)Q2t>aOdp z$ql%c~t$UlkZauDlWa&-0X1uUdGzntFHe%|Jc?wamsDbM5FlnH-$;- zMLUmjYggN?-0C>5@uK1RV^3qwaAz+0lz*BbnC0kfrIsQs-3;FL{gdSXeUL}45M@CV z#Z$$$912cb>VQ`9{`&Xbe&WR!=2$D&pXctMO8KOZO|JRivKCXgQx-dJ~n$>gD z7Y3r&;WLz4W(8+{T>3hpOW@RsEel#TomN;PSMtMLfnUDQ#iK`EU-ybnUEbZ@{irFd zb6Llardt7>AD6!Va!4dMFYnaNn~|@1C8jRlyxI8Xojc^VXCFRX*yFbNnzVrysI3oK zsDR$2J@$Cxo40Sb-fIY~ymkBbapqTE^`N~C~exhRaISG zeXV&?NFS(|k)6Hz?Xvq8OJ^zxKH|=bTMAMq9sK3T$7D&q_O<3IA$@I!7ur;PSpia| zItyf26jYIl(x%;lD*m2_J%au7fIR)s&#G_V)5x+S=ysUb)?E&r9@$moOgd;Z$QxO*|R}ozU=Jmd(@9KAo_%2pw8?c%DSRt_hAQE zBLjm2e1kyKyp4PRt^_SFcy9my`O5wLZ2nLF{f!U5_5W(P`t?cM!{g_kkk0?J=+d^t zF0DEJSF7L8_0P@Ue*50PE56@*&FczZ{)wwC74p39VZHiw!}Ut+h^ZPWznF1$T4*|9Sp@ z<*OZ`R%gub{W!YRFMjsi10Y*Ui^}5X=80}zd|F3leO6_L)6Xi|b?1_G-cE2k(VpIQ zsP0$I+QeOzpEFBZj`!KIy_zwra^|Ah=JVZdue7^PJip} z4e=IY%Q$}Vfc?J7%;Ghl8++mHpDz^FS~p+l?5L6a;e33-`#HH$iC>fjtk!Ipd;MhF zOOa|jsp{==R{86VFTHH(J9+Qtaks8jekWg=yqeOkR&rteKC7K6r<~m9c->wdoZI!K zGShgLk*j&W-P#m^*>aknde+#@k34l^(d`{(COfx1o4G7RGNEfhenQuR@D~cJ-?!vG zU*n!pqOkq<{r&&5ch>*E9$e2ayT!K6_jK8gUwU?CuM$3sMX!HUI&I@cX4_3uUmeI* zU-w!5(gx+|#Qz0*tez(Ji}Ead*W>(LW?4~C=Iy|hH@-w_`Ck*Me4f2B*!{X;?Xu4^ zt>%YFMwVFbssDfd-HOH6uNk;*cmZ|5*@kxsB@WwzwagOo^Xs+V?=AngrF z7t{@0xt$~)ZFjsd+pIJ9HhYq6NKS6+i7&ES(yO+3ZYsZh&uV%E`_liiuX)lUgGHi4 z-bzleQg+?t?Cbmd$u*Iqr<@mCzeq^>x<5I)%jwp={4(E(<$b?IS<61|HdDR6bJ>a6 zv#$Ky^ukP{FZig)(o-7K>J+B*ZEHuiWhUCEmKTuK(mp4NmP1S=Ezcw?}YQKw0RmS#uYy z`!r8!?>wFbs}s5yq@MMf*9B%a>K<6ssM)lxS(7QF@yZF714=@284NFsAghFNZER|i zd$@N=fc-7mfA(K*6i%+3dtEr~n`+HH>x@J9+YZOaR;BlUPjdgA`q?h=b>+Mk_gm?; z+x=eMPJC$i&FXE?{Kuu+Uw_!A?r&xv8uu|_JEy)kE6Bzdyq1eMu2^>B_lfL^=Y9WX zUl%-YEFb&O>io&-#l^B)G%vl?-!p&J>17^|rxsS!PqN!*`sQBUuUM~dPnR;pG6%El zRlF+sYWm66i$Z^utoP3U`z_dE{|&=8#@<#|`rDXSSLNi-cc}Qi`CY}~?vHO?c&<59 zv{)xjuDJ61smyCeJx>p>e!lvN|KiJa@ArP5`O0g*W9oG*O7B&fsJ#)k?hp8X z%^-5}8u!Lkd$cvu^Kxb`|F&6w;+xkTs#8Gart{s2N`ECee_wm0HNSC&>D-XGuhHv* zkAM4iS$+?%e9+bT^&gf^Ni%f)cJAJ9jn&h?@7n+Ll)*Iq=<}hc&8D^A*m*uE{8#SX zdplVk3whtx7CtZ1YQ%X=J+_$~*m1 zt2FWR!qeAgN3EJ|?`@#J`P$Tb{{396%Cn^&emZAuS{wFNCiuDZW36Q;PWeqYY-NjO z3uf87@SR8Cn&uOdty;@8ruylu|E9dC)F;ru;TFfsbJzNko}60Kr@3nO_f^YQc*Ry! zEX%m|C$dR%*4A|;^PFm11J_MBR{!t({+?yB*6YHj#YG-D7g&EjXWGlnt9wKuf3QiF zfa-;|${9-5RttBY@(7%|CoXk~$CKCVC%?{|ZNQsszirm3_U*BE_s1Xi2%K8;qWIM> zkH8t*xGuY1w+u@0^?oPw+Hd~LO&3EX6}K7$v4CBiD7Q=_Cw>1Ey`b|VOD}moy}C}d zb0$0g?<0{O&g(DEI6g~hZ-3nOAk+7uzJV5DQ;n|t{NQtO&CktCu8D-M)Sj!pcSh9z z+tI;GJ}1|2erx<^*=dy}vZuVai&`5Quh#6ctzC9`T~b#>FvPNhv$HPF&8j%`Z2zC> z{*&h}sQsj#)>Je%Q%82Lxb&Z5f0Ly?6KhTGpT2D46R6W4`Z?~n$kI~=Wj4|0!%xn4 zoxLdX)v0OO5}KD@zMLpKdz)?EyO+kjbCou`Y5xgJouYOv@6D9u-{&pTYU2jyUWNsN zGpw3Hxt5_JTYWnp{{n8v{zB09Lbhu)3>1vLOp*{8LnA=h9ZqCc7q0riP${B9ilL ztHUafc+6fjb?VexF!iE77kQ3vxP5nT_4T=KheaIa4?<=pWSUM|+S#p}GrizW`uTaG zc6<)vFqyu-zO31c4BjqVe$l}7g1dn$Lx9!{rS?dli5)Ss5N7Bs(Y)l}51z|eFM8?I zrHhv{W+=T-o}t8`G4hWzsRUnkb= zt?h}hO8lk!l~1{09oR1~=V}Ulod4xg{q-w`t_KCK)>bBK_19`gGk~U7y!3r1p16KF zBkCTv$m_aii%)S(^gXUDvBqwi?iAi-91LDdw=d&hSjP@hi+3u9_(>L~hM<>QHLL#o z*a(_6xp!}#O~nTXwaJ~J8I|Yr>-z#i#Kpyn%F5IxpLB6sJaNzOce_Cyn|?XltlggF zOdywd>HC7_KHj{0cdEc*%H+wDuUSW4sRvC=6j)5TdpFk7-adbK=XQ{Ty_OPKiNCfH z6yYzYqApHRhc8a)k~KU8isUb+MBcu8XXMl(buq(a60}E@(8aJIq$;^f&bCVB@WTyX z&k0Rk{IEcyU*0}%_e*m=Z~&Sw1J9gXMVUDPCxg8Pu8%)P+^hY5_nNh5$h>dgzI9di zgQktWmWnTX@!`XStuDxuB_a^7`&>MCuFpqpGI$M}+T_kRZ{BRFuuY(q(cI*G+4Q63D+60=k zndEaZ<&*xWx$pnvf*0Vjf=5tNy4)7uKkM)q!UM5{%y5pFVwhYIXJR zpZj;Gb?y1|s!J0(ovTo-MtgxWlgr=lt&gIYMXnH#1wu1;3k^LYK* zwZ5|6{W>@6U+>R0PQJ{crW5Wz&oTG32xu5?)84-;Yd+7GKiw-Wzr7&z%=EW!{h#i> z|93Zd>95v|MOUvrmtFmCj=WusMs{{~pzx+`+saPbwEW%MXC=Xq+m&OLot+(gY(#EIH7fas0 zeY>cjpx|W75ubK5_1m{^Pv>!e@n@~(rQ0|7_H}7?NjBYi(JdSMsi)Hpv~GUR>g~OH z-4RmR+1c+nCWreg_6CIe&Q!{7V{29iMT-5u$NMvXe_C-yJpRvYAGQBVi!bKSvrjdX zut_|{!|*`cz%{;fTiF!lG`2Sxon``t%}-13%`4pWY*m*gS8(9Y!1?BERTT^j0$V}n z0?cr#a=gb8aW3R#?VA&!c`BM;%h%64w7@OuXoRfL+9ts zUbyd-_5GjGKmUEVulzSfvU?RH!#=j)6gP!qk2lK5$hf$h?@H_XQg+X3{;sDJr9>}h zHy$$l;xX~=alhV|UxVkZnzbll+qG-gq+~UJUF<*iL0xnEB^u{FnbHjTsmYh{VpC#@Ri=`MLe;S&Jgn<5GPC zUqyt*slA+Olszly_pv_t+vjKRy6oSTSuAE8X1Q79cWi&m){kFq_ScoD-T(9K{1g8F z8~*#xXJlYlcA{2D%j}b&G1JE7=eHz#AuXm!`yhlktW74E6EdHi%Hk9E~k z-7VK%9=m4z@}*6Fil@Bw^!rmZFRi!D_-yN%zyGhdTQ>uP7=zEm&lTI#jn@5|r079Zp1epw-fE>`fdF}n-lJfKJndo^P=MH>3{$J^==DzuDR{UZ8_`jNoTHj1YN$I zZYcJ!_ZkDk(%>zcPAj^+etnZOLBJj4aJOhK&B6HBP z-tzM4TU}QO+E#pUC@U|&o%e}>;ex_mBiHB8pKsc@QStk`yV-j$yL7Lv{{HUdv14uE zwHHqq85THJrFOZv`1$*%CMP!wDwpV1eR$9aT2=A#W#(;PSq28FW#!8}o}3n3eD`jw zBwxGEKDXkFCr@_rv^(FtdpEU(gJD4cu93(eDje8HA_Gks93FnTCBh2I$Z~S0&YkPa z$;&(S_V#u`udL$Y;Igu^Cl4Mpd>3G3Xz0-C03XV+LkoZZ7T>`gy0aHu{{L^jfD?x% zqeJzUysjsk)j1Sf?5dkInKC4O1f4iaU1lgXlpPdNYzc60(PYXHCr9vQucp<%54Dm! zY@gn|{Ckag`tp1tn;IM-Icdy(3$ zd!UUKmrm=Omig6YtAkwfa*8HssqA^?hyacYGZwuLkM{}GSiJ4?#*8SF;48<=Kn|aN zZibS6#J$?*x|aVw)J{Bq%Fs3U)T~9je&4HozSiwi<@dSUtun6#ROcQFmcPxpjAKEp zRdN?w^TA@~C!E10e_wTLM%91*datxhbyY6hOuw0n7W2PzX>LvL3d`GTWO`NX8~^R7 z$*Jv^50^QHGVO?4EYO$edvWvf@5{Gwx+(v;J8!w&cF=m<%p+%(rPs$-{apGY|C>zk zvg5NBEu9`eOH0^#Z{?SRbG<7!AK&o%g%#)Xtj{xy_N`35`7PnK@tpV-heK-Hw>^?Q zZk;~&`G?)*ab@v)<1Lom)4#I(T>skS^EEQH1?gG469nE=zN~$_(7D6O~ovhmfHy?4G&-^KQ|PBFf0_AZEfKfXGj&HV7s8qFrK6!N8T_?Ip?J zCDumgWkP4#MOXb?`ke7j8JD6$+uy?+t#5gf8P6I^SS@(9Aj3L#u6TZm=kjc8HS4J4 z&)K}w?9T5BuGS2m5I`XR2?Uc1kXzI6&uUUUD=vXL`(g`E^73**00nk0RU|q1N{zc2&)uQh8Z6cq*S&*_sXhGon^+ z3e!mKDw$cSth)X(s|B9Arq$<35@k+}7a2bCK3%{%@ zpNbp1?ksw-NYm@?%js!dNxAD!eQnoVrSBu?u)E}z$jfu**i@w(oZC~Et51uo^PFe9 z_x(E7Q!}S)Io|MN44qkYA=uljp(;V`DCR#L~;NrfaUsida2k zk(S#PZQ=Z1YdnLW=*I2q(mb_wuh#YWt1pe$uX+3BX6ejDS1PM6r_WGoIJ!)D*^8T( ze@}0kH~0T{pNZQOE=TJ>U`@|od+Z{6`6RcKdQ+}0Rx{Ihb)fps!{2$&1C|h(zkQRjTJZYY0p`|FM4}-M()qsR$I8!a;-iax$c^mdwkXDWv@;|&6u|3>!R0p zqBGXYGi6*7Ioekr8aySdI&|Ish}kPPUAWc961QB_OLvQ(EPpV|hKiD7B9+2UetB{>ZfPx?$zZr*iz;_4oKZRlb^dv-O(Q z+!>u)e{Oy~@6F?1pN(9%<=HgHr0=@8uj*j5f~@xSWxf;7=I`KJm(>*n3hw7yIoI>$ zL{{&QU#|J-obk2|(!nenZj>AnQEU-7B*M6bcNvFbi=-~9VUa@*sVkC&bET)voj(?6>n=eotWe0{&Lr|9WU&|37;<)7!CaQ%`u&=}KMVIhzVWs+;ER>|-OLw$ zx^Kkmwm;Lpw(+Qyy6l$28@D{{n%TC&cUAD#W9lU__wpBh=1pC4{(RXItN6I|Ek&=V zt}MEE{L`%<4d&QuE6pBWbzk9LdnaUW_{s8&$G>WFrN8@Z+?Tk+>o2RbVD{v1HU0KA z`?qO&J++>`PgnZxwA{Z>eFAS>zm~4WJA40)t*N&i-YipA2PK*>heU4n`LHkjY97B| zq$a7n!|F%m;zaA!AGU`ifHo|Ct}U9o4qUAjy<8W({H0{es!NsMnYQ0mGYg$Ldz#nO ziRoQAQQrFdpZxQEe)V-i&hwQ1)XOJ&XH?`qdeLnC&hFukomT57qHvxt`0MGBjtE%oYxHkKALG ze@o#;niBv#4d(gOO2PE;C2Z03FO#g)p7gi;!vvtTFX4xEB0DgKXGPvoL&AtW{>MO ztGQOoPWZ`Qoon~m?U0kzPE*&7yJjxe{N!d_a%-cX;TqA?QxkJSPE6~xdmaNyqFD>K z<_TLC8)pB#dGu!D6Oa2POJ2EUiv>^dzW>kq+O%NqFS(J+<=QqJGn&%=@AlpDdsTHZ z`ezN6c4;!bke_SlYQ@m%5Oq}KWy6Z8uUOJ!gO_|3f4AYS)9VnqLn7VZzf25UXZ&T! z_wD^G;fAjFEL#Mp&C%TS`^c%Et1hQk{hhJ>ns!>&s-BXi%TDF|y`e6WTpFi(KTdjs zZ1GjW>5;F_SI6A*^L}+d*j#$^j72fOcICWL{`u`k6_W6P@|?v(}`nY zA8x_5vz1x|oZ`6|ZY>6_dS_s`APVX{GB6D6DSWA20!|!?Ene6Ev$pJT{A#sxrZNKq O1B0ilpUXO@geCyH?)Jn0 literal 0 HcmV?d00001 diff --git a/docs/en/api-reference/protocols/modbus.rst b/docs/en/api-reference/protocols/modbus.rst index aea7ad9b3e..c646147431 100644 --- a/docs/en/api-reference/protocols/modbus.rst +++ b/docs/en/api-reference/protocols/modbus.rst @@ -4,7 +4,6 @@ ESP-Modbus Overview -------- - The Modbus serial communication protocol is de facto standard protocol widely used to connect industrial electronic devices. Modbus allows communication among many devices connected to the same network, for example, a system that measures temperature and humidity and communicates the results to a computer. The Modbus protocol uses several types of data: Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs. Versions of the Modbus protocol exist for serial port and for Ethernet and other protocols that support the Internet protocol suite. There are many variants of Modbus protocols, some of them are: @@ -13,115 +12,651 @@ There are many variants of Modbus protocols, some of them are: * ``Modbus ASCII`` — This is used in serial communication and makes use of ASCII characters for protocol communication. The ASCII format uses a longitudinal redundancy check checksum. Modbus ASCII messages are framed by leading colon (":") and trailing newline (CR/LF). * ``Modbus TCP/IP or Modbus TCP`` — This is a Modbus variant used for communications over TCP/IP networks, connecting over port 502. It does not require a checksum calculation, as lower layers already provide checksum protection. +The following document (and included code snippets) requires some familiarity with the Modbus protocol. Refer to the Modbus Organization's with protocol specifications for specifics. -Modbus port specific API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Messaging Model And Data Mapping +-------------------------------- +Modbus is an application protocol that defines rules for messaging structure and data organization that are independent of the data transmission medium. Traditional serial Modbus is a register-based protocol that defines message transactions that occur between master(s) and slave devices (multiple masters are allowed on using Modbus TCP/IP). The slave devices listen for communication from the master and simply respond as instructed. The master(s) always controls communication and may communicate directly to one slave, or all connected slaves, but the slaves cannot communicate directly with each other. -ESP-IDF supports Modbus Serial/TCP slave and master protocol stacks (port) and provides Modbus controller interface API to interact with user application. +.. figure:: ../../../_static/modbus-segment.png + :align: center + :scale: 80% + :alt: Modbus segment diagram + :figclass: align-center -The functions below are used to create and then initialize actual Modbus controller interface for Serial/TCP port accordingly: + Modbus segment diagram -.. doxygenfunction:: mbc_slave_init -.. doxygenfunction:: mbc_master_init -.. doxygenfunction:: mbc_slave_init_tcp -.. doxygenfunction:: mbc_master_init_tcp +.. note:: It is assumed that the number of slaves and their register maps are known by the Modbus master before the start of stack. +The register map of each slave device is usually part of its device manual. A Slave device usually permits configuration of its short slave address and communication options that are used within the device's network segment. -Modbus common interface API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The Modbus protocol allows devices to map data to four types of registers (Holding, Input, Discrete, Coil). The figure below illustrates an example mapping of a device's data to the four types of registers. +.. figure:: ../../../_static/modbus-data-mapping.png + :align: center + :scale: 80% + :alt: Modbus data mapping + :figclass: align-center -The function initializes the Modbus controller interface and its active context (tasks, RTOS objects and other resources). + Modbus data mapping -.. doxygenfunction:: mbc_slave_setup -.. doxygenfunction:: mbc_master_setup +The following sections give an overview of how to use the ESP_Modbus component found under `components/freemodbus`. The sections cover initialization of a Modbus port, and the setup a master or slave device accordingly: -The function is used to setup communication parameters of the Modbus stack. See the Modbus controller API documentation for more information. -Note: The communication structure provided as a parameter is different for serial and TCP communication mode. +- :ref:`modbus_api_port_initialization` +- :ref:`modbus_api_slave_overview` +- :ref:`modbus_api_master_overview` -:cpp:func:`mbc_slave_set_descriptor`: Initialization of slave descriptor. +.. _modbus_api_port_initialization: + +Modbus Port Initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ESP_Modbus supports Modbus SERIAL and TCP ports and a port must be initialized before calling any other Modbus API. The functions below are used to create and then initialize Modbus controller interface (either master or slave) over a particular transmission medium (either Serial or TCP/IP): + +- :cpp:func:`mbc_slave_init` +- :cpp:func:`mbc_master_init` +- :cpp:func:`mbc_slave_init_tcp` +- :cpp:func:`mbc_master_init_tcp` + +The API call uses the first parameter to recognize the type of port being initialized. Supported enumeration for different ports: :cpp:enumerator:`MB_PORT_SERIAL_MASTER`, :cpp:enumerator:`MB_PORT_SERIAL_SLAVE` accordingly. +The parameters :cpp:enumerator:`MB_PORT_TCP_MASTER`, :cpp:enumerator:`MB_PORT_TCP_SLAVE` are reserved for internal usage. + +.. code:: c + + void* master_handler = NULL; // Pointer to allocate interface structure + // Initialization of Modbus master for serial port + esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler); + if (master_handler == NULL || err != ESP_OK) { + ESP_LOGE(TAG, "mb controller initialization fail."); + } + +This example code to initialize slave port: + +.. code:: c + + void* slave_handler = NULL; // Pointer to allocate interface structure + // Initialization of Modbus slave for TCP + esp_err_t err = mbc_slave_init_tcp(&slave_handler); + if (slave_handler == NULL || err != ESP_OK) { + // Error handling is performed here + ESP_LOGE(TAG, "mb controller initialization fail."); + } + +.. _modbus_api_master_overview: + +Modbus Master API Overview +-------------------------- + +The following overview describes how to setup Modbus master communication. The overview reflects a typical programming workflow and is broken down into the sections provided below: + +1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface for the selected port. +2. :ref:`modbus_api_master_configure_descriptor` - Configure data descriptors to access slave parameters. +3. :ref:`modbus_api_master_setup_communication_options` - Allows to setup communication options for selected port. +4. :ref:`modbus_api_master_start_communication` - Start stack and sending / receiving data. +5. :ref:`modbus_api_master_destroy` - Destroy Modbus controller and its resources. + +.. _modbus_api_master_configure_descriptor: + +Configuring Master Data Access +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The architectural approach of ESP_Modbus includes one level above standard Modbus IO driver. +The additional layer is called Modbus controller and its goal is to add an abstraction such as CID - characteristic identifier. +The CID is linked to a corresponding Modbus registers through the table called Data Dictionary and represents device physical parameter (such as temperature, humidity, etc.) in specific Modbus slave device. +This approach allows the upper layer (e.g., MESH or MQTT) to be isolated from Modbus specifics thus simplify Modbus integration with other protocols/networks. + +The Data Dictionary is the list in the Modbus master which shall be defined by user to link each CID to its corresponding Modbus registers representation using Register Mapping table of the Modbus slave being used. +Each element in this data dictionary is of type :cpp:type:`mb_parameter_descriptor_t` and represents the description of one physical characteristic: + +.. list-table:: Table 1 Modbus master Data Dictionary description + :widths: 8 10 82 + :header-rows: 1 + + * - Field + - Description + - Detailed information + * - ``cid`` + - Characteristic ID + - The identifier of characteristic (must be unique). + * - ``param_key`` + - Characteristic Name + - String description of the characteristic. + * - ``param_units`` + - Characteristic Units + - Physical Units of the characteristic. + * - ``mb_slave_addr`` + - Modbus Slave Address + - The short address of the device with correspond parameter UID. + * - ``mb_param_type`` + - Modbus Register Type + - Type of Modbus register area. + :cpp:enumerator:`MB_PARAM_INPUT`, :cpp:enumerator:`MB_PARAM_HOLDING`, :cpp:enumerator:`MB_PARAM_COIL`, :cpp:enumerator:`MB_PARAM_DISCRETE` - represents Input , Holding, Coil and Discrete input register area accordingly; + * - ``mb_reg_start`` + - Modbus Register Start + - Relative register address of the characteristic in the register area. + * - ``mb_size`` + - Modbus Register Size + - Length of characteristic in registers. + * - ``param_offset`` + - Instance Offset + - Offset to instance of the characteristic in bytes. It is used to calculate the absolute address to the characteristic in the storage structure. + It is optional field and can be set to zero if the parameter is not used in the application. + * - ``param_type`` + - Data Type + - Specifies type of the characteristic. + :cpp:enumerator:`PARAM_TYPE_U8`, :cpp:enumerator:`PARAM_TYPE_U16`, :cpp:enumerator:`PARAM_TYPE_U32` - Unsigned integer 8/16/32 bit type; + :cpp:enumerator:`PARAM_TYPE_FLOAT` - IEEE754 floating point format; + :cpp:enumerator:`PARAM_TYPE_ASCII` - ASCII string or binary data; + * - ``param_size`` + - Data Size + - The storage size of the characteristic (bytes). + * - ``param_opts`` + - Parameter Options + - Limits, options of characteristic used during processing of alarm in user application (optional) + * - ``access`` + - Parameter access type + - Can be used in user application to define the behavior of the characteristic during processing of data in user application; + :cpp:enumerator:`PAR_PERMS_READ_WRITE_TRIGGER`, :cpp:enumerator:`PAR_PERMS_READ`, :cpp:enumerator:`PAR_PERMS_READ_WRITE_TRIGGER`; + +.. note:: The ``cid`` and ``param_key`` have to be unique. Please use the prefix to the parameter key if you have several similar parameters in your register map table. + +.. list-table:: Table 2 Example Register mapping table of Modbus slave + :widths: 5 5 2 10 5 5 68 + :header-rows: 1 + + * - CID + - Register + - Length + - Range + - Type + - Units + - Description + * - 0 + - 30000 + - 4 + - MAX_UINT + - U32 + - Not defined + - Serial number of device (4 bytes) read-only + * - 1 + - 30002 + - 2 + - MAX_UINT + - U16 + - Not defined + - Software version (4 bytes) read-only + * - 2 + - 40000 + - 4 + - -20..40 + - FLOAT + - DegC + - Room temperature in DegC. Writing a temperature value to this register for single point calibration. + +.. code:: c + + // Enumeration of modbus slave addresses accessed by master device + enum { + MB_DEVICE_ADDR1 = 1, + MB_DEVICE_ADDR2, + MB_SLAVE_COUNT + }; + + // Enumeration of all supported CIDs for device + enum { + CID_SER_NUM1 = 0, + CID_SW_VER1, + CID_TEMP_DATA_1, + CID_SER_NUM2, + CID_SW_VER2, + CID_TEMP_DATA_2 + }; + + // Example Data Dictionary for Modbus parameters in 2 slaves in the segment + mb_parameter_descriptor_t device_parameters[] = { + // CID, Name, Units, Modbus addr, register type, Modbus Reg Start Addr, Modbus Reg read length, + // Instance offset (NA), Instance type, Instance length (bytes), Options (NA), Permissions + { CID_SER_NUM1, STR("Serial_number_1"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2, + 0, PARAM_TYPE_U32, 4, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_SW_VER1, STR("Software_version_1"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 1, + 0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_TEMP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0, 2, + 0, PARAM_TYPE_FLOAT, 4, OPTS( 16, 30, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_SER_NUM2, STR("Serial_number_2"), STR("--"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 0, 2, + 0, PARAM_TYPE_U32, 4, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_SW_VER2, STR("Software_version_2"), STR("--"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 2, 1, + 0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_TEMP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR2, MB_PARAM_HOLDING, 0, 2, + 0, PARAM_TYPE_FLOAT, 4, OPTS( 20, 30, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + }; + // Calculate number of parameters in the table + uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0])); + +During initialization of the Modbus stack, a pointer to the Data Dictionary (called descriptor) must be provided as the parameter of the function below. :cpp:func:`mbc_master_set_descriptor`: Initialization of master descriptor. -The Modbus stack uses parameter description tables (descriptors) for communication. These are different for master and slave implementation of stack and should be assigned by the API call before start of communication. +.. code:: c -.. doxygenfunction:: mbc_slave_start -.. doxygenfunction:: mbc_master_start - -Modbus controller start function. Starts stack and interface and allows communication. - -.. doxygenfunction:: mbc_slave_destroy -.. doxygenfunction:: mbc_master_destroy - -This function stops Modbus communication stack and destroys controller interface. - -There are some configurable parameters of modbus_controller interface and Modbus stack that can be configured using KConfig values in "Modbus configuration" menu. The most important option in KConfig menu is "Enable Modbus stack support ..." for appropriate communication mode that allows to select master or slave stack for implementation. See the examples for more information about how to use these API functions. + ESP_ERROR_CHECK(mbc_master_set_descriptor(&device_parameters[0], num_device_parameters)); +The Data Dictionary can be initialized from SD card, MQTT or other source before start of stack. Once the initialization and setup is done, the Modbus controller allows the reading of complex parameters from any slave included in descriptor table using its CID. -Modbus slave interface API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _modbus_api_master_setup_communication_options: + +Master Communication Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Calling the setup function allows for specific communication options to be defined for port. + +:cpp:func:`mbc_master_setup` + +The communication structure provided as a parameter is different for serial and TCP communication mode. + +Example setup for serial port: + +.. code:: c + + mb_communication_info_t comm_info = { + .port = MB_PORT_NUM, // Serial port number + .mode = MB_MODE_RTU, // Modbus mode of communication (MB_MODE_RTU or MB_MODE_ASCII) + .baudrate = 9600, // Modbus communication baud rate + .parity = MB_PARITY_NONE // parity option for serial port + }; + + ESP_ERROR_CHECK(mbc_master_setup((void*)&comm_info)); + +Modbus master TCP port requires additional definition of IP address table where number of addresses should be equal to number of unique slave addresses in master Modbus Data Dictionary: + +The order of IP address string corresponds to short slave address in the Data Dictionary. + +.. code:: c + + #define MB_SLAVE_COUNT 2 // Number of slaves in the segment being accessed (as defined in Data Dictionary) + + char* slave_ip_address_table[MB_SLAVE_COUNT] = { + "192.168.1.2", // Address corresponds to UID1 and set to predefined value by user + "192.168.1.3", // corresponds to UID2 in the segment + NULL // end of table + }; + + mb_communication_info_t comm_info = { + .ip_port = MB_TCP_PORT, // Modbus TCP port number (default = 502) + .ip_addr_type = MB_IPV4, // version of IP protocol + .ip_mode = MB_MODE_TCP, // Port communication mode + .ip_addr = (void*)slave_ip_address_table, // assign table of IP addresses + .ip_netif_ptr = esp_netif_ptr // esp_netif_ptr pointer to the corresponding network interface + }; + + ESP_ERROR_CHECK(mbc_master_setup((void*)&comm_info)); + +.. note:: Refer to :doc:`esp_netif component <../network/esp_netif>` for more information about network interface initialization. + +The slave IP addresses in the table can be assigned automatically using mDNS service as described in the example. +Refer to :example:`protocols/modbus/tcp/mb_tcp_master` for more information. + +.. note:: RS485 communication requires call to UART specific APIs to setup communication mode and pins. Refer to :ref:`uart-api-running-uart-communication` section of UART documentation. -The slave stack requires the user defined structures which represent Modbus parameters accessed by stack. These structures should be prepared by user and be assigned to the modbus_controller interface using :cpp:func:`mbc_slave_set_descriptor()` API call before start of communication. -The interface API functions below are used for Modbus slave application: +.. _modbus_api_master_start_communication: -.. doxygenfunction:: mbc_slave_set_descriptor +Master Communication +^^^^^^^^^^^^^^^^^^^^ -The function initializes Modbus communication descriptors for each type of Modbus register area (Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs). Once areas are initialized and the :cpp:func:`mbc_slave_start()` API is called the Modbus stack can access the data in user data structures by request from master. See the :cpp:type:`mb_register_area_descriptor_t` and example for more information. +The starting of the Modbus controller is the final step in enabling communication. This is performed using function below: -.. doxygenfunction:: mbc_slave_check_event +:cpp:func:`mbc_master_start` -The blocking call to function waits for event specified in the input parameter as event mask. Once master access the parameter and event mask matches the parameter the application task will be unblocked and function will return ESP_OK. See the :cpp:type:`mb_event_group_t` for more information about Modbus event masks. +.. code:: c + + esp_err_t err = mbc_master_start(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "mb controller start fail, err=%x.", err); + } + +The list of functions below are used by the Modbus master stack from a user's application: -.. doxygenfunction:: mbc_slave_get_param_info +:cpp:func:`mbc_master_send_request`: This function executes a blocking Modbus request. The master sends a data request (as defined in parameter request structure :cpp:type:`mb_param_request_t`) and then blocks until a response from corresponding slave and returns the status of command execution. This function provides a standard way for read/write access to Modbus devices in the network. -The function gets information about accessed parameters from modbus controller event queue. The KConfig 'CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE' key can be used to configure the notification queue size. The timeout parameter allows to specify timeout for waiting notification. The :cpp:type:`mb_param_info_t` structure contain information about accessed parameter. +:cpp:func:`mbc_master_get_cid_info`: The function gets information about each characteristic supported in the data dictionary and returns the characteristic's description in the form of the :cpp:type:`mb_parameter_descriptor_t` structure. Each characteristic is accessed using its CID. + +:cpp:func:`mbc_master_get_parameter`: The function reads the data of a characteristic defined in the parameters of a Modbus slave device. The additional data for request is taken from parameter description table. + +Example: + +.. code:: c + + const mb_parameter_descriptor_t* param_descriptor = NULL; + uint8_t temp_data[4] = {0}; // temporary buffer to hold maximum CID size + uint8_t type = 0; + .... + + // Get the information for characteristic cid from data dictionary + esp_err_t err = mbc_master_get_cid_info(cid, ¶m_descriptor); + if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { + err = mbc_master_get_parameter(param_descriptor->cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data, &type); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (char*)param_descriptor->param_units, + *(uint32_t*)temp_data); + } else { + ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (int)err, + (char*)esp_err_to_name(err)); + } + } else { + ESP_LOGE(TAG, "Could not get information for characteristic %d.", cid); + } -Modbus master interface API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -The Modbus master implementation requires parameter description table be defined before start of stack. This table describes characteristics (physical parameters like temperature, humidity, etc.) and links them to Modbus registers in specific slave device in the Modbus segment. The table has to be assigned to the modbus_controller interface using :cpp:func:`mbc_master_set_descriptor()` API call before start of communication. - -Below are the interface API functions that are used to setup and use Modbus master stack from user application and can be executed in next order: - -.. doxygenfunction:: mbc_master_set_descriptor - -Assigns parameter description table for Modbus controller interface. The table has to be prepared by user according to particular implementation. -Note: TCP communication stack requires to setup additional information about modbus slaves that corresponds to each address(index) used in description table. This information with IP addresses of the slaves is assigned using communication structure and interface setup call. - -.. doxygenfunction:: mbc_master_send_request - -This function sends data request as defined in parameter request, waits response from corresponded slave and returns status of command execution. This function provides a standard way for read/write access to Modbus devices in the network. - -.. doxygenfunction:: mbc_master_get_cid_info - -The function gets information about supported characteristic defined as cid. It will check if characteristic is supported and returns its description. - -.. doxygenfunction:: mbc_master_get_parameter - -The function reads data of characteristic defined in parameters from Modbus slave device and returns its data. The additional data for request is taken from parameter description table. - -.. doxygenfunction:: mbc_master_set_parameter +:cpp:func:`mbc_master_set_parameter` The function writes characteristic's value defined as a name and cid parameter in corresponded slave device. The additional data for parameter request is taken from master parameter description table. +.. code:: c + + uint8_t type = 0; // Type of parameter + uint8_t temp_data[4] = {0}; // temporary buffer + + esp_err_t err = mbc_master_set_parameter(CID_TEMP_DATA_2, "Temperature_2", (uint8_t*)temp_data, &type); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Set parameter data successfully."); + } else { + ESP_LOGE(TAG, "Set data fail, err = 0x%x (%s).", (int)err, (char*)esp_err_to_name(err)); + } + + +.. _modbus_api_master_destroy: + +Modbus Master Teardown +^^^^^^^^^^^^^^^^^^^^^^ + +This function stops Modbus communication stack and destroys controller interface and free all used active objects. + +:cpp:func:`mbc_master_destroy` + +.. code:: c + + ESP_ERROR_CHECK(mbc_master_destroy()); + + +.. _modbus_api_slave_overview: + +Modbus Slave API Overview +------------------------- + +The sections below represent typical programming workflow for the slave API which should be called in following order: + +1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface for the selected port. +2. :ref:`modbus_api_slave_configure_descriptor` - Configure data descriptors to access slave parameters. +3. :ref:`modbus_api_slave_setup_communication_options` - Allows to setup communication options for selected port. +4. :ref:`modbus_api_slave_communication` - Start stack and sending / receiving data. Filter events when master accesses the register areas. +5. :ref:`modbus_api_slave_destroy` - Destroy Modbus controller and its resources. + +.. _modbus_api_slave_configure_descriptor: + +Configuring Slave Data Access +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following functions must be called when the Modbus controller slave port is already initialized. Refer to :ref:`modbus_api_port_initialization`. + +The slave stack requires the user to define structures (memory storage areas) that store the Modbus parameters accessed by stack. These structures should be prepared by the user and be assigned to the Modbus controller interface using :cpp:func:`mbc_slave_set_descriptor` API call before the start of communication. The slave task can call the :cpp:func:`mbc_slave_check_event` function which will block until the Modbus master access the slave. The slave task can then get information about the data being accessed. + +.. note:: One slave can define several area descriptors per each type of Modbus register area with different start_offset. + +Register area is defined by using the :cpp:type:`mb_register_area_descriptor_t` structure. + +.. list-table:: Table 3 Modbus register area descriptor + :widths: 8 92 + :header-rows: 1 + + * - Field + - Description + * - ``start_offset`` + - Zero based register relative offset for defined register area. Example: register address = 40002 ( 4x register area - Function 3 - holding register ), start_offset = 2 + * - ``type`` + - Type of the Modbus register area. Refer to :cpp:type:`mb_param_type_t` for more information. + * - ``address`` + - A pointer to the memory area which is used to store the register data for this area descriptor. + * - ``size`` + - The size of the memory area in bytes which is used to store register data. + +:cpp:func:`mbc_slave_set_descriptor` + +The function initializes Modbus communication descriptors for each type of Modbus register area (Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs). Once areas are initialized and the :cpp:func:`mbc_slave_start()` API is called the Modbus stack can access the data in user data structures by request from master. + +.. code:: c + + #define MB_REG_INPUT_START_AREA0 (0) + #define MB_REG_HOLDING_START_AREA0 (0) + #define MB_REG_HOLD_CNT (100) + #define MB_REG_INPUT_CNT (100) + + mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure + unit16_t holding_reg_area[MB_REG_HOLD_CNT] = {0}; // storage area for holding registers + unit16_t input_reg_area[MB_REG_INPUT_CNT] = {0}; // storage area for input registers + + reg_area.type = MB_PARAM_HOLDING; // Set type of register area + reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol + reg_area.address = (void*)&holding_reg_area[0]; // Set pointer to storage instance + reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes + ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area)); + + reg_area.type = MB_PARAM_INPUT; + reg_area.start_offset = MB_REG_INPUT_START_AREA0; + reg_area.address = (void*)&input_reg_area[0]; + reg_area.size = sizeof(input_reg_area) << 1; + ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area)); + + +At least one area descriptor per each Modbus register type must be set in order to provide register access to its area. If the master tries to access an undefined area, the stack will generate a Modbus exception. + +Direct access to register area from user application must be protected by critical section: + +.. code:: c + + portENTER_CRITICAL(¶m_lock); + holding_reg_area[2] += 10; + portEXIT_CRITICAL(¶m_lock); + + +.. _modbus_api_slave_setup_communication_options: + +Slave Communication Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The function initializes the Modbus controller interface and its active context (tasks, RTOS objects and other resources). + +:cpp:func:`mbc_slave_setup` + +The function is used to setup communication parameters of the Modbus stack. + +Example initialization of Modbus TCP communication: + +.. code:: c + + esp_netif_init(); + ... + + mb_communication_info_t comm_info = { + .ip_port = MB_TCP_PORT, // Modbus TCP port number (default = 502) + .ip_addr_type = MB_IPV4, // version of IP protocol + .ip_mode = MB_MODE_TCP, // Port communication mode + .ip_addr = NULL, // This field keeps the client IP address to bind, NULL - bind to any client + .ip_netif_ptr = esp_netif_ptr // esp_netif_ptr - pointer to the corresponding network interface + }; + + // Setup communication parameters and start stack + ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info)); + +Example initialization of Modbus serial communication: + +.. code:: c + + #define MB_SLAVE_DEV_SPEED 9600 + #define MB_SLAVE_ADDR 1 + #define MB_SLAVE_PORT_NUM 2 + ... + + // Setup communication parameters and start stack + mb_communication_info_t comm_info = { + .mode = MB_MODE_RTU, // Communication type + .slave_addr = MB_SLAVE_ADDR, // Short address of the slave + .port = MB_SLAVE_PORT_NUM, // UART physical port number + .baudrate = MB_SLAVE_DEV_SPEED, // Baud rate for communication + .parity = MB_PARITY_NONE // Parity option + }; + + ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info)); + +.. _modbus_api_slave_communication: + +Slave Communication +^^^^^^^^^^^^^^^^^^^ + +The function below is used to start Modbus controller interface and allows communication. + +:cpp:func:`mbc_slave_start` + +.. code:: c + + ESP_ERROR_CHECK(mbc_slave_start()); + +:cpp:func:`mbc_slave_check_event` + +The blocking call to function waits for a event specified (represented as an event mask parameter). Once the master accesses the parameter and the event mask matches the parameter type, the application task will be unblocked and function will return the corresponding event :cpp:type:`mb_event_group_t` which describes the type of register access being done. + +:cpp:func:`mbc_slave_get_param_info` + +The function gets information about accessed parameters from the Modbus controller event queue. The KConfig :ref:`CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE` key can be used to configure the notification queue size. The timeout parameter allows a timeout to be specified when waiting for a notification. The :cpp:type:`mb_param_info_t` structure contains information about accessed parameter. + +.. list-table:: Table 4 Description of the register info structure: :cpp:type:`mb_param_info_t` + :widths: 10 90 + :header-rows: 1 + + * - Field + - Description + * - ``time_stamp`` + - the time stamp of the event when defined parameter is accessed + * - ``mb_offset`` + - start Modbus register accessed by master + * - ``type`` + - type of the Modbus register area being accessed (See the :cpp:type:`mb_event_group_t` for more information) + * - ``address`` + - memory address that corresponds to accessed register in defined area descriptor + * - ``size`` + - number of registers being accessed by master + +Example to get event when holding or input registers accessed in the slave: + +.. code:: c + + #define MB_READ_MASK (MB_EVENT_INPUT_REG_RD | MB_EVENT_HOLDING_REG_RD) + #define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR) + #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK) + #define MB_PAR_INFO_GET_TOUT (10 / portTICK_RATE_MS) + .... + + // The function blocks while waiting for register access + mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK); + + // Get information about data accessed from master + ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + const char* rw_str = (event & MB_READ_MASK) ? "READ" : "WRITE"; + + // Filter events and process them accordingly + if (event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { + ESP_LOGI(TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + rw_str, + (uint32_t)reg_info.time_stamp, + (uint32_t)reg_info.mb_offset, + (uint32_t)reg_info.type, + (uint32_t)reg_info.address, + (uint32_t)reg_info.size); + } else if (event & (MB_EVENT_INPUT_REG_RD)) { + ESP_LOGI(TAG, "INPUT %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + rw_str, + (uint32_t)reg_info.time_stamp, + (uint32_t)reg_info.mb_offset, + (uint32_t)reg_info.type, + (uint32_t)reg_info.address, + (uint32_t)reg_info.size); + } + +.. _modbus_api_slave_destroy: + +Modbus Slave Teardown +^^^^^^^^^^^^^^^^^^^^^ + +This function stops the Modbus communication stack, destroys the controller interface, and frees all used active objects allocated for the slave. + +:cpp:func:`mbc_slave_destroy` + +.. code:: c + + ESP_ERROR_CHECK(mbc_slave_destroy()); + +Possible Communication Issues And Solutions +------------------------------------------- + +If the examples do not work as expected and slave and master boards are not able to communicate correctly, it is possible to find the reason for errors. The most important errors are described in master example output and formatted as below: + +.. highlight:: none + +:: + + E (1692332) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x107) (ESP_ERR_TIMEOUT). + + +.. list-table:: Table 5 Modbus error codes and troubleshooting + :widths: 5 30 65 + :header-rows: 1 + + * - Error + - Description + - Possible solution + * - 0x106 + - ``ESP_ERR_NOT_SUPPORTED`` - Invalid register request - slave returned an exception because the requested register is not supported. + - Refer to slave register map. Check the master data dictionary for correctness. + * - 0x107 + - ``ESP_ERR_TIMEOUT`` - Slave response timeout - Modbus slave did not send response during configured slave response timeout. + - Measure and increase the maximum slave response timeout `idf.py menuconfig`, option :ref:`CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND`. + Check physical connection or network configuration and make sure that the slave response can reach the master side. + If the application has some high performance tasks with higher priority than :ref:`CONFIG_FMB_PORT_TASK_PRIO` it is recommended to place Modbus tasks on the other core using an option :ref:`CONFIG_FMB_PORT_TASK_AFFINITY`. + Configure the Modbus task's priority :ref:`CONFIG_FMB_PORT_TASK_PRIO` to ensure that the task gets sufficient processing time to handle Modbus stack events. + * - 0x108 + - ``ESP_ERR_INVALID_RESPONSE`` - Received unsupported response from slave or frame check failure. Master can not execute command handler because the command is either not supported or is incorrect. + - Check the physical connection then refer to register map of your slave to configure the master data dictionary properly. + * - 0x103 + - ``ESP_ERR_INVALID_STATE`` - Critical failure or FSM sequence failure or master FSM is busy processing previous request. + - Make sure your physical connection is working properly. Increase task stack size and check Modbus initialization sequence. Application Example ------------------- - The examples below use the FreeModbus library port for serial TCP slave and master implementations accordingly. The selection of stack is performed through KConfig menu option "Enable Modbus stack support ..." for appropriate communication mode and related configuration keys. -:example:`protocols/modbus/serial/mb_slave` - -:example:`protocols/modbus/serial/mb_master` - -:example:`protocols/modbus/tcp/mb_tcp_slave` - -:example:`protocols/modbus/tcp/mb_tcp_master` +- :example:`protocols/modbus/serial/mb_slave` +- :example:`protocols/modbus/serial/mb_master` +- :example:`protocols/modbus/tcp/mb_tcp_slave` +- :example:`protocols/modbus/tcp/mb_tcp_master` Please refer to the specific example README.md for details. +Protocol References +------------------- + + - ``https://modbus.org/specs.php``: Modbus Organization with protocol specifications. + +API Reference +------------- + +.. include-build-file:: inc/esp_modbus_common.inc +.. include-build-file:: inc/esp_modbus_master.inc +.. include-build-file:: inc/esp_modbus_slave.inc + From 1cf61c849fa5de5d1e2600e380eec104e1f7416f Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Mon, 6 Sep 2021 09:11:17 +0800 Subject: [PATCH 128/310] docs: enable publishing of S3 docs --- .gitlab/ci/docs.yml | 9 +-------- components/esp32s3/README.md | 7 ------- docs/conf_common.py | 2 +- 3 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 components/esp32s3/README.md diff --git a/.gitlab/ci/docs.yml b/.gitlab/ci/docs.yml index ffe2c0d813..80e627d605 100644 --- a/.gitlab/ci/docs.yml +++ b/.gitlab/ci/docs.yml @@ -66,7 +66,7 @@ check_docs_lang_sync: parallel: matrix: - DOCLANG: ["en", "zh_CN"] - DOCTGT: ["esp32", "esp32s2", "esp32c3"] + DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3"] check_docs_gh_links: image: $ESP_IDF_DOC_ENV_IMAGE @@ -128,13 +128,6 @@ build_docs_html_fast: variables: DOC_BUILDERS: "html" DOCS_FAST_BUILD: "yes" - # matrix is redefined to include esp32s3 here - # that we can build for S3 MRs during bringup phase without - # anything being built and published from master branch - parallel: - matrix: - - DOCLANG: ["en", "zh_CN"] - DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3"] build_docs_pdf: extends: diff --git a/components/esp32s3/README.md b/components/esp32s3/README.md deleted file mode 100644 index d5cf8378f6..0000000000 --- a/components/esp32s3/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# ESP32-S3 component - -This directory contains support for the upcoming ESP32-S3 SoC. This code is **still work in progress and not intended for public use**. - -Please follow announcements on [espressif.com](https://www.espressif.com/) and [esp32.com](https://esp32.com/) to be informed about the ESP32-S3 SoC. - -*This note will be removed once the ESP32-S3 initial support is ready.* diff --git a/docs/conf_common.py b/docs/conf_common.py index 33328995c9..6210a9a23f 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -141,7 +141,7 @@ html_context['github_repo'] = 'esp-idf' project_slug = 'esp-idf' versions_url = 'https://dl.espressif.com/dl/esp-idf/idf_versions.js' -idf_targets = ['esp32', 'esp32s2', 'esp32c3'] +idf_targets = ['esp32', 'esp32s2', 'esp32s3', 'esp32c3'] languages = ['en', 'zh_CN'] google_analytics_id = os.environ.get('CI_GOOGLE_ANALYTICS_ID', None) From 61ac7c3368eb6a02c00e7ac9fcf7bf2cd335910f Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Mon, 6 Sep 2021 12:46:14 +0800 Subject: [PATCH 129/310] freertos: upgrade - indexed notifications --- .../freertos/include/freertos/FreeRTOS.h | 12 +- .../include/freertos/FreeRTOSConfig.h | 2 + components/freertos/include/freertos/task.h | 672 ++++++++++++++---- components/freertos/linker.lf | 2 + components/freertos/tasks.c | 405 +++++++---- 5 files changed, 794 insertions(+), 299 deletions(-) diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h index c05c125380..d354bbedb3 100644 --- a/components/freertos/include/freertos/FreeRTOS.h +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -890,6 +890,14 @@ #define configUSE_TASK_NOTIFICATIONS 1 #endif +#ifndef configTASK_NOTIFICATION_ARRAY_ENTRIES + #define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 +#endif + +#if configTASK_NOTIFICATION_ARRAY_ENTRIES < 1 + #error configTASK_NOTIFICATION_ARRAY_ENTRIES must be at least 1 +#endif + #ifndef configUSE_POSIX_ERRNO #define configUSE_POSIX_ERRNO 0 #endif @@ -1217,8 +1225,8 @@ typedef struct xSTATIC_TCB struct _reent xDummy17; #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulDummy18; - uint8_t ucDummy19; + uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + uint8_t ucDummy19[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; #endif #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) uint8_t uxDummy20; diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index c1dcd1cd48..ecc7c30aac 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -300,4 +300,6 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 + #endif /* FREERTOS_CONFIG_H */ diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 53dfe53135..5c7ce9ada0 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -60,7 +60,15 @@ #define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) #define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) +/* The direct to task notification feature used to have only a single notification + * per task. Now there is an array of notifications per task that is dimensioned by + * configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward compatibility, any use of the + * original direct to task notification defaults to using the first index in the + * array. */ +#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 ) + #define tskNO_AFFINITY ( 0x7FFFFFFF ) + /** * task. h * @@ -2111,11 +2119,23 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; /** - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. + * task. h + *

BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction );
+ *
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
* - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * Sends a direct to task notification to a task, with an optional value and + * action. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2123,28 +2143,46 @@ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was - * already in the Blocked state to wait for a notification when the notification - * arrives then the task will automatically be removed from the Blocked state - * (unblocked) and the notification cleared. - * - * A task can use xTaskNotifyWait() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTake() to [optionally] block - * to wait for its notification value to have a non-zero value. The task does + * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block + * to wait for a notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * un-indexed equivalents). If the task was already in the Blocked state to + * wait for a notification when the notification arrives then the task will + * automatically be removed from the Blocked state (unblocked) and the + * notification cleared. + * + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotify() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() + * with the uxIndexToNotify parameter set to 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does + * not have this parameter and always sends notifications to index 0. + * * @param ulValue Data that can be sent with the notification. How the data is * used depends on the value of the eAction parameter. * @@ -2152,54 +2190,96 @@ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; * value, if at all. Valid values for eAction are as follows: * * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNofify() - * always returns pdPASS in this case. + * The target notification value is bitwise ORed with ulValue. + * xTaskNofifyIndexed() always returns pdPASS in this case. * * eIncrement - - * The task's notification value is incremented. ulValue is not used and - * xTaskNotify() always returns pdPASS in this case. + * The target notification value is incremented. ulValue is not used and + * xTaskNotifyIndexed() always returns pdPASS in this case. * * eSetValueWithOverwrite - - * The task's notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification (the - * task already had a notification pending). xTaskNotify() always returns - * pdPASS in this case. + * The target notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification at the + * same array index (the task already had a notification pending at that index). + * xTaskNotifyIndexed() always returns pdPASS in this case. * * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending then - * the task's notification value is set to ulValue and xTaskNotify() will - * return pdPASS. If the task being notified already had a notification - * pending then no action is performed and pdFAIL is returned. + * If the task being notified did not already have a notification pending at the + * same array index then the target notification value is set to ulValue and + * xTaskNotifyIndexed() will return pdPASS. If the task being notified already + * had a notification pending at the same array index then no action is + * performed and pdFAIL is returned. * * eNoAction - - * The task receives a notification without its notification value being - * updated. ulValue is not used and xTaskNotify() always returns pdPASS in - * this case. + * The task receives a notification at the specified array index without the + * notification value at that index being updated. ulValue is not used and + * xTaskNotifyIndexed() always returns pdPASS in this case. * - * @param pulPreviousNotificationValue Can be used to pass out the subject - * task's notification value before any bits are modified by the notify - * function. + * pulPreviousNotificationValue - + * Can be used to pass out the subject task's notification value before any + * bits are modified by the notify function. * * @return Dependent on the value of eAction. See the description of the * eAction parameter. * + * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; -#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) -#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) +BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; +#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL ) +#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL ) /** - * Send task notification from an ISR. + * task. h + *
BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );
+ *
BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );
* - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * xTaskNotifyAndQueryIndexed() performs the same operation as + * xTaskNotifyIndexed() with the addition that it also returns the subject + * task's prior notification value (the notification value at the time the + * function is called rather than when the function returns) in the additional + * pulPreviousNotifyValue parameter. * - * A version of xTaskNotify() that can be used from an interrupt service routine - * (ISR). + * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the + * addition that it also returns the subject task's prior notification value + * (the notification value as it was at the time the function is called, rather + * than when the function returns) in the additional pulPreviousNotifyValue + * parameter. + * + * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed + * \ingroup TaskNotifications + */ +#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) +#define xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) + +/** + * task. h + *
BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ *
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * A version of xTaskNotifyIndexed() that can be used from an interrupt service + * routine (ISR). + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2207,22 +2287,40 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was - * already in the Blocked state to wait for a notification when the notification - * arrives then the task will automatically be removed from the Blocked state - * (unblocked) and the notification cleared. - * - * A task can use xTaskNotifyWait() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTake() to [optionally] block - * to wait for its notification value to have a non-zero value. The task does + * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block + * to wait for a notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * un-indexed equivalents). If the task was already in the Blocked state to + * wait for a notification when the notification arrives then the task will + * automatically be removed from the Blocked state (unblocked) and the + * notification cleared. + * + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyFromISR() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling xTaskNotifyFromISR() is equivalent to calling + * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0. + * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR() + * does not have this parameter and always sends notifications to index 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the @@ -2260,9 +2358,6 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * updated. ulValue is not used and xTaskNotify() always returns pdPASS in * this case. * - * @param pulPreviousNotificationValue Can be used to pass out the subject task's - * notification value before any bits are modified by the notify function. - * * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * task to which the notification was sent to leave the Blocked state, and the @@ -2275,20 +2370,68 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * @return Dependent on the value of eAction. See the description of the * eAction parameter. * + * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; -#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) +BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) +#define xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) /** - * Wait for task notification + * task. h + *
BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );
+ *
BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as + * xTaskNotifyIndexedFromISR() with the addition that it also returns the + * subject task's prior notification value (the notification value at the time + * the function is called rather than at the time the function returns) in the + * additional pulPreviousNotifyValue parameter. + * + * xTaskNotifyAndQueryFromISR() performs the same operation as + * xTaskNotifyFromISR() with the addition that it also returns the subject + * task's prior notification value (the notification value at the time the + * function is called rather than at the time the function returns) in the + * additional pulPreviousNotifyValue parameter. + * + * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR + * \ingroup TaskNotifications + */ +#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) +#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) + +/** + * task. h + *
+ * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ *
+ * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ * 
+ * + * Waits for a direct to task notification to be pending at a given index within + * an array of direct to task notifications. + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2296,22 +2439,41 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was - * already in the Blocked state to wait for a notification when the notification - * arrives then the task will automatically be removed from the Blocked state - * (unblocked) and the notification cleared. + * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * un-indexed equivalents). If the task was already in the Blocked state to + * wait for a notification when the notification arrives then the task will + * automatically be removed from the Blocked state (unblocked) and the + * notification cleared. * - * A task can use xTaskNotifyWait() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTake() to [optionally] block - * to wait for its notification value to have a non-zero value. The task does + * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block + * to wait for a notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyWait() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling xTaskNotifyWait() is equivalent to calling + * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0. + * + * @param uxIndexToWaitOn The index within the calling task's array of + * notification values on which the calling task will wait for a notification to + * be received. uxIndexToWaitOn must be less than + * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does + * not have this parameter and always waits for notifications on index 0. * * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value * will be cleared in the calling task's notification value before the task @@ -2342,7 +2504,7 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal * the Blocked state for a notification to be received, should a notification * not already be pending when xTaskNotifyWait() was called. The task * will not consume any processing time while it is in the Blocked state. This - * is specified in kernel ticks, the macro pdMS_TO_TICKS( value_in_ms ) can be + * is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be * used to convert a time specified in milliseconds to a time specified in * ticks. * @@ -2350,18 +2512,37 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal * already pending when xTaskNotifyWait was called) then pdPASS is * returned. Otherwise pdFAIL is returned. * + * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed * \ingroup TaskNotifications */ -BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, + uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#define xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ + xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) ) +#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ + xTaskGenericNotifyWait( ( uxIndexToWaitOn ), ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) ) /** - * Simplified macro for sending task notification. + * task. h + *
BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify );
+ *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
* - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro - * to be available. + * Sends a direct to task notification to a particular index in the target + * task's notification array in a manner similar to giving a counting semaphore. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * macros to be available. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2369,46 +2550,74 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * xTaskNotifyGive() is a helper macro intended for use when task notifications - * are used as light weight and faster binary or counting semaphore equivalents. - * Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, - * the equivalent action that instead uses a task notification is - * xTaskNotifyGive(). + * xTaskNotifyGiveIndexed() is a helper macro intended for use when task + * notifications are used as light weight and faster binary or counting + * semaphore equivalents. Actual FreeRTOS semaphores are given using the + * xSemaphoreGive() API function, the equivalent action that instead uses a task + * notification is xTaskNotifyGiveIndexed(). * * When task notifications are being used as a binary or counting semaphore * equivalent then the task being notified should wait for the notification - * using the ulTaskNotificationTake() API function rather than the - * xTaskNotifyWait() API function. + * using the ulTaskNotificationTakeIndexed() API function rather than the + * xTaskNotifyWaitIndexed() API function. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyGive() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling xTaskNotifyGive() is equivalent to calling + * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() + * does not have this parameter and always sends notifications to index 0. + * * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the * eAction parameter set to eIncrement - so pdPASS is always returned. * + * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed * \ingroup TaskNotifications */ -#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL ) +#define xTaskNotifyGive( xTaskToNotify ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( 0 ), eIncrement, NULL ) +#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( 0 ), eIncrement, NULL ) /** - * Simplified macro for sending task notification from ISR. + * task. h + *
void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken );
+ *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt + * service routine (ISR). + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. * * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro * to be available. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). - * - * A version of xTaskNotifyGive() that can be called from an interrupt service - * routine (ISR). + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2416,28 +2625,46 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * vTaskNotifyGiveFromISR() is intended for use when task notifications are - * used as light weight and faster binary or counting semaphore equivalents. + * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications + * are used as light weight and faster binary or counting semaphore equivalents. * Actual FreeRTOS semaphores are given from an ISR using the * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses - * a task notification is vTaskNotifyGiveFromISR(). + * a task notification is vTaskNotifyGiveIndexedFromISR(). * * When task notifications are being used as a binary or counting semaphore * equivalent then the task being notified should wait for the notification - * using the ulTaskNotificationTake() API function rather than the - * xTaskNotifyWait() API function. + * using the ulTaskNotificationTakeIndexed() API function rather than the + * xTaskNotifyWaitIndexed() API function. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyFromISR() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling + * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. + * xTaskNotifyGiveFromISR() does not have this parameter and always sends + * notifications to index 0. + * * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * task to which the notification was sent to leave the Blocked state, and the @@ -2447,18 +2674,38 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * requested from an ISR is dependent on the port - see the documentation page * for the port in use. * + * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR * \ingroup TaskNotifications */ -void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ + vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) ); +#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) \ + vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) ); /** - * Simplified macro for receiving task notification. + * task. h + *
+ * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ *
+ * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * 
+ * + * Waits for a direct to task notification on a particular index in the calling + * task's notification array in a manner similar to taking a counting semaphore. + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2466,35 +2713,54 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * ulTaskNotifyTake() is intended for use when a task notification is used as a - * faster and lighter weight binary or counting semaphore alternative. Actual - * FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the - * equivalent action that instead uses a task notification is - * ulTaskNotifyTake(). + * ulTaskNotifyTakeIndexed() is intended for use when a task notification is + * used as a faster and lighter weight binary or counting semaphore alternative. + * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function, + * the equivalent action that instead uses a task notification is + * ulTaskNotifyTakeIndexed(). * * When a task is using its notification value as a binary or counting semaphore - * other tasks should send notifications to it using the xTaskNotifyGive() - * macro, or xTaskNotify() function with the eAction parameter set to + * other tasks should send notifications to it using the xTaskNotifyGiveIndexed() + * macro, or xTaskNotifyIndex() function with the eAction parameter set to * eIncrement. * - * ulTaskNotifyTake() can either clear the task's notification value to - * zero on exit, in which case the notification value acts like a binary - * semaphore, or decrement the task's notification value on exit, in which case - * the notification value acts like a counting semaphore. + * ulTaskNotifyTakeIndexed() can either clear the task's notification value at + * the array index specified by the uxIndexToWaitOn parameter to zero on exit, + * in which case the notification value acts like a binary semaphore, or + * decrement the notification value on exit, in which case the notification + * value acts like a counting semaphore. * - * A task can use ulTaskNotifyTake() to [optionally] block to wait for a + * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for * the task's notification value to be non-zero. The task does not consume any * CPU time while it is in the Blocked state. * - * Where as xTaskNotifyWait() will return when a notification is pending, - * ulTaskNotifyTake() will return when the task's notification value is + * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, + * ulTaskNotifyTakeIndexed() will return when the task's notification value is * not zero. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. ulTaskNotifyTake() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling ulTaskNotifyTake() is equivalent to calling + * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0. + * + * @param uxIndexToWaitOn The index within the calling task's array of + * notification values on which the calling task will wait for a notification to + * be non-zero. uxIndexToWaitOn must be less than + * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does + * not have this parameter and always waits for notifications on index 0. * * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's * notification value is decremented when the function exits. In this way the @@ -2508,29 +2774,153 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri * should the count not already be greater than zero when * ulTaskNotifyTake() was called. The task will not consume any processing * time while it is in the Blocked state. This is specified in kernel ticks, - * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time + * the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time * specified in milliseconds to a time specified in ticks. * * @return The task's notification count before it is either cleared to zero or * decremented (see the xClearCountOnExit parameter). * + * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed * \ingroup TaskNotifications */ -uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, + BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \ + ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), ( xClearCountOnExit ), ( xTicksToWait ) ) +#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) \ + ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), ( xClearCountOnExit ), ( xTicksToWait ) ) /** + * task. h + *
+ * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear );
  *
- * If the notification state of the task referenced by the handle xTask is
- * eNotified, then set the task's notification state to eNotWaitingNotification.
- * The task's notification value is not altered.  Set xTask to NULL to clear the
- * notification state of the calling task.
+ * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
+ * 
+ * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. + * + * If a notification is sent to an index within the array of notifications then + * the notification at that index is said to be 'pending' until it is read or + * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() + * is the function that clears a pending notification without reading the + * notification value. The notification value at the same array index is not + * altered. Set xTask to NULL to clear the notification state of the calling + * task. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyStateClear() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling xTaskNotifyStateClear() is equivalent to calling + * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0. + * + * @param xTask The handle of the RTOS task that will have a notification state + * cleared. Set xTask to NULL to clear a notification state in the calling + * task. To obtain a task's handle create the task using xTaskCreate() and + * make use of the pxCreatedTask parameter, or create the task using + * xTaskCreateStatic() and store the returned value, or use the task's name in + * a call to xTaskGetHandle(). + * + * @param uxIndexToClear The index within the target task's array of + * notification values to act upon. For example, setting uxIndexToClear to 1 + * will clear the state of the notification at index 1 within the array. + * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. + * ulTaskNotifyStateClear() does not have this parameter and always acts on the + * notification at index 0. * * @return pdTRUE if the task's notification state was set to * eNotWaitingNotification, otherwise pdFALSE. * + * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed * \ingroup TaskNotifications */ -BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); +BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear ) PRIVILEGED_FUNCTION; +#define xTaskNotifyStateClear( xTask ) \ + xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) +#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ + xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) ) + +/** + * task. h + *
+ * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear );
+ *
+ * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear );
+ * 
+ * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. + * + * ulTaskNotifyValueClearIndexed() clears the bits specified by the + * ulBitsToClear bit mask in the notification value at array index uxIndexToClear + * of the task referenced by xTask. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. ulTaskNotifyValueClear() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling + * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0. + * + * @param xTask The handle of the RTOS task that will have bits in one of its + * notification values cleared. Set xTask to NULL to clear bits in a + * notification value of the calling task. To obtain a task's handle create the + * task using xTaskCreate() and make use of the pxCreatedTask parameter, or + * create the task using xTaskCreateStatic() and store the returned value, or + * use the task's name in a call to xTaskGetHandle(). + * + * @param uxIndexToClear The index within the target task's array of + * notification values in which to clear the bits. uxIndexToClear + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. + * ulTaskNotifyValueClear() does not have this parameter and always clears bits + * in the notification value at index 0. + * + * @param ulBitsToClear Bit mask of the bits to clear in the notification value of + * xTask. Set a bit to 1 to clear the corresponding bits in the task's notification + * value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit architectures) to clear + * the notification value to 0. Set ulBitsToClear to 0 to query the task's + * notification value without clearing any bits. + * + * + * @return The value of the target task's notification value before the bits + * specified by ulBitsToClear were cleared. + * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear + * \ingroup TaskNotifications + */ +uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear, + uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; +#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \ + ulTaskGenericNotifyValueClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulBitsToClear ) ) +#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \ + ulTaskGenericNotifyValueClear( ( xTask ), ( uxIndexToClear ), ( ulBitsToClear ) ) + /*----------------------------------------------------------- * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index bb8d397ae3..a9aeec7d6b 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -40,7 +40,9 @@ entries: tasks: xTaskResumeAll (default) tasks: uxTaskResetEventItemValue (default) tasks: ulTaskNotifyTake (default) + tasks: ulTaskGenericNotifyTake (default) tasks: xTaskNotifyWait (default) + tasks: xTaskGenericNotifyWait (default) tasks: xTaskGenericNotify (default) tasks: eTaskGetState (default) tasks: pxTaskGetStackStart (default) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 872a586421..e91616233e 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -333,8 +333,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - volatile uint32_t ulNotifiedValue; - volatile uint8_t ucNotifyState; + volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; #endif /* See the comments in FreeRTOS.h with the definition of @@ -1090,8 +1090,8 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, #if ( configUSE_TASK_NOTIFICATIONS == 1 ) { - pxNewTCB->ulNotifiedValue = 0; - pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) ); + memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) ); } #endif @@ -1630,19 +1630,24 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * indefinitely? */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) { - #if( configUSE_TASK_NOTIFICATIONS == 1 ) + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) { + BaseType_t x; + /* The task does not appear on the event list item of * and of the RTOS objects, but could still be in the * blocked state if it is waiting on its notification - * rather than waiting on an object. */ - if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ) + * rather than waiting on an object. If not, is + * suspended. */ + eReturn = eSuspended; + + for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) { - eReturn = eBlocked; - } - else - { - eReturn = eSuspended; + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) + { + eReturn = eBlocked; + break; + } } } #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ @@ -1972,16 +1977,21 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); curTCB = pxCurrentTCB[ xPortGetCoreID() ]; - #if( configUSE_TASK_NOTIFICATIONS == 1 ) + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) { - if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ) + BaseType_t x; + + for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) { - /* The task was blocked to wait for a notification, but is - * now suspended, so no notification was received. */ - pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) + { + /* The task was blocked to wait for a notification, but is + * now suspended, so no notification was received. */ + pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION; + } } } - #endif + #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ } taskEXIT_CRITICAL(); @@ -5241,19 +5251,33 @@ TickType_t uxTaskResetEventItemValue( void ) #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) +#ifdef ESP_PLATFORM // IDF-3851 + // included here for backward binary compatibility + #undef ulTaskNotifyTake + uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) { - uint32_t ulReturn; + return ulTaskGenericNotifyTake(tskDEFAULT_INDEX_TO_NOTIFY, xClearCountOnExit, xTicksToWait); + } +#endif // ESP-PLATFORM + + uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait, + BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) + { + uint32_t ulReturn; + + configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); taskENTER_CRITICAL(); { /* Only block if the notification count is not already non-zero. */ - if( pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue == 0UL ) + if( pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] == 0UL ) { /* Mark this task as waiting for a notification. */ - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { @@ -5261,9 +5285,9 @@ TickType_t uxTaskResetEventItemValue( void ) traceTASK_NOTIFY_TAKE_BLOCK(); /* All ports are written to allow a yield in a critical - section (some will yield immediately, others wait until the - critical section exits) - but it is not something that - application code should ever do. */ + * section (some will yield immediately, others wait until the + * critical section exits) - but it is not something that + * application code should ever do. */ portYIELD_WITHIN_API(); } else @@ -5281,17 +5305,17 @@ TickType_t uxTaskResetEventItemValue( void ) taskENTER_CRITICAL(); { traceTASK_NOTIFY_TAKE(); - ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; + ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ]; if( ulReturn != 0UL ) { if( xClearCountOnExit != pdFALSE ) { - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = 0UL; + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = 0UL; } else { - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = ulReturn - ( uint32_t ) 1; + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1; } } else @@ -5299,7 +5323,7 @@ TickType_t uxTaskResetEventItemValue( void ) mtCOVERAGE_TEST_MARKER(); } - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); @@ -5309,24 +5333,41 @@ TickType_t uxTaskResetEventItemValue( void ) #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) +#ifdef ESP_PLATFORM // IDF-3851 + // included for backward compatibility + #undef xTaskNotifyWait + BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) { - BaseType_t xReturn; + return xTaskGenericNotifyWait(tskDEFAULT_INDEX_TO_NOTIFY, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait); + } +#endif // ESP-PLATFORM + BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait, + uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) + { + BaseType_t xReturn; + + configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); taskENTER_CRITICAL(); { /* Only block if a notification is not already pending. */ - if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) + if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) { /* Clear bits in the task's notification value as bits may get - set by the notifying task or interrupt. This can be used to - clear the value to zero. */ - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnEntry; + * set by the notifying task or interrupt. This can be used to + * clear the value to zero. */ + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; /* Mark this task as waiting for a notification. */ - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { @@ -5334,9 +5375,9 @@ TickType_t uxTaskResetEventItemValue( void ) traceTASK_NOTIFY_WAIT_BLOCK(); /* All ports are written to allow a yield in a critical - section (some will yield immediately, others wait until the - critical section exits) - but it is not something that - application code should ever do. */ + * section (some will yield immediately, others wait until the + * critical section exits) - but it is not something that + * application code should ever do. */ portYIELD_WITHIN_API(); } else @@ -5358,15 +5399,15 @@ TickType_t uxTaskResetEventItemValue( void ) if( pulNotificationValue != NULL ) { /* Output the current notification value, which may or may not - have changed. */ - *pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; + * have changed. */ + *pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ]; } /* If ucNotifyValue is set then either the task never entered the - blocked state (because a notification was already pending) or the - task unblocked because of a notification. Otherwise the task - unblocked because of a timeout. */ - if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) + * blocked state (because a notification was already pending) or the + * task unblocked because of a notification. Otherwise the task + * unblocked because of a timeout. */ + if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) { /* A notification was not received. */ xReturn = pdFALSE; @@ -5374,12 +5415,12 @@ TickType_t uxTaskResetEventItemValue( void ) else { /* A notification was already pending or a notification was - received while the task was waiting. */ - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnExit; + * received while the task was waiting. */ + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit; xReturn = pdTRUE; } - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); @@ -5389,14 +5430,19 @@ TickType_t uxTaskResetEventItemValue( void ) #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) + BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue ) { - TCB_t * pxTCB; - BaseType_t xReturn = pdPASS; - uint8_t ucOriginalNotifyState; + TCB_t * pxTCB; + BaseType_t xReturn = pdPASS; + uint8_t ucOriginalNotifyState; + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); configASSERT( xTaskToNotify ); pxTCB = xTaskToNotify; @@ -5404,49 +5450,53 @@ TickType_t uxTaskResetEventItemValue( void ) { if( pulPreviousNotificationValue != NULL ) { - *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ]; } - ucOriginalNotifyState = pxTCB->ucNotifyState; + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; switch( eAction ) { - case eSetBits : - pxTCB->ulNotifiedValue |= ulValue; + case eSetBits: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue; break; - case eIncrement : - ( pxTCB->ulNotifiedValue )++; + case eIncrement: + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; break; - case eSetValueWithOverwrite : - pxTCB->ulNotifiedValue = ulValue; + case eSetValueWithOverwrite: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; break; - case eSetValueWithoutOverwrite : + case eSetValueWithoutOverwrite: + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { - pxTCB->ulNotifiedValue = ulValue; + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; } else { /* The value could not be written to the task. */ xReturn = pdFAIL; } + break; case eNoAction: + /* The task is being notified without its notify value being - updated. */ + * updated. */ break; default: + /* Should not get here if all enums are handled. - Artificially force an assert by testing a value the - compiler can't assume is const. */ - configASSERT( pxTCB->ulNotifiedValue == ~0UL ); + * Artificially force an assert by testing a value the + * compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL ); break; } @@ -5454,7 +5504,7 @@ TickType_t uxTaskResetEventItemValue( void ) traceTASK_NOTIFY(); /* If the task is in the blocked state specifically to wait for a - notification then unblock it now. */ + * notification then unblock it now. */ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); @@ -5463,20 +5513,20 @@ TickType_t uxTaskResetEventItemValue( void ) /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); - #if( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked waiting for a notification then - xNextTaskUnblockTime might be set to the blocked task's time - out time. If the task is unblocked for a reason other than - a timeout xNextTaskUnblockTime is normally left unchanged, - because it will automatically get reset to a new value when - the tick count equals xNextTaskUnblockTime. However if - tickless idling is used it might be more important to enter - sleep mode at the earliest possible time - so reset - xNextTaskUnblockTime here to ensure it is updated at the - earliest possible time. */ - prvResetNextTaskUnblockTime(); - } + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked waiting for a notification then + * xNextTaskUnblockTime might be set to the blocked task's time + * out time. If the task is unblocked for a reason other than + * a timeout xNextTaskUnblockTime is normally left unchanged, + * because it will automatically get reset to a new value when + * the tick count equals xNextTaskUnblockTime. However if + * tickless idling is used it might be more important to enter + * sleep mode at the earliest possible time - so reset + * xNextTaskUnblockTime here to ensure it is updated at the + * earliest possible time. */ + prvResetNextTaskUnblockTime(); + } #endif if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) @@ -5507,32 +5557,38 @@ TickType_t uxTaskResetEventItemValue( void ) #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) + BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue, + BaseType_t * pxHigherPriorityTaskWoken ) { - TCB_t * pxTCB; - uint8_t ucOriginalNotifyState; - BaseType_t xReturn = pdPASS; + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; + BaseType_t xReturn = pdPASS; configASSERT( xTaskToNotify ); + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); pxTCB = xTaskToNotify; @@ -5541,55 +5597,59 @@ TickType_t uxTaskResetEventItemValue( void ) { if( pulPreviousNotificationValue != NULL ) { - *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ]; } - ucOriginalNotifyState = pxTCB->ucNotifyState; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; switch( eAction ) { - case eSetBits : - pxTCB->ulNotifiedValue |= ulValue; + case eSetBits: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue; break; - case eIncrement : - ( pxTCB->ulNotifiedValue )++; + case eIncrement: + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; break; - case eSetValueWithOverwrite : - pxTCB->ulNotifiedValue = ulValue; + case eSetValueWithOverwrite: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; break; - case eSetValueWithoutOverwrite : + case eSetValueWithoutOverwrite: + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { - pxTCB->ulNotifiedValue = ulValue; + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; } else { /* The value could not be written to the task. */ xReturn = pdFAIL; } + break; - case eNoAction : + case eNoAction: + /* The task is being notified without its notify value being - updated. */ + * updated. */ break; default: + /* Should not get here if all enums are handled. - Artificially force an assert by testing a value the - compiler can't assume is const. */ - configASSERT( pxTCB->ulNotifiedValue == ~0UL ); + * Artificially force an assert by testing a value the + * compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL ); break; } traceTASK_NOTIFY_FROM_ISR(); /* If the task is in the blocked state specifically to wait for a - notification then unblock it now. */ + * notification then unblock it now. */ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { /* The task should not have been on an event list. */ @@ -5603,14 +5663,14 @@ TickType_t uxTaskResetEventItemValue( void ) else { /* The delayed and ready lists cannot be accessed, so hold - this task pending until the scheduler is resumed. */ + * this task pending until the scheduler is resumed. */ vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); } if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* The notified task has a priority above the currently - executing task so a yield is required. */ + * executing task so a yield is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; @@ -5637,47 +5697,50 @@ TickType_t uxTaskResetEventItemValue( void ) #if( configUSE_TASK_NOTIFICATIONS == 1 ) - void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) + void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + BaseType_t * pxHigherPriorityTaskWoken ) { TCB_t * pxTCB; uint8_t ucOriginalNotifyState; configASSERT( xTaskToNotify ); + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); pxTCB = xTaskToNotify; taskENTER_CRITICAL_ISR(); { - ucOriginalNotifyState = pxTCB->ucNotifyState; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; /* 'Giving' is equivalent to incrementing a count in a counting - semaphore. */ - ( pxTCB->ulNotifiedValue )++; + * semaphore. */ + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; traceTASK_NOTIFY_GIVE_FROM_ISR(); /* If the task is in the blocked state specifically to wait for a - notification then unblock it now. */ + * notification then unblock it now. */ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { /* The task should not have been on an event list. */ @@ -5691,7 +5754,7 @@ TickType_t uxTaskResetEventItemValue( void ) else { /* The delayed and ready lists cannot be accessed, so hold - this task pending until the scheduler is resumed. */ + * this task pending until the scheduler is resumed. */ vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); } @@ -5699,7 +5762,7 @@ TickType_t uxTaskResetEventItemValue( void ) if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* The notified task has a priority above the currently - executing task so a yield is required. */ + * executing task so a yield is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; @@ -5720,25 +5783,27 @@ TickType_t uxTaskResetEventItemValue( void ) } #endif /* configUSE_TASK_NOTIFICATIONS */ - /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ) + BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear ) { - TCB_t *pxTCB; - BaseType_t xReturn; + TCB_t * pxTCB; + BaseType_t xReturn; + + configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES ); /* If null is passed in here then it is the calling task that is having - its notification state cleared. */ + * its notification state cleared. */ pxTCB = prvGetTCBFromHandle( xTask ); taskENTER_CRITICAL(); { - if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) + if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED ) { - pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION; xReturn = pdPASS; } else @@ -5754,7 +5819,35 @@ TickType_t uxTaskResetEventItemValue( void ) #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) + + uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear, + uint32_t ulBitsToClear ) + { + TCB_t * pxTCB; + uint32_t ulReturn; + + /* If null is passed in here then it is the calling task that is having + * its notification state cleared. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + taskENTER_CRITICAL(); + { + /* Return the notification as it was before the bits were cleared, + * then clear the bit mask. */ + ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ]; + pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear; + } + taskEXIT_CRITICAL(); + + return ulReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) uint32_t ulTaskGetIdleRunTimeCounter( void ) { From fa2707f1f3dbadbc23658928fc4a6c1e82d1b0ab Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Tue, 31 Aug 2021 14:32:53 +0530 Subject: [PATCH 130/310] hmac: Added Downstream JTAG enable mode for esp32c3 and esp32s3 If JTAG is disabled temporarily by burning SOFT_DIS_JTAG, it can be re-enabled temporarily through esp_hmac_jtag_enable API --- .../include/soc/esp32c3/esp_hmac.h | 29 ++++++++++ .../include/soc/esp32s3/esp_hmac.h | 29 ++++++++++ .../esp_hw_support/port/esp32c3/esp_hmac.c | 56 ++++++++++++++++++ .../esp_hw_support/port/esp32s3/esp_hmac.c | 57 +++++++++++++++++++ components/esp_hw_support/test/test_hmac.c | 48 ++++------------ .../soc/esp32c3/include/soc/hwcrypto_reg.h | 1 + .../soc/esp32s3/include/soc/hwcrypto_reg.h | 4 ++ 7 files changed, 186 insertions(+), 38 deletions(-) diff --git a/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h b/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h index cea11ee1ba..26e2bc71a0 100644 --- a/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h @@ -52,6 +52,35 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, size_t message_len, uint8_t *hmac); +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h b/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h index 8f8677e38c..101dce556b 100644 --- a/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h @@ -50,6 +50,35 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, size_t message_len, uint8_t *hmac); +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32c3/esp_hmac.c b/components/esp_hw_support/port/esp32c3/esp_hmac.c index 4c6daeac6b..0c85d7429c 100644 --- a/components/esp_hw_support/port/esp32c3/esp_hmac.c +++ b/components/esp_hw_support/port/esp32c3/esp_hmac.c @@ -8,14 +8,20 @@ #include "driver/periph_ctrl.h" #include "esp32c3/rom/hmac.h" #include "esp32c3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_hmac.h" +#include "esp_log.h" #include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" #include "hal/hmac_hal.h" #define SHA256_BLOCK_SZ 64 #define SHA256_PAD_SZ 8 +static const char *TAG = "esp_hmac"; + /** * @brief Apply the HMAC padding without the embedded length. * @@ -122,3 +128,53 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, return ESP_OK; } + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32s3/esp_hmac.c b/components/esp_hw_support/port/esp32s3/esp_hmac.c index 54ec775625..73c3193a8d 100644 --- a/components/esp_hw_support/port/esp32s3/esp_hmac.c +++ b/components/esp_hw_support/port/esp32s3/esp_hmac.c @@ -6,16 +6,23 @@ #include #include "driver/periph_ctrl.h" +#include "esp32s3/rom/efuse.h" #include "esp32s3/rom/hmac.h" #include "esp32s3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_hmac.h" +#include "esp_log.h" #include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" #include "hal/hmac_hal.h" #define SHA256_BLOCK_SZ 64 #define SHA256_PAD_SZ 8 +static const char *TAG = "esp_hmac"; + /** * @brief Apply the HMAC padding without the embedded length. * @@ -122,3 +129,53 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, return ESP_OK; } + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/esp_hw_support/test/test_hmac.c b/components/esp_hw_support/test/test_hmac.c index fee1f8d4f6..cf49bc19e3 100644 --- a/components/esp_hw_support/test/test_hmac.c +++ b/components/esp_hw_support/test/test_hmac.c @@ -21,16 +21,12 @@ typedef struct { uint8_t result[32]; } hmac_result; -static const esp_efuse_block_t key_block = EFUSE_BLK_KEY0; - -static void setup_keyblock(void) { +static void setup_keyblock(esp_efuse_block_t key_block, esp_efuse_purpose_t purpose) { const uint8_t key_data[32] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32 }; - esp_err_t status = esp_efuse_write_key(key_block, - ESP_EFUSE_KEY_PURPOSE_HMAC_UP, - key_data, sizeof(key_data)); + esp_err_t status = esp_efuse_write_key(key_block, purpose, key_data, sizeof(key_data)); if (status == ESP_OK) { printf("Written key!\n"); @@ -41,17 +37,11 @@ static void setup_keyblock(void) { } } -#if !CONFIG_IDF_TARGET_ESP32S3 // TODO: IDF-3664: S3 JTAG enable hasn't been implemented yet -#include "esp32s2/rom/efuse.h" -static const char *TAG = "test_hmac"; TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]") { int ets_status; - const uint8_t key_data[32] = { - 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31,32 - }; + setup_keyblock(EFUSE_BLK_KEY3, ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG); // Results calculated with Python: // @@ -63,31 +53,13 @@ TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]") 0x8e, 0x6c, 0x3e, 0x8e, 0x6e, 0x17, 0x62, 0x5c, 0x50, 0xac, 0x66, 0xa9, 0xa8, 0x57, 0x94, 0x9b }; - ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY3, - ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG, - key_data, sizeof(key_data)); - - if (ets_status == ESP_OK) { - ESP_LOGI(TAG, "HMAC_DOWN_JTAG key programmed!"); - } else { - ESP_LOGW(TAG, "HMAC_DOWN_JTAG key programming failed, \ - maybe written already. Continuing"); - } - TEST_ASSERT_MESSAGE(ESP_OK == esp_efuse_batch_write_begin(), "Error programming security efuse.\n"); - ets_status = esp_efuse_set_read_protect(ETS_EFUSE_BLOCK_KEY3); - if (ets_status != ESP_OK) { - ESP_LOGW(TAG, "EFUSE_BLOCK read protect setting failed. \ - Not a must prerequisite to run this test case. Continuing"); - } + ets_status = esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count); - ets_status = esp_efuse_write_field_bit(ESP_EFUSE_SOFT_DIS_JTAG); - if (ets_status != ESP_OK) { - ESP_LOGI(TAG, "JTAG Disable temporarily failed. \ - May be disabled already. Continuing the test."); - } + TEST_ASSERT_MESSAGE(ets_status == ESP_OK || ets_status == ESP_ERR_EFUSE_CNT_IS_FULL, + "JTAG Disable temporarily failed.\n"); TEST_ASSERT_MESSAGE(ESP_OK == esp_efuse_batch_write_commit(), "Error programming security efuse.\n"); @@ -101,13 +73,12 @@ TEST_CASE("HMAC 'downstream' JTAG Disable", "[hw_crypto]") TEST_ASSERT_EQUAL_HEX32_MESSAGE(ESP_OK, esp_hmac_jtag_disable(), "JTAG should be disabled now, please manually verify"); } -#endif TEST_CASE("HMAC 'upstream' MAC generation with zeroes", "[hw_crypto]") { uint8_t hmac[32]; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); const uint8_t zeroes[128] = { }; // Produce the HMAC of various numbers of zeroes @@ -202,7 +173,7 @@ TEST_CASE("HMAC 'upstream' MAC generation from data", "[hw_crypto]") { uint8_t hmac[32]; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); // 257 characters of pseudo-Latin from lipsum.com (not Copyright) const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque.."; @@ -1002,7 +973,8 @@ TEST_CASE("HMAC 'upstream' wait lock", "[hw_crypto]") // 257 characters of pseudo-Latin from lipsum.com (not Copyright) const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque.."; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); + static const hmac_result results[] = { { .msglen = 255, .result = { 0x59, 0x52, 0x50, 0x4, 0xb6, 0x28, 0xf9, 0x28, 0x7f, 0x6c, 0x37, 0xba, 0xfb, 0xb2, 0x58, 0xe7, 0xa, 0xac, 0x6c, 0x4a, 0xef, 0x66, 0x6, 0x7b, 0x1, 0x1f, 0x4c, 0xa4, 0xe5, 0xe5, 0x29, 0x5d }, diff --git a/components/soc/esp32c3/include/soc/hwcrypto_reg.h b/components/soc/esp32c3/include/soc/hwcrypto_reg.h index 6844627388..474b07faa3 100644 --- a/components/soc/esp32c3/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32c3/include/soc/hwcrypto_reg.h @@ -133,6 +133,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) diff --git a/components/soc/esp32s3/include/soc/hwcrypto_reg.h b/components/soc/esp32s3/include/soc/hwcrypto_reg.h index 09011285fd..a4b93fb81b 100644 --- a/components/soc/esp32s3/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32s3/include/soc/hwcrypto_reg.h @@ -99,6 +99,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) @@ -107,6 +108,9 @@ #define HMAC_RDATA_BASE ((DR_REG_HMAC_BASE) + 0xC0) #define HMAC_SET_MESSAGE_PAD_REG ((DR_REG_HMAC_BASE) + 0xF0) #define HMAC_ONE_BLOCK_REG ((DR_REG_HMAC_BASE) + 0xF4) +#define HMAC_SOFT_JTAG_CTRL_REG ((DR_REG_HMAC_BASE) + 0xF8) +#define HMAC_SOFT_JTAG_CTRL BIT((0) +#define HMAC_WR_JTAG_REG ((DR_REG_HMAC_BASE) + 0xFC) /* AES-XTS registers */ #define AES_XTS_PLAIN_BASE ((DR_REG_EXT_MEM_ENC) + 0x00) From fd5a7df404cbda926a79a0af1ff9797bdca1da7f Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Fri, 3 Sep 2021 17:07:26 +0530 Subject: [PATCH 131/310] esp32h2: Replicated HMAC JTAG downstream enable mode implementation --- .../include/soc/esp32h2/esp_hmac.h | 29 +++++++++ .../esp_hw_support/port/esp32h2/esp_hmac.c | 60 ++++++++++++++++++- .../soc/esp32h2/include/soc/hwcrypto_reg.h | 1 + 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h b/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h index cea11ee1ba..26e2bc71a0 100644 --- a/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h @@ -52,6 +52,35 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, size_t message_len, uint8_t *hmac); +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32h2/esp_hmac.c b/components/esp_hw_support/port/esp32h2/esp_hmac.c index d655dbf9d3..84340d8164 100644 --- a/components/esp_hw_support/port/esp32h2/esp_hmac.c +++ b/components/esp_hw_support/port/esp32h2/esp_hmac.c @@ -6,16 +6,22 @@ #include #include "driver/periph_ctrl.h" -#include "esp32h2/rom/hmac.h" -#include "esp32h2/rom/ets_sys.h" +#include "esp32c3/rom/hmac.h" +#include "esp32c3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_hmac.h" +#include "esp_log.h" #include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" #include "hal/hmac_hal.h" #define SHA256_BLOCK_SZ 64 #define SHA256_PAD_SZ 8 +static const char *TAG = "esp_hmac"; + /** * @brief Apply the HMAC padding without the embedded length. * @@ -122,3 +128,53 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, return ESP_OK; } + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/soc/esp32h2/include/soc/hwcrypto_reg.h b/components/soc/esp32h2/include/soc/hwcrypto_reg.h index 6844627388..474b07faa3 100644 --- a/components/soc/esp32h2/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32h2/include/soc/hwcrypto_reg.h @@ -133,6 +133,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) From 667017d517695e5923ecaccba98b8702fecf5863 Mon Sep 17 00:00:00 2001 From: Sachin Billore Date: Fri, 27 Aug 2021 21:28:02 +0530 Subject: [PATCH 132/310] ESP32S3 support for ESP-MQTT SSL Mutual Authentication with Digital Signature Closes IDF-3859 --- components/esp-tls/Kconfig | 3 ++- components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c | 2 ++ examples/protocols/mqtt/ssl_ds/README.md | 10 +++++----- examples/protocols/mqtt/ssl_ds/configure_ds.py | 6 +++--- examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig index fe38ea79f7..8dbaae4001 100644 --- a/components/esp-tls/Kconfig +++ b/components/esp-tls/Kconfig @@ -26,7 +26,8 @@ menu "ESP-TLS" config ESP_TLS_USE_DS_PERIPHERAL bool "Use Digital Signature (DS) Peripheral with ESP-TLS" - depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2) && ESP_TLS_USING_MBEDTLS + depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32S3) + depends on ESP_TLS_USING_MBEDTLS default y help Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral diff --git a/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c b/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c index a01134fae0..b0914cf01e 100644 --- a/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c +++ b/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c @@ -21,6 +21,8 @@ #include "esp32c3/rom/digital_signature.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/digital_signature.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/digital_signature.h" #else #error "Selected target does not support esp_rsa_sign_alt (for DS)" #endif diff --git a/examples/protocols/mqtt/ssl_ds/README.md b/examples/protocols/mqtt/ssl_ds/README.md index 20a06d09a7..b186469035 100644 --- a/examples/protocols/mqtt/ssl_ds/README.md +++ b/examples/protocols/mqtt/ssl_ds/README.md @@ -1,8 +1,8 @@ -| Supported Targets | ESP32-S2 | ESP32-C3 | +| Supported Targets | ESP32-S2 | ESP32-C3 | ESP32-S3 | # ESP-MQTT SSL Mutual Authentication with Digital Signature (See the README.md file in the upper level 'examples' directory for more information about examples.) -Espressif's ESP32-S2 and ESP32-C3 MCU have a built-in Digital Signature (DS) Peripheral, which provides hardware acceleration for RSA signature. More details can be found at [Digital Signature with ESP-TLS](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/protocols/esp_tls.html#digital-signature-with-esp-tls). +Espressif's ESP32-S2, ESP32-S3 and ESP32-C3 MCU have a built-in Digital Signature (DS) Peripheral, which provides hardware acceleration for RSA signature. More details can be found at [Digital Signature with ESP-TLS](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/protocols/esp_tls.html#digital-signature-with-esp-tls). This example connects to the broker test.mosquitto.org using ssl transport with client certificate(RSA) and as a demonstration subscribes/unsubscribes and sends a message on certain topic.The RSA signature operation required in the ssl connection is performed with help of the Digital Signature (DS) peripheral. (Please note that the public broker is maintained by the community so may not be always available, for details please visit http://test.mosquitto.org) @@ -12,12 +12,12 @@ It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. ### Hardware Required -This example can be executed on any ESP32-S2, ESP32-C3 board (which has a built-in DS peripheral), the only required interface is WiFi and connection to internet. +This example can be executed on any ESP32-S2, ESP32-S3, ESP32-C3 board (which has a built-in DS peripheral), the only required interface is WiFi and connection to internet. ### Configure the project #### 1) Selecting the target -As the project is to be built for the target ESP32-S2, ESP32-C3 it should be selected with the following command +As the project is to be built for the target ESP32-S2, ESP32-S3, ESP32-C3 it should be selected with the following command ``` idf.py set-target /* target */ ``` @@ -99,7 +99,7 @@ DATA=data ### configure_ds.py -The script [configure_ds.py](./configure_ds.py) is used for configuring the DS peripheral on the ESP32-S2/ESP32-C3 SoC. The steps in the script are based on technical details of certain operations in the Digital Signature calculation, which can be found at Digital Signature Section of [ESP32-S2 TRM](https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf) +The script [configure_ds.py](./configure_ds.py) is used for configuring the DS peripheral on the ESP32-S2/ESP32-S3/ESP32-C3 SoC. The steps in the script are based on technical details of certain operations in the Digital Signature calculation, which can be found at Digital Signature Section of [ESP32-S2 TRM](https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf) The configuration script performs the following steps - diff --git a/examples/protocols/mqtt/ssl_ds/configure_ds.py b/examples/protocols/mqtt/ssl_ds/configure_ds.py index b718052301..44f2c9e64b 100644 --- a/examples/protocols/mqtt/ssl_ds/configure_ds.py +++ b/examples/protocols/mqtt/ssl_ds/configure_ds.py @@ -46,8 +46,8 @@ csv_filename = esp_ds_data_dir + '/pre_prov.csv' bin_filename = esp_ds_data_dir + '/pre_prov.bin' expected_json_path = os.path.join('build', 'config', 'sdkconfig.json') # Targets supported by the script -supported_targets = {'esp32s2', 'esp32c3'} -supported_key_size = {'esp32s2':[1024, 2048, 3072, 4096], 'esp32c3':[1024, 2048, 3072]} +supported_targets = {'esp32s2', 'esp32c3', 'esp32s3'} +supported_key_size = {'esp32s2':[1024, 2048, 3072, 4096], 'esp32c3':[1024, 2048, 3072], 'esp32s3':[1024, 2048, 3072, 4096]} # @return @@ -89,7 +89,7 @@ def number_as_bytes(number, pad_bits=None): # privkey : path to the RSA private key # priv_key_pass : path to the RSA privaete key password # hmac_key : HMAC key value ( to calculate DS params) -# idf_target : The target chip for the script (e.g. esp32s2, esp32c3) +# idf_target : The target chip for the script (e.g. esp32s2, esp32c3, esp32s3) # @info # The function calculates the encrypted private key parameters. # Consult the DS documentation (available for the ESP32-S2) in the esp-idf programming guide for more details about the variables and calculations. diff --git a/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt b/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt index d1e3ea1f6b..b8ef6eadbd 100644 --- a/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt +++ b/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "app_main.c" INCLUDE_DIRS "." - REQUIRED_IDF_TARGETS esp32s2 esp32c3) + REQUIRED_IDF_TARGETS esp32s2 esp32c3 esp32s3) From 0e6b03f343bbce5812c2203c8af9b6c90e219edb Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Mon, 6 Sep 2021 11:21:39 +0530 Subject: [PATCH 133/310] esp32s2/hmac: Release HMAC lock in downstream mode incase of failure --- components/esp_hw_support/port/esp32s2/esp_hmac.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/components/esp_hw_support/port/esp32s2/esp_hmac.c b/components/esp_hw_support/port/esp32s2/esp_hmac.c index a95726bb58..328ccbd90d 100644 --- a/components/esp_hw_support/port/esp32s2/esp_hmac.c +++ b/components/esp_hw_support/port/esp32s2/esp_hmac.c @@ -47,7 +47,8 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) { - esp_err_t err; + int ets_status; + esp_err_t err = ESP_OK; if ((!token) || (key_id >= HMAC_KEY_MAX)) return ESP_ERR_INVALID_ARG; @@ -69,10 +70,10 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) REG_WRITE(DPORT_JTAG_CTRL_0_REG + i, __builtin_bswap32(key_word)); } - err = ets_hmac_calculate_downstream(convert_key_type(key_id), ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG); - if (err != ETS_OK) { - ESP_LOGE(TAG, "HMAC downstream JTAG enable mode setting failed."); - return ESP_FAIL; + ets_status = ets_hmac_calculate_downstream(convert_key_type(key_id), ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG); + if (ets_status != ETS_OK) { + err = ESP_FAIL; + ESP_LOGE(TAG, "HMAC downstream JTAG enable mode setting failed. (%d)", err); } ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); @@ -81,7 +82,7 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) esp_crypto_dma_lock_release(); - return ESP_OK; + return err; } esp_err_t esp_hmac_jtag_disable() From 3f2f6d0cf5438037f891ce9e483af1709ad8a33d Mon Sep 17 00:00:00 2001 From: Zim Kalinowski Date: Mon, 6 Sep 2021 14:39:48 +0800 Subject: [PATCH 134/310] freertos: upgrade to 10.4.3 - missing files from upstream --- .../freertos/GitHub-FreeRTOS-Kernel-Home.url | 7 + .../freertos/{license.txt => LICENSE.md} | 2 - components/freertos/Quick_Start_Guide.url | 5 + .../freertos/include/freertos/StackMacros.h | 32 +++ .../include/freertos/mpu_prototypes.h | 257 ++++++++++++++++++ .../freertos/include/freertos/projdefs.h | 6 +- .../freertos/include/freertos/stack_macros.h | 20 +- docs/en/COPYRIGHT.rst | 2 +- 8 files changed, 315 insertions(+), 16 deletions(-) create mode 100644 components/freertos/GitHub-FreeRTOS-Kernel-Home.url rename components/freertos/{license.txt => LICENSE.md} (92%) create mode 100644 components/freertos/Quick_Start_Guide.url create mode 100644 components/freertos/include/freertos/StackMacros.h create mode 100644 components/freertos/include/freertos/mpu_prototypes.h diff --git a/components/freertos/GitHub-FreeRTOS-Kernel-Home.url b/components/freertos/GitHub-FreeRTOS-Kernel-Home.url new file mode 100644 index 0000000000..87d25ce02f --- /dev/null +++ b/components/freertos/GitHub-FreeRTOS-Kernel-Home.url @@ -0,0 +1,7 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 +[InternetShortcut] +URL=https://github.com/FreeRTOS/FreeRTOS-Kernel +IconIndex=0 +IDList= +HotKey=0 diff --git a/components/freertos/license.txt b/components/freertos/LICENSE.md similarity index 92% rename from components/freertos/license.txt rename to components/freertos/LICENSE.md index 9e2f3185f2..9cf106272a 100644 --- a/components/freertos/license.txt +++ b/components/freertos/LICENSE.md @@ -1,7 +1,5 @@ MIT License -Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff --git a/components/freertos/Quick_Start_Guide.url b/components/freertos/Quick_Start_Guide.url new file mode 100644 index 0000000000..ebefebd612 --- /dev/null +++ b/components/freertos/Quick_Start_Guide.url @@ -0,0 +1,5 @@ +[InternetShortcut] +URL=https://www.FreeRTOS.org/FreeRTOS-quick-start-guide.html +IDList= +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 diff --git a/components/freertos/include/freertos/StackMacros.h b/components/freertos/include/freertos/StackMacros.h new file mode 100644 index 0000000000..8d09f10cd1 --- /dev/null +++ b/components/freertos/include/freertos/StackMacros.h @@ -0,0 +1,32 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */ + #warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released. +#endif + +#include "stack_macros.h" diff --git a/components/freertos/include/freertos/mpu_prototypes.h b/components/freertos/include/freertos/mpu_prototypes.h new file mode 100644 index 0000000000..ceb74f3e5b --- /dev/null +++ b/components/freertos/include/freertos/mpu_prototypes.h @@ -0,0 +1,257 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* + * When the MPU is used the standard (non MPU) API functions are mapped to + * equivalents that start "MPU_", the prototypes for which are defined in this + * header files. This will cause the application code to call the MPU_ version + * which wraps the non-MPU version with privilege promoting then demoting code, + * so the kernel code always runs will full privileges. + */ + + +#ifndef MPU_PROTOTYPES_H +#define MPU_PROTOTYPES_H + +/* MPU versions of tasks.h API functions. */ +BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskGetInfo( TaskHandle_t xTask, + TaskStatus_t * pxTaskStatus, + BaseType_t xGetFreeStackSpace, + eTaskState eState ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskPrioritySet( TaskHandle_t xTask, + UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL; +TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL; +char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, + TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL; +TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, + BaseType_t xIndex, + void * pvValue ) FREERTOS_SYSTEM_CALL; +void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, + BaseType_t xIndex ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, + void * pvParameter ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, + const UBaseType_t uxArraySize, + uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL; +uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, + uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, + BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL; +uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear, + uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, + TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of queue.h API functions. */ +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, + const void * const pvItemToQueue, + TickType_t xTicksToWait, + const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, + StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount, + StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, + const char * pcName ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + uint8_t * pucQueueStorage, + StaticQueue_t * pxStaticQueue, + const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; +QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; +QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, + const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, + BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, + UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of timers.h API functions. */ +TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL; +TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + StaticTimer_t * pxTimerBuffer ) FREERTOS_SYSTEM_CALL; +void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +void MPU_vTimerSetTimerID( TimerHandle_t xTimer, + void * pvNewID ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, + const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, + const BaseType_t xCommandID, + const TickType_t xOptionalValue, + BaseType_t * const pxHigherPriorityTaskWoken, + const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of event_group.h API functions. */ +EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL; +EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToWaitFor, + const BaseType_t xClearOnExit, + const BaseType_t xWaitForAllBits, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + const EventBits_t uxBitsToWaitFor, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of message/stream_buffer.h API functions. */ +size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, + const void * pvTxData, + size_t xDataLengthBytes, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, + void * pvRxData, + size_t xBufferLengthBytes, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, + size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL; +StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL; +StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + uint8_t * const pucStreamBufferStorageArea, + StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL; + + + +#endif /* MPU_PROTOTYPES_H */ diff --git a/components/freertos/include/freertos/projdefs.h b/components/freertos/include/freertos/projdefs.h index b7cb4f9641..ec8022ca0b 100644 --- a/components/freertos/include/freertos/projdefs.h +++ b/components/freertos/include/freertos/projdefs.h @@ -37,13 +37,13 @@ typedef void (* TaskFunction_t)( void * ); * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the * definition here is not suitable for your application. */ #ifndef pdMS_TO_TICKS - #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) ) + #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000U ) ) #endif - +#ifdef ESP_PLATFORM #ifndef pdTICKS_TO_MS #define pdTICKS_TO_MS( xTicks ) ( ( uint32_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ ) #endif - +#endif // ESP_PLATFORM #define pdFALSE ( ( BaseType_t ) 0 ) #define pdTRUE ( ( BaseType_t ) 1 ) diff --git a/components/freertos/include/freertos/stack_macros.h b/components/freertos/include/freertos/stack_macros.h index ab5452fc85..249c4ef840 100644 --- a/components/freertos/include/freertos/stack_macros.h +++ b/components/freertos/include/freertos/stack_macros.h @@ -65,8 +65,8 @@ /* Only the current stack state is to be checked. */ #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ - { \ - /* Is the currently saved stack pointer within the stack limit? */ \ + { \ + /* Is the currently saved stack pointer within the stack limit? */ \ if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack <= pxCurrentTCB[ xPortGetCoreID() ]->pxStack ) \ { \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ @@ -80,8 +80,8 @@ /* Only the current stack state is to be checked. */ #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ - { \ - \ + { \ + \ /* Is the currently saved stack pointer within the stack limit? */ \ if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack >= pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack ) \ { \ @@ -92,22 +92,22 @@ #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ /*-----------------------------------------------------------*/ -#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) +#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ + { \ static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ - \ + \ \ /* Has the extremity of the task stack ever been written over? */ \ if( memcmp( ( void * ) pxCurrentTCB[ xPortGetCoreID() ]->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ - { \ + { \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ - } \ + } \ } #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ @@ -116,7 +116,7 @@ #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ + { \ int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack; \ static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ diff --git a/docs/en/COPYRIGHT.rst b/docs/en/COPYRIGHT.rst index 2a8b688ef5..a79251bc59 100644 --- a/docs/en/COPYRIGHT.rst +++ b/docs/en/COPYRIGHT.rst @@ -19,7 +19,7 @@ These third party libraries can be included into the application (firmware) prod * :component:`Xtensa header files` are Copyright (C) 2013 Tensilica Inc and are licensed under the MIT License as reproduced in the individual header files. -* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2017 Amazon.com, Inc. or its affiliates are licensed under the MIT License, as described in :component_file:`license.txt`. +* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2017 Amazon.com, Inc. or its affiliates are licensed under the MIT License, as described in :component_file:`license.txt`. * Original parts of LWIP_ (components/lwip) are Copyright (C) 2001, 2002 Swedish Institute of Computer Science and are licensed under the BSD License as described in :component_file:`COPYING file`. From cf0e995fa9283c16bbd11c35a283e33d663c5e4f Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Mon, 6 Sep 2021 09:14:14 +0800 Subject: [PATCH 135/310] docs: bump esp-docs version to 0.1.1 --- .gitlab-ci.yml | 2 +- docs/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index da2de1785e..d1bc5816e1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -48,7 +48,7 @@ variables: # Docker images BOT_DOCKER_IMAGE_TAG: ":latest" - ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v4.4-1-v3" + ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v4.4-1-v4" ESP_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-env:v4.4-1" AFL_FUZZER_TEST_IMAGE: "$CI_DOCKER_REGISTRY/afl-fuzzer-test:v4.4-1-1" CLANG_STATIC_ANALYSIS_IMAGE: "${CI_DOCKER_REGISTRY}/clang-static-analysis:v4.4-1-2" diff --git a/docs/requirements.txt b/docs/requirements.txt index 8e1500e670..16bd54ca82 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1 @@ -esp-docs==0.1.0 +esp-docs==0.1.1 From 2be77287b324ff37fbb3f97d96a6b894e30da732 Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Fri, 30 Jul 2021 15:55:37 +0800 Subject: [PATCH 136/310] openthread: add iperf example for ot-network test --- components/openthread/Kconfig | 6 + .../openthread-core-esp32x-ftd-config.h | 2 +- .../ble_mesh_wifi_coexist/main/cmd_wifi.c | 39 +- .../common_components/iperf/include/iperf.h | 29 +- examples/common_components/iperf/iperf.c | 479 ++++++++++-------- examples/ethernet/iperf/main/cmd_ethernet.c | 26 +- examples/openthread/ot_cli/CMakeLists.txt | 2 + examples/openthread/ot_cli/Makefile | 2 + examples/openthread/ot_cli/README.md | 85 +++- .../openthread/ot_cli/main/CMakeLists.txt | 2 +- examples/openthread/ot_cli/main/esp_ot_cli.c | 18 +- .../ot_cli/main/esp_ot_cli_extension.c | 20 +- .../ot_cli/main/esp_ot_cli_extension.h | 20 +- .../openthread/ot_cli/main/esp_ot_config.h | 18 +- .../openthread/ot_cli/main/esp_ot_iperf.c | 98 ++++ .../openthread/ot_cli/main/esp_ot_iperf.h | 20 + .../ot_cli/main/esp_ot_tcp_socket.c | 22 +- .../ot_cli/main/esp_ot_tcp_socket.h | 18 +- .../ot_cli/main/esp_ot_udp_socket.c | 27 +- .../ot_cli/main/esp_ot_udp_socket.h | 18 +- examples/openthread/ot_cli/sdkconfig.defaults | 1 + examples/wifi/iperf/main/cmd_wifi.c | 117 +++-- 22 files changed, 673 insertions(+), 396 deletions(-) create mode 100644 examples/openthread/ot_cli/main/esp_ot_iperf.c create mode 100644 examples/openthread/ot_cli/main/esp_ot_iperf.h diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 7803240730..cdee2a0222 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -91,4 +91,10 @@ menu "OpenThread" help Override the shipped libopenthread_br.a and libopenthread_port.a, for internal builds. + config OPENTHREAD_NUM_MESSAGE_BUFFERS + int "The number of openthread message buffers" + depends on OPENTHREAD_ENABLED + default 65 + range 50 100 + endmenu diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 07a6bdc754..cc9bb2cd8d 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -95,7 +95,7 @@ * * The number of message buffers in buffer pool */ -#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 50 +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS CONFIG_OPENTHREAD_NUM_MESSAGE_BUFFERS /** * @def OPENTHREAD_CONFIG_COAP_API_ENABLE diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c index 40e67a3281..f496e7f2c2 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c @@ -23,7 +23,9 @@ typedef struct { struct arg_str *ip; struct arg_lit *server; struct arg_lit *udp; + struct arg_lit *version; struct arg_int *port; + struct arg_int *length; struct arg_int *interval; struct arg_int *time; struct arg_lit *abort; @@ -51,8 +53,8 @@ static const char *TAG = "iperf"; static EventGroupHandle_t wifi_event_group; const int CONNECTED_BIT = BIT0; const int DISCONNECTED_BIT = BIT1; -static esp_netif_t * sta_netif = NULL; -static esp_netif_t * ap_netif = NULL; +static esp_netif_t *sta_netif = NULL; +static esp_netif_t *ap_netif = NULL; static void scan_done_handler(void) { @@ -75,8 +77,8 @@ static void scan_done_handler(void) free(ap_list_buffer); } -static void wifi_event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void wifi_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { switch (event_id) { case WIFI_EVENT_SCAN_DONE: @@ -102,8 +104,8 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base, return; } -static void ip_event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void ip_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { switch (event_id) { case IP_EVENT_STA_GOT_IP: @@ -292,7 +294,7 @@ static int wifi_cmd_query(int argc, char **argv) static uint32_t wifi_get_local_ip(void) { int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 0); - esp_netif_t * ifx = ap_netif; + esp_netif_t *ifx = ap_netif; esp_netif_ip_info_t ip_info; wifi_mode_t mode; @@ -323,6 +325,9 @@ static int wifi_cmd_iperf(int argc, char **argv) memset(&cfg, 0, sizeof(cfg)); + // wifi iperf only support IPV4 address + cfg.type = IPERF_IP_TYPE_IPV4; + if ( iperf_args.abort->count != 0) { iperf_stop(); return 0; @@ -337,15 +342,21 @@ static int wifi_cmd_iperf(int argc, char **argv) if (iperf_args.ip->count == 0) { cfg.flag |= IPERF_FLAG_SERVER; } else { - cfg.dip = esp_ip4addr_aton(iperf_args.ip->sval[0]); + cfg.destination_ip4 = esp_ip4addr_aton(iperf_args.ip->sval[0]); cfg.flag |= IPERF_FLAG_CLIENT; } - cfg.sip = wifi_get_local_ip(); - if (cfg.sip == 0) { + cfg.source_ip4 = wifi_get_local_ip(); + if (cfg.source_ip4 == 0) { return 0; } + if (iperf_args.length->count == 0) { + cfg.len_send_buf = 0; + } else { + cfg.len_send_buf = iperf_args.length->ival[0]; + } + if (iperf_args.udp->count == 0) { cfg.flag |= IPERF_FLAG_TCP; } else { @@ -386,8 +397,10 @@ static int wifi_cmd_iperf(int argc, char **argv) ESP_LOGI(TAG, "mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d", cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp", cfg.flag & IPERF_FLAG_SERVER ? "server" : "client", - cfg.sip & 0xFF, (cfg.sip >> 8) & 0xFF, (cfg.sip >> 16) & 0xFF, (cfg.sip >> 24) & 0xFF, cfg.sport, - cfg.dip & 0xFF, (cfg.dip >> 8) & 0xFF, (cfg.dip >> 16) & 0xFF, (cfg.dip >> 24) & 0xFF, cfg.dport, + cfg.source_ip4 & 0xFF, (cfg.source_ip4 >> 8) & 0xFF, (cfg.source_ip4 >> 16) & 0xFF, + (cfg.source_ip4 >> 24) & 0xFF, cfg.sport, + cfg.destination_ip4 & 0xFF, (cfg.destination_ip4 >> 8) & 0xFF, (cfg.destination_ip4 >> 16) & 0xFF, + (cfg.destination_ip4 >> 24) & 0xFF, cfg.dport, cfg.interval, cfg.time); iperf_start(&cfg); @@ -471,7 +484,9 @@ void register_wifi(void) iperf_args.ip = arg_str0("c", "client", "", "run in client mode, connecting to "); iperf_args.server = arg_lit0("s", "server", "run in server mode"); iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP"); + iperf_args.version = arg_lit0("V", "ipv6_domain", "use IPV6 address rather than IPV4"); iperf_args.port = arg_int0("p", "port", "", "server port to listen on/connect to"); + iperf_args.length = arg_int0("l", "len", "", "set read/write buffer size"); iperf_args.interval = arg_int0("i", "interval", "", "seconds between periodic bandwidth reports"); iperf_args.time = arg_int0("t", "time", "