From f5450ca5301c40bfa01de66e45fe49851a2faa15 Mon Sep 17 00:00:00 2001 From: Nic Ballinger Date: Mon, 31 Jul 2023 17:49:11 -0500 Subject: [PATCH 001/142] fix(docs/jtag): Fix hard-coded HW breakpoints/watchpoints number Closes https://github.com/espressif/esp-idf/pull/11986 --- docs/en/api-guides/jtag-debugging/tips-and-quirks.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst b/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst index b0f216fea7d8..f1cb5340293f 100644 --- a/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst +++ b/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst @@ -48,7 +48,7 @@ Offset should be in hex format. To reset to the default behaviour you can specif Why Stepping with "next" Does Not Bypass Subroutine Calls? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When stepping through the code with ``next`` command, GDB is internally setting a breakpoint (one out of two available) ahead in the code to bypass the subroutine calls. This functionality will not work, if the two available breakpoints are already set elsewhere in the code. If this is the case, delete breakpoints to have one "spare". With both breakpoints already used, stepping through the code with ``next`` command will work as like with ``step`` command and debugger will step inside subroutine calls. +When stepping through the code with ``next`` command, GDB is internally setting a breakpoint ahead in the code to bypass the subroutine calls. If all {IDF_TARGET_SOC_CPU_BREAKPOINTS_NUM} breakpoints are already set, this functionality will not work. If this is the case, delete breakpoints to have one "spare". With all breakpoints already used, stepping through the code with ``next`` command will work as like with ``step`` command and debugger will step inside subroutine calls. .. _jtag-debugging-tip-code-options: @@ -110,7 +110,7 @@ What is the Meaning of Debugger's Startup Commands? On startup, debugger is issuing sequence of commands to reset the chip and halt it at specific line of code. This sequence (shown below) is user defined to pick up at most convenient/appropriate line and start debugging. -* ``set remote hardware-watchpoint-limit 2`` — Restrict GDB to using two hardware watchpoints supported by the chip, 2 for {IDF_TARGET_NAME}. For more information see https://sourceware.org/gdb/onlinedocs/gdb/Remote-Configuration.html. +* ``set remote hardware-watchpoint-limit {IDF_TARGET_SOC_CPU_WATCHPOINTS_NUM}`` — Restrict GDB to using available hardware watchpoints supported by the chip, {IDF_TARGET_SOC_CPU_WATCHPOINTS_NUM} for {IDF_TARGET_NAME}. For more information see https://sourceware.org/gdb/onlinedocs/gdb/Remote-Configuration.html. * ``mon reset halt`` — reset the chip and keep the CPUs halted * ``flushregs`` — monitor (``mon``) command can not inform GDB that the target state has changed. GDB will assume that whatever stack the target had before ``mon reset halt`` will still be valid. In fact, after reset the target state will change, and executing ``flushregs`` is a way to force GDB to get new state from the target. * ``thb app_main`` — insert a temporary hardware breakpoint at ``app_main``, put here another function name if required From c08a4e6b3d51482690bcd8424d9f34f6c19d530d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Tue, 29 Aug 2023 12:43:58 +0200 Subject: [PATCH 002/142] ci(examples): Enable storage/perf_benchmark build test for spiflash on ESP32-P4 --- examples/storage/.build-test-rules.yml | 6 +++--- examples/storage/perf_benchmark/README.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/storage/.build-test-rules.yml b/examples/storage/.build-test-rules.yml index 8fd1f02eec87..b3012a887910 100644 --- a/examples/storage/.build-test-rules.yml +++ b/examples/storage/.build-test-rules.yml @@ -112,10 +112,10 @@ examples/storage/parttool: reason: lack of runners examples/storage/perf_benchmark: - disable: - - if: IDF_TARGET == "esp32p4" + disable_test: + - if: IDF_TARGET in ["esp32p4"] temporary: true - reason: target esp32p4 is not supported yet + reason: target esp32p4 is not supported yet, only build test (for spiflash, not sdspi or sdmmc) examples/storage/sd_card/sdmmc: disable: diff --git a/examples/storage/perf_benchmark/README.md b/examples/storage/perf_benchmark/README.md index f9dd9440fb1a..c30959cac850 100644 --- a/examples/storage/perf_benchmark/README.md +++ b/examples/storage/perf_benchmark/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | # Storage performance benchmark example From afc7cf445ed688b85de9fdfd8b10a633a334d083 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Mon, 28 Aug 2023 20:08:47 +0800 Subject: [PATCH 003/142] feat(bt/bluedroid): Add flags for BQB auto test of L2CAP 1: add sdp_bqb_disable_flag to avoid running sdpu_build_n_send_error. 2: add sdp_bqb_inact_timeout_flag to set the SDP inactivity timeout to 90 seconds. 3: add l2cap_bqb_bad_cmd_len_rej_flag to reject the C-Frame with invalid PDU length 4: add l2cap_bqb_ertm_mode_included_flag to set L2CAP_FCR_ERTM_MODE for most L2CAP cases --- .../bt/host/bluedroid/stack/l2cap/l2c_api.c | 27 ++++++ .../bt/host/bluedroid/stack/l2cap/l2c_main.c | 28 ++++++ .../bt/host/bluedroid/stack/l2cap/l2c_utils.c | 17 +++- .../host/bluedroid/stack/sdp/include/sdpint.h | 6 +- .../bt/host/bluedroid/stack/sdp/sdp_main.c | 90 +++++++++++++++++-- 5 files changed, 158 insertions(+), 10 deletions(-) diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c index f88d58956ba8..fa01790d5f39 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c @@ -2137,6 +2137,33 @@ UINT8 L2CA_DataWrite (UINT16 cid, BT_HDR *p_data) } #endif ///CLASSIC_BT_INCLUDED == TRUE +/******************************************************************************* +** +** Function l2cap_bqb_write_data +** +** Description Call L2CA_DataWrite and write I-Frame data for BQB test. +** +** Returns None +** +*******************************************************************************/ +#if (BT_CLASSIC_BQB_INCLUDED == TRUE) +void l2cap_bqb_write_data(UINT16 cid) +{ + BT_HDR *p_buf; + uint8_t *p; + + if ((p_buf = (BT_HDR *)osi_malloc(SDP_DATA_BUF_SIZE)) != NULL) { + p_buf->len = 30; + p_buf->offset = L2CAP_MIN_OFFSET; + p = (UINT8 *)(p_buf + 1) + p_buf->offset; + for(int i = 0 ; i < 10; i++) { + UINT8_TO_BE_STREAM(p, 0) + } + L2CA_DataWrite(cid, p_buf); + } +} +#endif /* BT_CLASSIC_BQB_INCLUDED */ + /******************************************************************************* ** ** Function L2CA_SetChnlFlushability diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_main.c b/components/bt/host/bluedroid/stack/l2cap/l2c_main.c index 364aac8467da..dfdef99bef54 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_main.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_main.c @@ -52,6 +52,10 @@ tL2C_CB l2cb; tL2C_CB *l2c_cb_ptr; #endif +#if BT_CLASSIC_BQB_INCLUDED +static BOOLEAN s_l2cap_bqb_bad_cmd_len_rej_flag = FALSE; +#endif /* BT_CLASSIC_BQB_INCLUDED */ + #if 0 //Unused /******************************************************************************* ** @@ -107,6 +111,24 @@ void l2c_bcst_msg( BT_HDR *p_buf, UINT16 psm ) } #endif +/******************************************************************************* +** +** Function l2cap_bqb_bad_cmd_len_rej_ctrl +** +** Description Control rejecting L2CAP signaling PDUs with incorrect length +** for BQB test. +** +** Returns void +** +*******************************************************************************/ +#if BT_CLASSIC_BQB_INCLUDED +void l2cap_bqb_bad_cmd_len_rej_ctrl(BOOLEAN enable) +{ + s_l2cap_bqb_bad_cmd_len_rej_flag = enable; +} +#endif /* BT_CLASSIC_BQB_INCLUDED */ + + /******************************************************************************* ** ** Function l2c_rcv_acl_data @@ -461,6 +483,12 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) p_ccb->remote_cid = rcid; l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info); +#if BT_CLASSIC_BQB_INCLUDED + // L2CAP/COS/CED/BI-02-C + if (s_l2cap_bqb_bad_cmd_len_rej_flag) { + l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0); + } +#endif /* BT_CLASSIC_BQB_INCLUDED */ break; case L2CAP_CMD_CONN_RSP: diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c index c70cd9c816cd..2829197520b2 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c @@ -39,6 +39,10 @@ #include "osi/allocator.h" #include "osi/list.h" +#if BT_SDP_BQB_INCLUDED +extern BOOLEAN l2cap_bqb_ertm_mode_included_flag; +#endif /* BT_SDP_BQB_INCLUDED */ + /******************************************************************************* ** ** Function l2cu_allocate_lcb @@ -1558,8 +1562,17 @@ tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid) #if (CLASSIC_BT_INCLUDED == TRUE) l2c_fcr_free_timer (p_ccb); #endif ///CLASSIC_BT_INCLUDED == TRUE - p_ccb->ertm_info.preferred_mode = L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */ - p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_BASIC|L2CAP_FCR_CHAN_OPT_ERTM; + +#if BT_CLASSIC_BQB_INCLUDED + if (l2cap_bqb_ertm_mode_included_flag) { + p_ccb->ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE; + p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM; + } else +#endif /* BT_CLASSIC_BQB_INCLUDED */ + { + p_ccb->ertm_info.preferred_mode = L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */ + p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_BASIC|L2CAP_FCR_CHAN_OPT_ERTM; + } p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE; p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE; p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE; diff --git a/components/bt/host/bluedroid/stack/sdp/include/sdpint.h b/components/bt/host/bluedroid/stack/sdp/include/sdpint.h index 9c0e6047d025..ab97b70276af 100644 --- a/components/bt/host/bluedroid/stack/sdp/include/sdpint.h +++ b/components/bt/host/bluedroid/stack/sdp/include/sdpint.h @@ -37,8 +37,10 @@ #define SDP_MAX_CONTINUATION_LEN 16 /* As per the spec */ /* Timeout definitions. */ -#define SDP_INACT_TIMEOUT 30 /* Inactivity timeout */ - +#define SDP_INACT_TIMEOUT 30 /* Inactivity timeout */ +#if BT_SDP_BQB_INCLUDED +#define SDP_BQB_INACT_TIMEOUT 90 /* Inactivity timeout for BQB test */ +#endif /* BT_SDP_BQB_INCLUDED */ /* Define the Out-Flow default values. */ #define SDP_OFLOW_QOS_FLAG 0 diff --git a/components/bt/host/bluedroid/stack/sdp/sdp_main.c b/components/bt/host/bluedroid/stack/sdp/sdp_main.c index 3e7333719107..e945314b830b 100644 --- a/components/bt/host/bluedroid/stack/sdp/sdp_main.c +++ b/components/bt/host/bluedroid/stack/sdp/sdp_main.c @@ -71,6 +71,59 @@ static void sdp_disconnect_cfm (UINT16 l2cap_cid, UINT16 result); #define sdp_disconnect_cfm NULL #endif +#if BT_SDP_BQB_INCLUDED +static BOOLEAN s_sdp_bqb_disable_flag = FALSE; +static BOOLEAN s_sdp_bqb_inact_timeout_flag = FALSE; +BOOLEAN l2cap_bqb_ertm_mode_included_flag = FALSE; +#endif /* BT_SDP_BQB_INCLUDED */ + +/******************************************************************************* +** +** Function sdp_bqb_disable_ctrl +** +** Description Control the disable of bqb for SDP BQB test +** +** Returns void +** +*******************************************************************************/ +#if BT_SDP_BQB_INCLUDED +void sdp_bqb_disable_ctrl(BOOLEAN enable) +{ + s_sdp_bqb_disable_flag = enable; +} +#endif /* BT_SDP_BQB_INCLUDED */ + +/******************************************************************************* +** +** Function sdp_bqb_inact_timeout_ctrl +** +** Description Control the inactivity timeout for SDP BQB test +** +** Returns void +** +*******************************************************************************/ +#if BT_SDP_BQB_INCLUDED +void sdp_bqb_inact_timeout_ctrl(BOOLEAN enable) +{ + s_sdp_bqb_inact_timeout_flag = enable; +} +#endif /* BT_SDP_BQB_INCLUDED */ + +/******************************************************************************* +** +** Function l2cap_bqb_ertm_mode_included_ctrl +** +** Description Control the L2CAP flow control and retransmissions mode for SDP BQB test +** +** Returns void +** +*******************************************************************************/ +#if BT_SDP_BQB_INCLUDED +void l2cap_bqb_ertm_mode_included_ctrl(BOOLEAN enable) +{ + l2cap_bqb_ertm_mode_included_flag = enable; +} +#endif /* BT_SDP_BQB_INCLUDED */ /******************************************************************************* ** @@ -95,7 +148,17 @@ void sdp_init (void) sdp_cb.l2cap_my_cfg.mtu = SDP_MTU_SIZE; sdp_cb.l2cap_my_cfg.flush_to_present = TRUE; sdp_cb.l2cap_my_cfg.flush_to = SDP_FLUSH_TO; - +#if BT_SDP_BQB_INCLUDED + if (l2cap_bqb_ertm_mode_included_flag) { + sdp_cb.l2cap_my_cfg.fcr_present = TRUE; + sdp_cb.l2cap_my_cfg.fcr.mode = L2CAP_FCR_ERTM_MODE; + sdp_cb.l2cap_my_cfg.fcr.tx_win_sz = 8; + sdp_cb.l2cap_my_cfg.fcr.max_transmit = 0xff; + sdp_cb.l2cap_my_cfg.fcr.rtrans_tout = 2000; + sdp_cb.l2cap_my_cfg.fcr.mon_tout = 12000; + sdp_cb.l2cap_my_cfg.fcr.mps = 672; + } +#endif /* BT_SDP_BQB_INCLUDED */ sdp_cb.max_attr_list_size = SDP_MTU_SIZE - 16; sdp_cb.max_recs_per_search = SDP_MAX_DISC_SERVER_RECS; @@ -424,7 +487,15 @@ static void sdp_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) } else /* Start inactivity timer */ { - btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT); +#if BT_SDP_BQB_INCLUDED + /* Change the timeout from 30s to 90s for BQB test */ + if (s_sdp_bqb_inact_timeout_flag) { + btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_BQB_INACT_TIMEOUT); + } else +#endif /* BT_SDP_BQB_INCLUDED */ + { + btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT); + } } } } else { @@ -505,10 +576,17 @@ static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) != NULL) { if (p_ccb->con_state == SDP_STATE_CONNECTED) { - if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) { - sdp_disc_server_rsp (p_ccb, p_msg); - } else { - sdp_server_handle_client_req (p_ccb, p_msg); +#if BT_SDP_BQB_INCLUDED + /* Skip the following code in BQB test when the flag is true, since the PDU is reserved and + function sdp_server_handle_client_req will return error (sdpu_build_n_send_error) */ + if (!s_sdp_bqb_disable_flag) +#endif /* BT_SDP_BQB_INCLUDED */ + { + if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) { + sdp_disc_server_rsp(p_ccb, p_msg); + } else { + sdp_server_handle_client_req(p_ccb, p_msg); + } } } else { SDP_TRACE_WARNING ("SDP - Ignored L2CAP data while in state: %d, CID: 0x%x\n", From 195524efa85a01c2e53944dd3bceacb4e3d24ddb Mon Sep 17 00:00:00 2001 From: Chip Weinberger Date: Fri, 18 Aug 2023 00:24:02 -0700 Subject: [PATCH 004/142] docs(jtag-debugging): Add links to gdbstub for convenience Closes https://github.com/espressif/esp-idf/pull/12097 --- docs/en/api-guides/jtag-debugging/index.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/en/api-guides/jtag-debugging/index.rst b/docs/en/api-guides/jtag-debugging/index.rst index 9922131185d3..d022eb39efb2 100644 --- a/docs/en/api-guides/jtag-debugging/index.rst +++ b/docs/en/api-guides/jtag-debugging/index.rst @@ -3,7 +3,15 @@ JTAG Debugging :link_to_translation:`zh_CN:[中文]` -This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB. The document is structured as follows: +This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB. + +.. note:: + + You can also debug your {IDF_TARGET_NAME} without needing to setup JTAG or OpenOCD by using ``idf.py monitor``. See: :doc:`IDF Monitor <../../api-guides/tools/idf-monitor>` and :ref:CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME + +.. highlight:: none + +The document is structured as follows: :ref:`jtag-debugging-introduction` Introduction to the purpose of this guide. From c17d9ff68432345af0ce02cf30b9e20d551dea6c Mon Sep 17 00:00:00 2001 From: renpeiying Date: Tue, 19 Sep 2023 19:02:06 +0800 Subject: [PATCH 005/142] docs: Update Chinese translation for api-guides/jtag-debugging/index.rst --- docs/en/api-guides/jtag-debugging/index.rst | 4 ++-- docs/zh_CN/api-guides/jtag-debugging/index.rst | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/en/api-guides/jtag-debugging/index.rst b/docs/en/api-guides/jtag-debugging/index.rst index d022eb39efb2..523fb4da32ae 100644 --- a/docs/en/api-guides/jtag-debugging/index.rst +++ b/docs/en/api-guides/jtag-debugging/index.rst @@ -3,11 +3,11 @@ JTAG Debugging :link_to_translation:`zh_CN:[中文]` -This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB. +This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB. .. note:: - You can also debug your {IDF_TARGET_NAME} without needing to setup JTAG or OpenOCD by using ``idf.py monitor``. See: :doc:`IDF Monitor <../../api-guides/tools/idf-monitor>` and :ref:CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME + You can also debug your {IDF_TARGET_NAME} without needing to setup JTAG or OpenOCD by using ``idf.py monitor``. See: :doc:`../../api-guides/tools/idf-monitor` and :ref:`CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME`. .. highlight:: none diff --git a/docs/zh_CN/api-guides/jtag-debugging/index.rst b/docs/zh_CN/api-guides/jtag-debugging/index.rst index f41d85196666..e9ab7798ef5c 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/index.rst +++ b/docs/zh_CN/api-guides/jtag-debugging/index.rst @@ -3,7 +3,15 @@ JTAG 调试 :link_to_translation:`en:[English]` -本文将介绍如何安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,以及如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。本文结构如下: +本文将介绍如何安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,以及如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。 + +.. note:: + + 也可以使用 ``idf.py monitor`` 来调试 {IDF_TARGET_NAME},免于设置 JTAG 或 OpenOCD。请参阅 :doc:`../../api-guides/tools/idf-monitor` 和 :ref:`CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME`。 + +.. highlight:: none + +本文档结构如下: :ref:`jtag-debugging-introduction` 介绍本指南主旨。 From a79910cb21071ff76e2ddc4af987681f36e2e7c1 Mon Sep 17 00:00:00 2001 From: darshan Date: Mon, 18 Sep 2023 17:08:12 +0530 Subject: [PATCH 006/142] doc(nimble): Added the tutorial for spp_client example. --- .../tutorial/spp_client_walkthrough.md | 549 ++++++++++++++++++ 1 file changed, 549 insertions(+) create mode 100644 examples/bluetooth/nimble/ble_spp/spp_client/tutorial/spp_client_walkthrough.md diff --git a/examples/bluetooth/nimble/ble_spp/spp_client/tutorial/spp_client_walkthrough.md b/examples/bluetooth/nimble/ble_spp/spp_client/tutorial/spp_client_walkthrough.md new file mode 100644 index 000000000000..287974f8db05 --- /dev/null +++ b/examples/bluetooth/nimble/ble_spp/spp_client/tutorial/spp_client_walkthrough.md @@ -0,0 +1,549 @@ +# BLE SPP Client Example Walkthrough + +## Introduction + +In this tutorial, we will explore the spp_client example code provided by Espressif's ESP-IDF framework. This tutorial guides you in building a BLE Serial Port Profile (SPP) client using the NimBLE stack. BLE SPP enables wireless serial communication, making it valuable for IoT and embedded applications. By following this tutorial, you will learn how to scan for nearby BLE devices advertising the SPP service, establish connections, and create a virtual serial link for data exchange. + +## Includes + +This example is located in the examples folder of the ESP-IDF under the [ble_spp/spp_client/main](../main). The [main.c](../main/main.c) file located in the main folder contains all the functionality that we are going to review. The header files contained in [main.c](../main/main.c) are: + +```c +#include "esp_log.h" +#include "nvs_flash.h" +/* BLE */ +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "console/console.h" +#include "services/gap/ble_svc_gap.h" +#include "ble_spp_client.h" +#include "driver/uart.h" +``` + +These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `“nimble_port.h”`, `“nimble_port_freertos.h”`, `"ble_hs.h"`, `“ble_svc_gap.h”` and `“ble_spp_client.h”` which expose the BLE APIs required to implement this example. + +* `nimble_port.h`: Includes the declaration of functions required for the initialization of the nimble stack. +* `nimble_port_freertos.h`: Initializes and enables nimble host task. +* `ble_hs.h`: Defines the functionalities to handle the host event. +* `ble_svc_gap.h`: Defines the macros for device name, and device appearance and declares the function to set them. +* `ble_spp_client.h`: Defines constants and structures for a BLE SPP client using the NimBLE stack. It includes UUIDs and data structures for BLE communication in an ESP-IDF project. + +## Main Entry Point + +The program's entry point is the app_main() function: +```c +void +app_main(void) +{ + int rc; + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ret = nimble_port_init(); + if (ret != ESP_OK) { + MODLOG_DFLT(ERROR, "Failed to init nimble %d \n", ret); + return; + } + + /* Initialize UART driver and start uart task */ + ble_spp_uart_init(); + + /* Configure the host. */ + ble_hs_cfg.reset_cb = ble_spp_client_on_reset; + ble_hs_cfg.sync_cb = ble_spp_client_on_sync; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + /* Initialize data structures to track connected peers. */ + rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); + assert(rc == 0); + + /* Set the default device name. */ + rc = ble_svc_gap_device_name_set("nimble-ble-spp-client"); + assert(rc == 0); + + /* XXX Need to have template for store */ + ble_store_config_init(); + + nimble_port_freertos_init(ble_spp_client_host_task); +} +``` + +The main function starts by initializing the non-volatile storage library. This library allows us to save the key-value pairs in flash memory. `nvs_flash_init()` stores the PHY calibration data. In a Bluetooth Low Energy (BLE) device, cryptographic keys used for encryption and authentication are often stored in Non-Volatile Storage (NVS). BLE stores the peer keys, CCCD keys, peer records, etc on NVS. By storing these keys in NVS, the BLE device can quickly retrieve them when needed, without the need for time-consuming key generations. +```c +esp_err_t ret = nvs_flash_init(); +if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); +} +ESP_ERROR_CHECK(ret); +``` + +## BT Controller and Stack Initialization + +The main function calls `nimble_port_init()` to initialize BT Controller and nimble stack. This function initializes the BT controller by first creating its configuration structure named `esp_bt_controller_config_t` with default settings generated by the `BT_CONTROLLER_INIT_CONFIG_DEFAULT()` macro. It implements the Host Controller Interface (HCI) on the controller side, the Link Layer (LL), and the Physical Layer (PHY). The BT Controller is invisible to the user applications and deals with the lower layers of the BLE stack. The controller configuration includes setting the BT controller stack size, priority, and HCI baud rate. With the settings created, the BT controller is initialized and enabled with the `esp_bt_controller_init()` and `esp_bt_controller_enable()` functions: + +```c +esp_bt_controller_config_t config_opts = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); +ret = esp_bt_controller_init(&config_opts); +``` +Next, the controller is enabled in BLE Mode. + +```c +ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); +``` +The controller should be enabled in `ESP_BT_MODE_BLE` if you want to use the BLE mode. + +There are four Bluetooth modes supported: + +1. `ESP_BT_MODE_IDLE`: Bluetooth not running +2. `ESP_BT_MODE_BLE`: BLE mode +3. `ESP_BT_MODE_CLASSIC_BT`: BT Classic mode +4. `ESP_BT_MODE_BTDM`: Dual mode (BLE + BT Classic) + +After the initialization of the BT controller, the nimble stack, which includes the common definitions and APIs for BLE, is initialized by using `esp_nimble_init()`: + +```c +esp_err_t esp_nimble_init(void) +{ +#if !SOC_ESP_NIMBLE_CONTROLLER + /* Initialize the function pointers for OS porting */ + npl_freertos_funcs_init(); + + npl_freertos_mempool_init(); + + if(esp_nimble_hci_init() != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci inits failed\n"); + return ESP_FAIL; + } + + /* Initialize default event queue */ + ble_npl_eventq_init(&g_eventq_dflt); + /* Initialize the global memory pool */ + os_mempool_module_init(); + os_msys_init(); + +#endif + /* Initialize the host */ + ble_transport_hs_init(); + + return ESP_OK; +} +``` + +The main function calls `ble_spp_uart_init`, which is responsible for initializing the UART (Universal Asynchronous Receiver-Transmitter) communication for the BLE SPP client application. + +```c +static void ble_spp_uart_init(void) +{ + uart_config_t 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_RTS, + .rx_flow_ctrl_thresh = 122, + .source_clk = UART_SCLK_DEFAULT, + }; + + //Install UART driver, and get the queue. + uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_common_uart_queue, 0); + //Set UART parameters + uart_param_config(UART_NUM_0, &uart_config); + //Set UART pins + uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + xTaskCreate(ble_client_uart_task, "uTask", 4096, (void *)UART_NUM_0, 8, NULL); +} +``` + +* It defines a configuration structure (`uart_config_t`) to specify the UART communication settings, such as `baud rate`, `data bits`, `parity`, `stop bits`, `flow control`, and more. + +* `uart_driver_install` installs the UART driver, allocating memory for the UART communication buffers and creating a queue (`spp_common_uart_queue`) to manage UART events. + +* `uart_param_config` sets the UART parameters based on the configuration structure defined earlier. + +* `uart_set_pin` configures the UART pins for communication. In this case, it uses default pin configurations. + +* Finally, it creates a FreeRTOS task (`ble_client_uart_task`) that will handle UART communication. This task is responsible for sending and receiving data over UART. + +```c +/* Configure the host. */ +ble_hs_cfg.reset_cb = ble_spp_client_on_reset; +ble_hs_cfg.sync_cb = ble_spp_client_on_sync; +ble_hs_cfg.store_status_cb = ble_store_util_status_rr; +``` + +The host is configured by setting up the callbacks for Stack-reset, Stack-sync, and Storage status. + +```c +/* Initialize data structures to track connected peers. */ +rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); +assert(rc == 0); +``` +The main function invokes `peer_init()` to initialize memory pools to manage peer, service, characteristics, and descriptor objects in BLE. + +```c +/* Set the default device name. */ +rc = ble_svc_gap_device_name_set("nimble-ble-spp-client"); +assert(rc == 0); +``` +The main function calls `ble_svc_gap_device_name_set()` to set the default device name. + +```c +/* XXX Need to have template for store */ +ble_store_config_init(); +``` +The main function calls `ble_store_config_init()` to configure the host by setting up the storage callbacks which handle the read, write, and deletion of security material. + +```c +nimble_port_freertos_init(ble_spp_client_host_task); +``` +The main function ends by creating a task where nimble will run using `nimble_port_freertos_init()`. This enables the nimble stack by using `esp_nimble_enable()`. + +## ble_client_uart_task + +```c +void ble_client_uart_task(void *pvParameters) +{ + ESP_LOGI(tag, "BLE client UART task started"); + int rc; + int i; + uart_event_t event; + for (;;) { + //Waiting for UART event. + if (xQueueReceive(spp_common_uart_queue, (void * )&event, (TickType_t)portMAX_DELAY)) { + switch (event.type) { + //Event of UART receving data + case UART_DATA: + if (event.size) { + + /* Writing characteristics */ + uint8_t *temp = NULL; + temp = (uint8_t *)malloc(sizeof(uint8_t) * event.size); + if (temp == NULL) { + ESP_LOGE(tag, "malloc failed,%s L#%d", __func__, __LINE__); + break; + } + memset(temp, 0x0, event.size); + uart_read_bytes(UART_NUM_0, temp, event.size, portMAX_DELAY); + for ( i = 0; i <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + if (attribute_handle[i] != 0) { + rc = ble_gattc_write_flat(i, attribute_handle[i], temp, event.size, NULL, NULL); + if (rc == 0) { + ESP_LOGI(tag, "Write in uart task success!"); + } else { + ESP_LOGI(tag, "Error in writing characteristic rc=%d", rc); + } + vTaskDelay(10); + } + } + free(temp); + } + break; + default: + break; + } + } + } + vTaskDelete(NULL); + +} +``` + +This function, `ble_client_uart_task` manages the transfer of data between the UART interface and the Bluetooth connections, allowing for bidirectional communication over BLE. + +1. **Initialization**: It starts by logging the initiation of the BLE client UART task. This task handles UART communication for the SPP client. + +2. **Event Loop**: The function enters an infinite loop, where it continuously checks for UART events. + +3. **Waiting for UART Event**: It waits for a UART event using `xQueueReceive` with an indefinite delay (`portMAX_DELAY`). This allows it to block until there's UART data to process. + +4. **Event Type Check**: Once an event is received, it checks the event type. In this context, it's looking for UART data events (`UART_DATA`). + +5. **Data Processing**: If UART data is received (i.e., `event.size` is nonzero), it proceeds to handle the data. + + - It dynamically allocates memory for a temporary buffer (`temp`) to store the incoming data. + + - It reads the UART data into the `temp` buffer using `uart_read_bytes`. + + - It then iterates through potential BLE connections (`CONFIG_BT_NIMBLE_MAX_CONNECTIONS`) and checks if there's a valid attribute handle associated with the connection. + + - For each valid connection, it attempts to write the data from the `temp` buffer to the corresponding BLE characteristic using `ble_gattc_write_flat`. + + - If the write operation is successful, it logs a success message; otherwise, it logs an error message. + + - A small delay (`vTaskDelay`) is introduced between write attempts (e.g., to avoid flooding the BLE connection). + + - Finally, it frees the temporary buffer (`temp`) to release the allocated memory. + +6. **Task Deletion**: After processing, the task is deleted (`vTaskDelete(NULL)`) to free up system resources. + + +## ble_spp_client_scan() + +```c +static void +ble_spp_client_scan(void) +{ + uint8_t own_addr_type; + struct ble_gap_disc_params disc_params; + int rc; + + /* Figure out address to use while advertising (no privacy for now) */ + rc = ble_hs_id_infer_auto(0, &own_addr_type); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); + return; + } + + /* Tell the controller to filter duplicates; we don't want to process + * repeated advertisements from the same device. + */ + disc_params.filter_duplicates = 1; + + /** + * Perform a passive scan. I.e., don't send follow-up scan requests to + * each advertiser. + */ + disc_params.passive = 1; + + /* Use defaults for the rest of the parameters. */ + disc_params.itvl = 0; + disc_params.window = 0; + disc_params.filter_policy = 0; + disc_params.limited = 0; + + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, + ble_spp_client_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Error initiating GAP discovery procedure; rc=%d\n", + rc); + } +} +``` + +The function `ble_spp_client_scan()` initiates the General Discovery Procedure for scanning nearby BLE devices. The function starts by declaring several variables used in the scanning process. These variable include: + +* `own_addr_type`: A uint8_t variable that stores the type of address (public or random) that the device will use while scanning. +* `disc_params`: A struct of type `ble_gap_disc_params` that holds the parameters for the GAP (Generic Access Profile) discovery procedure. + +The function uses `ble_hs_id_infer_auto()` to determine the address type (public or random) that the device should use for scanning. The result is stored in the own_addr_type variable. + +Configure Discovery Parameters: The function configures the disc_params struct with the following settings: + +* `filter_duplicates`: Set to 1, indicating that the controller should filter out duplicate advertisements from the same device. This reduces unnecessary processing of repeated advertisements. +* `passive`: Set to 1, indicating that the scan will be a passive scan. In a passive scan, the scanning device only listens for advertisements without sending any follow-up scan requests to advertisers. It's used for general device discovery. + +The function sets some other parameters in the disc_params struct to their default values: + +* `itvl`: The scan interval is set to 0, using the default value. +* `window`: The scan window is set to 0, using the default value. +* `filter_policy`: The filter policy is set to 0, using the default value. +* `limited`: The limited discovery mode is set to 0, using the default value. + +The function then calls `ble_gap_disc()` to initiate the BLE scanning procedure. It passes the following parameters: + +* `own_addr_type`: The address type to use for scanning (determined earlier). +* `BLE_HS_FOREVER`: The duration for which the scan should continue (in this case, indefinitely). +* `&disc_params`: A pointer to the ble_gap_disc_params struct containing the scan parameters. +* `blecent_gap_event`: The callback function to handle the scan events (such as receiving advertisements from nearby devices). +* `NULL`: The argument for the callback context, which is not used in this example. + +If an error occurs during the initiation of the scanning procedure, the function prints an error message. + + +## ble_spp_client_gap_event + +The function `ble_spp_client_gap_event` is in responsible of managing various GAP (Generic Access Profile) events that arise during the BLE communication. + +The function employs a switch statement to manage diverse types of GAP events that can be received. + +* `BLE_GAP_EVENT_DISC`: This case is activated when a new advertisement report is detected during scanning. The function extracts the advertisement data using `ble_hs_adv_parse_fields` and then displays the advertisement fields using the print_adv_fields function. It subsequently verifies if the discovered device is of interest and attempts to establish a connection with it. + +* `BLE_GAP_EVENT_CONNECT`: This case is triggered when a new connection is established or when a connection attempt fails. If the Connection was established then the connection descriptor is initiated using the `ble_gap_conn_find()` method else advertisement is resumed. If the connection is successful, it displays the connection descriptor through `print_conn_desc` and stores the peer information. Additionally, it handles optional features such as BLE power control, vendor-specific commands, and security initiation. In the event of a connection attempt failure, it resumes scanning. + +* `BLE_GAP_EVENT_DISCONNECT`: This case is activated when a connection is terminated. It prints the reason for disconnection and the connection descriptor before removing information about the peer and resuming scanning. + +* `BLE_GAP_EVENT_DISC_COMPLETE`: This case is triggered upon the completion of the GAP discovery process. It displays the reason for the discovery's completion. + +* `BLE_GAP_EVENT_NOTIFY_RX`: This case is triggered when the Central device receives a notification or indication from the Peripheral device. It displays information about the received data. + +* `BLE_GAP_EVENT_MTU`: This case is activated when the Maximum Transmission Unit (MTU) is updated for a connection. It prints the new MTU value and related information. + + +## ble_spp_client_should_connect + +```c +static int +ble_spp_client_should_connect(const struct ble_gap_disc_desc *disc) +{ + struct ble_hs_adv_fields fields; + int rc; + int i; + + /* Check if device is already connected or not */ + for ( i = 0; i <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + if (memcmp(&connected_addr[i].val, disc->addr.val, PEER_ADDR_VAL_SIZE) == 0) { + MODLOG_DFLT(DEBUG, "Device already connected"); + return 0; + } + } + + /* The device has to be advertising connectability. */ + if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && + disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { + + return 0; + } + + rc = ble_hs_adv_parse_fields(&fields, disc->data, disc->length_data); + if (rc != 0) { + return 0; + } + + /* The device has to advertise support for the SPP + * service (0xABF0). + */ + for (i = 0; i < fields.num_uuids16; i++) { + if (ble_uuid_u16(&fields.uuids16[i].u) == GATT_SPP_SVC_UUID) { + return 1; + } + } + return 0; +} +``` + +This code defines a function `ble_spp_client_should_connect` responsible for determining whether the BLE client should connect to a discovered BLE device. Here's an explanation of its functionality: + +1. **Device Connection Check**: It first checks if the device is already connected by comparing the device's address (`disc->addr.val`) with the addresses of connected devices stored in the `connected_addr` array. If a match is found, it logs a message and returns 0, indicating that the device should not be connected again. + +2. **Advertisement Type Check**: It checks the type of advertisement. The function expects the device to be advertising in either "ADV_IND" (undirected advertising) or "DIR_IND" (directed advertising) mode. If the advertisement type is different, it returns 0, indicating that the device should not be connected. + +3. **Advertisement Data Parsing**: The function then parses the advertisement data using the `ble_hs_adv_parse_fields` function to extract information about the advertised services and characteristics. + +4. **SPP Service Check**: It checks if the device advertises support for the SPP service by iterating through the list of 16-bit UUIDs (`fields.uuids16`) present in the advertisement data. If it finds a match with the SPP service UUID (0xABF0), it returns 1, indicating that the device should be connected. + +In summary, this function checks if a discovered BLE device is eligible for connection based on whether it's already connected, the type of advertisement, and if it advertises support for the SPP service. It returns 1 if the device is eligible for connection and 0 otherwise. + + +## ble_spp_client_connect_if_interesting + +```c +static void +ble_spp_client_connect_if_interesting(const struct ble_gap_disc_desc *disc) +{ + uint8_t own_addr_type; + int rc; + + /* Don't do anything if we don't care about this advertiser. */ + if (!ble_spp_client_should_connect(disc)) { + return; + } + + /* Scanning must be stopped before a connection can be initiated. */ + rc = ble_gap_disc_cancel(); + if (rc != 0) { + MODLOG_DFLT(DEBUG, "Failed to cancel scan; rc=%d\n", rc); + return; + } + + /* Figure out address to use for connect (no privacy for now) */ + rc = ble_hs_id_infer_auto(0, &own_addr_type); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); + return; + } + + /* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for + * timeout. + */ + + rc = ble_gap_connect(own_addr_type, &disc->addr, 30000, NULL, + ble_spp_client_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d " + "addr=%s; rc=%d\n", + disc->addr.type, addr_str(disc->addr.val), rc); + return; + } +} +``` + +This function, `ble_spp_client_connect_if_interesting` decides whether to connect to a BLE device based on its advertisement. Here's an explanation of what it does: + +1. It takes as input a `struct ble_gap_disc_desc` called `disc`, which represents an advertisement from a nearby BLE device. + +2. It checks if the advertisement indicates support for the intended service (in this case, the SPP service) and proceeds to initiate connection, else rejects. + +3. If the advertisement is found to be advertising the SPP service, it cancels the ongoing BLE scanning process using `ble_gap_disc_cancel`. This is necessary because you can't initiate a connection while scanning. + +4. It determines the address type (`own_addr_type`) to be used for the connection, typically with no privacy considerations for now. + +5. Finally, it attempts to establish a connection with the advertiser using `ble_gap_connect`. It specifies a timeout of 30 seconds (30000 ms) for the connection attempt. If the connection attempt fails, it logs an error message. + + +## ble_spp_client_on_disc_complete + +```c +static void +ble_spp_client_on_disc_complete(const struct peer *peer, int status, void *arg) +{ + if (status != 0) { + /* Service discovery failed. Terminate the connection. */ + MODLOG_DFLT(ERROR, "Error: Service discovery failed; status=%d " + "conn_handle=%d\n", status, peer->conn_handle); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return; + } + + /* Service discovery has completed successfully. Now we have a complete + * list of services, characteristics, and descriptors that the peer + * supports. + */ + MODLOG_DFLT(INFO, "Service discovery complete; status=%d " + "conn_handle=%d\n", status, peer->conn_handle); + + ble_spp_client_set_handle(peer); +#if CONFIG_BT_NIMBLE_MAX_CONNECTIONS > 1 + ble_spp_client_scan(); +#endif +} +``` + +In this code snippet, a function named `ble_spp_client_on_disc_complete` is defined, which is a callback function called when the service discovery of a BLE peer device is completed. Here's a breakdown of what this function does: + +1. It takes three parameters: + - `peer`: A pointer to the BLE peer structure representing the connected device. + - `status`: An integer indicating the status of the service discovery operation. A non-zero value typically indicates a failure, while a value of 0 signifies success. + - `arg`: A pointer to an optional user-defined argument (not used in this function). + +2. If the `status` is not zero, it means that the service discovery has failed. In this case, the function logs an error message using the `MODLOG_DFLT` macro, indicating the failure and including the `status` and connection handle (`conn_handle`) of the peer device. + +3. If the service discovery is successful (i.e., `status` is zero), the function logs an informational message indicating that the service discovery is complete, again including the `status` and `conn_handle`. + +4. After a successful service discovery, the `ble_spp_client_set_handle` function is called to set the attribute handle for the peer device. This handle is essential for subsequent BLE operations. + +5. Finally, in cases where the application supports multiple connections (`CONFIG_BT_NIMBLE_MAX_CONNECTIONS > 1`), the function `ble_spp_client_scan` is called to initiate scanning for additional BLE devices. This allows the application to connect to multiple devices concurrently. + +In summary, this function handles the completion of service discovery for a BLE peer device, taking appropriate actions based on the success or failure of the operation and optionally initiating scanning for more devices when applicable. + + +## Conclusion + +In this tutorial, we have explored a BLE Serial Port Profile (SPP) client using the NimBLE stack. We started by setting up the NimBLE stack and initializing the necessary components. Then, we implemented the client's functionality, including scanning for nearby BLE devices advertising the SPP service, establishing connections, and handling data communication. + +**Key Takeaways**: + +- **Initialization**: Initialize the NimBLE stack and set up a BLE SPP client application. +- **Scanning**: Scan for nearby BLE devices and filter those advertising the SPP service. +- **Service Discovery**: Establish connections with discovered devices and perform service discovery. +- **Communication**: Handle data communication over the BLE connection, emulating a serial port. + + + From aa4783519a5e37043ea54d6cf08593048a46bc47 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Wed, 20 Sep 2023 09:58:10 +0530 Subject: [PATCH 007/142] feat(esp_hw_support): Add esp_crypto_lock layer for esp32c2 --- .../include/soc/esp32c2/esp_crypto_lock.h | 27 +++++++++++++++++++ .../port/esp32c2/CMakeLists.txt | 3 ++- .../port/esp32c2/esp_crypto_lock.c | 26 ++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 components/esp_hw_support/include/soc/esp32c2/esp_crypto_lock.h create mode 100644 components/esp_hw_support/port/esp32c2/esp_crypto_lock.c diff --git a/components/esp_hw_support/include/soc/esp32c2/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32c2/esp_crypto_lock.h new file mode 100644 index 000000000000..09d4f295f8c8 --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32c2/esp_crypto_lock.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Acquire lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_acquire(void); + +/** + * @brief Release lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_release(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32c2/CMakeLists.txt b/components/esp_hw_support/port/esp32c2/CMakeLists.txt index d0774a50297d..482f65e4f4db 100644 --- a/components/esp_hw_support/port/esp32c2/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c2/CMakeLists.txt @@ -7,7 +7,8 @@ set(srcs "rtc_clk_init.c" if(NOT BOOTLOADER_BUILD) - list(APPEND srcs "sar_periph_ctrl.c") + list(APPEND srcs "esp_crypto_lock.c" + "sar_periph_ctrl.c") endif() diff --git a/components/esp_hw_support/port/esp32c2/esp_crypto_lock.c b/components/esp_hw_support/port/esp32c2/esp_crypto_lock.c new file mode 100644 index 000000000000..53a2500a4719 --- /dev/null +++ b/components/esp_hw_support/port/esp32c2/esp_crypto_lock.c @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "esp_crypto_lock.h" + +/* Lock overview: +ECC: independent +*/ + +/* Lock for ECC peripheral */ +static _lock_t s_crypto_ecc_lock; + +void esp_crypto_ecc_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecc_lock); +} + +void esp_crypto_ecc_lock_release(void) +{ + _lock_release(&s_crypto_ecc_lock); +} From 6a7caa7b8ea79b0b40389fdc75f25c67e897eed8 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Mon, 18 Sep 2023 16:30:42 +0530 Subject: [PATCH 008/142] feat(esp_hw_support): Added locking mechanism for the ECDSA and ECC peripheral --- .../include/soc/esp32c6/esp_crypto_lock.h | 14 +++++++- .../include/soc/esp32h2/esp_crypto_lock.h | 28 ++++++++++++++++ .../include/soc/esp32p4/esp_crypto_lock.h | 28 ++++++++++++++++ .../port/esp32c6/esp_crypto_lock.c | 16 +++++++++- .../port/esp32h2/esp_crypto_lock.c | 32 +++++++++++++++++++ .../port/esp32p4/esp_crypto_lock.c | 32 +++++++++++++++++++ components/mbedtls/port/ecc/esp_ecc.c | 9 +++--- components/mbedtls/port/ecdsa/ecdsa_alt.c | 7 ++-- 8 files changed, 155 insertions(+), 11 deletions(-) diff --git a/components/esp_hw_support/include/soc/esp32c6/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32c6/esp_crypto_lock.h index 67a08741b51d..5b5bf5412892 100644 --- a/components/esp_hw_support/include/soc/esp32c6/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32c6/esp_crypto_lock.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -63,6 +63,18 @@ void esp_crypto_mpi_lock_acquire(void); */ void esp_crypto_mpi_lock_release(void); +/** + * @brief Acquire lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_acquire(void); + +/** + * @brief Release lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_release(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h index c768bd737720..6855caae231d 100644 --- a/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h @@ -63,6 +63,34 @@ void esp_crypto_mpi_lock_acquire(void); */ void esp_crypto_mpi_lock_release(void); + +/** + * @brief Acquire lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_acquire(void); + +/** + * @brief Release lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_release(void); + + +/** + * @brief Acquire lock for ECDSA cryptography peripheral + * + * Internally also locks the ECC and MPI peripheral, as the ECDSA depends on these peripherals + */ +void esp_crypto_ecdsa_lock_acquire(void); + +/** + * @brief Release lock for ECDSA cryptography peripheral + * + * Internally also releases the ECC and MPI peripheral, as the ECDSA depends on these peripherals + */ +void esp_crypto_ecdsa_lock_release(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.h index c768bd737720..6855caae231d 100644 --- a/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.h @@ -63,6 +63,34 @@ void esp_crypto_mpi_lock_acquire(void); */ void esp_crypto_mpi_lock_release(void); + +/** + * @brief Acquire lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_acquire(void); + +/** + * @brief Release lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_release(void); + + +/** + * @brief Acquire lock for ECDSA cryptography peripheral + * + * Internally also locks the ECC and MPI peripheral, as the ECDSA depends on these peripherals + */ +void esp_crypto_ecdsa_lock_acquire(void); + +/** + * @brief Release lock for ECDSA cryptography peripheral + * + * Internally also releases the ECC and MPI peripheral, as the ECDSA depends on these peripherals + */ +void esp_crypto_ecdsa_lock_release(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32c6/esp_crypto_lock.c b/components/esp_hw_support/port/esp32c6/esp_crypto_lock.c index 34f307b54c8c..4f020502940f 100644 --- a/components/esp_hw_support/port/esp32c6/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32c6/esp_crypto_lock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +12,7 @@ SHA: peripheral independent, but DMA is shared with AES AES: peripheral independent, but DMA is shared with SHA MPI/RSA: independent +ECC: independent HMAC: needs SHA DS: needs HMAC (which needs SHA), AES and MPI */ @@ -28,6 +29,9 @@ static _lock_t s_crypto_mpi_lock; /* Single lock for SHA and AES, sharing a reserved GDMA channel */ static _lock_t s_crypto_sha_aes_lock; +/* Lock for ECC peripheral */ +static _lock_t s_crypto_ecc_lock; + void esp_crypto_hmac_lock_acquire(void) { _lock_acquire(&s_crypto_hmac_lock); @@ -73,3 +77,13 @@ void esp_crypto_mpi_lock_release(void) { _lock_release(&s_crypto_mpi_lock); } + +void esp_crypto_ecc_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecc_lock); +} + +void esp_crypto_ecc_lock_release(void) +{ + _lock_release(&s_crypto_ecc_lock); +} diff --git a/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c b/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c index 3936a75b7670..209866fe4f4c 100644 --- a/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c @@ -12,8 +12,10 @@ SHA: peripheral independent, but DMA is shared with AES AES: peripheral independent, but DMA is shared with SHA MPI/RSA: independent +ECC: independent HMAC: needs SHA DS: needs HMAC (which needs SHA), AES and MPI +ECDSA: needs ECC and MPI */ /* Lock for DS peripheral */ @@ -28,6 +30,12 @@ static _lock_t s_crypto_mpi_lock; /* Single lock for SHA and AES, sharing a reserved GDMA channel */ static _lock_t s_crypto_sha_aes_lock; +/* Lock for ECC peripheral */ +static _lock_t s_crypto_ecc_lock; + +/* Lock for ECDSA peripheral */ +static _lock_t s_crypto_ecdsa_lock; + void esp_crypto_hmac_lock_acquire(void) { _lock_acquire(&s_crypto_hmac_lock); @@ -73,3 +81,27 @@ void esp_crypto_mpi_lock_release(void) { _lock_release(&s_crypto_mpi_lock); } + +void esp_crypto_ecc_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecc_lock); +} + +void esp_crypto_ecc_lock_release(void) +{ + _lock_release(&s_crypto_ecc_lock); +} + +void esp_crypto_ecdsa_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecdsa_lock); + esp_crypto_ecc_lock_acquire(); + esp_crypto_mpi_lock_acquire(); +} + +void esp_crypto_ecdsa_lock_release(void) +{ + esp_crypto_mpi_lock_release(); + esp_crypto_ecc_lock_release(); + _lock_release(&s_crypto_ecdsa_lock); +} diff --git a/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c b/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c index 04d6df1dc950..fbeee00aa96d 100644 --- a/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c @@ -12,8 +12,10 @@ SHA: peripheral independent, but DMA is shared with AES AES: peripheral independent, but DMA is shared with SHA MPI/RSA: independent +ECC: independent HMAC: needs SHA DS: needs HMAC (which needs SHA), AES and MPI +ECDSA: needs ECC and MPI */ /* Lock for DS peripheral */ @@ -28,6 +30,12 @@ static _lock_t s_crypto_mpi_lock; /* Single lock for SHA and AES, sharing a reserved GDMA channel */ static _lock_t s_crypto_sha_aes_lock; +/* Lock for ECC peripheral */ +static _lock_t s_crypto_ecc_lock; + +/* Lock for ECDSA peripheral */ +static _lock_t s_crypto_ecdsa_lock; + void esp_crypto_hmac_lock_acquire(void) { _lock_acquire(&s_crypto_hmac_lock); @@ -73,3 +81,27 @@ void esp_crypto_mpi_lock_release(void) { _lock_release(&s_crypto_mpi_lock); } + +void esp_crypto_ecc_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecc_lock); +} + +void esp_crypto_ecc_lock_release(void) +{ + _lock_release(&s_crypto_ecc_lock); +} + +void esp_crypto_ecdsa_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecdsa_lock); + esp_crypto_ecc_lock_acquire(); + esp_crypto_mpi_lock_acquire(); +} + +void esp_crypto_ecdsa_lock_release(void) +{ + esp_crypto_mpi_lock_release(); + esp_crypto_ecc_lock_release(); + _lock_release(&s_crypto_ecdsa_lock); +} diff --git a/components/mbedtls/port/ecc/esp_ecc.c b/components/mbedtls/port/ecc/esp_ecc.c index a9100b7e0d9b..939f0070ff88 100644 --- a/components/mbedtls/port/ecc/esp_ecc.c +++ b/components/mbedtls/port/ecc/esp_ecc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,15 +7,14 @@ #include #include +#include "esp_crypto_lock.h" #include "esp_private/periph_ctrl.h" #include "ecc_impl.h" #include "hal/ecc_hal.h" -static _lock_t s_crypto_ecc_lock; - static void esp_ecc_acquire_hardware(void) { - _lock_acquire(&s_crypto_ecc_lock); + esp_crypto_ecc_lock_acquire(); periph_module_enable(PERIPH_ECC_MODULE); } @@ -24,7 +23,7 @@ static void esp_ecc_release_hardware(void) { periph_module_disable(PERIPH_ECC_MODULE); - _lock_release(&s_crypto_ecc_lock); + esp_crypto_ecc_lock_release(); } int esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_point_t *result, bool verify_first) diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index 7a89613902b8..62272429f60a 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -5,6 +5,7 @@ */ #include #include "hal/ecdsa_hal.h" +#include "esp_crypto_lock.h" #include "esp_efuse.h" #include "mbedtls/error.h" #include "mbedtls/ecdsa.h" @@ -19,11 +20,9 @@ __attribute__((unused)) static const char *TAG = "ecdsa_alt"; -static _lock_t s_crypto_ecdsa_lock; - static void esp_ecdsa_acquire_hardware(void) { - _lock_acquire(&s_crypto_ecdsa_lock); + esp_crypto_ecdsa_lock_acquire(); periph_module_enable(PERIPH_ECDSA_MODULE); } @@ -32,7 +31,7 @@ static void esp_ecdsa_release_hardware(void) { periph_module_disable(PERIPH_ECDSA_MODULE); - _lock_release(&s_crypto_ecdsa_lock); + esp_crypto_ecdsa_lock_release(); } static void ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) From 5e08ac606c6b56e0ab3a48ca1fb41484494be17d Mon Sep 17 00:00:00 2001 From: xiaqilin Date: Wed, 20 Sep 2023 19:23:36 +0800 Subject: [PATCH 009/142] feat(ieee802154): update ieee802154 sleep logic and support modem sleep --- components/esp_phy/src/btbb_init.c | 8 +-- .../ieee802154/driver/esp_ieee802154_dev.c | 49 +++++++++++++------ components/ieee802154/esp_ieee802154.c | 10 ---- .../ieee802154/include/esp_ieee802154.h | 10 ---- .../src/port/esp_openthread_sleep.c | 4 +- .../main/esp_ot_sleepy_device_config.h | 3 +- 6 files changed, 40 insertions(+), 44 deletions(-) diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index 4a1841cfda4c..5939ec0e28d6 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -22,11 +22,11 @@ static uint8_t s_btbb_access_ref = 0; #include "btbb_retention_reg.h" static const char* TAG = "btbb_init"; -#if SOC_PM_RETENTION_HAS_CLOCK_BUG -#define BTBB_LINK_OWNER ENTRY(3) -#else +// #if SOC_PM_RETENTION_HAS_CLOCK_BUG +// #define BTBB_LINK_OWNER ENTRY(3) +// #else #define BTBB_LINK_OWNER ENTRY(0) | ENTRY(2) -#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG +// #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG static esp_err_t btbb_sleep_retention_init(void) { diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index 5d93f1895382..c5866fe2d10a 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -30,6 +30,12 @@ #include "esp_pm.h" #include "esp_private/esp_clk.h" #include "esp_private/sleep_retention.h" +static bool g_sleep_rf = false; +// #if SOC_PM_RETENTION_HAS_CLOCK_BUG +// #define BTBB_LINK_OWNER ENTRY(3) +// #else +#define IEEE802154_LINK_OWNER ENTRY(0) | ENTRY(2) +// #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG #endif #define CCA_DETECTION_TIME 8 @@ -673,6 +679,8 @@ IEEE802154_STATIC void tx_init(const uint8_t *frame) esp_err_t ieee802154_transmit(const uint8_t *frame, bool cca) { + ieee802154_wakeup(); + ieee802154_enter_critical(); tx_init(frame); @@ -700,6 +708,9 @@ esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time) { uint32_t tx_target_time; uint32_t current_time; + + ieee802154_wakeup(); + tx_init(frame); IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX_AT); if (cca) { @@ -741,6 +752,7 @@ esp_err_t ieee802154_receive(void) // already in rx state, don't abort current rx operation return ESP_OK; } + ieee802154_wakeup(); ieee802154_enter_critical(); rx_init(); @@ -753,7 +765,7 @@ esp_err_t ieee802154_receive_at(uint32_t time) { uint32_t rx_target_time = time - IEEE802154_RX_RAMPUP_TIME_US; uint32_t current_time; - + ieee802154_wakeup(); rx_init(); IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_RX_AT); set_next_rx_buffer(); @@ -773,7 +785,7 @@ static esp_err_t ieee802154_sleep_init(void) #if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE #define N_REGS_IEEE802154() (((IEEE802154_MAC_DATE_REG - IEEE802154_REG_BASE) / 4) + 1) const static sleep_retention_entries_config_t ieee802154_mac_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_IEEE802154_LINK(0x00), IEEE802154_REG_BASE, IEEE802154_REG_BASE, N_REGS_IEEE802154(), 0, 0), .owner = ENTRY(3) }, + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_IEEE802154_LINK(0x00), IEEE802154_REG_BASE, IEEE802154_REG_BASE, N_REGS_IEEE802154(), 0, 0), .owner = IEEE802154_LINK_OWNER }, }; err = sleep_retention_entries_create(ieee802154_mac_regs_retention, ARRAY_SIZE(ieee802154_mac_regs_retention), REGDMA_LINK_PRI_7, SLEEP_RETENTION_MODULE_802154_MAC); ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "failed to allocate memory for ieee802154 mac retention"); @@ -785,38 +797,41 @@ static esp_err_t ieee802154_sleep_init(void) IRAM_ATTR void ieee802154_enter_sleep(void) { #if CONFIG_FREERTOS_USE_TICKLESS_IDLE - esp_phy_disable(); -#if SOC_PM_RETENTION_HAS_CLOCK_BUG - sleep_retention_do_extra_retention(true);// backup -#endif - ieee802154_disable(); // IEEE802154 CLOCK Disable + if (g_sleep_rf == false) { + esp_phy_disable(); + g_sleep_rf = true; + } #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE } IRAM_ATTR void ieee802154_wakeup(void) { #if CONFIG_FREERTOS_USE_TICKLESS_IDLE - ieee802154_enable(); // IEEE802154 CLOCK Enable -#if SOC_PM_RETENTION_HAS_CLOCK_BUG - sleep_retention_do_extra_retention(false);// restore -#endif - esp_phy_enable(); + if (g_sleep_rf) { + esp_phy_enable(); + g_sleep_rf = false; + } #endif //CONFIG_FREERTOS_USE_TICKLESS_IDLE } esp_err_t ieee802154_sleep(void) { - ieee802154_enter_critical(); + if (ieee802154_get_state() != IEEE802154_STATE_SLEEP) { + ieee802154_enter_critical(); + stop_current_operation(); + ieee802154_set_state(IEEE802154_STATE_SLEEP); - stop_current_operation(); - ieee802154_set_state(IEEE802154_STATE_SLEEP); + ieee802154_exit_critical(); - ieee802154_exit_critical(); + ieee802154_enter_sleep(); // colse rf + } return ESP_OK; } esp_err_t ieee802154_energy_detect(uint32_t duration) { + ieee802154_wakeup(); + ieee802154_enter_critical(); stop_current_operation(); @@ -832,6 +847,8 @@ esp_err_t ieee802154_energy_detect(uint32_t duration) esp_err_t ieee802154_cca(void) { + ieee802154_wakeup(); + ieee802154_enter_critical(); stop_current_operation(); diff --git a/components/ieee802154/esp_ieee802154.c b/components/ieee802154/esp_ieee802154.c index 909faff77407..64aef9ecea16 100644 --- a/components/ieee802154/esp_ieee802154.c +++ b/components/ieee802154/esp_ieee802154.c @@ -334,16 +334,6 @@ uint8_t esp_ieee802154_get_recent_lqi(void) return ieee802154_get_recent_lqi(); } -void esp_ieee802154_enter_sleep(void) -{ - ieee802154_enter_sleep(); -} - -void esp_ieee802154_wakeup(void) -{ - ieee802154_wakeup(); -} - __attribute__((weak)) void esp_ieee802154_receive_done(uint8_t *data, esp_ieee802154_frame_info_t *frame_info) { diff --git a/components/ieee802154/include/esp_ieee802154.h b/components/ieee802154/include/esp_ieee802154.h index 22d3acb52dae..96de1a07758e 100644 --- a/components/ieee802154/include/esp_ieee802154.h +++ b/components/ieee802154/include/esp_ieee802154.h @@ -111,16 +111,6 @@ esp_ieee802154_state_t esp_ieee802154_get_state(void); */ esp_err_t esp_ieee802154_sleep(void); -/** - * @brief The IEEE 802.15.4 enter sleep. - */ -void esp_ieee802154_enter_sleep(void); - -/** - * @brief The IEEE 802.15.4 wakeup. - */ -void esp_ieee802154_wakeup(void); - /** * @brief Set the IEEE 802.15.4 Radio to receive state. * diff --git a/components/openthread/src/port/esp_openthread_sleep.c b/components/openthread/src/port/esp_openthread_sleep.c index fa6fdb3fcd3f..0077253eabd2 100644 --- a/components/openthread/src/port/esp_openthread_sleep.c +++ b/components/openthread/src/port/esp_openthread_sleep.c @@ -34,8 +34,7 @@ esp_err_t esp_openthread_sleep_init(void) void esp_openthread_sleep_process(void) { - if (esp_ieee802154_get_state() == ESP_IEEE802154_RADIO_SLEEP) { - esp_ieee802154_enter_sleep(); + if (s_ot_sleep == false && esp_ieee802154_get_state() == ESP_IEEE802154_RADIO_SLEEP) { esp_pm_lock_release(s_pm_lock); s_ot_sleep = true; } @@ -45,7 +44,6 @@ void esp_openthread_wakeup_process(void) { if (s_ot_sleep) { esp_pm_lock_acquire(s_pm_lock); - esp_ieee802154_wakeup(); s_ot_sleep = false; } } diff --git a/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h b/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h index d5b9383c06fa..cd4453383a15 100644 --- a/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h +++ b/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h @@ -25,6 +25,7 @@ } #endif +// When JIRA PM-3 fix, uart clock can autoswitch. #define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ @@ -38,7 +39,7 @@ .stop_bits = UART_STOP_BITS_1, \ .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ .rx_flow_ctrl_thresh = 0, \ - .source_clk = UART_SCLK_DEFAULT, \ + .source_clk = UART_SCLK_XTAL, \ }, \ .rx_pin = UART_PIN_NO_CHANGE, \ .tx_pin = UART_PIN_NO_CHANGE, \ From 9df70ceb226bff6e991e643ba8d2306371f31096 Mon Sep 17 00:00:00 2001 From: Liu Zhongwei Date: Tue, 12 Sep 2023 19:12:08 +0800 Subject: [PATCH 010/142] fix(spi_lcd_touch): LCD image source default from binary --- examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild b/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild index 8e30992953bb..cf4a5e392adb 100644 --- a/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild +++ b/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild @@ -70,7 +70,7 @@ menu "Example Configuration" choice EXAMPLE_LCD_IMAGE_SOURCE prompt "LCD image source from" - default EXAMPLE_LCD_IMAGE_FROM_FILE_SYSTEM + default EXAMPLE_LCD_IMAGE_FROM_EMBEDDED_BINARY help Select LCD image source From b4a173648aefd6ac04f7f156e60dd72718a4dac6 Mon Sep 17 00:00:00 2001 From: Liu Zhongwei Date: Wed, 20 Sep 2023 12:11:42 +0800 Subject: [PATCH 011/142] fix(nt35510_st7789): correct the word spelling --- components/esp_lcd/src/esp_lcd_panel_nt35510.c | 12 ++++++------ components/esp_lcd/src/esp_lcd_panel_st7789.c | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/components/esp_lcd/src/esp_lcd_panel_nt35510.c b/components/esp_lcd/src/esp_lcd_panel_nt35510.c index 5f3d596513f8..778c0eac8a8f 100644 --- a/components/esp_lcd/src/esp_lcd_panel_nt35510.c +++ b/components/esp_lcd/src/esp_lcd_panel_nt35510.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -47,7 +47,7 @@ typedef struct { int y_gap; uint8_t fb_bits_per_pixel; uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - uint8_t colmod_cal; // save surrent value of LCD_CMD_COLMOD register + uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register } nt35510_panel_t; esp_err_t @@ -86,16 +86,16 @@ esp_lcd_new_panel_nt35510(const esp_lcd_panel_io_handle_t io, const esp_lcd_pane uint8_t fb_bits_per_pixel = 0; switch (panel_dev_config->bits_per_pixel) { case 16: // RGB565 - nt35510->colmod_cal = 0x55; + nt35510->colmod_val = 0x55; fb_bits_per_pixel = 16; break; case 18: // RGB666 - nt35510->colmod_cal = 0x66; + nt35510->colmod_val = 0x66; // each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel fb_bits_per_pixel = 24; break; case 24: // RGB888 - nt35510->colmod_cal = 0x77; + nt35510->colmod_val = 0x77; fb_bits_per_pixel = 24; break; default: @@ -176,7 +176,7 @@ static esp_err_t panel_nt35510_init(esp_lcd_panel_t *panel) nt35510->madctl_val, }, 2), TAG, "io tx param LCD_CMD_MADCTL failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD << 8, (uint16_t[]) { - nt35510->colmod_cal, + nt35510->colmod_val, }, 2), TAG, "io tx param LCD_CMD_COLMOD failed"); return ESP_OK; diff --git a/components/esp_lcd/src/esp_lcd_panel_st7789.c b/components/esp_lcd/src/esp_lcd_panel_st7789.c index eb98cb2deca7..fb3f7349f48a 100644 --- a/components/esp_lcd/src/esp_lcd_panel_st7789.c +++ b/components/esp_lcd/src/esp_lcd_panel_st7789.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -50,7 +50,7 @@ typedef struct { int y_gap; uint8_t fb_bits_per_pixel; uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - uint8_t colmod_cal; // save surrent value of LCD_CMD_COLMOD register + uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register uint8_t ramctl_val_1; uint8_t ramctl_val_2; } st7789_panel_t; @@ -91,11 +91,11 @@ esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel uint8_t fb_bits_per_pixel = 0; switch (panel_dev_config->bits_per_pixel) { case 16: // RGB565 - st7789->colmod_cal = 0x55; + st7789->colmod_val = 0x55; fb_bits_per_pixel = 16; break; case 18: // RGB666 - st7789->colmod_cal = 0x66; + st7789->colmod_val = 0x66; // each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel fb_bits_per_pixel = 24; break; @@ -183,7 +183,7 @@ static esp_err_t panel_st7789_init(esp_lcd_panel_t *panel) st7789->madctl_val, }, 1), TAG, "io tx param LCD_CMD_MADCTL failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) { - st7789->colmod_cal, + st7789->colmod_val, }, 1), TAG, "io tx param LCD_CMD_COLMOD failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, ST7789_CMD_RAMCTRL, (uint8_t[]) { st7789->ramctl_val_1, st7789->ramctl_val_2 From 7b176501e3e9c711869fbbce45aac0afb268391e Mon Sep 17 00:00:00 2001 From: cjin Date: Thu, 21 Sep 2023 11:30:49 +0800 Subject: [PATCH 012/142] feat(ble): update ble sleep logic for esp32h2 --- components/bt/controller/esp32h2/bt.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index d29822f90ca8..1336dd222c1a 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -40,12 +40,9 @@ #include "hci_uart.h" #include "bt_osi_mem.h" -#if SOC_PM_RETENTION_HAS_CLOCK_BUG -#include "esp_private/sleep_retention.h" -#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG - #if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_modem.h" +#include "esp_private/sleep_retention.h" #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_BLUEDROID_ENABLED @@ -447,6 +444,7 @@ void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src) case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (320 - 1)); + break; case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); @@ -474,9 +472,6 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) } #if CONFIG_FREERTOS_USE_TICKLESS_IDLE r_ble_rtc_wake_up_state_clr(); -#if SOC_PM_RETENTION_HAS_CLOCK_BUG - sleep_retention_do_extra_retention(true); -#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ esp_phy_disable(); #ifdef CONFIG_PM_ENABLE @@ -493,9 +488,6 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) #ifdef CONFIG_PM_ENABLE esp_pm_lock_acquire(s_pm_lock); r_ble_rtc_wake_up_state_clr(); -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG - sleep_retention_do_extra_retention(false); -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG */ #endif //CONFIG_PM_ENABLE esp_phy_enable(); s_ble_active = true; @@ -546,7 +538,7 @@ esp_err_t controller_sleep_init(void) } #if CONFIG_FREERTOS_USE_TICKLESS_IDLE /* Create a new regdma link for BLE related register restoration */ - rc = sleep_modem_ble_mac_modem_state_init(1); + rc = sleep_modem_ble_mac_modem_state_init(0); assert(rc == 0); esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); @@ -924,11 +916,6 @@ esp_err_t esp_bt_controller_disable(void) esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE s_ble_active = false; - } else { -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE - /* Avoid consecutive backup of register cause assertion */ - sleep_retention_module_deinit(); -#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE } ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; return ESP_OK; From 40996f804aec4ef1eefd34ead34bcef404361523 Mon Sep 17 00:00:00 2001 From: cjin Date: Thu, 21 Sep 2023 11:31:53 +0800 Subject: [PATCH 013/142] change: remove has clock bug macro for esp32h2 --- components/esp_phy/src/btbb_init.c | 8 ++++---- components/soc/esp32h2/include/soc/Kconfig.soc_caps.in | 4 ---- components/soc/esp32h2/include/soc/soc_caps.h | 1 - 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index 5939ec0e28d6..4a1841cfda4c 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -22,11 +22,11 @@ static uint8_t s_btbb_access_ref = 0; #include "btbb_retention_reg.h" static const char* TAG = "btbb_init"; -// #if SOC_PM_RETENTION_HAS_CLOCK_BUG -// #define BTBB_LINK_OWNER ENTRY(3) -// #else +#if SOC_PM_RETENTION_HAS_CLOCK_BUG +#define BTBB_LINK_OWNER ENTRY(3) +#else #define BTBB_LINK_OWNER ENTRY(0) | ENTRY(2) -// #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG +#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG static esp_err_t btbb_sleep_retention_init(void) { diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 11b7544a2c73..e80aec35f666 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1183,10 +1183,6 @@ config SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG bool default y -config SOC_PM_RETENTION_HAS_CLOCK_BUG - bool - default y - config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 4467ab10bf88..e2080e6c474b 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -487,7 +487,6 @@ #define SOC_PM_MODEM_RETENTION_BY_REGDMA (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Thu, 21 Sep 2023 15:11:55 +0800 Subject: [PATCH 014/142] fix(sleep): fix modem reject the deepsleep request --- components/esp_hw_support/sleep_modes.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 723a82d1fa96..e989dd2f0d35 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -666,10 +666,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m } #endif - /* Enable sleep reject for faster return from this function, - * in case the wakeup is already triggerred. - */ - uint32_t reject_triggers = (s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK) | sleep_modem_reject_triggers(); + uint32_t reject_triggers = s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK; + + if (!deep_sleep) { + /* Enable sleep reject for faster return from this function, + * in case the wakeup is already triggerred. + */ + reject_triggers |= sleep_modem_reject_triggers(); + } //Append some flags in addition to power domains uint32_t sleep_flags = pd_flags; From a4277c9be86a8200bbe2631b416ae72be8b6fc7d Mon Sep 17 00:00:00 2001 From: renpeiying Date: Tue, 22 Aug 2023 16:34:41 +0800 Subject: [PATCH 015/142] docs: Provide Chinese translation for 5 documents in api-reference/network --- docs/en/api-reference/network/esp_dpp.rst | 15 +-- docs/en/api-reference/network/esp_nan.rst | 12 +-- docs/en/api-reference/network/esp_netif.rst | 3 + .../network/esp_netif_driver.rst | 30 +++--- .../api-reference/network/esp_openthread.rst | 13 +-- .../api-reference/network/esp_smartconfig.rst | 8 +- docs/zh_CN/api-reference/network/esp_dpp.rst | 30 +++++- docs/zh_CN/api-reference/network/esp_nan.rst | 21 +++- .../zh_CN/api-reference/network/esp_netif.rst | 3 + .../network/esp_netif_driver.rst | 96 ++++++++++++++++++- .../api-reference/network/esp_openthread.rst | 33 ++++++- .../api-reference/network/esp_smartconfig.rst | 23 ++++- docs/zh_CN/api-reference/network/index.rst | 5 +- 13 files changed, 249 insertions(+), 43 deletions(-) diff --git a/docs/en/api-reference/network/esp_dpp.rst b/docs/en/api-reference/network/esp_dpp.rst index 7e8ebeebb0ee..d7f951cb3c4f 100644 --- a/docs/en/api-reference/network/esp_dpp.rst +++ b/docs/en/api-reference/network/esp_dpp.rst @@ -1,8 +1,11 @@ Wi-Fi Easy Connect\ :sup:`TM` (DPP) =================================== -Wi-Fi Easy Connect\ :sup:`TM`, also known as Device Provisioning Protocol (DPP) or Easy Connect, is a provisioning protocol certified by Wi-Fi Alliance. It is a secure and standardized provisioning protocol for configuration of Wi-Fi Devices. With Easy Connect adding a new device to a network is as simple as scanning a QR Code. This reduces complexity and enhances user experience while onboarding devices without UI like Smart Home and IoT products. Unlike old protocols like WiFi Protected Setup (WPS), Wi-Fi Easy Connect incorporates strong encryption through public key cryptography to ensure networks remain secure as new devices are added. -Easy Connect brings many benefits in the User Experience: +:link_to_translation:`zh_CN:[中文]` + +Wi-Fi Easy Connect\ :sup:`TM`, also known as Device Provisioning Protocol (DPP) or Easy Connect, is a provisioning protocol certified by Wi-Fi Alliance. It is a secure and standardized provisioning protocol for configuration of Wi-Fi Devices. With Easy Connect, adding a new device to a network is as simple as scanning a QR Code. This reduces complexity and enhances user experience while onboarding devices without UI like Smart Home and IoT products. Unlike old protocols like Wi-Fi Protected Setup (WPS), Wi-Fi Easy Connect in corporates strong encryption through public key cryptography to ensure networks remain secure as new devices are added. + +Easy Connect brings many benefits in the user experience: - Simple and intuitive to use; no lengthy instructions to follow for new device setup - No need to remember and enter passwords into the device being provisioned @@ -11,16 +14,16 @@ Easy Connect brings many benefits in the User Experience: Please refer to Wi-Fi Alliance's official page on `Easy Connect `_ for more information. -{IDF_TARGET_NAME} supports Enrollee mode of Easy Connect with QR Code as the provisioning method. A display is required to display this QR Code. Users can scan this QR Code using their capable device and provision the {IDF_TARGET_NAME} to their Wi-Fi network. The provisioning device needs to be connected to the AP which need not support Wi-Fi Easy Connect™. -Easy Connect is still an evolving protocol. Of known platforms that support the QR Code method are some Android smartphones with Android 10 or higher. To use Easy Connect no additional App needs to be installed on the supported smartphone. +{IDF_TARGET_NAME} supports Enrollee mode of Easy Connect with QR Code as the provisioning method. A display is required to display this QR Code. Users can scan this QR Code using their capable device and provision the {IDF_TARGET_NAME} to their Wi-Fi network. The provisioning device needs to be connected to the AP which need not support Wi-Fi Easy Connect\ :sup:`TM`. + +Easy Connect is still an evolving protocol. Of known platforms that support the QR Code method are some Android smartphones with Android 10 or higher. To use Easy Connect, no additional App needs to be installed on the supported smartphone. Application Example ------------------- Example on how to provision {IDF_TARGET_NAME} using a supported smartphone: :example:`wifi/wifi_easy_connect/dpp-enrollee`. - API Reference ------------- -.. include-build-file:: inc/esp_dpp.inc +.. include-build-file:: inc/esp_dpp.inc \ No newline at end of file diff --git a/docs/en/api-reference/network/esp_nan.rst b/docs/en/api-reference/network/esp_nan.rst index 631be8592a56..9f23cc514ab4 100644 --- a/docs/en/api-reference/network/esp_nan.rst +++ b/docs/en/api-reference/network/esp_nan.rst @@ -1,20 +1,20 @@ Wi-Fi Aware\ :sup:`TM` (NAN) =================================== -Wi-Fi Aware\ :sup:`TM` or NAN (Neighbor Awareness Networking) is a protocol that allows Wi-Fi devices to discover services in their proximity. Typically, location-based services are based on querying servers for information about the environment and the location knowledge is based on GPS or other location reckoning techniques. However NAN does not require real-time connection to servers, GPS or other geo-location, but instead uses direct device-to-device Wi-Fi to discover and exchange information. NAN scales effectively in dense Wi-Fi environments and complements the connectivity of Wi-Fi by providing information about people and services in the proximity. +:link_to_translation:`zh_CN:[中文]` -Multiple NAN devices which are in the vicinity form a NAN cluster which allows them to communicate with each other. Devices within a NAN cluster can advertise (Publish method) or look for (Subscribe method) services using NAN Service Discovery protocols. Matching of services is done by service name, once a match is found a device can either send a message or establish an IPv6 datapath with the peer. +Wi-Fi Aware\ :sup:`TM` or NAN (Neighbor Awareness Networking) is a protocol that allows Wi-Fi devices to discover services in their proximity. Typically, location-based services are based on querying servers for information about the environment and the location knowledge is based on GPS or other location reckoning techniques. However, NAN does not require real-time connection to servers, GPS or other geo-location, but instead uses direct device-to-device Wi-Fi to discover and exchange information. NAN scales effectively in dense Wi-Fi environments and complements the connectivity of Wi-Fi by providing information about people and services in the proximity. + +Multiple NAN devices which are in the vicinity form a NAN cluster which allows them to communicate with each other. Devices within a NAN cluster can advertise (Publish method) or look for (Subscribe method) services using NAN Service Discovery protocols. Matching of services is done by service name, once a match is found, a device can either send a message or establish an IPv6 Datapath with the peer. {IDF_TARGET_NAME} supports Wi-Fi Aware in standalone mode with support for both Service Discovery and Datapath. Wi-Fi Aware is still an evolving protocol. Please refer to Wi-Fi Alliance's official page on `Wi-Fi Aware `_ for more information. Many Android smartphones with Android 8 or higher support Wi-Fi Aware. Refer to Android's developer guide on Wi-Fi Aware `Wi-Fi Aware `_ for more information. Application Example ------------------- -A pair of examples for a Publisher-Subscriber use case: :example:`wifi/wifi_aware/nan_publisher` and :example:`wifi/wifi_aware/nan_subscriber`. -A user interactive console example to explore full functionality of Wi-Fi Aware: :example:`wifi/wifi_aware/nan_console`. -Please check the `README` for more details in respective example directories. +A pair of examples for a Publisher-Subscriber use case: :example:`wifi/wifi_aware/nan_publisher` and :example:`wifi/wifi_aware/nan_subscriber`. A user interactive console example to explore full functionality of Wi-Fi Aware: :example:`wifi/wifi_aware/nan_console`. Please check the `README` for more details in respective example directories. API Reference ------------- -.. include-build-file:: inc/esp_nan.inc +.. include-build-file:: inc/esp_nan.inc \ No newline at end of file diff --git a/docs/en/api-reference/network/esp_netif.rst b/docs/en/api-reference/network/esp_netif.rst index 38073ed54832..2ff9b9f3ff86 100644 --- a/docs/en/api-reference/network/esp_netif.rst +++ b/docs/en/api-reference/network/esp_netif.rst @@ -16,6 +16,9 @@ Some ESP-NETIF API functions are intended to be called by application code, for In many cases, applications do not need to call ESP-NETIF APIs directly as they are called by the default network event handlers. + +.. _esp-netif structure: + ESP-NETIF Architecture ---------------------- diff --git a/docs/en/api-reference/network/esp_netif_driver.rst b/docs/en/api-reference/network/esp_netif_driver.rst index bf5a307ad95b..a716325c7f02 100644 --- a/docs/en/api-reference/network/esp_netif_driver.rst +++ b/docs/en/api-reference/network/esp_netif_driver.rst @@ -1,21 +1,23 @@ ESP-NETIF Custom I/O Driver =========================== -This section outlines implementing a new I/O driver with esp-netif connection capabilities. +:link_to_translation:`zh_CN:[中文]` -By convention, the I/O driver has to register itself as an esp-netif driver, and thus holds a dependency on esp-netif component and is responsible for providing data path functions, post-attach callback and in most cases, also default event handlers to define network interface actions based on driver's lifecycle transitions. +This section outlines implementing a new I/O driver with ESP-NETIF connection capabilities. + +By convention, the I/O driver has to register itself as an ESP-NETIF driver, and thus holds a dependency on ESP-NETIF component and is responsible for providing data path functions, post-attach callback and in most cases, also default event handlers to define network interface actions based on driver's lifecycle transitions. Packet Input/Output ^^^^^^^^^^^^^^^^^^^ -As shown in the diagram, the following three API functions for the packet data path must be defined for connecting with esp-netif: +According to the diagram shown in the :ref:`esp-netif structure` part, the following three API functions for the packet data path must be defined for connecting with ESP-NETIF: * :cpp:func:`esp_netif_transmit()` * :cpp:func:`esp_netif_free_rx_buffer()` * :cpp:func:`esp_netif_receive()` -The first two functions for transmitting and freeing the rx buffer are provided as callbacks, i.e., they get called from esp-netif (and its underlying TCP/IP stack) and I/O driver provides their implementation. +The first two functions for transmitting and freeing the rx buffer are provided as callbacks, i.e., they get called from ESP-NETIF (and its underlying TCP/IP stack) and I/O driver provides their implementation. The receiving function on the other hand gets called from the I/O driver, so that the driver's code simply calls :cpp:func:`esp_netif_receive()` on a new data received event. @@ -23,18 +25,18 @@ The receiving function on the other hand gets called from the I/O driver, so tha Post Attach Callback ^^^^^^^^^^^^^^^^^^^^ -A final part of the network interface initialization consists of attaching the esp-netif instance to the I/O driver, by means of calling the following API: +A final part of the network interface initialization consists of attaching the ESP-NETIF instance to the I/O driver, by means of calling the following API: .. code:: c esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle); -It is assumed that the ``esp_netif_iodriver_handle`` is a pointer to driver's object, a struct derived from ``struct esp_netif_driver_base_s``, so that the first member of I/O driver structure must be this base structure with pointers to +It is assumed that the ``esp_netif_iodriver_handle`` is a pointer to driver's object, a struct derived from ``struct esp_netif_driver_base_s``, so that the first member of I/O driver structure must be this base structure with pointers to: * post-attach function callback -* related esp-netif instance +* related ESP-NETIF instance -As a consequence the I/O driver has to create an instance of the struct per below: +As a result, the I/O driver has to create an instance of the struct per below: .. code:: c @@ -45,7 +47,7 @@ As a consequence the I/O driver has to create an instance of the struct per belo with actual values of ``my_netif_driver_t::base.post_attach`` and the actual drivers handle ``my_netif_driver_t::h``. -So when the :cpp:func:`esp_netif_attach()` gets called from the initialization code, the post-attach callback from I/O driver's code gets executed to mutually register callbacks between esp-netif and I/O driver instances. Typically the driver is started as well in the post-attach callback. An example of a simple post-attach callback is outlined below: +So when the :cpp:func:`esp_netif_attach()` gets called from the initialization code, the post-attach callback from I/O driver's code gets executed to mutually register callbacks between ESP-NETIF and I/O driver instances. Typically the driver is started as well in the post-attach callback. An example of a simple post-attach callback is outlined below: .. code:: c @@ -67,7 +69,8 @@ So when the :cpp:func:`esp_netif_attach()` gets called from the initialization c Default Handlers ^^^^^^^^^^^^^^^^ -I/O drivers also typically provide default definitions of lifecycle behaviour of related network interfaces based on state transitions of I/O drivers. For example *driver start* ``->`` *network start*, etc. +I/O drivers also typically provide default definitions of lifecycle behavior of related network interfaces based on state transitions of I/O drivers. For example *driver start* ``->`` *network start*, etc. + An example of such a default handler is provided below: .. code:: c @@ -83,11 +86,10 @@ An example of such a default handler is provided below: Network Stack Connection ------------------------ -The packet data path functions for transmitting and freeing the rx buffer (defined in the I/O driver) are called from the esp-netif, specifically from its TCP/IP stack connecting layer. +The packet data path functions for transmitting and freeing the rx buffer (defined in the I/O driver) are called from the ESP-NETIF, specifically from its TCP/IP stack connecting layer. -Note, that ESP-IDF provides several network stack configurations for the most common network interfaces, such as for the WiFi station or Ethernet. -These configurations are defined in :component_file:`esp_netif/include/esp_netif_defaults.h` and should be sufficient for most network drivers. (In rare cases, expert users might want to define custom lwIP based interface layers; it is possible, but an explicit dependency to lwIP needs to be set) +Note that ESP-IDF provides several network stack configurations for the most common network interfaces, such as for the Wi-Fi station or Ethernet. These configurations are defined in :component_file:`esp_netif/include/esp_netif_defaults.h` and should be sufficient for most network drivers. In rare cases, expert users might want to define custom lwIP based interface layers; it is possible, but an explicit dependency to lwIP needs to be set. -The following API reference outlines these network stack interaction with the esp-netif: +The following API reference outlines these network stack interaction with the ESP-NETIF: .. include-build-file:: inc/esp_netif_net_stack.inc diff --git a/docs/en/api-reference/network/esp_openthread.rst b/docs/en/api-reference/network/esp_openthread.rst index f8da5316ba7a..e976c3e974af 100644 --- a/docs/en/api-reference/network/esp_openthread.rst +++ b/docs/en/api-reference/network/esp_openthread.rst @@ -1,26 +1,27 @@ Thread ========== +:link_to_translation:`zh_CN:[中文]` + Introduction ------------ -`Thread `_ is a IP-based mesh networking protocol. It is based on the 802.15.4 physical and MAC layer. +`Thread `_ is an IP-based mesh networking protocol. It is based on the 802.15.4 physical and MAC layer. 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_br`. -- The Thread radio co-processor :example:`openthread/ot_rcp`. +- The OpenThread interactive shell :example:`openthread/ot_cli` +- The Thread Border Router :example:`openthread/ot_br` +- The Thread Radio Co-Processor :example:`openthread/ot_rcp` API Reference ------------- -For manipulating the Thread network, the OpenThread API shall be used. -The OpenThread API docs can be found at the `OpenThread official website `_. +For manipulating the Thread network, the OpenThread API shall be used. The OpenThread API docs can be found at the `OpenThread API docs `_. ESP-IDF provides extra APIs for launching and managing the OpenThread stack, binding to network interfaces and border routing features. diff --git a/docs/en/api-reference/network/esp_smartconfig.rst b/docs/en/api-reference/network/esp_smartconfig.rst index 9d95a68fc0fe..a816f52e686a 100644 --- a/docs/en/api-reference/network/esp_smartconfig.rst +++ b/docs/en/api-reference/network/esp_smartconfig.rst @@ -1,7 +1,9 @@ SmartConfig =========== -The SmartConfig\ :sup:`TM` is a provisioning technology developed by TI to connect a new Wi-Fi device to a Wi-Fi network. It uses a mobile app to broadcast the network credentials from a smartphone, or a tablet, to an un-provisioned Wi-Fi device. +:link_to_translation:`zh_CN:[中文]` + +The SmartConfig\ :sup:`TM` is a provisioning technology developed by TI to connect a new Wi-Fi device to a Wi-Fi network. It uses a mobile application to broadcast the network credentials from a smartphone, or a tablet, to an un-provisioned Wi-Fi device. The advantage of this technology is that the device does not need to directly know SSID or password of an Access Point (AP). This information is provided using the smartphone. This is particularly important to headless device and systems, due to their lack of a user interface. @@ -11,10 +13,10 @@ If you are looking for other options to provision your {IDF_TARGET_NAME} devices Application Example ------------------- -Connect {IDF_TARGET_NAME} to target AP using SmartConfig: :example:`wifi/smart_config`. +Connect {IDF_TARGET_NAME} to the target AP using SmartConfig: :example:`wifi/smart_config`. API Reference ------------- -.. include-build-file:: inc/esp_smartconfig.inc +.. include-build-file:: inc/esp_smartconfig.inc \ No newline at end of file diff --git a/docs/zh_CN/api-reference/network/esp_dpp.rst b/docs/zh_CN/api-reference/network/esp_dpp.rst index 66b50a4e342b..6adba413db8d 100644 --- a/docs/zh_CN/api-reference/network/esp_dpp.rst +++ b/docs/zh_CN/api-reference/network/esp_dpp.rst @@ -1 +1,29 @@ -.. include:: ../../../en/api-reference/network/esp_dpp.rst +Wi-Fi Easy Connect\ :sup:`TM` (DPP) +=================================== + +:link_to_translation:`en:[English]` + +Wi-Fi Easy Connect\ :sup:`TM` 是 Wi-Fi Alliance 认证的配网协议,也称为设备配网协议 (DPP) 或 Easy Connect,是一种安全和标准化的 Wi-Fi 设备配网协议。使用 Easy Connect 将新设备添加入网就像扫描二维码一样简单,特别是对于没有 UI 的智能家居和物联网产品而言,大大降低了联网复杂性,加强了的用户体验。与旧的协议如 Wi-Fi Protected Setup (WPS) 等旧协议相比,Wi-Fi Easy Connect 的公钥加密技术额外确保了添加新设备时的网络安全。 + +Easy Connect 从以下几个方面改善了用户体验: + + - 操作简单直观,设置新设备时无需阅读冗长的指南 + - 无需记住需配网设备的密码或输入密码 + - 支持电子/打印的二维码以及其他人类可读的字符串 + - 同时支持 WPA2 和 WPA3 网络 + +如需了解更多信息,请参考 Wi-Fi Alliance 的官方介绍:`Easy Connect `_。 + +{IDF_TARGET_NAME} 支持 Easy Connect 的二维码配网模式,用户需要使用显示器显示二维码,随后使用兼容的设备扫描此二维码,并将 {IDF_TARGET_NAME} 添加到自己的 Wi-Fi 网络中。此兼容设备需连接到无需支持 Wi-Fi Easy Connect\ :sup:`TM` 的 AP 上。 + +Easy Connect 协议仍在不断发展。目前已知支持二维码的平台为部分运行 Android 10 及更高系统版本的 Android 智能手机等。使用 Easy Connect 时,无需在智能手机上安装额外的应用程序。 + +应用示例 +------------------- + +如需了解使用智能手机配置 {IDF_TARGET_NAME} 的示例,请前往 :example:`wifi/wifi_easy_connect/dpp-enrollee`。 + +API 参考 +------------- + +.. include-build-file:: inc/esp_dpp.inc \ No newline at end of file diff --git a/docs/zh_CN/api-reference/network/esp_nan.rst b/docs/zh_CN/api-reference/network/esp_nan.rst index 5a3c60d3197e..53f3d4c93284 100644 --- a/docs/zh_CN/api-reference/network/esp_nan.rst +++ b/docs/zh_CN/api-reference/network/esp_nan.rst @@ -1 +1,20 @@ -.. include:: ../../../en/api-reference/network/esp_nan.rst +Wi-Fi Aware\ :sup:`TM` (NAN) +=================================== + +:link_to_translation:`en:[English]` + +Wi-Fi Aware\ :sup:`TM`,也可称为 NAN (Neighbor Awareness Networking) 协议,其支持 Wi-Fi 设备发现附近的其他服务。通常情况下,基于位置的服务需通过服务器查询环境信息,并通过 GPS 或其他位置推算技术获取定位。不过,NAN 无需与服务器、GPS 或其他地理位置服务保持实时连接,即可支持设备之间通过 Wi-Fi 直接连接来交换信息。NAN 能够在 Wi-Fi 密集的环境中高效扩展,并通过提供附近人员和服务的信息来完善 Wi-Fi 连接性。 + +多个邻近的 NAN 设备组成一个 NAN 集群,集群中的设备能够相互通信。NAN 设备还可通过 NAN 服务发现协议,通过发布或订阅功能,在所处集群内提供或查找服务。通过服务名称可以完成服务匹配,一旦找到匹配,设备就可以发送信息,或与匹配到的设备间建立 IPv6 数据路径。 + +{IDF_TARGET_NAME} 支持独立模式下的 Wi-Fi Aware,同时支持服务发现协议和数据路径。Wi-Fi Aware 协议仍在改进中,如需了解更多信息,请前往 Wi-Fi Alliance 官网的 `Wi-Fi Aware `_ 页面。大多数 Android 8 及更高版本的 Android 智能手机都支持 Wi-Fi Aware。如需了解更多信息,请参阅 Android 的开发者指南 `Wi-Fi Aware `_。 + +应用示例 +------------------- + +如需查看发布者和订阅者示例,请前往 :example:`wifi/wifi_aware/nan_publisher` 和 :example:`wifi/wifi_aware/nan_subscriber`。如需探索 Wi-Fi Aware 的全部功能,请参考用户交互界面控制台示例 :example:`wifi/wifi_aware/nan_console`。如需了解更多信息,请参考对应示例目录中的 `README` 文档。 + +API 参考 +------------- + +.. include-build-file:: inc/esp_nan.inc \ No newline at end of file diff --git a/docs/zh_CN/api-reference/network/esp_netif.rst b/docs/zh_CN/api-reference/network/esp_netif.rst index 44f494cec219..3eb9bfe3e879 100644 --- a/docs/zh_CN/api-reference/network/esp_netif.rst +++ b/docs/zh_CN/api-reference/network/esp_netif.rst @@ -16,6 +16,9 @@ ESP-IDF 支持实现了 BSD API 的自定义 TCP/IP 协议栈。有关不使用 应用程序通常无需直接调用 ESP-NETIF 的 API,它们会由默认网络事件句柄调用。 + +.. _esp-netif structure: + ESP-NETIF 架构 ---------------------- diff --git a/docs/zh_CN/api-reference/network/esp_netif_driver.rst b/docs/zh_CN/api-reference/network/esp_netif_driver.rst index 127e5dcce74e..ddcab047acee 100644 --- a/docs/zh_CN/api-reference/network/esp_netif_driver.rst +++ b/docs/zh_CN/api-reference/network/esp_netif_driver.rst @@ -1 +1,95 @@ -.. include:: ../../../en/api-reference/network/esp_netif_driver.rst +ESP-NETIF 自定义 I/O 驱动程序 +=============================== + +:link_to_translation:`en:[English]` + +本节概述了如何配置具有 ESP-NETIF 连接功能的新 I/O 驱动程序。 + +通常情况下,I/O 驱动程序须注册为 ESP-NETIF 驱动程序。因此,它依赖于 ESP-NETIF 组件,并负责提供数据路径函数、后附回调函数,并在多数情况下用于设置默认事件处理程序,根据驱动程序的生命周期转换来定义网络接口操作。 + + +数据包 Input/Output +^^^^^^^^^^^^^^^^^^^^^^^ + +根据 :ref:`esp-netif structure` 章节提供的图表可以看出,须定义以下三个数据路径函数 API 以连接 ESP-NETIF: + +* :cpp:func:`esp_netif_transmit()` +* :cpp:func:`esp_netif_free_rx_buffer()` +* :cpp:func:`esp_netif_receive()` + +前两个函数可以传输和释放 RX 缓冲区,用作回调。它们由 ESP-NETIF(及其底层 TCP/IP 堆栈)调用,并由 I/O 驱动实现。 + +另一方面,接收函数由 I/O 驱动程序调用,因此驱动的代码只需在接收到新数据时调用 :cpp:func:`esp_netif_receive()` 函数。 + + +后附回调 +^^^^^^^^^^^^^^^^^^^^ + +网络接口初始化的最后一步是调用以下 API,将 ESP-NETIF 实例附加到 I/O 驱动程序上: + +.. code:: c + + esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle); + +假设 ``esp_netif_iodriver_handle`` 是指向驱动程序对象的指针,该对象是从 ``struct esp_netif_driver_base_s`` 衍生的结构体,那么 I/O 驱动结构体的第一个成员必须是此基础结构,并指向: + +* 后附函数回调 +* 相关的 ESP-NETIF 实例 + +因此,I/O 驱动程序须创建以下结构体的实例: + +.. code:: c + + typedef struct my_netif_driver_s { + esp_netif_driver_base_t base; /*!< 保留基本结构体作为 esp-netif 驱动 */ + driver_impl *h; /*!< 驱动实现 */ + } my_netif_driver_t; + +此实例中包含 ``my_netif_driver_t::base.post_attach`` 的真实值和实际的驱动处理程序 ``my_netif_driver_t::h``。 + +从初始化代码调用 :cpp:func:`esp_netif_attach()` 时,将执行 I/O 驱动程序代码的后附回调,以在 ESP-NETIF 和 I/O 驱动程序实例之间相互注册回调。通常,后附回调中也会启动驱动程序。以下为一个简单的后附回调示例: + +.. code:: c + + static esp_err_t my_post_attach_start(esp_netif_t * esp_netif, void * args) + { + my_netif_driver_t *driver = args; + const esp_netif_driver_ifconfig_t driver_ifconfig = { + .driver_free_rx_buffer = my_free_rx_buf, + .transmit = my_transmit, + .handle = driver->driver_impl + }; + driver->base.netif = esp_netif; + ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig)); + my_driver_start(driver->driver_impl); + return ESP_OK; + } + + +默认处理程序 +^^^^^^^^^^^^^^^^ + +I/O 驱动程序通常还会根据 I/O 驱动程序的状态转换,为相关网络接口的生命周期行为提供默认定义,例如 *driver start* ``->`` *network start* 等。 + +以下是此类默认处理程序的一个示例: + +.. code:: c + + esp_err_t my_driver_netif_set_default_handlers(my_netif_driver_t *driver, esp_netif_t * esp_netif) + { + driver_set_event_handler(driver->driver_impl, esp_netif_action_start, MY_DRV_EVENT_START, esp_netif); + driver_set_event_handler(driver->driver_impl, esp_netif_action_stop, MY_DRV_EVENT_STOP, esp_netif); + return ESP_OK; + } + + +网络堆栈连接 +------------------------ + +用于传输和释放 RX 缓冲区的数据路径函数(在 I/O 驱动中定义)由 ESP-NETIF 的 TCP/IP 堆栈连接层调用。 + +注意,ESP-IDF 为最常见的网络接口(如 Wi-Fi station 或以太网)提供了几种网络堆栈配置。这些配置定义在 :component_file:`esp_netif/include/esp_netif_defaults.h` 中,能够满足大多数网络驱动程序的需求。在少数情况下,一些专家用户可能希望自定义基于 lwIP 的接口层,这需要额外设置 lwIP 依赖。 + +以下参考 API 概述了这些网络堆栈和 ESP-NETIF 的交互: + +.. include-build-file:: inc/esp_netif_net_stack.inc diff --git a/docs/zh_CN/api-reference/network/esp_openthread.rst b/docs/zh_CN/api-reference/network/esp_openthread.rst index 299652af277b..fdbfb5b5ec63 100644 --- a/docs/zh_CN/api-reference/network/esp_openthread.rst +++ b/docs/zh_CN/api-reference/network/esp_openthread.rst @@ -1 +1,32 @@ -.. include:: ../../../en/api-reference/network/esp_openthread.rst +Thread +====== + +:link_to_translation:`en:[English]` + +概述 +---- + +`Thread `_ 是一个基于 IP 的网状网络协议,它基于 802.15.4 物理层和 MAC 层。 + +应用示例 +-------------------- + +ESP-IDF 示例目录 :example:`openthread` 包含以下应用程序: + +- OpenThread 交互 shell::example:`openthread/ot_cli` +- 边界路由器 (Thread Border Router)::example:`openthread/ot_br` +- Thread 无线电协处理器 (Thread Radio Co-Processor)::example:`openthread/ot_rcp` + + +API参考 +------------- + +应使用 OpenThread API 操作 Thread 网络。请参考 `OpenThread API 文档 `_。 + +ESP-IDF 提供额外的 API,用于启动和管理 OpenThread 实现执行网络接口绑定和边界路由功能。 + +.. include-build-file:: inc/esp_openthread.inc +.. include-build-file:: inc/esp_openthread_types.inc +.. 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 diff --git a/docs/zh_CN/api-reference/network/esp_smartconfig.rst b/docs/zh_CN/api-reference/network/esp_smartconfig.rst index 00a8e6f6603d..bf3981d59946 100644 --- a/docs/zh_CN/api-reference/network/esp_smartconfig.rst +++ b/docs/zh_CN/api-reference/network/esp_smartconfig.rst @@ -1 +1,22 @@ -.. include:: ../../../en/api-reference/network/esp_smartconfig.rst +SmartConfig +=========== + +:link_to_translation:`en:[English]` + +SmartConfig\ :sup:`TM` 是由 TI 开发的配网技术,用于将新的 Wi-Fi 设备连接到 Wi-Fi 网络。它使用移动应用程序将无线网凭据从智能手机或平板电脑端广播给未配网的 Wi-Fi 设备。 + +这项技术的优势在于,设备无需直接获知 AP 的 SSID 或密码,而是通过智能手机获取。这对于没有用户界面的无头设备和系统而言十分重要。 + +如需通过其他方式为 {IDF_TARGET_NAME} 设备配网,请参阅 :doc:`../provisioning/index`。 + + +应用示例 +------------ + +前往 :example:`wifi/smart_config`,查看使用 SmartConfig 将 {IDF_TARGET_NAME} 连接到目标 AP 的应用示例。 + + +API 参考 +---------- + +.. include-build-file:: inc/esp_smartconfig.inc \ No newline at end of file diff --git a/docs/zh_CN/api-reference/network/index.rst b/docs/zh_CN/api-reference/network/index.rst index 097920d2ae2f..3b8795808b94 100644 --- a/docs/zh_CN/api-reference/network/index.rst +++ b/docs/zh_CN/api-reference/network/index.rst @@ -48,9 +48,8 @@ Thread 是一种基于 IPv6 的物联网网状网络技术。 本部分的 Thread API 示例代码存放在 ESP-IDF 示例项目的 :example:`openthread` 目录下。 -IP 网络层协议 -================ - +ESP-NETIF +========= .. toctree:: :maxdepth: 1 From 7a0684d03f1512914f65bb51bbc55f2099f3ab73 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 22 Sep 2023 11:47:34 +0800 Subject: [PATCH 016/142] fix(sleep): fix pma cfg csr regs bad retention --- components/esp_hw_support/sleep_cpu.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c index 8ed524e74a4c..b0f01badb7ef 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -507,18 +507,18 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi frame->pmacfg1 = RV_READ_CSR(CSR_PMACFG(1)); frame->pmacfg2 = RV_READ_CSR(CSR_PMACFG(2)); frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(3)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(4)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(5)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(6)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(7)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(8)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(9)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(10)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(11)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(12)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(13)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(14)); - frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(15)); + frame->pmacfg4 = RV_READ_CSR(CSR_PMACFG(4)); + frame->pmacfg5 = RV_READ_CSR(CSR_PMACFG(5)); + frame->pmacfg6 = RV_READ_CSR(CSR_PMACFG(6)); + frame->pmacfg7 = RV_READ_CSR(CSR_PMACFG(7)); + frame->pmacfg8 = RV_READ_CSR(CSR_PMACFG(8)); + frame->pmacfg9 = RV_READ_CSR(CSR_PMACFG(9)); + frame->pmacfg10 = RV_READ_CSR(CSR_PMACFG(10)); + frame->pmacfg11 = RV_READ_CSR(CSR_PMACFG(11)); + frame->pmacfg12 = RV_READ_CSR(CSR_PMACFG(12)); + frame->pmacfg13 = RV_READ_CSR(CSR_PMACFG(13)); + frame->pmacfg14 = RV_READ_CSR(CSR_PMACFG(14)); + frame->pmacfg15 = RV_READ_CSR(CSR_PMACFG(15)); #endif // SOC_CPU_HAS_PMA frame->utvec = RV_READ_CSR(utvec); From 510ddd1cbc495b11b50cac60694c0ad63e01988a Mon Sep 17 00:00:00 2001 From: baohongde Date: Fri, 22 Sep 2023 12:14:32 +0800 Subject: [PATCH 017/142] fix(bt/bluedroid): Fix issue of QoS configuration failure when t_poll is greater than 40 --- components/bt/controller/lib_esp32 | 2 +- components/bt/host/bluedroid/api/esp_gap_bt_api.c | 4 ++++ .../bluedroid/api/include/api/esp_gap_bt_api.h | 5 +++++ components/bt/host/bluedroid/bta/dm/bta_dm_qos.c | 14 +++++++------- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index 19fa60b819db..03bfbf0a689e 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit 19fa60b819db1e3bb8a07790f819b69657e4ae3f +Subproject commit 03bfbf0a689e268309e496a1a0bb248ddab2c808 diff --git a/components/bt/host/bluedroid/api/esp_gap_bt_api.c b/components/bt/host/bluedroid/api/esp_gap_bt_api.c index e0c8ac836bfa..e887ec5261d3 100644 --- a/components/bt/host/bluedroid/api/esp_gap_bt_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_bt_api.c @@ -428,6 +428,10 @@ esp_err_t esp_bt_gap_set_qos(esp_bd_addr_t remote_bda, uint32_t t_poll) return ESP_ERR_INVALID_STATE; } + if (t_poll < ESP_BT_GAP_TPOLL_MIN || t_poll > ESP_BT_GAP_TPOLL_MAX) { + return ESP_ERR_INVALID_ARG; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_ACT_SET_QOS; diff --git a/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h b/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h index 24b8a2a2c7d4..ea7a4eaf0aea 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h @@ -233,6 +233,11 @@ typedef enum { #define ESP_BT_GAP_MIN_INQ_LEN (0x01) /*!< Minimum inquiry duration, unit is 1.28s */ #define ESP_BT_GAP_MAX_INQ_LEN (0x30) /*!< Maximum inquiry duration, unit is 1.28s */ +/** Minimum, Default and Maximum poll interval **/ +#define ESP_BT_GAP_TPOLL_MIN (0x0006) /*!< Minimum poll interval, unit is 625 microseconds */ +#define ESP_BT_GAP_TPOLL_DFT (0x0028) /*!< Default poll interval, unit is 625 microseconds */ +#define ESP_BT_GAP_TPOLL_MAX (0x1000) /*!< Maximum poll interval, unit is 625 microseconds */ + /// GAP state callback parameters typedef union { /** diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_qos.c b/components/bt/host/bluedroid/bta/dm/bta_dm_qos.c index 1239bae1f936..19a31b9449db 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_qos.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_qos.c @@ -34,13 +34,13 @@ void bta_dm_set_qos(tBTA_DM_MSG *p_data) { FLOW_SPEC p_flow = { - .qos_flags = 0, /* TBD */ - .service_type = GUARANTEED, /* see below */ - .token_rate = 0, /* bytes/second */ - .token_bucket_size = 0, /* bytes */ - .peak_bandwidth = 0, /* bytes/second */ - .latency = 625 * p_data->qos_set.t_poll, /* microseconds */ - .delay_variation = 0xFFFFFFFF /* microseconds */ + .qos_flags = 0, /* TBD */ + .service_type = NO_TRAFFIC, /* service_type */ + .token_rate = 0, /* bytes/second */ + .token_bucket_size = 0, /* bytes */ + .peak_bandwidth = 0, /* bytes/second */ + .latency = 625 * p_data->qos_set.t_poll, /* microseconds */ + .delay_variation = 0xFFFFFFFF /* microseconds */ }; tBTM_STATUS status = BTM_SetQoS (p_data->qos_set.bd_addr, &p_flow, p_data->qos_set.p_cb); From c2cbb5d04c0676457e04fe18165a7f55ad69445d Mon Sep 17 00:00:00 2001 From: baohongde Date: Thu, 7 Sep 2023 16:44:05 +0800 Subject: [PATCH 018/142] fix(bt/bluedroid): Triggering disconnect event of GAP correctly --- .../bt/host/bluedroid/stack/btm/btm_acl.c | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/components/bt/host/bluedroid/stack/btm/btm_acl.c b/components/bt/host/bluedroid/stack/btm/btm_acl.c index 58f6f21b8e5b..96e0b1447561 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_acl.c @@ -2659,37 +2659,33 @@ void btm_acl_connected(BD_ADDR bda, UINT16 handle, UINT8 link_type, UINT8 enc_mo *******************************************************************************/ void btm_acl_disconnected(UINT16 handle, UINT8 reason) { - BOOLEAN need_report = TRUE; + + /* Report BR/EDR ACL disconnection result to upper layer */ + tACL_CONN *conn = btm_handle_to_acl(handle); + if (conn) { +#if BLE_INCLUDED == TRUE + if (conn->transport == BT_TRANSPORT_BR_EDR) +#endif + { + tBTM_ACL_LINK_STAT_EVENT_DATA evt_data = { + .event = BTM_ACL_DISCONN_CMPL_EVT, + .link_act.disconn_cmpl.reason = reason, + .link_act.disconn_cmpl.handle = handle, + }; + bdcpy(evt_data.link_act.disconn_cmpl.bd_addr, conn->remote_addr); + btm_acl_link_stat_report(&evt_data); + } + } #if BTM_SCO_INCLUDED == TRUE /* If L2CAP doesn't know about it, send it to SCO */ if (!l2c_link_hci_disc_comp (handle, reason)) { btm_sco_removed (handle, reason); - need_report = FALSE; } #else l2c_link_hci_disc_comp(handle, reason); #endif /* BTM_SCO_INCLUDED */ - if (need_report) { - /* Report BR/EDR ACL disconnection result to upper layer */ - tACL_CONN *conn = btm_handle_to_acl(handle); - if (conn) { -#if BLE_INCLUDED == TRUE - if (conn->transport == BT_TRANSPORT_BR_EDR) -#endif - { - tBTM_ACL_LINK_STAT_EVENT_DATA evt_data = { - .event = BTM_ACL_DISCONN_CMPL_EVT, - .link_act.disconn_cmpl.reason = reason, - .link_act.disconn_cmpl.handle = handle, - }; - bdcpy(evt_data.link_act.disconn_cmpl.bd_addr, conn->remote_addr); - btm_acl_link_stat_report(&evt_data); - } - } - } - #if (SMP_INCLUDED == TRUE) /* Notify security manager */ btm_sec_disconnected(handle, reason); From beef3bd065163f269a8ae93d3ef08c6c41960f33 Mon Sep 17 00:00:00 2001 From: Liu Zhongwei Date: Tue, 12 Sep 2023 15:33:30 +0800 Subject: [PATCH 019/142] feat(esp_lcd): add lock for lvgl in examples --- .../lcd/i2c_oled/main/i2c_oled_example_main.c | 9 ++- .../peripherals/lcd/i80_controller/README.md | 6 +- .../main/i80_controller_example_main.c | 57 +++++++++++++++--- examples/peripherals/lcd/rgb_panel/README.md | 8 ++- .../lcd/rgb_panel/main/rgb_lcd_example_main.c | 60 +++++++++++++++---- .../peripherals/lcd/spi_lcd_touch/README.md | 6 +- .../main/spi_lcd_touch_example_main.c | 58 +++++++++++++++--- 7 files changed, 173 insertions(+), 31 deletions(-) diff --git a/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c b/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c index fa71893d5ff0..b95a6f77b817 100644 --- a/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c +++ b/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -141,5 +141,10 @@ void app_main(void) lv_disp_set_rotation(disp, LV_DISP_ROT_NONE); ESP_LOGI(TAG, "Display LVGL Scroll Text"); - example_lvgl_demo_ui(disp); + // Lock the mutex due to the LVGL APIs are not thread-safe + if (lvgl_port_lock(0)) { + example_lvgl_demo_ui(disp); + // Release the mutex + lvgl_port_unlock(); + } } diff --git a/examples/peripherals/lcd/i80_controller/README.md b/examples/peripherals/lcd/i80_controller/README.md index 55652f79c284..81f68ae419d6 100644 --- a/examples/peripherals/lcd/i80_controller/README.md +++ b/examples/peripherals/lcd/i80_controller/README.md @@ -13,7 +13,7 @@ The UI will display two images (one Espressif logo and another Espressif text), This example is constructed by [IDF component manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html), all the external dependency will be handled by the CMake build system automatically. In this case, it will help download the lvgl from [registry](https://components.espressif.com/component/lvgl/lvgl), with the version specified in the [manifest file](main/idf_component.yml). -This example uses the [esp_timer](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html) to generate the ticks needed by LVGL. For more porting guides, please refer to [LVGL porting doc](https://docs.lvgl.io/master/porting/index.html). +This example uses the [esp_timer](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html) to generate the ticks needed by LVGL and uses a dedicated task to run the `lv_timer_handler()`. Since the LVGL APIs are not thread-safe, this example uses a mutex which be invoked before the call of `lv_timer_handler()` and released after it. The same mutex needs to be used in other tasks and threads around every LVGL (lv_...) related function call and code. For more porting guides, please refer to [LVGL porting doc](https://docs.lvgl.io/master/porting/index.html). ## How to use the example @@ -94,7 +94,9 @@ I (558) example: Turn on LCD backlight I (558) example: Initialize LVGL library I (558) example: Register display driver to LVGL I (558) example: Install LVGL tick timer -I (558) example: Display LVGL animation +I (558) example: Create LVGL task +I (558) example: Starting LVGL task +I (638) example: Display LVGL animation ``` ## Touch Screen Support diff --git a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c index 13a72fc0afe8..f8c5ea29c960 100644 --- a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c +++ b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c @@ -7,6 +7,7 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/semphr.h" #include "esp_timer.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" @@ -86,10 +87,16 @@ static const char *TAG = "example"; #endif #define EXAMPLE_LVGL_TICK_PERIOD_MS 2 +#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500 +#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1 +#define EXAMPLE_LVGL_TASK_STACK_SIZE (4 * 1024) +#define EXAMPLE_LVGL_TASK_PRIORITY 2 // Supported alignment: 16, 32, 64. A higher alignment can enables higher burst transfer size, thus a higher i80 bus throughput. #define EXAMPLE_PSRAM_DATA_ALIGNMENT 64 +static SemaphoreHandle_t lvgl_mux = NULL; + extern void example_lvgl_demo_ui(lv_disp_t *disp); static bool example_notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) @@ -139,6 +146,39 @@ static void example_increase_lvgl_tick(void *arg) lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS); } +bool example_lvgl_lock(int timeout_ms) +{ + // Convert timeout in milliseconds to FreeRTOS ticks + // If `timeout_ms` is set to -1, the program will block until the condition is met + const TickType_t timeout_ticks = (timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); + return xSemaphoreTakeRecursive(lvgl_mux, timeout_ticks) == pdTRUE; +} + +void example_lvgl_unlock(void) +{ + xSemaphoreGiveRecursive(lvgl_mux); +} + +static void example_lvgl_port_task(void *arg) +{ + ESP_LOGI(TAG, "Starting LVGL task"); + uint32_t task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; + while (1) { + // Lock the mutex due to the LVGL APIs are not thread-safe + if (example_lvgl_lock(-1)) { + task_delay_ms = lv_timer_handler(); + // Release the mutex + example_lvgl_unlock(); + } + if (task_delay_ms > EXAMPLE_LVGL_TASK_MAX_DELAY_MS) { + task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; + } else if (task_delay_ms < EXAMPLE_LVGL_TASK_MIN_DELAY_MS) { + task_delay_ms = EXAMPLE_LVGL_TASK_MIN_DELAY_MS; + } + vTaskDelay(pdMS_TO_TICKS(task_delay_ms)); + } +} + #if CONFIG_EXAMPLE_LCD_IMAGE_FROM_FILE_SYSTEM void example_init_filesystem(void) { @@ -448,13 +488,16 @@ void app_main(void) lv_indev_drv_register(&indev_drv); #endif // CONFIG_EXAMPLE_LCD_TOUCH_ENABLED - ESP_LOGI(TAG, "Display LVGL animation"); - example_lvgl_demo_ui(disp); + lvgl_mux = xSemaphoreCreateRecursiveMutex(); + assert(lvgl_mux); + ESP_LOGI(TAG, "Create LVGL task"); + xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL); - while (1) { - // raise the task priority of LVGL and/or reduce the handler period can improve the performance - vTaskDelay(pdMS_TO_TICKS(10)); - // The task running lv_timer_handler should have lower priority than that running `lv_tick_inc` - lv_timer_handler(); + ESP_LOGI(TAG, "Display LVGL animation"); + // Lock the mutex due to the LVGL APIs are not thread-safe + if (example_lvgl_lock(-1)) { + example_lvgl_demo_ui(disp); + // Release the mutex + example_lvgl_unlock(); } } diff --git a/examples/peripherals/lcd/rgb_panel/README.md b/examples/peripherals/lcd/rgb_panel/README.md index 44a01a8caeb6..087cbbe58b41 100644 --- a/examples/peripherals/lcd/rgb_panel/README.md +++ b/examples/peripherals/lcd/rgb_panel/README.md @@ -5,7 +5,11 @@ [esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) supports RGB interfaced LCD panel, with one or two frame buffer(s) managed by the driver itself. -This example shows the general process of installing an RGB panel driver, and displays a scatter chart on the screen based on the LVGL library. For more information about porting the LVGL library, please refer to [official porting guide](https://docs.lvgl.io/master/porting/index.html). This example uses two kinds of **buffering mode** based on the number of frame buffers: +This example shows the general process of installing an RGB panel driver, and displays a scatter chart on the screen based on the LVGL library. + +This example uses the [esp_timer](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html) to generate the ticks needed by LVGL and uses a dedicated task to run the `lv_timer_handler()`. Since the LVGL APIs are not thread-safe, this example uses a mutex which be invoked before the call of `lv_timer_handler()` and released after it. The same mutex needs to be used in other tasks and threads around every LVGL (lv_...) related function call and code. For more porting guides, please refer to [LVGL porting doc](https://docs.lvgl.io/master/porting/index.html). + +This example uses two kinds of **buffering mode** based on the number of frame buffers: | Number of Frame Buffers | LVGL buffering mode | Way to avoid tear effect | |-------------------------|---------------------|-------------------------------------------------------------------------------------------------------------| @@ -89,6 +93,8 @@ I (906) example: Initialize LVGL library I (916) example: Allocate separate LVGL draw buffers from PSRAM I (916) example: Register display driver to LVGL I (926) example: Install LVGL tick timer +I (926) example: Create LVGL task +I (926) example: Starting LVGL task I (926) example: Display LVGL Scatter Chart ... ``` diff --git a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c index f9ebecb94620..8c8599a3d3cf 100644 --- a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c +++ b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -59,6 +59,12 @@ static const char *TAG = "example"; #endif // CONFIG_EXAMPLE_DOUBLE_FB #define EXAMPLE_LVGL_TICK_PERIOD_MS 2 +#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500 +#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1 +#define EXAMPLE_LVGL_TASK_STACK_SIZE (4 * 1024) +#define EXAMPLE_LVGL_TASK_PRIORITY 2 + +static SemaphoreHandle_t lvgl_mux = NULL; // we use two semaphores to sync the VSYNC event and the LVGL task, to avoid potential tearing effect #if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM @@ -101,6 +107,39 @@ static void example_increase_lvgl_tick(void *arg) lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS); } +bool example_lvgl_lock(int timeout_ms) +{ + // Convert timeout in milliseconds to FreeRTOS ticks + // If `timeout_ms` is set to -1, the program will block until the condition is met + const TickType_t timeout_ticks = (timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); + return xSemaphoreTakeRecursive(lvgl_mux, timeout_ticks) == pdTRUE; +} + +void example_lvgl_unlock(void) +{ + xSemaphoreGiveRecursive(lvgl_mux); +} + +static void example_lvgl_port_task(void *arg) +{ + ESP_LOGI(TAG, "Starting LVGL task"); + uint32_t task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; + while (1) { + // Lock the mutex due to the LVGL APIs are not thread-safe + if (example_lvgl_lock(-1)) { + task_delay_ms = lv_timer_handler(); + // Release the mutex + example_lvgl_unlock(); + } + if (task_delay_ms > EXAMPLE_LVGL_TASK_MAX_DELAY_MS) { + task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; + } else if (task_delay_ms < EXAMPLE_LVGL_TASK_MIN_DELAY_MS) { + task_delay_ms = EXAMPLE_LVGL_TASK_MIN_DELAY_MS; + } + vTaskDelay(pdMS_TO_TICKS(task_delay_ms)); + } +} + void app_main(void) { static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s) @@ -201,8 +240,6 @@ void app_main(void) ESP_LOGI(TAG, "Allocate separate LVGL draw buffers from PSRAM"); buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); assert(buf1); - buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); - assert(buf2); // initialize LVGL draw buffers lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 100); #endif // CONFIG_EXAMPLE_DOUBLE_FB @@ -229,13 +266,16 @@ void app_main(void) ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000)); - ESP_LOGI(TAG, "Display LVGL Scatter Chart"); - example_lvgl_demo_ui(disp); + lvgl_mux = xSemaphoreCreateRecursiveMutex(); + assert(lvgl_mux); + ESP_LOGI(TAG, "Create LVGL task"); + xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL); - while (1) { - // raise the task priority of LVGL and/or reduce the handler period can improve the performance - vTaskDelay(pdMS_TO_TICKS(10)); - // The task running lv_timer_handler should have lower priority than that running `lv_tick_inc` - lv_timer_handler(); + ESP_LOGI(TAG, "Display LVGL Scatter Chart"); + // Lock the mutex due to the LVGL APIs are not thread-safe + if (example_lvgl_lock(-1)) { + example_lvgl_demo_ui(disp); + // Release the mutex + example_lvgl_unlock(); } } diff --git a/examples/peripherals/lcd/spi_lcd_touch/README.md b/examples/peripherals/lcd/spi_lcd_touch/README.md index 804abb7aefea..fec1348be3aa 100644 --- a/examples/peripherals/lcd/spi_lcd_touch/README.md +++ b/examples/peripherals/lcd/spi_lcd_touch/README.md @@ -7,7 +7,9 @@ `esp_lcd` allows user to add their own panel drivers in the project scope (i.e. panel driver can live outside of esp-idf), so that the upper layer code like LVGL porting code can be reused without any modifications, as long as user-implemented panel driver follows the interface defined in the `esp_lcd` component. -This example shows how to use GC9A01 or ILI9341 display driver from Component manager in esp-idf project. These components are using API provided by `esp_lcd` component. This example will draw a fancy dash board with the LVGL library. For more information about porting the LVGL library, you can also refer to [another lvgl porting example](../i80_controller/README.md). +This example shows how to use GC9A01 or ILI9341 display driver from Component manager in esp-idf project. These components are using API provided by `esp_lcd` component. This example will draw a fancy dash board with the LVGL library. + +This example uses the [esp_timer](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html) to generate the ticks needed by LVGL and uses a dedicated task to run the `lv_timer_handler()`. Since the LVGL APIs are not thread-safe, this example uses a mutex which be invoked before the call of `lv_timer_handler()` and released after it. The same mutex needs to be used in other tasks and threads around every LVGL (lv_...) related function call and code. For more porting guides, please refer to [LVGL porting doc](https://docs.lvgl.io/master/porting/index.html). ## Touch controller STMPE610 @@ -83,6 +85,8 @@ I (599) example: Turn on LCD backlight I (599) example: Initialize LVGL library I (609) example: Register display driver to LVGL I (619) example: Install LVGL tick timer +I (619) example: Starting LVGL task +I (619) example: Display LVGL animation I (619) example: Display LVGL Meter Widget ... ``` diff --git a/examples/peripherals/lcd/spi_lcd_touch/main/spi_lcd_touch_example_main.c b/examples/peripherals/lcd/spi_lcd_touch/main/spi_lcd_touch_example_main.c index 4b761fc95ae4..03c7921e322b 100644 --- a/examples/peripherals/lcd/spi_lcd_touch/main/spi_lcd_touch_example_main.c +++ b/examples/peripherals/lcd/spi_lcd_touch/main/spi_lcd_touch_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -7,6 +7,7 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/semphr.h" #include "esp_timer.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" @@ -60,7 +61,12 @@ static const char *TAG = "example"; #define EXAMPLE_LCD_PARAM_BITS 8 #define EXAMPLE_LVGL_TICK_PERIOD_MS 2 +#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500 +#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1 +#define EXAMPLE_LVGL_TASK_STACK_SIZE (4 * 1024) +#define EXAMPLE_LVGL_TASK_PRIORITY 2 +static SemaphoreHandle_t lvgl_mux = NULL; #if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED esp_lcd_touch_handle_t tp = NULL; @@ -164,6 +170,39 @@ static void example_increase_lvgl_tick(void *arg) lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS); } +bool example_lvgl_lock(int timeout_ms) +{ + // Convert timeout in milliseconds to FreeRTOS ticks + // If `timeout_ms` is set to -1, the program will block until the condition is met + const TickType_t timeout_ticks = (timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); + return xSemaphoreTakeRecursive(lvgl_mux, timeout_ticks) == pdTRUE; +} + +void example_lvgl_unlock(void) +{ + xSemaphoreGiveRecursive(lvgl_mux); +} + +static void example_lvgl_port_task(void *arg) +{ + ESP_LOGI(TAG, "Starting LVGL task"); + uint32_t task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; + while (1) { + // Lock the mutex due to the LVGL APIs are not thread-safe + if (example_lvgl_lock(-1)) { + task_delay_ms = lv_timer_handler(); + // Release the mutex + example_lvgl_unlock(); + } + if (task_delay_ms > EXAMPLE_LVGL_TASK_MAX_DELAY_MS) { + task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; + } else if (task_delay_ms < EXAMPLE_LVGL_TASK_MIN_DELAY_MS) { + task_delay_ms = EXAMPLE_LVGL_TASK_MIN_DELAY_MS; + } + vTaskDelay(pdMS_TO_TICKS(task_delay_ms)); + } +} + void app_main(void) { static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s) @@ -296,13 +335,16 @@ void app_main(void) lv_indev_drv_register(&indev_drv); #endif - ESP_LOGI(TAG, "Display LVGL Meter Widget"); - example_lvgl_demo_ui(disp); + lvgl_mux = xSemaphoreCreateRecursiveMutex(); + assert(lvgl_mux); + ESP_LOGI(TAG, "Create LVGL task"); + xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL); - while (1) { - // raise the task priority of LVGL and/or reduce the handler period can improve the performance - vTaskDelay(pdMS_TO_TICKS(10)); - // The task running lv_timer_handler should have lower priority than that running `lv_tick_inc` - lv_timer_handler(); + ESP_LOGI(TAG, "Display LVGL Meter Widget"); + // Lock the mutex due to the LVGL APIs are not thread-safe + if (example_lvgl_lock(-1)) { + example_lvgl_demo_ui(disp); + // Release the mutex + example_lvgl_unlock(); } } From e271e27bd08b6ed7d3b323590884ae373cb43597 Mon Sep 17 00:00:00 2001 From: liqigan Date: Tue, 19 Sep 2023 19:55:12 +0800 Subject: [PATCH 020/142] fix(bt/bluedroid): Fix the mistaken deletion of bluedriod enable in bt_spp_acceptor example --- .../bluedroid/classic_bt/bt_spp_acceptor/main/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c index c56b82b98568..02dbd1c8ec6b 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c @@ -232,6 +232,11 @@ void app_main(void) return; } + if ((ret = esp_bluedroid_enable()) != ESP_OK) { + ESP_LOGE(SPP_TAG, "%s enable bluedroid failed: %s", __func__, esp_err_to_name(ret)); + return; + } + if ((ret = esp_bt_gap_register_callback(esp_bt_gap_cb)) != ESP_OK) { ESP_LOGE(SPP_TAG, "%s gap register failed: %s", __func__, esp_err_to_name(ret)); return; From ea38a2e9a493ab35e1572057f275a1ac71d49343 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 14 Sep 2023 12:14:08 +0800 Subject: [PATCH 021/142] feat(cache): support cache driver on esp32p4 --- .../bootloader_flash/src/bootloader_flash.c | 37 +- .../src/bootloader_flash_config_esp32c2.c | 9 +- .../src/bootloader_flash_config_esp32c3.c | 9 +- .../src/bootloader_flash_config_esp32c6.c | 7 +- .../src/bootloader_flash_config_esp32h2.c | 7 +- .../src/bootloader_flash_config_esp32p4.c | 7 +- .../src/bootloader_flash_config_esp32s2.c | 8 +- .../src/bootloader_flash_config_esp32s3.c | 6 +- .../src/bootloader_utility.c | 4 +- .../bootloader_support/src/esp_image_format.c | 12 +- components/esp_hw_support/dma/gdma.c | 3 +- .../esp_hw_support/mspi_timing_tuning.c | 5 +- components/esp_hw_support/sleep_modes.c | 5 +- .../test_apps/dma/main/CMakeLists.txt | 2 +- .../test_apps/dma/main/test_gdma.c | 28 +- components/esp_lcd/src/esp_lcd_panel_io_i80.c | 3 +- components/esp_mm/esp_cache.c | 34 +- components/esp_mm/esp_mmu_map.c | 14 +- .../test_apps/mm/main/test_cache_msync.c | 7 +- components/esp_system/port/cpu_start.c | 6 +- .../esp_system/port/soc/esp32p4/Kconfig.cache | 42 +- components/hal/cache_hal.c | 288 +++-- components/hal/esp32/cache_hal_esp32.c | 26 +- components/hal/esp32/include/hal/cache_ll.h | 45 +- components/hal/esp32c2/include/hal/cache_ll.h | 109 +- components/hal/esp32c3/include/hal/cache_ll.h | 108 +- components/hal/esp32c6/include/hal/cache_ll.h | 128 ++- components/hal/esp32h2/include/hal/cache_ll.h | 128 ++- components/hal/esp32p4/include/hal/cache_ll.h | 984 +++++++++++++++++- components/hal/esp32s2/include/hal/cache_ll.h | 120 ++- components/hal/esp32s3/include/hal/cache_ll.h | 145 ++- components/hal/include/hal/cache_hal.h | 91 +- components/hal/mmu_hal.c | 5 - .../esp32p4/include/soc/Kconfig.soc_caps.in | 6 +- .../soc/esp32p4/include/soc/ext_mem_defs.h | 5 + components/soc/esp32p4/include/soc/soc_caps.h | 3 +- components/spi_flash/cache_utils.c | 12 +- components/spi_flash/flash_mmap.c | 8 - 38 files changed, 1927 insertions(+), 539 deletions(-) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index fb2afe66dbf4..f837694d535d 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -12,10 +12,6 @@ #include "soc/soc_caps.h" #include "hal/efuse_ll.h" #include "hal/efuse_hal.h" -#if CONFIG_IDF_TARGET_ESP32P4 -//TODO: IDF-7516 -#include "esp32p4/rom/cache.h" -#endif #if CONFIG_IDF_TARGET_ESP32 # include "soc/spi_struct.h" @@ -128,6 +124,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) #include "hal/mmu_hal.h" #include "hal/mmu_ll.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #if CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/opi_flash.h" @@ -205,7 +202,7 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size) Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif //---------------Do mapping------------------------ @@ -238,15 +235,10 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size) #if CONFIG_IDF_TARGET_ESP32 Cache_Read_Enable(0); #else -#if CONFIG_IDF_TARGET_ESP32P4 - /** - * TODO: IDF-7516 - * we need to invalidate l1 dcache to make each mmap clean - * to that vaddr - */ - Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE, MMU_BLOCK0_VADDR, actual_mapped_len); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, MMU_BLOCK0_VADDR, actual_mapped_len); #endif - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif mapped = true; @@ -263,7 +255,7 @@ void bootloader_munmap(const void *mapping) Cache_Flush(0); mmu_init(0); #else - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); mmu_hal_unmap_all(); #endif mapped = false; @@ -291,7 +283,7 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size); @@ -299,7 +291,7 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s #if CONFIG_IDF_TARGET_ESP32 Cache_Read_Enable(0); #else - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif return spi_to_esp_err(r); @@ -322,7 +314,7 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif //---------------Do mapping------------------------ @@ -341,11 +333,10 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest #if CONFIG_IDF_TARGET_ESP32 Cache_Read_Enable(0); #else -#if CONFIG_IDF_TARGET_ESP32P4 - //TODO: IDF-7516 - Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE, FLASH_READ_VADDR, actual_mapped_len); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, MMU_BLOCK0_VADDR, actual_mapped_len); #endif - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif } map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at)); @@ -468,9 +459,9 @@ void bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t fla assert(false); break; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); esp_rom_opiflash_cache_mode_config(flash_mode, &cache_rd); - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } #endif diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c index 7a3c1f3b50db..692fa53abc56 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,8 +23,9 @@ #include "bootloader_flash_priv.h" #include "bootloader_init.h" #include "hal/mmu_hal.h" -#include "hal/cache_hal.h" #include "hal/mmu_ll.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" #define FLASH_IO_MATRIX_DUMMY_40M 0 #define FLASH_IO_MATRIX_DUMMY_80M 0 @@ -126,10 +127,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c index cbbb81189a15..c76a98040701 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,8 +24,9 @@ #include "bootloader_flash_priv.h" #include "bootloader_init.h" #include "hal/mmu_hal.h" -#include "hal/cache_hal.h" #include "hal/mmu_ll.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" #define FLASH_IO_MATRIX_DUMMY_40M 0 #define FLASH_IO_MATRIX_DUMMY_80M 0 @@ -137,10 +138,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c index 7b725a4862fa..719eb3a860c6 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c @@ -24,8 +24,9 @@ #include "bootloader_flash_priv.h" #include "bootloader_init.h" #include "hal/mmu_hal.h" -#include "hal/cache_hal.h" #include "hal/mmu_ll.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" void bootloader_flash_update_id() { @@ -102,10 +103,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c index ef83e6d87072..9f6e526ce647 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c @@ -24,8 +24,9 @@ #include "bootloader_flash_priv.h" #include "bootloader_init.h" #include "hal/mmu_hal.h" -#include "hal/cache_hal.h" #include "hal/mmu_ll.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "soc/pcr_reg.h" void bootloader_flash_update_id() @@ -109,10 +110,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c index b2fb0e385d0e..11f295d2aa02 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c @@ -18,8 +18,9 @@ #include "bootloader_flash_priv.h" #include "bootloader_init.h" #include "hal/mmu_hal.h" -#include "hal/cache_hal.h" #include "hal/mmu_ll.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" void bootloader_flash_update_id() { @@ -96,10 +97,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c index d6479a1a18cb..9fb267439be8 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,7 +23,9 @@ #include "bootloader_common.h" #include "bootloader_init.h" #include "hal/mmu_hal.h" +#include "hal/mmu_ll.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #define FLASH_IO_MATRIX_DUMMY_40M 0 #define FLASH_IO_MATRIX_DUMMY_80M 0 @@ -150,12 +152,12 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); // Set flash chip size esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode // TODO: set frequency - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c index f995cb41b8c3..b73663993df8 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c @@ -24,7 +24,9 @@ #include "bootloader_flash.h" #include "bootloader_init.h" #include "hal/mmu_hal.h" +#include "hal/mmu_ll.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #define FLASH_IO_MATRIX_DUMMY_40M 0 #define FLASH_IO_MATRIX_DUMMY_80M 0 @@ -157,12 +159,12 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); // Set flash chip size esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode // TODO: set frequency - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index e591189fa32d..0ec4f07c0a23 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -836,7 +836,7 @@ static void set_cache_and_start_app( Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif //reset MMU table first mmu_hal_unmap_all(); @@ -896,7 +896,7 @@ static void set_cache_and_start_app( // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) Cache_Read_Enable(0); #else - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif ESP_LOGD(TAG, "start: 0x%08"PRIx32, entry_addr); diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 26a1e67edf2f..e45c6c2d7ecd 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -21,6 +21,7 @@ #include "esp_rom_sys.h" #include "bootloader_memory_utils.h" #include "soc/soc_caps.h" +#include "hal/cache_ll.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/secure_boot.h" #elif CONFIG_IDF_TARGET_ESP32S2 @@ -41,7 +42,6 @@ #elif CONFIG_IDF_TARGET_ESP32P4 #include "esp32p4/rom/rtc.h" #include "esp32p4/rom/secure_boot.h" -#include "esp32p4/rom/cache.h" #endif #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) @@ -236,9 +236,8 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_ } } } -#if CONFIG_IDF_TARGET_ESP32P4 - //TODO: IDF-7516 - Cache_WriteBack_All(CACHE_MAP_L1_DCACHE); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + cache_ll_writeback_all(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA, CACHE_LL_ID_ALL); #endif } #endif // BOOTLOADER_BUILD @@ -675,10 +674,9 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui MIN(SHA_CHUNK, data_len - i)); } } -#if CONFIG_IDF_TARGET_ESP32P4 - //TODO: IDF-7516 +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE if (do_load && esp_ptr_in_diram_iram((uint32_t *)load_addr)) { - Cache_WriteBack_All(CACHE_MAP_L1_DCACHE); + cache_ll_writeback_all(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA, CACHE_LL_ID_ALL); } #endif diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index fd7aa1686d97..79c012a88d61 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -45,6 +45,7 @@ #include "esp_private/periph_ctrl.h" #include "gdma_priv.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" static const char *TAG = "gdma"; @@ -357,7 +358,7 @@ esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_t ESP_RETURN_ON_FALSE((sram_alignment & (sram_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "invalid sram alignment: %zu", sram_alignment); - uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); + uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_EXT_MEM); if (psram_alignment == 0) { // fall back to use the same size of the psram data cache line size psram_alignment = data_cache_line_size; diff --git a/components/esp_hw_support/mspi_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning.c index 2b524fb7e332..9768966f3eb1 100644 --- a/components/esp_hw_support/mspi_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning.c @@ -15,6 +15,7 @@ #include "soc/soc.h" #include "hal/spi_flash_hal.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "esp_private/mspi_timing_tuning.h" #include "mspi_timing_config.h" #include "mspi_timing_by_mspi_delay.h" @@ -473,7 +474,7 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down) * for preventing concurrent from MSPI to external memory */ #if SOC_CACHE_FREEZE_SUPPORTED - cache_hal_freeze(CACHE_TYPE_ALL); + cache_hal_freeze(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif //#if SOC_CACHE_FREEZE_SUPPORTED if (switch_down) { @@ -485,7 +486,7 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down) } #if SOC_CACHE_FREEZE_SUPPORTED - cache_hal_unfreeze(CACHE_TYPE_ALL); + cache_hal_unfreeze(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif //#if SOC_CACHE_FREEZE_SUPPORTED } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index a4f920890b48..37841c7eaaf2 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -43,6 +43,7 @@ #include "regi2c_ctrl.h" //For `REGI2C_ANA_CALI_PD_WORKAROUND`, temp #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "hal/wdt_hal.h" #include "hal/uart_hal.h" #if SOC_TOUCH_SENSOR_SUPPORTED @@ -403,7 +404,7 @@ static int s_cache_suspend_cnt = 0; static void IRAM_ATTR suspend_cache(void) { s_cache_suspend_cnt++; if (s_cache_suspend_cnt == 1) { - cache_hal_suspend(CACHE_TYPE_ALL); + cache_hal_suspend(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } } @@ -412,7 +413,7 @@ static void IRAM_ATTR resume_cache(void) { s_cache_suspend_cnt--; assert(s_cache_suspend_cnt >= 0 && DRAM_STR("cache resume doesn't match suspend ops")); if (s_cache_suspend_cnt == 0) { - cache_hal_resume(CACHE_TYPE_ALL); + cache_hal_resume(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } } diff --git a/components/esp_hw_support/test_apps/dma/main/CMakeLists.txt b/components/esp_hw_support/test_apps/dma/main/CMakeLists.txt index 4088442971ea..54b239820957 100644 --- a/components/esp_hw_support/test_apps/dma/main/CMakeLists.txt +++ b/components/esp_hw_support/test_apps/dma/main/CMakeLists.txt @@ -11,5 +11,5 @@ endif() # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity + PRIV_REQUIRES unity esp_mm WHOLE_ARCHIVE) diff --git a/components/esp_hw_support/test_apps/dma/main/test_gdma.c b/components/esp_hw_support/test_apps/dma/main/test_gdma.c index ba9d2eb33385..6d3d909d1f85 100644 --- a/components/esp_hw_support/test_apps/dma/main/test_gdma.c +++ b/components/esp_hw_support/test_apps/dma/main/test_gdma.c @@ -16,7 +16,7 @@ #include "soc/soc_caps.h" #include "hal/gdma_ll.h" #include "hal/cache_ll.h" -#include "rom/cache.h" +#include "esp_cache.h" TEST_CASE("GDMA channel allocation", "[GDMA]") { @@ -187,7 +187,7 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl uint8_t *dst_data = dst_buf + 64; // prepare the source data - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 128; i++) { src_data[i] = i; } @@ -198,41 +198,41 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl dma_descriptor_align8_t *rx_descs_noncache = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(rx_descs)); tx_descs_noncache[0].buffer = src_data; - tx_descs_noncache[0].dw0.size = 50; - tx_descs_noncache[0].dw0.length = 50; + tx_descs_noncache[0].dw0.size = 64; + tx_descs_noncache[0].dw0.length = 64; tx_descs_noncache[0].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; tx_descs_noncache[0].dw0.suc_eof = 0; tx_descs_noncache[0].next = &tx_descs[1]; // Note, the DMA doesn't recognize a non-cacheable address, here must be the cached address - tx_descs_noncache[1].buffer = src_data + 50; - tx_descs_noncache[1].dw0.size = 50; - tx_descs_noncache[1].dw0.length = 50; + tx_descs_noncache[1].buffer = src_data + 64; + tx_descs_noncache[1].dw0.size = 64; + tx_descs_noncache[1].dw0.length = 64; tx_descs_noncache[1].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; tx_descs_noncache[1].dw0.suc_eof = 1; tx_descs_noncache[1].next = NULL; rx_descs_noncache->buffer = dst_data; - rx_descs_noncache->dw0.size = 100; + rx_descs_noncache->dw0.size = 128; rx_descs_noncache->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; rx_descs_noncache->dw0.suc_eof = 1; rx_descs_noncache->next = NULL; #else tx_descs->buffer = src_data; - tx_descs->dw0.size = 100; - tx_descs->dw0.length = 100; + tx_descs->dw0.size = 128; + tx_descs->dw0.length = 128; tx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; tx_descs->dw0.suc_eof = 1; tx_descs->next = NULL; rx_descs->buffer = dst_data; - rx_descs->dw0.size = 100; + rx_descs->dw0.size = 128; rx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; rx_descs->next = NULL; #endif #if CONFIG_IDF_TARGET_ESP32P4 // do write-back for the source data because it's in the cache - Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)src_data, 100); + TEST_ESP_OK(esp_cache_msync((void *)src_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_C2M)); #endif TEST_ESP_OK(gdma_start(rx_chan, (intptr_t)rx_descs)); @@ -242,14 +242,14 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl #if CONFIG_IDF_TARGET_ESP32P4 // the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data - Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)dst_data, 100); + TEST_ESP_OK(esp_cache_msync((void *)dst_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_M2C)); #endif // check the DMA descriptor write-back feature TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, tx_descs[0].dw0.owner); TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, rx_descs[0].dw0.owner); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 128; i++) { TEST_ASSERT_EQUAL(i, dst_data[i]); } free((void *)src_buf); diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i80.c b/components/esp_lcd/src/esp_lcd_panel_io_i80.c index 39cd7fd65ad8..0130bbd46314 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i80.c @@ -30,6 +30,7 @@ #include "hal/dma_types.h" #include "hal/gpio_hal.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "esp_private/gdma.h" #include "driver/gpio.h" #include "esp_private/periph_ctrl.h" @@ -491,7 +492,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons trans_desc->user_ctx = i80_device->user_ctx; if (esp_ptr_external_ram(color)) { - uint32_t dcache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); + uint32_t dcache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_EXT_MEM); // flush frame buffer from cache to the physical PSRAM // note the esp_cache_msync function will check the alignment of the address and size, make sure they're aligned to current cache line size esp_cache_msync((void *)ALIGN_DOWN((intptr_t)color, dcache_line_size), ALIGN_UP(color_size, dcache_line_size), 0); diff --git a/components/esp_mm/esp_cache.c b/components/esp_mm/esp_cache.c index 4784bfad90bd..6eff6cbda404 100644 --- a/components/esp_mm/esp_cache.c +++ b/components/esp_mm/esp_cache.c @@ -23,38 +23,52 @@ DEFINE_CRIT_SECTION_LOCK_STATIC(s_spinlock); esp_err_t esp_cache_msync(void *addr, size_t size, int flags) { ESP_RETURN_ON_FALSE_ISR(addr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); - ESP_RETURN_ON_FALSE_ISR(mmu_hal_check_valid_ext_vaddr_region(0, (uint32_t)addr, size, MMU_VADDR_DATA), ESP_ERR_INVALID_ARG, TAG, "invalid address"); + + uint32_t addr_end = 0; + bool ovf = __builtin_add_overflow((uint32_t)addr, size, &addr_end); + ESP_EARLY_LOGV(TAG, "addr_end: 0x%x\n", addr_end); + ESP_RETURN_ON_FALSE_ISR(!ovf, ESP_ERR_INVALID_ARG, TAG, "wrong size, total size overflow"); + bool both_dir = (flags & ESP_CACHE_MSYNC_FLAG_DIR_C2M) && (flags & ESP_CACHE_MSYNC_FLAG_DIR_M2C); ESP_RETURN_ON_FALSE_ISR(!both_dir, ESP_ERR_INVALID_ARG, TAG, "both C2M and M2C directions are selected, you should only select one"); - uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); + + uint32_t vaddr = (uint32_t)addr; + bool valid = false; + uint32_t cache_level = 0; + uint32_t cache_id = 0; + valid = cache_hal_vaddr_to_cache_level_id(vaddr, size, &cache_level, &cache_id); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_ARG, TAG, "invalid addr or null pointer"); + + uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, cache_level); if ((flags & ESP_CACHE_MSYNC_FLAG_UNALIGNED) == 0) { bool aligned_addr = (((uint32_t)addr % data_cache_line_size) == 0) && ((size % data_cache_line_size) == 0); - ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address, end address or the size is(are) not aligned with the data cache line size (%d)B", data_cache_line_size); + ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address: 0x%x, or the size: 0x%x is(are) not aligned with the data cache line size (0x%x)B", (uint32_t)addr, size, data_cache_line_size); } - uint32_t vaddr = (uint32_t)addr; if (flags & ESP_CACHE_MSYNC_FLAG_DIR_M2C) { - ESP_EARLY_LOGD(TAG, "M2C DIR"); + ESP_EARLY_LOGV(TAG, "M2C DIR"); esp_os_enter_critical_safe(&s_spinlock); //Add preload feature / flag here, IDF-7800 - cache_hal_invalidate_addr(vaddr, size); + valid = cache_hal_invalidate_addr(vaddr, size); esp_os_exit_critical_safe(&s_spinlock); - + assert(valid); } else { - ESP_EARLY_LOGD(TAG, "C2M DIR"); + ESP_EARLY_LOGV(TAG, "C2M DIR"); #if SOC_CACHE_WRITEBACK_SUPPORTED esp_os_enter_critical_safe(&s_spinlock); - cache_hal_writeback_addr(vaddr, size); + valid = cache_hal_writeback_addr(vaddr, size); esp_os_exit_critical_safe(&s_spinlock); + assert(valid); if (flags & ESP_CACHE_MSYNC_FLAG_INVALIDATE) { esp_os_enter_critical_safe(&s_spinlock); - cache_hal_invalidate_addr(vaddr, size); + valid &= cache_hal_invalidate_addr(vaddr, size); esp_os_exit_critical_safe(&s_spinlock); } + assert(valid); #endif } diff --git a/components/esp_mm/esp_mmu_map.c b/components/esp_mm/esp_mmu_map.c index 9fbc9d50b5c9..ecf0ad56a605 100644 --- a/components/esp_mm/esp_mmu_map.c +++ b/components/esp_mm/esp_mmu_map.c @@ -118,6 +118,16 @@ static bool s_is_overlapped(uint32_t block_start, uint32_t block_end, uint32_t n #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + +static cache_bus_mask_t s_get_bus_mask(uint32_t vaddr_start, uint32_t len) +{ +#if CACHE_LL_EXT_MEM_VIA_L2CACHE + return cache_ll_l2_get_bus(0, vaddr_start, len); +#else + return cache_ll_l1_get_bus(0, vaddr_start, len); +#endif +} + static void s_reserve_irom_region(mem_region_t *hw_mem_regions, int region_nums) { /** @@ -133,7 +143,7 @@ static void s_reserve_irom_region(mem_region_t *hw_mem_regions, int region_nums) irom_len_to_reserve += (uint32_t)&_instruction_reserved_start - ALIGN_DOWN_BY((uint32_t)&_instruction_reserved_start, CONFIG_MMU_PAGE_SIZE); irom_len_to_reserve = ALIGN_UP_BY(irom_len_to_reserve, CONFIG_MMU_PAGE_SIZE); - cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, (uint32_t)&_instruction_reserved_start, irom_len_to_reserve); + cache_bus_mask_t bus_mask = s_get_bus_mask((uint32_t)&_instruction_reserved_start, irom_len_to_reserve); for (int i = 0; i < SOC_MMU_LINEAR_ADDRESS_REGION_NUM; i++) { if (bus_mask & hw_mem_regions[i].bus_id) { @@ -161,7 +171,7 @@ static void s_reserve_drom_region(mem_region_t *hw_mem_regions, int region_nums) drom_len_to_reserve += (uint32_t)&_rodata_reserved_start - ALIGN_DOWN_BY((uint32_t)&_rodata_reserved_start, CONFIG_MMU_PAGE_SIZE); drom_len_to_reserve = ALIGN_UP_BY(drom_len_to_reserve, CONFIG_MMU_PAGE_SIZE); - cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, (uint32_t)&_rodata_reserved_start, drom_len_to_reserve); + cache_bus_mask_t bus_mask = s_get_bus_mask((uint32_t)&_rodata_reserved_start, drom_len_to_reserve); for (int i = 0; i < SOC_MMU_LINEAR_ADDRESS_REGION_NUM; i++) { if (bus_mask & hw_mem_regions[i].bus_id) { diff --git a/components/esp_mm/test_apps/mm/main/test_cache_msync.c b/components/esp_mm/test_apps/mm/main/test_cache_msync.c index 993edc7ff717..21ad6e5f00d9 100644 --- a/components/esp_mm/test_apps/mm/main/test_cache_msync.c +++ b/components/esp_mm/test_apps/mm/main/test_cache_msync.c @@ -23,6 +23,7 @@ #include "esp_partition.h" #include "esp_flash.h" #include "test_mm_utils.h" +#include "soc/ext_mem_defs.h" const static char *TAG = "CACHE_TEST"; @@ -32,9 +33,11 @@ const static char *TAG = "CACHE_TEST"; #define TEST_OFFSET 0x100000 #if CONFIG_IDF_TARGET_ESP32S2 -#define TEST_SYNC_START (0x3F500000 + TEST_OFFSET) +#define TEST_SYNC_START (SOC_DPORT_CACHE_ADDRESS_LOW + TEST_OFFSET) #elif CONFIG_IDF_TARGET_ESP32S3 -#define TEST_SYNC_START (0x3C000000 + TEST_OFFSET) +#define TEST_SYNC_START (SOC_DRAM0_CACHE_ADDRESS_LOW + TEST_OFFSET) +#elif CONFIG_IDF_TARGET_ESP32P4 +#define TEST_SYNC_START (SOC_DRAM_PSRAM_ADDRESS_LOW + TEST_OFFSET) #endif #define TEST_SYNC_SIZE 0x8000 diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 3c720d122afb..58f58f140155 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -341,7 +341,7 @@ void IRAM_ATTR do_multicore_settings(void) cache_bus_mask_t cache_bus_mask_core0 = cache_ll_l1_get_enabled_bus(0); #ifndef CONFIG_IDF_TARGET_ESP32 // 1. disable the cache before changing its settings. - cache_hal_disable(CACHE_TYPE_ALL); + cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif for (unsigned core = 1; core < SOC_CPU_CORES_NUM; core++) { // 2. change cache settings. All cores must have the same settings. @@ -349,7 +349,7 @@ void IRAM_ATTR do_multicore_settings(void) } #ifndef CONFIG_IDF_TARGET_ESP32 // 3. enable the cache after changing its settings. - cache_hal_enable(CACHE_TYPE_ALL); + cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); #endif } #endif //#if !CONFIG_IDF_TARGET_ESP32P4 @@ -496,7 +496,7 @@ void IRAM_ATTR call_start_cpu0(void) #endif // CONFIG_IDF_TARGET_ESP32S3 #if CONFIG_IDF_TARGET_ESP32P4 - //TODO: IDF-7516, add cache init API + //TODO: IDF-5670, add cache init API extern void esp_config_l2_cache_mode(void); esp_config_l2_cache_mode(); #endif diff --git a/components/esp_system/port/soc/esp32p4/Kconfig.cache b/components/esp_system/port/soc/esp32p4/Kconfig.cache index 46b88d730930..90bc34a8294a 100644 --- a/components/esp_system/port/soc/esp32p4/Kconfig.cache +++ b/components/esp_system/port/soc/esp32p4/Kconfig.cache @@ -1,43 +1,47 @@ menu "Cache config" - choice ESP32P4_L2_CACHE_SIZE + choice CACHE_L2_CACHE_SIZE prompt "L2 cache size" - default ESP32P4_L2_CACHE_128KB + default CACHE_L2_CACHE_128KB help L2 cache size to be set on application startup. - config ESP32P4_L2_CACHE_128KB + config CACHE_L2_CACHE_128KB bool "128KB" - config ESP32P4_L2_CACHE_256KB + config CACHE_L2_CACHE_256KB bool "256KB" - config ESP32P4_L2_CACHE_512KB + config CACHE_L2_CACHE_512KB bool "512KB" endchoice - config ESP32P4_L2_CACHE_SIZE + config CACHE_L2_CACHE_SIZE hex - default 0x20000 if ESP32P4_L2_CACHE_128KB - default 0x40000 if ESP32P4_L2_CACHE_256KB - default 0x80000 if ESP32P4_L2_CACHE_512KB + default 0x20000 if CACHE_L2_CACHE_128KB + default 0x40000 if CACHE_L2_CACHE_256KB + default 0x80000 if CACHE_L2_CACHE_512KB - choice ESP32P4_L2_CACHE_LINE_SIZE + choice CACHE_L2_CACHE_LINE_SIZE prompt "L2 cache line size" - default ESP32P4_L2_CACHE_LINE_64B if ESP32P4_L2_CACHE_128KB - default ESP32P4_L2_CACHE_LINE_64B if ESP32P4_L2_CACHE_256KB - default ESP32P4_L2_CACHE_LINE_128B if ESP32P4_L2_CACHE_512KB + default CACHE_L2_CACHE_LINE_64B if CACHE_L2_CACHE_128KB + default CACHE_L2_CACHE_LINE_64B if CACHE_L2_CACHE_256KB + default CACHE_L2_CACHE_LINE_128B if CACHE_L2_CACHE_512KB help L2 cache line size to be set on application startup. - config ESP32P4_L2_CACHE_LINE_64B + config CACHE_L2_CACHE_LINE_64B bool "64 Bytes" - depends on ESP32P4_L2_CACHE_128KB || ESP32P4_L2_CACHE_256KB - config ESP32P4_L2_CACHE_LINE_128B + depends on CACHE_L2_CACHE_128KB || CACHE_L2_CACHE_256KB + config CACHE_L2_CACHE_LINE_128B bool "128 Bytes" endchoice - config ESP32P4_L2_CACHE_LINE_SIZE + config CACHE_L2_CACHE_LINE_SIZE int - default 64 if ESP32P4_L2_CACHE_LINE_64B - default 128 if ESP32P4_L2_CACHE_LINE_128B + default 64 if CACHE_L2_CACHE_LINE_64B + default 128 if CACHE_L2_CACHE_LINE_128B + + config CACHE_L1_CACHE_LINE_SIZE + int + default 64 endmenu # Cache config diff --git a/components/hal/cache_hal.c b/components/hal/cache_hal.c index c2ab573dcdb4..ef4422f6e3c4 100644 --- a/components/hal/cache_hal.c +++ b/components/hal/cache_hal.c @@ -5,6 +5,7 @@ */ #include #include +#include #include "sdkconfig.h" #include "esp_err.h" #include "esp_attr.h" @@ -24,47 +25,45 @@ * Now this file doesn't compile on ESP32 *----------------------------------------------------------------------------*/ -/** - * To know if autoload is enabled or not. - * - * We should have a unified flag for this aim, then we don't need to call following 2 functions - * to know the flag. - * - * Suggest ROM keeping this flag value to BIT(2). Then we can replace following lines to: - * #define DATA_AUTOLOAD_FLAG BIT(2) - * #define INST_AUTOLOAD_FLAG BIT(2) - */ -#if CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-7516 -#define DATA_AUTOLOAD_ENABLE Cache_Disable_L2_Cache() -#define INST_AUTOLOAD_ENABLE Cache_Disable_L2_Cache() -#else -#define DATA_AUTOLOAD_ENABLE cache_ll_is_cache_autoload_enabled(CACHE_TYPE_DATA) -#define INST_AUTOLOAD_ENABLE cache_ll_is_cache_autoload_enabled(CACHE_TYPE_INSTRUCTION) -#endif - /** * Necessary hal contexts, could be maintained by upper layer in the future */ typedef struct { - bool data_autoload_en; - bool inst_autoload_en; + bool i_autoload_en; + bool d_autoload_en; #if CACHE_LL_ENABLE_DISABLE_STATE_SW // There's no register indicating if cache is enabled on these chips, use sw flag to save this state. - volatile bool cache_enabled; + bool i_cache_enabled; + bool d_cache_enabled; #endif +} cache_hal_state_t; + + +typedef struct { + cache_hal_state_t l1; + cache_hal_state_t l2; } cache_hal_context_t; static cache_hal_context_t ctx; + +void s_cache_hal_init_ctx(void) +{ + ctx.l1.d_autoload_en = cache_ll_is_cache_autoload_enabled(1, CACHE_TYPE_DATA, CACHE_LL_ID_ALL); + ctx.l1.i_autoload_en = cache_ll_is_cache_autoload_enabled(1, CACHE_TYPE_INSTRUCTION, CACHE_LL_ID_ALL); + ctx.l2.d_autoload_en = cache_ll_is_cache_autoload_enabled(2, CACHE_TYPE_DATA, CACHE_LL_ID_ALL); + ctx.l2.i_autoload_en = cache_ll_is_cache_autoload_enabled(2, CACHE_TYPE_INSTRUCTION, CACHE_LL_ID_ALL); +} + void cache_hal_init(void) { - ctx.data_autoload_en = DATA_AUTOLOAD_ENABLE; - ctx.inst_autoload_en = INST_AUTOLOAD_ENABLE; -#if SOC_CACHE_L2_SUPPORTED - Cache_Enable_L2_Cache(ctx.inst_autoload_en); -#else - cache_ll_enable_cache(CACHE_TYPE_ALL, ctx.inst_autoload_en, ctx.data_autoload_en); -#endif //SOC_CACHE_L2_SUPPORTED + s_cache_hal_init_ctx(); + + if (CACHE_LL_LEVEL_EXT_MEM == 1) { + cache_ll_enable_cache(1, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, ctx.l1.i_autoload_en, ctx.l1.d_autoload_en); + } else if (CACHE_LL_LEVEL_EXT_MEM == 2) { + cache_ll_enable_cache(2, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, ctx.l2.i_autoload_en, ctx.l2.d_autoload_en); + } cache_ll_l1_enable_bus(0, CACHE_LL_DEFAULT_DBUS_MASK); cache_ll_l1_enable_bus(0, CACHE_LL_DEFAULT_IBUS_MASK); @@ -74,125 +73,222 @@ void cache_hal_init(void) #endif #if CACHE_LL_ENABLE_DISABLE_STATE_SW - ctx.cache_enabled = 1; + ctx.l1.i_cache_enabled = 1; + ctx.l1.d_cache_enabled = 1; + ctx.l2.i_cache_enabled = 1; + ctx.l2.d_cache_enabled = 1; #endif } -void cache_hal_disable(cache_type_t type) +#if CACHE_LL_ENABLE_DISABLE_STATE_SW +void s_update_cache_state(uint32_t cache_level, cache_type_t type, bool en) { -#if SOC_CACHE_L2_SUPPORTED - Cache_Disable_L2_Cache(); -#else - cache_ll_disable_cache(type); -#endif //SOC_CACHE_L2_SUPPORTED + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + switch (cache_level) { + case 1: + if (type == CACHE_TYPE_INSTRUCTION) { + ctx.l1.i_cache_enabled = en; + break; + } else if (type == CACHE_TYPE_DATA) { + ctx.l1.d_cache_enabled = en; + break; + } else if (type == CACHE_TYPE_ALL) { + ctx.l1.i_cache_enabled = en; + ctx.l1.d_cache_enabled = en; + break; + } else { + HAL_ASSERT(false); + break; + } + case 2: + if (type == CACHE_TYPE_INSTRUCTION) { + ctx.l2.i_cache_enabled = en; + break; + } else if (type == CACHE_TYPE_DATA) { + ctx.l2.d_cache_enabled = en; + break; + } else if (type == CACHE_TYPE_ALL) { + ctx.l2.i_cache_enabled = en; + ctx.l2.d_cache_enabled = en; + break; + } else { + HAL_ASSERT(false); + break; + } + default: + HAL_ASSERT(false); + break; + } +} + +bool s_get_cache_state(uint32_t cache_level, cache_type_t type) +{ + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + bool enabled = false; + + switch (cache_level) { + case 1: + if (type == CACHE_TYPE_INSTRUCTION) { + enabled = ctx.l1.i_cache_enabled; + break; + } else if (type == CACHE_TYPE_DATA) { + enabled = ctx.l1.d_cache_enabled; + break; + } else if (type == CACHE_TYPE_ALL) { + enabled = ctx.l1.i_cache_enabled; + enabled &= ctx.l1.d_cache_enabled; + break; + } else { + HAL_ASSERT(false); + break; + } + case 2: + if (type == CACHE_TYPE_INSTRUCTION) { + enabled = ctx.l2.i_cache_enabled; + break; + } else if (type == CACHE_TYPE_DATA) { + enabled = ctx.l2.d_cache_enabled; + break; + } else if (type == CACHE_TYPE_ALL) { + enabled = ctx.l2.i_cache_enabled; + enabled &= ctx.l2.d_cache_enabled; + break; + } else { + HAL_ASSERT(false); + break; + } + default: + HAL_ASSERT(false); + break; + } + + return enabled; +} +#endif //#if CACHE_LL_ENABLE_DISABLE_STATE_SW + +void cache_hal_disable(cache_type_t type, uint32_t cache_level) +{ + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + cache_ll_disable_cache(cache_level, type, CACHE_LL_ID_ALL); #if CACHE_LL_ENABLE_DISABLE_STATE_SW - ctx.cache_enabled = 0; + s_update_cache_state(cache_level, type, false); #endif } -void cache_hal_enable(cache_type_t type) +void cache_hal_enable(cache_type_t type, uint32_t cache_level) { -#if SOC_CACHE_L2_SUPPORTED - Cache_Enable_L2_Cache(ctx.inst_autoload_en); -#else - cache_ll_enable_cache(type, ctx.inst_autoload_en, ctx.data_autoload_en); -#endif //SOC_CACHE_L2_SUPPORTED + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + if (cache_level == 1) { + cache_ll_enable_cache(1, type, CACHE_LL_ID_ALL, ctx.l1.i_autoload_en, ctx.l1.d_autoload_en); + } else if (cache_level == 2) { + cache_ll_enable_cache(2, type, CACHE_LL_ID_ALL, ctx.l2.i_autoload_en, ctx.l2.d_autoload_en); + } #if CACHE_LL_ENABLE_DISABLE_STATE_SW - ctx.cache_enabled = 1; + s_update_cache_state(cache_level, type, true); #endif } -void cache_hal_suspend(cache_type_t type) +void cache_hal_suspend(cache_type_t type, uint32_t cache_level) { -#if SOC_CACHE_L2_SUPPORTED - Cache_Suspend_L2_Cache(); -#else - cache_ll_suspend_cache(type); -#endif //SOC_CACHE_L2_SUPPORTED + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + cache_ll_suspend_cache(cache_level, type, CACHE_LL_ID_ALL); #if CACHE_LL_ENABLE_DISABLE_STATE_SW - ctx.cache_enabled = 0; + s_update_cache_state(cache_level, type, false); #endif } -void cache_hal_resume(cache_type_t type) +void cache_hal_resume(cache_type_t type, uint32_t cache_level) { -#if SOC_CACHE_L2_SUPPORTED - Cache_Resume_L2_Cache(ctx.inst_autoload_en); -#else - cache_ll_resume_cache(type, ctx.inst_autoload_en, ctx.data_autoload_en); -#endif + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + if (cache_level == 1) { + cache_ll_resume_cache(1, type, CACHE_LL_ID_ALL, ctx.l1.i_autoload_en, ctx.l1.d_autoload_en); + } else if (cache_level == 2) { + cache_ll_resume_cache(2, type, CACHE_LL_ID_ALL, ctx.l2.i_autoload_en, ctx.l2.d_autoload_en); + } #if CACHE_LL_ENABLE_DISABLE_STATE_SW - ctx.cache_enabled = 1; + s_update_cache_state(cache_level, type, true); #endif } -bool cache_hal_is_cache_enabled(cache_type_t type) +bool cache_hal_is_cache_enabled(cache_type_t type, uint32_t cache_level) { - bool enabled; + bool enabled = false; #if CACHE_LL_ENABLE_DISABLE_STATE_SW - enabled = ctx.cache_enabled; + enabled = s_get_cache_state(cache_level, type); #else enabled = cache_ll_is_cache_enabled(type); #endif //CACHE_LL_ENABLE_DISABLE_STATE_SW return enabled; } -void cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size) +bool cache_hal_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) { - //Now only esp32 has 2 MMUs, this file doesn't build on esp32 - HAL_ASSERT(mmu_hal_check_valid_ext_vaddr_region(0, vaddr, size, MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION)); -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE | CACHE_MAP_L2_CACHE, vaddr, size); -#else - cache_ll_invalidate_addr(vaddr, size); -#endif + if (!out_level || !out_id) { + return false; + } + return cache_ll_vaddr_to_cache_level_id(vaddr_start, len, out_level, out_id); +} + +bool cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size) +{ + bool valid = false; + uint32_t cache_level = 0; + uint32_t cache_id = 0; + + valid = cache_hal_vaddr_to_cache_level_id(vaddr, size, &cache_level, &cache_id); + if (valid) { + cache_ll_invalidate_addr(cache_level, CACHE_TYPE_ALL, cache_id, vaddr, size); + } + + return valid; } #if SOC_CACHE_WRITEBACK_SUPPORTED -void cache_hal_writeback_addr(uint32_t vaddr, uint32_t size) +bool cache_hal_writeback_addr(uint32_t vaddr, uint32_t size) { - HAL_ASSERT(mmu_hal_check_valid_ext_vaddr_region(0, vaddr, size, MMU_VADDR_DATA)); -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, vaddr, size); - Cache_WriteBack_Addr(CACHE_MAP_L2_CACHE, vaddr, size); -#else - cache_ll_writeback_addr(vaddr, size); -#endif + bool valid = false; + uint32_t cache_level = 0; + uint32_t cache_id = 0; + + valid = cache_hal_vaddr_to_cache_level_id(vaddr, size, &cache_level, &cache_id); + if (valid) { + cache_ll_writeback_addr(cache_level, CACHE_TYPE_DATA, cache_id, vaddr, size); + } + + return valid; } #endif //#if SOC_CACHE_WRITEBACK_SUPPORTED - #if SOC_CACHE_FREEZE_SUPPORTED -void cache_hal_freeze(cache_type_t type) +void cache_hal_freeze(cache_type_t type, uint32_t cache_level) { -#if SOC_CACHE_L2_SUPPORTED - Cache_Freeze_L2_Cache_Enable(CACHE_FREEZE_ACK_BUSY); -#else - cache_ll_freeze_cache(type); -#endif //SOC_CACHE_L2_SUPPORTED + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + cache_ll_freeze_cache(cache_level, type, CACHE_LL_ID_ALL); } -void cache_hal_unfreeze(cache_type_t type) +void cache_hal_unfreeze(cache_type_t type, uint32_t cache_level) { -#if SOC_CACHE_L2_SUPPORTED - Cache_Freeze_L2_Cache_Disable(); -#else - cache_ll_unfreeze_cache(type); -#endif //SOC_CACHE_L2_SUPPORTED + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + cache_ll_unfreeze_cache(cache_level, type, CACHE_LL_ID_ALL); } #endif //#if SOC_CACHE_FREEZE_SUPPORTED -uint32_t cache_hal_get_cache_line_size(cache_type_t type) +uint32_t cache_hal_get_cache_line_size(cache_type_t type, uint32_t cache_level) { - uint32_t line_size = 0; -#if SOC_CACHE_L2_SUPPORTED - line_size = Cache_Get_L2_Cache_Line_Size(); -#else - line_size = cache_ll_get_line_size(type); -#endif //SOC_CACHE_L2_SUPPORTED + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + + uint32_t line_size = cache_ll_get_line_size(cache_level, type, CACHE_LL_ID_ALL); + return line_size; } diff --git a/components/hal/esp32/cache_hal_esp32.c b/components/hal/esp32/cache_hal_esp32.c index 2cd500775f5d..895aeaa02a5d 100644 --- a/components/hal/esp32/cache_hal_esp32.c +++ b/components/hal/esp32/cache_hal_esp32.c @@ -14,7 +14,7 @@ static uint32_t s_cache_status[2]; * There's a bug that Cache_Read_Disable requires a call to Cache_Flush * before Cache_Read_Enable, even if cached data was not modified. */ -void cache_hal_suspend(cache_type_t type) +void cache_hal_suspend(cache_type_t type, uint32_t cache_level) { s_cache_status[0] = cache_ll_l1_get_enabled_bus(0); cache_ll_l1_disable_cache(0); @@ -25,7 +25,7 @@ void cache_hal_suspend(cache_type_t type) } -void cache_hal_resume(cache_type_t type) +void cache_hal_resume(cache_type_t type, uint32_t cache_level) { cache_ll_l1_enable_cache(0); cache_ll_l1_enable_bus(0, s_cache_status[0]); @@ -36,7 +36,7 @@ void cache_hal_resume(cache_type_t type) } -bool cache_hal_is_cache_enabled(cache_type_t type) +bool cache_hal_is_cache_enabled(cache_type_t type, uint32_t cache_level) { bool result = cache_ll_l1_is_cache_enabled(0, CACHE_TYPE_ALL); #if !CONFIG_FREERTOS_UNICORE @@ -44,3 +44,23 @@ bool cache_hal_is_cache_enabled(cache_type_t type) #endif return result; } + +bool cache_hal_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + if (!out_level || !out_id) { + return false; + } + return cache_ll_vaddr_to_cache_level_id(vaddr_start, len, out_level, out_id); +} + +uint32_t cache_hal_get_cache_line_size(cache_type_t type, uint32_t cache_level) +{ + HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); + return 4; +} + +bool cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size) +{ + //esp32 doesn't support invalidate certain addr + abort(); +} diff --git a/components/hal/esp32/include/hal/cache_ll.h b/components/hal/esp32/include/hal/cache_ll.h index b0256d099dda..773202ad2775 100644 --- a/components/hal/esp32/include/hal/cache_ll.h +++ b/components/hal/esp32/include/hal/cache_ll.h @@ -19,6 +19,12 @@ extern "C" { #endif +#define CACHE_LL_ID_ALL 2 //All of the caches in a type and level, make this value greater than any ID +#define CACHE_LL_LEVEL_INT_MEM 0 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 1 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 2 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 1 //Number of cache levels + /** * @brief enable a cache unit * @@ -27,7 +33,7 @@ extern "C" { __attribute__((always_inline)) static inline void cache_ll_l1_enable_cache(uint32_t cache_id) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); if (cache_id == 0) { DPORT_REG_SET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE); @@ -67,7 +73,7 @@ static inline void cache_ll_l1_disable_cache(uint32_t cache_id) __attribute__((always_inline)) static inline bool cache_ll_l1_is_cache_enabled(uint32_t cache_id, cache_type_t type) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); (void) type; //On 32 it shares between I and D cache bool enabled; @@ -94,7 +100,7 @@ __attribute__((always_inline)) #endif static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); cache_bus_mask_t mask = (cache_bus_mask_t)0; uint32_t vaddr_end = vaddr_start + len - 1; @@ -135,7 +141,7 @@ __attribute__((always_inline)) static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) { (void) mask; - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); uint32_t bus_mask = 0; if (cache_id == 0) { @@ -170,7 +176,7 @@ __attribute__((always_inline)) static inline cache_bus_mask_t cache_ll_l1_get_enabled_bus(uint32_t cache_id) { cache_bus_mask_t mask = (cache_bus_mask_t)0; - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); if (cache_id == 0) { uint32_t bus_mask= DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG); mask = (cache_bus_mask_t)(mask | ((!(bus_mask & DPORT_PRO_CACHE_MASK_IRAM0)) ? CACHE_BUS_IBUS0 : 0)); @@ -202,7 +208,7 @@ __attribute__((always_inline)) static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) { (void) mask; - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); uint32_t bus_mask = 0; if (cache_id == 0) { @@ -226,6 +232,33 @@ static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t m } } +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid + */ +__attribute__((always_inline)) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; + + valid |= ((vaddr_start >= SOC_DROM0_CACHE_ADDRESS_LOW) && (vaddr_end < SOC_DROM0_CACHE_ADDRESS_HIGH)) || ((vaddr_start >= SOC_DRAM1_CACHE_ADDRESS_LOW) && (vaddr_end < SOC_DRAM1_CACHE_ADDRESS_HIGH)); + valid |= ((vaddr_start >= SOC_IRAM0_CACHE_ADDRESS_LOW) && (vaddr_end < SOC_IRAM0_CACHE_ADDRESS_HIGH)); + + if (valid) { + *out_level = 1; + *out_id = 0; + } + + return valid; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c2/include/hal/cache_ll.h b/components/hal/esp32c2/include/hal/cache_ll.h index b4820799df01..ba192c98b608 100644 --- a/components/hal/esp32c2/include/hal/cache_ll.h +++ b/components/hal/esp32c2/include/hal/cache_ll.h @@ -36,72 +36,83 @@ extern "C" { #define CACHE_LL_L1_ILG_EVENT_PRELOAD_OP_FAULT (1<<1) #define CACHE_LL_L1_ILG_EVENT_SYNC_OP_FAULT (1<<0) +#define CACHE_LL_ID_ALL 1 //All of the caches in a type and level, make this value greater than any ID +#define CACHE_LL_LEVEL_INT_MEM 0 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 1 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 2 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 1 //Number of cache levels //On ESP32C2, the auto preload flag is always 0 #define CACHE_LL_L1_ICACHE_AUTOLOAD 0 /** - * @brief Check if Cache auto preload is enabled or not. On ESP32C2, instructions and data share Cache + * @brief Check if Cache auto preload is enabled or not. * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * - * @return false (On ESP32C2, it's always false) + * @return true: enabled; false: disabled */ __attribute__((always_inline)) -static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) +static inline bool cache_ll_is_cache_autoload_enabled(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { bool enabled = false; return enabled; } /** - * @brief Disable Cache. On ESP32C2, instructions and data share Cache + * @brief Disable Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_disable_cache(cache_type_t type) +static inline void cache_ll_disable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { (void) type; Cache_Disable_ICache(); } /** - * @brief Enable Cache. On ESP32C2, instructions and data share Cache - * - * @param type see `cache_type_t` + * @brief Enable Cache * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_enable_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_enable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Enable_ICache(CACHE_LL_L1_ICACHE_AUTOLOAD); } /** - * @brief Suspend Cache. On ESP32C2, instructions and data share Cache + * @brief Suspend Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_suspend_cache(cache_type_t type) +static inline void cache_ll_suspend_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Suspend_ICache(); } /** - * @brief Resume Cache. On ESP32C2, instructions and data share Cache + * @brief Resume Cache * - * @param type see `cache_type_t` - * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_resume_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Resume_ICache(CACHE_LL_L1_ICACHE_AUTOLOAD); } @@ -124,13 +135,16 @@ static inline bool cache_ll_is_cache_enabled(cache_type_t type) /** * @brief Invalidate cache supported addr * - * Invalidate a Cache item + * Invalidate a cache item * - * @param vaddr Start address of the region to be invalidated - * @param size Size of the region to be invalidated + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated */ __attribute__((always_inline)) -static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_invalidate_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_Invalidate_Addr(vaddr, size); } @@ -138,12 +152,14 @@ static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) /** * @brief Get Cache line size, in bytes * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * * @return Cache line size, in bytes */ __attribute__((always_inline)) -static inline uint32_t cache_ll_get_line_size(cache_type_t type) +static inline uint32_t cache_ll_get_line_size(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { uint32_t size = 0; size = Cache_Get_ICache_Line_Size(); @@ -165,7 +181,7 @@ __attribute__((always_inline)) #endif static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); cache_bus_mask_t mask = (cache_bus_mask_t)0; uint32_t vaddr_end = vaddr_start + len - 1; @@ -191,7 +207,7 @@ __attribute__((always_inline)) #endif static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32c2, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -213,7 +229,7 @@ static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t ma __attribute__((always_inline)) static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32c2, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -226,6 +242,33 @@ static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t m REG_SET_BIT(EXTMEM_ICACHE_CTRL1_REG, dbus_mask); } +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid + */ +__attribute__((always_inline)) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; + + valid |= (SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_end)); + valid |= (SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_end)); + + if (valid) { + *out_level = 1; + *out_id = 0; + } + + return valid; +} + /*------------------------------------------------------------------------------ * Interrupt *----------------------------------------------------------------------------*/ diff --git a/components/hal/esp32c3/include/hal/cache_ll.h b/components/hal/esp32c3/include/hal/cache_ll.h index 7ea850b02da4..71022d0121f1 100644 --- a/components/hal/esp32c3/include/hal/cache_ll.h +++ b/components/hal/esp32c3/include/hal/cache_ll.h @@ -36,18 +36,26 @@ extern "C" { #define CACHE_LL_L1_ILG_EVENT_PRELOAD_OP_FAULT (1<<1) #define CACHE_LL_L1_ILG_EVENT_SYNC_OP_FAULT (1<<0) +#define CACHE_LL_ID_ALL 1 //All of the caches in a type and level, make this value greater than any ID +#define CACHE_LL_LEVEL_INT_MEM 0 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 1 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 2 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 1 //Number of cache levels #define CACHE_LL_L1_ICACHE_AUTOLOAD (1<<2) /** - * @brief Check if Cache auto preload is enabled or not. On ESP32C3, instructions and data share Cache + * @brief Check if Cache auto preload is enabled or not. * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * * @return true: enabled; false: disabled */ __attribute__((always_inline)) -static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) +static inline bool cache_ll_is_cache_autoload_enabled(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); bool enabled = false; if (REG_GET_BIT(EXTMEM_ICACHE_AUTOLOAD_CTRL_REG, EXTMEM_ICACHE_AUTOLOAD_ENA)) { enabled = true; @@ -56,54 +64,58 @@ static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) } /** - * @brief Disable Cache. On ESP32C3, instructions and data share Cache + * @brief Disable Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_disable_cache(cache_type_t type) +static inline void cache_ll_disable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { (void) type; Cache_Disable_ICache(); } /** - * @brief Enable Cache. On ESP32C3, instructions and data share Cache - * - * @param type see `cache_type_t` + * @brief Enable Cache * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_enable_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_enable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Enable_ICache(inst_autoload_en ? CACHE_LL_L1_ICACHE_AUTOLOAD : 0); } /** - * @brief Suspend Cache. On ESP32C3, instructions and data share Cache + * @brief Suspend Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_suspend_cache(cache_type_t type) +static inline void cache_ll_suspend_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Suspend_ICache(); } /** - * @brief Resume Cache. On ESP32C3, instructions and data share Cache + * @brief Resume Cache * - * @param type see `cache_type_t` - * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_resume_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Resume_ICache(inst_autoload_en ? CACHE_LL_L1_ICACHE_AUTOLOAD : 0); } @@ -126,13 +138,16 @@ static inline bool cache_ll_is_cache_enabled(cache_type_t type) /** * @brief Invalidate cache supported addr * - * Invalidate a Cache + * Invalidate a cache item * - * @param vaddr Start address of the region to be invalidated - * @param size Size of the region to be invalidated + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated */ __attribute__((always_inline)) -static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_invalidate_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_Invalidate_Addr(vaddr, size); } @@ -140,12 +155,14 @@ static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) /** * @brief Get Cache line size, in bytes * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * * @return Cache line size, in bytes */ __attribute__((always_inline)) -static inline uint32_t cache_ll_get_line_size(cache_type_t type) +static inline uint32_t cache_ll_get_line_size(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { uint32_t size = 0; size = Cache_Get_ICache_Line_Size(); @@ -167,7 +184,7 @@ __attribute__((always_inline)) #endif static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); cache_bus_mask_t mask = (cache_bus_mask_t)0; uint32_t vaddr_end = vaddr_start + len - 1; @@ -193,7 +210,7 @@ __attribute__((always_inline)) #endif static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32c3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -215,7 +232,7 @@ static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t ma __attribute__((always_inline)) static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32c3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -228,6 +245,33 @@ static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t m REG_SET_BIT(EXTMEM_ICACHE_CTRL1_REG, dbus_mask); } +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid + */ +__attribute__((always_inline)) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; + + valid |= (SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_end)); + valid |= (SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_end)); + + if (valid) { + *out_level = 1; + *out_id = 0; + } + + return valid; +} + /*------------------------------------------------------------------------------ * Interrupt *----------------------------------------------------------------------------*/ diff --git a/components/hal/esp32c6/include/hal/cache_ll.h b/components/hal/esp32c6/include/hal/cache_ll.h index 9cf70595d039..6aa203eb45e2 100644 --- a/components/hal/esp32c6/include/hal/cache_ll.h +++ b/components/hal/esp32c6/include/hal/cache_ll.h @@ -26,18 +26,26 @@ extern "C" { #define CACHE_LL_L1_ACCESS_EVENT_MASK (1<<4) #define CACHE_LL_L1_ACCESS_EVENT_CACHE_FAIL (1<<4) +#define CACHE_LL_ID_ALL 1 //All of the caches in a type and level, make this value greater than any ID +#define CACHE_LL_LEVEL_INT_MEM 0 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 1 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 2 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 1 //Number of cache levels #define CACHE_LL_L1_ICACHE_AUTOLOAD (1<<0) /** - * @brief Check if Cache auto preload is enabled or not. On ESP32C6, instructions and data share Cache + * @brief Check if Cache auto preload is enabled or not. * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * * @return true: enabled; false: disabled */ __attribute__((always_inline)) -static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) +static inline bool cache_ll_is_cache_autoload_enabled(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); bool enabled = false; if (REG_GET_BIT(EXTMEM_L1_CACHE_AUTOLOAD_CTRL_REG, EXTMEM_L1_CACHE_AUTOLOAD_ENA)) { enabled = true; @@ -46,54 +54,58 @@ static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) } /** - * @brief Disable Cache. On ESP32C6, instructions and data share Cache + * @brief Disable Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_disable_cache(cache_type_t type) +static inline void cache_ll_disable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { (void) type; Cache_Disable_ICache(); } /** - * @brief Enable Cache. On ESP32C6, instructions and data share Cache + * @brief Enable Cache * - * @param type see `cache_type_t` - * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_enable_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_enable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Enable_ICache(inst_autoload_en ? CACHE_LL_L1_ICACHE_AUTOLOAD : 0); } /** - * @brief Suspend Cache. On ESP32C6, instructions and data share Cache + * @brief Suspend Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_suspend_cache(cache_type_t type) +static inline void cache_ll_suspend_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Suspend_ICache(); } /** - * @brief Resume Cache. On ESP326, instructions and data share Cache - * - * @param type see `cache_type_t` + * @brief Resume Cache * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_resume_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Resume_ICache(inst_autoload_en ? CACHE_LL_L1_ICACHE_AUTOLOAD : 0); } @@ -101,48 +113,57 @@ static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_e /** * @brief Invalidate cache supported addr * - * Invalidate a Cache item + * Invalidate a cache item * - * @param vaddr Start address of the region to be invalidated - * @param size Size of the region to be invalidated + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated */ __attribute__((always_inline)) -static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_invalidate_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_Invalidate_Addr(vaddr, size); } /** - * @brief Freeze Cache. On ESP32C6, instructions and data share Cache + * @brief Freeze Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_freeze_cache(cache_type_t type) +static inline void cache_ll_freeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY); } /** - * @brief Unfreeze Cache. On ESP32C6, instructions and data share Cache + * @brief Unfreeze Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_unfreeze_cache(cache_type_t type) +static inline void cache_ll_unfreeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Freeze_ICache_Disable(); } /** - * @brief Get cache line size, in bytes + * @brief Get Cache line size, in bytes * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * - * @return cache line size, in bytes + * @return Cache line size, in bytes */ __attribute__((always_inline)) -static inline uint32_t cache_ll_get_line_size(cache_type_t type) +static inline uint32_t cache_ll_get_line_size(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { uint32_t size = 0; size = Cache_Get_ICache_Line_Size(); @@ -164,7 +185,7 @@ __attribute__((always_inline)) #endif static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); cache_bus_mask_t mask = (cache_bus_mask_t)0; uint32_t vaddr_end = vaddr_start + len - 1; @@ -189,7 +210,7 @@ __attribute__((always_inline)) #endif static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32c6, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -211,7 +232,7 @@ static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t ma __attribute__((always_inline)) static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32c6, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -224,6 +245,33 @@ static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t m REG_SET_BIT(EXTMEM_L1_CACHE_CTRL_REG, dbus_mask); } +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid + */ +__attribute__((always_inline)) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; + + valid |= (SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_end)); + valid |= (SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_end)); + + if (valid) { + *out_level = 1; + *out_id = 0; + } + + return valid; +} + /*------------------------------------------------------------------------------ * Interrupt *----------------------------------------------------------------------------*/ diff --git a/components/hal/esp32h2/include/hal/cache_ll.h b/components/hal/esp32h2/include/hal/cache_ll.h index 8f60f3e635c5..280e4a489a86 100644 --- a/components/hal/esp32h2/include/hal/cache_ll.h +++ b/components/hal/esp32h2/include/hal/cache_ll.h @@ -26,18 +26,26 @@ extern "C" { #define CACHE_LL_L1_ACCESS_EVENT_MASK (1<<4) #define CACHE_LL_L1_ACCESS_EVENT_CACHE_FAIL (1<<4) +#define CACHE_LL_ID_ALL 1 //All of the caches in a type and level, make this value greater than any ID +#define CACHE_LL_LEVEL_INT_MEM 0 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 1 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 2 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 1 //Number of cache levels #define CACHE_LL_L1_ICACHE_AUTOLOAD (1<<0) /** - * @brief Check if Cache auto preload is enabled or not. On ESP32h2, instructions and data share Cache + * @brief Check if Cache auto preload is enabled or not. * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * * @return true: enabled; false: disabled */ __attribute__((always_inline)) -static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) +static inline bool cache_ll_is_cache_autoload_enabled(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); bool enabled = false; if (REG_GET_BIT(CACHE_L1_CACHE_AUTOLOAD_CTRL_REG, CACHE_L1_CACHE_AUTOLOAD_ENA)) { enabled = true; @@ -46,54 +54,58 @@ static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) } /** - * @brief Disable Cache. On ESP32H2, instructions and data share Cache + * @brief Disable Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_disable_cache(cache_type_t type) +static inline void cache_ll_disable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { (void) type; Cache_Disable_ICache(); } /** - * @brief Enable Cache. On ESP32H2, instructions and data share Cache + * @brief Enable Cache * - * @param type see `cache_type_t` - * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_enable_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_enable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Enable_ICache(inst_autoload_en ? CACHE_LL_L1_ICACHE_AUTOLOAD : 0); } /** - * @brief Suspend Cache. On ESP32H2, instructions and data share Cache + * @brief Suspend Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_suspend_cache(cache_type_t type) +static inline void cache_ll_suspend_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Suspend_ICache(); } /** - * @brief Resume Cache. On ESP326, instructions and data share Cache - * - * @param type see `cache_type_t` + * @brief Resume Cache * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_resume_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { Cache_Resume_ICache(inst_autoload_en ? CACHE_LL_L1_ICACHE_AUTOLOAD : 0); } @@ -101,48 +113,57 @@ static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_e /** * @brief Invalidate cache supported addr * - * Invalidate a Cache item + * Invalidate a cache item * - * @param vaddr Start address of the region to be invalidated - * @param size Size of the region to be invalidated + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated */ __attribute__((always_inline)) -static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_invalidate_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_Invalidate_Addr(vaddr, size); } /** - * @brief Freeze Cache. On ESP32H2, instructions and data share Cache + * @brief Freeze Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_freeze_cache(cache_type_t type) +static inline void cache_ll_freeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY); } /** - * @brief Unfreeze Cache. On ESP32H2, instructions and data share Cache + * @brief Unfreeze Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_unfreeze_cache(cache_type_t type) +static inline void cache_ll_unfreeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { Cache_Freeze_ICache_Disable(); } /** - * @brief Get cache line size, in bytes + * @brief Get Cache line size, in bytes * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * - * @return cache line size, in bytes + * @return Cache line size, in bytes */ __attribute__((always_inline)) -static inline uint32_t cache_ll_get_line_size(cache_type_t type) +static inline uint32_t cache_ll_get_line_size(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { uint32_t size = 0; size = Cache_Get_ICache_Line_Size(); @@ -164,7 +185,7 @@ __attribute__((always_inline)) #endif static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); cache_bus_mask_t mask = (cache_bus_mask_t)0; uint32_t vaddr_end = vaddr_start + len - 1; @@ -189,7 +210,7 @@ __attribute__((always_inline)) #endif static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32h2, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -211,7 +232,7 @@ static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t ma __attribute__((always_inline)) static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32h2, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -224,6 +245,33 @@ static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t m REG_SET_BIT(CACHE_L1_CACHE_CTRL_REG, dbus_mask); } +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid + */ +__attribute__((always_inline)) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; + + valid |= (SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_end)); + valid |= (SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_end)); + + if (valid) { + *out_level = 1; + *out_id = 0; + } + + return valid; +} + /*------------------------------------------------------------------------------ * Interrupt *----------------------------------------------------------------------------*/ diff --git a/components/hal/esp32p4/include/hal/cache_ll.h b/components/hal/esp32p4/include/hal/cache_ll.h index 9dd1109c1789..2054bebf5df5 100644 --- a/components/hal/esp32p4/include/hal/cache_ll.h +++ b/components/hal/esp32p4/include/hal/cache_ll.h @@ -8,10 +8,12 @@ #pragma once +#include #include "soc/cache_reg.h" #include "soc/ext_mem_defs.h" #include "hal/cache_types.h" #include "hal/assert.h" +#include "esp32p4/rom/cache.h" #ifdef __cplusplus extern "C" { @@ -23,43 +25,945 @@ extern "C" { */ #define CACHE_LL_L2MEM_NON_CACHE_ADDR(addr) ((intptr_t)(addr) + 0x40000000) +/** + * Cache capabilities + */ #define CACHE_LL_ENABLE_DISABLE_STATE_SW 1 //There's no register indicating cache enable/disable state, we need to use software way for this state. +#define CACHE_LL_EXT_MEM_VIA_L2CACHE 1 -#define CACHE_LL_DEFAULT_IBUS_MASK CACHE_BUS_IBUS0 -#define CACHE_LL_DEFAULT_DBUS_MASK CACHE_BUS_DBUS0 +#define CACHE_LL_ID_ALL 3 //All of the caches in a type and level, make this value greater than any ID +#define CACHE_LL_LEVEL_INT_MEM 1 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 2 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 3 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 2 //Number of cache levels +#define CACHE_LL_CACHE_AUTOLOAD (1<<0) -//TODO: IDF-7516 +#define CACHE_LL_DEFAULT_IBUS_MASK (CACHE_BUS_IBUS0 | CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2) +#define CACHE_LL_DEFAULT_DBUS_MASK (CACHE_BUS_DBUS0 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2) + +//TODO: IDF-7515 #define CACHE_LL_L1_ACCESS_EVENT_MASK (0x3f) -// #define CACHE_LL_L1_ACCESS_EVENT_DBUS_WR_IC (1<<5) -// #define CACHE_LL_L1_ACCESS_EVENT_DBUS_REJECT (1<<4) -// #define CACHE_LL_L1_ACCESS_EVENT_DBUS_ACS_MSK_IC (1<<3) -// #define CACHE_LL_L1_ACCESS_EVENT_IBUS_REJECT (1<<2) -// #define CACHE_LL_L1_ACCESS_EVENT_IBUS_WR_IC (1<<1) -// #define CACHE_LL_L1_ACCESS_EVENT_IBUS_ACS_MSK_IC (1<<0) -// #define CACHE_LL_L1_ILG_EVENT_MASK (0x23) -// #define CACHE_LL_L1_ILG_EVENT_MMU_ENTRY_FAULT (1<<5) -// #define CACHE_LL_L1_ILG_EVENT_PRELOAD_OP_FAULT (1<<1) -// #define CACHE_LL_L1_ILG_EVENT_SYNC_OP_FAULT (1<<0) +/*------------------------------------------------------------------------------ + * Autoload + *----------------------------------------------------------------------------*/ /** - * @brief Get the buses of a particular cache that are mapped to a virtual address range + * @brief Check if L1 ICache autoload is enabled or not + * + * @param cache_id id of the cache in this type and level + * + * @return true: enabled; false: disabled + */ +__attribute__((always_inline)) +static inline bool cache_ll_l1_is_icache_autoload_enabled(uint32_t cache_id) +{ + bool enabled = false; + + if (cache_id == 0) { + enabled = REG_GET_BIT(CACHE_L1_ICACHE0_AUTOLOAD_CTRL_REG, CACHE_L1_ICACHE0_AUTOLOAD_ENA); + } else if (cache_id == 1) { + enabled = REG_GET_BIT(CACHE_L1_ICACHE1_AUTOLOAD_CTRL_REG, CACHE_L1_ICACHE1_AUTOLOAD_ENA); + } else if (cache_id == CACHE_LL_ID_ALL) { + enabled = REG_GET_BIT(CACHE_L1_ICACHE0_AUTOLOAD_CTRL_REG, CACHE_L1_ICACHE0_AUTOLOAD_ENA) && REG_GET_BIT(CACHE_L1_ICACHE1_AUTOLOAD_CTRL_REG, CACHE_L1_ICACHE1_AUTOLOAD_ENA); + } + + return enabled; +} + +/** + * @brief Check if L1 DCache autoload is enabled or not + * + * @param cache_id id of the cache in this type and level + * + * @return true: enabled; false: disabled + */ +__attribute__((always_inline)) +static inline bool cache_ll_l1_is_dcache_autoload_enabled(uint32_t cache_id) +{ + bool enabled = false; + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + enabled = REG_GET_BIT(CACHE_L1_DCACHE_AUTOLOAD_CTRL_REG, CACHE_L1_DCACHE_AUTOLOAD_ENA); + } + return enabled; +} + +/** + * @brief Check if L2 Cache auto preload is enabled or not + * + * @param cache_id id of the cache in this type and level + * + * @return true: enabled; false: disabled + */ +__attribute__((always_inline)) +static inline bool cache_ll_l2_is_cache_autoload_enabled(uint32_t cache_id) +{ + bool enabled = false; + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + enabled = REG_GET_BIT(CACHE_L2_CACHE_AUTOLOAD_CTRL_REG, CACHE_L2_CACHE_AUTOLOAD_ENA); + } + return enabled; +} + +/** + * @brief Check if Cache auto preload is enabled or not. + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * + * @return true: enabled; false: disabled + */ +__attribute__((always_inline)) +static inline bool cache_ll_is_cache_autoload_enabled(uint32_t cache_level, cache_type_t type, uint32_t cache_id) +{ + bool enabled = false; + + if (cache_level == 2) { + enabled = cache_ll_l2_is_cache_autoload_enabled(cache_id); + } else if (cache_level == 1) { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + enabled = cache_ll_l1_is_icache_autoload_enabled(cache_id); + break; + case CACHE_TYPE_DATA: + enabled = cache_ll_l1_is_dcache_autoload_enabled(cache_id); + break; + case CACHE_TYPE_ALL: + default: //CACHE_TYPE_ALL + enabled = cache_ll_l1_is_icache_autoload_enabled(CACHE_LL_ID_ALL) && cache_ll_l1_is_dcache_autoload_enabled(cache_id); + break; + } + } + + return enabled; +} + +/*------------------------------------------------------------------------------ + * Disable + *----------------------------------------------------------------------------*/ +/** + * @brief Disable L1 ICache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_disable_icache(uint32_t cache_id) +{ + if (cache_id == 0) { + Cache_Disable_L1_CORE0_ICache(); + } else if (cache_id == 1) { + Cache_Disable_L1_CORE1_ICache(); + } else if (cache_id == CACHE_LL_ID_ALL) { + Cache_Disable_L1_CORE0_ICache(); + Cache_Disable_L1_CORE1_ICache(); + } +} + +/** + * @brief Disable L1 DCache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_disable_dcache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Disable_L1_DCache(); + } +} + +/** + * @brief Disable L2 Cache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_disable_cache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Disable_L2_Cache(); + } +} + +/** + * @brief Disable Cache + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_disable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) +{ + HAL_ASSERT(cache_level == 1 || cache_level == 2); + + if (cache_level == 1) { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + cache_ll_l1_disable_icache(cache_id); + break; + case CACHE_TYPE_DATA: + cache_ll_l1_disable_dcache(cache_id); + break; + case CACHE_TYPE_ALL: + default: + cache_ll_l1_disable_icache(CACHE_LL_ID_ALL); + cache_ll_l1_disable_dcache(cache_id); + break; + } + } else { + cache_ll_l2_disable_cache(cache_id); + } +} + +/*------------------------------------------------------------------------------ + * Enable + *----------------------------------------------------------------------------*/ +/** + * @brief Enable L1 ICache + * + * @param cache_id id of the cache in this type and level + * @param inst_autoload_en icache autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_enable_icache(uint32_t cache_id, bool inst_autoload_en) +{ + if (cache_id == 0) { + Cache_Enable_L1_CORE0_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } else if (cache_id == 1) { + Cache_Enable_L1_CORE1_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } else if (cache_id == CACHE_LL_ID_ALL) { + Cache_Enable_L1_CORE1_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + Cache_Enable_L1_CORE0_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } +} + +/** + * @brief Enable L1 DCache + * + * @param cache_id id of the cache in this type and level + * @param data_autoload_en dcache autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_enable_dcache(uint32_t cache_id, bool data_autoload_en) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Enable_L1_DCache(data_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } +} + +/** + * @brief Enable L2 Cache + * + * @param cache_id id of the cache in this type and level + * @param inst_autoload_en autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_enable_cache(uint32_t cache_id, bool autoload_en) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Enable_L2_Cache(autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } +} + +/** + * @brief Enable Cache + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_enable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) +{ + HAL_ASSERT(cache_level == 1 || cache_level == 2); + + if (cache_level == 2) { + cache_ll_l2_enable_cache(cache_id, inst_autoload_en); + } else { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + cache_ll_l1_enable_icache(cache_id, inst_autoload_en); + break; + case CACHE_TYPE_DATA: + cache_ll_l1_enable_dcache(cache_id, data_autoload_en); + break; + case CACHE_TYPE_ALL: + default: + cache_ll_l1_enable_dcache(cache_id, data_autoload_en); + cache_ll_l1_enable_icache(cache_id, inst_autoload_en); + break; + } + } +} + +/*------------------------------------------------------------------------------ + * Suspend + *----------------------------------------------------------------------------*/ +/** + * @brief Suspend L1 ICache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_suspend_icache(uint32_t cache_id) +{ + if (cache_id == 0) { + Cache_Suspend_L1_CORE0_ICache(); + } else if (cache_id == 1) { + Cache_Suspend_L1_CORE1_ICache(); + } else if (cache_id == CACHE_LL_ID_ALL) { + Cache_Suspend_L1_CORE0_ICache(); + Cache_Suspend_L1_CORE1_ICache(); + } +} + +/** + * @brief Suspend L1 DCache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_suspend_dcache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Suspend_L1_DCache(); + } +} + +/** + * @brief Suspend L2 Cache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_suspend_cache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Suspend_L2_Cache(); + } +} + +/** + * @brief Suspend Cache + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_suspend_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) +{ + HAL_ASSERT(cache_level == 1 || cache_level == 2); + + if (cache_level == 1) { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + cache_ll_l1_suspend_icache(cache_id); + break; + case CACHE_TYPE_DATA: + cache_ll_l1_suspend_dcache(cache_id); + break; + case CACHE_TYPE_ALL: + default: + cache_ll_l1_suspend_icache(CACHE_LL_ID_ALL); + cache_ll_l1_suspend_dcache(cache_id); + break; + } + } else { + cache_ll_l2_suspend_cache(cache_id); + } +} + +/*------------------------------------------------------------------------------ + * Resume + *----------------------------------------------------------------------------*/ +/** + * @brief Resume L1 ICache + * + * @param cache_id id of the cache in this type and level + * @param inst_autoload_en icache autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_resume_icache(uint32_t cache_id, bool inst_autoload_en) +{ + if (cache_id == 0) { + Cache_Resume_L1_CORE0_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } else if (cache_id == 1) { + Cache_Resume_L1_CORE1_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } else if (cache_id == CACHE_LL_ID_ALL) { + Cache_Resume_L1_CORE1_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + Cache_Resume_L1_CORE0_ICache(inst_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } +} + +/** + * @brief Resume L1 DCache + * + * @param cache_id id of the cache in this type and level + * @param data_autoload_en dcache autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_resume_dcache(uint32_t cache_id, bool data_autoload_en) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Resume_L1_DCache(data_autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } +} + +/** + * @brief Resume L2 Cache + * + * @param cache_id id of the cache in this type and level + * @param inst_autoload_en autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_resume_cache(uint32_t cache_id, bool autoload_en) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Resume_L2_Cache(autoload_en ? CACHE_LL_CACHE_AUTOLOAD : 0); + } +} + +/** + * @brief Resume Cache + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not + */ +__attribute__((always_inline)) +static inline void cache_ll_resume_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) +{ + HAL_ASSERT(cache_level == 1 || cache_level == 2); + + if (cache_level == 2) { + cache_ll_l2_resume_cache(cache_id, inst_autoload_en); + } else { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + cache_ll_l1_resume_icache(cache_id, inst_autoload_en); + break; + case CACHE_TYPE_DATA: + cache_ll_l1_resume_dcache(cache_id, data_autoload_en); + break; + case CACHE_TYPE_ALL: + default: + cache_ll_l1_resume_dcache(cache_id, data_autoload_en); + cache_ll_l1_resume_icache(CACHE_LL_ID_ALL, inst_autoload_en); + break; + } + } +} + +/*------------------------------------------------------------------------------ + * Invalidate + *----------------------------------------------------------------------------*/ +/** + * @brief Invalidate L1 ICache addr + * + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_invalidate_icache_addr(uint32_t cache_id, uint32_t vaddr, uint32_t size) +{ + if (cache_id == 0) { + Cache_Invalidate_Addr(CACHE_MAP_L1_ICACHE_0, vaddr, size); + } else if (cache_id == 1) { + Cache_Invalidate_Addr(CACHE_MAP_L1_ICACHE_1, vaddr, size); + } else if (cache_id == CACHE_LL_ID_ALL) { + Cache_Invalidate_Addr(CACHE_MAP_L1_ICACHE_MASK, vaddr, size); + } +} + +/** + * @brief Invalidate L1 DCache addr + * + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_invalidate_dcache_addr(uint32_t cache_id, uint32_t vaddr, uint32_t size) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE, vaddr, size); + } +} + +/** + * @brief Invalidate L2 Cache addr + * + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_invalidate_cache_addr(uint32_t cache_id, uint32_t vaddr, uint32_t size) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Invalidate_Addr(CACHE_MAP_L2_CACHE, vaddr, size); + } +} + +/** + * @brief Invalidate cache supported addr + * + * Invalidate a cache item + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated + */ +__attribute__((always_inline)) +static inline void cache_ll_invalidate_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) +{ + if (cache_level == 1 || cache_level == 2 || cache_level == CACHE_LL_LEVEL_ALL) { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + cache_ll_l1_invalidate_icache_addr(cache_id, vaddr, size); + break; + case CACHE_TYPE_DATA: + cache_ll_l1_invalidate_dcache_addr(cache_id, vaddr, size); + break; + case CACHE_TYPE_ALL: + default: + cache_ll_l1_invalidate_icache_addr(cache_id, vaddr, size); + cache_ll_l1_invalidate_dcache_addr(cache_id, vaddr, size); + break; + } + } + + if (cache_level == 2 || cache_level == CACHE_LL_LEVEL_ALL) { + cache_ll_l2_invalidate_cache_addr(cache_id, vaddr, size); + } +} + +/*------------------------------------------------------------------------------ + * Writeback + *----------------------------------------------------------------------------*/ +/** + * @brief Writeback L1 DCache addr + * + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be written back + * @param size size of the region to be written back + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_writeback_dcache_addr(uint32_t cache_id, uint32_t vaddr, uint32_t size) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, vaddr, size); + } +} + +/** + * @brief Writeback L2 Cache addr + * + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be written back + * @param size size of the region to be written back + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_writeback_cache_addr(uint32_t cache_id, uint32_t vaddr, uint32_t size) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_WriteBack_Addr(CACHE_MAP_L2_CACHE, vaddr, size); + } +} + +/** + * @brief Writeback cache supported addr + * + * Writeback a cache item + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be written back + * @param size size of the region to be written back + */ +__attribute__((always_inline)) +static inline void cache_ll_writeback_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) +{ + if (cache_level == 1 || cache_level == 2 || cache_level == CACHE_LL_LEVEL_ALL) { + switch (type) { + case CACHE_TYPE_DATA: + cache_ll_l1_writeback_dcache_addr(cache_id, vaddr, size); + break; + default: + HAL_ASSERT(false); + } + } + + if (cache_level == 2 || cache_level == CACHE_LL_LEVEL_ALL) { + cache_ll_l2_writeback_cache_addr(cache_id, vaddr, size); + } +} + +/** + * @brief Writeback L1 DCache all + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_writeback_dcache_all(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_WriteBack_All(CACHE_MAP_L1_DCACHE); + } +} + +/** + * @brief Writeback L2 Cache all + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_writeback_cache_all(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_WriteBack_All(CACHE_MAP_L2_CACHE); + } +} + +/** + * @brief Writeback all + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_writeback_all(uint32_t cache_level, cache_type_t type, uint32_t cache_id) +{ + if (cache_level == 1 || cache_level == 2 || cache_level == CACHE_LL_LEVEL_ALL) { + switch (type) { + case CACHE_TYPE_DATA: + cache_ll_l1_writeback_dcache_all(cache_id); + break; + default: + HAL_ASSERT(false); + } + } + + if (cache_level == 2 || cache_level == CACHE_LL_LEVEL_ALL) { + cache_ll_l2_writeback_cache_all(cache_id); + } +} + +/*------------------------------------------------------------------------------ + * Freeze + *----------------------------------------------------------------------------*/ +/** + * @brief Freeze L1 ICache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_freeze_icache(uint32_t cache_id) +{ + if (cache_id == 0) { + Cache_Freeze_L1_ICache0_Enable(CACHE_FREEZE_ACK_BUSY); + } else if (cache_id == 1) { + Cache_Freeze_L1_ICache1_Enable(CACHE_FREEZE_ACK_BUSY); + } else if (cache_id == CACHE_LL_ID_ALL) { + Cache_Freeze_L1_ICache0_Enable(CACHE_FREEZE_ACK_BUSY); + Cache_Freeze_L1_ICache1_Enable(CACHE_FREEZE_ACK_BUSY); + } +} + +/** + * @brief Freeze L1 DCache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_freeze_dcache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Freeze_L1_DCache_Enable(CACHE_FREEZE_ACK_BUSY); + } +} + +/** + * @brief Freeze L2 Cache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_freeze_cache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Freeze_L2_Cache_Enable(CACHE_FREEZE_ACK_BUSY); + } +} + +/** + * @brief Freeze Cache + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_freeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) +{ + HAL_ASSERT(cache_level == 1 || cache_level == 2); + + if (cache_level == 1) { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + cache_ll_l1_freeze_icache(cache_id); + break; + case CACHE_TYPE_DATA: + cache_ll_l1_freeze_dcache(cache_id); + break; + default: + cache_ll_l1_freeze_icache(CACHE_LL_ID_ALL); + cache_ll_l1_freeze_dcache(cache_id); + break; + } + } else { + cache_ll_l2_freeze_cache(cache_id); + } +} + +/*------------------------------------------------------------------------------ + * Unfreeze + *----------------------------------------------------------------------------*/ +/** + * @brief Unfreeze L1 ICache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_unfreeze_icache(uint32_t cache_id) +{ + if (cache_id == 0) { + Cache_Freeze_L1_ICache0_Disable(); + } else if (cache_id == 1) { + Cache_Freeze_L1_ICache1_Disable(); + } else if (cache_id == CACHE_LL_ID_ALL) { + Cache_Freeze_L1_ICache1_Disable(); + Cache_Freeze_L1_ICache0_Disable(); + } +} + +/** + * @brief Unfreeze L1 DCache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_unfreeze_dcache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Freeze_L1_DCache_Disable(); + } +} + +/** + * @brief Unfreeze L2 Cache + * + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_l2_unfreeze_cache(uint32_t cache_id) +{ + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + Cache_Freeze_L2_Cache_Disable(); + } +} + +/** + * @brief Unfreeze Cache + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + */ +__attribute__((always_inline)) +static inline void cache_ll_unfreeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) +{ + HAL_ASSERT(cache_level == 1 || cache_level == 2); + + if (cache_level == 2) { + cache_ll_l2_unfreeze_cache(cache_id); + } else { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + cache_ll_l1_unfreeze_icache(cache_id); + break; + case CACHE_TYPE_DATA: + cache_ll_l1_unfreeze_dcache(cache_id); + break; + case CACHE_TYPE_ALL: + default: + cache_ll_l1_unfreeze_dcache(cache_id); + cache_ll_l1_unfreeze_icache(CACHE_LL_ID_ALL); + break; + } + } +} + +/*------------------------------------------------------------------------------ + * Cache Line Size + *----------------------------------------------------------------------------*/ +/** + * @brief Get ICache line size, in bytes + * + * @param cache_id id of the cache in this type and level + * + * @return ICache line size, in bytes + */ +__attribute__((always_inline)) +static inline uint32_t cache_ll_l1_icache_get_line_size(uint32_t cache_id) +{ + uint32_t size = 0; + + if (cache_id == 0 || cache_id == 1 || cache_id == CACHE_LL_ID_ALL) { + size = 64; + } + + return size; +} + +/** + * @brief Get DCache line size, in bytes + * + * @param cache_id id of the cache in this type and level + * + * @return DCache line size, in bytes + */ +__attribute__((always_inline)) +static inline uint32_t cache_ll_l1_dcache_get_line_size(uint32_t cache_id) +{ + uint32_t size = 0; + + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + size = 64; + } + + return size; +} + +/** + * @brief Get L2 Cache line size, in bytes + * + * @param cache_id id of the cache in this type and level + * + * @return L2 Cache line size, in bytes + */ +__attribute__((always_inline)) +static inline uint32_t cache_ll_l2_cache_get_line_size(uint32_t cache_id) +{ + uint32_t size = 0; + + if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) { + size = Cache_Get_L2_Cache_Line_Size(); + } + + return size; +} + +/** + * @brief Get Cache line size, in bytes + * + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * + * @return Cache line size, in bytes + */ +__attribute__((always_inline)) +static inline uint32_t cache_ll_get_line_size(uint32_t cache_level, cache_type_t type, uint32_t cache_id) +{ + HAL_ASSERT(cache_level == 1 || cache_level == 2); + + uint32_t size = 0; + if (cache_level == 2) { + size = cache_ll_l2_cache_get_line_size(cache_id); + } else { + switch (type) { + case CACHE_TYPE_INSTRUCTION: + size = cache_ll_l1_icache_get_line_size(cache_id); + break; + case CACHE_TYPE_DATA: + size = cache_ll_l1_dcache_get_line_size(cache_id); + break; + case CACHE_TYPE_ALL: + default: + break; + } + } + + return size; +} + +/*------------------------------------------------------------------------------ + * Cache Bus + *----------------------------------------------------------------------------*/ +/** + * @brief Get the buses of a particular L1 Cache that are mapped to a virtual address range * * External virtual address can only be accessed when the involved cache buses are enabled. * This API is to get the cache buses where the memory region (from `vaddr_start` to `vaddr_start + len`) reside. * - * This api in esp32p4 is not used. There is no hardware interface to mask the i/dbus to l2 cache. Needs check, TODO: IDF-7516 - * * @param cache_id cache ID (when l1 cache is per core) * @param vaddr_start virtual address start * @param len vaddr length */ -#if !BOOTLOADER_BUILD __attribute__((always_inline)) -#endif static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + return (cache_bus_mask_t)(CACHE_LL_DEFAULT_IBUS_MASK | CACHE_LL_DEFAULT_DBUS_MASK); +} + +/** + * Enable the L1 Cache Buses + * + * @param cache_id cache ID (when l1 cache is per core) + * @param mask To know which buses should be enabled + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) +{ + //not used, for compatibility +} + +/** + * Disable the Cache Buses + * + * @param cache_id cache ID (when l1 cache is per core) + * @param mask To know which buses should be disabled + */ +__attribute__((always_inline)) +static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) +{ + //not used, for compatibility +} + +/** + * @brief Get the buses of a particular cache that are mapped to a virtual address range + * + * @param cache_id cache ID + * @param vaddr_start virtual address start + * @param len vaddr length + */ +__attribute__((always_inline)) +static inline cache_bus_mask_t cache_ll_l2_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) +{ + (void)cache_id; cache_bus_mask_t mask = (cache_bus_mask_t)0; uint32_t vaddr_end = vaddr_start + len - 1; @@ -70,38 +974,40 @@ static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t v mask = (cache_bus_mask_t)(mask | CACHE_BUS_IBUS1); mask = (cache_bus_mask_t)(mask | CACHE_BUS_DBUS1); } else { - HAL_ASSERT(0); //Out of region + HAL_ASSERT(0); } return mask; } /** - * Enable the Cache Buses + * @brief Get Cache level and the ID of the vaddr * - * This api is not used in esp32p4. Needs check, TODO: IDF-7516 + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id * - * @param cache_id cache ID (when l1 cache is per core) - * @param mask To know which buses should be enabled + * @return true for valid */ -#if !BOOTLOADER_BUILD __attribute__((always_inline)) -#endif -static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) { -} + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; -/** - * Disable the Cache Buses - * - * This api is not used in esp32p4. Needs check, TODO: IDF-7516 - * - * @param cache_id cache ID (when l1 cache is per core) - * @param mask To know which buses should be disabled - */ -__attribute__((always_inline)) -static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) -{ + if (vaddr_start >= SOC_IRAM0_ADDRESS_LOW && vaddr_end < SOC_IRAM0_ADDRESS_HIGH) { + *out_level = 1; + *out_id = CACHE_LL_ID_ALL; + valid = true; + } else if (vaddr_start >= SOC_DRAM_FLASH_ADDRESS_LOW && vaddr_end < SOC_DRAM_PSRAM_ADDRESS_HIGH) { + //PSRAM vaddr is right after the FLASH vaddr + *out_level = 2; + *out_id = CACHE_LL_ID_ALL; + valid = true; + } + + return valid; } /*------------------------------------------------------------------------------ diff --git a/components/hal/esp32s2/include/hal/cache_ll.h b/components/hal/esp32s2/include/hal/cache_ll.h index 4e575c948704..0a2ecbde7a0e 100644 --- a/components/hal/esp32s2/include/hal/cache_ll.h +++ b/components/hal/esp32s2/include/hal/cache_ll.h @@ -23,6 +23,11 @@ extern "C" { #define CACHE_LL_DEFAULT_IBUS_MASK CACHE_BUS_IBUS0 #define CACHE_LL_DEFAULT_DBUS_MASK CACHE_BUS_IBUS2 +#define CACHE_LL_ID_ALL 1 //All of the caches in a type and level, make this value greater than any ID +#define CACHE_LL_LEVEL_INT_MEM 0 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 1 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 2 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 1 //Number of cache levels #define CACHE_LL_L1_ICACHE_AUTOLOAD (1<<0) #define CACHE_LL_L1_DCACHE_AUTOLOAD (1<<0) @@ -57,15 +62,18 @@ static inline bool cache_ll_l1_is_dcache_autoload_enabled(void) } /** - * @brief Check if ICache or DCache auto preload is enabled or not + * @brief Check if Cache auto preload is enabled or not. * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * * @return true: enabled; false: disabled */ __attribute__((always_inline)) -static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) +static inline bool cache_ll_is_cache_autoload_enabled(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); bool enabled = false; switch (type) { @@ -101,12 +109,14 @@ static inline void cache_ll_l1_disable_dcache(void) } /** - * @brief Disable ICache or DCache or both + * @brief Disable Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_disable_cache(cache_type_t type) +static inline void cache_ll_disable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { switch (type) { @@ -146,16 +156,16 @@ static inline void cache_ll_l1_enable_dcache(bool data_autoload_en) } /** - * @brief Enable ICache or DCache or both - * - * @param type see `cache_type_t` - * - * @param data_autoload_en Dcache auto preload enabled + * @brief Enable Cache * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_enable_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_enable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { switch (type) { @@ -191,12 +201,14 @@ static inline void cache_ll_l1_suspend_dcache(void) } /** - * @brief Suspend ICache or DCache or both + * @brief Suspend Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_suspend_cache(cache_type_t type) +static inline void cache_ll_suspend_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { switch (type) { @@ -236,16 +248,16 @@ static inline void cache_ll_l1_resume_dcache(bool data_autoload_en) } /** - * @brief Resume ICache or DCache or both + * @brief Resume Cache * - * @param type see `cache_type_t` - * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_resume_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { switch (type) { @@ -271,7 +283,7 @@ static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_e */ __attribute__((always_inline)) static inline bool cache_ll_l1_is_icache_enabled(uint32_t cache_id){ - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); bool enabled; enabled = REG_GET_BIT(EXTMEM_PRO_ICACHE_CTRL_REG, EXTMEM_PRO_ICACHE_ENABLE); @@ -288,7 +300,7 @@ static inline bool cache_ll_l1_is_icache_enabled(uint32_t cache_id){ __attribute__((always_inline)) static inline bool cache_ll_l1_is_dcache_enabled(uint32_t cache_id) { - HAL_ASSERT(cache_id == 0); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); bool enabled; enabled = REG_GET_BIT(EXTMEM_PRO_DCACHE_CTRL_REG, EXTMEM_PRO_DCACHE_ENABLE); @@ -324,13 +336,16 @@ static inline bool cache_ll_is_cache_enabled(cache_type_t type) /** * @brief Invalidate cache supported addr * - * Invalidate a Cache item for either ICache or DCache. + * Invalidate a cache item * - * @param vaddr Start address of the region to be invalidated - * @param size Size of the region to be invalidated + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated */ __attribute__((always_inline)) -static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_invalidate_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_Invalidate_Addr(vaddr, size); } @@ -338,13 +353,16 @@ static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) /** * @brief Writeback cache supported addr * - * Writeback the DCache item to external memory + * Writeback a cache item * - * @param vaddr Start address of the region to writeback - * @param size Size of the region to writeback + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be written back + * @param size size of the region to be written back */ __attribute__((always_inline)) -static inline void cache_ll_writeback_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_writeback_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_WriteBack_Addr(vaddr, size); } @@ -376,14 +394,16 @@ static inline uint32_t cache_ll_l1_dcache_get_line_size(void) } /** - * @brief Get ICache or DCache line size, in bytes + * @brief Get Cache line size, in bytes * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * - * @return ICache/DCache line size, in bytes + * @return Cache line size, in bytes */ __attribute__((always_inline)) -static inline uint32_t cache_ll_get_line_size(cache_type_t type) +static inline uint32_t cache_ll_get_line_size(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { uint32_t size = 0; switch (type) @@ -504,6 +524,32 @@ static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t m REG_SET_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, dbus_mask); } +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid + */ +__attribute__((always_inline)) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; + + valid |= ((vaddr_start >= SOC_DROM0_ADDRESS_LOW) && (vaddr_end < SOC_DROM0_ADDRESS_HIGH)) || ((vaddr_start >= SOC_DPORT_CACHE_ADDRESS_LOW) && (vaddr_end < SOC_DRAM0_CACHE_ADDRESS_HIGH)); + valid |= ((vaddr_start >= SOC_IRAM0_CACHE_ADDRESS_LOW) && (vaddr_end < SOC_IRAM1_ADDRESS_HIGH)); + + if (valid) { + *out_level = 1; + *out_id = 0; + } + + return valid; +} #ifdef __cplusplus } diff --git a/components/hal/esp32s3/include/hal/cache_ll.h b/components/hal/esp32s3/include/hal/cache_ll.h index 9a953b252819..215473731e69 100644 --- a/components/hal/esp32s3/include/hal/cache_ll.h +++ b/components/hal/esp32s3/include/hal/cache_ll.h @@ -38,6 +38,11 @@ extern "C" { #define CACHE_LL_L1_ILG_EVENT_ICACHE_PRELOAD_OP_FAULT (1<<1) #define CACHE_LL_L1_ILG_EVENT_ICACHE_SYNC_OP_FAULT (1<<0) +#define CACHE_LL_ID_ALL 2 //All of the caches in a type and level, make this value greater than any id +#define CACHE_LL_LEVEL_INT_MEM 0 //Cache level for accessing internal mem +#define CACHE_LL_LEVEL_EXT_MEM 1 //Cache level for accessing external mem +#define CACHE_LL_LEVEL_ALL 2 //All of the cache levels, make this value greater than any level +#define CACHE_LL_LEVEL_NUMS 1 //Number of cache levels #define CACHE_LL_L1_ICACHE_AUTOLOAD (1<<2) #define CACHE_LL_L1_DCACHE_AUTOLOAD (1<<2) @@ -72,15 +77,18 @@ static inline bool cache_ll_l1_is_dcache_autoload_enabled(void) } /** - * @brief Check if ICache or DCache auto preload is enabled or not + * @brief Check if Cache auto preload is enabled or not. * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * * @return true: enabled; false: disabled */ __attribute__((always_inline)) -static inline bool cache_ll_is_cache_autoload_enabled(cache_type_t type) +static inline bool cache_ll_is_cache_autoload_enabled(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); bool enabled = false; switch (type) { @@ -116,12 +124,14 @@ static inline void cache_ll_l1_disable_dcache(void) } /** - * @brief Disable ICache or DCache or both + * @brief Disable Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_disable_cache(cache_type_t type) +static inline void cache_ll_disable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { switch (type) { @@ -161,16 +171,16 @@ static inline void cache_ll_l1_enable_dcache(bool data_autoload_en) } /** - * @brief Enable ICache or DCache or both - * - * @param type see `cache_type_t` + * @brief Enable Cache * - * @param data_autoload_en Dcache auto preload enabled - * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_enable_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_enable_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { switch (type) { @@ -206,12 +216,14 @@ static inline void cache_ll_l1_suspend_dcache(void) } /** - * @brief Suspend ICache or DCache or both + * @brief Suspend Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_suspend_cache(cache_type_t type) +static inline void cache_ll_suspend_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { switch (type) { @@ -251,16 +263,16 @@ static inline void cache_ll_l1_resume_dcache(bool data_autoload_en) } /** - * @brief Resume ICache or DCache or both - * - * @param type see `cache_type_t` - * - * @param data_autoload_en Dcache auto preload enabled + * @brief Resume Cache * - * @param inst_autoload_en Icache auto preload enabled + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param data_autoload_en data autoload enabled or not + * @param inst_autoload_en inst autoload enabled or not */ __attribute__((always_inline)) -static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_en, bool data_autoload_en) +static inline void cache_ll_resume_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id, bool inst_autoload_en, bool data_autoload_en) { switch (type) { @@ -287,7 +299,7 @@ static inline void cache_ll_resume_cache(cache_type_t type, bool inst_autoload_e __attribute__((always_inline)) static inline bool cache_ll_l1_is_icache_enabled(uint32_t cache_id) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); return REG_GET_BIT(EXTMEM_ICACHE_CTRL_REG, EXTMEM_ICACHE_ENABLE); } @@ -301,7 +313,7 @@ static inline bool cache_ll_l1_is_icache_enabled(uint32_t cache_id) __attribute__((always_inline)) static inline bool cache_ll_l1_is_dcache_enabled(uint32_t cache_id) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); return REG_GET_BIT(EXTMEM_DCACHE_CTRL_REG, EXTMEM_DCACHE_ENABLE); } @@ -334,13 +346,16 @@ static inline bool cache_ll_is_cache_enabled(cache_type_t type) /** * @brief Invalidate cache supported addr * - * Invalidate a Cache item for either ICache or DCache. + * Invalidate a cache item * - * @param vaddr Start address of the region to be invalidated - * @param size Size of the region to be invalidated + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be invalidated + * @param size size of the region to be invalidated */ __attribute__((always_inline)) -static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_invalidate_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_Invalidate_Addr(vaddr, size); } @@ -348,13 +363,16 @@ static inline void cache_ll_invalidate_addr(uint32_t vaddr, uint32_t size) /** * @brief Writeback cache supported addr * - * Writeback the DCache item to external memory + * Writeback a cache item * - * @param vaddr Start address of the region to writeback - * @param size Size of the region to writeback + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level + * @param vaddr start address of the region to be written back + * @param size size of the region to be written back */ __attribute__((always_inline)) -static inline void cache_ll_writeback_addr(uint32_t vaddr, uint32_t size) +static inline void cache_ll_writeback_addr(uint32_t cache_level, cache_type_t type, uint32_t cache_id, uint32_t vaddr, uint32_t size) { Cache_WriteBack_Addr(vaddr, size); } @@ -378,12 +396,14 @@ static inline void cache_ll_l1_freeze_dcache(void) } /** - * @brief Freeze ICache or DCache or both + * @brief Freeze Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_freeze_cache(cache_type_t type) +static inline void cache_ll_freeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { switch (type) { @@ -419,12 +439,14 @@ static inline void cache_ll_l1_unfreeze_dcache(void) } /** - * @brief Unfreeze ICache or DCache or both + * @brief Unfreeze Cache * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level */ __attribute__((always_inline)) -static inline void cache_ll_unfreeze_cache(cache_type_t type) +static inline void cache_ll_unfreeze_cache(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { switch (type) { @@ -468,14 +490,16 @@ static inline uint32_t cache_ll_l1_dcache_get_line_size(void) } /** - * @brief Get ICache or DCache line size, in bytes + * @brief Get Cache line size, in bytes * - * @param type see `cache_type_t` + * @param cache_level level of the cache + * @param type see `cache_type_t` + * @param cache_id id of the cache in this type and level * - * @return ICache/DCache line size, in bytes + * @return Cache line size, in bytes */ __attribute__((always_inline)) -static inline uint32_t cache_ll_get_line_size(cache_type_t type) +static inline uint32_t cache_ll_get_line_size(uint32_t cache_level, cache_type_t type, uint32_t cache_id) { uint32_t size = 0; switch (type) @@ -508,7 +532,7 @@ __attribute__((always_inline)) #endif static inline cache_bus_mask_t cache_ll_l1_get_bus(uint32_t cache_id, uint32_t vaddr_start, uint32_t len) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); cache_bus_mask_t mask = (cache_bus_mask_t)0; uint32_t vaddr_end = vaddr_start + len - 1; @@ -534,7 +558,7 @@ __attribute__((always_inline)) #endif static inline void cache_ll_l1_enable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32s3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -566,7 +590,7 @@ __attribute__((always_inline)) static inline cache_bus_mask_t cache_ll_l1_get_enabled_bus(uint32_t cache_id) { cache_bus_mask_t mask = (cache_bus_mask_t)0; - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32s3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first uint32_t ibus_mask = REG_READ(EXTMEM_ICACHE_CTRL1_REG); @@ -595,7 +619,7 @@ static inline cache_bus_mask_t cache_ll_l1_get_enabled_bus(uint32_t cache_id) __attribute__((always_inline)) static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t mask) { - HAL_ASSERT(cache_id == 0 || cache_id == 1); + HAL_ASSERT(cache_id <= CACHE_LL_ID_ALL); //On esp32s3, only `CACHE_BUS_IBUS0` and `CACHE_BUS_DBUS0` are supported. Use `cache_ll_l1_get_bus()` to get your bus first HAL_ASSERT((mask & (CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2| CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)) == 0); @@ -616,6 +640,33 @@ static inline void cache_ll_l1_disable_bus(uint32_t cache_id, cache_bus_mask_t m REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, dbus_mask); } +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid + */ +__attribute__((always_inline)) +static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id) +{ + bool valid = false; + uint32_t vaddr_end = vaddr_start + len - 1; + + valid |= (SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_IRAM0_CACHE(vaddr_end)); + valid |= (SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_start) && SOC_ADDRESS_IN_DRAM0_CACHE(vaddr_end)); + + if (valid) { + *out_level = 1; + *out_id = 0; + } + + return valid; +} + /*------------------------------------------------------------------------------ * Interrupt *----------------------------------------------------------------------------*/ diff --git a/components/hal/include/hal/cache_hal.h b/components/hal/include/hal/cache_hal.h index 8464c48f883d..f5592f15db77 100644 --- a/components/hal/include/hal/cache_hal.h +++ b/components/hal/include/hal/cache_hal.h @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,105 +21,128 @@ extern "C" { void cache_hal_init(void); /** - * @brief Disable cache + * @brief Disable Cache * - * Disable the ICache or DCache or both, all the items in the corresponding Cache(s) will be invalideated. - * Next request to these items will trigger a transaction to the external memory (flash / psram) + * Disable the ICache or DCache or both, of a certain level or all levels. + * All the items in the corresponding Cache(s) will be invalideated. + * Next request to these items will trigger a transaction to the physical memory * * @note If the autoload feature is enabled, this API will return until the ICache autoload is disabled. * - * @param type see `cache_type_t` + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) */ -void cache_hal_disable(cache_type_t type); +void cache_hal_disable(cache_type_t type, uint32_t cache_level); /** - * @brief Enable cache + * @brief Enable Cache * - * Enable the ICache or DCache or both. + * Enable the ICache or DCache or both, of a certain level or all levels. * - * @param type see `cache_type_t` + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) */ -void cache_hal_enable(cache_type_t type); +void cache_hal_enable(cache_type_t type, uint32_t cache_level); /** - * @brief Suspend cache + * @brief Suspend Cache * - * Suspend the ICache or DCache or both,suspends the CPU access to cache for a while, without invalidation. + * Suspend the ICache or DCache or both, of a certain level or all levels. + * This API suspends the CPU access to cache for a while, without invalidation. * - * @param type see `cache_type_t` - * - * @return Current status of corresponding Cache(s) + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) */ -void cache_hal_suspend(cache_type_t type); +void cache_hal_suspend(cache_type_t type, uint32_t cache_level); /** - * @brief Resume cache + * @brief Resume Cache * - * Resume the ICache or DCache or both. + * Resume the ICache or DCache or both, of a certain level or all levels. * - * @param type see `cache_type_t` + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) */ -void cache_hal_resume(cache_type_t type); +void cache_hal_resume(cache_type_t type, uint32_t cache_level); /** * @brief Check if corresponding cache is enabled or not * - * @param type see `cache_type_t` + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) * * @return true: enabled; false: disabled */ -bool cache_hal_is_cache_enabled(cache_type_t type); +bool cache_hal_is_cache_enabled(cache_type_t type, uint32_t cache_level); /** - * @brief Invalidate cache supported addr + * @brief Invalidate Cache supported addr * * Invalidate a Cache item for either ICache or DCache. * * @param vaddr Start address of the region to be invalidated * @param size Size of the region to be invalidated + * + * @return True for valid address. No operation if invalid */ -void cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size); +bool cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size); #if SOC_CACHE_WRITEBACK_SUPPORTED /** - * @brief Writeback cache supported addr + * @brief Writeback Cache supported addr * * Writeback the DCache item to external memory * * @param vaddr Start address of the region to writeback * @param size Size of the region to writeback + * + * @return True for valid address. No operation if invalid */ -void cache_hal_writeback_addr(uint32_t vaddr, uint32_t size); +bool cache_hal_writeback_addr(uint32_t vaddr, uint32_t size); #endif //#if SOC_CACHE_WRITEBACK_SUPPORTED #if SOC_CACHE_FREEZE_SUPPORTED /** - * @brief Freeze cache + * @brief Freeze Cache * * Freeze cache, CPU access to cache will be suspended, until the cache is unfrozen. * - * @param type see `cache_type_t` + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) */ -void cache_hal_freeze(cache_type_t type); +void cache_hal_freeze(cache_type_t type, uint32_t cache_level); /** * @brief Unfreeze cache * * Unfreeze cache, CPU access to cache will be restored * - * @param type see `cache_type_t` + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) */ -void cache_hal_unfreeze(cache_type_t type); +void cache_hal_unfreeze(cache_type_t type, uint32_t cache_level); #endif //#if SOC_CACHE_FREEZE_SUPPORTED /** * @brief Get cache line size, in bytes * - * @param type see `cache_type_t` - * + * @param type see `cache_type_t` + * @param cache_level Level of the Cache(s) * * @return cache line size, in bytes */ -uint32_t cache_hal_get_cache_line_size(cache_type_t type); +uint32_t cache_hal_get_cache_line_size(cache_type_t type, uint32_t cache_level); + +/** + * @brief Get Cache level and the ID of the vaddr + * + * @param vaddr_start virtual address start + * @param len vaddr length + * @param out_level cache level + * @param out_id cache id + * + * @return true for valid, false for invalid addr or null pointer + */ +bool cache_hal_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id); #ifdef __cplusplus } diff --git a/components/hal/mmu_hal.c b/components/hal/mmu_hal.c index 622de3b4f905..b60fae6483f6 100644 --- a/components/hal/mmu_hal.c +++ b/components/hal/mmu_hal.c @@ -20,11 +20,6 @@ void mmu_hal_init(void) ROM_Boot_Cache_Init(); #endif -//TODO: IDF-7516 -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_Invalidate_All(CACHE_MAP_L2_CACHE); -#endif - mmu_ll_set_page_size(0, CONFIG_MMU_PAGE_SIZE); mmu_hal_unmap_all(); } diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 428c5f571c4c..ed382a62699d 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -195,11 +195,15 @@ config SOC_SHARED_IDCACHE_SUPPORTED bool default y +config SOC_CACHE_WRITEBACK_SUPPORTED + bool + default y + config SOC_CACHE_FREEZE_SUPPORTED bool default y -config SOC_CACHE_L2_SUPPORTED +config SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE bool default y diff --git a/components/soc/esp32p4/include/soc/ext_mem_defs.h b/components/soc/esp32p4/include/soc/ext_mem_defs.h index 2b05bba68132..0e428d116e19 100644 --- a/components/soc/esp32p4/include/soc/ext_mem_defs.h +++ b/components/soc/esp32p4/include/soc/ext_mem_defs.h @@ -19,6 +19,11 @@ extern "C" { #define SOC_MMU_PAGE_SIZE 0x10000 #endif +#define SOC_IRAM0_ADDRESS_LOW 0x4ff00000 +#define SOC_IRAM0_ADDRESS_HIGH 0x4ffc0000 + +#define SOC_DRAM0_ADDRESS_LOW SOC_IRAM0_ADDRESS_LOW +#define SOC_DRAM0_ADDRESS_HIGH SOC_IRAM0_ADDRESS_HIGH #define SOC_IRAM0_CACHE_ADDRESS_LOW 0x40000000 #define SOC_IRAM0_CACHE_ADDRESS_HIGH 0x50000000 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index aba4e39aa3e2..199b44ee0e20 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -130,8 +130,9 @@ /*-------------------------- CACHE CAPS --------------------------------------*/ #define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data +#define SOC_CACHE_WRITEBACK_SUPPORTED 1 #define SOC_CACHE_FREEZE_SUPPORTED 1 -#define SOC_CACHE_L2_SUPPORTED 1 +#define SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE 1 /*-------------------------- CPU CAPS ----------------------------------------*/ #define SOC_CPU_CORES_NUM (2U) diff --git a/components/spi_flash/cache_utils.c b/components/spi_flash/cache_utils.c index c1e7e75c7636..ad8707fd6ba8 100644 --- a/components/spi_flash/cache_utils.c +++ b/components/spi_flash/cache_utils.c @@ -360,17 +360,17 @@ void IRAM_ATTR spi_flash_enable_cache(uint32_t cpuid) void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state) { - cache_hal_suspend(CACHE_TYPE_ALL); + cache_hal_suspend(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state) { - cache_hal_resume(CACHE_TYPE_ALL); + cache_hal_resume(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } bool IRAM_ATTR spi_flash_cache_enabled(void) { - return cache_hal_is_cache_enabled(CACHE_TYPE_ALL); + return cache_hal_is_cache_enabled(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); } #if CONFIG_IDF_TARGET_ESP32S2 @@ -918,15 +918,15 @@ void esp_config_l2_cache_mode(void) { cache_size_t cache_size; cache_line_size_t cache_line_size; -#if CONFIG_ESP32P4_L2_CACHE_128KB +#if CONFIG_CACHE_L2_CACHE_128KB cache_size = CACHE_SIZE_128K; -#elif CONFIG_ESP32P4_L2_CACHE_256KB +#elif CONFIG_CACHE_L2_CACHE_256KB cache_size = CACHE_SIZE_256K; #else cache_size = CACHE_SIZE_512K; #endif -#if CONFIG_ESP32P4_L2_CACHE_LINE_64B +#if CONFIG_CACHE_L2_CACHE_LINE_64B cache_line_size = CACHE_LINE_SIZE_64B; #else cache_line_size = CACHE_LINE_SIZE_128B; diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index c620a2d86f70..da4e991566a7 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -30,9 +30,6 @@ #if CONFIG_IDF_TARGET_ESP32 #include "esp_private/esp_cache_esp32_private.h" -#elif CONFIG_IDF_TARGET_ESP32P4 -//TODO: IDF-7516 -#include "esp32p4/rom/cache.h" #endif #include "esp_private/cache_utils.h" @@ -377,12 +374,7 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length) return true; #else // CONFIG_IDF_TARGET_ESP32 if (vaddr != NULL) { -#if CONFIG_IDF_TARGET_ESP32P4 - //TODO: IDF-7516 - Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE | CACHE_MAP_L2_CACHE, (uint32_t)vaddr, SPI_FLASH_MMU_PAGE_SIZE); -#else cache_hal_invalidate_addr((uint32_t)vaddr, SPI_FLASH_MMU_PAGE_SIZE); -#endif ret = true; } #endif // CONFIG_IDF_TARGET_ESP32 From cc581c3c360a8d940cf81d1500c0fd54ed5f8159 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 14 Sep 2023 12:17:08 +0800 Subject: [PATCH 022/142] change(cp_dma): check cache line by cache level --- .../esp_hw_support/dma/async_memcpy_gdma.c | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/components/esp_hw_support/dma/async_memcpy_gdma.c b/components/esp_hw_support/dma/async_memcpy_gdma.c index a19f61cefba0..33409016fdc7 100644 --- a/components/esp_hw_support/dma/async_memcpy_gdma.c +++ b/components/esp_hw_support/dma/async_memcpy_gdma.c @@ -21,6 +21,7 @@ #include "esp_async_memcpy_priv.h" #include "hal/dma_types.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "rom/cache.h" static const char *TAG = "async_mcp.gdma"; @@ -161,13 +162,20 @@ static esp_err_t esp_async_memcpy_install_gdma_template(const async_memcpy_confi portMUX_INITIALIZE(&mcp_gdma->spin_lock); atomic_init(&mcp_gdma->fsm, MCP_FSM_IDLE); mcp_gdma->gdma_bus_id = gdma_bus_id; + + uint32_t psram_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_EXT_MEM); + uint32_t sram_cache_line_size = 0; +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + sram_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_INT_MEM); +#endif + // if the psram_trans_align is configured to zero, we should fall back to use the data cache line size - uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); - size_t psram_trans_align = MAX(data_cache_line_size, config->psram_trans_align); - size_t trans_align = MAX(config->sram_trans_align, psram_trans_align); + size_t psram_trans_align = MAX(psram_cache_line_size, config->psram_trans_align); + size_t sram_trans_align = MAX(sram_cache_line_size, config->sram_trans_align); + size_t trans_align = MAX(sram_trans_align, psram_trans_align); mcp_gdma->max_single_dma_buffer = ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, trans_align); mcp_gdma->psram_trans_align = psram_trans_align; - mcp_gdma->sram_trans_align = config->sram_trans_align; + mcp_gdma->sram_trans_align = sram_trans_align; mcp_gdma->parent.del = mcp_gdma_del; mcp_gdma->parent.memcpy = mcp_gdma_memcpy; #if SOC_GDMA_SUPPORT_ETM @@ -322,6 +330,7 @@ static bool check_buffer_aligned(async_memcpy_gdma_context_t *mcp_gdma, void *sr { bool valid = true; uint32_t align_mask = 0; + if (esp_ptr_external_ram(dst)) { if (mcp_gdma->psram_trans_align) { align_mask = mcp_gdma->psram_trans_align - 1; @@ -331,12 +340,7 @@ static bool check_buffer_aligned(async_memcpy_gdma_context_t *mcp_gdma, void *sr align_mask = mcp_gdma->sram_trans_align - 1; } } -#if CONFIG_IDF_TARGET_ESP32P4 - uint32_t data_cache_line_mask = cache_hal_get_cache_line_size(CACHE_TYPE_DATA) - 1; - if (data_cache_line_mask > align_mask) { - align_mask = data_cache_line_mask; - } -#endif + // destination address must be cache line aligned valid = valid && (((uint32_t)dst & align_mask) == 0); valid = valid && ((n & align_mask) == 0); From e8813ddd1dbea6535a820994e1414c990d13cb74 Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 8 Sep 2023 15:20:22 +0800 Subject: [PATCH 023/142] feat(cache): added an helper API for cache-align-malloc --- components/esp_mm/esp_cache.c | 71 +++++++++++++++++++ .../include/esp_private/esp_cache_private.h | 64 +++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 components/esp_mm/include/esp_private/esp_cache_private.h diff --git a/components/esp_mm/esp_cache.c b/components/esp_mm/esp_cache.c index 6eff6cbda404..2695589fa940 100644 --- a/components/esp_mm/esp_cache.c +++ b/components/esp_mm/esp_cache.c @@ -6,17 +6,24 @@ #include #include +#include #include "sdkconfig.h" #include "esp_check.h" #include "esp_log.h" +#include "esp_heap_caps.h" #include "esp_rom_caps.h" #include "soc/soc_caps.h" #include "hal/mmu_hal.h" #include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "esp_cache.h" +#include "esp_private/esp_cache_private.h" #include "esp_private/critical_section.h" static const char *TAG = "cache"; + +#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + DEFINE_CRIT_SECTION_LOCK_STATIC(s_spinlock); @@ -74,3 +81,67 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags) return ESP_OK; } + + +esp_err_t esp_cache_aligned_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size) +{ + ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t cache_level = CACHE_LL_LEVEL_INT_MEM; + uint32_t heap_caps = 0; + uint32_t data_cache_line_size = 0; + void *ptr = NULL; + + if (flags & ESP_CACHE_MALLOC_FLAG_PSRAM) { + cache_level = CACHE_LL_LEVEL_EXT_MEM; + heap_caps |= MALLOC_CAP_SPIRAM; + } else { + heap_caps |= MALLOC_CAP_INTERNAL; + if (flags & ESP_CACHE_MALLOC_FLAG_DMA) { + heap_caps |= MALLOC_CAP_DMA; + } + } + +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, cache_level); +#else + if (cache_level == CACHE_LL_LEVEL_EXT_MEM) { + data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, cache_level); + } else { + data_cache_line_size = 4; + } +#endif + + size = ALIGN_UP_BY(size, data_cache_line_size); + ptr = heap_caps_aligned_alloc(data_cache_line_size, size, heap_caps); + ESP_RETURN_ON_FALSE_ISR(ptr, ESP_ERR_NO_MEM, TAG, "no enough heap memory for (%"PRId32")B alignment", data_cache_line_size); + + *out_ptr = ptr; + if (actual_size) { + *actual_size = size; + } + + return ESP_OK; +} + + +esp_err_t esp_cache_aligned_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size) +{ + ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + esp_err_t ret = ESP_FAIL; + size_t size_bytes = 0; + bool ovf = false; + + ovf = __builtin_mul_overflow(n, size, &size_bytes); + ESP_RETURN_ON_FALSE_ISR(!ovf, ESP_ERR_INVALID_ARG, TAG, "wrong size, total size overflow"); + + void *ptr = NULL; + ret = esp_cache_aligned_malloc(size_bytes, flags, &ptr, actual_size); + if (ret == ESP_OK) { + memset(ptr, 0, size_bytes); + *out_ptr = ptr; + } + + return ret; +} diff --git a/components/esp_mm/include/esp_private/esp_cache_private.h b/components/esp_mm/include/esp_private/esp_cache_private.h new file mode 100644 index 000000000000..7735d298b97c --- /dev/null +++ b/components/esp_mm/include/esp_private/esp_cache_private.h @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "esp_err.h" +#include "esp_bit_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Cache malloc flags + */ +/** + * @brief Memory is in PSRAM + */ +#define ESP_CACHE_MALLOC_FLAG_PSRAM BIT(0) + +/** + * @brief Memory is capable to be accessed by DMA + */ +#define ESP_CACHE_MALLOC_FLAG_DMA BIT(1) + +/** + * @brief Helper function for malloc a cache aligned memory buffer + * + * @param[in] size Size in bytes, the amount of memory to allocate + * @param[in] flags Flags, see `ESP_CACHE_MALLOC_FLAG_x` + * @param[out] out_ptr A pointer to the memory allocated successfully + * @param[out] actual_size Actual size for allocation in bytes, when the size you specified doesn't meet the cache alignment requirements, this value might be bigger than the size you specified. Set null if you don't care this value. + * + * @return + * - ESP_OK: + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_NO_MEM: No enough memory for allocation + */ +esp_err_t esp_cache_aligned_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size); + +/** + * @brief Helper function for calloc a cache aligned memory buffer + * + * @param[in] n Number of continuing chunks of memory to allocate + * @param[in] size Size of one chunk, in bytes + * @param[in] flags Flags, see `ESP_CACHE_MALLOC_FLAG_x` + * @param[out] out_ptr A pointer to the memory allocated successfully + * @param[out] actual_size Actual size for allocation in bytes, when the size you specified doesn't meet the cache alignment requirements, this value might be bigger than the size you specified. Set null if you don't care this value. + * + * @return + * - ESP_OK: + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_NO_MEM: No enough memory for allocation + */ +esp_err_t esp_cache_aligned_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size); + + +#ifdef __cplusplus +} +#endif From 900aebd15896d147f38b590e0ebbf4600d77ecfb Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 8 Sep 2023 14:54:45 +0800 Subject: [PATCH 024/142] feat(dma): added APIs for dma specific malloc --- components/esp_hw_support/CMakeLists.txt | 5 +- components/esp_hw_support/dma/esp_dma_utils.c | 69 +++++++++++++++++++ .../esp_hw_support/include/esp_dma_utils.h | 57 +++++++++++++++ .../main/i80_controller_example_main.c | 10 +-- 4 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 components/esp_hw_support/dma/esp_dma_utils.c create mode 100644 components/esp_hw_support/include/esp_dma_utils.h diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index c269eba0f341..342e54281eab 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -34,7 +34,8 @@ if(NOT BOOTLOADER_BUILD) "sar_periph_ctrl_common.c" "port/${target}/io_mux.c" "port/${target}/esp_clk_tree.c" - "port/esp_clk_tree_common.c") + "port/esp_clk_tree_common.c" + "dma/esp_dma_utils.c") if(CONFIG_SOC_ADC_SUPPORTED) list(APPEND srcs "adc_share_hw_ctrl.c") @@ -51,6 +52,8 @@ if(NOT BOOTLOADER_BUILD) # [refactor-todo]: requires "driver" for GPIO and RTC (by sleep_gpio and sleep_modes) list(APPEND priv_requires driver esp_timer) + list(APPEND priv_requires esp_mm) + if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S2) list(APPEND srcs "rtc_wdt.c") endif() diff --git a/components/esp_hw_support/dma/esp_dma_utils.c b/components/esp_hw_support/dma/esp_dma_utils.c new file mode 100644 index 000000000000..4309a69cc453 --- /dev/null +++ b/components/esp_hw_support/dma/esp_dma_utils.c @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_check.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "esp_dma_utils.h" +#include "esp_private/esp_cache_private.h" +#include "soc/soc_caps.h" + +static const char *TAG = "dma_utils"; +_Static_assert(ESP_DMA_MALLOC_FLAG_PSRAM == ESP_CACHE_MALLOC_FLAG_PSRAM); + +#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + + +esp_err_t esp_dma_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size) +{ + ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + esp_err_t ret = ESP_OK; + +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + ret = esp_cache_aligned_malloc(size, flags | ESP_CACHE_MALLOC_FLAG_DMA, out_ptr, actual_size); +#else + if (flags & ESP_DMA_MALLOC_FLAG_PSRAM) { + ret = esp_cache_aligned_malloc(size, flags | ESP_CACHE_MALLOC_FLAG_DMA, out_ptr, actual_size); + } else { + size = ALIGN_UP_BY(size, 4); + void *ptr = heap_caps_aligned_alloc(4, size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + ESP_RETURN_ON_FALSE_ISR(ptr, ESP_ERR_NO_MEM, TAG, "no enough heap memory"); + *out_ptr = ptr; + if (actual_size) { + *actual_size = size; + } + } +#endif + + return ret; +} + + +esp_err_t esp_dma_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size) +{ + ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + esp_err_t ret = ESP_FAIL; + size_t size_bytes = 0; + bool ovf = false; + + ovf = __builtin_mul_overflow(n, size, &size_bytes); + ESP_RETURN_ON_FALSE_ISR(!ovf, ESP_ERR_INVALID_ARG, TAG, "wrong size, total size overflow"); + + void *ptr = NULL; + ret = esp_dma_malloc(size_bytes, flags, &ptr, actual_size); + if (ret == ESP_OK) { + memset(ptr, 0, size_bytes); + *out_ptr = ptr; + } + + return ret; +} diff --git a/components/esp_hw_support/include/esp_dma_utils.h b/components/esp_hw_support/include/esp_dma_utils.h new file mode 100644 index 000000000000..3d4435b7cc4e --- /dev/null +++ b/components/esp_hw_support/include/esp_dma_utils.h @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * DMA malloc flags + */ +/** + * @brief Memory is in PSRAM + */ +#define ESP_DMA_MALLOC_FLAG_PSRAM BIT(0) + +/** + * @brief Helper function for malloc a DMA capable memory buffer + * + * @param[in] size Size in bytes, the amount of memory to allocate + * @param[in] flags Flags, see `ESP_DMA_MALLOC_FLAG_x` + * @param[out] out_ptr A pointer to the memory allocated successfully + * @param[out] actual_size Actual size for allocation in bytes, when the size you specified doesn't meet the DMA alignment requirements, this value might be bigger than the size you specified. Set null if you don't care this value. + * + * @return + * - ESP_OK: + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_NO_MEM: No enough memory for allocation + */ +esp_err_t esp_dma_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size); + +/** + * @brief Helper function for calloc a DMA capable memory buffer + * + * @param[in] n Number of continuing chunks of memory to allocate + * @param[in] size Size of one chunk, in bytes + * @param[in] flags Flags, see `ESP_DMA_MALLOC_FLAG_x` + * @param[out] out_ptr A pointer to the memory allocated successfully + * @param[out] actual_size Actual size for allocation in bytes, when the size you specified doesn't meet the cache alignment requirements, this value might be bigger than the size you specified. Set null if you don't care this value. + * + * @return + * - ESP_OK: + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_NO_MEM: No enough memory for allocation + */ +esp_err_t esp_dma_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c index 13a72fc0afe8..0d0140d77bce 100644 --- a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c +++ b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c @@ -17,6 +17,7 @@ #include "driver/i2c.h" #include "esp_err.h" #include "esp_log.h" +#include "esp_dma_utils.h" #include "lvgl.h" #if CONFIG_EXAMPLE_LCD_TOUCH_CONTROLLER_GT911 #include "esp_lcd_touch_gt911.h" @@ -406,13 +407,12 @@ void app_main(void) // it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized lv_color_t *buf1 = NULL; lv_color_t *buf2 = NULL; + uint32_t malloc_flags = 0; #if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM - buf1 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - buf2 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); -#else - buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + malloc_flags |= ESP_DMA_MALLOC_FLAG_PSRAM; #endif // CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM + ESP_ERROR_CHECK(esp_dma_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), malloc_flags, (void *)&buf1, NULL)); + ESP_ERROR_CHECK(esp_dma_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), malloc_flags, (void *)&buf2, NULL)); assert(buf1); assert(buf2); ESP_LOGI(TAG, "buf1@%p, buf2@%p", buf1, buf2); From 0a1503897c92a09dbe6866959d4790fab370a1d8 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 14 Sep 2023 19:55:24 +0800 Subject: [PATCH 025/142] feat(cache): support esp_cache_msync for instructions --- components/esp_mm/esp_cache.c | 16 ++++++++++++---- components/esp_mm/include/esp_cache.h | 10 ++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/components/esp_mm/esp_cache.c b/components/esp_mm/esp_cache.c index 2695589fa940..2b3c405e9ac1 100644 --- a/components/esp_mm/esp_cache.c +++ b/components/esp_mm/esp_cache.c @@ -37,7 +37,8 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags) ESP_RETURN_ON_FALSE_ISR(!ovf, ESP_ERR_INVALID_ARG, TAG, "wrong size, total size overflow"); bool both_dir = (flags & ESP_CACHE_MSYNC_FLAG_DIR_C2M) && (flags & ESP_CACHE_MSYNC_FLAG_DIR_M2C); - ESP_RETURN_ON_FALSE_ISR(!both_dir, ESP_ERR_INVALID_ARG, TAG, "both C2M and M2C directions are selected, you should only select one"); + bool both_type = (flags & ESP_CACHE_MSYNC_FLAG_TYPE_DATA) && (flags & ESP_CACHE_MSYNC_FLAG_TYPE_INST); + ESP_RETURN_ON_FALSE_ISR(!both_dir && !both_type, ESP_ERR_INVALID_ARG, TAG, "both C2M and M2C directions, or both data and instruction type are selected, you should only select one direction or one type"); uint32_t vaddr = (uint32_t)addr; bool valid = false; @@ -46,10 +47,14 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags) valid = cache_hal_vaddr_to_cache_level_id(vaddr, size, &cache_level, &cache_id); ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_ARG, TAG, "invalid addr or null pointer"); - uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, cache_level); + cache_type_t cache_type = CACHE_TYPE_DATA; + if (flags & ESP_CACHE_MSYNC_FLAG_TYPE_INST) { + cache_type = CACHE_TYPE_INSTRUCTION; + } + uint32_t cache_line_size = cache_hal_get_cache_line_size(cache_type, cache_level); if ((flags & ESP_CACHE_MSYNC_FLAG_UNALIGNED) == 0) { - bool aligned_addr = (((uint32_t)addr % data_cache_line_size) == 0) && ((size % data_cache_line_size) == 0); - ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address: 0x%x, or the size: 0x%x is(are) not aligned with the data cache line size (0x%x)B", (uint32_t)addr, size, data_cache_line_size); + bool aligned_addr = (((uint32_t)addr % cache_line_size) == 0) && ((size % cache_line_size) == 0); + ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address: 0x%x, or the size: 0x%x is(are) not aligned with cache line size (0x%x)B", (uint32_t)addr, size, cache_line_size); } if (flags & ESP_CACHE_MSYNC_FLAG_DIR_M2C) { @@ -62,6 +67,9 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags) assert(valid); } else { ESP_EARLY_LOGV(TAG, "C2M DIR"); + if (flags & ESP_CACHE_MSYNC_FLAG_TYPE_INST) { + ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_ARG, TAG, "C2M direction doesn't support instruction type"); + } #if SOC_CACHE_WRITEBACK_SUPPORTED diff --git a/components/esp_mm/include/esp_cache.h b/components/esp_mm/include/esp_cache.h index 848bee251e42..f8efcb979ce7 100644 --- a/components/esp_mm/include/esp_cache.h +++ b/components/esp_mm/include/esp_cache.h @@ -36,6 +36,15 @@ extern "C" { * @brief Cache msync direction: from memory to Cache */ #define ESP_CACHE_MSYNC_FLAG_DIR_M2C BIT(3) +/** + * @brief Cache msync type: data + * @note If you don't set type (ESP_CACHE_MSYNC_FLAG_TYPE_x flags), it is by default data type + */ +#define ESP_CACHE_MSYNC_FLAG_TYPE_DATA BIT(4) +/** + * @brief Cache msync type: instruction + */ +#define ESP_CACHE_MSYNC_FLAG_TYPE_INST BIT(5) /** * @brief Memory sync between Cache and storage memory @@ -54,6 +63,7 @@ extern "C" { * This API is cache-safe and thread-safe * * @note If you don't set direction (ESP_CACHE_MSYNC_FLAG_DIR_x flags), this API is by default C2M direction + * @note If you don't set type (ESP_CACHE_MSYNC_FLAG_TYPE_x flags), this API is by default doing msync for data * @note You should not call this during any Flash operations (e.g. esp_flash APIs, nvs and some other APIs that are based on esp_flash APIs) * @note If XIP_From_PSRAM is enabled (by enabling both CONFIG_SPIRAM_FETCH_INSTRUCTIONS and CONFIG_SPIRAM_RODATA), you can call this API during Flash operations * From ec27891af69152765af6410d7299e501ad146e6c Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 15 Sep 2023 20:11:52 +0800 Subject: [PATCH 026/142] change(cache): swap cache hal arg 'type' and 'level' --- .../bootloader_flash/src/bootloader_flash.c | 18 +++++----- .../src/bootloader_flash_config_esp32c2.c | 4 +-- .../src/bootloader_flash_config_esp32c3.c | 4 +-- .../src/bootloader_flash_config_esp32c6.c | 4 +-- .../src/bootloader_flash_config_esp32h2.c | 4 +-- .../src/bootloader_flash_config_esp32p4.c | 4 +-- .../src/bootloader_flash_config_esp32s2.c | 4 +-- .../src/bootloader_flash_config_esp32s3.c | 4 +-- .../src/bootloader_utility.c | 4 +-- .../esp_hw_support/dma/async_memcpy_gdma.c | 4 +-- components/esp_hw_support/dma/gdma.c | 2 +- .../esp_hw_support/mspi_timing_tuning.c | 4 +-- components/esp_hw_support/sleep_modes.c | 4 +-- components/esp_lcd/src/esp_lcd_panel_io_i80.c | 2 +- components/esp_mm/esp_cache.c | 6 ++-- components/esp_system/port/cpu_start.c | 4 +-- components/hal/cache_hal.c | 16 ++++----- components/hal/esp32/cache_hal_esp32.c | 8 ++--- components/hal/include/hal/cache_hal.h | 33 ++++++++++--------- components/spi_flash/cache_utils.c | 6 ++-- 20 files changed, 70 insertions(+), 69 deletions(-) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index f837694d535d..c75f0d0eebb0 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -202,7 +202,7 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size) Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif //---------------Do mapping------------------------ @@ -238,7 +238,7 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size) #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, MMU_BLOCK0_VADDR, actual_mapped_len); #endif - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif mapped = true; @@ -255,7 +255,7 @@ void bootloader_munmap(const void *mapping) Cache_Flush(0); mmu_init(0); #else - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); mmu_hal_unmap_all(); #endif mapped = false; @@ -283,7 +283,7 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size); @@ -291,7 +291,7 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s #if CONFIG_IDF_TARGET_ESP32 Cache_Read_Enable(0); #else - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif return spi_to_esp_err(r); @@ -314,7 +314,7 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif //---------------Do mapping------------------------ @@ -336,7 +336,7 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, MMU_BLOCK0_VADDR, actual_mapped_len); #endif - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif } map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at)); @@ -459,9 +459,9 @@ void bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t fla assert(false); break; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); esp_rom_opiflash_cache_mode_config(flash_mode, &cache_rd); - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } #endif diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c index 692fa53abc56..85f7c16654af 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c @@ -127,10 +127,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c index c76a98040701..fb1f2329d1a6 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c @@ -138,10 +138,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c index 719eb3a860c6..6a1e62459c74 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c @@ -103,10 +103,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c index 9f6e526ce647..b4b1bb94c3b4 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c @@ -110,10 +110,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c index 11f295d2aa02..14887abe949b 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c @@ -97,10 +97,10 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Set flash chip size esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c index 9fb267439be8..a1855bb4c4a3 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c @@ -152,12 +152,12 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) default: size = 2; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Set flash chip size esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode // TODO: set frequency - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c index b73663993df8..1b0caa3020c8 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c @@ -159,12 +159,12 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Set flash chip size esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode // TODO: set frequency - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 0ec4f07c0a23..ea3f37531baf 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -836,7 +836,7 @@ static void set_cache_and_start_app( Cache_Read_Disable(0); Cache_Flush(0); #else - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif //reset MMU table first mmu_hal_unmap_all(); @@ -896,7 +896,7 @@ static void set_cache_and_start_app( // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) Cache_Read_Enable(0); #else - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif ESP_LOGD(TAG, "start: 0x%08"PRIx32, entry_addr); diff --git a/components/esp_hw_support/dma/async_memcpy_gdma.c b/components/esp_hw_support/dma/async_memcpy_gdma.c index 33409016fdc7..d460ca23d0f1 100644 --- a/components/esp_hw_support/dma/async_memcpy_gdma.c +++ b/components/esp_hw_support/dma/async_memcpy_gdma.c @@ -163,10 +163,10 @@ static esp_err_t esp_async_memcpy_install_gdma_template(const async_memcpy_confi atomic_init(&mcp_gdma->fsm, MCP_FSM_IDLE); mcp_gdma->gdma_bus_id = gdma_bus_id; - uint32_t psram_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_EXT_MEM); + uint32_t psram_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); uint32_t sram_cache_line_size = 0; #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE - sram_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_INT_MEM); + sram_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); #endif // if the psram_trans_align is configured to zero, we should fall back to use the data cache line size diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index 79c012a88d61..feca5dfe53a6 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -358,7 +358,7 @@ esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_t ESP_RETURN_ON_FALSE((sram_alignment & (sram_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "invalid sram alignment: %zu", sram_alignment); - uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_EXT_MEM); + uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); if (psram_alignment == 0) { // fall back to use the same size of the psram data cache line size psram_alignment = data_cache_line_size; diff --git a/components/esp_hw_support/mspi_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning.c index 9768966f3eb1..fd05a330001f 100644 --- a/components/esp_hw_support/mspi_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning.c @@ -474,7 +474,7 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down) * for preventing concurrent from MSPI to external memory */ #if SOC_CACHE_FREEZE_SUPPORTED - cache_hal_freeze(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_freeze(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif //#if SOC_CACHE_FREEZE_SUPPORTED if (switch_down) { @@ -486,7 +486,7 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down) } #if SOC_CACHE_FREEZE_SUPPORTED - cache_hal_unfreeze(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_unfreeze(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif //#if SOC_CACHE_FREEZE_SUPPORTED } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 37841c7eaaf2..e2b50a8931ac 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -404,7 +404,7 @@ static int s_cache_suspend_cnt = 0; static void IRAM_ATTR suspend_cache(void) { s_cache_suspend_cnt++; if (s_cache_suspend_cnt == 1) { - cache_hal_suspend(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } } @@ -413,7 +413,7 @@ static void IRAM_ATTR resume_cache(void) { s_cache_suspend_cnt--; assert(s_cache_suspend_cnt >= 0 && DRAM_STR("cache resume doesn't match suspend ops")); if (s_cache_suspend_cnt == 0) { - cache_hal_resume(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_resume(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } } diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i80.c b/components/esp_lcd/src/esp_lcd_panel_io_i80.c index 0130bbd46314..db86c75f03b5 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i80.c @@ -492,7 +492,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons trans_desc->user_ctx = i80_device->user_ctx; if (esp_ptr_external_ram(color)) { - uint32_t dcache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, CACHE_LL_LEVEL_EXT_MEM); + uint32_t dcache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); // flush frame buffer from cache to the physical PSRAM // note the esp_cache_msync function will check the alignment of the address and size, make sure they're aligned to current cache line size esp_cache_msync((void *)ALIGN_DOWN((intptr_t)color, dcache_line_size), ALIGN_UP(color_size, dcache_line_size), 0); diff --git a/components/esp_mm/esp_cache.c b/components/esp_mm/esp_cache.c index 2b3c405e9ac1..38ee4ca687fb 100644 --- a/components/esp_mm/esp_cache.c +++ b/components/esp_mm/esp_cache.c @@ -51,7 +51,7 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags) if (flags & ESP_CACHE_MSYNC_FLAG_TYPE_INST) { cache_type = CACHE_TYPE_INSTRUCTION; } - uint32_t cache_line_size = cache_hal_get_cache_line_size(cache_type, cache_level); + uint32_t cache_line_size = cache_hal_get_cache_line_size(cache_level, cache_type); if ((flags & ESP_CACHE_MSYNC_FLAG_UNALIGNED) == 0) { bool aligned_addr = (((uint32_t)addr % cache_line_size) == 0) && ((size % cache_line_size) == 0); ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address: 0x%x, or the size: 0x%x is(are) not aligned with cache line size (0x%x)B", (uint32_t)addr, size, cache_line_size); @@ -111,10 +111,10 @@ esp_err_t esp_cache_aligned_malloc(size_t size, uint32_t flags, void **out_ptr, } #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE - data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, cache_level); + data_cache_line_size = cache_hal_get_cache_line_size(cache_level, CACHE_TYPE_DATA); #else if (cache_level == CACHE_LL_LEVEL_EXT_MEM) { - data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA, cache_level); + data_cache_line_size = cache_hal_get_cache_line_size(cache_level, CACHE_TYPE_DATA); } else { data_cache_line_size = 4; } diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 58f58f140155..484609959616 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -341,7 +341,7 @@ void IRAM_ATTR do_multicore_settings(void) cache_bus_mask_t cache_bus_mask_core0 = cache_ll_l1_get_enabled_bus(0); #ifndef CONFIG_IDF_TARGET_ESP32 // 1. disable the cache before changing its settings. - cache_hal_disable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif for (unsigned core = 1; core < SOC_CPU_CORES_NUM; core++) { // 2. change cache settings. All cores must have the same settings. @@ -349,7 +349,7 @@ void IRAM_ATTR do_multicore_settings(void) } #ifndef CONFIG_IDF_TARGET_ESP32 // 3. enable the cache after changing its settings. - cache_hal_enable(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); #endif } #endif //#if !CONFIG_IDF_TARGET_ESP32P4 diff --git a/components/hal/cache_hal.c b/components/hal/cache_hal.c index ef4422f6e3c4..6252970e4387 100644 --- a/components/hal/cache_hal.c +++ b/components/hal/cache_hal.c @@ -167,7 +167,7 @@ bool s_get_cache_state(uint32_t cache_level, cache_type_t type) } #endif //#if CACHE_LL_ENABLE_DISABLE_STATE_SW -void cache_hal_disable(cache_type_t type, uint32_t cache_level) +void cache_hal_disable(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); @@ -178,7 +178,7 @@ void cache_hal_disable(cache_type_t type, uint32_t cache_level) #endif } -void cache_hal_enable(cache_type_t type, uint32_t cache_level) +void cache_hal_enable(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); @@ -193,7 +193,7 @@ void cache_hal_enable(cache_type_t type, uint32_t cache_level) #endif } -void cache_hal_suspend(cache_type_t type, uint32_t cache_level) +void cache_hal_suspend(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); @@ -204,7 +204,7 @@ void cache_hal_suspend(cache_type_t type, uint32_t cache_level) #endif } -void cache_hal_resume(cache_type_t type, uint32_t cache_level) +void cache_hal_resume(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); @@ -219,7 +219,7 @@ void cache_hal_resume(cache_type_t type, uint32_t cache_level) #endif } -bool cache_hal_is_cache_enabled(cache_type_t type, uint32_t cache_level) +bool cache_hal_is_cache_enabled(uint32_t cache_level, cache_type_t type) { bool enabled = false; #if CACHE_LL_ENABLE_DISABLE_STATE_SW @@ -269,14 +269,14 @@ bool cache_hal_writeback_addr(uint32_t vaddr, uint32_t size) #endif //#if SOC_CACHE_WRITEBACK_SUPPORTED #if SOC_CACHE_FREEZE_SUPPORTED -void cache_hal_freeze(cache_type_t type, uint32_t cache_level) +void cache_hal_freeze(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); cache_ll_freeze_cache(cache_level, type, CACHE_LL_ID_ALL); } -void cache_hal_unfreeze(cache_type_t type, uint32_t cache_level) +void cache_hal_unfreeze(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); @@ -284,7 +284,7 @@ void cache_hal_unfreeze(cache_type_t type, uint32_t cache_level) } #endif //#if SOC_CACHE_FREEZE_SUPPORTED -uint32_t cache_hal_get_cache_line_size(cache_type_t type, uint32_t cache_level) +uint32_t cache_hal_get_cache_line_size(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); diff --git a/components/hal/esp32/cache_hal_esp32.c b/components/hal/esp32/cache_hal_esp32.c index 895aeaa02a5d..6b4fd2037da2 100644 --- a/components/hal/esp32/cache_hal_esp32.c +++ b/components/hal/esp32/cache_hal_esp32.c @@ -14,7 +14,7 @@ static uint32_t s_cache_status[2]; * There's a bug that Cache_Read_Disable requires a call to Cache_Flush * before Cache_Read_Enable, even if cached data was not modified. */ -void cache_hal_suspend(cache_type_t type, uint32_t cache_level) +void cache_hal_suspend(uint32_t cache_level, cache_type_t type) { s_cache_status[0] = cache_ll_l1_get_enabled_bus(0); cache_ll_l1_disable_cache(0); @@ -25,7 +25,7 @@ void cache_hal_suspend(cache_type_t type, uint32_t cache_level) } -void cache_hal_resume(cache_type_t type, uint32_t cache_level) +void cache_hal_resume(uint32_t cache_level, cache_type_t type) { cache_ll_l1_enable_cache(0); cache_ll_l1_enable_bus(0, s_cache_status[0]); @@ -36,7 +36,7 @@ void cache_hal_resume(cache_type_t type, uint32_t cache_level) } -bool cache_hal_is_cache_enabled(cache_type_t type, uint32_t cache_level) +bool cache_hal_is_cache_enabled(uint32_t cache_level, cache_type_t type) { bool result = cache_ll_l1_is_cache_enabled(0, CACHE_TYPE_ALL); #if !CONFIG_FREERTOS_UNICORE @@ -53,7 +53,7 @@ bool cache_hal_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint3 return cache_ll_vaddr_to_cache_level_id(vaddr_start, len, out_level, out_id); } -uint32_t cache_hal_get_cache_line_size(cache_type_t type, uint32_t cache_level) +uint32_t cache_hal_get_cache_line_size(uint32_t cache_level, cache_type_t type) { HAL_ASSERT(cache_level && (cache_level <= CACHE_LL_LEVEL_NUMS)); return 4; diff --git a/components/hal/include/hal/cache_hal.h b/components/hal/include/hal/cache_hal.h index f5592f15db77..36926976c74c 100644 --- a/components/hal/include/hal/cache_hal.h +++ b/components/hal/include/hal/cache_hal.h @@ -29,20 +29,20 @@ void cache_hal_init(void); * * @note If the autoload feature is enabled, this API will return until the ICache autoload is disabled. * - * @param type see `cache_type_t` * @param cache_level Level of the Cache(s) + * @param type see `cache_type_t` */ -void cache_hal_disable(cache_type_t type, uint32_t cache_level); +void cache_hal_disable(uint32_t cache_level, cache_type_t type); /** * @brief Enable Cache * * Enable the ICache or DCache or both, of a certain level or all levels. * - * @param type see `cache_type_t` * @param cache_level Level of the Cache(s) + * @param type see `cache_type_t` */ -void cache_hal_enable(cache_type_t type, uint32_t cache_level); +void cache_hal_enable(uint32_t cache_level, cache_type_t type); /** * @brief Suspend Cache @@ -50,30 +50,30 @@ void cache_hal_enable(cache_type_t type, uint32_t cache_level); * Suspend the ICache or DCache or both, of a certain level or all levels. * This API suspends the CPU access to cache for a while, without invalidation. * - * @param type see `cache_type_t` * @param cache_level Level of the Cache(s) + * @param type see `cache_type_t` */ -void cache_hal_suspend(cache_type_t type, uint32_t cache_level); +void cache_hal_suspend(uint32_t cache_level, cache_type_t type); /** * @brief Resume Cache * * Resume the ICache or DCache or both, of a certain level or all levels. * - * @param type see `cache_type_t` * @param cache_level Level of the Cache(s) + * @param type see `cache_type_t` */ -void cache_hal_resume(cache_type_t type, uint32_t cache_level); +void cache_hal_resume(uint32_t cache_level, cache_type_t type); /** * @brief Check if corresponding cache is enabled or not * - * @param type see `cache_type_t` * @param cache_level Level of the Cache(s) + * @param type see `cache_type_t` * * @return true: enabled; false: disabled */ -bool cache_hal_is_cache_enabled(cache_type_t type, uint32_t cache_level); +bool cache_hal_is_cache_enabled(uint32_t cache_level, cache_type_t type); /** * @brief Invalidate Cache supported addr @@ -107,30 +107,31 @@ bool cache_hal_writeback_addr(uint32_t vaddr, uint32_t size); * * Freeze cache, CPU access to cache will be suspended, until the cache is unfrozen. * - * @param type see `cache_type_t` * @param cache_level Level of the Cache(s) + * @param type see `cache_type_t` */ -void cache_hal_freeze(cache_type_t type, uint32_t cache_level); +void cache_hal_freeze(uint32_t cache_level, cache_type_t type); /** * @brief Unfreeze cache * * Unfreeze cache, CPU access to cache will be restored * - * @param type see `cache_type_t` * @param cache_level Level of the Cache(s) + * @param type see `cache_type_t` */ -void cache_hal_unfreeze(cache_type_t type, uint32_t cache_level); +void cache_hal_unfreeze(uint32_t cache_level, cache_type_t type); #endif //#if SOC_CACHE_FREEZE_SUPPORTED /** * @brief Get cache line size, in bytes * + * @param cache_level Level of the Cache(s) * @param type see `cache_type_t` - * @param cache_level Level of the Cache(s) * + * * @return cache line size, in bytes */ -uint32_t cache_hal_get_cache_line_size(cache_type_t type, uint32_t cache_level); +uint32_t cache_hal_get_cache_line_size(uint32_t cache_level, cache_type_t type); /** * @brief Get Cache level and the ID of the vaddr diff --git a/components/spi_flash/cache_utils.c b/components/spi_flash/cache_utils.c index ad8707fd6ba8..9c145f1ee7fd 100644 --- a/components/spi_flash/cache_utils.c +++ b/components/spi_flash/cache_utils.c @@ -360,17 +360,17 @@ void IRAM_ATTR spi_flash_enable_cache(uint32_t cpuid) void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state) { - cache_hal_suspend(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state) { - cache_hal_resume(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + cache_hal_resume(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } bool IRAM_ATTR spi_flash_cache_enabled(void) { - return cache_hal_is_cache_enabled(CACHE_TYPE_ALL, CACHE_LL_LEVEL_EXT_MEM); + return cache_hal_is_cache_enabled(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); } #if CONFIG_IDF_TARGET_ESP32S2 From 32db81a6d615f2a53a8cc9f3baba587d0726387a Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 21 Sep 2023 14:47:09 +0800 Subject: [PATCH 027/142] change(rmt): update cache_hal_get_cache_line_size accordingly --- components/driver/rmt/rmt_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/driver/rmt/rmt_rx.c b/components/driver/rmt/rmt_rx.c index 9ee7d1ad16a1..eb490d17f86e 100644 --- a/components/driver/rmt/rmt_rx.c +++ b/components/driver/rmt/rmt_rx.c @@ -353,7 +353,7 @@ esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_ ESP_RETURN_ON_FALSE(esp_ptr_internal(buffer), ESP_ERR_INVALID_ARG, TAG, "buffer must locate in internal RAM for DMA use"); #if CONFIG_IDF_TARGET_ESP32P4 - uint32_t data_cache_line_mask = cache_hal_get_cache_line_size(CACHE_TYPE_DATA) - 1; + uint32_t data_cache_line_mask = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA) - 1; ESP_RETURN_ON_FALSE(((uintptr_t)buffer & data_cache_line_mask) == 0, ESP_ERR_INVALID_ARG, TAG, "buffer must be aligned to cache line size"); ESP_RETURN_ON_FALSE((buffer_size & data_cache_line_mask) == 0, ESP_ERR_INVALID_ARG, TAG, "buffer size must be aligned to cache line size"); #endif From 87af877d339d9d6b24f8a41faf15d50318a2c026 Mon Sep 17 00:00:00 2001 From: baohongde Date: Fri, 22 Sep 2023 14:36:45 +0800 Subject: [PATCH 028/142] feat(bt/hci): Added Vendor-Specific HCI command to disable DM1 for ACL-U --- components/bt/controller/lib_esp32 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index 03bfbf0a689e..943b0f24eb6e 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit 03bfbf0a689e268309e496a1a0bb248ddab2c808 +Subproject commit 943b0f24eb6ed390213599e4a9556c66844ef0db From 3dc13d58a163607a5d5bc08994ea316d877899d8 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 21 Sep 2023 11:41:06 +0800 Subject: [PATCH 029/142] fix(intr): always allocate memory from internal ram Closes https://github.com/espressif/esp-idf/issues/12271 --- components/driver/rmt/rmt_tx.c | 4 ++++ .../driver/test_apps/rmt/main/CMakeLists.txt | 2 +- .../test_apps/rmt/main/test_util_rmt_encoders.c | 5 +++-- components/driver/test_apps/rmt/pytest_rmt.py | 17 +++++++++++++++-- .../test_apps/rmt/sdkconfig.defaults.esp32s3 | 4 ++++ components/esp_hw_support/intr_alloc.c | 4 ++-- 6 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 components/driver/test_apps/rmt/sdkconfig.defaults.esp32s3 diff --git a/components/driver/rmt/rmt_tx.c b/components/driver/rmt/rmt_tx.c index 31a53bec3f45..5c1136e51e58 100644 --- a/components/driver/rmt/rmt_tx.c +++ b/components/driver/rmt/rmt_tx.c @@ -486,6 +486,10 @@ esp_err_t rmt_transmit(rmt_channel_handle_t channel, rmt_encoder_t *encoder, con #if !SOC_RMT_SUPPORT_TX_LOOP_COUNT ESP_RETURN_ON_FALSE(config->loop_count <= 0, ESP_ERR_NOT_SUPPORTED, TAG, "loop count is not supported"); #endif // !SOC_RMT_SUPPORT_TX_LOOP_COUNT +#if CONFIG_RMT_ISR_IRAM_SAFE + // payload is retrieved by the encoder, we should make sure it's still accessible even when the cache is disabled + ESP_RETURN_ON_FALSE(esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); +#endif rmt_group_t *group = channel->group; rmt_hal_context_t *hal = &group->hal; int channel_id = channel->channel_id; diff --git a/components/driver/test_apps/rmt/main/CMakeLists.txt b/components/driver/test_apps/rmt/main/CMakeLists.txt index 0f606cfe2166..018443a52a29 100644 --- a/components/driver/test_apps/rmt/main/CMakeLists.txt +++ b/components/driver/test_apps/rmt/main/CMakeLists.txt @@ -9,5 +9,5 @@ if(CONFIG_RMT_ISR_IRAM_SAFE) endif() idf_component_register(SRCS "${srcs}" - PRIV_REQUIRES unity driver esp_timer + PRIV_REQUIRES unity driver esp_timer esp_psram WHOLE_ARCHIVE) diff --git a/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c b/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c index 6c95e5d63174..15dde71a3091 100644 --- a/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c +++ b/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c @@ -9,6 +9,7 @@ #include "sdkconfig.h" #include "unity.h" #include "driver/rmt_encoder.h" +#include "esp_heap_caps.h" #include "esp_attr.h" typedef struct { @@ -72,7 +73,7 @@ static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder) esp_err_t test_rmt_new_led_strip_encoder(rmt_encoder_handle_t *ret_encoder) { - rmt_led_strip_encoder_t *led_encoder = calloc(1, sizeof(rmt_led_strip_encoder_t)); + rmt_led_strip_encoder_t *led_encoder = heap_caps_calloc(1, sizeof(rmt_led_strip_encoder_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); led_encoder->base.encode = rmt_encode_led_strip; led_encoder->base.del = rmt_del_led_strip_encoder; led_encoder->base.reset = rmt_led_strip_encoder_reset; @@ -187,7 +188,7 @@ static esp_err_t rmt_nec_protocol_encoder_reset(rmt_encoder_t *encoder) esp_err_t test_rmt_new_nec_protocol_encoder(rmt_encoder_handle_t *ret_encoder) { - rmt_nec_protocol_encoder_t *nec_encoder = calloc(1, sizeof(rmt_nec_protocol_encoder_t)); + rmt_nec_protocol_encoder_t *nec_encoder = heap_caps_calloc(1, sizeof(rmt_nec_protocol_encoder_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); nec_encoder->base.encode = rmt_encode_nec_protocol; nec_encoder->base.del = rmt_del_nec_protocol_encoder; nec_encoder->base.reset = rmt_nec_protocol_encoder_reset; diff --git a/components/driver/test_apps/rmt/pytest_rmt.py b/components/driver/test_apps/rmt/pytest_rmt.py index 1bbb3bace0e0..95e33cf3168e 100644 --- a/components/driver/test_apps/rmt/pytest_rmt.py +++ b/components/driver/test_apps/rmt/pytest_rmt.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest @@ -7,7 +7,6 @@ @pytest.mark.esp32 @pytest.mark.esp32s2 -@pytest.mark.esp32s3 @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 @@ -22,3 +21,17 @@ ) def test_rmt(dut: Dut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.esp32s3 +@pytest.mark.octal_psram +@pytest.mark.parametrize( + 'config', + [ + 'iram_safe', + 'release', + ], + indirect=True, +) +def test_rmt_psram(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/driver/test_apps/rmt/sdkconfig.defaults.esp32s3 b/components/driver/test_apps/rmt/sdkconfig.defaults.esp32s3 new file mode 100644 index 000000000000..24336a0742ef --- /dev/null +++ b/components/driver/test_apps/rmt/sdkconfig.defaults.esp32s3 @@ -0,0 +1,4 @@ +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index 02d72ccd5d18..da8b616ec3a8 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -560,7 +560,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre //Allocate that int! if (flags & ESP_INTR_FLAG_SHARED) { //Populate vector entry and add to linked list. - shared_vector_desc_t *sh_vec=malloc(sizeof(shared_vector_desc_t)); + shared_vector_desc_t *sh_vec = heap_caps_malloc(sizeof(shared_vector_desc_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (sh_vec == NULL) { portEXIT_CRITICAL(&spinlock); free(ret); @@ -583,7 +583,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre vd->flags = VECDESC_FL_NONSHARED; if (handler) { #if CONFIG_APPTRACE_SV_ENABLE - non_shared_isr_arg_t *ns_isr_arg=malloc(sizeof(non_shared_isr_arg_t)); + non_shared_isr_arg_t *ns_isr_arg = heap_caps_malloc(sizeof(non_shared_isr_arg_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (!ns_isr_arg) { portEXIT_CRITICAL(&spinlock); free(ret); From 265288190027c3430ba9d92462720e9fa8239adb Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Thu, 21 Sep 2023 20:31:38 +0800 Subject: [PATCH 030/142] feat(openthread): enable time sync feature --- components/openthread/Kconfig | 9 +++++++ .../openthread-core-esp32x-ftd-config.h | 11 +++++++- .../openthread-core-esp32x-mtd-config.h | 10 +++++++ .../src/port/esp_openthread_radio.c | 26 ++++++++++++++++--- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 1742ccd2397a..90be8b4f2d10 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -277,4 +277,13 @@ menu "OpenThread" default n help Only used for Thread1.2 certification + + config OPENTHREAD_TIME_SYNC + bool "Enable the time synchronization service feature" + depends on OPENTHREAD_ENABLED + default n + help + Select this option to enable time synchronization feature, the devices in the same Thread network could + sync to the same network time. + 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 166edab9aae0..88b68a090806 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -517,7 +517,6 @@ #define OPENTHREAD_CONFIG_OPERATIONAL_DATASET_AUTO_INIT 1 #endif - /** * * Define as 1 to enable support for allocating message pool buffer in PSRAM @@ -536,4 +535,14 @@ #define OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT 1 #endif +/** + * @def OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + * + * Define as 1 to enable the time synchronization service feature. + * + */ +#if CONFIG_OPENTHREAD_TIME_SYNC +#define OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1 +#endif + #define OPENTHREAD_FTD 1 diff --git a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h index f84a6f80ebbc..537d972611c1 100644 --- a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h @@ -242,4 +242,14 @@ */ #define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE CONFIG_OPENTHREAD_DNS_CLIENT +/** + * @def OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + * + * Define as 1 to enable the time synchronization service feature. + * + */ +#if CONFIG_OPENTHREAD_TIME_SYNC +#define OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1 +#endif + #define OPENTHREAD_MTD 1 diff --git a/components/openthread/src/port/esp_openthread_radio.c b/components/openthread/src/port/esp_openthread_radio.c index 6ad310fd03e6..314b6ab70bf8 100644 --- a/components/openthread/src/port/esp_openthread_radio.c +++ b/components/openthread/src/port/esp_openthread_radio.c @@ -711,15 +711,33 @@ void IRAM_ATTR esp_ieee802154_receive_sfd_done(void) void IRAM_ATTR esp_ieee802154_transmit_sfd_done(uint8_t *frame) { assert(frame == (uint8_t *)&s_transmit_psdu || frame == s_enhack); -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - otRadioFrame ot_frame; - ot_frame.mPsdu = frame + 1; - ot_frame.mLength = frame[0]; +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE if (s_csl_period > 0) { + otRadioFrame ot_frame; + ot_frame.mPsdu = frame + 1; + ot_frame.mLength = frame[0]; + otMacFrameSetCslIe(&ot_frame, s_csl_period, get_csl_phase()); } #endif + +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + if (frame == (uint8_t *)&s_transmit_psdu && s_transmit_frame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0) + { + uint8_t *p_time_ie = s_transmit_frame.mPsdu + s_transmit_frame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset; + uint64_t time = (uint64_t)((int64_t)otPlatTimeGet() + s_transmit_frame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset); + + *p_time_ie = s_transmit_frame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq; + + *(++p_time_ie) = (uint8_t)(time & 0xff); + for (uint8_t i = 1; i < sizeof(uint64_t); i++) + { + time = time >> 8; + *(++p_time_ie) = (uint8_t)(time & 0xff); + } + } +#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE } void IRAM_ATTR esp_ieee802154_energy_detect_done(int8_t power) From eb65d0a9cd574e1a4e5b780c4bc4bd5df4455851 Mon Sep 17 00:00:00 2001 From: liqigan Date: Fri, 22 Sep 2023 16:10:08 +0800 Subject: [PATCH 031/142] fix(bt/bluedroid): Fix the issue for HID congestion checking --- components/bt/host/bluedroid/stack/hid/hidd_conn.c | 2 +- components/bt/host/bluedroid/stack/hid/hidh_conn.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/bt/host/bluedroid/stack/hid/hidd_conn.c b/components/bt/host/bluedroid/stack/hid/hidd_conn.c index 623f085985f4..3b44402eed1b 100644 --- a/components/bt/host/bluedroid/stack/hid/hidd_conn.c +++ b/components/bt/host/bluedroid/stack/hid/hidd_conn.c @@ -776,7 +776,7 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param } #endif HIDD_TRACE_VERBOSE("%s: report sent", __func__); - if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED || !L2CA_DataWrite(cid, p_buf)) + if (L2CA_DataWrite(cid, p_buf) == L2CAP_DW_FAILED) return (HID_ERR_CONGESTED); return (HID_SUCCESS); } diff --git a/components/bt/host/bluedroid/stack/hid/hidh_conn.c b/components/bt/host/bluedroid/stack/hid/hidh_conn.c index 42d170ddd0c4..801f087cc5af 100644 --- a/components/bt/host/bluedroid/stack/hid/hidh_conn.c +++ b/components/bt/host/bluedroid/stack/hid/hidh_conn.c @@ -928,7 +928,7 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param, data_size -= bytes_copied; /* Send the buffer through L2CAP */ - if ((p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) || (!L2CA_DataWrite (cid, p_buf))) { + if (L2CA_DataWrite(cid, p_buf) == L2CAP_DW_FAILED) { return (HID_ERR_CONGESTED); } From dc5d4b0ac01bcab04bbe612070c97420c4f76a9f Mon Sep 17 00:00:00 2001 From: Tomas Sebestik Date: Fri, 22 Sep 2023 10:35:24 +0200 Subject: [PATCH 032/142] ci(danger-gitlab): Add CI job tracelog checks output For role/check 'mrSourceBranchName' changed the output severity to warn (was info) --- .gitlab/dangerjs/configParameters.js | 56 +++++++++++++++++++ .gitlab/dangerjs/dangerfile.js | 8 ++- .gitlab/dangerjs/mrAreaLabels.js | 9 ++- .gitlab/dangerjs/mrCommitsCommitMessage.js | 8 ++- .gitlab/dangerjs/mrCommitsEmail.js | 7 +++ .gitlab/dangerjs/mrCommitsTooManyCommits.js | 7 +++ .gitlab/dangerjs/mrDescriptionJiraLinks.js | 10 +++- .gitlab/dangerjs/mrDescriptionLongEnough.js | 7 +++ .gitlab/dangerjs/mrDescriptionReleaseNotes.js | 14 +++-- .gitlab/dangerjs/mrDocsTranslation.js | 9 +++ .gitlab/dangerjs/mrSizeTooLarge.js | 7 +++ .gitlab/dangerjs/mrSourceBranchName.js | 14 ++++- .gitlab/dangerjs/mrTitleNoDraftOrWip.js | 33 +++++++---- 13 files changed, 165 insertions(+), 24 deletions(-) create mode 100644 .gitlab/dangerjs/configParameters.js diff --git a/.gitlab/dangerjs/configParameters.js b/.gitlab/dangerjs/configParameters.js new file mode 100644 index 000000000000..9fb27960c588 --- /dev/null +++ b/.gitlab/dangerjs/configParameters.js @@ -0,0 +1,56 @@ +let outputStatuses = []; + +/** + * Logs the status of a rule with padded formatting and stores it in the `outputStatuses` array. + * If the rule already exists in the array, its status is updated. + * @param message The name of the rule + * @param status The output (exit) status of the rule + */ +function recordRuleExitStatus(message, status) { + // Check if the rule already exists in the array + const existingRecord = outputStatuses.find( + (rule) => rule.message === message + ); + + if (existingRecord) { + // Update the status of the existing rule + existingRecord.status = status; + } else { + // If the rule doesn't exist, add it to the array + outputStatuses.push({ message, status }); + } +} + +/** + * Displays all the rule output statuses stored in the `outputStatuses` array. + * Filters out any empty lines, sorts them alphabetically, and prints the statuses + * with a header and separator. + * These statuses are later displayed in CI job tracelog. + */ +function displayAllOutputStatuses() { + const lineLength = 100; + const sortedStatuses = outputStatuses.sort((a, b) => + a.message.localeCompare(b.message) + ); + + const formattedLines = sortedStatuses.map((statusObj) => { + const paddingLength = + lineLength - statusObj.message.length - statusObj.status.length; + const paddedMessage = statusObj.message.padEnd( + statusObj.message.length + paddingLength, + "." + ); + return `${paddedMessage} ${statusObj.status}`; + }); + + console.log( + "DangerJS checks (rules) output states:\n" + "=".repeat(lineLength + 2) + ); + console.log(formattedLines.join("\n")); + console.log("=".repeat(lineLength + 2)); +} + +module.exports = { + displayAllOutputStatuses, + recordRuleExitStatus, +}; diff --git a/.gitlab/dangerjs/dangerfile.js b/.gitlab/dangerjs/dangerfile.js index 80b51967257a..544afcfa857e 100644 --- a/.gitlab/dangerjs/dangerfile.js +++ b/.gitlab/dangerjs/dangerfile.js @@ -1,7 +1,8 @@ +const { displayAllOutputStatuses } = require("./configParameters.js"); + /* * Modules with checks are stored in ".gitlab/dangerjs/". To import them, use path relative to "dangerfile.js" */ - async function runChecks() { // Checks for merge request title require("./mrTitleNoDraftOrWip.js")(); @@ -28,13 +29,16 @@ async function runChecks() { // Checks for Source branch name require("./mrSourceBranchName.js")(); + // Show DangerJS individual checks statuses - visible in CI job tracelog + displayAllOutputStatuses(); + // Add success log if no issues if ( results.fails.length === 0 && results.warnings.length === 0 && results.messages.length === 0 ) { - return message("Good Job! All checks are passing!"); + return message("🎉 Good Job! All checks are passing!"); } } diff --git a/.gitlab/dangerjs/mrAreaLabels.js b/.gitlab/dangerjs/mrAreaLabels.js index 6ee3148be7be..159d5bc07401 100644 --- a/.gitlab/dangerjs/mrAreaLabels.js +++ b/.gitlab/dangerjs/mrAreaLabels.js @@ -1,9 +1,12 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check if MR has area labels (light blue labels) * * @dangerjs WARN */ module.exports = async function () { + const ruleName = "Merge request area labels"; const projectId = 103; // ESP-IDF const areaLabelColor = /^#d2ebfa$/i; // match color code (case-insensitive) const projectLabels = await danger.gitlab.api.Labels.all(projectId); // Get all project labels @@ -13,8 +16,12 @@ module.exports = async function () { const mrLabels = danger.gitlab.mr.labels; // Get MR labels if (!mrLabels.some((label) => areaLabels.includes(label))) { - warn( + recordRuleExitStatus(ruleName, "Failed"); + return warn( `Please add some [area labels](${process.env.DANGER_GITLAB_HOST}/espressif/esp-idf/-/labels) to this MR.` ); } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, "Passed"); }; diff --git a/.gitlab/dangerjs/mrCommitsCommitMessage.js b/.gitlab/dangerjs/mrCommitsCommitMessage.js index 14ac0a1a2dbc..6d90dbaf6a9d 100644 --- a/.gitlab/dangerjs/mrCommitsCommitMessage.js +++ b/.gitlab/dangerjs/mrCommitsCommitMessage.js @@ -4,6 +4,7 @@ const { maximumBodyLineChars, allowedTypes, } = require("./mrCommitsConstants.js"); +const { recordRuleExitStatus } = require("./configParameters.js"); /** * Check that commit messages are based on the Espressif ESP-IDF project's rules for git commit messages. @@ -11,6 +12,7 @@ const { * @dangerjs WARN */ module.exports = async function () { + const ruleName = "Commit messages style"; const mrCommits = danger.gitlab.commits; const lint = require("@commitlint/lint").default; @@ -154,6 +156,10 @@ module.exports = async function () { dangerMessage += AImessageSuggestion; } - warn(dangerMessage); + recordRuleExitStatus(ruleName, "Failed"); + return warn(dangerMessage); } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, "Passed"); }; diff --git a/.gitlab/dangerjs/mrCommitsEmail.js b/.gitlab/dangerjs/mrCommitsEmail.js index 9ffc1b7eea43..8adfc743ef54 100644 --- a/.gitlab/dangerjs/mrCommitsEmail.js +++ b/.gitlab/dangerjs/mrCommitsEmail.js @@ -1,16 +1,23 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check if the author is accidentally making a commit using a personal email * * @dangerjs INFO */ module.exports = function () { + const ruleName = 'Commits from outside Espressif'; const mrCommitAuthorEmails = danger.gitlab.commits.map(commit => commit.author_email); const mrCommitCommitterEmails = danger.gitlab.commits.map(commit => commit.committer_email); const emailPattern = /.*@espressif\.com/; const filteredEmails = [...mrCommitAuthorEmails, ...mrCommitCommitterEmails].filter((email) => !emailPattern.test(email)); if (filteredEmails.length) { + recordRuleExitStatus(ruleName, "Failed"); return message( `Some of the commits were authored or committed by developers outside Espressif: ${filteredEmails.join(', ')}. Please check if this is expected.` ); } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, 'Passed'); }; diff --git a/.gitlab/dangerjs/mrCommitsTooManyCommits.js b/.gitlab/dangerjs/mrCommitsTooManyCommits.js index 32a8cf96fa7c..1cd49e1ad03f 100644 --- a/.gitlab/dangerjs/mrCommitsTooManyCommits.js +++ b/.gitlab/dangerjs/mrCommitsTooManyCommits.js @@ -1,15 +1,22 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check if MR has not an excessive numbers of commits (if squashed) * * @dangerjs INFO */ module.exports = function () { + const ruleName = 'Number of commits in merge request'; const tooManyCommitThreshold = 2; // above this number of commits, squash commits is suggested const mrCommits = danger.gitlab.commits; if (mrCommits.length > tooManyCommitThreshold) { + recordRuleExitStatus(ruleName, "Passed (with suggestions)"); return message( `You might consider squashing your ${mrCommits.length} commits (simplifying branch history).` ); } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, 'Passed'); }; diff --git a/.gitlab/dangerjs/mrDescriptionJiraLinks.js b/.gitlab/dangerjs/mrDescriptionJiraLinks.js index e407cbf7f1c6..53d929da681f 100644 --- a/.gitlab/dangerjs/mrDescriptionJiraLinks.js +++ b/.gitlab/dangerjs/mrDescriptionJiraLinks.js @@ -1,3 +1,5 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** Check that there are valid JIRA links in MR description. * * This check extracts the "Related" section from the MR description and @@ -10,6 +12,7 @@ * */ module.exports = async function () { + const ruleName = 'Jira ticket references'; const axios = require("axios"); const mrDescription = danger.gitlab.mr.description; const mrCommitMessages = danger.gitlab.commits.map( @@ -26,6 +29,7 @@ module.exports = async function () { !sectionRelated.header || // No section Related in MR description or ... !jiraTicketRegex.test(sectionRelated.content) // no Jira links in section Related ) { + recordRuleExitStatus(ruleName, 'Passed (with suggestions)'); return message( "Please consider adding references to JIRA issues in the `Related` section of the MR description." ); @@ -88,6 +92,9 @@ module.exports = async function () { createReport(); } + // At this point, the rule has passed + recordRuleExitStatus(ruleName, 'Passed'); + // --------------------------------------------------------------- /** @@ -225,6 +232,7 @@ module.exports = async function () { let dangerMessage = `Some issues found for the related JIRA tickets in this MR:\n${partMessages.join( "\n" )}`; - warn(dangerMessage); + recordRuleExitStatus(ruleName, "Failed"); + return warn(dangerMessage); } }; diff --git a/.gitlab/dangerjs/mrDescriptionLongEnough.js b/.gitlab/dangerjs/mrDescriptionLongEnough.js index cbd2dab1e827..abd098204dd3 100644 --- a/.gitlab/dangerjs/mrDescriptionLongEnough.js +++ b/.gitlab/dangerjs/mrDescriptionLongEnough.js @@ -1,17 +1,24 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check if MR Description has accurate description". * * @dangerjs WARN */ module.exports = function () { + const ruleName = "Merge request sufficient description"; const mrDescription = danger.gitlab.mr.description; const descriptionChunk = mrDescription.match(/^([^#]*)/)[1].trim(); // Extract all text before the first section header (i.e., the text before the "## Release notes") const shortMrDescriptionThreshold = 50; // Description is considered too short below this number of characters if (descriptionChunk.length < shortMrDescriptionThreshold) { + recordRuleExitStatus(ruleName, "Failed"); return warn( "The MR description looks very brief, please check if more details can be added." ); } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, "Passed"); }; diff --git a/.gitlab/dangerjs/mrDescriptionReleaseNotes.js b/.gitlab/dangerjs/mrDescriptionReleaseNotes.js index e8691b8509a3..f9ea40341f58 100644 --- a/.gitlab/dangerjs/mrDescriptionReleaseNotes.js +++ b/.gitlab/dangerjs/mrDescriptionReleaseNotes.js @@ -1,3 +1,5 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check if MR Description contains mandatory section "Release notes" * @@ -6,6 +8,7 @@ * @dangerjs WARN (if section missing, is empty or wrong markdown format) */ module.exports = function () { + const ruleName = 'Merge request Release Notes section'; const mrDescription = danger.gitlab.mr.description; const wiki_link = `${process.env.DANGER_GITLAB_HOST}/espressif/esp-idf/-/wikis/rfc/How-to-write-release-notes-properly`; @@ -15,8 +18,8 @@ module.exports = function () { const sectionReleaseNotes = mrDescription.match(regexSectionReleaseNotes); if (!sectionReleaseNotes) { - warn(`The \`Release Notes\` section seems to be missing. Please check if the section header in MR description is present and in the correct markdown format ("## Release Notes").\n\nSee [Release Notes Format Rules](${wiki_link}).`); - return null; + recordRuleExitStatus(ruleName, "Failed"); + return warn(`The \`Release Notes\` section seems to be missing. Please check if the section header in MR description is present and in the correct markdown format ("## Release Notes").\n\nSee [Release Notes Format Rules](${wiki_link}).`); } const releaseNotesLines = sectionReleaseNotes[1].replace(//g, '') @@ -55,9 +58,12 @@ module.exports = function () { if (error_output.length > 0) { // Paragraphs joined by double `\n`s. error_output = [...error_output, `See [Release Notes Format Guide](${wiki_link}).`].join('\n\n'); - warn(error_output); + recordRuleExitStatus(ruleName, "Failed"); + return warn(error_output); } - return null; + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, 'Passed'); }; function check_entry(entry) { diff --git a/.gitlab/dangerjs/mrDocsTranslation.js b/.gitlab/dangerjs/mrDocsTranslation.js index 30a6175b78b9..7c9412a2af8e 100644 --- a/.gitlab/dangerjs/mrDocsTranslation.js +++ b/.gitlab/dangerjs/mrDocsTranslation.js @@ -1,3 +1,5 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check the documentation files in this MR. * @@ -24,6 +26,7 @@ * */ module.exports = async function () { + const ruleName = 'Documentation translation'; let partMessages = []; // Create a blank field for future records of individual issues const pathProject = "espressif/esp-idf"; const regexIncludeLink = /\.\.\sinclude::\s((\.\.\/)+)en\//; @@ -90,6 +93,9 @@ module.exports = async function () { // Create a report with found issues with documents in MR createReport(); + // At this point, the rule has passed + recordRuleExitStatus(ruleName, 'Passed'); + /** * Generates an object that represents the relationships between files in two different languages found in this MR. * @@ -245,6 +251,7 @@ module.exports = async function () { // No docs issues found in MR, but translation labels have been added anyway if (!partMessages.length && translationLabelsPresent) { + recordRuleExitStatus(ruleName, "Failed"); return warn( `Please remove the \`needs translation: XX\` labels. For documents that need to translate from scratch, Doc team will translate them in the future. For the current stage, we only focus on updating exiting EN and CN translation to make them in sync.` ); @@ -261,9 +268,11 @@ module.exports = async function () { dangerMessage += ` \nWhen synchronizing the EN and CN versions, please follow the [Documentation Code](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/contribute/documenting-code.html#standardize-document-format). The total number of lines of EN and CN should be same.\n \nIf you have difficulty in providing translation, you can contact Documentation team by adding needs translation: CN or needs translation: EN labels into this MR and retrying Danger CI job. The documentation team will be automatically notified and will help you with the translations before the merge.\n`; + recordRuleExitStatus(ruleName, "Failed"); return warn(dangerMessage); // no "needs translation: XX" labels in MR; report issues as warn } else { dangerMessage += `\nTranslation labels needs translation: CN or needs translation: EN were added - this will automatically notify the Documentation team to help you with translation issues.`; + recordRuleExitStatus(ruleName, 'Passed (with suggestions)'); return message(dangerMessage); // "needs translation: XX" labels were found in MR and Docs team was notified; report issues as info } } diff --git a/.gitlab/dangerjs/mrSizeTooLarge.js b/.gitlab/dangerjs/mrSizeTooLarge.js index c36b024cf5e3..4be6ba1e933e 100644 --- a/.gitlab/dangerjs/mrSizeTooLarge.js +++ b/.gitlab/dangerjs/mrSizeTooLarge.js @@ -1,15 +1,22 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check if MR is too large (more than 1000 lines of changes) * * @dangerjs INFO */ module.exports = async function () { + const ruleName = "Merge request size (number of changed lines)"; const bigMrLinesOfCodeThreshold = 1000; const totalLines = await danger.git.linesOfCode(); if (totalLines > bigMrLinesOfCodeThreshold) { + recordRuleExitStatus(ruleName, "Passed (with suggestions)"); return message( `This MR seems to be quite large (total lines of code: ${totalLines}), you might consider splitting it into smaller MRs` ); } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, "Passed"); }; diff --git a/.gitlab/dangerjs/mrSourceBranchName.js b/.gitlab/dangerjs/mrSourceBranchName.js index ae76ed8e569b..9512d13ec20c 100644 --- a/.gitlab/dangerjs/mrSourceBranchName.js +++ b/.gitlab/dangerjs/mrSourceBranchName.js @@ -1,23 +1,31 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Throw Danger WARN if branch name contains more than one slash or uppercase letters * * @dangerjs INFO */ module.exports = function () { + const ruleName = "Source branch name"; const sourceBranch = danger.gitlab.mr.source_branch; // Check if the source branch name contains more than one slash const slashCount = (sourceBranch.match(/\//g) || []).length; if (slashCount > 1) { - return message( + recordRuleExitStatus(ruleName, "Failed"); + return warn( `The source branch name \`${sourceBranch}\` contains more than one slash. This can cause troubles with git sync. Please rename the branch.` ); } // Check if the source branch name contains any uppercase letters if (sourceBranch !== sourceBranch.toLowerCase()) { - return message( - `The source branch name \`${sourceBranch}\` contains uppercase letters. This can cause troubles on case-insensitive file systems (macOS). Please use only lowercase letters.`, + recordRuleExitStatus(ruleName, "Failed"); + return warn( + `The source branch name \`${sourceBranch}\` contains uppercase letters. This can cause troubles on case-insensitive file systems (macOS). Please use only lowercase letters.` ); } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, "Passed"); }; diff --git a/.gitlab/dangerjs/mrTitleNoDraftOrWip.js b/.gitlab/dangerjs/mrTitleNoDraftOrWip.js index f38bd851a39a..222383ac03a2 100644 --- a/.gitlab/dangerjs/mrTitleNoDraftOrWip.js +++ b/.gitlab/dangerjs/mrTitleNoDraftOrWip.js @@ -1,22 +1,31 @@ +const { recordRuleExitStatus } = require("./configParameters.js"); + /** * Check if MR Title contains prefix "WIP: ...". * * @dangerjs WARN */ module.exports = function () { - const mrTitle = danger.gitlab.mr.title; + const ruleName = 'Merge request not in Draft or WIP state'; + const mrTitle = danger.gitlab.mr.title; const regexes = [ - { prefix: 'WIP', regex: /^WIP:/i }, - { prefix: 'W.I.P', regex: /^W\.I\.P/i }, - { prefix: '[WIP]', regex: /^\[WIP/i }, - { prefix: '[W.I.P]', regex: /^\[W\.I\.P/i }, - { prefix: '(WIP)', regex: /^\(WIP/i }, - { prefix: '(W.I.P)', regex: /^\(W\.I\.P/i }, + { prefix: "WIP", regex: /^WIP:/i }, + { prefix: "W.I.P", regex: /^W\.I\.P/i }, + { prefix: "[WIP]", regex: /^\[WIP/i }, + { prefix: "[W.I.P]", regex: /^\[W\.I\.P/i }, + { prefix: "(WIP)", regex: /^\(WIP/i }, + { prefix: "(W.I.P)", regex: /^\(W\.I\.P/i }, ]; - for (const item of regexes) { - if (item.regex.test(mrTitle)) { - return warn(`Please remove the \`${item.prefix}\` prefix from the MR name before merging this MR.`); - } - } + for (const item of regexes) { + if (item.regex.test(mrTitle)) { + recordRuleExitStatus(ruleName, "Failed"); + return warn( + `Please remove the \`${item.prefix}\` prefix from the MR name before merging this MR.` + ); + } + } + + // At this point, the rule has passed + recordRuleExitStatus(ruleName, "Passed"); }; From ec4bfbbd3da6e90d85461753cd0912876f9fd0b4 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Fri, 22 Sep 2023 14:59:04 +0530 Subject: [PATCH 033/142] fix(examples/iperf): Update and rename default TCP/UDP buffer sizes --- .../common_components/iperf/include/iperf.h | 9 +++--- examples/common_components/iperf/iperf.c | 32 +++++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/examples/common_components/iperf/include/iperf.h b/examples/common_components/iperf/include/iperf.h index e856eefdedc1..9ac7627d3a00 100644 --- a/examples/common_components/iperf/include/iperf.h +++ b/examples/common_components/iperf/include/iperf.h @@ -42,10 +42,11 @@ extern "C" { #define IPERF_REPORT_TASK_PRIORITY CONFIG_IPERF_REPORT_TASK_PRIORITY #define IPERF_REPORT_TASK_STACK 4096 -#define IPERF_UDP_TX_LEN (1470) -#define IPERF_UDP_RX_LEN (16 << 10) -#define IPERF_TCP_TX_LEN (16 << 10) -#define IPERF_TCP_RX_LEN (16 << 10) +#define IPERF_DEFAULT_IPV4_UDP_TX_LEN (1470) +#define IPERF_DEFAULT_IPV6_UDP_TX_LEN (1450) +#define IPERF_DEFAULT_UDP_RX_LEN (16 << 10) +#define IPERF_DEFAULT_TCP_TX_LEN (16 << 10) +#define IPERF_DEFAULT_TCP_RX_LEN (16 << 10) #define IPERF_MAX_DELAY 64 diff --git a/examples/common_components/iperf/iperf.c b/examples/common_components/iperf/iperf.c index 0f022dab29f3..7713967909f6 100644 --- a/examples/common_components/iperf/iperf.c +++ b/examples/common_components/iperf/iperf.c @@ -152,8 +152,8 @@ static void IRAM_ATTR socket_recv(int recv_socket, struct sockaddr_storage liste static void IRAM_ATTR socket_send(int send_socket, struct sockaddr_storage dest_addr, uint8_t type, int bw_lim) { uint8_t *buffer; - int32_t *pkt_id_p; - int32_t pkt_cnt = 0; + uint32_t *pkt_id_p; + uint32_t pkt_cnt = 0; int actual_send = 0; int want_send = 0; int period_us = -1; @@ -169,7 +169,7 @@ static void IRAM_ATTR socket_send(int send_socket, struct sockaddr_storage dest_ const char *error_log = (type == IPERF_TRANS_TYPE_TCP) ? "tcp client send" : "udp client send"; buffer = s_iperf_ctrl.buffer; - pkt_id_p = (int32_t *)s_iperf_ctrl.buffer; + pkt_id_p = (uint32_t *)s_iperf_ctrl.buffer; want_send = s_iperf_ctrl.buffer_len; iperf_start_report(); @@ -193,13 +193,7 @@ static void IRAM_ATTR socket_send(int send_socket, struct sockaddr_storage dest_ } prev_time = send_time; } - *pkt_id_p = htonl(pkt_cnt); // datagrams need to be sequentially numbered - if (pkt_cnt >= INT32_MAX) { - pkt_cnt = 0; - } - else { - pkt_cnt++; - } + *pkt_id_p = htonl(pkt_cnt++); // datagrams need to be sequentially numbered actual_send = sendto(send_socket, buffer, want_send, 0, (struct sockaddr *)&dest_addr, socklen); if (actual_send != want_send) { if (type == IPERF_TRANS_TYPE_UDP) { @@ -545,13 +539,23 @@ static void iperf_task_traffic(void *arg) static uint32_t iperf_get_buffer_len(void) { if (iperf_is_udp_client()) { - return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_UDP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf); +#ifdef CONFIG_LWIP_IPV6 + if (s_iperf_ctrl.cfg.len_send_buf) { + return s_iperf_ctrl.cfg.len_send_buf; + } else if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) { + return IPERF_DEFAULT_IPV6_UDP_TX_LEN; + } else { + return IPERF_DEFAULT_IPV4_UDP_TX_LEN; + } +#else + return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_DEFAULT_IPV4_UDP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf); +#endif } else if (iperf_is_udp_server()) { - return IPERF_UDP_RX_LEN; + return IPERF_DEFAULT_UDP_RX_LEN; } else if (iperf_is_tcp_client()) { - return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_TCP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf); + return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_DEFAULT_TCP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf); } else { - return IPERF_TCP_RX_LEN; + return IPERF_DEFAULT_TCP_RX_LEN; } return 0; } From 326ced0b353415cc8870b76213fc3ddf803117a5 Mon Sep 17 00:00:00 2001 From: darshan Date: Fri, 22 Sep 2023 15:39:32 +0530 Subject: [PATCH 034/142] doc(nimble): Added the tutorial for spp_server example. --- .../tutorial/spp_server_walkthrough.md | 579 ++++++++++++++++++ 1 file changed, 579 insertions(+) create mode 100644 examples/bluetooth/nimble/ble_spp/spp_server/tutorial/spp_server_walkthrough.md diff --git a/examples/bluetooth/nimble/ble_spp/spp_server/tutorial/spp_server_walkthrough.md b/examples/bluetooth/nimble/ble_spp/spp_server/tutorial/spp_server_walkthrough.md new file mode 100644 index 000000000000..55d92b9879e8 --- /dev/null +++ b/examples/bluetooth/nimble/ble_spp/spp_server/tutorial/spp_server_walkthrough.md @@ -0,0 +1,579 @@ +# BLE SPP Server Walkthrough + +## Introduction + +In this tutorial, we will explore the spp_server example code provided by Espressif's ESP-IDF framework. This tutorial guides you in building a BLE Serial Port Profile (SPP) server using the NimBLE stack. BLE SPP enables wireless serial communication, making it valuable for IoT and embedded applications. It allows the ESP32 to communicate with other BLE devices, handling connection management, advertising, and data transmission. The code also defines a custom GATT service and initializes UART communication for data transfer. + +## Includes + +This example is located in the examples folder of the ESP-IDF under the [ble_spp/spp_server/main](../main). The [main.c](../main/main.c) file located in the main folder contains all the functionality that we are going to review. The header files contained in [main.c](../main/main.c) are: + +```c +#include "esp_log.h" +#include "nvs_flash.h" +/* BLE */ +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "console/console.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" +#include "ble_spp_server.h" +#include "driver/uart.h" +``` + +These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `“nimble_port.h”`, `“nimble_port_freertos.h”`, `"ble_hs.h"`, `“ble_svc_gap.h”` and `“ble_spp_server.h”` which expose the BLE APIs required to implement this example. + +* `nimble_port.h`: Includes the declaration of functions required for the initialization of the nimble stack. +* `nimble_port_freertos.h`: Initializes and enables nimble host task. +* `ble_hs.h`: Defines the functionalities to handle the host event. +* `ble_svc_gap.h`: Defines the macros for device name, and device appearance and declares the function to set them. +* `ble_spp_server.h`: Includes necessary headers and defines UUIDs for the SPP service and characteristic. + + +## Main Entry Point + +The program's entry point is the `app_main()` function: +```c +void +app_main(void) +{ + int rc; + + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ret = nimble_port_init(); + if (ret != ESP_OK) { + MODLOG_DFLT(ERROR, "Failed to init nimble %d \n", ret); + return; + } + + /* Initialize connection_handle array */ + for (int i = 0; i <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + conn_handle_subs[i] = false; + } + + /* Initialize uart driver and start uart task */ + ble_spp_uart_init(); + + /* Initialize the NimBLE host configuration. */ + ble_hs_cfg.reset_cb = ble_spp_server_on_reset; + ble_hs_cfg.sync_cb = ble_spp_server_on_sync; + ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + ble_hs_cfg.sm_io_cap = CONFIG_EXAMPLE_IO_TYPE; +#ifdef CONFIG_EXAMPLE_BONDING + ble_hs_cfg.sm_bonding = 1; +#endif +#ifdef CONFIG_EXAMPLE_MITM + ble_hs_cfg.sm_mitm = 1; +#endif +#ifdef CONFIG_EXAMPLE_USE_SC + ble_hs_cfg.sm_sc = 1; +#else + ble_hs_cfg.sm_sc = 0; +#endif +#ifdef CONFIG_EXAMPLE_BONDING + ble_hs_cfg.sm_our_key_dist = 1; + ble_hs_cfg.sm_their_key_dist = 1; +#endif + + /* Register custom service */ + rc = gatt_svr_init(); + assert(rc == 0); + + /* Set the default device name. */ + rc = ble_svc_gap_device_name_set("nimble-ble-spp-svr"); + assert(rc == 0); + + /* XXX Need to have template for store */ + ble_store_config_init(); + + nimble_port_freertos_init(ble_spp_server_host_task); +} +``` + +The main function starts by initializing the non-volatile storage library. This library allows us to save the key-value pairs in flash memory. `nvs_flash_init()` stores the PHY calibration data. In a Bluetooth Low Energy (BLE) device, cryptographic keys used for encryption and authentication are often stored in Non-Volatile Storage (NVS). BLE stores the peer keys, CCCD keys, peer records, etc on NVS. By storing these keys in NVS, the BLE device can quickly retrieve them when needed, without the need for time-consuming key generations. + +```c +esp_err_t ret = nvs_flash_init(); +if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); +} +ESP_ERROR_CHECK(ret); +``` + +### BT Controller and Stack Initialization + +The main function calls `nimble_port_init()` to initialize BT Controller and nimble stack. This function initializes the BT controller by first creating its configuration structure named `esp_bt_controller_config_t` with default settings generated by the `BT_CONTROLLER_INIT_CONFIG_DEFAULT()` macro. It implements the Host Controller Interface (HCI) on the controller side, the Link Layer (LL), and the Physical Layer (PHY). The BT Controller is invisible to the user applications and deals with the lower layers of the BLE stack. The controller configuration includes setting the BT controller stack size, priority, and HCI baud rate. With the settings created, the BT controller is initialized and enabled with the `esp_bt_controller_init()` and `esp_bt_controller_enable()` functions: + + +```c +esp_bt_controller_config_t config_opts = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); +ret = esp_bt_controller_init(&config_opts); +``` + +Next, the controller is enabled in BLE Mode. +```c +ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); +``` + +The controller should be enabled in `ESP_BT_MODE_BLE` if you want to use the BLE mode. +There are four Bluetooth modes supported: + +1. `ESP_BT_MODE_IDLE`: Bluetooth not running +2. `ESP_BT_MODE_BLE`: BLE mode +3. `ESP_BT_MODE_CLASSIC_BT`: BT Classic mode +4. `ESP_BT_MODE_BTDM`: Dual mode (BLE + BT Classic) + +After the initialization of the BT controller, the nimble stack, which includes the common definitions and APIs for BLE, is initialized by using `esp_nimble_init()`: + +```c +esp_err_t esp_nimble_init(void) +{ +#if !SOC_ESP_NIMBLE_CONTROLLER + /* Initialize the function pointers for OS porting */ + npl_freertos_funcs_init(); + + npl_freertos_mempool_init(); + + if(esp_nimble_hci_init() != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci inits failed\n"); + return ESP_FAIL; + } + + /* Initialize default event queue */ + ble_npl_eventq_init(&g_eventq_dflt); + + os_msys_init(); + + void ble_store_ram_init(void); + /* XXX Need to have template for store */ + ble_store_ram_init(); +#endif + + /* Initialize the host */ + ble_hs_init(); + return ESP_OK; +} +``` + +After this, an array called `conn_handle_subs` is being initialized for the purpose of managing Bluetooth connections. The for loop iterates through a range of values, setting each element of the array to false. This action signifies that there are no active connections at the initialization stage. + +```c +/* Initialize connection_handle array */ +for (int i = 0; i <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + conn_handle_subs[i] = false; +} +``` + +The main function calls `ble_spp_uart_init`, which is responsible for initializing the UART (Universal Asynchronous Receiver-Transmitter) communication for the BLE SPP server application. + + +```c +static void ble_spp_uart_init(void) +{ + uart_config_t 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_RTS, + .rx_flow_ctrl_thresh = 122, + .source_clk = UART_SCLK_DEFAULT, + }; + //Install UART driver, and get the queue. + uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_common_uart_queue, 0); + //Set UART parameters + uart_param_config(UART_NUM_0, &uart_config); + //Set UART pins + uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + xTaskCreate(ble_server_uart_task, "uTask", 4096, (void *)UART_NUM_0, 8, NULL); +} +``` + +* It defines a configuration structure (`uart_config_t`) to specify the UART communication settings, such as `baud rate`, `data bits`, `parity`, `stop bits`, `flow control`, and more. + +* `uart_driver_install` installs the UART driver, allocating memory for the UART communication buffers and creating a queue (`spp_common_uart_queue`) to manage UART events. + +* `uart_param_config` sets the UART parameters based on the configuration structure defined earlier. + +* `uart_set_pin` configures the UART pins for communication. In this case, it uses default pin configurations. + +* Finally, it creates a FreeRTOS task (`ble_server_uart_task`) that will handle UART communication. This task is responsible for sending and receiving data over UART. + +```c +/* Initialize the NimBLE host configuration. */ +ble_hs_cfg.reset_cb = ble_spp_server_on_reset; +ble_hs_cfg.sync_cb = ble_spp_server_on_sync; +ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb; +ble_hs_cfg.store_status_cb = ble_store_util_status_rr; +``` +The host is configured by setting up the callbacks for Stack-reset, Stack-sync, registration of each GATT resource (service, characteristic, or descriptor), and storage status. + +### Security Manager Configuration +Security Manager (sm_ members) is configurable at runtime to simplify security testing. Defaults for those are configured by selecting proper options via menuconfig for example configurations. + +### I/O CAPABILITIES +```c + ble_hs_cfg.sm_io_cap = CONFIG_EXAMPLE_IO_TYPE; +#ifdef CONFIG_EXAMPLE_BONDING + ble_hs_cfg.sm_bonding = 1; +#endif +``` +`CONFIG_EXAMPLE_BONDING` is set to enable the bonding on BLE SPP server. By default this flag is disabled. It can be configured through the sdkconfig file or from the menuconfig options. + +### MITM PROTECTION +```c +#ifdef CONFIG_EXAMPLE_MITM + ble_hs_cfg.sm_mitm = 1; +#endif +``` +When the `CONFIG_EXAMPLE_MITM` flag is set during pairing, it will enable the MITM bit in the auth req field of pairing request, which in turn necessitates protection against Man-In-The-Middle attacks during the pairing process. The flag can be configured through sdkconfig or menuconfig as mentioned above. + +### SECURE CONNECTION FEUTURE +```c +#ifdef CONFIG_EXAMPLE_USE_SC + ble_hs_cfg.sm_sc = 1; +#else + ble_hs_cfg.sm_sc = 0; +#endif +``` +When the `CONFIG_EXAMPLE_USE_SC` flag is set in the Pairing Request/Response, it enables the usage of LE Secure Connections for pairing, provided that the remote device also supports it. If the remote device does not support LE Secure Connections, the pairing process falls back to using legacy pairing. + +So, the main function configures security features in a BLE application like Bonding, MITM protection, Secure connections, and Key distribution. + +### GATT SERVER INIT +```c +rc = gatt_svr_init(); +assert(rc == 0); +``` +The gatt_svr_init function is called during the initialization phase of a BLE application to set up the GATT server and define the services and characteristics it supports. + +### SETTING DEVICE NAME +The main function calls `ble_svc_gap_device_name_set()` to set the default device name. 'nimble-ble-spp-svr' is passed as the default device name to this function. +```c +rc = ble_svc_gap_device_name_set("nimble-ble-spp-svr"); +``` + +### BLE STORE CONFIGURATION +The main function calls `ble_store_config_init()` to configure the host by setting up the storage callbacks which handle the read, write, and deletion of security material. +```c +/* XXX Need to have a template for store */ +ble_store_config_init(); +``` + +### THREAD MODEL +The main function creates a task where nimble will run using `nimble_port_freertos_init()`. This enables the nimble stack by using `esp_nimble_enable()`. +```c +nimble_port_freertos_init(ble_spp_server_host_task); +``` + +`esp_nimble_enable()` create a task where the nimble host will run. Nimble stack runs in a separate thread with its own context to handle async operations from controller and post HCI commands to controller. + + +## ble_server_uart_task + +```c +void ble_server_uart_task(void *pvParameters) +{ + MODLOG_DFLT(INFO, "BLE server UART_task started\n"); + uart_event_t event; + int rc = 0; + for (;;) { + //Waiting for UART event. + if (xQueueReceive(spp_common_uart_queue, (void * )&event, (TickType_t)portMAX_DELAY)) { + switch (event.type) { + //Event of UART receving data + case UART_DATA: + if (event.size) { + uint8_t *ntf; + ntf = (uint8_t *)malloc(sizeof(uint8_t) * event.size); + memset(ntf, 0x00, event.size); + uart_read_bytes(UART_NUM_0, ntf, event.size, portMAX_DELAY); + + for (int i = 0; i <= CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + /* Check if client has subscribed to notifications */ + if (conn_handle_subs[i]) { + struct os_mbuf *txom; + txom = ble_hs_mbuf_from_flat(ntf, sizeof(ntf)); + rc = ble_gatts_notify_custom(i, ble_spp_svc_gatt_read_val_handle, + txom); + if (rc == 0) { + MODLOG_DFLT(INFO, "Notification sent successfully"); + } else { + MODLOG_DFLT(INFO, "Error in sending notification rc = %d", rc); + } + } + } + } + break; + default: + break; + } + } + } + vTaskDelete(NULL); +} +``` + +The function `ble_server_uart_task` serves as a BLE server with UART communication capabilities. Here's a summary of what this code does: + +1. The task starts and logs a message to indicate that the BLE server UART task has begun. It enters an infinite loop (`for (;;)`) to continuously process UART events. + +2. Inside the loop, it waits for a UART event to occur using the `xQueueReceive` function. When a UART event is received, it checks the type of event. + +3. If the event type is `UART_DATA`, it reads the data from the UART and stores it in a dynamically allocated buffer (`ntf`). The buffer is then used to send notifications to connected BLE clients. + +4. It iterates through a loop for each possible BLE connection (up to `CONFIG_BT_NIMBLE_MAX_CONNECTIONS` connections). + +5. For each connection, it checks if a client has subscribed to notifications (`conn_handle_subs[i]`). + +6. If a client has subscribed, it prepares a BLE notification message (`txom`) containing the UART data and sends it to the client using the `ble_gatts_notify_custom` function. + +7. It logs whether the notification was sent successfully or if there was an error. The loop continues processing UART events, and the task repeats. + +8. Finally, the task is deleted using `vTaskDelete(NULL)` when it is no longer needed. + + +## ble_spp_server_advertise + +```c +static void +ble_spp_server_advertise(void) +{ + struct ble_gap_adv_params adv_params; + struct ble_hs_adv_fields fields; + const char *name; + int rc; + + /** + * Set the advertisement data included in our advertisements: + * o Flags (indicates advertisement type and other general info). + * o Advertising tx power. + * o Device name. + * o 16-bit service UUIDs (alert notifications). + */ + + memset(&fields, 0, sizeof fields); + + /* Advertise two flags: + * o Discoverability in forthcoming advertisement (general) + * o BLE-only (BR/EDR unsupported). + */ + fields.flags = BLE_HS_ADV_F_DISC_GEN | + BLE_HS_ADV_F_BREDR_UNSUP; + + /* Indicate that the TX power level field should be included; have the + * stack fill this value automatically. This is done by assigning the + * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. + */ + fields.tx_pwr_lvl_is_present = 1; + fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + + name = ble_svc_gap_device_name(); + fields.name = (uint8_t *)name; + fields.name_len = strlen(name); + fields.name_is_complete = 1; + + fields.uuids16 = (ble_uuid16_t[]) { + BLE_UUID16_INIT(BLE_SVC_SPP_UUID16) + }; + fields.num_uuids16 = 1; + fields.uuids16_is_complete = 1; + + rc = ble_gap_adv_set_fields(&fields); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc); + return; + } + + /* Begin advertising. */ + memset(&adv_params, 0, sizeof adv_params); + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; + rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, + &adv_params, ble_spp_server_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc); + return; + } +} +``` + +The function `ble_spp_server_advertise` is responsible for enabling advertising in a BLE server application. Here's a summary of what the code does: + +1. It configures the advertisement data to include the following information: +- Flags indicating general discoverability and BLE-only mode. +- Advertising transmission power level. +- Device name. +- A 16-bit service UUID (alert notifications). + +2. The code sets up the advertisement data using the `fields` structure and specifies that the TX power level should be automatically filled by the stack. + +3. It retrieves the device name using `ble_svc_gap_device_name()` and includes it in the advertisement data. + +4. It includes a 16-bit service UUID related to alert notifications in the advertisement data. + +5. The code then attempts to set the advertisement data using `ble_gap_adv_set_fields()` and starts advertising in general discoverable and undirected connectable modes using `ble_gap_adv_start()`. + +In summary, this code sets up and initiates BLE advertising for a server application, making the device discoverable to other BLE devices and allowing them to establish connections. + + +## GAP Event in spp_server + +Various events are handled in the `ble_spp_server_gap_event()`. Their list is as follows: + +1. `BLE_GAP_EVENT_CONNECT`: This case handles when a new connection is established or a connection attempt fails. It prints connection status, and details about the connection, and, in case of failure, resume advertising. If the Connection was established then the connection descriptor is initiated using the method `ble_gap_conn_find()`. + +2. `BLE_GAP_EVENT_DISCONNECT`: This case handles a disconnection event. It prints disconnection details and resumes advertising. + +3. `BLE_GAP_EVENT_CONN_UPDATE`: This case handles a connection parameter update event. It prints the updated connection parameters. + +4. `BLE_GAP_EVENT_ADV_COMPLETE`: This case handles the completion of advertising. It resumes advertising when advertising completes. + +5. `BLE_GAP_EVENT_MTU`: This case is activated when the Maximum Transmission Unit (MTU) is updated for a connection. It prints the new MTU value and related information. + +6. `BLE_GAP_EVENT_SUBSCRIBE`: This case handles a subscription event. It prints details about subscription changes. + + +## ble_svc_gatt_handler + +```c +static int ble_svc_gatt_handler(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + MODLOG_DFLT(INFO, "Callback for read"); + break; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + MODLOG_DFLT(INFO, "Data received in write event,conn_handle = %x,attr_handle = %x", conn_handle, attr_handle); + break; + + default: + MODLOG_DFLT(INFO, "\nDefault Callback"); + break; + } + return 0; +} +``` + +This callback function `ble_svc_gatt_handler` is responsible for handling read and write operations on characteristics within the custom service. Here is a summary of what the code does: + +1. The function is defined with the following parameters: +- `uint16_t conn_handle`: The connection handle for the BLE connection. +- `uint16_t attr_handle`: The attribute handle associated with the operation. +- `struct ble_gatt_access_ctxt *ctxt`: A context structure containing information about the GATT (Generic Attribute Profile) access operation. +- `void *arg`: A generic argument pointer (not used in this code). + +2. Inside the function, there is a `switch` statement that checks the type of GATT access operation being performed, which can be either a read or a write operation. + +3. If the operation is a read operation (`BLE_GATT_ACCESS_OP_READ_CHR`), the code logs a message with "Callback for read." + +4. If the operation is a write operation (`BLE_GATT_ACCESS_OP_WRITE_CHR`), the code logs a message with information about the received data, including the connection handle and attribute handle. + +5. If the operation is neither read nor write (i.e., the default case), it logs a message with "Default Callback." + + +## Custom service + +```c +/* Define new custom service */ +static const struct ble_gatt_svc_def new_ble_svc_gatt_defs[] = { + { + /*** Service: SPP */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BLE_SVC_SPP_UUID16), + .characteristics = (struct ble_gatt_chr_def[]) + { { + /* Support SPP service */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_SPP_CHR_UUID16), + .access_cb = ble_svc_gatt_handler, + .val_handle = &ble_spp_svc_gatt_read_val_handle, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY, + }, { + 0, /* No more characteristics */ + } + }, + }, + { + 0, /* No more services. */ + }, +}; +``` + +The provided code defines a custom service for BLE communication. Here is a summary of what this code does: + +1. It defines a custom BLE service using the `ble_gatt_svc_def` structure. + +2. This service is marked as a primary service using `BLE_GATT_SVC_TYPE_PRIMARY`. The UUID (Universally Unique Identifier) for the service is specified as `BLE_SVC_SPP_UUID16`. + +3. Inside the service, there is a list of characteristics defined using the `ble_gatt_chr_def` structure. In this case, there's only one characteristic defined. The characteristic supports various operations, including reading, writing, and notifications. The UUID for the characteristic is specified as `BLE_SVC_SPP_CHR_UUID16`. + +4. A callback function named `ble_svc_gatt_handler` is assigned to handle access to this characteristic. + +5. The characteristic is set to support reading (`BLE_GATT_CHR_F_READ`), writing (`BLE_GATT_CHR_F_WRITE`), and notifications (`BLE_GATT_CHR_F_NOTIFY`). + +6. The `val_handle` field is used to store the handle for reading the characteristic's value. + +In summary, this code defines a custom BLE service with one characteristic, and it specifies that this characteristic can be read, written to, and used for notifications. The UUIDs and callback functions for the service and characteristic are also specified. + + +## gatt_svr_register_cb + +```c +static void +gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) +{ + char buf[BLE_UUID_STR_LEN]; + + switch (ctxt->op) { + case BLE_GATT_REGISTER_OP_SVC: + MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n", + ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), + ctxt->svc.handle); + break; + + case BLE_GATT_REGISTER_OP_CHR: + MODLOG_DFLT(DEBUG, "registering characteristic %s with " + "def_handle=%d val_handle=%d\n", + ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), + ctxt->chr.def_handle, + ctxt->chr.val_handle); + break; + + case BLE_GATT_REGISTER_OP_DSC: + MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n", + ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), + ctxt->dsc.handle); + break; + + default: + assert(0); + break; + } +} +``` + +This function is invoked when various GATT (Generic Attribute Profile) elements, such as services, characteristics, or descriptors, are registered. + +1. The function takes two parameters: `struct ble_gatt_register_ctxt *ctxt`, which represents context information about the registration operation, and `void *arg`, which is not used in this code snippet. + +2. Inside the function, a switch statement is used to handle different GATT registration operations (`ctxt->op`). The possible operations include registering a service (`BLE_GATT_REGISTER_OP_SVC`), registering a characteristic (`BLE_GATT_REGISTER_OP_CHR`), and registering a descriptor (`BLE_GATT_REGISTER_OP_DSC`). + +3. For each case, the code uses the `MODLOG_DFLT` macro to log debug information. The information logged includes the type of element being registered (service, characteristic, or descriptor) and its UUID in string format. Additionally, it logs specific details like handles associated with these elements. + + +## Conclusion + +Overall, this code establishes a BLE SPP server, handles BLE events, advertises services, manages a custom Serial Port Profile (SPP) service, and enables UART data communication with connected BLE clients. It allows data to be exchanged between the ESP32 device and connected BLE clients via UART communication. From 464d278f8a93ae0660df7a532bc8a647d2fa6d63 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 20 Jul 2023 17:48:38 +0200 Subject: [PATCH 035/142] fix(esp_hw_support): fix build with CONFIG_ESP_CONSOLE_UART=n on C6 Closes https://github.com/espressif/esp-idf/issues/11924 --- components/esp_hw_support/sleep_modes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 6a7a12bb1348..2d066877b74c 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -488,12 +488,12 @@ FORCE_INLINE_ATTR void resume_uarts(void) FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t pd_flags, int64_t sleep_duration) { bool should_skip_sleep = false; -#if !SOC_PM_SUPPORT_TOP_PD +#if !SOC_PM_SUPPORT_TOP_PD || !CONFIG_ESP_CONSOLE_UART suspend_uarts(); #else if (pd_flags & PMU_SLEEP_PD_TOP) { if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && - // +1 is for cover the last charactor flush time + // +1 is for cover the last character flush time (sleep_duration < (int64_t)((UART_LL_FIFO_DEF_LEN - uart_ll_get_txfifo_len(CONSOLE_UART_DEV) + 1) * UART_FLUSH_US_PER_CHAR) + SLEEP_UART_FLUSH_DONE_TO_SLEEP_US)) { should_skip_sleep = true; } else { From 2fe4fe2c19b3604ef551d8c512179eeaa78facd7 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 20 Jul 2023 17:58:02 +0200 Subject: [PATCH 036/142] ci(system): re-enable build test app for C2 and C6, clean up configs Since we can use CONFIG_NAME now to specify build rules, we don't need to have target-specific config files. --- tools/test_apps/.build-test-rules.yml | 6 ++++++ tools/test_apps/system/build_test/README.md | 2 -- .../sdkconfig.ci.esp32c2_without_rom_impl_components | 5 ----- .../sdkconfig.ci.esp32c6_with_rom_impl_components | 5 ----- .../sdkconfig.ci.esp32c6_without_rom_impl_components | 5 ----- .../system/build_test/sdkconfig.ci.esp32c6_without_rvfplib | 2 -- .../sdkconfig.ci.esp32h2_with_rom_impl_components | 5 ----- ..._impl_components => sdkconfig.ci.no_rom_impl_components} | 3 ++- ...g.ci.esp32c2_without_rvfplib => sdkconfig.ci.no_rvfplib} | 0 ...rom_impl_components => sdkconfig.ci.rom_impl_components} | 3 ++- .../system/build_test/sdkconfig.ci.usb_console_ets_printf | 1 - .../system/build_test/sdkconfig.ci.usb_serial_jtag | 1 - 12 files changed, 10 insertions(+), 28 deletions(-) delete mode 100644 tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_without_rom_impl_components delete mode 100644 tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_with_rom_impl_components delete mode 100644 tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rom_impl_components delete mode 100644 tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rvfplib delete mode 100644 tools/test_apps/system/build_test/sdkconfig.ci.esp32h2_with_rom_impl_components rename tools/test_apps/system/build_test/{sdkconfig.ci.esp32h2_without_rom_impl_components => sdkconfig.ci.no_rom_impl_components} (60%) rename tools/test_apps/system/build_test/{sdkconfig.ci.esp32c2_without_rvfplib => sdkconfig.ci.no_rvfplib} (100%) rename tools/test_apps/system/build_test/{sdkconfig.ci.esp32c2_with_rom_impl_components => sdkconfig.ci.rom_impl_components} (60%) diff --git a/tools/test_apps/.build-test-rules.yml b/tools/test_apps/.build-test-rules.yml index 39cadd6f2a2e..91c70d60a66a 100644 --- a/tools/test_apps/.build-test-rules.yml +++ b/tools/test_apps/.build-test-rules.yml @@ -76,6 +76,12 @@ tools/test_apps/system/bootloader_sections: tools/test_apps/system/build_test: disable: + # For ROM impl build tests, disable them if none of the tested features are supported in the ROM + - if: CONFIG_NAME == "rom_impl_components" and ((ESP_ROM_HAS_HAL_WDT != 1 and ESP_ROM_HAS_HAL_SYSTIMER != 1) and (ESP_ROM_HAS_HEAP_TLSF != 1 and ESP_ROM_HAS_SPI_FLASH != 1)) + - if: CONFIG_NAME == "no_rom_impl_components" and ((ESP_ROM_HAS_HAL_WDT != 1 and ESP_ROM_HAS_HAL_SYSTIMER != 1) and (ESP_ROM_HAS_HEAP_TLSF != 1 and ESP_ROM_HAS_SPI_FLASH != 1)) + - if: CONFIG_NAME == "no_rvfplib" and ESP_ROM_HAS_RVFPLIB != 1 + - if: CONFIG_NAME == "usb_serial_jtag" AND SOC_USB_SERIAL_JTAG_SUPPORTED != 1 + - if: CONFIG_NAME == "usb_console_ets_printf" AND SOC_USB_OTG_SUPPORTED != 1 - if: IDF_TARGET in ["esp32p4"] temporary: true reason: target(s) not supported yet #TODO: IDF-8119 diff --git a/tools/test_apps/system/build_test/README.md b/tools/test_apps/system/build_test/README.md index 3c495f94c0d0..ff948772002a 100644 --- a/tools/test_apps/system/build_test/README.md +++ b/tools/test_apps/system/build_test/README.md @@ -1,8 +1,6 @@ | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -Efuse on ESP32-C2 not supported - This project is for testing if the application can be built with a particular sdkconfig setting. To add new configuration, create one more sdkconfig.ci.NAME file in this directory. diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_without_rom_impl_components b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_without_rom_impl_components deleted file mode 100644 index e777b3938273..000000000000 --- a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_without_rom_impl_components +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_IDF_TARGET="esp32c2" -CONFIG_HAL_WDT_USE_ROM_IMPL=n -CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=n -CONFIG_HEAP_TLSF_USE_ROM_IMPL=n -CONFIG_SPI_FLASH_ROM_IMPL=n diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_with_rom_impl_components b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_with_rom_impl_components deleted file mode 100644 index cb561f4977d5..000000000000 --- a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_with_rom_impl_components +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_IDF_TARGET="esp32c6" -CONFIG_HAL_WDT_USE_ROM_IMPL=y -CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=y -CONFIG_HEAP_TLSF_USE_ROM_IMPL=y -CONFIG_SPI_FLASH_ROM_IMPL=y diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rom_impl_components b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rom_impl_components deleted file mode 100644 index ee55ffa7447f..000000000000 --- a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rom_impl_components +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_IDF_TARGET="esp32c6" -CONFIG_HAL_WDT_USE_ROM_IMPL=n -CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=n -CONFIG_HEAP_TLSF_USE_ROM_IMPL=n -CONFIG_SPI_FLASH_ROM_IMPL=n diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rvfplib b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rvfplib deleted file mode 100644 index e82ca0e1f0d7..000000000000 --- a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c6_without_rvfplib +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_IDF_TARGET="esp32c6" -CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32h2_with_rom_impl_components b/tools/test_apps/system/build_test/sdkconfig.ci.esp32h2_with_rom_impl_components deleted file mode 100644 index 7456ed4f6545..000000000000 --- a/tools/test_apps/system/build_test/sdkconfig.ci.esp32h2_with_rom_impl_components +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_IDF_TARGET="esp32h2" -CONFIG_HAL_WDT_USE_ROM_IMPL=y -CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=y -CONFIG_HEAP_TLSF_USE_ROM_IMPL=y -CONFIG_SPI_FLASH_ROM_IMPL=y diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32h2_without_rom_impl_components b/tools/test_apps/system/build_test/sdkconfig.ci.no_rom_impl_components similarity index 60% rename from tools/test_apps/system/build_test/sdkconfig.ci.esp32h2_without_rom_impl_components rename to tools/test_apps/system/build_test/sdkconfig.ci.no_rom_impl_components index 843ca0e1a1ef..91e0216ac40f 100644 --- a/tools/test_apps/system/build_test/sdkconfig.ci.esp32h2_without_rom_impl_components +++ b/tools/test_apps/system/build_test/sdkconfig.ci.no_rom_impl_components @@ -1,5 +1,6 @@ -CONFIG_IDF_TARGET="esp32h2" CONFIG_HAL_WDT_USE_ROM_IMPL=n CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=n CONFIG_HEAP_TLSF_USE_ROM_IMPL=n CONFIG_SPI_FLASH_ROM_IMPL=n + +# update tools/test_apps/.build-test-rules.yml if adding more ROM options above! diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_without_rvfplib b/tools/test_apps/system/build_test/sdkconfig.ci.no_rvfplib similarity index 100% rename from tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_without_rvfplib rename to tools/test_apps/system/build_test/sdkconfig.ci.no_rvfplib diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_with_rom_impl_components b/tools/test_apps/system/build_test/sdkconfig.ci.rom_impl_components similarity index 60% rename from tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_with_rom_impl_components rename to tools/test_apps/system/build_test/sdkconfig.ci.rom_impl_components index 68e9623a04a5..3b8ce276179b 100644 --- a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c2_with_rom_impl_components +++ b/tools/test_apps/system/build_test/sdkconfig.ci.rom_impl_components @@ -1,5 +1,6 @@ -CONFIG_IDF_TARGET="esp32c2" CONFIG_HAL_WDT_USE_ROM_IMPL=y CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=y CONFIG_HEAP_TLSF_USE_ROM_IMPL=y CONFIG_SPI_FLASH_ROM_IMPL=y + +# update tools/test_apps/.build-test-rules.yml if adding more ROM options above! diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.usb_console_ets_printf b/tools/test_apps/system/build_test/sdkconfig.ci.usb_console_ets_printf index 52aabffb986e..fac982eb0ef6 100644 --- a/tools/test_apps/system/build_test/sdkconfig.ci.usb_console_ets_printf +++ b/tools/test_apps/system/build_test/sdkconfig.ci.usb_console_ets_printf @@ -1,3 +1,2 @@ -CONFIG_IDF_TARGET="esp32s3" CONFIG_ESP_CONSOLE_USB_CDC=y CONFIG_ESP_CONSOLE_USB_CDC_SUPPORT_ETS_PRINTF=y diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.usb_serial_jtag b/tools/test_apps/system/build_test/sdkconfig.ci.usb_serial_jtag index 81161641fa7d..5e9f8e25bd87 100644 --- a/tools/test_apps/system/build_test/sdkconfig.ci.usb_serial_jtag +++ b/tools/test_apps/system/build_test/sdkconfig.ci.usb_serial_jtag @@ -1,2 +1 @@ -CONFIG_IDF_TARGET="esp32c3" CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y From cbd4fc1b35031118a5d80ddb33050d310ca91f8c Mon Sep 17 00:00:00 2001 From: Abhinav Kudnar Date: Mon, 18 Sep 2023 16:38:01 +0530 Subject: [PATCH 037/142] doc (nimble): Added the tutorial for coc_blecent example. --- .../tutorial/coc_blecent_walkthrough.md | 304 ++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/tutorial/coc_blecent_walkthrough.md diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/tutorial/coc_blecent_walkthrough.md b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/tutorial/coc_blecent_walkthrough.md new file mode 100644 index 000000000000..349171cd1a16 --- /dev/null +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/tutorial/coc_blecent_walkthrough.md @@ -0,0 +1,304 @@ +# COC BLECENT Example Walkthrough + +## Introduction + +This example is designed to demonstrate the process of BLE service discovery, connection establishment, and data transfer using the L2CAP layer's connection-oriented channels. It begins by conducting a passive scan to identify nearby peripheral devices. If a device is found that both advertises its connectability and supports connection-oriented channels, the example proceeds to establish a connection with that device. + +## Includes + +This example is located in the examples folder of the ESP-IDF under the [COC_BLECENT/main](../main). The [main.c](../main/main.c) file located in the main folder contains all the functionality that we are going to review. The header files contained in [main.c](../main/main.c) are: + +```c +#include "esp_log.h" +#include "nvs_flash.h" +/* BLE */ +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "console/console.h" +#include "services/gap/ble_svc_gap.h" +#include "coc_blecent.h" +``` +These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `“nimble_port.h”`, `“nimble_port_freertos.h”`, `"ble_hs.h"`, `“ble_svc_gap.h”` and `“coc_blecent.h”` which expose the BLE APIs required to implement this example. + +* `nimble_port.h`: Includes the declaration of functions required for the initialization of the nimble stack. +* `nimble_port_freertos.h`: Initializes and enables nimble host task. +* `ble_hs.h`: Defines the functionalities to handle the host event. +* `ble_svc_gap.h`: Defines the macros for device name, and device appearance and declares the function to set them. +* `coc_blecent.h`: Provides necessary definitions and forward declarations for the coc_blecent example's functionality. + +## Main Entry Point + +The program's entry point is the app_main() function: +```c +void +app_main(void) +{ + int rc; + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ret = nimble_port_init(); + assert(ret == 0); + + /* Configure the host. */ + ble_hs_cfg.reset_cb = blecent_on_reset; + ble_hs_cfg.sync_cb = blecent_on_sync; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1 + blecent_l2cap_coc_mem_init(); + xTaskCreate(ble_coc_cent_task, "ble_coc_cent_task", 4096, NULL, 10, NULL); +#endif + + /* Initialize data structures to track connected peers. */ + rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); + assert(rc == 0); + + /* Set the default device name. */ + rc = ble_svc_gap_device_name_set("blecent-l2coc"); + assert(rc == 0); + + /* XXX Need to have template for store */ + ble_store_config_init(); + + nimble_port_freertos_init(blecent_host_task); +} +``` +The main function starts by initializing the non-volatile storage library. This library allows us to save the key-value pairs in flash memory. `nvs_flash_init()` stores the PHY calibration data. In a Bluetooth Low Energy (BLE) device, cryptographic keys used for encryption and authentication are often stored in Non-Volatile Storage (NVS). BLE stores the peer keys, CCCD keys, peer records, etc on NVS. By storing these keys in NVS, the BLE device can quickly retrieve them when needed, without the need for time-consuming key generations. +```c +esp_err_t ret = nvs_flash_init(); +``` + +## BT Controller and Stack Initialization +The main function calls `nimble_port_init()` to initialize the BT Controller and nimble stack. This function initializes the BT controller by first creating its configuration structure named `esp_bt_controller_config_t` with default settings generated by the `BT_CONTROLLER_INIT_CONFIG_DEFAULT()` macro. It implements the Host Controller Interface (HCI) on the controller side, the Link Layer (LL), and the Physical Layer (PHY). The BT Controller is invisible to the user applications and deals with the lower layers of the BLE stack. The controller configuration includes setting the BT controller stack size, priority, and HCI baud rate. With the settings created, the BT controller is initialized and enabled with the `esp_bt_controller_init()` and `esp_bt_controller_enable()` functions: + +```c +esp_bt_controller_config_t config_opts = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); +ret = esp_bt_controller_init(&config_opts); +``` +Next, the controller is enabled in BLE Mode. + +```c +ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); +``` +The controller should be enabled in `ESP_BT_MODE_BLE` if you want to use the BLE mode. + +There are four Bluetooth modes supported: + +1. `ESP_BT_MODE_IDLE`: Bluetooth not running +2. `ESP_BT_MODE_BLE`: BLE mode +3. `ESP_BT_MODE_CLASSIC_BT`: BT Classic mode +4. `ESP_BT_MODE_BTDM`: Dual mode (BLE + BT Classic) + +After the initialization of the BT controller, the nimble stack, which includes the common definitions and APIs for BLE, is initialized by using `esp_nimble_init()`: + +```c +esp_err_t esp_nimble_init(void) +{ +#if !SOC_ESP_NIMBLE_CONTROLLER + /* Initialize the function pointers for OS porting */ + npl_freertos_funcs_init(); + + npl_freertos_mempool_init(); + + if(esp_nimble_hci_init() != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci inits failed\n"); + return ESP_FAIL; + } + + /* Initialize default event queue */ + ble_npl_eventq_init(&g_eventq_dflt); + /* Initialize the global memory pool */ + os_mempool_module_init(); + os_msys_init(); + +#endif + /* Initialize the host */ + ble_transport_hs_init(); + + return ESP_OK; +} +``` +The host is configured by setting up the callbacks for Stack-reset, Stack-sync, and Storage status. +```c +ble_hs_cfg.reset_cb = blecent_on_reset; +ble_hs_cfg.sync_cb = blecent_on_sync; +ble_hs_cfg.store_status_cb = ble_store_util_status_rr; +``` +## Task creation for l2cap_coc data sending. +```c +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1 + blecent_l2cap_coc_mem_init(); + xTaskCreate(ble_coc_cent_task, "ble_coc_cent_task", 4096, NULL, 10, NULL); +#endif +``` +`BLE_L2CAP_COC_MAX_NUM` defines a maximum number of BLE Connection-Oriented Channels. When set to (0), BLE COC is not compiled in. +If the example supports l2cap_coc then allocate mempool and mbuf_pools for allocating the data packets.Then`xTaskCreate` Creates a new task and adds it to the list of tasks that are ready to run with `ble_coc_cent_task` as a pointer to the task entry function, `ble_coc_cent_task` as the name of the task, `4096` as a task stack size in bytes. + +The main function invokes `peer_init()` to initialize memory pools to manage peer, service, characteristics, and descriptor objects in BLE. +```c +rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); +``` + +## Setting device name +The main function calls `ble_svc_gap_device_name_set()` to set the default device name.'blecent-l2coc' is passed as the default device name to this function. +```c +rc = ble_svc_gap_device_name_set("blecent-l2coc"); +``` + +## Ble store configuration +The main function calls `ble_store_config_init()` to configure the host by setting up the storage callbacks which handle the read, write, and deletion of security material. +```c +/* XXX Need to have a template for store */ + ble_store_config_init(); +``` +## Thread model +The main function ends by creating a task where nimble will run using `nimble_port_freertos_init()`. This enables the nimble stack by using `esp_nimble_enable()`. +```c +nimble_port_freertos_init(blecent_host_task); +``` +`esp_nimble_enable()` creates a task where the nimble host will run. The nimble stack runs in a separate thread with its own context to handle async operations from the controller and post HCI commands to the controller. + +## L2CAP_COC_CENT host task +```c +void ble_coc_cent_task(void *pvParameters) +{ + while (1) { + if (coc_chan) { + for (int i = 0; i < 5; i++) { + blecent_l2cap_coc_send_data(coc_chan); + vTaskDelay(500 / portTICK_PERIOD_MS); + } + coc_chan = NULL; + } + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} +``` +This task runs indefinitely and is responsible for periodically sending data over a Connection-Oriented Channel (COC) established using L2CAP.This task continuously checks for the presence of an L2CAP COC represented by the coc_chan variable. If such a channel exists, it sends data over the channel multiple times with a 500-millisecond delay between each transmission. After sending the data, it resets the coc_chan to NULL to indicate that the channel is available for a new connection. This loop then repeats, with a 1-second pause between iterations, effectively allowing the task to periodically attempt data transmissions over an L2CAP COC when available. + +## L2CAP_COC memory initialization (mempool and mbuf_pool) +The purpose of the above function is to initialize memory pools and buffer pools used for managing memory buffers for be_l2cap_coc.It inlvoes 2 impoertant allocations i.e mempool_init and mbuf_pool_init +- Memory Pool Initialization: +`os_mempool_init`: This function initializes a memory pool named `sdu_coc_mbuf_mempool`. A memory pool is a reserved area of memory that can be used for dynamic memory allocation. + +- Memory Buffer Pool Initialization: +`os_mbuf_pool_init`: This function initializes a mbuf (memory buffer) pool named `sdu_os_mbuf_pool`. A mbuf is a data structure typically used to manage data buffers efficiently. + +## L2CAP_COC event callback +This callback function is responsible for handling L2CAP events related to COCs in a BLE application. It logs information about successful COC connections and disconnections, including relevant details such as channel information and status. Additionally, it sets a global variable (coc_chan) to the connected channel pointer, which can be useful for further interaction with the COC in the application. + +- a. `BLE_L2CAP_EVENT_COC_CONNECTED`: This case is executed when a COC (Connection-Oriented Channel) is successfully connected. + - It checks event->connect. status to see if the connection was established successfully. If there's an error (status is nonzero), it prints an error message and returns 0 (indicating a failure). + - It obtains information about the connected COC using ble_l2cap_get_chan_info and stores it in the chan_info structure. + - It prints information about the connected COC, including connection handle, channel pointer, PSM (Protocol/Service Multiplexer), source and destination channel IDs, Maximum Packet Size (MPS), and Maximum Transmission Unit (MTU). + - It stores the channel pointer in the global variable coc_chan for future reference. +- b. `BLE_L2CAP_EVENT_COC_DISCONNECTED`: This case is executed when a COC is disconnected. + - It prints a message indicating that the COC has been disconnected. +- c. `Default Case`: If the event type doesn't match the two handled cases, the function returns 0, indicating that it has successfully handled the event. The default case is used to ignore unhandled event types. + +## L2CAP connect after completion of the discovery procedure +```c +static void +blecent_l2cap_coc_on_disc_complete(const struct peer *peer, int status, void *arg) +{ + uint16_t psm = 0x1002; + struct os_mbuf *sdu_rx; + + sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); + ble_l2cap_connect(conn_handle_coc, psm, MTU, sdu_rx, blecent_l2cap_coc_event_cb, + NULL); +} +``` +This function is called when the service discovery process is completed, and its purpose is to initiate a connection at the L2CAP. It specifies the PSM, MTU, and other parameters required for the connection, and it sets up a callback function (blecent_l2cap_coc_event_cb) to handle L2CAP events related to this connection. + +## Send data on l2cap channel. +A function named `blecent_l2cap_coc_send_data` is involved in sending data over a BLE (Bluetooth Low Energy) connection using L2CAP (Logical Link Control and Adaptation Protocol) Connection-Oriented Channels (COC). Below is it explanation. + +1. **Function Signature**: The function takes a single argument, `struct ble_l2cap_chan *chan`, which represents the L2CAP channel over which data will be sent. +```c +static void blecent_l2cap_coc_send_data(struct ble_l2cap_chan *chan) +``` + +2. **Variable Declarations**: + - `struct os_mbuf *sdu_rx_data;`: Declares a pointer to an OS mbuf, which is a data structure typically used for managing memory buffers. + - `int rc = 0;`: Initializes an integer variable `rc` to 0, which will be used to store the return code of various operations. + - `int len = 512;`: Sets the variable `len` to 512, which represents the length of the data buffer to be sent. + - `uint8_t value[len];`: Declares an array `value` of type `uint8_t` with a length of `len` (512 in this case). + ```c + struct os_mbuf *sdu_rx_data; + int rc = 0; + int len = 512; + uint8_t value[len]; + ``` + +3. **Data Preparation**: + - A loop initializes the `value` array with values from 0 to 511. This loop fills the `value` array with consecutive numbers starting from 0. + ```c + for (int i = 0; i < len; i++) { + value[i] = i; + } + ``` + +4. **Memory Allocation and Data Copying**: + - A `do-while` loop is used to allocate an OS mbuf from a pool named `sdu_os_mbuf_pool`. If the allocation fails (sdu_rx_data is `NULL`), the code waits for 10 milliseconds (`vTaskDelay`) and tries again. + - Once a valid mbuf (`sdu_rx_data`) is obtained, the data from the `value` array is appended to this mbuf using `os_mbuf_append`. + ```c + do { + sdu_rx_data = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); + if (sdu_rx_data == NULL) { + vTaskDelay(10 / portTICK_PERIOD_MS); + sdu_rx_data = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); + } + } while (sdu_rx_data == NULL); + + os_mbuf_append(sdu_rx_data, value, len); + ``` + +5. **Printing Mbuf Data**: The function `print_mbuf_data` is called to print the data contained in the `sdu_rx_data` mbuf. This is likely a debugging or logging step to verify the content. + + +6. **Data Transmission**: + - The code attempts to send the data using the `ble_l2cap_send` function, passing the `chan` (L2CAP channel) and the mbuf (`sdu_rx_data`) as arguments. + - If the initial send operation returns `BLE_HS_ESTALLED`, indicating that the channel is stalled or busy, the code enters a loop where it waits for 100 milliseconds (`vTaskDelay`) and retries the send operation until it succeeds or encounters an error other than `BLE_HS_ESTALLED`. + +7. **Result Reporting**: + - After exiting the loop, the code checks the value of `rc`: + - If `rc` is 0, it logs a message indicating that the data was sent successfully. + - If `rc` is not 0, it logs a message indicating that data sending failed and includes the value of `rc` for further debugging. + +8. **Memory Cleanup**: Finally, the allocated mbuf (`sdu_rx_data`) is freed using `os_mbuf_free` to release the memory. + +This code is essentially preparing data in the `value` array, encapsulating it in an OS mbuf, attempting to send it over an L2CAP channel, handling stalls, and reporting the success or failure of the operation. It is part of a BLE application running on an embedded system. + +## BLECENT_GAP_EVENT ( setting discovery callback as `blecent_l2cap_coc_on_disc_complete` ) +Below is an explanation of `GAP_CONNECT_EVENT` where the application sets the discovery call back as `blecent_l2cap_coc_on_disc_complete` if the maximum number of BLE Connection-Oriented Channels is greater than 0. +```c +case BLE_GAP_EVENT_CONNECT: + /* A new connection was established or a connection attempt failed. */ + if (event->connect.status == 0) { + /* Connection successfully established. */ + MODLOG_DFLT(INFO, "Connection established "); + + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + print_conn_desc(&desc); + MODLOG_DFLT(INFO, "\n"); + +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1 + conn_handle_coc = event->connect.conn_handle; + disc_cb = blecent_l2cap_coc_on_disc_complete; +``` +For More info related to `BLECENT_GAP_EVENT` here is the complete tutorial for [blecent_walkthrough.md](../../../blecent/tutorial/blecent_walkthrough.md) + +## Conclusion +- This example is developed to illustrate the sequence of BLE operations, including service discovery, connection setup, and data exchange via the L2CAP layer's connection-oriented channels. +- It commences by performing a passive scan to detect peripheral devices in the vicinity. +- If a suitable device is detected, one that both advertises its readiness for connection and offers support for connection-oriented channels, the example advances to initiate a connection with that specific device. \ No newline at end of file From 28a45e20b8995fe874a9614f512e5cdc85d0cc66 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 7 Aug 2023 19:31:10 +0800 Subject: [PATCH 038/142] feat(parlio_tx): supported parlio tx on p4 --- components/driver/parlio/parlio_common.c | 12 +- components/driver/parlio/parlio_private.h | 41 + components/driver/parlio/parlio_tx.c | 100 ++- .../driver/test_apps/.build-test-rules.yml | 4 + components/driver/test_apps/parlio/README.md | 4 +- .../driver/test_apps/parlio/main/test_board.h | 10 + .../hal/esp32c6/include/hal/parlio_ll.h | 47 +- .../hal/esp32h2/include/hal/parlio_ll.h | 49 +- .../hal/esp32p4/include/hal/clk_gate_ll.h | 5 - .../hal/esp32p4/include/hal/parlio_ll.h | 790 ++++++++++++++++++ components/hal/parlio_hal.c | 1 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 6 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 20 + .../soc/esp32p4/include/soc/parl_io_struct.h | 1 + components/soc/esp32p4/include/soc/soc_caps.h | 4 +- components/soc/esp32p4/parlio_periph.c | 56 +- examples/peripherals/.build-test-rules.yml | 4 + 17 files changed, 1083 insertions(+), 71 deletions(-) create mode 100644 components/hal/esp32p4/include/hal/parlio_ll.h diff --git a/components/driver/parlio/parlio_common.c b/components/driver/parlio/parlio_common.c index f3450ff79d78..409a3f7f0f6c 100644 --- a/components/driver/parlio/parlio_common.c +++ b/components/driver/parlio/parlio_common.c @@ -18,7 +18,6 @@ #include "soc/parlio_periph.h" #include "hal/parlio_ll.h" #include "esp_private/esp_clk.h" -#include "esp_private/periph_ctrl.h" #include "parlio_private.h" static const char *TAG = "parlio"; @@ -45,9 +44,10 @@ parlio_group_t *parlio_acquire_group_handle(int group_id) s_platform.groups[group_id] = group; group->group_id = group_id; group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; - // enable APB access PARLIO registers - periph_module_enable(parlio_periph_signals.groups[group_id].module); - periph_module_reset(parlio_periph_signals.groups[group_id].module); + PARLIO_RCC_ATOMIC() { + parlio_ll_enable_bus_clock(group_id, true); + parlio_ll_reset_register(group_id); + } // hal layer initialize parlio_hal_init(&group->hal); } @@ -78,7 +78,9 @@ void parlio_release_group_handle(parlio_group_t *group) s_platform.groups[group_id] = NULL; // hal layer deinitialize parlio_hal_deinit(&group->hal); - periph_module_disable(parlio_periph_signals.groups[group_id].module); + PARLIO_RCC_ATOMIC() { + parlio_ll_enable_bus_clock(group_id, false); + } free(group); } _lock_release(&s_platform.mutex); diff --git a/components/driver/parlio/parlio_private.h b/components/driver/parlio/parlio_private.h index 1eabbe81ccc4..b7418b3ff91e 100644 --- a/components/driver/parlio/parlio_private.h +++ b/components/driver/parlio/parlio_private.h @@ -11,8 +11,14 @@ #include "soc/soc_caps.h" #include "hal/parlio_types.h" #include "hal/parlio_hal.h" +#include "hal/parlio_ll.h" +#include "hal/dma_types.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" +#include "rom/cache.h" #include "esp_heap_caps.h" #include "driver/parlio_types.h" +#include "esp_private/periph_ctrl.h" #if CONFIG_PARLIO_ISR_IRAM_SAFE #define PARLIO_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) @@ -32,6 +38,41 @@ #define PARLIO_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | PARLIO_INTR_ALLOC_FLAG_SHARED) #endif +#if SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS == SOC_GDMA_BUS_AXI +/* The parlio peripheral uses DMA via AXI bus, which requires the descriptor aligned with 8 */ +typedef dma_descriptor_align8_t parlio_dma_desc_t; +#else +typedef dma_descriptor_align4_t parlio_dma_desc_t; +#endif + +#ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR +/* The descriptor address can be mapped by a fixed offset */ +#define PARLIO_GET_NON_CACHED_DESC_ADDR(desc) (desc ? (parlio_dma_desc_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(desc)) : NULL) +#else +#define PARLIO_GET_NON_CACHED_DESC_ADDR(desc) (desc) +#endif // CACHE_LL_L2MEM_NON_CACHE_ADDR + +#if SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS == SOC_GDMA_BUS_AXI +#define PARLIO_DMA_DESC_ALIGNMENT 8 +#define PARLIO_DMA_DESC_SIZE 8 +#else +#define PARLIO_DMA_DESC_ALIGNMENT 4 +#define PARLIO_DMA_DESC_SIZE sizeof(parlio_dma_desc_t) +#endif + +#if SOC_PERIPH_CLK_CTRL_SHARED +#define PARLIO_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define PARLIO_CLOCK_SRC_ATOMIC() +#endif + +#if !SOC_RCC_IS_INDEPENDENT +// Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section +#define PARLIO_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define PARLIO_RCC_ATOMIC() +#endif // SOC_RCC_IS_INDEPENDENT + #define PARLIO_PM_LOCK_NAME_LEN_MAX 16 #ifdef __cplusplus diff --git a/components/driver/parlio/parlio_tx.c b/components/driver/parlio/parlio_tx.c index 81d0eba5bbcb..82d5b0b3d0e0 100644 --- a/components/driver/parlio/parlio_tx.c +++ b/components/driver/parlio/parlio_tx.c @@ -29,7 +29,6 @@ #include "soc/parlio_periph.h" #include "hal/parlio_ll.h" #include "hal/gpio_hal.h" -#include "hal/dma_types.h" #include "driver/gpio.h" #include "driver/parlio_tx.h" #include "parlio_private.h" @@ -66,7 +65,7 @@ typedef struct parlio_tx_unit_t { _Atomic parlio_tx_fsm_t fsm; // Driver FSM state parlio_tx_done_callback_t on_trans_done; // callback function when the transmission is done void *user_data; // user data passed to the callback function - dma_descriptor_t *dma_nodes; // DMA descriptor nodes + parlio_dma_desc_t *dma_nodes; // DMA descriptor nodes parlio_tx_trans_desc_t trans_desc_pool[]; // transaction descriptor pool } parlio_tx_unit_t; @@ -258,13 +257,26 @@ static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const par ESP_RETURN_ON_ERROR(ret, TAG, "create NO_LIGHT_SLEEP lock failed"); } #endif - - parlio_ll_tx_set_clock_source(hal->regs, clk_src); - // set clock division, round up - uint32_t div = (periph_src_clk_hz + config->output_clk_freq_hz - 1) / config->output_clk_freq_hz; - parlio_ll_tx_set_clock_div(hal->regs, div); - // precision lost due to division, calculate the real frequency - tx_unit->out_clk_freq_hz = periph_src_clk_hz / div; + hal_utils_clk_div_t clk_div = {}; + hal_utils_clk_info_t clk_info = { + .src_freq_hz = periph_src_clk_hz, + .exp_freq_hz = config->output_clk_freq_hz, + .max_integ = PARLIO_LL_TX_MAX_CLK_INT_DIV, + .min_integ = 1, + .round_opt = HAL_DIV_ROUND, + }; +#if PARLIO_LL_TX_MAX_CLK_FRACT_DIV + clk_info.max_fract = PARLIO_LL_TX_MAX_CLK_FRACT_DIV; + tx_unit->out_clk_freq_hz = hal_utils_calc_clk_div_frac_accurate(&clk_info, &clk_div); +#else + tx_unit->out_clk_freq_hz = hal_utils_calc_clk_div_integer(&clk_info, &clk_div.integer); +#endif + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_tx_set_clock_source(hal->regs, clk_src); + // set clock division + parlio_ll_tx_set_clock_div(hal->regs, &clk_div); + } + // precision lost due to division if (tx_unit->out_clk_freq_hz != config->output_clk_freq_hz) { ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32, tx_unit->out_clk_freq_hz); } @@ -302,8 +314,13 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no memory for tx unit"); size_t dma_nodes_num = config->max_transfer_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; // DMA descriptors must be placed in internal SRAM - unit->dma_nodes = heap_caps_calloc(dma_nodes_num, sizeof(dma_descriptor_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + + unit->dma_nodes = heap_caps_aligned_calloc(PARLIO_DMA_DESC_ALIGNMENT, dma_nodes_num, PARLIO_DMA_DESC_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); ESP_GOTO_ON_FALSE(unit->dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no memory for DMA nodes"); + // Link the descriptors + for (int i = 0; i < dma_nodes_num; i++) { + unit->dma_nodes[i].next = (i == dma_nodes_num - 1) ? NULL : &(unit->dma_nodes[i+1]); + } unit->max_transfer_bits = config->max_transfer_size * 8; unit->data_width = data_width; @@ -328,10 +345,14 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un ESP_GOTO_ON_ERROR(parlio_tx_unit_init_dma(unit), err, TAG, "install tx DMA failed"); // reset fifo and core clock domain - parlio_ll_tx_reset_clock(hal->regs); + PARLIO_RCC_ATOMIC() { + parlio_ll_tx_reset_clock(hal->regs); + } parlio_ll_tx_reset_fifo(hal->regs); - // stop output clock - parlio_ll_tx_enable_clock(hal->regs, false); + PARLIO_CLOCK_SRC_ATOMIC() { + // stop output clock + parlio_ll_tx_enable_clock(hal->regs, false); + } // clock gating parlio_ll_tx_enable_clock_gating(hal->regs, config->flags.clk_gate_en); // set data width @@ -351,6 +372,11 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un // set sample clock edge parlio_ll_tx_set_sample_clock_edge(hal->regs, config->sample_edge); +#if SOC_PARLIO_TX_SIZE_BY_DMA + // Always use DMA EOF as the Parlio TX EOF + parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DMA_EOF); +#endif // SOC_PARLIO_TX_SIZE_BY_DMA + // clear any pending interrupt parlio_ll_clear_interrupt_status(hal->regs, PARLIO_LL_EVENT_TX_MASK); @@ -380,30 +406,28 @@ esp_err_t parlio_del_tx_unit(parlio_tx_unit_handle_t unit) return parlio_destroy_tx_unit(unit); } -static void IRAM_ATTR parlio_tx_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, size_t len) +static void IRAM_ATTR parlio_tx_mount_dma_data(parlio_dma_desc_t *desc_head, const void *buffer, size_t len) { size_t prepared_length = 0; uint8_t *data = (uint8_t *)buffer; - dma_descriptor_t *desc = desc_head; - while (len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE) { - desc->dw0.suc_eof = 0; // not the end of the transaction - desc->dw0.size = DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - desc->dw0.length = DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - desc->buffer = &data[prepared_length]; - desc = desc->next; // move to next descriptor - prepared_length += DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - len -= DMA_DESCRIPTOR_BUFFER_MAX_SIZE; - } - if (len) { - desc->dw0.suc_eof = 1; // end of the transaction - desc->dw0.size = len; - desc->dw0.length = len; - desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - desc->buffer = &data[prepared_length]; + parlio_dma_desc_t *desc = desc_head; + + while (len) { + parlio_dma_desc_t *non_cache_desc = PARLIO_GET_NON_CACHED_DESC_ADDR(desc); + uint32_t mount_bytes = len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE ? DMA_DESCRIPTOR_BUFFER_MAX_SIZE : len; + len -= mount_bytes; + non_cache_desc->dw0.suc_eof = len == 0; // whether the last frame + non_cache_desc->dw0.size = mount_bytes; + non_cache_desc->dw0.length = mount_bytes; + non_cache_desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + non_cache_desc->buffer = &data[prepared_length]; desc = desc->next; // move to next descriptor - prepared_length += len; + prepared_length += mount_bytes; } +#if CONFIG_IDF_TARGET_ESP32P4 + // Write back to cache to synchronize the cache before DMA start + Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)buffer, len); +#endif // CONFIG_IDF_TARGET_ESP32P4 } esp_err_t parlio_tx_unit_wait_all_done(parlio_tx_unit_handle_t tx_unit, int timeout_ms) @@ -451,7 +475,9 @@ static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio parlio_tx_mount_dma_data(tx_unit->dma_nodes, t->payload, (t->payload_bits + 7) / 8); parlio_ll_tx_reset_fifo(hal->regs); - parlio_ll_tx_reset_clock(hal->regs); + PARLIO_RCC_ATOMIC() { + parlio_ll_tx_reset_clock(hal->regs); + } parlio_ll_tx_set_idle_data_value(hal->regs, t->idle_value); parlio_ll_tx_set_trans_bit_len(hal->regs, t->payload_bits); @@ -460,7 +486,9 @@ static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio while (parlio_ll_tx_is_ready(hal->regs) == false); // turn on the core clock after we start the TX unit parlio_ll_tx_start(hal->regs, true); - parlio_ll_tx_enable_clock(hal->regs, true); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_tx_enable_clock(hal->regs, true); + } } esp_err_t parlio_tx_unit_enable(parlio_tx_unit_handle_t tx_unit) @@ -592,7 +620,9 @@ static void IRAM_ATTR parlio_tx_default_isr(void *args) if (status & PARLIO_LL_EVENT_TX_EOF) { parlio_ll_clear_interrupt_status(hal->regs, PARLIO_LL_EVENT_TX_EOF); - parlio_ll_tx_enable_clock(hal->regs, false); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_tx_enable_clock(hal->regs, false); + } parlio_ll_tx_start(hal->regs, false); parlio_tx_trans_desc_t *trans_desc = NULL; diff --git a/components/driver/test_apps/.build-test-rules.yml b/components/driver/test_apps/.build-test-rules.yml index d13e5809a912..dc0a8ef9bf66 100644 --- a/components/driver/test_apps/.build-test-rules.yml +++ b/components/driver/test_apps/.build-test-rules.yml @@ -88,6 +88,10 @@ components/driver/test_apps/mcpwm: components/driver/test_apps/parlio: disable: - if: SOC_PARLIO_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runner components/driver/test_apps/pulse_cnt: disable: diff --git a/components/driver/test_apps/parlio/README.md b/components/driver/test_apps/parlio/README.md index b450dc5ffac0..7b822bdb0efd 100644 --- a/components/driver/test_apps/parlio/README.md +++ b/components/driver/test_apps/parlio/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/parlio/main/test_board.h b/components/driver/test_apps/parlio/main/test_board.h index 4d6c0139f616..08aecfd0813e 100644 --- a/components/driver/test_apps/parlio/main/test_board.h +++ b/components/driver/test_apps/parlio/main/test_board.h @@ -31,6 +31,16 @@ extern "C" { #define TEST_DATA5_GPIO 5 #define TEST_DATA6_GPIO 8 #define TEST_DATA7_GPIO 9 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define TEST_CLK_GPIO 20 +#define TEST_DATA0_GPIO 21 +#define TEST_DATA1_GPIO 22 +#define TEST_DATA2_GPIO 34 +#define TEST_DATA3_GPIO 35 +#define TEST_DATA4_GPIO 48 +#define TEST_DATA5_GPIO 49 +#define TEST_DATA6_GPIO 10 +#define TEST_DATA7_GPIO 11 #else #error "Unsupported target" #endif diff --git a/components/hal/esp32c6/include/hal/parlio_ll.h b/components/hal/esp32c6/include/hal/parlio_ll.h index a260d03521f5..1d1265e74e13 100644 --- a/components/hal/esp32c6/include/hal/parlio_ll.h +++ b/components/hal/esp32c6/include/hal/parlio_ll.h @@ -12,17 +12,20 @@ #include #include "hal/assert.h" #include "hal/misc.h" +#include "hal/hal_utils.h" #include "soc/pcr_struct.h" #include "soc/parl_io_struct.h" #include "hal/parlio_types.h" #define PARLIO_LL_RX_MAX_BYTES_PER_FRAME 0xFFFF -#define PARLIO_LL_RX_MAX_CLOCK_DIV 0x10000 +#define PARLIO_LL_RX_MAX_CLK_INT_DIV 0x10000 +#define PARLIO_LL_RX_MAX_CLK_FRACT_DIV 0 // Not support fractional divider #define PARLIO_LL_RX_MAX_TIMEOUT 0xFFFF #define PARLIO_LL_TX_MAX_BYTES_PER_FRAME 0xFFFF #define PARLIO_LL_TX_MAX_BITS_PER_FRAME (PARLIO_LL_TX_MAX_BYTES_PER_FRAME * 8) -#define PARLIO_LL_TX_MAX_CLOCK_DIV 0x10000 +#define PARLIO_LL_TX_MAX_CLK_INT_DIV 0x10000 +#define PARLIO_LL_TX_MAX_CLK_FRACT_DIV 0 // Not support fractional divider #define PARLIO_LL_EVENT_TX_FIFO_EMPTY (1 << 0) #define PARLIO_LL_EVENT_RX_FIFO_FULL (1 << 1) @@ -47,6 +50,30 @@ typedef enum { PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */ } parlio_ll_rx_eof_cond_t; +/** + * @brief Enable or disable the parlio peripheral APB clock + * + * @param group_id The group id of the parlio module + * @param enable Set true to enable, false to disable + */ +static inline void parlio_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.parl_io_conf.parl_clk_en = enable; +} + +/** + * @brief Reset the parlio module + * + * @param group_id The group id of the parlio module + */ +static inline void parlio_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.parl_io_conf.parl_rst_en = 1; + PCR.parl_io_conf.parl_rst_en = 0; +} + ///////////////////////////////////////RX Unit/////////////////////////////////////// /** @@ -81,13 +108,13 @@ static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c * @brief Set the clock divider for the RX unit * * @param dev Parallel IO register base address - * @param div Clock divider + * @param clk_div Clock division with integral part, no fractional part on C6 */ -static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, uint32_t div) +static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) { (void)dev; - HAL_ASSERT(div > 0 && div <= PARLIO_LL_RX_MAX_CLOCK_DIV); - PCR.parl_clk_rx_conf.parl_clk_rx_div_num = div - 1; + HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.parl_clk_rx_conf, parl_clk_rx_div_num, clk_div->integer - 1); } /** @@ -363,13 +390,13 @@ static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c * @brief Set the clock divider for the TX unit * * @param dev Parallel IO register base address - * @param div Clock divider + * @param clk_div Clock division with integral part, no fractional part on C6 */ -static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, uint32_t div) +static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) { (void)dev; - HAL_ASSERT(div > 0 && div <= PARLIO_LL_TX_MAX_CLOCK_DIV); - PCR.parl_clk_tx_conf.parl_clk_tx_div_num = div - 1; + HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.parl_clk_tx_conf, parl_clk_tx_div_num, clk_div->integer - 1); } /** diff --git a/components/hal/esp32h2/include/hal/parlio_ll.h b/components/hal/esp32h2/include/hal/parlio_ll.h index ddf7946b99a4..f4938b1c4b0e 100644 --- a/components/hal/esp32h2/include/hal/parlio_ll.h +++ b/components/hal/esp32h2/include/hal/parlio_ll.h @@ -12,16 +12,19 @@ #include #include "hal/assert.h" #include "hal/misc.h" +#include "hal/hal_utils.h" #include "soc/pcr_struct.h" #include "soc/parl_io_struct.h" #include "hal/parlio_types.h" #define PARLIO_LL_RX_MAX_BYTES_PER_FRAME 0xFFFF -#define PARLIO_LL_RX_MAX_CLOCK_DIV 0x10000 +#define PARLIO_LL_RX_MAX_CLK_INT_DIV 0x10000 +#define PARLIO_LL_RX_MAX_CLK_FRACT_DIV 0 // Not support fractional divider #define PARLIO_LL_RX_MAX_TIMEOUT 0xFFFF #define PARLIO_LL_TX_MAX_BITS_PER_FRAME 0x7FFFF -#define PARLIO_LL_TX_MAX_CLOCK_DIV 0x10000 +#define PARLIO_LL_TX_MAX_CLK_INT_DIV 0x10000 +#define PARLIO_LL_TX_MAX_CLK_FRACT_DIV 0 // Not support fractional divider #define PARLIO_LL_EVENT_TX_FIFO_EMPTY (1 << 0) #define PARLIO_LL_EVENT_RX_FIFO_FULL (1 << 1) @@ -32,6 +35,8 @@ #define PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG 7 // TXD[7] can be used a valid signal #define PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE 7 // TXD[7] can be used as clock gate signal +#define PARLIO_LL_CLK_DIVIDER_MAX (0) // Not support fractional divider + #ifdef __cplusplus extern "C" { #endif @@ -47,6 +52,30 @@ typedef enum { PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */ } parlio_ll_rx_eof_cond_t; +/** + * @brief Enable or disable the parlio peripheral APB clock + * + * @param group_id The group id of the parlio module + * @param enable Set true to enable, false to disable + */ +static inline void parlio_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.parl_io_conf.parl_clk_en = enable; +} + +/** + * @brief Reset the parlio module + * + * @param group_id The group id of the parlio module + */ +static inline void parlio_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.parl_io_conf.parl_rst_en = 1; + PCR.parl_io_conf.parl_rst_en = 0; +} + ///////////////////////////////////////RX Unit/////////////////////////////////////// /** @@ -81,13 +110,13 @@ static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c * @brief Set the clock divider for the RX unit * * @param dev Parallel IO register base address - * @param div Clock divider + * @param clk_div Clock division with integral part, no fractional part on H2 */ -static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, uint32_t div) +static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) { (void)dev; - HAL_ASSERT(div > 0 && div <= PARLIO_LL_RX_MAX_CLOCK_DIV); - PCR.parl_clk_rx_conf.parl_clk_rx_div_num = div - 1; + HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.parl_clk_rx_conf, parl_clk_rx_div_num, clk_div->integer - 1); } /** @@ -367,13 +396,13 @@ static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c * @brief Set the clock divider for the TX unit * * @param dev Parallel IO register base address - * @param div Clock divider + * @param clk_div Clock division with integral part, no fractional part on H2 */ -static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, uint32_t div) +static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) { (void)dev; - HAL_ASSERT(div > 0 && div <= PARLIO_LL_TX_MAX_CLOCK_DIV); - PCR.parl_clk_tx_conf.parl_clk_tx_div_num = div - 1; + HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.parl_clk_tx_conf, parl_clk_tx_div_num, clk_div->integer - 1); } /** diff --git a/components/hal/esp32p4/include/hal/clk_gate_ll.h b/components/hal/esp32p4/include/hal/clk_gate_ll.h index 566a112b4001..48e7a095099f 100644 --- a/components/hal/esp32p4/include/hal/clk_gate_ll.h +++ b/components/hal/esp32p4/include/hal/clk_gate_ll.h @@ -66,8 +66,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return HP_SYS_CLKRST_REG_GPSPI2_MST_CLK_EN; case PERIPH_GPSPI3_MODULE: return HP_SYS_CLKRST_REG_GPSPI3_MST_CLK_EN; - case PERIPH_PARLIO_MODULE: - return HP_SYS_CLKRST_REG_PARLIO_RX_CLK_EN | HP_SYS_CLKRST_REG_PARLIO_TX_CLK_EN; case PERIPH_I3C_MODULE: return HP_SYS_CLKRST_REG_I3C_MST_CLK_EN; case PERIPH_CAM_MODULE: @@ -153,8 +151,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return HP_SYS_CLKRST_REG_RST_EN_CAN2; case PERIPH_LEDC_MODULE: return HP_SYS_CLKRST_REG_RST_EN_LEDC; - case PERIPH_PARLIO_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_PARLIO | HP_SYS_CLKRST_REG_RST_EN_PARLIO_RX | HP_SYS_CLKRST_REG_RST_EN_PARLIO_TX; case PERIPH_I2S0_MODULE: return HP_SYS_CLKRST_REG_RST_EN_I2S0_APB; case PERIPH_I2S1_MODULE: @@ -298,7 +294,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) case PERIPH_TWAI1_MODULE: case PERIPH_TWAI2_MODULE: case PERIPH_LEDC_MODULE: - case PERIPH_PARLIO_MODULE: case PERIPH_I2S0_MODULE: return HP_SYS_CLKRST_HP_RST_EN1_REG; case PERIPH_I2S1_MODULE: diff --git a/components/hal/esp32p4/include/hal/parlio_ll.h b/components/hal/esp32p4/include/hal/parlio_ll.h new file mode 100644 index 000000000000..21a543f995c1 --- /dev/null +++ b/components/hal/esp32p4/include/hal/parlio_ll.h @@ -0,0 +1,790 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include +#include "hal/assert.h" +#include "hal/misc.h" +#include "hal/parlio_types.h" +#include "hal/hal_utils.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/parl_io_struct.h" +#include "soc/hp_sys_clkrst_struct.h" + +#define PARLIO_LL_RX_MAX_BYTES_PER_FRAME 0xFFFF +#define PARLIO_LL_RX_MAX_CLK_INT_DIV 0x100 +#define PARLIO_LL_RX_MAX_CLK_FRACT_DIV 0x100 +#define PARLIO_LL_RX_MAX_TIMEOUT 0xFFFF + +#define PARLIO_LL_TX_MAX_BITS_PER_FRAME 0x7FFFF +#define PARLIO_LL_TX_MAX_CLK_INT_DIV 0x100 +#define PARLIO_LL_TX_MAX_CLK_FRACT_DIV 0x100 + +#define PARLIO_LL_EVENT_TX_FIFO_EMPTY (1 << 0) +#define PARLIO_LL_EVENT_RX_FIFO_FULL (1 << 1) +#define PARLIO_LL_EVENT_TX_EOF (1 << 2) +#define PARLIO_LL_EVENT_TX_MASK (PARLIO_LL_EVENT_TX_FIFO_EMPTY | PARLIO_LL_EVENT_TX_EOF) +#define PARLIO_LL_EVENT_RX_MASK (PARLIO_LL_EVENT_RX_FIFO_FULL) + +#define PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG 15 // TXD[15] can be used a valid signal +#define PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE 15 // TXD[15] can be used as clock gate signal + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PARLIO_LL_CLK_SRC_XTAL = PARLIO_CLK_SRC_XTAL, + PARLIO_LL_CLK_SRC_PLL_F160M = PARLIO_CLK_SRC_PLL_F160M, + PARLIO_LL_CLK_SRC_RC_FAST = PARLIO_CLK_SRC_RC_FAST, + PARLIO_LL_CLK_SRC_PAD = PARLIO_CLK_SRC_EXTERNAL, // clock source from GPIO pad +} parlio_ll_clock_source_t; + +typedef enum { + PARLIO_LL_RX_EOF_COND_RX_FULL, /*!< RX unit generates EOF event when it receives enough data */ + PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */ +} parlio_ll_rx_eof_cond_t; + +typedef enum { + PARLIO_LL_TX_EOF_COND_DATA_LEN, /*!< TX unit generates EOF event when it transmits particular data bit length that specified in `tx_bitlen`. */ + PARLIO_LL_TX_EOF_COND_DMA_EOF, /*!< TX unit generates EOF event when the DMA EOF takes place */ +} parlio_ll_tx_eof_cond_t; + +/** + * @brief Enable or disable the parlio peripheral APB clock + * + * @param group_id The group id of the parlio module + * @param enable Set true to enable, false to disable + */ +static inline void parlio_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_parlio_apb_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the parlio module + * + * @param group_id The group id of the parlio module + */ +static inline void parlio_ll_reset_register(int group_id) +{ + (void)group_id; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio = 1; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_reset_register(__VA_ARGS__) + +///////////////////////////////////////RX Unit/////////////////////////////////////// + +/** + * @brief Set the clock source for the RX unit + * + * @param dev Parallel IO register base address + * @param src Clock source + */ +static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +{ + (void)dev; + uint32_t clk_sel = 0; + switch (src) { + case PARLIO_LL_CLK_SRC_XTAL: + clk_sel = 0; + break; + case PARLIO_LL_CLK_SRC_RC_FAST: + clk_sel = 1; + break; + case PARLIO_LL_CLK_SRC_PLL_F160M: + clk_sel = 2; + break; + case PARLIO_LL_CLK_SRC_PAD: + clk_sel = 3; + break; + + default: // unsupported clock source + HAL_ASSERT(false); + break; + } + HP_SYS_CLKRST.peri_clk_ctrl117.reg_parlio_rx_clk_src_sel = clk_sel; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_rx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_set_clock_source(__VA_ARGS__) + +/** + * @brief Get the clock source for the RX unit + * + * @param dev Parallel IO register base address + * @return + * parlio_clock_source_t RX core clock source + */ +static inline parlio_ll_clock_source_t parlio_ll_rx_get_clock_source(parl_io_dev_t *dev) +{ + (void)dev; + uint32_t clk_sel = HP_SYS_CLKRST.peri_clk_ctrl117.reg_parlio_rx_clk_src_sel; + switch (clk_sel) { + case 0: + return PARLIO_LL_CLK_SRC_XTAL; + case 1: + return PARLIO_LL_CLK_SRC_RC_FAST; + case 2: + return PARLIO_LL_CLK_SRC_PLL_F160M; + case 3: + return PARLIO_LL_CLK_SRC_PAD; + default: // unsupported clock source + HAL_ASSERT(false); + break; + } + return PARLIO_LL_CLK_SRC_XTAL; +} + + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_rx_get_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_get_clock_source(__VA_ARGS__) + +/** + * @brief Set the clock divider for the RX unit + * + * @param dev Parallel IO register base address + * @param clk_div Clock division with integral and decimal part + */ +static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) +{ + (void)dev; + HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl117, reg_parlio_rx_clk_div_num, clk_div->integer - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl118, reg_parlio_rx_clk_div_denominator, clk_div->denominator); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl118, reg_parlio_rx_clk_div_numerator, clk_div->numerator); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_rx_set_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_set_clock_div(__VA_ARGS__) + +/** + * @brief Reset the RX unit Core clock domain + * + * @param dev Parallel IO register base address + */ +static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev) +{ + (void)dev; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_rx = 1; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_rx = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_rx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_reset_clock(__VA_ARGS__) + +/** + * @brief Enable the RX unit Core clock domain + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) +{ + (void)dev; + HP_SYS_CLKRST.peri_clk_ctrl117.reg_parlio_rx_clk_en = en; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_rx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_enable_clock(__VA_ARGS__) + +/** + * @brief Set the condition to generate the RX EOF event + * + * @param dev Parallel IO register base address + * @param cond RX EOF condition + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_rx_eof_cond_t cond) +{ + dev->rx_genrl_cfg.rx_eof_gen_sel = cond; +} + +/** + * @brief Start RX unit to sample the input data + * + * @param dev Parallel IO register base address + * @param en True to start, False to stop + */ +static inline void parlio_ll_rx_start(parl_io_dev_t *dev, bool en) +{ + dev->rx_start_cfg.rx_start = en; +} + +/** + * @brief Set the receive length + * + * @note The receive length can be used to generate DMA EOF signal, or to work as a frame end delimiter + * + * @param dev Parallel IO register base address + * @param bitlen Number of bits to receive in the next transaction, bitlen must be a multiple of 8 + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_recv_bit_len(parl_io_dev_t *dev, uint32_t bitlen) +{ + dev->rx_data_cfg.rx_bitlen = bitlen; +} + +/** + * @brief Set the sub mode of the level controlled receive mode + * + * @param dev Parallel IO register base address + * @param active_level Level of the external enable signal, true for active high, false for active low + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_level) +{ + dev->rx_mode_cfg.rx_smp_mode_sel = 0; + dev->rx_mode_cfg.rx_ext_en_inv = !active_level; // 0: active low, 1: active high +} + +/** + * @brief Set the sub mode of the pulse controlled receive mode + * + * @param dev Parallel IO register base address + * @param start_inc Whether the start pulse is counted + * @param end_inc Whether the end pulse is counted + * @param end_by_len Whether to use the frame length to determine the end of the frame + * @param pulse_inv Whether the pulse is inverted + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_pulse_recv_mode(parl_io_dev_t *dev, bool start_inc, bool end_inc, bool end_by_len, bool pulse_inv) +{ + uint32_t submode = 0; + uint32_t step = 1; + if (end_by_len) { + submode += 4; + } else { // end by pulse + step = 2; + if (!end_inc) { + submode += 1; + } + } + if (!start_inc) { + submode += step; + } + dev->rx_mode_cfg.rx_smp_mode_sel = 1; + dev->rx_mode_cfg.rx_pulse_submode_sel = submode; + dev->rx_mode_cfg.rx_ext_en_inv = pulse_inv; +} + +/** + * @brief Set the receive mode to software controlled receive mode + * + * @param dev Parallel IO register base address + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_soft_recv_mode(parl_io_dev_t *dev) +{ + dev->rx_mode_cfg.rx_smp_mode_sel = 2; +} + +/** + * @brief Whether to start the software controlled receive mode + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +static inline void parlio_ll_rx_start_soft_recv(parl_io_dev_t *dev, bool en) +{ + dev->rx_mode_cfg.rx_sw_en = en; +} + +/** + * @brief Set the sample clock edge + * + * @param dev Parallel IO register base address + * @param edge Sample clock edge + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_sample_clock_edge(parl_io_dev_t *dev, parlio_sample_edge_t edge) +{ + dev->rx_clk_cfg.rx_clk_i_inv = edge; + dev->rx_clk_cfg.rx_clk_o_inv = edge; +} + +/** + * @brief Set the order to pack bits into one byte + * + * @param dev Parallel IO register base address + * @param order Packing order + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_bit_pack_order(parl_io_dev_t *dev, parlio_bit_pack_order_t order) +{ + dev->rx_data_cfg.rx_data_order_inv = order; +} + +/** + * @brief Set the bus width of the RX unit + * + * @param dev Parallel IO register base address + * @param width Bus width + */ +static inline void parlio_ll_rx_set_bus_width(parl_io_dev_t *dev, uint32_t width) +{ + uint32_t width_sel = 0; + switch (width) { + case 16: + width_sel = 4; + break; + case 8: + width_sel = 3; + break; + case 4: + width_sel = 2; + break; + case 2: + width_sel = 1; + break; + case 1: + width_sel = 0; + break; + default: + HAL_ASSERT(false); + } + dev->rx_data_cfg.rx_bus_wid_sel = width_sel; +} + +/** + * @brief Reset RX Async FIFO + * + * @note During the reset of the asynchronous FIFO, it takes two clock cycles to synchronize within AHB clock domain (GDMA) and Core clock domain. + * The reset synchronization must be performed two clock cycles in advance. + * @note If the next frame transfer needs to be reset, you need to first switch to the internal free-running clock, + * and then switch to the actual clock after the reset is completed. + * + * @param dev Parallel IO register base address + */ +static inline void parlio_ll_rx_reset_fifo(parl_io_dev_t *dev) +{ + dev->fifo_cfg.rx_fifo_srst = 1; + dev->fifo_cfg.rx_fifo_srst = 0; +} + +/** + * @brief Set which data line as the enable signal + * + * @param dev Parallel IO register base address + * @param line_num Data line number (0-15) + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_treat_data_line_as_en(parl_io_dev_t *dev, uint32_t line_num) +{ + dev->rx_mode_cfg.rx_ext_en_sel = line_num; +} + +/** + * @brief Wether to enable the RX clock gating + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +static inline void parlio_ll_rx_enable_clock_gating(parl_io_dev_t *dev, bool en) +{ + dev->rx_genrl_cfg.rx_gating_en = en; +} + +/** + * @brief Enable RX timeout feature + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_enable_timeout(parl_io_dev_t *dev, bool en) +{ + dev->rx_genrl_cfg.rx_timeout_en = en; +} + +/** + * @brief Set the threshold of RX timeout + * + * @param dev Parallel IO register base address + * @param thres Threshold of RX timeout + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_timeout_thres(parl_io_dev_t *dev, uint32_t thres) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_genrl_cfg, rx_timeout_thres, thres); +} + +/** + * @brief Update the RX configuration, to make the new configuration take effect + * + * @param dev Parallel IO register base address + */ +__attribute__((always_inline)) +static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev) +{ + dev->reg_update.rx_reg_update = 1; + while (dev->reg_update.rx_reg_update); +} + +///////////////////////////////////TX Unit/////////////////////////////////////// + +/** + * @brief Set the clock source for the TX unit + * + * @param dev Parallel IO register base address + * @param src Clock source + */ +static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +{ + (void)dev; + uint32_t clk_sel = 0; + switch (src) { + case PARLIO_LL_CLK_SRC_XTAL: + clk_sel = 0; + break; + case PARLIO_LL_CLK_SRC_RC_FAST: + clk_sel = 1; + break; + case PARLIO_LL_CLK_SRC_PLL_F160M: + clk_sel = 2; + break; + case PARLIO_LL_CLK_SRC_PAD: + clk_sel = 3; + break; + + default: // unsupported clock source + HAL_ASSERT(false); + break; + } + HP_SYS_CLKRST.peri_clk_ctrl118.reg_parlio_tx_clk_src_sel = clk_sel; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_set_clock_source(__VA_ARGS__) + +/** + * @brief Get the clock source for the TX unit + * + * @param dev Parallel IO register base address + * @return + * parlio_clock_source_t TX core clock source + */ +static inline parlio_ll_clock_source_t parlio_ll_tx_get_clock_source(parl_io_dev_t *dev) +{ + (void)dev; + uint32_t clk_sel = HP_SYS_CLKRST.peri_clk_ctrl118.reg_parlio_tx_clk_src_sel; + switch (clk_sel) { + case 0: + return PARLIO_LL_CLK_SRC_XTAL; + case 1: + return PARLIO_LL_CLK_SRC_RC_FAST; + case 2: + return PARLIO_LL_CLK_SRC_PLL_F160M; + case 3: + return PARLIO_LL_CLK_SRC_PAD; + default: // unsupported clock source + HAL_ASSERT(false); + break; + } + return PARLIO_LL_CLK_SRC_XTAL; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_tx_get_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_get_clock_source(__VA_ARGS__) + +/** + * @brief Set the clock divider for the TX unit + * + * @param dev Parallel IO register base address + * @param clk_div Clock division with integral and decimal part + */ +static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) +{ + (void)dev; + HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl118, reg_parlio_tx_clk_div_num, clk_div->integer - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl119, reg_parlio_tx_clk_div_denominator, clk_div->denominator); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl119, reg_parlio_tx_clk_div_numerator, clk_div->numerator); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_set_clock_source(__VA_ARGS__) + +/** + * @brief Reset the TX unit Core clock domain + * + * @param dev Parallel IO register base address + */ +__attribute__((always_inline)) +static inline void parlio_ll_tx_reset_clock(parl_io_dev_t *dev) +{ + (void)dev; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_tx = 1; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_tx = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_tx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_reset_clock(__VA_ARGS__) + +/** + * @brief Enable the TX unit Core clock domain + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +__attribute__((always_inline)) +static inline void parlio_ll_tx_enable_clock(parl_io_dev_t *dev, bool en) +{ + (void)dev; + HP_SYS_CLKRST.peri_clk_ctrl118.reg_parlio_tx_clk_en = en; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define parlio_ll_tx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_enable_clock(__VA_ARGS__) + +/** + * @brief Set the data length to be transmitted + * + * @param dev Parallel IO register base address + * @param bitlen Data length in bits, must be a multiple of 8 + */ +__attribute__((always_inline)) +static inline void parlio_ll_tx_set_trans_bit_len(parl_io_dev_t *dev, uint32_t bitlen) +{ + dev->tx_data_cfg.tx_bitlen = bitlen; +} + +/** + * @brief Set the condition to generate the TX EOF event + * + * @param dev Parallel IO register base address + * @param cond TX EOF condition + */ +static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_tx_eof_cond_t cond) +{ + dev->tx_genrl_cfg.tx_eof_gen_sel = cond; +} + +/** + * @brief Wether to enable the TX clock gating + * + * @note The MSB of TXD will be taken as the gating enable signal + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +static inline void parlio_ll_tx_enable_clock_gating(parl_io_dev_t *dev, bool en) +{ + dev->tx_genrl_cfg.tx_gating_en = en; +} + +/** + * @brief Start TX unit to transmit data + * + * @param dev Parallel IO register base address + * @param en True to start, False to stop + */ +__attribute__((always_inline)) +static inline void parlio_ll_tx_start(parl_io_dev_t *dev, bool en) +{ + dev->tx_start_cfg.tx_start = en; +} + +/** + * @brief Whether to treat the MSB of TXD as the valid signal + * + * @note If enabled, TXD[15] will work as valid signal, which stay high during data transmission. + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +static inline void parlio_ll_tx_treat_msb_as_valid(parl_io_dev_t *dev, bool en) +{ + dev->tx_genrl_cfg.tx_valid_output_en = en; +} + +/** + * @brief Set the sample clock edge + * + * @param dev Parallel IO register base address + * @param edge Sample clock edge + */ +static inline void parlio_ll_tx_set_sample_clock_edge(parl_io_dev_t *dev, parlio_sample_edge_t edge) +{ + dev->tx_clk_cfg.tx_clk_i_inv = edge; + dev->tx_clk_cfg.tx_clk_o_inv = edge; +} + +/** + * @brief Set the order to unpack bits from a byte + * + * @param dev Parallel IO register base address + * @param order Packing order + */ +static inline void parlio_ll_tx_set_bit_pack_order(parl_io_dev_t *dev, parlio_bit_pack_order_t order) +{ + dev->tx_data_cfg.tx_data_order_inv = order; +} + +/** + * @brief Set the bus width of the TX unit + * + * @param dev Parallel IO register base address + * @param width Bus width + */ +static inline void parlio_ll_tx_set_bus_width(parl_io_dev_t *dev, uint32_t width) +{ + uint32_t width_sel = 0; + switch (width) { + // TODO: check this field (IDF-8284) + case 16: + width_sel = 4; + break; + case 8: + width_sel = 3; + break; + case 4: + width_sel = 2; + break; + case 2: + width_sel = 1; + break; + case 1: + width_sel = 0; + break; + default: + HAL_ASSERT(false); + } + dev->tx_data_cfg.tx_bus_wid_sel = width_sel; +} + +/** + * @brief Reset TX Async FIFO + * + * @note During the reset of the asynchronous FIFO, it takes two clock cycles to synchronize within AHB clock domain (GDMA) and Core clock domain. + * The reset synchronization must be performed two clock cycles in advance. + * @note If the next frame transfer needs to be reset, you need to first switch to the internal free-running clock, + * and then switch to the actual clock after the reset is completed. + * + * @param dev Parallel IO register base address + */ +__attribute__((always_inline)) +static inline void parlio_ll_tx_reset_fifo(parl_io_dev_t *dev) +{ + dev->fifo_cfg.tx_fifo_srst = 1; + dev->fifo_cfg.tx_fifo_srst = 0; +} + +/** + * @brief Set the value to output on the TXD when the TX unit is in IDLE state + * + * @param dev Parallel IO register base address + * @param value Value to output + */ +__attribute__((always_inline)) +static inline void parlio_ll_tx_set_idle_data_value(parl_io_dev_t *dev, uint32_t value) +{ + dev->tx_genrl_cfg.tx_idle_value = value; +} + +/** + * @brief Check whether the TX unit is ready + * + * @param dev Parallel IO register base address + * @return true: ready, false: busy + */ +__attribute__((always_inline)) +static inline bool parlio_ll_tx_is_ready(parl_io_dev_t *dev) +{ + return dev->st.tx_ready; +} + +////////////////////////////////////Interrupt//////////////////////////////////////////////// + +/** + * @brief Enable Parallel IO interrupt for specific event mask + * + * @param dev Parallel IO register base address + * @param mask Event mask + * @param enable True to enable, False to disable + */ +static inline void parlio_ll_enable_interrupt(parl_io_dev_t *dev, uint32_t mask, bool enable) +{ + if (enable) { + dev->int_ena.val |= mask; + } else { + dev->int_ena.val &= ~mask; + } +} + +/** + * @brief Get interrupt status for TX unit + * + * @param dev Parallel IO register base address + * @return Interrupt status + */ +__attribute__((always_inline)) +static inline uint32_t parlio_ll_tx_get_interrupt_status(parl_io_dev_t *dev) +{ + return dev->int_st.val & PARLIO_LL_EVENT_TX_MASK; +} + +/** + * @brief Get interrupt status for RX unit + * + * @param dev Parallel IO register base address + * @return Interrupt status + */ +__attribute__((always_inline)) +static inline uint32_t parlio_ll_rx_get_interrupt_status(parl_io_dev_t *dev) +{ + return dev->int_st.val & PARLIO_LL_EVENT_RX_MASK; +} + +/** + * @brief Clear Parallel IO interrupt status by mask + * + * @param dev Parallel IO register base address + * @param mask Interrupt status mask + */ +__attribute__((always_inline)) +static inline void parlio_ll_clear_interrupt_status(parl_io_dev_t *dev, uint32_t mask) +{ + dev->int_clr.val = mask; +} + +/** + * @brief Get interrupt status register address + * + * @param dev Parallel IO register base address + * @return Register address + */ +static inline volatile void *parlio_ll_get_interrupt_status_reg(parl_io_dev_t *dev) +{ + return &dev->int_st; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/parlio_hal.c b/components/hal/parlio_hal.c index d44300882937..af8b9bb7c647 100644 --- a/components/hal/parlio_hal.c +++ b/components/hal/parlio_hal.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include "hal/parlio_hal.h" #include "hal/parlio_ll.h" diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 050a05c4afde..52c495ddd6dd 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -35,6 +35,10 @@ config SOC_ETM_SUPPORTED bool default y +config SOC_PARLIO_SUPPORTED + bool + default y + config SOC_ASYNC_MEMCPY_SUPPORTED bool default y @@ -651,7 +655,7 @@ config SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH int default 16 -config SOC_PARLIO_TX_RX_SHARE_INTERRUPT +config SOC_PARLIO_TX_SIZE_BY_DMA bool default y diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 8e3e34bc9c30..a8bd52ee9564 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -448,6 +448,26 @@ typedef enum { //////////////////////////////////////////////////PARLIO//////////////////////////////////////////////////////////////// +/** + * @brief Array initializer for all supported clock sources of PARLIO + */ +#define SOC_PARLIO_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_RC_FAST, PARLIO_CLK_SRC_EXTERNAL} + +/** + * @brief PARLIO clock source + */ +typedef enum { + PARLIO_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + PARLIO_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + PARLIO_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + PARLIO_CLK_SRC_EXTERNAL = -1, /*!< Select EXTERNAL clock as the source clock */ +#if SOC_CLK_TREE_SUPPORTED + PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ +#else + PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default clock choice */ +#endif +} soc_periph_parlio_clk_src_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/parl_io_struct.h b/components/soc/esp32p4/include/soc/parl_io_struct.h index 7c1693b9bc47..aea2cb383b8c 100644 --- a/components/soc/esp32p4/include/soc/parl_io_struct.h +++ b/components/soc/esp32p4/include/soc/parl_io_struct.h @@ -498,6 +498,7 @@ typedef struct parl_io_dev_t { volatile parl_io_version_reg_t version; } parl_io_dev_t; +extern parl_io_dev_t PARL_IO; #ifndef __cplusplus _Static_assert(sizeof(parl_io_dev_t) == 0x400, "Invalid size of parl_io_dev_t structure"); diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 0ae4f43de63d..a9a1dcb64a82 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -37,7 +37,7 @@ #define SOC_MCPWM_SUPPORTED 1 // #define SOC_TWAI_SUPPORTED 1 //TODO: IDF-7470 #define SOC_ETM_SUPPORTED 1 -// #define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471, TODO: IDF-7472 +#define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 // disable usb serial jtag for esp32p4, current image does not support // #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 //TODO: IDF-7496 @@ -317,7 +317,7 @@ #define SOC_PARLIO_RX_UNITS_PER_GROUP 1U /*!< number of RX units in each group */ #define SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the TX unit */ #define SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the RX unit */ -#define SOC_PARLIO_TX_RX_SHARE_INTERRUPT 1 /*!< TX and RX unit share the same interrupt source number */ +#define SOC_PARLIO_TX_SIZE_BY_DMA 1 /*!< Transaction length is controlled by DMA instead of indicated by register */ /*--------------------------- MPI CAPS ---------------------------------------*/ #define SOC_MPI_MEM_BLOCKS_NUM (4) diff --git a/components/soc/esp32p4/parlio_periph.c b/components/soc/esp32p4/parlio_periph.c index 827c6144158a..5dcafc7206e2 100644 --- a/components/soc/esp32p4/parlio_periph.c +++ b/components/soc/esp32p4/parlio_periph.c @@ -8,5 +8,59 @@ #include "soc/gpio_sig_map.h" const parlio_signal_conn_t parlio_periph_signals = { - + .groups = { + [0] = { + .module = PERIPH_PARLIO_MODULE, + .tx_irq_id = ETS_HP_PARLIO_TX_INTR_SOURCE, + .rx_irq_id = ETS_HP_PARLIO_RX_INTR_SOURCE, + .tx_units = { + [0] = { + .data_sigs = { + PARLIO_TX_DATA0_PAD_OUT_IDX, + PARLIO_TX_DATA1_PAD_OUT_IDX, + PARLIO_TX_DATA2_PAD_OUT_IDX, + PARLIO_TX_DATA3_PAD_OUT_IDX, + PARLIO_TX_DATA4_PAD_OUT_IDX, + PARLIO_TX_DATA5_PAD_OUT_IDX, + PARLIO_TX_DATA6_PAD_OUT_IDX, + PARLIO_TX_DATA7_PAD_OUT_IDX, + PARLIO_TX_DATA8_PAD_OUT_IDX, + PARLIO_TX_DATA9_PAD_OUT_IDX, + PARLIO_TX_DATA10_PAD_OUT_IDX, + PARLIO_TX_DATA11_PAD_OUT_IDX, + PARLIO_TX_DATA12_PAD_OUT_IDX, + PARLIO_TX_DATA13_PAD_OUT_IDX, + PARLIO_TX_DATA14_PAD_OUT_IDX, + PARLIO_TX_DATA15_PAD_OUT_IDX, + }, + .clk_out_sig = PARLIO_TX_CLK_PAD_OUT_IDX, + .clk_in_sig = PARLIO_TX_CLK_PAD_IN_IDX, + } + }, + .rx_units = { + [0] = { + .data_sigs = { + PARLIO_RX_DATA0_PAD_IN_IDX, + PARLIO_RX_DATA1_PAD_IN_IDX, + PARLIO_RX_DATA2_PAD_IN_IDX, + PARLIO_RX_DATA3_PAD_IN_IDX, + PARLIO_RX_DATA4_PAD_IN_IDX, + PARLIO_RX_DATA5_PAD_IN_IDX, + PARLIO_RX_DATA6_PAD_IN_IDX, + PARLIO_RX_DATA7_PAD_IN_IDX, + PARLIO_RX_DATA8_PAD_IN_IDX, + PARLIO_RX_DATA9_PAD_IN_IDX, + PARLIO_RX_DATA10_PAD_IN_IDX, + PARLIO_RX_DATA11_PAD_IN_IDX, + PARLIO_RX_DATA12_PAD_IN_IDX, + PARLIO_RX_DATA13_PAD_IN_IDX, + PARLIO_RX_DATA14_PAD_IN_IDX, + PARLIO_RX_DATA15_PAD_IN_IDX, + }, + .clk_out_sig = PARLIO_RX_CLK_PAD_OUT_IDX, + .clk_in_sig = PARLIO_RX_CLK_PAD_IN_IDX, + } + } + }, + }, }; diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 02974dcc02ec..72196d2c6e9d 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -132,6 +132,10 @@ examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop: examples/peripherals/parlio: disable: - if: SOC_PARLIO_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runner examples/peripherals/parlio/simple_rgb_led_matrix: disable: From 7729144f1ad1b2f75b1096c906ef00d75635691c Mon Sep 17 00:00:00 2001 From: Wang Zi Yan Date: Tue, 19 Sep 2023 19:10:51 +0800 Subject: [PATCH 039/142] docs: Update CN for speed.rst --- docs/en/api-guides/performance/speed.rst | 2 +- docs/zh_CN/api-guides/performance/speed.rst | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/en/api-guides/performance/speed.rst b/docs/en/api-guides/performance/speed.rst index 5ca18c05b9f8..f4ee59dcc0fe 100644 --- a/docs/en/api-guides/performance/speed.rst +++ b/docs/en/api-guides/performance/speed.rst @@ -256,7 +256,7 @@ Using standard C library functions like ``fread`` and ``fwrite`` instead of plat :doc:`/api-reference/storage/fatfs` specific information and tips: .. list:: - + - Maximum size of the R/W request = FatFS cluster size (allocation unit size). - Use ``read`` and ``write`` instead of ``fread`` and ``fwrite``. - To increase speed of buffered reading functions like ``fread`` and ``fgets``, you can increase a size of the file buffer (Newlib's default is 128 bytes) to a higher number like 4096, 8192 or 16384. This can be done locally via the ``setvbuf`` function used on a certain file pointer or globally applied to all files via modifying :ref:`CONFIG_FATFS_VFS_FSTAT_BLKSIZE`. diff --git a/docs/zh_CN/api-guides/performance/speed.rst b/docs/zh_CN/api-guides/performance/speed.rst index 4a4db95ada42..e7dbc949e2d3 100644 --- a/docs/zh_CN/api-guides/performance/speed.rst +++ b/docs/zh_CN/api-guides/performance/speed.rst @@ -70,7 +70,7 @@ 如果启用了选项 :ref:`CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS` ,则可以使用 FreeRTOS API :cpp:func:`vTaskGetRunTimeStats` 来获取各个 FreeRTOS 任务运行时占用处理器的时间。 -:ref:`SEGGER SystemView ` 是一款出色的工具,可将任务执行情况可视化,也可用于排查系统整体的性能问题或改进方向。 +:ref:`SEGGER SystemView ` 是一款出色的工具,可将任务执行情况可视化,也可用于排查系统整体的性能问题或改进方向。 提高整体速度 ----------------------------- @@ -82,7 +82,7 @@ :esp32: - 设置 :ref:`CONFIG_ESPTOOLPY_FLASHFREQ` 为 80 MHz。该值为默认值 40 MHz 的两倍,这意味着从 flash 加载或执行代码的速度也将翻倍。在更改此设置之前,应事先确认连接 {IDF_TARGET_NAME} 和 flash 的板或模块在温度限制范围内支持 80 MHz 的操作。相关信息参见硬件数据手册。 - 设置 :ref:`CONFIG_ESPTOOLPY_FLASHMODE` 为 QIO 或 QOUT 模式(四线 I/O 模式)。相较于默认的 DIO 模式,在这两种模式下,从 flash 加载或执行代码的速度几乎翻倍。如果两种模式都支持,QIO 会稍微快于 QOUT。请注意,flash 芯片以及 {IDF_TARGET_NAME} 与 flash 芯片之间的电气连接都必须支持四线 I/O 模式,否则 SoC 将无法正常工作。 - 设置 :ref:`CONFIG_COMPILER_OPTIMIZATION` 为 ``Optimize for performance (-O2)`` 。相较于默认设置,这可能会略微增加二进制文件大小,但几乎必然会提高某些代码的性能。请注意,如果代码包含 C 或 C++ 的未定义行为,提高编译器优化级别可能会暴露出原本未发现的错误。 - :SOC_ASSIST_DEBUG_SUPPORTED: - 将 :ref:`CONFIG_ESP_SYSTEM_HW_STACK_GUARD` 设置为禁用。这可能会小幅提升某些代码的性能,且在设备中断多次的情况下尤为明显。 + :SOC_ASSIST_DEBUG_SUPPORTED: - 禁用 :ref:`CONFIG_ESP_SYSTEM_HW_STACK_GUARD` 可能会小幅提高代码性能,尤其是在设备上出现大量中断的情况下。 :esp32: - 如果应用程序是基于 ESP32 rev. 3 (ECO3) 的项目并且使用 PSRAM,设置 :ref:`CONFIG_ESP32_REV_MIN` 为 ``3`` 将禁用 PSRAM 的错误修复工作,可以减小代码大小并提高整体性能。 :SOC_CPU_HAS_FPU: - 避免使用浮点运算 ``float``。尽管 {IDF_TARGET_NAME} 具备单精度浮点运算器,但是浮点运算总是慢于整数运算。因此可以考虑使用不同的整数表示方法进行运算,如定点表示法,或者将部分计算用整数运算后再切换为浮点运算。 :not SOC_CPU_HAS_FPU: - 避免使用浮点运算 ``float``。{IDF_TARGET_NAME} 通过软件模拟进行浮点运算,因此速度非常慢。可以考虑使用不同的整数表示方法进行运算,如定点表示法,或者将部分计算用整数运算后再切换为浮点运算。 @@ -142,7 +142,7 @@ ESP-IDF FreeRTOS 是实时操作系统,因此需确保高吞吐量或低延迟的任务获得更高优先级,以便立即运行。调用 :cpp:func:`xTaskCreate` 或 :cpp:func:`xTaskCreatePinnedToCore` 会设定优先级,并且可以在运行时调用 :cpp:func:`vTaskPrioritySet` 进行更改。 -此外,还需确保任务适时释放 CPU(通过调用 :cpp:func:`vTaskDelay` 或 ``sleep()`` ,或在信号量、队列、任务通知等方面进行阻塞),以避免低优先级任务饥饿并造成系统性问题。 :ref:`task-watchdog-timer` 提供任务饥饿自动检测机制,但请注意,正确的固件操作有时需要长时间运算,因此任务看门狗定时器超时并不总意味着存在问题。在这些情况下,可能需要微调超时时限,甚至禁用任务看门狗定时器。 +此外,还需确保任务适时释放 CPU(通过调用 :cpp:func:`vTaskDelay` 或 ``sleep()`` ,或在信号量、队列、任务通知等方面进行阻塞),以避免低优先级任务饥饿并造成系统性问题。 :ref:`task-watchdog-timer` 提供任务饥饿自动检测机制,但请注意,正确的固件操作有时需要长时间运算,因此任务看门狗定时器超时并不总意味着存在问题。在这些情况下,可能需要微调超时时限,甚至禁用任务看门狗定时器。 .. _built-in-task-priorities: @@ -245,7 +245,8 @@ ESP-IDF 支持动态 :doc:`/api-reference/system/intr_alloc` 和中断抢占。 :SOC_WIFI_SUPPORTED: * 关于提高 Wi-Fi 网速,参见 :ref:`How-to-improve-Wi-Fi-performance` 和 :ref:`wifi-buffer-usage` 。 * 关于提高 lwIP TCP/IP(Wi-Fi 和以太网)网速,参见 :ref:`lwip-performance` 。 - :SOC_WIFI_SUPPORTED: * 示例 :example:`wifi/iperf` 包含了一种针对 Wi-Fi TCP/IP 吞吐量进行了大量优化的配置。将文件 :example_file:`wifi/iperf/sdkconfig.defaults` 、 :example_file:`wifi/iperf/sdkconfig.defaults.{IDF_TARGET_PATH_NAME}` 和 :example_file:`wifi/iperf/sdkconfig.ci.99` 的内容追加到项目的 ``sdkconfig`` 文件中,即可添加所有相关选项。请注意,部分选项可能会导致可调试性降低、固件大小增加、内存使用增加或其他功能的性能降低等影响。为了获得最佳结果,请阅读上述链接文档,并据此确定哪些选项最适合当前应用程序。 + :SOC_WIFI_SUPPORTED: * 示例 :example:`wifi/iperf` 中的配置针对 Wi-Fi TCP/IP 吞吐量进行了大量优化。将文件 :example_file:`wifi/iperf/sdkconfig.defaults` 、 :example_file:`wifi/iperf/sdkconfig.defaults.{IDF_TARGET_PATH_NAME}` 和 :example_file:`wifi/iperf/sdkconfig.ci.99` 的内容追加到项目的 ``sdkconfig`` 文件中,即可添加所有相关选项。请注意,部分选项可能会导致可调试性降低、固件大小增加、内存使用增加或其他功能的性能降低等影响。为了获得最佳结果,请阅读上述链接文档,并据此确定哪些选项最适合当前应用程序。 + :SOC_EMAC_SUPPORTED: * 示例 :example:`ethernet/iperf` 中的配置针对以太网 TCP/IP 吞吐量进行了大量优化。如需了解详情,请查看 :example_file:`ethernet/iperf/sdkconfig.defaults`。请注意,部分选项可能会导致可调试性降低、固件大小增加、内存使用增加或其他功能的性能降低等影响。为了获得最佳结果,请阅读上述链接文档,并据此确定哪些选项最适合当前应用程序。 提高 I/O 性能 ---------------------------------- @@ -255,7 +256,7 @@ ESP-IDF 支持动态 :doc:`/api-reference/system/intr_alloc` 和中断抢占。 :doc:`/api-reference/storage/fatfs` 具体信息和提示如下: .. list:: - + - 读取/写入请求的最大大小等于 FatFS 簇大小(分配单元大小)。 - 使用 ``read`` 和 ``write`` 而非 ``fread`` 和 ``fwrite`` 可以提高性能。 - 要提高诸如 ``fread`` 和 ``fgets`` 等缓冲读取函数的执行速度,可以增加文件缓冲区的大小(Newlib 的默认值为 128 字节),例如 4096、8192 或 16384 字节。为此,可以在特定文件的指针上使用 ``setvbuf`` 函数进行局部更改,或者修改 :ref:`CONFIG_FATFS_VFS_FSTAT_BLKSIZE` 实现全局应用。 From 0860e75587377b01730a4f338a25064edb191129 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Fri, 18 Aug 2023 15:52:22 +0800 Subject: [PATCH 040/142] feat(bt/bluedroid): Add HFP config for BQB test --- .../common/include/common/bt_target.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 75f128927e7d..4c3c5ef37cb7 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -1982,6 +1982,24 @@ #define PAN_NAP_SECURITY_LEVEL 0 #endif +/****************************************************************************** +** +** HFP +** +******************************************************************************/ + +#if (BTC_HF_INCLUDED == TRUE) && (BT_CLASSIC_BQB_INCLUDED == TRUE) +#define BT_HF_AG_BQB_INCLUDED TRUE +#else +#define BT_HF_AG_BQB_INCLUDED FALSE +#endif + +#if (BTC_HF_CLIENT_INCLUDED == TRUE) && (BT_CLASSIC_BQB_INCLUDED == TRUE) +#define BT_HF_CLIENT_BQB_INCLUDED TRUE +#else +#define BT_HF_CLIENT_BQB_INCLUDED FALSE +#endif + /****************************************************************************** ** ** GAP From 5600da1cfedc65717aaede44e1ade1f597d79c3f Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Mon, 14 Aug 2023 14:07:36 +0800 Subject: [PATCH 041/142] feat(bt/bluedroid): Modify AT+CNUM response api and HFP AG example --- .../bt/host/bluedroid/api/esp_hf_ag_api.c | 8 +++++-- .../bluedroid/api/include/api/esp_hf_ag_api.h | 8 +++++-- .../bluedroid/api/include/api/esp_hf_defs.h | 2 +- .../btc/profile/std/hf_ag/btc_hf_ag.c | 12 +++++----- .../btc/profile/std/include/btc_hf_ag.h | 3 ++- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 2 +- .../classic_bt/hfp_ag/main/bt_app_hf.c | 23 +++++++++++++++---- 7 files changed, 41 insertions(+), 17 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_hf_ag_api.c b/components/bt/host/bluedroid/api/esp_hf_ag_api.c index 5e43ab89189b..4d0acdf7efc9 100644 --- a/components/bt/host/bluedroid/api/esp_hf_ag_api.c +++ b/components/bt/host/bluedroid/api/esp_hf_ag_api.c @@ -337,11 +337,14 @@ esp_err_t esp_hf_ag_clcc_response(esp_bd_addr_t remote_addr, int index, esp_hf_c return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } -esp_err_t esp_hf_ag_cnum_response(esp_bd_addr_t remote_addr, char *number, esp_hf_subscriber_service_type_t type) +esp_err_t esp_hf_ag_cnum_response(esp_bd_addr_t remote_addr, char *number, int number_type, esp_hf_subscriber_service_type_t service_type) { if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { return ESP_ERR_INVALID_STATE; } + if (number == NULL) { + return ESP_ERR_INVALID_ARG; + } btc_msg_t msg; msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_HF; @@ -351,7 +354,8 @@ esp_err_t esp_hf_ag_cnum_response(esp_bd_addr_t remote_addr, char *number, esp_h memset(&arg, 0, sizeof(btc_hf_args_t)); memcpy(&(arg.cnum_rep), remote_addr, sizeof(esp_bd_addr_t)); arg.cnum_rep.number = number; //deep_copy - arg.cnum_rep.type = type; + arg.cnum_rep.number_type = number_type; + arg.cnum_rep.service_type = service_type; /* Switch to BTC context */ bt_status_t status = btc_transfer_context(&msg, &arg, sizeof(btc_hf_args_t), diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h index 31c9a07e4b75..b38e0f1610bc 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h @@ -525,14 +525,18 @@ esp_err_t esp_hf_ag_clcc_response(esp_bd_addr_t remote_addr, int index, esp_hf_c * * @param[in] remote_addr: remote bluetooth device address * @param[in] number: registration number - * @param[in] type: service type (unknown/voice/fax) + * @param[in] number_type: value of number type from + * 128-143: national or international, may contain prefix and/or escape digits + * 144-159: international, includes country code prefix, add "+" if needed + * 160-175: national, but no prefix nor escape digits + * @param[in] service_type: service type (unknown/voice/fax) * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled * - ESP_FAIL: others * */ -esp_err_t esp_hf_ag_cnum_response(esp_bd_addr_t remote_addr, char *number, esp_hf_subscriber_service_type_t type); +esp_err_t esp_hf_ag_cnum_response(esp_bd_addr_t remote_addr, char *number, int number_type, esp_hf_subscriber_service_type_t service_type); /** * diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h b/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h index 114d60e2cdd4..50c3e05e3424 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h @@ -124,7 +124,7 @@ typedef enum { /// +CNUM service type of the phone number typedef enum { ESP_HF_SUBSCRIBER_SERVICE_TYPE_UNKNOWN = 0, /*!< unknown */ - ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE, /*!< voice service */ + ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE = 4, /*!< voice service */ ESP_HF_SUBSCRIBER_SERVICE_TYPE_FAX, /*!< fax service */ } esp_hf_subscriber_service_type_t; diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index c0317949f012..618a0e98464b 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -607,7 +607,7 @@ static bt_status_t btc_hf_clcc_response(bt_bdaddr_t *bd_addr, int index, esp_hf_ } //AT+CNUM -static bt_status_t btc_hf_cnum_response(bt_bdaddr_t *bd_addr, const char *number, esp_hf_subscriber_service_type_t type) +static bt_status_t btc_hf_cnum_response(bt_bdaddr_t *bd_addr, const char *number, int number_type, esp_hf_subscriber_service_type_t service_type) { int idx = btc_hf_idx_by_bdaddr(bd_addr); CHECK_HF_SLC_CONNECTED(idx); @@ -615,11 +615,11 @@ static bt_status_t btc_hf_cnum_response(bt_bdaddr_t *bd_addr, const char *number if (is_connected(idx, bd_addr)) { tBTA_AG_RES_DATA ag_res; memset(&ag_res, 0, sizeof (ag_res)); - BTC_TRACE_EVENT("cnum_response: number = %s, type = %d", number, type); - if (number) { - sprintf(ag_res.str, ",\"%s\",%d",number, type); + BTC_TRACE_EVENT("cnum_response: number = %s, number type = %d, service type = %d", number, number_type, service_type); + if (service_type) { + sprintf(ag_res.str, ",\"%s\",%d,,%d",number, number_type, service_type); } else { - sprintf(ag_res.str, ",\"\",%d",type); + sprintf(ag_res.str, ",\"%s\",%d,,",number, number_type); } ag_res.ok_flag = BTA_AG_OK_DONE; BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CNUM_RES, &ag_res); @@ -1142,7 +1142,7 @@ void btc_hf_call_handler(btc_msg_t *msg) case BTC_HF_CNUM_RESPONSE_EVT: { - btc_hf_cnum_response(&arg->cnum_rep.remote_addr, arg->cnum_rep.number, arg->cnum_rep.type); + btc_hf_cnum_response(&arg->cnum_rep.remote_addr, arg->cnum_rep.number, arg->cnum_rep.number_type, arg->cnum_rep.service_type); break; } diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h index 79d23377497a..078064fdd05e 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h @@ -143,7 +143,8 @@ typedef union struct cnum_args { bt_bdaddr_t remote_addr; char *number; - esp_hf_subscriber_service_type_t type; + int number_type; + esp_hf_subscriber_service_type_t service_type; } cnum_rep; //BTC_HF_NREC_RESPONSE_EVT diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c index aecc0d1965c6..2b46c33b4835 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c @@ -148,7 +148,7 @@ HF_CMD_HANDLER(ind_change) if (sscanf(argv[3], "%d", &ntk_state) != 1 || (ntk_state != ESP_HF_NETWORK_STATE_NOT_AVAILABLE && ntk_state != ESP_HF_NETWORK_STATE_AVAILABLE)) { - printf("Invalid argument for netwrok state %s\n", argv[3]); + printf("Invalid argument for network state %s\n", argv[3]); return 1; } if (sscanf(argv[4], "%d", &signal) != 1 || diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c index c1e3f8bcf88f..a83c1e39bb99 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -360,7 +360,12 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) esp_hf_call_setup_status_t call_setup_state = 2; esp_hf_network_state_t ntk_state = 1; int signal = 2; - esp_hf_ag_devices_status_indchange(param->ind_upd.remote_addr,call_state,call_setup_state,ntk_state,signal); + int battery = 3; + esp_hf_ag_ciev_report(param->ind_upd.remote_addr, ESP_HF_IND_TYPE_CALL, call_state); + esp_hf_ag_ciev_report(param->ind_upd.remote_addr, ESP_HF_IND_TYPE_CALLSETUP, call_setup_state); + esp_hf_ag_ciev_report(param->ind_upd.remote_addr, ESP_HF_IND_TYPE_SERVICE, ntk_state); + esp_hf_ag_ciev_report(param->ind_upd.remote_addr, ESP_HF_IND_TYPE_SIGNAL, signal); + esp_hf_ag_ciev_report(param->ind_upd.remote_addr, ESP_HF_IND_TYPE_BATTCHG, battery); break; } @@ -399,15 +404,25 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) ESP_LOGI(BT_HF_TAG, "--Calling Line Identification."); esp_hf_ag_clcc_response(param->clcc_rep.remote_addr, index, dir, current_call_status, mode, mpty, number, type); + + //AG shall always send ok response to HF + //index = 0 means response ok + index = 0; + esp_hf_ag_clcc_response(param->clcc_rep.remote_addr, index, dir, current_call_status, mode, mpty, number, type); break; } case ESP_HF_CNUM_RESPONSE_EVT: { char *number = {"123456"}; - esp_hf_subscriber_service_type_t type = 1; - ESP_LOGI(BT_HF_TAG, "--Current Number is %s ,Type is %s.", number, c_subscriber_service_type_str[type]); - esp_hf_ag_cnum_response(param->cnum_rep.remote_addr, number,type); + int number_type = 129; + esp_hf_subscriber_service_type_t service_type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE; + if (service_type == ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE || service_type == ESP_HF_SUBSCRIBER_SERVICE_TYPE_FAX) { + ESP_LOGI(BT_HF_TAG, "--Current Number is %s, Number Type is %d, Service Type is %s.", number, number_type, c_subscriber_service_type_str[service_type - 3]); + } else { + ESP_LOGI(BT_HF_TAG, "--Current Number is %s, Number Type is %d, Service Type is %s.", number, number_type, c_subscriber_service_type_str[0]); + } + esp_hf_ag_cnum_response(hf_peer_addr, number, number_type, service_type); break; } From 5875f1160ee8852d1123670160a8108d1fb50397 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Tue, 15 Aug 2023 17:29:17 +0800 Subject: [PATCH 042/142] feat(bt/bluedroid): Add supprot for specific indicator sending from AG to Client --- .../bt/host/bluedroid/api/esp_hf_ag_api.c | 21 +++++++++++++ .../bluedroid/api/include/api/esp_hf_ag_api.h | 31 +++++++++++++++---- .../bluedroid/api/include/api/esp_hf_defs.h | 15 +++++++-- .../btc/profile/std/hf_ag/btc_hf_ag.c | 19 ++++++++++++ .../btc/profile/std/include/btc_hf_ag.h | 7 +++++ .../bt/host/bluedroid/stack/btm/btm_sco.c | 2 +- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 5 ++- 7 files changed, 90 insertions(+), 10 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_hf_ag_api.c b/components/bt/host/bluedroid/api/esp_hf_ag_api.c index 4d0acdf7efc9..42878a4c7ab9 100644 --- a/components/bt/host/bluedroid/api/esp_hf_ag_api.c +++ b/components/bt/host/bluedroid/api/esp_hf_ag_api.c @@ -255,6 +255,27 @@ esp_err_t esp_hf_ag_devices_status_indchange(esp_bd_addr_t remote_addr, return (state == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_hf_ag_ciev_report(esp_bd_addr_t remote_addr, esp_hf_ciev_report_type_t ind_type, int value) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF; + msg.act = BTC_HF_CIEV_REPORT_EVT; + + btc_hf_args_t arg; + memset(&arg, 0, sizeof(btc_hf_args_t)); + memcpy(&(arg.ciev_rep.remote_addr), remote_addr, sizeof(esp_bd_addr_t)); + arg.ciev_rep.ind.type = ind_type; + arg.ciev_rep.ind.value = value; + + /* Switch to BTC context */ + bt_status_t state = btc_transfer_context(&msg, &arg, sizeof(btc_hf_args_t), NULL, NULL); + return (state == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + esp_err_t esp_hf_ag_cind_response(esp_bd_addr_t remote_addr, esp_hf_call_status_t call_state, esp_hf_call_setup_status_t call_setup_state, diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h index b38e0f1610bc..02730e491004 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h @@ -402,7 +402,7 @@ esp_err_t esp_hf_ag_vra_control(esp_bd_addr_t remote_bda, esp_hf_vr_state_t valu */ esp_err_t esp_hf_ag_volume_control(esp_bd_addr_t remote_bda, esp_hf_volume_control_target_t type, int volume); - /** +/** * * @brief Handle Unknown AT command from HFP Client. * As a precondition to use this API, Service Level Connection shall exist with HFP client. @@ -419,7 +419,7 @@ esp_err_t esp_hf_ag_volume_control(esp_bd_addr_t remote_bda, esp_hf_volume_contr */ esp_err_t esp_hf_ag_unknown_at_send(esp_bd_addr_t remote_addr, char *unat); - /** +/** * * @brief Unsolicited send extend AT error code to HFP Client. * As a precondition to use this API, Service Level Connection shall exist with HFP client. @@ -435,7 +435,7 @@ esp_err_t esp_hf_ag_unknown_at_send(esp_bd_addr_t remote_addr, char *unat); */ esp_err_t esp_hf_ag_cmee_send(esp_bd_addr_t remote_bda, esp_hf_at_response_code_t response_code, esp_hf_cme_err_t error_code); - /** +/** * * @brief Unsolicited send device status notification to HFP Client. * As a precondition to use this API, Service Level Connection shall exist with HFP client. @@ -452,10 +452,29 @@ esp_err_t esp_hf_ag_cmee_send(esp_bd_addr_t remote_bda, esp_hf_at_response_code_ * */ esp_err_t esp_hf_ag_devices_status_indchange(esp_bd_addr_t remote_addr, esp_hf_call_status_t call_state, - esp_hf_call_setup_status_t call_setup_state, - esp_hf_network_state_t ntk_state, int signal); + esp_hf_call_setup_status_t call_setup_state, + esp_hf_network_state_t ntk_state, int signal) __attribute__(( + deprecated("Please use esp_hf_ag_ciev_report") + )); + +/** + * + * @brief Send indicator report "+CIEV: " to HFP Client. "CIEV" means “indicator events reporting", + * and all indicator types can be sent one type at a time. + * As a precondition to use this API, Service Level Connection shall exist with HFP client. + * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] ind_type: indicator type + * @param[in] value: indicator value + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_ag_ciev_report(esp_bd_addr_t remote_addr, esp_hf_ciev_report_type_t ind_type, int value); - /** +/** * * @brief Response to device individual indicators to HFP Client. * As a precondition to use this API, Service Level Connection shall exist with HFP client. diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h b/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h index 50c3e05e3424..b7671ff1e7ad 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,6 +51,17 @@ typedef enum ESP_HF_NETWORK_STATE_AVAILABLE } esp_hf_network_state_t; +/// +CIEV report type +typedef enum { + ESP_HF_IND_TYPE_CALL = 1, /*!< position of call indicator */ + ESP_HF_IND_TYPE_CALLSETUP, /*!< position of callsetup indicator */ + ESP_HF_IND_TYPE_SERVICE, /*!< position of service indicator */ + ESP_HF_IND_TYPE_SIGNAL, /*!< position of signal strength indicator, range: 0-5 */ + ESP_HF_IND_TYPE_ROAM, /*!< position of roaming indicator */ + ESP_HF_IND_TYPE_BATTCHG, /*!< position of battery charge indicator, range: 0-5 */ + ESP_HF_IND_TYPE_CALLHELD /*!< position of callheld indicator */ +} esp_hf_ciev_report_type_t; + /** +CIEV Service type */ typedef enum { @@ -60,7 +71,7 @@ typedef enum /// +CIND call status indicator values typedef enum { - ESP_HF_CALL_STATUS_NO_CALLS = 0, /*!< no call in progress */ + ESP_HF_CALL_STATUS_NO_CALLS = 0, /*!< no call in progress */ ESP_HF_CALL_STATUS_CALL_IN_PROGRESS = 1, /*!< call is present(active or held) */ } esp_hf_call_status_t; diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index 618a0e98464b..6b12ada8ef5d 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -528,6 +528,19 @@ static bt_status_t btc_hf_indchange_notification(bt_bdaddr_t *bd_addr, return BT_STATUS_SUCCESS; } +// +CIEV<...> for device status update, send other indicators, e.g. roaming, battery, call held and bearer +bt_status_t btc_hf_ciev_report(bt_bdaddr_t *bd_addr, tBTA_AG_IND_TYPE indicator, uint16_t value) +{ + int idx = btc_hf_idx_by_bdaddr(bd_addr); + CHECK_HF_INIT(idx); + + if (is_connected(idx, bd_addr)) { + send_indicator_update(indicator, value); + return BT_STATUS_SUCCESS; + } + return BT_STATUS_FAIL; +} + //AT+CIND response static bt_status_t btc_hf_cind_response(bt_bdaddr_t *bd_addr, esp_hf_call_setup_status_t call_status, @@ -1117,6 +1130,12 @@ void btc_hf_call_handler(btc_msg_t *msg) break; } + case BTC_HF_CIEV_REPORT_EVT: + { + btc_hf_ciev_report(&arg->ciev_rep.remote_addr, arg->ciev_rep.ind.type, arg->ciev_rep.ind.value); + break; + } + case BTC_HF_CIND_RESPONSE_EVT: { btc_hf_cind_response(&arg->cind_rep.remote_addr, diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h index 078064fdd05e..d42c69124375 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h @@ -44,6 +44,7 @@ typedef enum BTC_HF_UNAT_RESPONSE_EVT, BTC_HF_CME_ERR_EVT, BTC_HF_IND_NOTIFICATION_EVT, + BTC_HF_CIEV_REPORT_EVT, BTC_HF_CIND_RESPONSE_EVT, BTC_HF_COPS_RESPONSE_EVT, BTC_HF_CLCC_RESPONSE_EVT, @@ -109,6 +110,12 @@ typedef union int signal; } ind_change; + //BTC_HF_CIEV_REPORT_EVT + struct ciev_args { + bt_bdaddr_t remote_addr; + tBTA_AG_IND ind; + } ciev_rep; + //BTC_HF_CIND_RESPONSE_EVT struct cind_args { bt_bdaddr_t remote_addr; diff --git a/components/bt/host/bluedroid/stack/btm/btm_sco.c b/components/bt/host/bluedroid/stack/btm/btm_sco.c index 8431a7d77b69..a45dacb9f86e 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_sco.c +++ b/components/bt/host/bluedroid/stack/btm/btm_sco.c @@ -1033,7 +1033,7 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle, #endif btm_cb.sco_cb.sco_disc_reason = hci_status; - BTM_TRACE_ERROR("%s, handle %x", __FUNCTION__, hci_handle); + BTM_TRACE_API("%s, handle %x", __FUNCTION__, hci_handle); #if (BTM_MAX_SCO_LINKS>0) for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { if (((p->state == SCO_ST_CONNECTING) || diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c index 2b46c33b4835..6daa150dbd87 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c @@ -157,7 +157,10 @@ HF_CMD_HANDLER(ind_change) return 1; } printf("Device Indicator Changed!\n"); - esp_hf_ag_devices_status_indchange(hf_peer_addr, call_state, call_setup_state, ntk_state, signal); + esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_CALL, call_state); + esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_CALLSETUP, call_setup_state); + esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_SERVICE, ntk_state); + esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_SIGNAL, signal); return 0; } From bf77d8755a0e3347c321c1da015d9368703b40bc Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Mon, 21 Aug 2023 17:43:00 +0800 Subject: [PATCH 043/142] fix(bt/bluedroid): Fix the process of sending OK in ATD and COPS cmds --- components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h | 3 +++ components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c | 1 - components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h index 02730e491004..4b04b0dbef2a 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h @@ -620,6 +620,9 @@ esp_err_t esp_hf_ag_reject_call(esp_bd_addr_t remote_addr, int num_active, int n * * @brief Initiate a call from AG. * As a precondition to use this API, Service Level Connection shall exist with HFP client. + * If the AG is driven by the HF to call esp_hf_ag_out_call, it needs to response an OK or ERROR + * to HF. But if the AG is actively calling esp_hf_ag_out_call, it does not need to take a response + * to HF. * * @param[in] remote_addr: remote bluetooth device address * @param[in] num_active: the number of active call diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c index 1a49ad36a72a..1ea646060c56 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c @@ -1522,7 +1522,6 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result) if (p_result->data.ok_flag != BTA_AG_OK_ERROR) { if (p_result->data.str[0] != 0) { bta_ag_send_result(p_scb, code, p_result->data.str, 0); - bta_ag_send_ok(p_scb); } if (p_result->data.ok_flag == BTA_AG_OK_DONE) { bta_ag_send_ok(p_scb); diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index 6b12ada8ef5d..b14e4f8edf96 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -1510,7 +1510,6 @@ void btc_hf_cb_handler(btc_msg_t *msg) param.out_call.num_or_loc = osi_malloc((strlen(p_data->val.str) + 1) * sizeof(char)); sprintf(param.out_call.num_or_loc, "%s", p_data->val.str); btc_hf_cb_to_app(ESP_HF_DIAL_EVT, ¶m); - send_indicator_update(BTA_AG_IND_CALLSETUP,BTA_AG_CALLSETUP_OUTGOING); osi_free(param.out_call.num_or_loc); } else if (event == BTA_AG_AT_BLDN_EVT) { //dial_last memcpy(param.out_call.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t)); From cf52a57b5522548324335a4c23365fc7c1484a11 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Mon, 21 Aug 2023 20:22:54 +0800 Subject: [PATCH 044/142] feat(bt/bluedroid): Modify the btc hf features for AT+NREC cmd in BQB test --- .../btc/profile/std/hf_ag/btc_hf_ag.c | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index b14e4f8edf96..cd74e10f1256 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -71,26 +71,36 @@ static hf_local_param_t *hf_local_param; #if (BTM_WBS_INCLUDED == TRUE) #ifndef BTC_HF_FEATURES -#define BTC_HF_FEATURES ( BTA_AG_FEAT_ECNR | \ - BTA_AG_FEAT_REJECT | \ - BTA_AG_FEAT_ECS | \ - BTA_AG_FEAT_EXTERR | \ - BTA_AG_FEAT_VREC | \ - BTA_AG_FEAT_INBAND | \ - BTA_AG_FEAT_CODEC | \ - BTA_AG_FEAT_ESCO_S4| \ - BTA_AG_FEAT_UNAT) +#define BTC_HF_FEATURES ( BTA_AG_FEAT_ECNR | \ + BTA_AG_FEAT_REJECT | \ + BTA_AG_FEAT_ECS | \ + BTA_AG_FEAT_EXTERR | \ + BTA_AG_FEAT_VREC | \ + BTA_AG_FEAT_INBAND | \ + BTA_AG_FEAT_CODEC | \ + BTA_AG_FEAT_ESCO_S4 | \ + BTA_AG_FEAT_UNAT ) #endif #else #ifndef BTC_HF_FEATURES -#define BTC_HF_FEATURES ( BTA_AG_FEAT_ECNR | \ - BTA_AG_FEAT_REJECT | \ - BTA_AG_FEAT_ECS | \ - BTA_AG_FEAT_EXTERR | \ - BTA_AG_FEAT_VREC | \ - BTA_AG_FEAT_INBAND | \ - BTA_AG_FEAT_ESCO_S4| \ - BTA_AG_FEAT_UNAT) +#if BT_HF_AG_BQB_INCLUDED +#define BTC_HF_FEATURES ( BTA_AG_FEAT_REJECT | \ + BTA_AG_FEAT_ECS | \ + BTA_AG_FEAT_EXTERR | \ + BTA_AG_FEAT_VREC | \ + BTA_AG_FEAT_INBAND | \ + BTA_AG_FEAT_ESCO_S4 | \ + BTA_AG_FEAT_UNAT ) +#else +#define BTC_HF_FEATURES ( BTA_AG_FEAT_ECNR | \ + BTA_AG_FEAT_REJECT | \ + BTA_AG_FEAT_ECS | \ + BTA_AG_FEAT_EXTERR | \ + BTA_AG_FEAT_VREC | \ + BTA_AG_FEAT_INBAND | \ + BTA_AG_FEAT_ESCO_S4 | \ + BTA_AG_FEAT_UNAT ) +#endif /* BT_HF_AG_BQB_INCLUDED */ #endif #endif From 03de9d0cf74ff9120d53a97ff965121115021223 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Mon, 21 Aug 2023 17:35:43 +0800 Subject: [PATCH 045/142] feat(bt/bluedroid): Add flag to send BRSF features for hfp ag BQB test --- .../bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c | 29 ++++++++++++++++++- .../bluedroid/bta/hf_ag/include/bta_ag_int.h | 26 +++++++++++------ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c index 1ea646060c56..6bccfe1b7ea8 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c @@ -36,6 +36,9 @@ #include "stack/port_api.h" #include "bta/utl.h" +#if BT_HF_AG_BQB_INCLUDED +static BOOLEAN s_bta_hf_ag_bqb_brsf_flag = false; +#endif /* BT_HF_AG_BQB_INCLUDED */ #if (BTA_AG_INCLUDED == TRUE) /***************************************************************************** @@ -338,6 +341,22 @@ const UINT8 bta_ag_callsetup_ind_tbl[] = #define COLON_IDX_4_VGSVGM 4 #endif +/******************************************************************************* +** +** Function bta_hf_ag_bqb_brsf_ctrl +** +** Description Control the usage of BTA_AG_BQB_BRSF_FEAT_SPEC for BQB test +** +** Returns void +** +*******************************************************************************/ +#if BT_HF_AG_BQB_INCLUDED +void bta_hf_ag_bqb_brsf_ctrl(BOOLEAN enable) +{ + s_bta_hf_ag_bqb_brsf_flag = enable; +} +#endif /* BT_HF_AG_BQB_INCLUDED */ + /******************************************* * Funcitons Result ********************************************/ @@ -1025,7 +1044,15 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, /* store peer features */ p_scb->peer_features = (UINT16) int_arg; /* send BRSF, send OK */ - bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL, (INT16) (p_scb->features & BTA_AG_BSRF_FEAT_SPEC)); +#if BT_HF_AG_BQB_INCLUDED + if (s_bta_hf_ag_bqb_brsf_flag == true) { + bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL, (INT16) (p_scb->features & BTA_AG_BQB_BRSF_FEAT_SPEC)); + } else { + bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL, (INT16) (p_scb->features & BTA_AG_BRSF_FEAT_SPEC)); + } +#else + bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL, (INT16) (p_scb->features & BTA_AG_BRSF_FEAT_SPEC)); +#endif /* BT_HF_AG_BQB_INCLUDED */ bta_ag_send_ok(p_scb); break; } diff --git a/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h b/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h index 61e7948ecc5d..9ced8b366501 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h +++ b/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h @@ -76,16 +76,24 @@ #define BTA_AG_ACP 0 /* accepted connection */ #define BTA_AG_INT 1 /* initiating connection */ +#if BT_HF_AG_BQB_INCLUDED +/* feature mask that matches spec for BQB test */ +#define BTA_AG_BQB_BRSF_FEAT_SPEC (BTA_AG_FEAT_VOIP | \ + BTA_AG_FEAT_VTAG | BTA_AG_FEAT_CODEC | \ + BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \ + BTA_AG_FEAT_ESCO_S4 | BTA_AG_FEAT_EXTERR) +#endif /* BT_HF_AG_BQB_INCLUDED */ + /* feature mask that matches spec */ -#define BTA_AG_BSRF_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \ - BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \ - BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \ - BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \ - BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \ - BTA_AG_FEAT_ESCO_S4| BTA_AG_FEAT_VOIP) - -#define BTA_AG_SDP_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \ - BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \ +#define BTA_AG_BRSF_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \ + BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \ + BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \ + BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \ + BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \ + BTA_AG_FEAT_ESCO_S4 | BTA_AG_FEAT_VOIP) + +#define BTA_AG_SDP_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \ + BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \ BTA_AG_FEAT_VTAG) enum From c5fa755251282e15f0e776d3f1a0dbda89f2553b Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Fri, 18 Aug 2023 15:50:15 +0800 Subject: [PATCH 046/142] feat(bt/bluedroid): Add eSCO S1 support for hfp client BQB test --- .../bta/hf_client/bta_hf_client_sco.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c index e4fe45c8c4c3..d464a8892534 100644 --- a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c +++ b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c @@ -29,6 +29,10 @@ #include "hci/hci_audio.h" #endif +#if BT_HF_CLIENT_BQB_INCLUDED +static BOOLEAN s_bta_hf_client_bqb_esco_s1_flag = false; +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ + #if (BTA_HF_INCLUDED == TRUE) #define BTA_HF_CLIENT_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \ BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \ @@ -39,6 +43,7 @@ #define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3 1 /* eSCO setting for CVSD S3 */ #define BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2 2 /* eSCO setting for mSBC T2 */ #define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4 3 /* eSCO setting for CVSD S4 */ +#define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S1 4 /* eSCO setting for CVSD S1 */ static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = { /* SCO CVSD */ @@ -91,7 +96,23 @@ static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = { BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), .retrans_effort = BTM_ESCO_RETRANS_QUALITY, + }, + /* ESCO CVSD S1 */ +#if BT_HF_CLIENT_BQB_INCLUDED + { + .rx_bw = BTM_64KBITS_RATE, + .tx_bw = BTM_64KBITS_RATE, + .max_latency = 7, + .voice_contfmt = BTM_VOICE_SETTING_CVSD, + /* Packet Types : EV3 */ + .packet_types = (HCI_ESCO_PKT_TYPES_MASK_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), + .retrans_effort = BTM_ESCO_RETRANS_POWER, } +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ }; enum { @@ -106,6 +127,22 @@ enum { #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */ }; +/******************************************************************************* +** +** Function bta_hf_client_bqb_esco_s1_ctrl +** +** Description Control the usage of CVSD eSCO S1 parameter for BQB test +** +** Returns void +** +*******************************************************************************/ +#if BT_HF_CLIENT_BQB_INCLUDED +void bta_hf_client_bqb_esco_s1_ctrl(BOOLEAN enable) +{ + s_bta_hf_client_bqb_esco_s1_flag = enable; +} +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ + static void bta_hf_client_sco_event(UINT8 event); /******************************************************************************* ** @@ -214,6 +251,11 @@ static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data) (bta_hf_client_cb.scb.features && BTA_HF_CLIENT_FEAT_ESCO_S4) && (bta_hf_client_cb.scb.peer_features && BTA_HF_CLIENT_PEER_ESCO_S4)) { index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4; +#if BT_HF_CLIENT_BQB_INCLUDED + if (s_bta_hf_client_bqb_esco_s1_flag == true) { + index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S1; + } +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ } else if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) { index = BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2; } From a481a1553ddda91d44b3164b6b40f50639beeb23 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Mon, 21 Aug 2023 17:39:41 +0800 Subject: [PATCH 047/142] feat(bt/bluedroid): Add flag to change HFP client features for BQB test --- .../btc/profile/std/hf_client/btc_hf_client.c | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c b/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c index 1ed961875833..3909a4c6f6b1 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c @@ -28,6 +28,10 @@ #include "esp_bt.h" #include +#if BT_HF_CLIENT_BQB_INCLUDED +static BOOLEAN s_bta_hf_client_bqb_esco_s4_flag = false; +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ + #if (BTC_HF_CLIENT_INCLUDED == TRUE) /************************************************************************************ @@ -54,6 +58,21 @@ #endif +/******************************************************************************* +** +** Function bta_hf_client_bqb_esco_s4_ctrl +** +** Description Control the usage of BTA_HF_CLIENT_FEAT_ESCO_S4 for BQB test +** +** Returns void +** +*******************************************************************************/ +#if BT_HF_CLIENT_BQB_INCLUDED +void bta_hf_client_bqb_esco_s4_ctrl(BOOLEAN enable) +{ + s_bta_hf_client_bqb_esco_s4_flag = enable; +} +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ /************************************************************************************ ** Static variables @@ -743,6 +762,11 @@ bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable) if (btc_hf_client_version >= HFP_HF_VERSION_1_7) { hf_client_local_param.btc_hf_client_features |= BTA_HF_CLIENT_FEAT_ESCO_S4; +#if BT_HF_CLIENT_BQB_INCLUDED + if (s_bta_hf_client_bqb_esco_s4_flag == true) { + hf_client_local_param.btc_hf_client_features = BTA_HF_CLIENT_FEAT_ESCO_S4; + } +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ BTC_TRACE_EVENT("eSCO S4 Setting Supported"); } From 8b1c5d3a6ad6a5f6f84c7068cd6c63e4df22e4dc Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Mon, 21 Aug 2023 17:37:23 +0800 Subject: [PATCH 048/142] feat(bt/bluedroid): Add flag to control whether to send AT+CLIP cmd for BQB test --- .../bta/hf_client/bta_hf_client_main.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) 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 1716f96ba139..4124a10f30bd 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 @@ -25,6 +25,10 @@ #include "bta/bta_hf_client_api.h" #include "bta_hf_client_int.h" +#if BT_HF_CLIENT_BQB_INCLUDED +static BOOLEAN s_bta_hf_client_bqb_clip_flag = TRUE; +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ + #if (BTA_HF_INCLUDED == TRUE) /* uncomment to enable extra debug */ /* #define BTA_HF_CLIENT_DEBUG TRUE */ @@ -247,6 +251,21 @@ tBTA_HF_CLIENT_CB bta_hf_client_cb; tBTA_HF_CLIENT_CB *bta_hf_client_cb_ptr; #endif +/******************************************************************************* +** +** Function bta_hf_client_bqb_clip_ctrl +** +** Description Control if send the command AT+CLIP for BQB test +** +** Returns void +** +*******************************************************************************/ +#if BT_HF_CLIENT_BQB_INCLUDED +void bta_hf_client_bqb_clip_ctrl(BOOLEAN enable) +{ + s_bta_hf_client_bqb_clip_flag = enable; +} +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ /******************************************************************************* ** @@ -538,7 +557,14 @@ static void send_post_slc_cmd(void) bta_hf_client_send_at_cmee(TRUE); bta_hf_client_send_at_cops(FALSE); bta_hf_client_send_at_btrh(TRUE, 0); + +#if BT_HF_CLIENT_BQB_INCLUDED + if (s_bta_hf_client_bqb_clip_flag == TRUE) { + bta_hf_client_send_at_clip(TRUE); + } +#else bta_hf_client_send_at_clip(TRUE); +#endif /* BT_HF_CLIENT_BQB_INCLUDED */ } /******************************************************************************* From f0e90b296a82e1a574c8f7ad73539f18a348c1e9 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Fri, 25 Aug 2023 11:18:49 +0800 Subject: [PATCH 049/142] fix(bt/bluedroid): Revise the description for index in esp_hf_ag_clcc_response and correct the error return in btc_hf_indchange_notification 1: modify the description of param index in function esp_hf_ag_clcc_response. 2: fix the error code return of function btc_hf_indchange_notification. --- components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h | 2 +- components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h index 4b04b0dbef2a..4ce0096b09a1 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h @@ -520,7 +520,7 @@ esp_err_t esp_hf_ag_cops_response(esp_bd_addr_t remote_addr, char *name); * As a precondition to use this API, Service Level Connection shall exist with HFP client. * * @param[in] remote_addr: remote bluetooth device address - * @param[in] index: the index of current call + * @param[in] index: the index of current call, starting with 1, finishing response with 0 (send OK) * @param[in] dir: call direction (incoming/outgoing) * @param[in] current_call_state: current call state * @param[in] mode: current call mode (voice/data/fax) diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index cd74e10f1256..8ababa1c6fc4 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -535,7 +535,7 @@ static bt_status_t btc_hf_indchange_notification(bt_bdaddr_t *bd_addr, send_indicator_update(BTA_AG_IND_SIGNAL, signal); return BT_STATUS_SUCCESS; } - return BT_STATUS_SUCCESS; + return BT_STATUS_FAIL; } // +CIEV<...> for device status update, send other indicators, e.g. roaming, battery, call held and bearer From 12abb32a6e07e891ed5caf9f70fec10978d03909 Mon Sep 17 00:00:00 2001 From: "wanglai@espressif.com" Date: Fri, 25 Aug 2023 12:02:08 +0800 Subject: [PATCH 050/142] fix(bt/bluedroid): Modify the operator name to English in hfp_ag example --- .../bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c index a83c1e39bb99..05b75588d467 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -85,9 +85,9 @@ const char *c_volume_control_target_str[] = { // esp_hf_subscriber_service_type_t char *c_operator_name_str[] = { - "中国移动", - "中国联通", - "中国电信", + "China Mobile", + "China Unicom", + "China Telecom", }; // esp_hf_subscriber_service_type_t From 6fd3667ab103e8811bac2e7b954fffd1fb65c159 Mon Sep 17 00:00:00 2001 From: Euripedes Rocha Date: Mon, 25 Sep 2023 08:04:48 +0200 Subject: [PATCH 051/142] change(mqtt): Update submodule to e6afdb Update submodule: git log --oneline 05b347643f6679cc60a50a9664b86a24ebf3ae10..e6afdb4025fe018ae0add44e3c45249ea1974774 Detailed description of the changes: * fix: using return value of asprintf now - See merge request espressif/esp-mqtt!192 - See commit https://github.com/espressif/esp-mqtt/commit/c0b40b1 * fix: Uses caps allocation for data buffer instead of item struct - See merge request espressif/esp-mqtt!193 - See commit https://github.com/espressif/esp-mqtt/commit/00ee059 --- components/mqtt/esp-mqtt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mqtt/esp-mqtt b/components/mqtt/esp-mqtt index 05b347643f66..e6afdb4025fe 160000 --- a/components/mqtt/esp-mqtt +++ b/components/mqtt/esp-mqtt @@ -1 +1 @@ -Subproject commit 05b347643f6679cc60a50a9664b86a24ebf3ae10 +Subproject commit e6afdb4025fe018ae0add44e3c45249ea1974774 From 150900eabbea03ce6e6691d0816de12a664a4f1a Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Fri, 22 Sep 2023 16:14:01 +0800 Subject: [PATCH 052/142] feat: add config to disable ble hci uart flow control --- components/bt/controller/esp32/Kconfig.in | 5 +++++ components/bt/controller/esp32/bt.c | 9 ++++++++- .../main/controller_hci_uart_demo.c | 2 +- .../main/Kconfig.projbuild | 6 ++++++ .../main/main.c | 13 ++++++++++++- 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/components/bt/controller/esp32/Kconfig.in b/components/bt/controller/esp32/Kconfig.in index f9a505cf2561..f31094116c44 100644 --- a/components/bt/controller/esp32/Kconfig.in +++ b/components/bt/controller/esp32/Kconfig.in @@ -205,6 +205,11 @@ menu "HCI UART(H4) Options" help UART Baudrate for HCI. Please use standard baudrate. + config BTDM_CTRL_HCI_UART_FLOW_CTRL_EN + bool "Enable UART flow control" + depends on BTDM_CTRL_HCI_MODE_UART_H4 + default y + endmenu menu "MODEM SLEEP Options" diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index 64a08dc6e23b..e20fa81430b8 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -221,6 +221,7 @@ extern void btdm_controller_scan_duplicate_list_clear(void); /* Shutdown */ extern void esp_bt_controller_shutdown(void); extern void sdk_config_set_bt_pll_track_enable(bool enable); +extern void sdk_config_set_uart_flow_ctrl_enable(bool enable); extern char _bss_start_btdm; extern char _bss_end_btdm; @@ -1527,6 +1528,12 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); #endif +#if CONFIG_BTDM_CTRL_HCI_UART_FLOW_CTRL_EN + sdk_config_set_uart_flow_ctrl_enable(true); +#else + sdk_config_set_uart_flow_ctrl_enable(false); +#endif + #ifdef CONFIG_PM_ENABLE if (!s_btdm_allow_light_sleep) { if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { diff --git a/examples/bluetooth/hci/controller_hci_uart_esp32/main/controller_hci_uart_demo.c b/examples/bluetooth/hci/controller_hci_uart_esp32/main/controller_hci_uart_demo.c index d4459a8d3355..7684b7aa69c4 100644 --- a/examples/bluetooth/hci/controller_hci_uart_esp32/main/controller_hci_uart_demo.c +++ b/examples/bluetooth/hci/controller_hci_uart_esp32/main/controller_hci_uart_demo.c @@ -25,7 +25,7 @@ static void uart_gpio_reset(void) periph_module_enable(PERIPH_UHCI0_MODULE); #ifdef CONFIG_BTDM_CTRL_HCI_UART_NO - ESP_LOGI(tag, "HCI UART%d Pin select: TX 5, RX 18, CTS 23, RTS 19", CONFIG_BTDM_CTRL_HCI_UART_NO); + ESP_LOGI(tag, "HCI UART%d Pin select: TX 5, RX 18, CTS 23, RTS 19 Baudrate:%d", CONFIG_BTDM_CTRL_HCI_UART_NO, CONFIG_BTDM_CTRL_HCI_UART_BAUDRATE); uart_set_pin(CONFIG_BTDM_CTRL_HCI_UART_NO, 5, 18, 19, 23); #endif diff --git a/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/Kconfig.projbuild b/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/Kconfig.projbuild index 395e8bef94eb..0912aa239a48 100644 --- a/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/Kconfig.projbuild +++ b/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/Kconfig.projbuild @@ -7,4 +7,10 @@ menu "Example Configuration" help UART Baudrate for HCI. Please use standard baudrate. + config EXAMPLE_HCI_UART_FLOW_CTRL_ENABLE + bool "Enable HCI UART flow control" + default y + help + Enable/disable HCI UART flow control + endmenu diff --git a/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/main.c b/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/main.c index 8bef0692b55a..3ac6e29fb279 100644 --- a/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/main.c +++ b/examples/bluetooth/hci/controller_hci_uart_esp32c3_and_esp32s3/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -29,6 +29,12 @@ static const char *tag = "UHCI"; #define GPIO_OUTPUT_PIN_SEL ((1ULL< Date: Fri, 15 Sep 2023 17:25:10 +0530 Subject: [PATCH 053/142] fix(bootloader_support): Fix condition for SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT Fix the condition to verify the image when SECURE_SIGNED_APPS_ECDSA_V2_SCHEME and SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT are selected. --- components/bootloader_support/src/secure_boot.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/bootloader_support/src/secure_boot.c b/components/bootloader_support/src/secure_boot.c index 5e9b8832fccb..9015bdfd5abe 100644 --- a/components/bootloader_support/src/secure_boot.c +++ b/components/bootloader_support/src/secure_boot.c @@ -144,9 +144,9 @@ static esp_err_t secure_boot_v2_check(bool *need_fix) #endif #endif // CONFIG_SECURE_BOOT -#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT +#if (CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT -static void rsa_check_signature_on_update_check(void) +static void check_signature_on_update_check(void) { // We rely on the keys used to sign this app to verify the next app on OTA, so make sure there is at // least one to avoid a stuck firmware @@ -164,7 +164,7 @@ static void rsa_check_signature_on_update_check(void) } #endif } -#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT +#endif // (CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT void esp_secure_boot_init_checks(void) { @@ -184,9 +184,9 @@ void esp_secure_boot_init_checks(void) #endif // CONFIG_SECURE_BOOT -#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT - rsa_check_signature_on_update_check(); -#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT +#if (CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + check_signature_on_update_check(); +#endif // (CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT } From 7c2df01af2db184ef10b9bd7e5daf92bf9f0ab06 Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Mon, 18 Sep 2023 17:38:09 +0530 Subject: [PATCH 054/142] fix(bootloader): Update kconfig option --- components/bootloader/Kconfig.projbuild | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index d376f4f1a249..b1c291c624f1 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -709,14 +709,12 @@ menu "Security features" config SECURE_BOOT_VERIFICATION_KEY string "Secure boot public signature verification key" - depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES && !SECURE_SIGNED_APPS_RSA_SCHEME + depends on SECURE_SIGNED_APPS && SECURE_SIGNED_APPS_ECDSA_SCHEME && !SECURE_BOOT_BUILD_SIGNED_BINARIES default "signature_verification_key.bin" help Path to a public key file used to verify signed images. Secure Boot V1: This ECDSA public key is compiled into the bootloader and/or app, to verify app images. - Secure Boot V2: This RSA public key is compiled into the signature block at - the end of the bootloader/app. Key file is in raw binary format, and can be extracted from a PEM formatted private key using the espsecure.py From 7d98bdd495efae8af993330a3059f059250cf1ba Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Mon, 18 Sep 2023 17:53:43 +0530 Subject: [PATCH 055/142] feat: Add test app to verify SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT Add a test app to verify the working of the application when SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT is selected in the menuconfig and the application is not signed --- tools/test_apps/.build-test-rules.yml | 6 ++++++ .../signed_app_no_secure_boot/CMakeLists.txt | 7 +++++++ .../security/signed_app_no_secure_boot/README.md | 11 +++++++++++ .../signed_app_no_secure_boot/main/CMakeLists.txt | 2 ++ .../signed_app_no_secure_boot/main/main.c | 15 +++++++++++++++ .../pytest_signed_app_no_secure_boot.py | 12 ++++++++++++ .../signed_app_no_secure_boot/sdkconfig.defaults | 8 ++++++++ 7 files changed, 61 insertions(+) create mode 100644 tools/test_apps/security/signed_app_no_secure_boot/CMakeLists.txt create mode 100644 tools/test_apps/security/signed_app_no_secure_boot/README.md create mode 100644 tools/test_apps/security/signed_app_no_secure_boot/main/CMakeLists.txt create mode 100644 tools/test_apps/security/signed_app_no_secure_boot/main/main.c create mode 100644 tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py create mode 100644 tools/test_apps/security/signed_app_no_secure_boot/sdkconfig.defaults diff --git a/tools/test_apps/.build-test-rules.yml b/tools/test_apps/.build-test-rules.yml index 39cadd6f2a2e..e41802b864ad 100644 --- a/tools/test_apps/.build-test-rules.yml +++ b/tools/test_apps/.build-test-rules.yml @@ -68,6 +68,12 @@ tools/test_apps/security/secure_boot: - if: IDF_ENV_FPGA != 1 reason: the test can only run on an FPGA as efuses need to be reset during the test. +tools/test_apps/security/signed_app_no_secure_boot: + enable: + - if: IDF_TARGET in ["esp32c2", "esp32c3"] + temporary: true + reason: No need to test on all targets + tools/test_apps/system/bootloader_sections: disable: - if: IDF_TARGET == "esp32c2" diff --git a/tools/test_apps/security/signed_app_no_secure_boot/CMakeLists.txt b/tools/test_apps/security/signed_app_no_secure_boot/CMakeLists.txt new file mode 100644 index 000000000000..09d112f667b1 --- /dev/null +++ b/tools/test_apps/security/signed_app_no_secure_boot/CMakeLists.txt @@ -0,0 +1,7 @@ +# 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.16) + +# Secure Boot not currently supported for ESP32-S2 +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(secure_boot) diff --git a/tools/test_apps/security/signed_app_no_secure_boot/README.md b/tools/test_apps/security/signed_app_no_secure_boot/README.md new file mode 100644 index 000000000000..7a2105fef335 --- /dev/null +++ b/tools/test_apps/security/signed_app_no_secure_boot/README.md @@ -0,0 +1,11 @@ +| Supported Targets | ESP32-C2 | ESP32-C3 | +| ----------------- | -------- | -------- | + +# Secure Signed On Update No Secure Boot + +This examples verifies the case when CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT is selected and application is not signed. The application should abort its execution with the logs: + +``` +secure_boot_v2: No signatures were found for the running app +secure_boot: This app is not signed, but check signature on update is enabled in config. It won't be possible to verify any update. +``` \ No newline at end of file diff --git a/tools/test_apps/security/signed_app_no_secure_boot/main/CMakeLists.txt b/tools/test_apps/security/signed_app_no_secure_boot/main/CMakeLists.txt new file mode 100644 index 000000000000..cf2c455cb50e --- /dev/null +++ b/tools/test_apps/security/signed_app_no_secure_boot/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/tools/test_apps/security/signed_app_no_secure_boot/main/main.c b/tools/test_apps/security/signed_app_no_secure_boot/main/main.c new file mode 100644 index 000000000000..b49cdd1ee815 --- /dev/null +++ b/tools/test_apps/security/signed_app_no_secure_boot/main/main.c @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define TAG "example_secure_boot" + +void app_main(void) +{ + printf("\nExample for secured signed with no secure boot\n"); +} diff --git a/tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py b/tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py new file mode 100644 index 000000000000..686b7cdedaaf --- /dev/null +++ b/tools/test_apps/security/signed_app_no_secure_boot/pytest_signed_app_no_secure_boot.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32c2 +@pytest.mark.esp32c3 +@pytest.mark.generic +def test_examples_security_on_update_no_secure_boot(dut: Dut) -> None: + dut.expect("This app is not signed, but check signature on update is enabled in config. It won't be possible to verify any update.", timeout=10) diff --git a/tools/test_apps/security/signed_app_no_secure_boot/sdkconfig.defaults b/tools/test_apps/security/signed_app_no_secure_boot/sdkconfig.defaults new file mode 100644 index 000000000000..2bab812218d6 --- /dev/null +++ b/tools/test_apps/security/signed_app_no_secure_boot/sdkconfig.defaults @@ -0,0 +1,8 @@ +CONFIG_SECURE_SIGNED_ON_UPDATE=y +CONFIG_SECURE_SIGNED_APPS=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT=y +CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT=y +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set From 96a8316e71d1ac691fd858d9fc93e37eb6e03f38 Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Fri, 8 Sep 2023 14:03:04 +0530 Subject: [PATCH 056/142] feat(esp_http_client): Add API to set auth data This new API can be used to set the authentication data in the client context when the auth data is received in the custom header Closes: https://github.com/espressif/esp-idf/pull/12131 --- components/esp_http_client/esp_http_client.c | 9 +++++++++ .../esp_http_client/include/esp_http_client.h | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 61faf2135735..feb3891af0e2 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -1645,6 +1645,15 @@ esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_h } } +esp_err_t esp_http_client_set_auth_data(esp_http_client_handle_t client, const char *auth_data, int len) +{ + if (client == NULL || auth_data == NULL || len <= 0) { + return ESP_ERR_INVALID_ARG; + } + http_utils_append_string(&client->auth_header, auth_data, len); + return ESP_OK; +} + void esp_http_client_add_auth(esp_http_client_handle_t client) { if (client == NULL) { diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index c125c9d468d1..6135976d5689 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -600,6 +600,21 @@ esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_h */ esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client); +/** + * @brief On receiving a custom authentication header, this API can be invoked to set the + * authentication information from the header. This API can be called from the event + * handler. + * + * @param[in] client The esp_http_client handle + * @param[in] auth_data The authentication data received in the header + * @param[in] len length of auth_data. + * + * @return + * - ESP_ERR_INVALID_ARG + * - ESP_OK + */ +esp_err_t esp_http_client_set_auth_data(esp_http_client_handle_t client, const char *auth_data, int len); + /** * @brief On receiving HTTP Status code 401, this API can be invoked to add authorization * information. From 04ac8e43dbaf37e42452fef034606ae3f04e644b Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Mon, 11 Sep 2023 17:48:42 +0530 Subject: [PATCH 057/142] fix(esp_http_client): Call event_handler after header value is received --- components/esp_http_client/esp_http_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index feb3891af0e2..460470a1f8c7 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -233,7 +233,6 @@ static int http_on_header_event(esp_http_client_handle_t client) static int http_on_header_field(http_parser *parser, const char *at, size_t length) { esp_http_client_t *client = parser->data; - http_on_header_event(client); http_utils_append_string(&client->current_header_key, at, length); return 0; @@ -254,6 +253,7 @@ static int http_on_header_value(http_parser *parser, const char *at, size_t leng http_utils_append_string(&client->auth_header, at, length); } http_utils_append_string(&client->current_header_value, at, length); + http_on_header_event(client); return 0; } From 40cfacabab6d33dc5dafa0ba873ef4e4fe5bd0f2 Mon Sep 17 00:00:00 2001 From: Linda Date: Fri, 22 Sep 2023 14:38:55 +0800 Subject: [PATCH 058/142] docs: update arguments of REG_SET_BITS --- docs/en/migration-guides/release-5.x/5.0/peripherals.rst | 4 ++-- docs/zh_CN/migration-guides/release-5.x/5.0/peripherals.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/migration-guides/release-5.x/5.0/peripherals.rst b/docs/en/migration-guides/release-5.x/5.0/peripherals.rst index 9cad8b120f36..c56238cdf53f 100644 --- a/docs/en/migration-guides/release-5.x/5.0/peripherals.rst +++ b/docs/en/migration-guides/release-5.x/5.0/peripherals.rst @@ -537,7 +537,7 @@ Register Access Macros Previously, all register access macros could be used as expressions, so the following was allowed:: - uint32_t val = REG_SET_BITS(reg, mask); + uint32_t val = REG_SET_BITS(reg, bits, mask); In ESP-IDF v5.0, register access macros which write or read-modify-write the register can no longer be used as expressions, and can only be used as statements. This applies to the following macros: ``REG_WRITE``, ``REG_SET_BIT``, ``REG_CLR_BIT``, ``REG_SET_BITS``, ``REG_SET_FIELD``, ``WRITE_PERI_REG``, ``CLEAR_PERI_REG_MASK``, ``SET_PERI_REG_MASK``, ``SET_PERI_REG_BITS``. @@ -548,5 +548,5 @@ To store the value which would have been written into the register, split the op To get the value of the register after modification (which may be different from the value written), add an explicit read:: - REG_SET_BITS(reg, mask); + REG_SET_BITS(reg, bits, mask); uint32_t new_val = REG_READ(reg); diff --git a/docs/zh_CN/migration-guides/release-5.x/5.0/peripherals.rst b/docs/zh_CN/migration-guides/release-5.x/5.0/peripherals.rst index 93861e866ead..adb3f3d43317 100644 --- a/docs/zh_CN/migration-guides/release-5.x/5.0/peripherals.rst +++ b/docs/zh_CN/migration-guides/release-5.x/5.0/peripherals.rst @@ -537,7 +537,7 @@ LCD 更新前,所有用于访问寄存器的宏都可以作为表达式来使用,所以以下命令是允许的:: - uint32_t val = REG_SET_BITS(reg, mask); + uint32_t val = REG_SET_BITS(reg, bits, mask); 在 ESP-IDF v5.0 中,用于写入或读取-修改-写入寄存器的宏不能再作为表达式使用,而只能作为语句使用,这适用于以下宏: ``REG_WRITE``, ``REG_SET_BIT``, ``REG_CLR_BIT``, ``REG_SET_BITS``, ``REG_SET_FIELD``, ``WRITE_PERI_REG``, ``CLEAR_PERI_REG_MASK``, ``SET_PERI_REG_MASK``, ``SET_PERI_REG_BITS``。 @@ -548,5 +548,5 @@ LCD 要获得修改后的寄存器的值(该值可能与写入的值不同),要增加一个显示的读取命令:: - REG_SET_BITS(reg, mask); + REG_SET_BITS(reg, bits, mask); uint32_t new_val = REG_READ(reg); From 9eddc6c4c6ab64b4d3e47d9b12cab46c9a55b138 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Mon, 25 Sep 2023 16:36:34 +0800 Subject: [PATCH 059/142] fix(openthread): update openthread_br lib --- components/openthread/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/openthread/lib b/components/openthread/lib index 64c77643c92b..12f563ee4902 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 64c77643c92b76fff36bd13211f6b821c4beb8ef +Subproject commit 12f563ee490236f7332eb22f568e71c7c1d4a3b7 From 76aca4cc8af73566a9b18f412a27cb87956682fc Mon Sep 17 00:00:00 2001 From: "chaijie@espressif.com" Date: Fri, 15 Sep 2023 19:21:58 +0800 Subject: [PATCH 060/142] fix(sleep): fix inproper sleep vol param for esp32c6 & esp32h2 --- .../esp_hw_support/port/esp32c6/pmu_param.c | 34 ++-- .../esp_hw_support/port/esp32c6/pmu_sleep.c | 34 ++-- .../port/esp32c6/private_include/pmu_param.h | 152 +++++++++--------- .../esp_hw_support/port/esp32h2/pmu_param.c | 34 ++-- .../esp_hw_support/port/esp32h2/pmu_sleep.c | 35 ++-- .../port/esp32h2/private_include/pmu_param.h | 127 ++++++++------- 6 files changed, 194 insertions(+), 222 deletions(-) diff --git a/components/esp_hw_support/port/esp32c6/pmu_param.c b/components/esp_hw_support/port/esp32c6/pmu_param.c index 6d2d818419d3..6e0a8ea8cbc6 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_param.c +++ b/components/esp_hw_support/port/esp32c6/pmu_param.c @@ -209,8 +209,8 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ .xpd = 1, \ - .slp_mem_dbias = 0xc, \ - .slp_logic_dbias = 0xc, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ .dbias = 0x19 \ }, \ .regulator1 = { \ @@ -229,8 +229,8 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ .xpd = 1, \ - .slp_mem_dbias = 0xc, \ - .slp_logic_dbias = 0xc, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ .dbias = 0x1a \ }, \ .regulator1 = { \ @@ -246,12 +246,12 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .bias_sleep = 0 \ }, \ .regulator0 = { \ - .slp_mem_xpd = 1, \ - .slp_logic_xpd = 1, \ - .xpd = 0, \ - .slp_mem_dbias = 0x4, \ - .slp_logic_dbias = 0x4, \ - .dbias = 0x1a \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .xpd = 1, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .dbias = 1 \ }, \ .regulator1 = { \ .drv_b = 0x0 \ @@ -404,8 +404,8 @@ const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mod .regulator0 = { \ .slp_xpd = 0, \ .xpd = 1, \ - .slp_dbias = 0x0, \ - .dbias = 0x1a \ + .slp_dbias = 0, \ + .dbias = LP_CALI_DBIAS \ }, \ .regulator1 = { \ .drv_b = 0x0 \ @@ -415,15 +415,15 @@ const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mod #define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ .bias = { \ .xpd_bias = 0, \ - .dbg_atten = 0x0, \ + .dbg_atten = 0, \ .pd_cur = 1, \ .bias_sleep = 1, \ }, \ .regulator0 = { \ - .slp_xpd = 1, \ - .xpd = 0, \ - .slp_dbias = 0x0, \ - .dbias = 0x12 \ + .slp_xpd = 0, \ + .xpd = 1, \ + .slp_dbias = 0, \ + .dbias = 12 \ }, \ .regulator1 = { \ .drv_b = 0x0 \ diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index dfb63c9ff3e6..cdeeb43fa906 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -16,6 +16,7 @@ #include "soc/pmu_struct.h" #include "hal/lp_aon_hal.h" #include "esp_private/esp_pmu.h" +#include "pmu_param.h" #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) @@ -155,6 +156,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period); if (dslp) { + config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period); pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags); config->analog = analog_default; } else { @@ -162,21 +164,15 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->digital = digital_default; pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags); - if (!(pd_flags & PMU_SLEEP_PD_TOP) || !(pd_flags & PMU_SLEEP_PD_MODEM)){ - analog_default.hp_sys.analog.xpd = 1; - analog_default.hp_sys.analog.dbias = 2; - } if (!(pd_flags & PMU_SLEEP_PD_XTAL)){ - analog_default.hp_sys.analog.xpd = 1; - analog_default.hp_sys.analog.pd_cur = 0; - analog_default.hp_sys.analog.bias_sleep = 0; - analog_default.hp_sys.analog.dbias = 25; - - analog_default.lp_sys[LP(SLEEP)].analog.xpd = 1; - analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = 0; - analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = 0; - analog_default.lp_sys[LP(SLEEP)].analog.dbias = 26; + analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON; + analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON; + analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS; + + analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON; + analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON; + analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_DBIAS; } config->analog = analog_default; @@ -206,25 +202,17 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp) { assert(ctx->hal); + pmu_ll_hp_set_dbg_atten (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbg_atten); pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur); pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep); - pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd); - pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd); pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd); - pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_dbias); - pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias); pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b); - pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_xpd); - pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias); - pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.xpd); - pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias); - pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b); - pmu_ll_lp_set_dbg_atten (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbg_atten); pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur); pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep); + pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_xpd); pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd); pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_dbias); pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias); diff --git a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h index 2608204a7acf..f340c5ca05d0 100644 --- a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h @@ -16,6 +16,37 @@ extern "C" { #endif +#define HP_CALI_DBIAS 25 +#define LP_CALI_DBIAS 26 + +// FOR XTAL FORCE PU IN SLEEP +#define PMU_PD_CUR_SLEEP_ON 0 +#define PMU_BIASSLP_SLEEP_ON 0 + +// FOR BOTH LIGHTSLEEP & DEEPSLEEP +#define PMU_PD_CUR_SLEEP_DEFAULT 1 +#define PMU_BIASSLP_SLEEP_DEFAULT 1 +#define PMU_LP_XPD_SLEEP_DEFAULT 1 +#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0 +#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0 + +// FOR LIGHTSLEEP +#define PMU_HP_DRVB_LIGHTSLEEP 0 +#define PMU_LP_DRVB_LIGHTSLEEP 0 +#define PMU_HP_XPD_LIGHTSLEEP 1 + +#define PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT 0 +#define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1 +#define PMU_LP_DBIAS_LIGHTSLEEP_0V7 12 + +// FOR DEEPSLEEP +#define PMU_DBG_HP_DEEPSLEEP 0 +#define PMU_HP_XPD_DEEPSLEEP 0 +#define PMU_LP_DRVB_DEEPSLEEP 0 + +#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12 +#define PMU_LP_DBIAS_DEEPSLEEP_0V7 23 + typedef struct { pmu_hp_dig_power_reg_t dig_power; pmu_hp_clk_power_reg_t clk_power; @@ -211,6 +242,7 @@ typedef struct { #define PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ #define PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ +#define PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US (500) /* Slow OSC as PMU slow clock source in deepsleep is about 500 us */ typedef struct { struct { @@ -293,84 +325,52 @@ typedef struct { } lp_sys[PMU_MODE_LP_MAX]; } pmu_sleep_analog_config_t; -#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ - .hp_sys = { \ - .analog = { \ - .xpd_bias = 0, \ - .dbg_atten = 0, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .slp_mem_xpd = 1, \ - .slp_logic_xpd = 1, \ - .slp_mem_dbias = 4, \ - .slp_logic_dbias = 4, \ - .xpd = 0, \ - .dbias = 0, \ - .drv_b = 0 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_ACTIVE] = { \ - .analog = { \ - .slp_xpd = 0, \ - .slp_dbias = 0, \ - .xpd = 1, \ - .dbias = 26, \ - .drv_b = 0 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_SLEEP] = { \ - .analog = { \ - .xpd_bias = 0, \ - .dbg_atten = 0, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .xpd = 0, \ - .dbias = 28, \ - .slp_xpd = 1, \ - .slp_dbias = 3, \ - .drv_b = 0 \ - } \ - } \ +#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .drv_b = PMU_HP_DRVB_LIGHTSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .xpd = PMU_HP_XPD_LIGHTSLEEP, \ + .dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \ + .dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_LIGHTSLEEP_0V7 \ + } \ + } \ } -#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ - .hp_sys = { \ - .analog = { \ - .xpd_bias = 0, \ - .dbg_atten = 0, \ - .pd_cur = 0, \ - .bias_sleep = 0, \ - .slp_mem_xpd = 0, \ - .slp_logic_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_dbias = 0, \ - .xpd = 0, \ - .dbias = 0, \ - .drv_b = 0 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_ACTIVE] = { \ - .analog = { \ - .slp_xpd = 0, \ - .slp_dbias = 0, \ - .xpd = 1, \ - .dbias = 26, \ - .drv_b = 0 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_SLEEP] = { \ - .analog = { \ - .xpd_bias = 0, \ - .dbg_atten = 14, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .xpd = 0, \ - .dbias = 0, \ - .slp_xpd = 1, \ - .slp_dbias = 14, \ - .drv_b = 0 \ - } \ - } \ +#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .pd_cur = PMU_PD_CUR_SLEEP_ON, \ + .bias_sleep = PMU_BIASSLP_SLEEP_ON, \ + .xpd = PMU_HP_XPD_DEEPSLEEP, \ + .dbg_atten = PMU_DBG_HP_DEEPSLEEP \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbg_atten = PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_DEEPSLEEP_0V7 \ + } \ + } \ } typedef struct { diff --git a/components/esp_hw_support/port/esp32h2/pmu_param.c b/components/esp_hw_support/port/esp32h2/pmu_param.c index 715c5552ca57..83bf887aa31e 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_param.c +++ b/components/esp_hw_support/port/esp32h2/pmu_param.c @@ -210,9 +210,9 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ .xpd = 1, \ - .slp_mem_dbias = 0x5, \ - .slp_logic_dbias = 0xc, \ - .dbias = 0xf \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .dbias = HP_CALI_DBIAS \ }, \ .regulator1 = { \ .drv_b = 0x1a \ @@ -230,9 +230,9 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ .xpd = 1, \ - .slp_mem_dbias = 0x5, \ - .slp_logic_dbias = 0xc, \ - .dbias = 0xd \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .dbias = HP_CALI_DBIAS \ }, \ .regulator1 = { \ .drv_b = 0x1b \ @@ -247,11 +247,11 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .bias_sleep = 1 \ }, \ .regulator0 = { \ - .slp_mem_xpd = 1, \ - .slp_logic_xpd = 1, \ - .xpd = 0, \ - .slp_mem_dbias = 0x1, \ - .slp_logic_dbias = 0x5, \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .xpd = 1, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ .dbias = 0 \ }, \ .regulator1 = { \ @@ -403,10 +403,10 @@ const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mod .slp_xpd = 0, \ .xpd = 1, \ .slp_dbias = 0, \ - .dbias = 0xe \ + .dbias = LP_CALI_DBIAS \ }, \ .regulator1 = { \ - .drv_b = 3 \ + .drv_b = 0 \ } \ } @@ -417,10 +417,10 @@ const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mod .bias_sleep = 1, \ }, \ .regulator0 = { \ - .slp_xpd = 1, \ - .xpd = 0, \ - .slp_dbias = 0xf, \ - .dbias = 0 \ + .slp_xpd = 0, \ + .xpd = 1, \ + .slp_dbias = 0, \ + .dbias = 1 \ }, \ .regulator1 = { \ .drv_b = 9 \ diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index ffe456fa6017..1f39dd0a7fc7 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -16,6 +16,7 @@ #include "soc/pmu_struct.h" #include "hal/lp_aon_hal.h" #include "esp_private/esp_pmu.h" +#include "pmu_param.h" #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) @@ -120,21 +121,15 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->digital = digital_default; pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags); - if (!(pd_flags & PMU_SLEEP_PD_TOP) || !(pd_flags & PMU_SLEEP_PD_MODEM)){ - analog_default.hp_sys.analog.xpd = 1; - analog_default.hp_sys.analog.dbias = 2; - } if (!(pd_flags & PMU_SLEEP_PD_XTAL)){ - analog_default.hp_sys.analog.xpd_trx = 1; - analog_default.hp_sys.analog.xpd = 1; - analog_default.hp_sys.analog.dbias = 25; - analog_default.hp_sys.analog.pd_cur = 0; - analog_default.hp_sys.analog.bias_sleep = 0; - - analog_default.lp_sys[LP(SLEEP)].analog.xpd = 1; - analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = 0; - analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = 0; - analog_default.lp_sys[LP(SLEEP)].analog.dbias = 26; + analog_default.hp_sys.analog.xpd_trx = PMU_XPD_TRX_SLEEP_ON; + analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS; + analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON; + analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON; + + analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON; + analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON; + analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_DBIAS; } config->analog = analog_default; } @@ -165,23 +160,13 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con assert(ctx->hal); pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur); pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep); - pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd); - pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd); pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd); - pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_dbias); - pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias); pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b); pmu_ll_hp_set_trx_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd_trx); - - pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_xpd); - pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias); - pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.xpd); - pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias); - pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b); - pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur); pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep); + pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_xpd); pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd); pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_dbias); pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias); diff --git a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h index f52cdcf5ffe8..b6f183522e13 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h @@ -16,6 +16,36 @@ extern "C" { #endif +#define HP_CALI_DBIAS 17 +#define LP_CALI_DBIAS 18 + +// FOR XTAL FORCE PU IN SLEEP +#define PMU_PD_CUR_SLEEP_ON 0 +#define PMU_BIASSLP_SLEEP_ON 0 +#define PMU_XPD_TRX_SLEEP_ON 1 + + +// FOR BOTH LIGHTSLEEP & DEEPSLEEP +#define PMU_PD_CUR_SLEEP_DEFAULT 1 +#define PMU_BIASSLP_SLEEP_DEFAULT 1 +#define PMU_LP_XPD_SLEEP_DEFAULT 1 +#define PMU_XPD_TRX_SLEEP_DEFAULT 0 +#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0 +#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0 + +// FOR LIGHTSLEEP +#define PMU_HP_XPD_LIGHTSLEEP 1 +#define PMU_HP_DRVB_LIGHTSLEEP 0xFFFFF8 +#define PMU_LP_DRVB_LIGHTSLEEP 0 + +#define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1 +#define PMU_LP_DBIAS_LIGHTSLEEP_0V7 6 + +// FOR DEEPSLEEP +#define PMU_HP_XPD_DEEPSLEEP 0 +#define PMU_LP_DRVB_DEEPSLEEP 7 +#define PMU_LP_DBIAS_DEEPSLEEP_0V7 PMU_LP_DBIAS_LIGHTSLEEP_0V7 + typedef struct { pmu_hp_dig_power_reg_t dig_power; pmu_hp_clk_power_reg_t clk_power; @@ -291,79 +321,48 @@ typedef struct { } lp_sys[PMU_MODE_LP_MAX]; } pmu_sleep_analog_config_t; -#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ - .hp_sys = { \ - .analog = { \ - .xpd_trx = 0, \ - .xpd_bias = 0x0, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .slp_mem_xpd = 0, \ - .slp_logic_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_dbias = 0, \ - .xpd = 1, \ - .dbias = 0, \ - .drv_b = 0xFFFFF8 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_ACTIVE] = { \ - .analog = { \ - .slp_xpd = 0, \ - .slp_dbias = 0x0, \ - .xpd = 1, \ - .dbias = 0xe, \ - .drv_b = 0x0 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_SLEEP] = { \ - .analog = { \ - .xpd_bias = 0, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .xpd = 0, \ - .dbias = 0, \ - .slp_xpd = 1, \ - .slp_dbias = 0x5, \ - .drv_b = 0x7 \ - } \ - } \ -} - -#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ +#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ .hp_sys = { \ .analog = { \ - .xpd_bias = 0, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .xpd = 0, \ - .dbias = 0, \ - .slp_mem_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_xpd = 0, \ - .slp_logic_dbias = 0, \ - .drv_b = 0xFFFFFF \ + .xpd_trx = PMU_XPD_TRX_SLEEP_DEFAULT, \ + .drv_b = PMU_HP_DRVB_LIGHTSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .xpd = PMU_HP_XPD_LIGHTSLEEP, \ + .dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6 \ } \ }, \ - .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT,\ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_LIGHTSLEEP_0V7 \ + } \ + } \ +} + +#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ .analog = { \ - .xpd = 1, \ - .dbias = 0xe, \ - .slp_xpd = 0, \ - .slp_dbias = 0, \ - .drv_b = 0 \ + .xpd_trx = PMU_XPD_TRX_SLEEP_DEFAULT, \ + .pd_cur = PMU_PD_CUR_SLEEP_ON, \ + .bias_sleep = PMU_BIASSLP_SLEEP_ON, \ + .xpd = PMU_HP_XPD_DEEPSLEEP \ } \ }, \ .lp_sys[PMU_MODE_LP_SLEEP] = { \ .analog = { \ - .xpd_bias = 0, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .xpd = 0, \ - .dbias = 0, \ - .slp_xpd = 1, \ - .slp_dbias = 5, \ - .drv_b = 7 \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT,\ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_DEEPSLEEP_0V7 \ } \ } \ } From 364a6a1df43558fee5084af4cb17240e4b93ad89 Mon Sep 17 00:00:00 2001 From: xiaqilin Date: Thu, 21 Sep 2023 11:56:09 +0800 Subject: [PATCH 061/142] fix(ieee802154): using link0/2 for ieee802154 in esp32h2 chip --- .../ieee802154/driver/esp_ieee802154_dev.c | 44 ++++++++----------- .../private_include/esp_ieee802154_dev.h | 12 ----- examples/openthread/.build-test-rules.yml | 3 +- .../openthread/ot_sleepy_device/README.md | 4 +- .../main/esp_ot_sleepy_device_config.h | 2 +- examples/openthread/pytest_otbr.py | 4 -- 6 files changed, 24 insertions(+), 45 deletions(-) diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index c5866fe2d10a..7760c049ff32 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -30,12 +30,12 @@ #include "esp_pm.h" #include "esp_private/esp_clk.h" #include "esp_private/sleep_retention.h" -static bool g_sleep_rf = false; -// #if SOC_PM_RETENTION_HAS_CLOCK_BUG -// #define BTBB_LINK_OWNER ENTRY(3) -// #else +static bool s_rf_closed = false; +#if SOC_PM_RETENTION_HAS_CLOCK_BUG +#define IEEE802154_LINK_OWNER ENTRY(3) +#else #define IEEE802154_LINK_OWNER ENTRY(0) | ENTRY(2) -// #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG +#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG #endif #define CCA_DETECTION_TIME 8 @@ -52,6 +52,7 @@ static uint8_t s_recent_rx_frame_info_index; static portMUX_TYPE s_ieee802154_spinlock = portMUX_INITIALIZER_UNLOCKED; static esp_err_t ieee802154_sleep_init(void); +static void ieee802154_rf_enable(void); static IRAM_ATTR void event_end_process(void) { @@ -679,8 +680,7 @@ IEEE802154_STATIC void tx_init(const uint8_t *frame) esp_err_t ieee802154_transmit(const uint8_t *frame, bool cca) { - ieee802154_wakeup(); - + ieee802154_rf_enable(); ieee802154_enter_critical(); tx_init(frame); @@ -708,9 +708,7 @@ esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time) { uint32_t tx_target_time; uint32_t current_time; - - ieee802154_wakeup(); - + ieee802154_rf_enable(); tx_init(frame); IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX_AT); if (cca) { @@ -752,7 +750,7 @@ esp_err_t ieee802154_receive(void) // already in rx state, don't abort current rx operation return ESP_OK; } - ieee802154_wakeup(); + ieee802154_rf_enable(); ieee802154_enter_critical(); rx_init(); @@ -765,7 +763,7 @@ esp_err_t ieee802154_receive_at(uint32_t time) { uint32_t rx_target_time = time - IEEE802154_RX_RAMPUP_TIME_US; uint32_t current_time; - ieee802154_wakeup(); + ieee802154_rf_enable(); rx_init(); IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_RX_AT); set_next_rx_buffer(); @@ -794,22 +792,22 @@ static esp_err_t ieee802154_sleep_init(void) return err; } -IRAM_ATTR void ieee802154_enter_sleep(void) +IRAM_ATTR static void ieee802154_rf_disable(void) { #if CONFIG_FREERTOS_USE_TICKLESS_IDLE - if (g_sleep_rf == false) { + if (s_rf_closed == false) { esp_phy_disable(); - g_sleep_rf = true; + s_rf_closed = true; } #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE } -IRAM_ATTR void ieee802154_wakeup(void) +IRAM_ATTR static void ieee802154_rf_enable(void) { #if CONFIG_FREERTOS_USE_TICKLESS_IDLE - if (g_sleep_rf) { + if (s_rf_closed) { esp_phy_enable(); - g_sleep_rf = false; + s_rf_closed = false; } #endif //CONFIG_FREERTOS_USE_TICKLESS_IDLE } @@ -820,18 +818,15 @@ esp_err_t ieee802154_sleep(void) ieee802154_enter_critical(); stop_current_operation(); ieee802154_set_state(IEEE802154_STATE_SLEEP); - ieee802154_exit_critical(); - - ieee802154_enter_sleep(); // colse rf + ieee802154_rf_disable(); // colse rf } return ESP_OK; } esp_err_t ieee802154_energy_detect(uint32_t duration) { - ieee802154_wakeup(); - + ieee802154_rf_enable(); ieee802154_enter_critical(); stop_current_operation(); @@ -847,8 +842,7 @@ esp_err_t ieee802154_energy_detect(uint32_t duration) esp_err_t ieee802154_cca(void) { - ieee802154_wakeup(); - + ieee802154_rf_enable(); ieee802154_enter_critical(); stop_current_operation(); diff --git a/components/ieee802154/private_include/esp_ieee802154_dev.h b/components/ieee802154/private_include/esp_ieee802154_dev.h index bf802823697f..7fc5756134d7 100644 --- a/components/ieee802154/private_include/esp_ieee802154_dev.h +++ b/components/ieee802154/private_include/esp_ieee802154_dev.h @@ -178,18 +178,6 @@ uint8_t ieee802154_get_recent_lqi(void); */ ieee802154_state_t ieee802154_get_state(void); -/** - * @brief The IEEE 802.15.4 enter sleep. - * - */ -void ieee802154_enter_sleep(void); - -/** - * @brief The IEEE 802.15.4 wakeup. - * - */ -void ieee802154_wakeup(void); - /** The following three functions are only used for internal test. **/ /** * @brief The clear channel assessment done. diff --git a/examples/openthread/.build-test-rules.yml b/examples/openthread/.build-test-rules.yml index abb3a5109196..49f57448246b 100644 --- a/examples/openthread/.build-test-rules.yml +++ b/examples/openthread/.build-test-rules.yml @@ -45,7 +45,8 @@ examples/openthread/ot_rcp: reason: only test on esp32c6 <<: *openthread_dependencies +# To add support for the ESP32-C6 in TZ-302 examples/openthread/ot_sleepy_device: enable: - - if: IDF_TARGET in ["esp32h2", "esp32c6"] + - if: IDF_TARGET in ["esp32h2"] <<: [*openthread_dependencies, *openthread_sleep_dependencies] diff --git a/examples/openthread/ot_sleepy_device/README.md b/examples/openthread/ot_sleepy_device/README.md index a41def3d9915..5c832db28dee 100644 --- a/examples/openthread/ot_sleepy_device/README.md +++ b/examples/openthread/ot_sleepy_device/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-H2 | +| ----------------- | -------- | # OpenThread Sleepy Device Example diff --git a/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h b/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h index cd4453383a15..73bd029b275e 100644 --- a/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h +++ b/examples/openthread/ot_sleepy_device/main/esp_ot_sleepy_device_config.h @@ -25,7 +25,7 @@ } #endif -// When JIRA PM-3 fix, uart clock can autoswitch. +// When JIRA PM-3 is fixed, the UART clock will automatically switch. #define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index 2ae516518b23..eabb1cc24bcb 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -548,10 +548,6 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N @pytest.mark.openthread_sleep @pytest.mark.parametrize( 'config, count, app_path, target', [ - ('cli_h2|sleepy_c6', 2, - f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' - f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device")}', - 'esp32h2|esp32c6'), ('cli_c6|sleepy_h2', 2, f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device")}', From 303d2c2dc6472ca797afd148b2a0e5775d0ad34c Mon Sep 17 00:00:00 2001 From: Bogdan Kolendovskyy Date: Thu, 21 Sep 2023 13:11:39 +0200 Subject: [PATCH 062/142] fix(esp_eth): Add model number 0x13 to list of suported models Add model number 0x13 to KSZ80xx driver's list of supported models corresonding to KSZ8041RLNI. --- components/esp_eth/src/esp_eth_phy_ksz80xx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/esp_eth/src/esp_eth_phy_ksz80xx.c b/components/esp_eth/src/esp_eth_phy_ksz80xx.c index 67f2a8999d10..0c61e3347cd3 100644 --- a/components/esp_eth/src/esp_eth_phy_ksz80xx.c +++ b/components/esp_eth/src/esp_eth_phy_ksz80xx.c @@ -20,6 +20,7 @@ typedef enum { KSZ80XX_MODEL_NUMBER_11 = 0x11, // KSZ8041 + KSZ80XX_MODEL_NUMBER_13 = 0x13, // KSZ8041RLNI KSZ80XX_MODEL_NUMBER_15 = 0x15, // KSZ8021/31 KSZ80XX_MODEL_NUMBER_16 = 0x16, // KSZ8051/81/91 KSZ80XX_MODEL_NUMBER_17 = 0x17, // KSZ8061 @@ -37,6 +38,7 @@ typedef struct static const uint8_t supported_model_numbers[] = { KSZ80XX_MODEL_NUMBER_11, + KSZ80XX_MODEL_NUMBER_13, KSZ80XX_MODEL_NUMBER_15, KSZ80XX_MODEL_NUMBER_16, KSZ80XX_MODEL_NUMBER_17, @@ -45,6 +47,7 @@ static const uint8_t supported_model_numbers[] = static const char *model_names[] = { "41", // models with model number 0x11 + "41RLNI", // models with model number 0x13 "21/31", // models with model number 0x15 "51/81/91", // models with model number 0x16 "61", // models with model number 0x17 @@ -128,6 +131,7 @@ static bool ksz80xx_init_model(phy_ksz80xx_t *ksz80xx) switch (ksz80xx->model_number) { case KSZ80XX_MODEL_NUMBER_21: // models KSZ8001 case KSZ80XX_MODEL_NUMBER_11: // models KSZ8041 + case KSZ80XX_MODEL_NUMBER_13: // models KSZ8041RLNI ksz80xx->op_mode_reg = KSZ80XX_PC2R_REG_ADDR; ksz80xx->op_mode_offset = 2; // bits 4:2 break; From d3d15fb53fbefe45ecbed673bbfc564b3b0b566b Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Mon, 25 Sep 2023 14:50:43 +0530 Subject: [PATCH 063/142] feat(http_parser): Add sbom manifest file --- components/http_parser/sbom.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 components/http_parser/sbom.yml diff --git a/components/http_parser/sbom.yml b/components/http_parser/sbom.yml new file mode 100644 index 000000000000..47f62cd7a2dc --- /dev/null +++ b/components/http_parser/sbom.yml @@ -0,0 +1,5 @@ +name: 'HTTP Parser' +version: '2.7.0' +supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' +originator: 'Organization: NGINX, Joyent, Inc. and other Node contributors' +description: HTTP request/response parser for c. From a989ce4ab13a058f3cff36427a0fa32fa64e71b0 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 18 Jul 2023 20:08:22 +0800 Subject: [PATCH 064/142] feat(ana_cmpr): supported analog comparator on esp32p4 --- .../driver/analog_comparator/ana_cmpr.c | 26 ++- .../include/driver/ana_cmpr_types.h | 5 +- .../hal/esp32h2/include/hal/ana_cmpr_ll.h | 23 ++- .../hal/esp32p4/include/hal/ana_cmpr_ll.h | 163 ++++++++++++++++++ components/soc/esp32h2/ana_cmpr_periph.c | 1 + components/soc/esp32p4/ana_cmpr_periph.c | 38 ++++ .../esp32p4/include/soc/Kconfig.soc_caps.in | 12 ++ .../esp32p4/include/soc/ana_cmpr_channel.h | 12 ++ .../soc/esp32p4/include/soc/ana_cmpr_struct.h | 37 ++++ .../soc/esp32p4/include/soc/clk_tree_defs.h | 16 ++ .../soc/esp32p4/include/soc/gpio_struct.h | 22 +-- .../esp32p4/include/soc/lp_system_struct.h | 40 +---- components/soc/esp32p4/include/soc/soc_caps.h | 6 +- .../soc/esp32p4/ld/esp32p4.peripherals.ld | 1 + components/soc/include/soc/ana_cmpr_periph.h | 2 + .../en/api-reference/peripherals/ana_cmpr.rst | 31 +++- docs/en/api-reference/peripherals/etm.rst | 4 + docs/zh_CN/api-reference/peripherals/etm.rst | 4 + 18 files changed, 377 insertions(+), 66 deletions(-) create mode 100644 components/hal/esp32p4/include/hal/ana_cmpr_ll.h create mode 100644 components/soc/esp32p4/ana_cmpr_periph.c create mode 100644 components/soc/esp32p4/include/soc/ana_cmpr_channel.h create mode 100644 components/soc/esp32p4/include/soc/ana_cmpr_struct.h diff --git a/components/driver/analog_comparator/ana_cmpr.c b/components/driver/analog_comparator/ana_cmpr.c index 7fbdcf268932..c560f179344f 100644 --- a/components/driver/analog_comparator/ana_cmpr.c +++ b/components/driver/analog_comparator/ana_cmpr.c @@ -35,6 +35,7 @@ struct ana_cmpr_t { bool is_enabled; /*!< Whether the Analog comparator unit is enabled */ ana_cmpr_event_callbacks_t cbs; /*!< The callback group that set by user */ intr_handle_t intr_handle; /*!< Interrupt handle */ + uint32_t intr_mask; /*!< Interrupt mask */ void *user_data; /*!< User data that passed to the callbacks */ uint32_t src_clk_freq_hz; /*!< Source clock frequency of the Analog Comparator unit */ esp_pm_lock_handle_t pm_lock; /*!< The Power Management lock that used to avoid unexpected power down of the clock domain */ @@ -76,7 +77,14 @@ static void IRAM_ATTR s_ana_cmpr_default_intr_handler(void *usr_data) analog_cmpr_ll_clear_intr(cmpr_handle->dev, status); /* Call the user callback function if it is specified and the corresponding event triggers*/ - if (cmpr_handle->cbs.on_cross && (status & ANALOG_CMPR_LL_EVENT_CROSS)) { + if (cmpr_handle->cbs.on_cross && (status & cmpr_handle->intr_mask)) { +#if SOC_ANA_CMPR_SUPPORT_MULTI_INTR + if (status & ANALOG_CMPR_LL_POS_CROSS_MASK(cmpr_handle->unit)) { + evt_data.cross_type = ANA_CMPR_CROSS_POS; + } else if (status & ANALOG_CMPR_LL_NEG_CROSS_MASK(cmpr_handle->unit)) { + evt_data.cross_type = ANA_CMPR_CROSS_NEG; + } +#endif // SOC_ANA_CMPR_SUPPORT_MULTI_INTR need_yield = cmpr_handle->cbs.on_cross(cmpr_handle, &evt_data, cmpr_handle->user_data); } if (need_yield) { @@ -102,7 +110,7 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t * ESP_RETURN_ON_FALSE(s_ana_cmpr[unit], ESP_ERR_NO_MEM, TAG, "no memory for analog comparator struct"); /* Assign analog comparator unit */ - s_ana_cmpr[unit]->dev = ANALOG_CMPR_LL_GET_HW(); + s_ana_cmpr[unit]->dev = ANALOG_CMPR_LL_GET_HW(unit); s_ana_cmpr[unit]->ref_src = config->ref_src; s_ana_cmpr[unit]->is_enabled = false; s_ana_cmpr[unit]->pm_lock = NULL; @@ -126,12 +134,15 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t * /* Configure the register */ portENTER_CRITICAL(&s_spinlock); analog_cmpr_ll_set_ref_source(s_ana_cmpr[unit]->dev, config->ref_src); +#if !SOC_ANA_CMPR_SUPPORT_MULTI_INTR analog_cmpr_ll_set_cross_type(s_ana_cmpr[unit]->dev, config->cross_type); +#endif // SOC_ANA_CMPR_SUPPORT_MULTI_INTR portEXIT_CRITICAL(&s_spinlock); /* Allocate the interrupt, currently the interrupt source of Analog Comparator is shared with GPIO interrupt source */ - ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(ETS_GPIO_INTR_SOURCE, ANA_CMPR_INTR_FLAG, (uint32_t)analog_cmpr_ll_get_intr_status_reg(s_ana_cmpr[unit]->dev), - ANALOG_CMPR_LL_EVENT_CROSS, s_ana_cmpr_default_intr_handler, s_ana_cmpr[unit], &s_ana_cmpr[unit]->intr_handle), + s_ana_cmpr[unit]->intr_mask = analog_cmpr_ll_get_intr_mask_by_type(s_ana_cmpr[unit]->dev, config->cross_type); + ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(ana_cmpr_io_map[unit].intr_src, ANA_CMPR_INTR_FLAG, (uint32_t)analog_cmpr_ll_get_intr_status_reg(s_ana_cmpr[unit]->dev), + s_ana_cmpr[unit]->intr_mask, s_ana_cmpr_default_intr_handler, s_ana_cmpr[unit], &s_ana_cmpr[unit]->intr_handle), err, TAG, "allocate interrupt failed"); if (config->ref_src == ANA_CMPR_REF_SRC_INTERNAL) { @@ -224,7 +235,10 @@ esp_err_t ana_cmpr_set_cross_type(ana_cmpr_handle_t cmpr, ana_cmpr_cross_type_t ESP_ERR_INVALID_ARG, TAG, "invalid cross type"); portENTER_CRITICAL_SAFE(&s_spinlock); +#if !SOC_ANA_CMPR_SUPPORT_MULTI_INTR analog_cmpr_ll_set_cross_type(cmpr->dev, cross_type); +#endif + cmpr->intr_mask = analog_cmpr_ll_get_intr_mask_by_type(cmpr->dev, cross_type); portEXIT_CRITICAL_SAFE(&s_spinlock); ESP_EARLY_LOGD(TAG, "unit %d cross type updated to %d", (int)cmpr->unit, cross_type); @@ -273,7 +287,7 @@ esp_err_t ana_cmpr_enable(ana_cmpr_handle_t cmpr) /* Enable the Analog Comparator */ portENTER_CRITICAL(&s_spinlock); - analog_cmpr_ll_enable_intr(cmpr->dev, ANALOG_CMPR_LL_EVENT_CROSS, !!(cmpr->cbs.on_cross)); + analog_cmpr_ll_enable_intr(cmpr->dev, cmpr->intr_mask, true); analog_cmpr_ll_enable(cmpr->dev, true); portEXIT_CRITICAL(&s_spinlock); @@ -289,7 +303,7 @@ esp_err_t ana_cmpr_disable(ana_cmpr_handle_t cmpr) "the analog comparator not enabled yet"); /* Disable the Analog Comparator */ portENTER_CRITICAL(&s_spinlock); - analog_cmpr_ll_enable_intr(cmpr->dev, ANALOG_CMPR_LL_EVENT_CROSS, false); + analog_cmpr_ll_enable_intr(cmpr->dev, cmpr->intr_mask, false); analog_cmpr_ll_enable(cmpr->dev, false); portEXIT_CRITICAL(&s_spinlock); diff --git a/components/driver/analog_comparator/include/driver/ana_cmpr_types.h b/components/driver/analog_comparator/include/driver/ana_cmpr_types.h index a04ae0b52f75..acafb6ccda92 100644 --- a/components/driver/analog_comparator/include/driver/ana_cmpr_types.h +++ b/components/driver/analog_comparator/include/driver/ana_cmpr_types.h @@ -90,7 +90,10 @@ typedef int ana_cmpr_clk_src_t; * */ typedef struct { - // No data for now +#if SOC_ANA_CMPR_SUPPORT_MULTI_INTR + ana_cmpr_cross_type_t cross_type; /*!< The cross type of the target signal to the reference signal. + * Will either be ANA_CMPR_CROSS_POS or ANA_CMPR_CROSS_NEG */ +#endif } ana_cmpr_cross_event_data_t; /** diff --git a/components/hal/esp32h2/include/hal/ana_cmpr_ll.h b/components/hal/esp32h2/include/hal/ana_cmpr_ll.h index a818ea8b4719..834391be3068 100644 --- a/components/hal/esp32h2/include/hal/ana_cmpr_ll.h +++ b/components/hal/esp32h2/include/hal/ana_cmpr_ll.h @@ -11,12 +11,9 @@ #include "hal/assert.h" #include "soc/gpio_ext_struct.h" -#define ANALOG_CMPR_LL_GET_HW() (&ANALOG_CMPR) +#define ANALOG_CMPR_LL_GET_HW(unit) (&ANALOG_CMPR) #define ANALOG_CMPR_LL_EVENT_CROSS (1 << 0) -#define ANALOG_CMPR_LL_POS_CROSS_MASK (1 << 1) -#define ANALOG_CMPR_LL_NEG_CROSS_MASK (1 << 2) - #ifdef __cplusplus extern "C" { #endif @@ -84,6 +81,24 @@ static inline void analog_cmpr_ll_set_cross_type(analog_cmpr_dev_t *hw, uint8_t hw->pad_comp_config.zero_det_mode = type; } +/** + * @brief Get the interrupt mask by trigger type + * @note Only one interrupt on H2 + * + * @param hw Analog comparator register base address + * @param type The type of cross interrupt + * - 0: disable interrupt + * - 1: enable positive cross interrupt (input analog goes from low to high and across the reference voltage) + * - 2: enable negative cross interrupt (input analog goes from high to low and across the reference voltage) + * - 3: enable any positive or negative cross interrupt + * @return interrupt mask + */ +__attribute__((always_inline)) +static inline uint32_t analog_cmpr_ll_get_intr_mask_by_type(analog_cmpr_dev_t *hw, uint8_t type) +{ + return ANALOG_CMPR_LL_EVENT_CROSS; +} + /** * @brief Set the debounce cycle for the cross detection * diff --git a/components/hal/esp32p4/include/hal/ana_cmpr_ll.h b/components/hal/esp32p4/include/hal/ana_cmpr_ll.h new file mode 100644 index 000000000000..9f4abbf6d373 --- /dev/null +++ b/components/hal/esp32p4/include/hal/ana_cmpr_ll.h @@ -0,0 +1,163 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "hal/misc.h" +#include "hal/assert.h" +#include "soc/ana_cmpr_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ANALOG_CMPR_LL_GET_HW(unit) (&ANALOG_CMPR[unit]) +#define ANALOG_CMPR_LL_GET_UNIT(hw) ((hw) == (&ANALOG_CMPR[0]) ? 0 : 1) +#define ANALOG_CMPR_LL_EVENT_CROSS (1 << 0) + +#define ANALOG_CMPR_LL_NEG_CROSS_MASK(unit) (1UL << ((int)unit * 3)) +#define ANALOG_CMPR_LL_POS_CROSS_MASK(unit) (1UL << ((int)unit * 3 + 1)) + +/** + * @brief Enable analog comparator + * + * @param hw Analog comparator register base address + * @param en True to enable, False to disable + */ +static inline void analog_cmpr_ll_enable(analog_cmpr_dev_t *hw, bool en) +{ + hw->pad_comp_config->xpd_comp = en; +} + +/** + * @brief Set the voltage of the internal reference + * + * @param hw Analog comparator register base address + * @param volt_level The voltage level of the internal reference, range [0.0V, 0.7VDD], step 0.1VDD + */ +__attribute__((always_inline)) +static inline void analog_cmpr_ll_set_internal_ref_voltage(analog_cmpr_dev_t *hw, uint32_t volt_level) +{ + hw->pad_comp_config->dref_comp = volt_level; +} + +/** + * @brief Get the voltage of the internal reference + * + * @param hw Analog comparator register base address + * @return The voltage of the internal reference + */ +static inline float analog_cmpr_ll_get_internal_ref_voltage(analog_cmpr_dev_t *hw) +{ + return hw->pad_comp_config->dref_comp * 0.1F; +} + +/** + * @brief The reference voltage comes from internal or external + * + * @note Also see `analog_cmpr_ll_set_internal_ref_voltage` to use the internal reference voltage + * + * @param hw Analog comparator register base address + * @param ref_src reference source, 0 for internal, 1 for external GPIO pad (GPIO10) + */ +static inline void analog_cmpr_ll_set_ref_source(analog_cmpr_dev_t *hw, uint32_t ref_src) +{ + hw->pad_comp_config->mode_comp = ref_src; +} + +/** + * @brief Get the interrupt mask by trigger type + * + * @param hw Analog comparator register base address + * @param type The type of cross interrupt + * - 0: disable interrupt + * - 1: enable positive cross interrupt (input analog goes from low to high and across the reference voltage) + * - 2: enable negative cross interrupt (input analog goes from high to low and across the reference voltage) + * - 3: enable any positive or negative cross interrupt + * @return interrupt mask + */ +__attribute__((always_inline)) +static inline uint32_t analog_cmpr_ll_get_intr_mask_by_type(analog_cmpr_dev_t *hw, uint8_t type) +{ + uint32_t unit = ANALOG_CMPR_LL_GET_UNIT(hw); + uint32_t mask = 0; + if (type & 0x01) { + mask |= ANALOG_CMPR_LL_POS_CROSS_MASK(unit); + } + if (type & 0x02) { + mask |= ANALOG_CMPR_LL_POS_CROSS_MASK(unit); + } + return mask; +} + +/** + * @brief Set the debounce cycle for the cross detection + * + * @note When the comparator detects a cross, it will wait for the debounce cycle to make sure the cross is stable. + * + * @param hw Analog comparator register base address + * @param cycle The debounce cycle + */ +__attribute__((always_inline)) +static inline void analog_cmpr_ll_set_debounce_cycle(analog_cmpr_dev_t *hw, uint32_t cycle) +{ + hw->pad_comp_filter->zero_det_filter_cnt = cycle; +} + +/** + * @brief Enable comparator interrupt + * + * @param hw Analog comparator register base address + * @param mask Interrupt mask + * @param enable True to enable, False to disable + */ +static inline void analog_cmpr_ll_enable_intr(analog_cmpr_dev_t *hw, uint32_t mask, bool enable) +{ + if (enable) { + hw->int_ena->val |= mask; + } else { + hw->int_ena->val &= ~mask; + } +} + +/** + * @brief Get comparator interrupt status + * + * @param hw Analog comparator register base address + */ +__attribute__((always_inline)) +static inline uint32_t analog_cmpr_ll_get_intr_status(analog_cmpr_dev_t *hw) +{ + return hw->int_st->val; +} + +/** + * @brief Clear comparator interrupt status + * + * @param hw Analog comparator register base address + * @param mask Interrupt status word + */ +__attribute__((always_inline)) +static inline void analog_cmpr_ll_clear_intr(analog_cmpr_dev_t *hw, uint32_t mask) +{ + hw->int_clr->val = mask; +} + +/** + * @brief Get the interrupt status register address + * + * @param hw Analog comparator register base address + * @return The interrupt status register address + */ +static inline volatile void *analog_cmpr_ll_get_intr_status_reg(analog_cmpr_dev_t *hw) +{ + return hw->int_st; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/ana_cmpr_periph.c b/components/soc/esp32h2/ana_cmpr_periph.c index 4d3a67586c8c..8a5bec3c6cf9 100644 --- a/components/soc/esp32h2/ana_cmpr_periph.c +++ b/components/soc/esp32h2/ana_cmpr_periph.c @@ -10,5 +10,6 @@ const ana_cmpr_conn_t ana_cmpr_io_map[SOC_ANA_CMPR_NUM] = { [0] = { .src_gpio = ANA_CMPR0_SRC_GPIO, .ext_ref_gpio = ANA_CMPR0_EXT_REF_GPIO, + .intr_src = ETS_GPIO_INTR_SOURCE, }, }; diff --git a/components/soc/esp32p4/ana_cmpr_periph.c b/components/soc/esp32p4/ana_cmpr_periph.c new file mode 100644 index 000000000000..f189bbd28778 --- /dev/null +++ b/components/soc/esp32p4/ana_cmpr_periph.c @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/ana_cmpr_periph.h" +#include "soc/ana_cmpr_struct.h" + +const ana_cmpr_conn_t ana_cmpr_io_map[SOC_ANA_CMPR_NUM] = { + [0] = { + .src_gpio = ANA_CMPR0_SRC_GPIO, + .ext_ref_gpio = ANA_CMPR0_EXT_REF_GPIO, + .intr_src = ETS_GPIO_PAD_COMP_INTR_SOURCE, + }, + [1] = { + .src_gpio = ANA_CMPR1_SRC_GPIO, + .ext_ref_gpio = ANA_CMPR1_EXT_REF_GPIO, + .intr_src = ETS_GPIO_PAD_COMP_INTR_SOURCE, + }, +}; + +analog_cmpr_dev_t ANALOG_CMPR[SOC_ANA_CMPR_NUM] = { + [0] = { + .pad_comp_config = &LP_SYS.pad_comp[0], + .pad_comp_filter = &GPIO.zero_det_filter_cnt[0], + .int_st = &GPIO.int_st, + .int_ena = &GPIO.int_ena, + .int_clr = &GPIO.int_clr, + }, + [1] = { + .pad_comp_config = &LP_SYS.pad_comp[1], + .pad_comp_filter = &GPIO.zero_det_filter_cnt[1], + .int_st = &GPIO.int_st, + .int_ena = &GPIO.int_ena, + .int_clr = &GPIO.int_clr, + }, +}; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 3a120de79b33..e5e7e61fd516 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -3,6 +3,10 @@ # using gen_soc_caps_kconfig.py, do not edit manually ##################################################### +config SOC_ANA_CMPR_SUPPORTED + bool + default y + config SOC_UART_SUPPORTED bool default y @@ -383,6 +387,14 @@ config SOC_DEDIC_PERIPH_ALWAYS_ENABLE bool default y +config SOC_ANA_CMPR_NUM + int + default 2 + +config SOC_ANA_CMPR_SUPPORT_MULTI_INTR + bool + default y + config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32p4/include/soc/ana_cmpr_channel.h b/components/soc/esp32p4/include/soc/ana_cmpr_channel.h new file mode 100644 index 000000000000..e6430604c2a3 --- /dev/null +++ b/components/soc/esp32p4/include/soc/ana_cmpr_channel.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#define ANA_CMPR0_EXT_REF_GPIO 51 /*!< The GPIO that can be used as external reference voltage */ +#define ANA_CMPR0_SRC_GPIO 52 /*!< The GPIO that used for inputting the source signal to compare */ +#define ANA_CMPR1_EXT_REF_GPIO 53 /*!< The GPIO that can be used as external reference voltage */ +#define ANA_CMPR1_SRC_GPIO 54 /*!< The GPIO that used for inputting the source signal to compare */ diff --git a/components/soc/esp32p4/include/soc/ana_cmpr_struct.h b/components/soc/esp32p4/include/soc/ana_cmpr_struct.h new file mode 100644 index 000000000000..b49d31807d79 --- /dev/null +++ b/components/soc/esp32p4/include/soc/ana_cmpr_struct.h @@ -0,0 +1,37 @@ +/** + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* NOTE: this file is created manually for compatibility */ + +#pragma once + +#include +#include "soc/gpio_struct.h" +#include "soc/lp_system_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The Analog Comparator Device struct + * @note The field in it are register pointers, which point to the physical address + * of the corresponding configuration register + * @note see 'ana_cmpr_periph.c' for the device instance + */ +typedef struct { + volatile lp_system_reg_pad_comp_reg_t *pad_comp_config; + volatile gpio_zero_det_filter_cnt_reg_t *pad_comp_filter; + volatile gpio_int_st_reg_t *int_st; + volatile gpio_int_ena_reg_t *int_ena; + volatile gpio_int_clr_reg_t *int_clr; +} analog_cmpr_dev_t; + +extern analog_cmpr_dev_t ANALOG_CMPR[2]; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 8e3e34bc9c30..a58f4214dd3b 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -405,6 +405,22 @@ typedef enum { //////////////////////////////////////////////////GPIO Glitch Filter//////////////////////////////////////////////////// +///////////////////////////////////////////////////Analog Comparator//////////////////////////////////////////////////// + +/** + * @brief Array initializer for all supported clock sources of Analog Comparator + */ +#define SOC_ANA_CMPR_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL} + +/** + * @brief Sigma Delta Modulator clock source + */ +typedef enum { + ANA_CMPR_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL clock as the source clock */ + ANA_CMPR_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M clock as the source clock */ + ANA_CMPR_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the default clock choice */ +} soc_periph_ana_cmpr_clk_src_t; + //////////////////////////////////////////////////TWAI////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////ADC/////////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32p4/include/soc/gpio_struct.h b/components/soc/esp32p4/include/soc/gpio_struct.h index 7aaade288358..748d4c2b7db8 100644 --- a/components/soc/esp32p4/include/soc/gpio_struct.h +++ b/components/soc/esp32p4/include/soc/gpio_struct.h @@ -558,26 +558,13 @@ typedef union { */ typedef union { struct { - /** zero_det0_filter_cnt : R/W; bitpos: [31:0]; default: 4294967295; + /** zero_det_filter_cnt : R/W; bitpos: [31:0]; default: 4294967295; * GPIO analog comparator zero detect filter count */ - uint32_t zero_det0_filter_cnt:32; + uint32_t zero_det_filter_cnt:32; }; uint32_t val; -} gpio_zero_det0_filter_cnt_reg_t; - -/** Type of zero_det1_filter_cnt register - * GPIO analog comparator zero detect filter count - */ -typedef union { - struct { - /** zero_det1_filter_cnt : R/W; bitpos: [31:0]; default: 4294967295; - * GPIO analog comparator zero detect filter count - */ - uint32_t zero_det1_filter_cnt:32; - }; - uint32_t val; -} gpio_zero_det1_filter_cnt_reg_t; +} gpio_zero_det_filter_cnt_reg_t; /** Type of send_seq register * High speed sdio pad bist send sequence @@ -871,8 +858,7 @@ typedef struct gpio_dev_t { volatile gpio_int_st_reg_t int_st; volatile gpio_int_ena_reg_t int_ena; volatile gpio_int_clr_reg_t int_clr; - volatile gpio_zero_det0_filter_cnt_reg_t zero_det0_filter_cnt; - volatile gpio_zero_det1_filter_cnt_reg_t zero_det1_filter_cnt; + volatile gpio_zero_det_filter_cnt_reg_t zero_det_filter_cnt[2]; volatile gpio_send_seq_reg_t send_seq; volatile gpio_recive_seq_reg_t recive_seq; volatile gpio_bistin_sel_reg_t bistin_sel; diff --git a/components/soc/esp32p4/include/soc/lp_system_struct.h b/components/soc/esp32p4/include/soc/lp_system_struct.h index f54c249eec0e..633e5a0aaabf 100644 --- a/components/soc/esp32p4/include/soc/lp_system_struct.h +++ b/components/soc/esp32p4/include/soc/lp_system_struct.h @@ -677,44 +677,22 @@ typedef union { */ typedef union { struct { - /** dref_comp0 : R/W; bitpos: [2:0]; default: 0; + /** dref_comp : R/W; bitpos: [2:0]; default: 0; * pad comp dref */ - uint32_t dref_comp0:3; - /** mode_comp0 : R/W; bitpos: [3]; default: 0; + uint32_t dref_comp:3; + /** mode_comp : R/W; bitpos: [3]; default: 0; * pad comp mode */ - uint32_t mode_comp0:1; - /** xpd_comp0 : R/W; bitpos: [4]; default: 0; + uint32_t mode_comp:1; + /** xpd_comp : R/W; bitpos: [4]; default: 0; * pad comp xpd */ - uint32_t xpd_comp0:1; + uint32_t xpd_comp:1; uint32_t reserved_5:27; }; uint32_t val; -} lp_system_reg_pad_comp0_reg_t; - -/** Type of pad_comp1 register - * need_des - */ -typedef union { - struct { - /** dref_comp1 : R/W; bitpos: [2:0]; default: 0; - * pad comp dref - */ - uint32_t dref_comp1:3; - /** mode_comp1 : R/W; bitpos: [3]; default: 0; - * pad comp mode - */ - uint32_t mode_comp1:1; - /** xpd_comp1 : R/W; bitpos: [4]; default: 0; - * pad comp xpd - */ - uint32_t xpd_comp1:1; - uint32_t reserved_5:27; - }; - uint32_t val; -} lp_system_reg_pad_comp1_reg_t; +} lp_system_reg_pad_comp_reg_t; /** Type of backup_dma_cfg0 register * need_des @@ -1291,8 +1269,7 @@ typedef struct { volatile lp_system_reg_lp_pmu_rdn_eco_low_reg_t lp_pmu_rdn_eco_low; volatile lp_system_reg_lp_pmu_rdn_eco_high_reg_t lp_pmu_rdn_eco_high; uint32_t reserved_140[2]; - volatile lp_system_reg_pad_comp0_reg_t pad_comp0; - volatile lp_system_reg_pad_comp1_reg_t pad_comp1; + volatile lp_system_reg_pad_comp_reg_t pad_comp[2]; uint32_t reserved_150; volatile lp_system_reg_backup_dma_cfg0_reg_t backup_dma_cfg0; volatile lp_system_reg_backup_dma_cfg1_reg_t backup_dma_cfg1; @@ -1323,6 +1300,7 @@ typedef struct { volatile lp_system_reg_rng_cfg_reg_t rng_cfg; } lp_system_reg_dev_t; +extern lp_system_reg_dev_t LP_SYS; #ifndef __cplusplus _Static_assert(sizeof(lp_system_reg_dev_t) == 0x1c4, "Invalid size of lp_system_reg_dev_t structure"); diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index e4ee0d074d9e..8cb49267ba92 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -26,7 +26,7 @@ /*-------------------------- COMMON CAPS ---------------------------------------*/ // #define SOC_ADC_SUPPORTED 1 //TODO: IDF-6496 -// #define SOC_ANA_CMPR_SUPPORTED 1 //TODO: IDF-7479 +#define SOC_ANA_CMPR_SUPPORTED 1 // #define SOC_DEDICATED_GPIO_SUPPORTED 1 //TODO: IDF-7552 #define SOC_UART_SUPPORTED 1 #define SOC_GDMA_SUPPORTED 1 @@ -220,6 +220,10 @@ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ +/*------------------------- Analog Comparator CAPS ---------------------------*/ +#define SOC_ANA_CMPR_NUM (2U) +#define SOC_ANA_CMPR_SUPPORT_MULTI_INTR (1) + /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-P4 has 2 I2Cs #define SOC_I2C_NUM (2U) diff --git a/components/soc/esp32p4/ld/esp32p4.peripherals.ld b/components/soc/esp32p4/ld/esp32p4.peripherals.ld index 4085a915e41e..f4223a2f01ce 100644 --- a/components/soc/esp32p4/ld/esp32p4.peripherals.ld +++ b/components/soc/esp32p4/ld/esp32p4.peripherals.ld @@ -65,6 +65,7 @@ PROVIDE ( TEE = 0x60098000 ); /* TODO: IDF-7542 */ PROVIDE ( HP_APM = 0x60099000 ); /* TODO: IDF-7542 */ PROVIDE ( PMU = 0x50115000 ); +PROVIDE ( LP_SYS = 0x50110000 ); PROVIDE ( LP_AON_CLKRST = 0x50111000 ); PROVIDE ( EFUSE = 0x5012D000 ); PROVIDE ( LP_TIMER = 0x50112000 ); diff --git a/components/soc/include/soc/ana_cmpr_periph.h b/components/soc/include/soc/ana_cmpr_periph.h index 9418b15578eb..c197bdb10a46 100644 --- a/components/soc/include/soc/ana_cmpr_periph.h +++ b/components/soc/include/soc/ana_cmpr_periph.h @@ -8,6 +8,7 @@ #include #include "soc/soc_caps.h" +#include "soc/periph_defs.h" #if SOC_ANA_CMPR_SUPPORTED #include "soc/ana_cmpr_channel.h" #endif @@ -20,6 +21,7 @@ extern "C" { typedef struct { int src_gpio; int ext_ref_gpio; + int intr_src; } ana_cmpr_conn_t; extern const ana_cmpr_conn_t ana_cmpr_io_map[SOC_ANA_CMPR_NUM]; diff --git a/docs/en/api-reference/peripherals/ana_cmpr.rst b/docs/en/api-reference/peripherals/ana_cmpr.rst index 0593dd11f722..b686e6b69323 100644 --- a/docs/en/api-reference/peripherals/ana_cmpr.rst +++ b/docs/en/api-reference/peripherals/ana_cmpr.rst @@ -1,9 +1,11 @@ Analog Comparator ================= -{IDF_TARGET_ANA_CMPR_NUM: default="NOT UPDATED", esp32h2="one"} -{IDF_TARGET_ANA_CMPR_SRC_CHAN: default="NOT UPDATED", esp32h2="GPIO11"} -{IDF_TARGET_ANA_CMPR_EXT_REF_CHAN: default="NOT UPDATED", esp32h2="GPIO10"} +{IDF_TARGET_ANA_CMPR_NUM: default="NOT UPDATED", esp32h2="one", esp32p4="two"} +{IDF_TARGET_ANA_CMPR_SRC_CHAN0: default="NOT UPDATED", esp32h2="GPIO11", esp32p4="GPIO52"} +{IDF_TARGET_ANA_CMPR_EXT_REF_CHAN0: default="NOT UPDATED", esp32h2="GPIO10", esp32p4="GPIO51"} +{IDF_TARGET_ANA_CMPR_SRC_CHAN1: default="NOT UPDATED", esp32p4="GPIO54"} +{IDF_TARGET_ANA_CMPR_EXT_REF_CHAN1: default="NOT UPDATED", esp32p4="GPIO53"} Introduction ------------ @@ -16,10 +18,18 @@ Analog Comparator on {IDF_TARGET_NAME} has {IDF_TARGET_ANA_CMPR_NUM} unit(s), th **UNIT0** -- Source Channel: {IDF_TARGET_ANA_CMPR_SRC_CHAN} -- External Reference Channel: {IDF_TARGET_ANA_CMPR_EXT_REF_CHAN} +- Source Channel: {IDF_TARGET_ANA_CMPR_SRC_CHAN0} +- External Reference Channel: {IDF_TARGET_ANA_CMPR_EXT_REF_CHAN0} - Internal Reference Channel: Range 0% ~ 70% VDD, step 10% VDD +.. only:: esp32p4 + + **UNIT1** + + - Source Channel: {IDF_TARGET_ANA_CMPR_SRC_CHAN1} + - External Reference Channel: {IDF_TARGET_ANA_CMPR_EXT_REF_CHAN1} + - Internal Reference Channel: Range 0% ~ 70% VDD, step 10% VDD + Functional Overview ------------------- @@ -33,6 +43,10 @@ The following sections of this document cover the typical steps to install and o - `Thread Safety <#thread-safety>`__ - lists which APIs are guaranteed to be thread safe by the driver. - `Kconfig Options <#kconfig-options>`__ - lists the supported Kconfig options that can be used to make a different effect on driver behavior. +.. only:: SOC_ANA_CMPR_SUPPORT_ETM + + - `ETM Events <#etm-events>`__ - + Resource Allocation ^^^^^^^^^^^^^^^^^^^ @@ -180,6 +194,13 @@ Kconfig Options - :ref:`CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM` controls where to place the Analog Comparator control functions (IRAM or Flash), see `IRAM Safe <#iram-safe>`__ for more information. - :ref:`CONFIG_ANA_CMPR_ENABLE_DEBUG_LOG` is used to enabled the debug log output. Enabling this option increases the firmware binary size. +.. only:: SOC_ANA_CMPR_SUPPORT_ETM + + ETM Events + ^^^^^^^^^^ + + To create an analog comparator cross event, you need to include ``driver/ana_cmpr_etm.h`` additionally, and allocate the event by :cpp:func:`ana_cmpr_new_etm_event`. You can refer to :doc:`GPTimer ` for how to connect an event to a task. + Application Example ------------------- diff --git a/docs/en/api-reference/peripherals/etm.rst b/docs/en/api-reference/peripherals/etm.rst index e8dbcefd8b11..96165f19f43a 100644 --- a/docs/en/api-reference/peripherals/etm.rst +++ b/docs/en/api-reference/peripherals/etm.rst @@ -71,6 +71,10 @@ Other Peripheral Events :SOC_GDMA_SUPPORT_ETM: - Refer to :doc:`/api-reference/system/async_memcpy` for how to get the ETM event handle from async memcpy. :SOC_MCPWM_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/mcpwm` for how to get the ETM event handle from MCPWM. + .. only:: esp32p4 + + :SOC_ANA_CMPR_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/ana_cmpr` for how to get the ETM event handle from analog comparator. + .. _etm-task: ETM Task diff --git a/docs/zh_CN/api-reference/peripherals/etm.rst b/docs/zh_CN/api-reference/peripherals/etm.rst index 37c036972dac..3f7d5baddc23 100644 --- a/docs/zh_CN/api-reference/peripherals/etm.rst +++ b/docs/zh_CN/api-reference/peripherals/etm.rst @@ -71,6 +71,10 @@ GPIO **边沿** 事件是最常见的事件类型,任何 GPIO 管脚均可触 :SOC_GDMA_SUPPORT_ETM: - 要了解如何从 async memcpy 获取 ETM 事件句柄,请参阅 :doc:`/api-reference/system/async_memcpy`。 :SOC_MCPWM_SUPPORT_ETM: - 要了解如何从 MCPWM 中获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/mcpwm`。 + .. only:: esp32p4 + + :SOC_ANA_CMPR_SUPPORT_ETM: - 要了解如何从模拟比较器获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/ana_cmpr`。 + .. _etm-task: ETM 任务 From bf2a5653a97a6cbe2e6082c837830287e6f6de0a Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Fri, 28 Jul 2023 15:40:38 +0800 Subject: [PATCH 065/142] feat(ana_cmpr): supported analog comparator etm function on p4 --- components/driver/CMakeLists.txt | 3 + .../driver/analog_comparator/ana_cmpr_etm.c | 108 ++++++++++++++++++ .../include/driver/ana_cmpr_etm.h | 36 ++++++ .../include/driver/ana_cmpr_types.h | 6 +- .../include/esp_private/etm_interface.h | 1 + .../hal/esp32p4/include/hal/ana_cmpr_ll.h | 3 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 8 ++ .../soc/esp32p4/include/soc/gpio_struct.h | 2 +- components/soc/esp32p4/include/soc/soc_caps.h | 6 +- 9 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 components/driver/analog_comparator/ana_cmpr_etm.c create mode 100644 components/driver/analog_comparator/include/driver/ana_cmpr_etm.h diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 74ac9e75cf57..0a168abb5ad9 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -47,6 +47,9 @@ endif() # Analog comparator related source files if(CONFIG_SOC_ANA_CMPR_SUPPORTED) list(APPEND srcs "analog_comparator/ana_cmpr.c") + if(CONFIG_SOC_ANA_CMPR_SUPPORT_ETM) + list(APPEND srcs "analog_comparator/ana_cmpr_etm.c") + endif() endif() # DAC related source files diff --git a/components/driver/analog_comparator/ana_cmpr_etm.c b/components/driver/analog_comparator/ana_cmpr_etm.c new file mode 100644 index 000000000000..0c9494c680df --- /dev/null +++ b/components/driver/analog_comparator/ana_cmpr_etm.c @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#if CONFIG_ETM_ENABLE_DEBUG_LOG +// The local log level must be defined before including esp_log.h +// Set the maximum log level for this source file +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#endif +#include "freertos/FreeRTOS.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "esp_check.h" +#include "soc/soc_caps.h" +#include "hal/ana_cmpr_ll.h" +#include "driver/ana_cmpr_types.h" +#include "driver/ana_cmpr_etm.h" +#include "esp_private/etm_interface.h" + +static const char *TAG = "ana-cmpr-etm"; + +#define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT + +typedef struct ana_cmpr_etm_event_t ana_cmpr_etm_event_t; + +typedef struct { + portMUX_TYPE spinlock; + ana_cmpr_etm_event_t *events[SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT]; +} ana_cmpr_etm_unit_t; + +struct ana_cmpr_etm_event_t { + esp_etm_event_t base; + ana_cmpr_unit_t unit; + ana_cmpr_event_type_t type; +}; + +static ana_cmpr_etm_unit_t s_ana_cmpr_etm_unit[SOC_ANA_CMPR_NUM] = { + [0 ... SOC_ANA_CMPR_NUM - 1] = { + .spinlock = portMUX_INITIALIZER_UNLOCKED, + .events[0 ... SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT - 1] = NULL, + }, +}; + +static esp_err_t ana_cmpr_etm_event_register_to_unit(ana_cmpr_etm_event_t *evt) +{ + ESP_RETURN_ON_FALSE(!s_ana_cmpr_etm_unit[evt->unit].events[evt->type], + ESP_ERR_INVALID_STATE, TAG, "this event has been registered on the unit"); + portENTER_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); + s_ana_cmpr_etm_unit[evt->unit].events[evt->type] = evt; + portEXIT_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); + return ESP_OK; +} + +static esp_err_t ana_cmpr_etm_event_unregister_from_unit(ana_cmpr_etm_event_t *evt) +{ + ESP_RETURN_ON_FALSE(s_ana_cmpr_etm_unit[evt->unit].events[evt->type] == evt, + ESP_ERR_INVALID_ARG, TAG, "the event handle is not match to registered handle"); + portENTER_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); + s_ana_cmpr_etm_unit[evt->unit].events[evt->type] = NULL; + portEXIT_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); + return ESP_OK; +} + +static esp_err_t ana_cmpr_del_etm_event(esp_etm_event_handle_t base_event) +{ + ana_cmpr_etm_event_t *event = __containerof(base_event, ana_cmpr_etm_event_t, base); + ESP_RETURN_ON_ERROR(ana_cmpr_etm_event_unregister_from_unit(event), TAG, "unregister the event from the unit"); + free(event); + event = NULL; + return ESP_OK; +} + +esp_err_t ana_cmpr_new_etm_event(const ana_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *ret_event) +{ +#if CONFIG_ETM_ENABLE_DEBUG_LOG + esp_log_level_set(TAG, ESP_LOG_DEBUG); +#endif + esp_err_t ret = ESP_OK; + ana_cmpr_etm_event_t *event = NULL; + ESP_GOTO_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + + event = heap_caps_calloc(1, sizeof(ana_cmpr_etm_event_t), ETM_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(event, ESP_ERR_NO_MEM, err, TAG, "no mem for analog comparator event"); + event->unit = config->unit; + event->type = config->event_type; + // register the event channel to the group + ESP_GOTO_ON_ERROR(ana_cmpr_etm_event_register_to_unit(event), err, TAG, "register event channel to group failed"); + + uint32_t event_id = ANALOG_CMPR_LL_ETM_SOURCE(config->unit, config->event_type); + event->base.del = ana_cmpr_del_etm_event; + event->base.event_id = event_id; + event->base.trig_periph = ETM_TRIG_PERIPH_ANA_CMPR; + ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", unit_id=%d", event, event_id, config->unit); + *ret_event = &event->base; + return ESP_OK; + +err: + if (event) { + free(event); + event = NULL; + } + return ret; +} diff --git a/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h b/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h new file mode 100644 index 000000000000..08b205db860d --- /dev/null +++ b/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "esp_etm.h" +#include "driver/ana_cmpr_types.h" + +#if SOC_ANA_CMPR_SUPPORT_ETM + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ANA_CMPR_EVENT_POS_CROSS, + ANA_CMPR_EVENT_NEG_CROSS, +} ana_cmpr_event_type_t; + +typedef struct { + ana_cmpr_unit_t unit; + ana_cmpr_event_type_t event_type; /*!< Which kind of cross type can trigger the ETM event module */ +} ana_cmpr_etm_event_config_t; + +esp_err_t ana_cmpr_new_etm_event(const ana_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *ret_event); + +#ifdef __cplusplus +} +#endif + +#endif // SOC_ANA_CMPR_SUPPORT_ETM diff --git a/components/driver/analog_comparator/include/driver/ana_cmpr_types.h b/components/driver/analog_comparator/include/driver/ana_cmpr_types.h index acafb6ccda92..52a92b5eb141 100644 --- a/components/driver/analog_comparator/include/driver/ana_cmpr_types.h +++ b/components/driver/analog_comparator/include/driver/ana_cmpr_types.h @@ -7,6 +7,7 @@ #pragma once #include +#include "soc/soc_caps.h" #include "soc/clk_tree_defs.h" #ifdef __cplusplus @@ -18,7 +19,10 @@ extern "C" { * */ typedef enum { - ANA_CMPR_UNIT_0, /*!< Analog Comparator unit */ + ANA_CMPR_UNIT_0, /*!< Analog Comparator unit 0 */ +#if SOC_ANA_CMPR_NUM == 2 + ANA_CMPR_UNIT_1, /*!< Analog Comparator unit 1 */ +#endif } ana_cmpr_unit_t; /** diff --git a/components/esp_hw_support/include/esp_private/etm_interface.h b/components/esp_hw_support/include/esp_private/etm_interface.h index 351f89c70246..47958aa7e604 100644 --- a/components/esp_hw_support/include/esp_private/etm_interface.h +++ b/components/esp_hw_support/include/esp_private/etm_interface.h @@ -25,6 +25,7 @@ typedef enum { ETM_TRIG_PERIPH_GPTIMER, /*!< ETM trigger source: GPTimer */ ETM_TRIG_PERIPH_SYSTIMER, /*!< ETM trigger source: Systimer */ ETM_TRIG_PERIPH_MCPWM, /*!< ETM trigger source: MCPWM */ + ETM_TRIG_PERIPH_ANA_CMPR, /*!< ETM trigger source: Analog Comparator */ } etm_trigger_peripheral_t; /** diff --git a/components/hal/esp32p4/include/hal/ana_cmpr_ll.h b/components/hal/esp32p4/include/hal/ana_cmpr_ll.h index 9f4abbf6d373..1ce151c07972 100644 --- a/components/hal/esp32p4/include/hal/ana_cmpr_ll.h +++ b/components/hal/esp32p4/include/hal/ana_cmpr_ll.h @@ -10,6 +10,7 @@ #include "hal/misc.h" #include "hal/assert.h" #include "soc/ana_cmpr_struct.h" +#include "soc/soc_etm_source.h" #ifdef __cplusplus extern "C" { @@ -22,6 +23,8 @@ extern "C" { #define ANALOG_CMPR_LL_NEG_CROSS_MASK(unit) (1UL << ((int)unit * 3)) #define ANALOG_CMPR_LL_POS_CROSS_MASK(unit) (1UL << ((int)unit * 3 + 1)) +#define ANALOG_CMPR_LL_ETM_SOURCE(unit, type) (GPIO_EVT_ZERO_DET_POS0 + (unit) * 2 + (type)) + /** * @brief Enable analog comparator * diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index e5e7e61fd516..f93ed20ca741 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -395,6 +395,14 @@ config SOC_ANA_CMPR_SUPPORT_MULTI_INTR bool default y +config SOC_ANA_CMPR_SUPPORT_ETM + bool + default y + +config SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT + int + default 2 + config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32p4/include/soc/gpio_struct.h b/components/soc/esp32p4/include/soc/gpio_struct.h index 748d4c2b7db8..052c0b9a6db6 100644 --- a/components/soc/esp32p4/include/soc/gpio_struct.h +++ b/components/soc/esp32p4/include/soc/gpio_struct.h @@ -553,7 +553,7 @@ typedef union { uint32_t val; } gpio_clock_gate_reg_t; -/** Type of zero_det0_filter_cnt register +/** Type of zero_det_filter_cnt register * GPIO analog comparator zero detect filter count */ typedef union { diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 8cb49267ba92..987b968e658a 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -221,8 +221,10 @@ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ /*------------------------- Analog Comparator CAPS ---------------------------*/ -#define SOC_ANA_CMPR_NUM (2U) -#define SOC_ANA_CMPR_SUPPORT_MULTI_INTR (1) +#define SOC_ANA_CMPR_NUM (2U) +#define SOC_ANA_CMPR_SUPPORT_MULTI_INTR (1) +#define SOC_ANA_CMPR_SUPPORT_ETM (1) +#define SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT (2) /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-P4 has 2 I2Cs From ff7a11e5393dd2ea9ecb81714873db436432d2f8 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 31 Jul 2023 10:43:54 +0800 Subject: [PATCH 066/142] feat(ana_cmpr): supported etm in analog comparator example --- .../driver/analog_comparator/ana_cmpr.c | 84 +++++++-- .../driver/analog_comparator/ana_cmpr_etm.c | 55 +----- .../analog_comparator/ana_cmpr_private.h | 20 +++ .../include/driver/ana_cmpr.h | 6 + .../include/driver/ana_cmpr_etm.h | 29 ++- .../include/driver/ana_cmpr_types.h | 14 +- components/driver/gpio/gpio.c | 2 +- .../driver/test_apps/.build-test-rules.yml | 4 + .../test_apps/analog_comparator/README.md | 4 +- .../analog_comparator/main/test_ana_cmpr.c | 7 +- .../main/test_ana_cmpr_common.c | 2 +- .../main/test_ana_cmpr_iram.c | 3 +- .../include/esp_private/etm_interface.h | 2 +- .../esp_hw_support/port/esp32c6/io_mux.c | 1 + .../esp_hw_support/port/esp32h2/io_mux.c | 1 + .../esp_hw_support/port/esp32p4/io_mux.c | 34 ++++ .../test_apps/etm/main/CMakeLists.txt | 5 + .../test_apps/etm/main/test_ana_cmpr_etm.c | 167 ++++++++++++++++++ .../hal/esp32h2/include/hal/ana_cmpr_ll.h | 36 ++-- .../hal/esp32p4/include/hal/ana_cmpr_ll.h | 10 +- components/hal/esp32p4/include/hal/gpio_ll.h | 4 + components/soc/esp32h2/ana_cmpr_periph.c | 13 +- .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32h2/include/soc/ana_cmpr_struct.h | 36 ++++ .../soc/esp32h2/include/soc/gpio_ext_struct.h | 5 - components/soc/esp32h2/include/soc/soc_caps.h | 3 +- .../soc/esp32h2/ld/esp32h2.peripherals.ld | 1 - components/soc/esp32p4/ana_cmpr_periph.c | 2 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 6 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 2 +- components/soc/esp32p4/include/soc/soc_caps.h | 7 +- components/soc/include/soc/ana_cmpr_periph.h | 6 +- docs/doxygen/Doxyfile | 1 + .../en/api-reference/peripherals/ana_cmpr.rst | 13 +- docs/en/api-reference/peripherals/etm.rst | 5 +- docs/zh_CN/api-reference/peripherals/etm.rst | 5 +- examples/peripherals/.build-test-rules.yml | 4 + .../peripherals/analog_comparator/README.md | 12 +- .../analog_comparator/main/CMakeLists.txt | 10 +- .../analog_comparator/main/Kconfig.projbuild | 17 +- .../main/ana_cmpr_example_etm.c | 133 ++++++++++++++ .../main/ana_cmpr_example_intr.c | 122 +++++++++++++ .../main/ana_cmpr_example_main.c | 121 +------------ .../main/ana_cmpr_example_main.h | 45 +++++ 44 files changed, 796 insertions(+), 267 deletions(-) create mode 100644 components/driver/analog_comparator/ana_cmpr_private.h create mode 100644 components/esp_hw_support/test_apps/etm/main/test_ana_cmpr_etm.c create mode 100644 components/soc/esp32h2/include/soc/ana_cmpr_struct.h create mode 100644 examples/peripherals/analog_comparator/main/ana_cmpr_example_etm.c create mode 100644 examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c create mode 100644 examples/peripherals/analog_comparator/main/ana_cmpr_example_main.h diff --git a/components/driver/analog_comparator/ana_cmpr.c b/components/driver/analog_comparator/ana_cmpr.c index c560f179344f..f417c2a02a31 100644 --- a/components/driver/analog_comparator/ana_cmpr.c +++ b/components/driver/analog_comparator/ana_cmpr.c @@ -25,6 +25,7 @@ #include "soc/ana_cmpr_periph.h" #include "hal/ana_cmpr_ll.h" #include "driver/ana_cmpr.h" +#include "driver/gpio.h" #include "esp_private/io_mux.h" #include "esp_private/esp_clk.h" @@ -36,6 +37,7 @@ struct ana_cmpr_t { ana_cmpr_event_callbacks_t cbs; /*!< The callback group that set by user */ intr_handle_t intr_handle; /*!< Interrupt handle */ uint32_t intr_mask; /*!< Interrupt mask */ + int intr_priority; /*!< Interrupt priority */ void *user_data; /*!< User data that passed to the callbacks */ uint32_t src_clk_freq_hz; /*!< Source clock frequency of the Analog Comparator unit */ esp_pm_lock_handle_t pm_lock; /*!< The Power Management lock that used to avoid unexpected power down of the clock domain */ @@ -44,16 +46,16 @@ struct ana_cmpr_t { /* Helper macros */ #define ANA_CMPR_NULL_POINTER_CHECK(p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, TAG, "input parameter '"#p"' is NULL") #define ANA_CMPR_NULL_POINTER_CHECK_ISR(p) ESP_RETURN_ON_FALSE_ISR((p), ESP_ERR_INVALID_ARG, TAG, "input parameter '"#p"' is NULL") -#define ANA_CMPR_UNIT_CHECK(unit) ESP_RETURN_ON_FALSE((unit) >= ANA_CMPR_UNIT_0 && (unit) < SOC_ANA_CMPR_NUM, \ +#define ANA_CMPR_UNIT_CHECK(unit) ESP_RETURN_ON_FALSE((unit) >= 0 && (unit) < SOC_ANA_CMPR_NUM, \ ESP_ERR_INVALID_ARG, TAG, "invalid uint number"); /* Memory allocation caps which decide the section that memory supposed to allocate */ #if CONFIG_ANA_CMPR_ISR_IRAM_SAFE #define ANA_CMPR_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) -#define ANA_CMPR_INTR_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM) // Shared with GPIO +#define ANA_CMPR_INTR_FLAG (ESP_INTR_FLAG_IRAM) #else #define ANA_CMPR_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT -#define ANA_CMPR_INTR_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED) // Shared with GPIO +#define ANA_CMPR_INTR_FLAG (0) #endif /* Driver tag */ @@ -71,20 +73,20 @@ static void IRAM_ATTR s_ana_cmpr_default_intr_handler(void *usr_data) { ana_cmpr_handle_t cmpr_handle = (ana_cmpr_handle_t)usr_data; bool need_yield = false; - ana_cmpr_cross_event_data_t evt_data; + ana_cmpr_cross_event_data_t evt_data = {.cross_type = ANA_CMPR_CROSS_ANY}; /* Get and clear the interrupt status */ uint32_t status = analog_cmpr_ll_get_intr_status(cmpr_handle->dev); analog_cmpr_ll_clear_intr(cmpr_handle->dev, status); /* Call the user callback function if it is specified and the corresponding event triggers*/ if (cmpr_handle->cbs.on_cross && (status & cmpr_handle->intr_mask)) { -#if SOC_ANA_CMPR_SUPPORT_MULTI_INTR +#if SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE if (status & ANALOG_CMPR_LL_POS_CROSS_MASK(cmpr_handle->unit)) { evt_data.cross_type = ANA_CMPR_CROSS_POS; } else if (status & ANALOG_CMPR_LL_NEG_CROSS_MASK(cmpr_handle->unit)) { evt_data.cross_type = ANA_CMPR_CROSS_NEG; } -#endif // SOC_ANA_CMPR_SUPPORT_MULTI_INTR +#endif // SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE need_yield = cmpr_handle->cbs.on_cross(cmpr_handle, &evt_data, cmpr_handle->user_data); } if (need_yield) { @@ -92,6 +94,22 @@ static void IRAM_ATTR s_ana_cmpr_default_intr_handler(void *usr_data) } } +static esp_err_t s_ana_cmpr_init_gpio(ana_cmpr_handle_t cmpr, bool is_external_ref) +{ + uint64_t pin_mask = BIT64(ana_cmpr_periph[cmpr->unit].src_gpio); + if (is_external_ref) { + pin_mask |= BIT64(ana_cmpr_periph[cmpr->unit].ext_ref_gpio); + } + gpio_config_t ana_cmpr_gpio_cfg = { + .pin_bit_mask = pin_mask, + .mode = GPIO_MODE_DISABLE, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + return gpio_config(&ana_cmpr_gpio_cfg); +} + esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t *ret_cmpr) { #if CONFIG_ANA_CMPR_ENABLE_DEBUG_LOG @@ -101,6 +119,7 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t * ANA_CMPR_NULL_POINTER_CHECK(ret_cmpr); ana_cmpr_unit_t unit = config->unit; ANA_CMPR_UNIT_CHECK(unit); + ESP_RETURN_ON_FALSE(config->intr_priority >= 0 && config->intr_priority <= 7, ESP_ERR_INVALID_ARG, TAG, "interrupt priority should be within 0~7"); ESP_RETURN_ON_FALSE(!s_ana_cmpr[unit], ESP_ERR_INVALID_STATE, TAG, "unit has been allocated already"); esp_err_t ret = ESP_OK; @@ -112,6 +131,7 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t * /* Assign analog comparator unit */ s_ana_cmpr[unit]->dev = ANALOG_CMPR_LL_GET_HW(unit); s_ana_cmpr[unit]->ref_src = config->ref_src; + s_ana_cmpr[unit]->intr_priority = config->intr_priority; s_ana_cmpr[unit]->is_enabled = false; s_ana_cmpr[unit]->pm_lock = NULL; @@ -123,6 +143,10 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t * ESP_GOTO_ON_ERROR(ret, err, TAG, "create NO_LIGHT_SLEEP, lock failed"); #endif + if (!config->flags.io_loop_back) { + ESP_GOTO_ON_ERROR(s_ana_cmpr_init_gpio(s_ana_cmpr[unit], config->ref_src == ANA_CMPR_REF_SRC_EXTERNAL), err, TAG, "failed to initialize GPIO"); + } + /* Analog clock comes from IO MUX, but IO MUX clock might be shared with other submodules as well */ ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)config->clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, @@ -134,23 +158,19 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t * /* Configure the register */ portENTER_CRITICAL(&s_spinlock); analog_cmpr_ll_set_ref_source(s_ana_cmpr[unit]->dev, config->ref_src); -#if !SOC_ANA_CMPR_SUPPORT_MULTI_INTR +#if !SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE analog_cmpr_ll_set_cross_type(s_ana_cmpr[unit]->dev, config->cross_type); -#endif // SOC_ANA_CMPR_SUPPORT_MULTI_INTR - portEXIT_CRITICAL(&s_spinlock); - - /* Allocate the interrupt, currently the interrupt source of Analog Comparator is shared with GPIO interrupt source */ +#endif // SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE + /* Record the interrupt mask, the interrupt will be lazy installed when register the callbacks */ s_ana_cmpr[unit]->intr_mask = analog_cmpr_ll_get_intr_mask_by_type(s_ana_cmpr[unit]->dev, config->cross_type); - ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(ana_cmpr_io_map[unit].intr_src, ANA_CMPR_INTR_FLAG, (uint32_t)analog_cmpr_ll_get_intr_status_reg(s_ana_cmpr[unit]->dev), - s_ana_cmpr[unit]->intr_mask, s_ana_cmpr_default_intr_handler, s_ana_cmpr[unit], &s_ana_cmpr[unit]->intr_handle), - err, TAG, "allocate interrupt failed"); + portEXIT_CRITICAL(&s_spinlock); if (config->ref_src == ANA_CMPR_REF_SRC_INTERNAL) { ESP_LOGD(TAG, "unit %d allocated, source signal: GPIO %d, reference signal: internal", - (int)unit, ana_cmpr_io_map[unit].src_gpio); + (int)unit, ana_cmpr_periph[unit].src_gpio); } else { ESP_LOGD(TAG, "unit %d allocated, source signal: GPIO %d, reference signal: GPIO %d", - (int)unit, ana_cmpr_io_map[unit].src_gpio, ana_cmpr_io_map[unit].ext_ref_gpio); + (int)unit, ana_cmpr_periph[unit].src_gpio, ana_cmpr_periph[unit].ext_ref_gpio); } *ret_cmpr = s_ana_cmpr[unit]; @@ -230,12 +250,19 @@ esp_err_t ana_cmpr_set_debounce(ana_cmpr_handle_t cmpr, const ana_cmpr_debounce_ esp_err_t ana_cmpr_set_cross_type(ana_cmpr_handle_t cmpr, ana_cmpr_cross_type_t cross_type) { +#if SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE + /* Not support to set the cross type after initialized, because it relies on the interrupt types to distinguish the edge, + * i.e. have to re-allocate the interrupt to change the cross type */ + (void)cmpr; + (void)cross_type; + return ESP_ERR_NOT_SUPPORTED; +#else ANA_CMPR_NULL_POINTER_CHECK_ISR(cmpr); ESP_RETURN_ON_FALSE_ISR(cross_type >= ANA_CMPR_CROSS_DISABLE && cross_type <= ANA_CMPR_CROSS_ANY, ESP_ERR_INVALID_ARG, TAG, "invalid cross type"); portENTER_CRITICAL_SAFE(&s_spinlock); -#if !SOC_ANA_CMPR_SUPPORT_MULTI_INTR +#if !SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE analog_cmpr_ll_set_cross_type(cmpr->dev, cross_type); #endif cmpr->intr_mask = analog_cmpr_ll_get_intr_mask_by_type(cmpr->dev, cross_type); @@ -244,6 +271,7 @@ esp_err_t ana_cmpr_set_cross_type(ana_cmpr_handle_t cmpr, ana_cmpr_cross_type_t ESP_EARLY_LOGD(TAG, "unit %d cross type updated to %d", (int)cmpr->unit, cross_type); return ESP_OK; +#endif } esp_err_t ana_cmpr_register_event_callbacks(ana_cmpr_handle_t cmpr, const ana_cmpr_event_callbacks_t *cbs, void *user_data) @@ -263,6 +291,16 @@ esp_err_t ana_cmpr_register_event_callbacks(ana_cmpr_handle_t cmpr, const ana_cm } #endif + /* Allocate the interrupt, the interrupt source of Analog Comparator is shared with GPIO interrupt source on ESP32H2 */ + if (!cmpr->intr_handle) { + int intr_flags = ANA_CMPR_INTR_FLAG | (cmpr->intr_priority ? BIT(cmpr->intr_priority) : ESP_INTR_FLAG_LOWMED); +#if SOC_ANA_CMPR_INTR_SHARE_WITH_GPIO + intr_flags |= ESP_INTR_FLAG_SHARED; +#endif // SOC_ANA_CMPR_INTR_SHARE_WITH_GPIO + ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(ana_cmpr_periph[cmpr->unit].intr_src, intr_flags, (uint32_t)analog_cmpr_ll_get_intr_status_reg(cmpr->dev), + cmpr->intr_mask, s_ana_cmpr_default_intr_handler, cmpr, &cmpr->intr_handle), TAG, "allocate interrupt failed"); + } + /* Save the callback group */ memcpy(&(cmpr->cbs), cbs, sizeof(ana_cmpr_event_callbacks_t)); cmpr->user_data = user_data; @@ -327,10 +365,10 @@ esp_err_t ana_cmpr_get_gpio(ana_cmpr_unit_t unit, ana_cmpr_channel_type_t chan_t /* Get the gpio number according to the channel type */ switch (chan_type) { case ANA_CMPR_SOURCE_CHAN: - *gpio_num = ana_cmpr_io_map[unit].src_gpio; + *gpio_num = ana_cmpr_periph[unit].src_gpio; break; case ANA_CMPR_EXT_REF_CHAN: - *gpio_num = ana_cmpr_io_map[unit].ext_ref_gpio; + *gpio_num = ana_cmpr_periph[unit].ext_ref_gpio; break; default: ESP_LOGE(TAG, "invalid channel type"); @@ -339,3 +377,11 @@ esp_err_t ana_cmpr_get_gpio(ana_cmpr_unit_t unit, ana_cmpr_channel_type_t chan_t return ESP_OK; } + +ana_cmpr_unit_t ana_cmpr_priv_get_unit_by_handle(ana_cmpr_handle_t cmpr) +{ + if (!cmpr) { + return -1; + } + return cmpr->unit; +} diff --git a/components/driver/analog_comparator/ana_cmpr_etm.c b/components/driver/analog_comparator/ana_cmpr_etm.c index 0c9494c680df..02dc491269de 100644 --- a/components/driver/analog_comparator/ana_cmpr_etm.c +++ b/components/driver/analog_comparator/ana_cmpr_etm.c @@ -21,81 +21,42 @@ #include "driver/ana_cmpr_types.h" #include "driver/ana_cmpr_etm.h" #include "esp_private/etm_interface.h" +#include "ana_cmpr_private.h" static const char *TAG = "ana-cmpr-etm"; #define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT -typedef struct ana_cmpr_etm_event_t ana_cmpr_etm_event_t; - typedef struct { - portMUX_TYPE spinlock; - ana_cmpr_etm_event_t *events[SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT]; -} ana_cmpr_etm_unit_t; - -struct ana_cmpr_etm_event_t { esp_etm_event_t base; - ana_cmpr_unit_t unit; - ana_cmpr_event_type_t type; -}; - -static ana_cmpr_etm_unit_t s_ana_cmpr_etm_unit[SOC_ANA_CMPR_NUM] = { - [0 ... SOC_ANA_CMPR_NUM - 1] = { - .spinlock = portMUX_INITIALIZER_UNLOCKED, - .events[0 ... SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT - 1] = NULL, - }, -}; - -static esp_err_t ana_cmpr_etm_event_register_to_unit(ana_cmpr_etm_event_t *evt) -{ - ESP_RETURN_ON_FALSE(!s_ana_cmpr_etm_unit[evt->unit].events[evt->type], - ESP_ERR_INVALID_STATE, TAG, "this event has been registered on the unit"); - portENTER_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); - s_ana_cmpr_etm_unit[evt->unit].events[evt->type] = evt; - portEXIT_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); - return ESP_OK; -} - -static esp_err_t ana_cmpr_etm_event_unregister_from_unit(ana_cmpr_etm_event_t *evt) -{ - ESP_RETURN_ON_FALSE(s_ana_cmpr_etm_unit[evt->unit].events[evt->type] == evt, - ESP_ERR_INVALID_ARG, TAG, "the event handle is not match to registered handle"); - portENTER_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); - s_ana_cmpr_etm_unit[evt->unit].events[evt->type] = NULL; - portEXIT_CRITICAL(&s_ana_cmpr_etm_unit[evt->unit].spinlock); - return ESP_OK; -} +} ana_cmpr_etm_event_t; static esp_err_t ana_cmpr_del_etm_event(esp_etm_event_handle_t base_event) { ana_cmpr_etm_event_t *event = __containerof(base_event, ana_cmpr_etm_event_t, base); - ESP_RETURN_ON_ERROR(ana_cmpr_etm_event_unregister_from_unit(event), TAG, "unregister the event from the unit"); free(event); event = NULL; return ESP_OK; } -esp_err_t ana_cmpr_new_etm_event(const ana_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *ret_event) +esp_err_t ana_cmpr_new_etm_event(ana_cmpr_handle_t cmpr, const ana_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *ret_event) { #if CONFIG_ETM_ENABLE_DEBUG_LOG esp_log_level_set(TAG, ESP_LOG_DEBUG); #endif esp_err_t ret = ESP_OK; ana_cmpr_etm_event_t *event = NULL; - ESP_GOTO_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - + ana_cmpr_unit_t unit = ana_cmpr_priv_get_unit_by_handle(cmpr); + ESP_RETURN_ON_FALSE(((int)unit) >= 0, ESP_ERR_INVALID_ARG, TAG, "invalid analog comparator handle"); + ESP_RETURN_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); event = heap_caps_calloc(1, sizeof(ana_cmpr_etm_event_t), ETM_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(event, ESP_ERR_NO_MEM, err, TAG, "no mem for analog comparator event"); - event->unit = config->unit; - event->type = config->event_type; - // register the event channel to the group - ESP_GOTO_ON_ERROR(ana_cmpr_etm_event_register_to_unit(event), err, TAG, "register event channel to group failed"); - uint32_t event_id = ANALOG_CMPR_LL_ETM_SOURCE(config->unit, config->event_type); + uint32_t event_id = ANALOG_CMPR_LL_ETM_SOURCE(unit, config->event_type); event->base.del = ana_cmpr_del_etm_event; event->base.event_id = event_id; event->base.trig_periph = ETM_TRIG_PERIPH_ANA_CMPR; - ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", unit_id=%d", event, event_id, config->unit); + ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", unit_id=%d", event, event_id, unit); *ret_event = &event->base; return ESP_OK; diff --git a/components/driver/analog_comparator/ana_cmpr_private.h b/components/driver/analog_comparator/ana_cmpr_private.h new file mode 100644 index 000000000000..4bbacb9c0cc2 --- /dev/null +++ b/components/driver/analog_comparator/ana_cmpr_private.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "driver/ana_cmpr_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ana_cmpr_unit_t ana_cmpr_priv_get_unit_by_handle(ana_cmpr_handle_t cmpr); + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/analog_comparator/include/driver/ana_cmpr.h b/components/driver/analog_comparator/include/driver/ana_cmpr.h index 4cd09852b13b..d10b1e0a74f5 100644 --- a/components/driver/analog_comparator/include/driver/ana_cmpr.h +++ b/components/driver/analog_comparator/include/driver/ana_cmpr.h @@ -28,6 +28,12 @@ typedef struct { * for external reference, the reference signal should be connect to `ANA_CMPRx_EXT_REF_GPIO` */ ana_cmpr_cross_type_t cross_type; /*!< The crossing types that can trigger interrupt */ + int intr_priority; /*!< The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) + * otherwise the larger the higher, 7 is NMI */ + struct { + uint32_t io_loop_back:1; /*!< Enable this field when the other signals that output on the comparision pins are supposed to be fed back. + * Normally used for debug/test scenario */ + } flags; /*!< Analog comparator driver flags */ } ana_cmpr_config_t; /** diff --git a/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h b/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h index 08b205db860d..dce83452386d 100644 --- a/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h +++ b/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h @@ -17,17 +17,36 @@ extern "C" { #endif +/** + * @brief Analog Comparator ETM Events for each unit + * + */ typedef enum { - ANA_CMPR_EVENT_POS_CROSS, - ANA_CMPR_EVENT_NEG_CROSS, + ANA_CMPR_EVENT_POS_CROSS, /*!< Positive cross event when the source signal becomes higher than the reference signal */ + ANA_CMPR_EVENT_NEG_CROSS, /*!< Negative cross event when the source signal becomes lower than the reference signal */ } ana_cmpr_event_type_t; +/** + * @brief Analog Comparator ETM event configuration + * + */ typedef struct { - ana_cmpr_unit_t unit; - ana_cmpr_event_type_t event_type; /*!< Which kind of cross type can trigger the ETM event module */ + ana_cmpr_event_type_t event_type; /*!< Which kind of cross type can trigger the ETM event module */ } ana_cmpr_etm_event_config_t; -esp_err_t ana_cmpr_new_etm_event(const ana_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *ret_event); +/** + * @brief Allocate a new Analog Comparator ETM event + * + * @param[in] cmpr Analog Comparator handle that allocated by `ana_cmpr_new_unit` + * @param[in] config Analog Comparator ETM event configuration + * @param[out] ret_event The returned generic handle of ETM event, which is used to connect to a task in the ETM driver + * @return + * - ESP_OK Success to create the new ETM event handle + * - ESP_ERR_NO_MEM No memory for the ETM event + * - ESP_ERR_INVALID_ARG NULL pointer of the input parameters + * - ESP_ERR_INVALID_STATE The event on the unit has been registered + */ +esp_err_t ana_cmpr_new_etm_event(ana_cmpr_handle_t cmpr, const ana_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *ret_event); #ifdef __cplusplus } diff --git a/components/driver/analog_comparator/include/driver/ana_cmpr_types.h b/components/driver/analog_comparator/include/driver/ana_cmpr_types.h index 52a92b5eb141..978509262097 100644 --- a/components/driver/analog_comparator/include/driver/ana_cmpr_types.h +++ b/components/driver/analog_comparator/include/driver/ana_cmpr_types.h @@ -18,12 +18,9 @@ extern "C" { * @brief Analog comparator unit * */ -typedef enum { - ANA_CMPR_UNIT_0, /*!< Analog Comparator unit 0 */ -#if SOC_ANA_CMPR_NUM == 2 - ANA_CMPR_UNIT_1, /*!< Analog Comparator unit 1 */ -#endif -} ana_cmpr_unit_t; +typedef int ana_cmpr_unit_t; + +#define ANA_CMPR_UNIT_0 0 /*!< @deprecated Analog comparator unit 0 */ /** * @brief Analog comparator reference source @@ -94,10 +91,9 @@ typedef int ana_cmpr_clk_src_t; * */ typedef struct { -#if SOC_ANA_CMPR_SUPPORT_MULTI_INTR ana_cmpr_cross_type_t cross_type; /*!< The cross type of the target signal to the reference signal. - * Will either be ANA_CMPR_CROSS_POS or ANA_CMPR_CROSS_NEG */ -#endif + * Will either be ANA_CMPR_CROSS_POS or ANA_CMPR_CROSS_NEG + * Always be ANA_CMPR_CROSS_ANY if target does not support independent interrupt (like ESP32H2) */ } ana_cmpr_cross_event_data_t; /** diff --git a/components/driver/gpio/gpio.c b/components/driver/gpio/gpio.c index 3cea507013c2..b6f4324607ed 100644 --- a/components/driver/gpio/gpio.c +++ b/components/driver/gpio/gpio.c @@ -594,7 +594,7 @@ esp_err_t gpio_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, p.source = ETS_GPIO_INTR0_SOURCE; #endif p.intr_alloc_flags = intr_alloc_flags; -#if SOC_ANA_CMPR_SUPPORTED +#if SOC_ANA_CMPR_INTR_SHARE_WITH_GPIO p.intr_alloc_flags |= ESP_INTR_FLAG_SHARED; #endif p.fn = fn; diff --git a/components/driver/test_apps/.build-test-rules.yml b/components/driver/test_apps/.build-test-rules.yml index d13e5809a912..5af096497f9d 100644 --- a/components/driver/test_apps/.build-test-rules.yml +++ b/components/driver/test_apps/.build-test-rules.yml @@ -3,6 +3,10 @@ components/driver/test_apps/analog_comparator: disable: - if: SOC_ANA_CMPR_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: not supported yet components/driver/test_apps/dac_test_apps/dac: disable: diff --git a/components/driver/test_apps/analog_comparator/README.md b/components/driver/test_apps/analog_comparator/README.md index 8161d00f6d8e..bde3cf8e7385 100644 --- a/components/driver/test_apps/analog_comparator/README.md +++ b/components/driver/test_apps/analog_comparator/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-H2 | -| ----------------- | -------- | +| Supported Targets | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | diff --git a/components/driver/test_apps/analog_comparator/main/test_ana_cmpr.c b/components/driver/test_apps/analog_comparator/main/test_ana_cmpr.c index 53a69ea9c7f0..b24776e455ed 100644 --- a/components/driver/test_apps/analog_comparator/main/test_ana_cmpr.c +++ b/components/driver/test_apps/analog_comparator/main/test_ana_cmpr.c @@ -18,7 +18,7 @@ TEST_CASE("ana_cmpr_unit_install_uninstall", "[ana_cmpr]") /* Allocate a wrong unit */ TEST_ESP_ERR(ESP_ERR_INVALID_ARG, ana_cmpr_new_unit(&config, &cmpr)); /* Allocate a correct unit */ - config.unit = ANA_CMPR_UNIT_0; + config.unit = 0; TEST_ESP_OK(ana_cmpr_new_unit(&config, &cmpr)); /* Try to allocate a existed unit */ TEST_ESP_ERR(ESP_ERR_INVALID_STATE, ana_cmpr_new_unit(&config, &cmpr)); @@ -51,14 +51,15 @@ TEST_CASE("ana_cmpr_unit_install_uninstall", "[ana_cmpr]") TEST_CASE("ana_cmpr_internal_reference", "[ana_cmpr]") { int src_chan = test_init_src_chan_gpio(); - uint32_t cnt = 0; + uint32_t cnt = 0; ana_cmpr_handle_t cmpr = NULL; ana_cmpr_config_t config = { - .unit = ANA_CMPR_UNIT_0, + .unit = 0, .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, .ref_src = ANA_CMPR_REF_SRC_INTERNAL, .cross_type = ANA_CMPR_CROSS_ANY, + .flags.io_loop_back = 1, }; TEST_ESP_OK(ana_cmpr_new_unit(&config, &cmpr)); ana_cmpr_internal_ref_config_t ref_cfg = { diff --git a/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_common.c b/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_common.c index 9db12a0d07fe..0feb218ea666 100644 --- a/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_common.c +++ b/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_common.c @@ -19,7 +19,7 @@ bool IRAM_ATTR test_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr, const ana int test_init_src_chan_gpio(void) { int src_chan_num = -1; - TEST_ESP_OK(ana_cmpr_get_gpio(ANA_CMPR_UNIT_0, ANA_CMPR_SOURCE_CHAN, &src_chan_num)); + TEST_ESP_OK(ana_cmpr_get_gpio(0, ANA_CMPR_SOURCE_CHAN, &src_chan_num)); TEST_ASSERT(src_chan_num > 0); gpio_config_t io_conf = { .intr_type = GPIO_INTR_DISABLE, diff --git a/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_iram.c b/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_iram.c index ce0d5425f995..44da8afacd6e 100644 --- a/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_iram.c +++ b/components/driver/test_apps/analog_comparator/main/test_ana_cmpr_iram.c @@ -44,10 +44,11 @@ TEST_CASE("ana_cmpr_internal_reference_iram_safe", "[ana_cmpr]") ana_cmpr_handle_t cmpr = NULL; ana_cmpr_config_t config = { - .unit = ANA_CMPR_UNIT_0, + .unit = 0, .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, .ref_src = ANA_CMPR_REF_SRC_INTERNAL, .cross_type = ANA_CMPR_CROSS_ANY, + .flags.io_loop_back = 1, }; TEST_ESP_OK(ana_cmpr_new_unit(&config, &cmpr)); test_data.handle = cmpr; diff --git a/components/esp_hw_support/include/esp_private/etm_interface.h b/components/esp_hw_support/include/esp_private/etm_interface.h index 47958aa7e604..a7c7e4253886 100644 --- a/components/esp_hw_support/include/esp_private/etm_interface.h +++ b/components/esp_hw_support/include/esp_private/etm_interface.h @@ -25,7 +25,7 @@ typedef enum { ETM_TRIG_PERIPH_GPTIMER, /*!< ETM trigger source: GPTimer */ ETM_TRIG_PERIPH_SYSTIMER, /*!< ETM trigger source: Systimer */ ETM_TRIG_PERIPH_MCPWM, /*!< ETM trigger source: MCPWM */ - ETM_TRIG_PERIPH_ANA_CMPR, /*!< ETM trigger source: Analog Comparator */ + ETM_TRIG_PERIPH_ANA_CMPR, /*!< ETM trigger source: Analog Comparator */ } etm_trigger_peripheral_t; /** diff --git a/components/esp_hw_support/port/esp32c6/io_mux.c b/components/esp_hw_support/port/esp32c6/io_mux.c index ea7446b2baaf..e5679e40b4bd 100644 --- a/components/esp_hw_support/port/esp32c6/io_mux.c +++ b/components/esp_hw_support/port/esp32c6/io_mux.c @@ -28,5 +28,6 @@ esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src) } gpio_ll_iomux_set_clk_src(clk_src); + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32h2/io_mux.c b/components/esp_hw_support/port/esp32h2/io_mux.c index a621deb8a31c..653c0b298129 100644 --- a/components/esp_hw_support/port/esp32h2/io_mux.c +++ b/components/esp_hw_support/port/esp32h2/io_mux.c @@ -28,5 +28,6 @@ esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src) } gpio_ll_iomux_set_clk_src(clk_src); + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32p4/io_mux.c b/components/esp_hw_support/port/esp32p4/io_mux.c index e69de29bb2d1..10e021aba0f8 100644 --- a/components/esp_hw_support/port/esp32p4/io_mux.c +++ b/components/esp_hw_support/port/esp32p4/io_mux.c @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "freertos/FreeRTOS.h" +#include "esp_private/io_mux.h" +#include "esp_private/periph_ctrl.h" +#include "hal/gpio_ll.h" + +static portMUX_TYPE s_io_mux_spinlock = portMUX_INITIALIZER_UNLOCKED; +static soc_module_clk_t s_io_mux_clk_src = 0; // by default, the clock source is not set explicitly by any consumer (e.g. SDM, Filter) + +esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src) +{ + bool clk_conflict = false; + // check is the IO MUX has been set to another clock source + portENTER_CRITICAL(&s_io_mux_spinlock); + if (s_io_mux_clk_src != 0 && s_io_mux_clk_src != clk_src) { + clk_conflict = true; + } else { + s_io_mux_clk_src = clk_src; + } + portEXIT_CRITICAL(&s_io_mux_spinlock); + + if (clk_conflict) { + return ESP_ERR_INVALID_STATE; + } + PERIPH_RCC_ATOMIC() { + gpio_ll_iomux_set_clk_src(clk_src); + } + return ESP_OK; +} diff --git a/components/esp_hw_support/test_apps/etm/main/CMakeLists.txt b/components/esp_hw_support/test_apps/etm/main/CMakeLists.txt index 14c910836c8e..e7a895debdcb 100644 --- a/components/esp_hw_support/test_apps/etm/main/CMakeLists.txt +++ b/components/esp_hw_support/test_apps/etm/main/CMakeLists.txt @@ -21,6 +21,11 @@ if(CONFIG_SOC_MCPWM_SUPPORT_ETM) list(APPEND srcs "test_mcpwm_etm.c") endif() +if(CONFIG_SOC_ANA_CMPR_SUPPORT_ETM AND CONFIG_SOC_TIMER_SUPPORT_ETM) + # Analog Comparator event test relies on GPTIMER task + list(APPEND srcs "test_ana_cmpr_etm.c") +endif() + # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} diff --git a/components/esp_hw_support/test_apps/etm/main/test_ana_cmpr_etm.c b/components/esp_hw_support/test_apps/etm/main/test_ana_cmpr_etm.c new file mode 100644 index 000000000000..348662862807 --- /dev/null +++ b/components/esp_hw_support/test_apps/etm/main/test_ana_cmpr_etm.c @@ -0,0 +1,167 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "unity.h" +#include "unity_test_utils.h" +#include "esp_attr.h" +#include "esp_etm.h" +#include "driver/gpio.h" +#include "driver/gptimer.h" +#include "driver/ana_cmpr.h" +#include "driver/gptimer_etm.h" +#include "driver/ana_cmpr_etm.h" + +#define TEST_ANA_CMPR_UNIT 0 +#define TEST_TIME_US 5000 + +static gptimer_handle_t s_test_ana_cmpr_gptimer_init(void) +{ + gptimer_handle_t gptimer = NULL; + gptimer_config_t timer_config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us + }; + TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer)); + TEST_ESP_OK(gptimer_set_raw_count(gptimer, 0)); + TEST_ESP_OK(gptimer_enable(gptimer)); + return gptimer; +} + +static void s_test_ana_cmpr_gptimer_deinit(gptimer_handle_t gptimer) +{ + TEST_ESP_OK(gptimer_disable(gptimer)); + TEST_ESP_OK(gptimer_del_timer(gptimer)); +} + +static ana_cmpr_handle_t s_test_ana_cmpr_init(void) +{ + ana_cmpr_handle_t cmpr = NULL; + + ana_cmpr_config_t config = { + .unit = TEST_ANA_CMPR_UNIT, + .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, + .ref_src = ANA_CMPR_REF_SRC_INTERNAL, + .cross_type = ANA_CMPR_CROSS_ANY, + }; + TEST_ESP_OK(ana_cmpr_new_unit(&config, &cmpr)); + + ana_cmpr_internal_ref_config_t ref_cfg = { + .ref_volt = ANA_CMPR_REF_VOLT_50_PCT_VDD, + }; + TEST_ESP_OK(ana_cmpr_set_internal_reference(cmpr, &ref_cfg)); + + ana_cmpr_debounce_config_t dbc_cfg = { + .wait_us = 10, + }; + TEST_ESP_OK(ana_cmpr_set_debounce(cmpr, &dbc_cfg)); + TEST_ESP_OK(ana_cmpr_enable(cmpr)); + + return cmpr; +} + +static void s_test_ana_cmpr_deinit(ana_cmpr_handle_t cmpr) +{ + TEST_ESP_OK(ana_cmpr_disable(cmpr)); + TEST_ESP_OK(ana_cmpr_del_unit(cmpr)); +} + +static int s_test_ana_cmpr_src_gpio_init(void) +{ + int gpio_num = -1; + TEST_ESP_OK(ana_cmpr_get_gpio(TEST_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &gpio_num)); + gpio_config_t io_conf = { + .intr_type = GPIO_INTR_DISABLE, + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = (1ULL << gpio_num), + .pull_down_en = false, + .pull_up_en = false, + }; + gpio_config(&io_conf); + gpio_set_level(gpio_num, 1); + return gpio_num; +} + +typedef struct { + esp_etm_event_handle_t cmpr_pos_evt; + esp_etm_event_handle_t cmpr_neg_evt; + esp_etm_task_handle_t gptimer_start_task; + esp_etm_task_handle_t gptimer_stop_task; + esp_etm_channel_handle_t etm_pos_handle; + esp_etm_channel_handle_t etm_neg_handle; +} test_ana_cmpr_etm_handles_t; + +static test_ana_cmpr_etm_handles_t s_test_ana_cmpr_init_etm(ana_cmpr_handle_t cmpr, gptimer_handle_t gptimer) +{ + test_ana_cmpr_etm_handles_t etm_handles = {}; + + /* Allocate the analog comparator positive & negative cross events */ + ana_cmpr_etm_event_config_t evt_cfg = { + .event_type = ANA_CMPR_EVENT_POS_CROSS, + }; + TEST_ESP_OK(ana_cmpr_new_etm_event(cmpr, &evt_cfg, &etm_handles.cmpr_pos_evt)); + evt_cfg.event_type = GPIO_ETM_EVENT_EDGE_NEG; + TEST_ESP_OK(ana_cmpr_new_etm_event(cmpr, &evt_cfg, &etm_handles.cmpr_neg_evt)); + + /* Allocate the GPTimer tasks */ + gptimer_etm_task_config_t gptimer_etm_task_conf = { + .task_type = GPTIMER_ETM_TASK_START_COUNT, + }; + TEST_ESP_OK(gptimer_new_etm_task(gptimer, &gptimer_etm_task_conf, &etm_handles.gptimer_start_task)); + gptimer_etm_task_conf.task_type = GPTIMER_ETM_TASK_STOP_COUNT; + TEST_ESP_OK(gptimer_new_etm_task(gptimer, &gptimer_etm_task_conf, &etm_handles.gptimer_stop_task)); + + /* Allocate the Event Task Matrix channels */ + esp_etm_channel_config_t etm_cfg = {}; + TEST_ESP_OK(esp_etm_new_channel(&etm_cfg, &etm_handles.etm_pos_handle)); + TEST_ESP_OK(esp_etm_new_channel(&etm_cfg, &etm_handles.etm_neg_handle)); + /* Bind the events and tasks */ + TEST_ESP_OK(esp_etm_channel_connect(etm_handles.etm_pos_handle, etm_handles.cmpr_pos_evt, etm_handles.gptimer_start_task)); + TEST_ESP_OK(esp_etm_channel_connect(etm_handles.etm_neg_handle, etm_handles.cmpr_neg_evt, etm_handles.gptimer_stop_task)); + /* Enable the ETM channels */ + TEST_ESP_OK(esp_etm_channel_enable(etm_handles.etm_pos_handle)); + TEST_ESP_OK(esp_etm_channel_enable(etm_handles.etm_neg_handle)); + + return etm_handles; +} + +static void s_test_ana_cmpr_deinit_etm(test_ana_cmpr_etm_handles_t handles) +{ + TEST_ESP_OK(esp_etm_channel_disable(handles.etm_pos_handle)); + TEST_ESP_OK(esp_etm_channel_disable(handles.etm_pos_handle)); + + TEST_ESP_OK(esp_etm_del_task(handles.gptimer_start_task)); + TEST_ESP_OK(esp_etm_del_task(handles.gptimer_stop_task)); + + TEST_ESP_OK(esp_etm_del_event(handles.cmpr_pos_evt)); + TEST_ESP_OK(esp_etm_del_event(handles.cmpr_neg_evt)); + + TEST_ESP_OK(esp_etm_del_channel(handles.etm_pos_handle)); + TEST_ESP_OK(esp_etm_del_channel(handles.etm_neg_handle)); +} + +TEST_CASE("analog_comparator_etm_event", "[etm]") +{ + gptimer_handle_t gptimer = s_test_ana_cmpr_gptimer_init(); + ana_cmpr_handle_t cmpr = s_test_ana_cmpr_init(); + int src_gpio = s_test_ana_cmpr_src_gpio_init(); + test_ana_cmpr_etm_handles_t handles = s_test_ana_cmpr_init_etm(cmpr, gptimer); + + gpio_set_level(src_gpio, 0); + esp_rom_delay_us(TEST_TIME_US); + gpio_set_level(src_gpio, 1); + + uint64_t cnt_us = 0; + TEST_ESP_OK(gptimer_get_raw_count(gptimer, &cnt_us)); + + s_test_ana_cmpr_deinit_etm(handles); + s_test_ana_cmpr_deinit(cmpr); + s_test_ana_cmpr_gptimer_deinit(gptimer); + + TEST_ASSERT_UINT64_WITHIN(TEST_TIME_US * 0.1, 5000, cnt_us); +} diff --git a/components/hal/esp32h2/include/hal/ana_cmpr_ll.h b/components/hal/esp32h2/include/hal/ana_cmpr_ll.h index 834391be3068..d45b43a5fa8b 100644 --- a/components/hal/esp32h2/include/hal/ana_cmpr_ll.h +++ b/components/hal/esp32h2/include/hal/ana_cmpr_ll.h @@ -9,9 +9,9 @@ #include #include "hal/misc.h" #include "hal/assert.h" -#include "soc/gpio_ext_struct.h" +#include "soc/ana_cmpr_struct.h" -#define ANALOG_CMPR_LL_GET_HW(unit) (&ANALOG_CMPR) +#define ANALOG_CMPR_LL_GET_HW(unit) (&ANALOG_CMPR[unit]) #define ANALOG_CMPR_LL_EVENT_CROSS (1 << 0) #ifdef __cplusplus @@ -26,7 +26,7 @@ extern "C" { */ static inline void analog_cmpr_ll_enable(analog_cmpr_dev_t *hw, bool en) { - hw->pad_comp_config.xpd_comp = en; + hw->pad_comp_config->xpd_comp = en; } /** @@ -38,7 +38,7 @@ static inline void analog_cmpr_ll_enable(analog_cmpr_dev_t *hw, bool en) __attribute__((always_inline)) static inline void analog_cmpr_ll_set_internal_ref_voltage(analog_cmpr_dev_t *hw, uint32_t volt_level) { - hw->pad_comp_config.dref_comp = volt_level; + hw->pad_comp_config->dref_comp = volt_level; } /** @@ -49,7 +49,7 @@ static inline void analog_cmpr_ll_set_internal_ref_voltage(analog_cmpr_dev_t *hw */ static inline float analog_cmpr_ll_get_internal_ref_voltage(analog_cmpr_dev_t *hw) { - return hw->pad_comp_config.dref_comp * 0.1F; + return hw->pad_comp_config->dref_comp * 0.1F; } /** @@ -62,7 +62,7 @@ static inline float analog_cmpr_ll_get_internal_ref_voltage(analog_cmpr_dev_t *h */ static inline void analog_cmpr_ll_set_ref_source(analog_cmpr_dev_t *hw, uint32_t ref_src) { - hw->pad_comp_config.mode_comp = ref_src; + hw->pad_comp_config->mode_comp = ref_src; } /** @@ -78,7 +78,7 @@ static inline void analog_cmpr_ll_set_ref_source(analog_cmpr_dev_t *hw, uint32_t __attribute__((always_inline)) static inline void analog_cmpr_ll_set_cross_type(analog_cmpr_dev_t *hw, uint8_t type) { - hw->pad_comp_config.zero_det_mode = type; + hw->pad_comp_config->zero_det_mode = type; } /** @@ -86,16 +86,14 @@ static inline void analog_cmpr_ll_set_cross_type(analog_cmpr_dev_t *hw, uint8_t * @note Only one interrupt on H2 * * @param hw Analog comparator register base address - * @param type The type of cross interrupt - * - 0: disable interrupt - * - 1: enable positive cross interrupt (input analog goes from low to high and across the reference voltage) - * - 2: enable negative cross interrupt (input analog goes from high to low and across the reference voltage) - * - 3: enable any positive or negative cross interrupt + * @param type Not used on H2, because H2 can't distinguish the edge type + * The parameter here only to be compatible with other targets * @return interrupt mask */ __attribute__((always_inline)) static inline uint32_t analog_cmpr_ll_get_intr_mask_by_type(analog_cmpr_dev_t *hw, uint8_t type) { + (void)type; return ANALOG_CMPR_LL_EVENT_CROSS; } @@ -110,7 +108,7 @@ static inline uint32_t analog_cmpr_ll_get_intr_mask_by_type(analog_cmpr_dev_t *h __attribute__((always_inline)) static inline void analog_cmpr_ll_set_debounce_cycle(analog_cmpr_dev_t *hw, uint32_t cycle) { - hw->pad_comp_filter.zero_det_filter_cnt = cycle; + hw->pad_comp_filter->zero_det_filter_cnt = cycle; } /** @@ -122,11 +120,13 @@ static inline void analog_cmpr_ll_set_debounce_cycle(analog_cmpr_dev_t *hw, uint */ static inline void analog_cmpr_ll_enable_intr(analog_cmpr_dev_t *hw, uint32_t mask, bool enable) { + uint32_t val = hw->int_ena->val; if (enable) { - hw->int_ena.val |= mask; + val |= mask; } else { - hw->int_ena.val &= ~mask; + val &= ~mask; } + hw->int_ena->val = val; } /** @@ -137,7 +137,7 @@ static inline void analog_cmpr_ll_enable_intr(analog_cmpr_dev_t *hw, uint32_t ma __attribute__((always_inline)) static inline uint32_t analog_cmpr_ll_get_intr_status(analog_cmpr_dev_t *hw) { - return hw->int_st.val; + return hw->int_st->val; } /** @@ -149,7 +149,7 @@ static inline uint32_t analog_cmpr_ll_get_intr_status(analog_cmpr_dev_t *hw) __attribute__((always_inline)) static inline void analog_cmpr_ll_clear_intr(analog_cmpr_dev_t *hw, uint32_t mask) { - hw->int_clr.val = mask; + hw->int_clr->val = mask; } /** @@ -160,7 +160,7 @@ static inline void analog_cmpr_ll_clear_intr(analog_cmpr_dev_t *hw, uint32_t mas */ static inline volatile void *analog_cmpr_ll_get_intr_status_reg(analog_cmpr_dev_t *hw) { - return &hw->int_st; + return hw->int_st; } #ifdef __cplusplus diff --git a/components/hal/esp32p4/include/hal/ana_cmpr_ll.h b/components/hal/esp32p4/include/hal/ana_cmpr_ll.h index 1ce151c07972..d1075ed64ac7 100644 --- a/components/hal/esp32p4/include/hal/ana_cmpr_ll.h +++ b/components/hal/esp32p4/include/hal/ana_cmpr_ll.h @@ -19,12 +19,14 @@ extern "C" { #define ANALOG_CMPR_LL_GET_HW(unit) (&ANALOG_CMPR[unit]) #define ANALOG_CMPR_LL_GET_UNIT(hw) ((hw) == (&ANALOG_CMPR[0]) ? 0 : 1) #define ANALOG_CMPR_LL_EVENT_CROSS (1 << 0) +#define ANALOG_CMPR_LL_ETM_EVENTS_PER_UNIT (2) #define ANALOG_CMPR_LL_NEG_CROSS_MASK(unit) (1UL << ((int)unit * 3)) #define ANALOG_CMPR_LL_POS_CROSS_MASK(unit) (1UL << ((int)unit * 3 + 1)) #define ANALOG_CMPR_LL_ETM_SOURCE(unit, type) (GPIO_EVT_ZERO_DET_POS0 + (unit) * 2 + (type)) + /** * @brief Enable analog comparator * @@ -92,7 +94,7 @@ static inline uint32_t analog_cmpr_ll_get_intr_mask_by_type(analog_cmpr_dev_t *h mask |= ANALOG_CMPR_LL_POS_CROSS_MASK(unit); } if (type & 0x02) { - mask |= ANALOG_CMPR_LL_POS_CROSS_MASK(unit); + mask |= ANALOG_CMPR_LL_NEG_CROSS_MASK(unit); } return mask; } @@ -120,11 +122,13 @@ static inline void analog_cmpr_ll_set_debounce_cycle(analog_cmpr_dev_t *hw, uint */ static inline void analog_cmpr_ll_enable_intr(analog_cmpr_dev_t *hw, uint32_t mask, bool enable) { + uint32_t val = hw->int_ena->val; if (enable) { - hw->int_ena->val |= mask; + val |= mask; } else { - hw->int_ena->val &= ~mask; + val &= ~mask; } + hw->int_ena->val = val; } /** diff --git a/components/hal/esp32p4/include/hal/gpio_ll.h b/components/hal/esp32p4/include/hal/gpio_ll.h index 274d5e68102d..61e241428060 100644 --- a/components/hal/esp32p4/include/hal/gpio_ll.h +++ b/components/hal/esp32p4/include/hal/gpio_ll.h @@ -603,6 +603,10 @@ static inline void gpio_ll_iomux_set_clk_src(soc_module_clk_t src) } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define gpio_ll_iomux_set_clk_src(...) (void)__DECLARE_RCC_ATOMIC_ENV; gpio_ll_iomux_set_clk_src(__VA_ARGS__) + /** * @brief Force hold digital io pad. * @note GPIO force hold, whether the chip in sleep mode or wakeup mode. diff --git a/components/soc/esp32h2/ana_cmpr_periph.c b/components/soc/esp32h2/ana_cmpr_periph.c index 8a5bec3c6cf9..e83acba42c9c 100644 --- a/components/soc/esp32h2/ana_cmpr_periph.c +++ b/components/soc/esp32h2/ana_cmpr_periph.c @@ -5,11 +5,22 @@ */ #include "soc/ana_cmpr_periph.h" +#include "soc/ana_cmpr_struct.h" -const ana_cmpr_conn_t ana_cmpr_io_map[SOC_ANA_CMPR_NUM] = { +const ana_cmpr_periph_t ana_cmpr_periph[SOC_ANA_CMPR_NUM] = { [0] = { .src_gpio = ANA_CMPR0_SRC_GPIO, .ext_ref_gpio = ANA_CMPR0_EXT_REF_GPIO, .intr_src = ETS_GPIO_INTR_SOURCE, }, }; + +analog_cmpr_dev_t ANALOG_CMPR[SOC_ANA_CMPR_NUM] = { + [0] = { + .pad_comp_config = &GPIO_EXT.pad_comp_config, + .pad_comp_filter = &GPIO_EXT.pad_comp_filter, + .int_st = &GPIO_EXT.int_st, + .int_ena = &GPIO_EXT.int_ena, + .int_clr = &GPIO_EXT.int_clr, + }, +}; diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 11b7544a2c73..16b41ee5dd1f 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -483,6 +483,10 @@ config SOC_ANA_CMPR_NUM int default 1 +config SOC_ANA_CMPR_INTR_SHARE_WITH_GPIO + bool + default y + config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32h2/include/soc/ana_cmpr_struct.h b/components/soc/esp32h2/include/soc/ana_cmpr_struct.h new file mode 100644 index 000000000000..b8444fb0be10 --- /dev/null +++ b/components/soc/esp32h2/include/soc/ana_cmpr_struct.h @@ -0,0 +1,36 @@ +/** + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* NOTE: this file is created manually for compatibility */ + +#pragma once + +#include +#include "soc/gpio_ext_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The Analog Comparator Device struct + * @note The field in it are register pointers, which point to the physical address + * of the corresponding configuration register + * @note see 'ana_cmpr_periph.c' for the device instance + */ +typedef struct { + volatile gpio_pad_comp_config_reg_t *pad_comp_config; + volatile gpio_pad_comp_filter_reg_t *pad_comp_filter; + volatile gpio_ext_int_st_reg_t *int_st; + volatile gpio_ext_int_ena_reg_t *int_ena; + volatile gpio_ext_int_clr_reg_t *int_clr; +} analog_cmpr_dev_t; + +extern analog_cmpr_dev_t ANALOG_CMPR[1]; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/include/soc/gpio_ext_struct.h b/components/soc/esp32h2/include/soc/gpio_ext_struct.h index 9b211852e1ff..813ee4bbfcde 100644 --- a/components/soc/esp32h2/include/soc/gpio_ext_struct.h +++ b/components/soc/esp32h2/include/soc/gpio_ext_struct.h @@ -305,15 +305,10 @@ typedef struct { volatile gpio_ext_version_reg_t version; } gpio_ext_dev_t; -// analog comparator is a stand alone peripheral, but it is connected to GPIO -// so we rename it to analog_cmpr_dev_t from user's perspective -typedef gpio_ext_dev_t analog_cmpr_dev_t; - extern gpio_sd_dev_t SDM; extern gpio_glitch_filter_dev_t GLITCH_FILTER; extern gpio_etm_dev_t GPIO_ETM; extern gpio_ext_dev_t GPIO_EXT; -extern analog_cmpr_dev_t ANALOG_CMPR; #ifndef __cplusplus _Static_assert(sizeof(gpio_ext_dev_t) == 0x100, "Invalid size of gpio_ext_dev_t structure"); diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 4467ab10bf88..5ac067ee67cf 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -220,7 +220,8 @@ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ /*------------------------- Analog Comparator CAPS ---------------------------*/ -#define SOC_ANA_CMPR_NUM (1U) +#define SOC_ANA_CMPR_NUM (1U) +#define SOC_ANA_CMPR_INTR_SHARE_WITH_GPIO (1) /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-H2 has 2 I2C diff --git a/components/soc/esp32h2/ld/esp32h2.peripherals.ld b/components/soc/esp32h2/ld/esp32h2.peripherals.ld index 9b88f4b68f4a..faac00ad3c6c 100644 --- a/components/soc/esp32h2/ld/esp32h2.peripherals.ld +++ b/components/soc/esp32h2/ld/esp32h2.peripherals.ld @@ -44,7 +44,6 @@ PROVIDE ( HMAC = 0x6008D000 ); PROVIDE ( IO_MUX = 0x60090000 ); PROVIDE ( GPIO = 0x60091000 ); PROVIDE ( GPIO_EXT = 0x60091f00 ); -PROVIDE ( ANALOG_CMPR = 0x60091f00 ); PROVIDE ( SDM = 0x60091f00 ); PROVIDE ( GLITCH_FILTER = 0x60091f30 ); PROVIDE ( GPIO_ETM = 0x60091f60 ); diff --git a/components/soc/esp32p4/ana_cmpr_periph.c b/components/soc/esp32p4/ana_cmpr_periph.c index f189bbd28778..df1db2ef6366 100644 --- a/components/soc/esp32p4/ana_cmpr_periph.c +++ b/components/soc/esp32p4/ana_cmpr_periph.c @@ -7,7 +7,7 @@ #include "soc/ana_cmpr_periph.h" #include "soc/ana_cmpr_struct.h" -const ana_cmpr_conn_t ana_cmpr_io_map[SOC_ANA_CMPR_NUM] = { +const ana_cmpr_periph_t ana_cmpr_periph[SOC_ANA_CMPR_NUM] = { [0] = { .src_gpio = ANA_CMPR0_SRC_GPIO, .ext_ref_gpio = ANA_CMPR0_EXT_REF_GPIO, diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index f93ed20ca741..930416a4e834 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -391,7 +391,7 @@ config SOC_ANA_CMPR_NUM int default 2 -config SOC_ANA_CMPR_SUPPORT_MULTI_INTR +config SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE bool default y @@ -399,10 +399,6 @@ config SOC_ANA_CMPR_SUPPORT_ETM bool default y -config SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT - int - default 2 - config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index a58f4214dd3b..0a50c5483c24 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -413,7 +413,7 @@ typedef enum { #define SOC_ANA_CMPR_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL} /** - * @brief Sigma Delta Modulator clock source + * @brief Analog Comparator clock source */ typedef enum { ANA_CMPR_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL clock as the source clock */ diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 987b968e658a..c72c2ba214b4 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -221,10 +221,9 @@ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ /*------------------------- Analog Comparator CAPS ---------------------------*/ -#define SOC_ANA_CMPR_NUM (2U) -#define SOC_ANA_CMPR_SUPPORT_MULTI_INTR (1) -#define SOC_ANA_CMPR_SUPPORT_ETM (1) -#define SOC_ANA_CMPR_ETM_EVENTS_PER_UNIT (2) +#define SOC_ANA_CMPR_NUM (2) +#define SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE (1) // Support positive/negative/any cross interrupt +#define SOC_ANA_CMPR_SUPPORT_ETM (1) /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-P4 has 2 I2Cs diff --git a/components/soc/include/soc/ana_cmpr_periph.h b/components/soc/include/soc/ana_cmpr_periph.h index c197bdb10a46..ce4738fcd672 100644 --- a/components/soc/include/soc/ana_cmpr_periph.h +++ b/components/soc/include/soc/ana_cmpr_periph.h @@ -8,7 +8,7 @@ #include #include "soc/soc_caps.h" -#include "soc/periph_defs.h" +#include "soc/interrupts.h" #if SOC_ANA_CMPR_SUPPORTED #include "soc/ana_cmpr_channel.h" #endif @@ -22,9 +22,9 @@ typedef struct { int src_gpio; int ext_ref_gpio; int intr_src; -} ana_cmpr_conn_t; +} ana_cmpr_periph_t; -extern const ana_cmpr_conn_t ana_cmpr_io_map[SOC_ANA_CMPR_NUM]; +extern const ana_cmpr_periph_t ana_cmpr_periph[SOC_ANA_CMPR_NUM]; #endif #ifdef __cplusplus diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 777ffd4d7b96..60441c822fdf 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -73,6 +73,7 @@ INPUT = \ $(PROJECT_PATH)/components/bt/host/nimble/esp-hci/include/esp_nimble_hci.h \ $(PROJECT_PATH)/components/console/esp_console.h \ $(PROJECT_PATH)/components/driver/analog_comparator/include/driver/ana_cmpr.h \ + $(PROJECT_PATH)/components/driver/analog_comparator/include/driver/ana_cmpr_etm.h \ $(PROJECT_PATH)/components/driver/analog_comparator/include/driver/ana_cmpr_types.h \ $(PROJECT_PATH)/components/driver/dac/include/driver/dac_continuous.h \ $(PROJECT_PATH)/components/driver/dac/include/driver/dac_cosine.h \ diff --git a/docs/en/api-reference/peripherals/ana_cmpr.rst b/docs/en/api-reference/peripherals/ana_cmpr.rst index b686e6b69323..e9d3809649c6 100644 --- a/docs/en/api-reference/peripherals/ana_cmpr.rst +++ b/docs/en/api-reference/peripherals/ana_cmpr.rst @@ -1,7 +1,6 @@ Analog Comparator ================= -{IDF_TARGET_ANA_CMPR_NUM: default="NOT UPDATED", esp32h2="one", esp32p4="two"} {IDF_TARGET_ANA_CMPR_SRC_CHAN0: default="NOT UPDATED", esp32h2="GPIO11", esp32p4="GPIO52"} {IDF_TARGET_ANA_CMPR_EXT_REF_CHAN0: default="NOT UPDATED", esp32h2="GPIO10", esp32p4="GPIO51"} {IDF_TARGET_ANA_CMPR_SRC_CHAN1: default="NOT UPDATED", esp32p4="GPIO54"} @@ -14,13 +13,13 @@ Analog Comparator is a peripheral that can be used to compare a source signal wi It is a cost effective way to replace an amplifier comparator in some scenarios. But unlike the continuous comparing of the amplifier comparator, ESP Analog Comparator is driven by a source clock, which decides the sampling frequency. -Analog Comparator on {IDF_TARGET_NAME} has {IDF_TARGET_ANA_CMPR_NUM} unit(s), the channels in the unit(s) are: +Analog Comparator on {IDF_TARGET_NAME} has {IDF_TARGET_SOC_ANA_CMPR_NUM} unit(s), the channels in the unit(s) are: **UNIT0** - Source Channel: {IDF_TARGET_ANA_CMPR_SRC_CHAN0} - External Reference Channel: {IDF_TARGET_ANA_CMPR_EXT_REF_CHAN0} -- Internal Reference Channel: Range 0% ~ 70% VDD, step 10% VDD +- Internal Reference Channel: Range 0% ~ 70% of the VDD, the step is 10% of the VDD .. only:: esp32p4 @@ -28,7 +27,7 @@ Analog Comparator on {IDF_TARGET_NAME} has {IDF_TARGET_ANA_CMPR_NUM} unit(s), th - Source Channel: {IDF_TARGET_ANA_CMPR_SRC_CHAN1} - External Reference Channel: {IDF_TARGET_ANA_CMPR_EXT_REF_CHAN1} - - Internal Reference Channel: Range 0% ~ 70% VDD, step 10% VDD + - Internal Reference Channel: Range 0% ~ 70% of the VDD, the step is 10% of the VDD Functional Overview ------------------- @@ -56,7 +55,7 @@ To allocate the resource of the Analog Comparator unit, :cpp:func:`ana_cmpr_new_ - :cpp:member:`ana_cmpr_config_t::unit` selects the Analog Comparator unit. - :cpp:member:`ana_cmpr_config_t::clk_src` selects the source clock for Analog Comparator, it can affect the sampling frequency. Note that the clock source of the Analog Comparator comes from the io mux, it is shared with GPIO extension peripherals like SDM (Sigma-Delta Modulation) and Glitch Filter. The configuration will fail if you specific different clock sources for multiple GPIO extension peripherals. The default clock sources of these peripherals are same, typically, we select :cpp:enumerator:`soc_periph_ana_cmpr_clk_src_t::ANA_CMPR_CLK_SRC_DEFAULT` as the clock source. -- :cpp:member:`ana_cmpr_config_t::ref_src` selects the reference source from internal voltage or external signal (from {IDF_TARGET_ANA_CMPR_EXT_REF_CHAN}). +- :cpp:member:`ana_cmpr_config_t::ref_src` selects the reference source from internal voltage or external signal. - :cpp:member:`ana_cmpr_config_t::cross_type` selects which kind of cross type can trigger the interrupt. The function :cpp:func:`ana_cmpr_new_unit` can fail due to various errors such as insufficient memory, invalid arguments, etc. If a previously created Analog Comparator unit is no longer required, you should recycle it by calling :cpp:func:`ana_cmpr_del_unit`. It allows the underlying HW channel to be used for other purposes. Before deleting an Analog Comparator unit handle, you should disable it by :cpp:func:`ana_cmpr_unit_disable` in advance, or make sure it has not enabled yet by :cpp:func:`ana_cmpr_unit_enable`. @@ -67,7 +66,7 @@ The function :cpp:func:`ana_cmpr_new_unit` can fail due to various errors such a ana_cmpr_handle_t cmpr = NULL; ana_cmpr_config_t config = { - .unit = ANA_CMPR_UNIT_0, + .unit = 0, .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, .ref_src = ANA_CMPR_REF_SRC_INTERNAL, .cross_type = ANA_CMPR_CROSS_ANY, @@ -199,7 +198,7 @@ Kconfig Options ETM Events ^^^^^^^^^^ - To create an analog comparator cross event, you need to include ``driver/ana_cmpr_etm.h`` additionally, and allocate the event by :cpp:func:`ana_cmpr_new_etm_event`. You can refer to :doc:`GPTimer ` for how to connect an event to a task. + To create an analog comparator cross event, you need to include ``driver/ana_cmpr_etm.h`` additionally, and allocate the event by :cpp:func:`ana_cmpr_new_etm_event`. You can refer to :doc:`ETM ` for how to connect an event to a task. Application Example ------------------- diff --git a/docs/en/api-reference/peripherals/etm.rst b/docs/en/api-reference/peripherals/etm.rst index 96165f19f43a..bca698df5dfc 100644 --- a/docs/en/api-reference/peripherals/etm.rst +++ b/docs/en/api-reference/peripherals/etm.rst @@ -70,10 +70,7 @@ Other Peripheral Events :SOC_TIMER_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/gptimer` for how to get the ETM event handle from GPTimer. :SOC_GDMA_SUPPORT_ETM: - Refer to :doc:`/api-reference/system/async_memcpy` for how to get the ETM event handle from async memcpy. :SOC_MCPWM_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/mcpwm` for how to get the ETM event handle from MCPWM. - - .. only:: esp32p4 - - :SOC_ANA_CMPR_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/ana_cmpr` for how to get the ETM event handle from analog comparator. + :SOC_ANA_CMPR_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/ana_cmpr` for how to get the ETM event handle from analog comparator. .. _etm-task: diff --git a/docs/zh_CN/api-reference/peripherals/etm.rst b/docs/zh_CN/api-reference/peripherals/etm.rst index 3f7d5baddc23..8d56935aec34 100644 --- a/docs/zh_CN/api-reference/peripherals/etm.rst +++ b/docs/zh_CN/api-reference/peripherals/etm.rst @@ -70,10 +70,7 @@ GPIO **边沿** 事件是最常见的事件类型,任何 GPIO 管脚均可触 :SOC_TIMER_SUPPORT_ETM: - 要了解如何从 GPTimer 获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/gptimer`。 :SOC_GDMA_SUPPORT_ETM: - 要了解如何从 async memcpy 获取 ETM 事件句柄,请参阅 :doc:`/api-reference/system/async_memcpy`。 :SOC_MCPWM_SUPPORT_ETM: - 要了解如何从 MCPWM 中获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/mcpwm`。 - - .. only:: esp32p4 - - :SOC_ANA_CMPR_SUPPORT_ETM: - 要了解如何从模拟比较器获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/ana_cmpr`。 + :SOC_ANA_CMPR_SUPPORT_ETM: - 要了解如何从模拟比较器获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/ana_cmpr`。 .. _etm-task: diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 02974dcc02ec..c3055b0a6051 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -18,6 +18,10 @@ examples/peripherals/adc/oneshot_read: examples/peripherals/analog_comparator: disable: - if: SOC_ANA_CMPR_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: not supported yet examples/peripherals/dac: disable: diff --git a/examples/peripherals/analog_comparator/README.md b/examples/peripherals/analog_comparator/README.md index 8a6adb523c84..330b1dcc0e30 100644 --- a/examples/peripherals/analog_comparator/README.md +++ b/examples/peripherals/analog_comparator/README.md @@ -1,11 +1,17 @@ -| Supported Targets | ESP32-H2 | -| ----------------- | -------- | +| Supported Targets | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | # Analog Comparator Example (See the README.md file in the upper level 'examples' directory for more information about examples.) -This example is going to show how to use the Analog Comparator. +This example is going to show how to use the Analog Comparator. The example toggles a GPIO to monitor the positive and negative crosses on the analog comparator unit. + +## Realization + +- If the target supports generating the analog comparator events (like ESP32-P4), the example can toggle the monitoring GPIO via Event Task Matrix (ETM). ETM can bind the analog comparator cross events (positive and negative events) with the GPIO tasks (to set or clear a GPIO), so that every event happens, hardware will execute the corresponding task without CPU involved. + +- If the target does not support to generate the analog comparator events (like ESP32-H2). The example will register an event callback on the analog comparator, and toggle the GPIO in the callback. It requires the CPU to process every event ISR, thus it is not effective as ETM and can't achieve a high resolution. ## How to Use Example diff --git a/examples/peripherals/analog_comparator/main/CMakeLists.txt b/examples/peripherals/analog_comparator/main/CMakeLists.txt index e017eb488976..07070ae02048 100644 --- a/examples/peripherals/analog_comparator/main/CMakeLists.txt +++ b/examples/peripherals/analog_comparator/main/CMakeLists.txt @@ -1,2 +1,10 @@ -idf_component_register(SRCS "ana_cmpr_example_main.c" +set(src "ana_cmpr_example_main.c") + +if(CONFIG_EXAMPLE_USE_ETM) + list(APPEND src "ana_cmpr_example_etm.c") +else() + list(APPEND src "ana_cmpr_example_intr.c") +endif() + +idf_component_register(SRCS ${src} INCLUDE_DIRS ".") diff --git a/examples/peripherals/analog_comparator/main/Kconfig.projbuild b/examples/peripherals/analog_comparator/main/Kconfig.projbuild index 1e2f780b3708..21bd9d1998f7 100644 --- a/examples/peripherals/analog_comparator/main/Kconfig.projbuild +++ b/examples/peripherals/analog_comparator/main/Kconfig.projbuild @@ -1,5 +1,20 @@ menu "Analog Comparator Example Configuration" + choice EXAMPLE_REALIZATION + prompt "Analog Comparator example realization methods" + default EXAMPLE_USE_ETM if SOC_ANA_CMPR_SUPPORT_ETM && SOC_GPIO_SUPPORT_ETM + default EXAMPLE_USE_INTR if !SOC_ANA_CMPR_SUPPORT_ETM || !SOC_GPIO_SUPPORT_ETM + config EXAMPLE_USE_INTR + bool "Use Interrupt" + help + Enable to set the monitor GPIO via interrupt callback + config EXAMPLE_USE_ETM + depends on SOC_ANA_CMPR_SUPPORT_ETM && SOC_GPIO_SUPPORT_ETM + bool "Use ETM" + help + Enable to set the monitor GPIO via Event Task Matrix + endchoice + choice EXAMPLE_REFERENCE_SOURCE prompt "Analog Comparator reference source" default EXAMPLE_INTERNAL_REF @@ -18,7 +33,7 @@ menu "Analog Comparator Example Configuration" endchoice config EXAMPLE_HYSTERESIS_COMPARATOR - depends on EXAMPLE_INTERNAL_REF + depends on EXAMPLE_INTERNAL_REF && !EXAMPLE_USE_ETM bool "Enable hysteresis comparator" default n help diff --git a/examples/peripherals/analog_comparator/main/ana_cmpr_example_etm.c b/examples/peripherals/analog_comparator/main/ana_cmpr_example_etm.c new file mode 100644 index 000000000000..a8dbfce5b109 --- /dev/null +++ b/examples/peripherals/analog_comparator/main/ana_cmpr_example_etm.c @@ -0,0 +1,133 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "driver/ana_cmpr.h" +#include "driver/ana_cmpr_etm.h" +#include "driver/gpio_etm.h" +#include "esp_etm.h" +#include "esp_log.h" +#include "ana_cmpr_example_main.h" + +static const char *TAG = "ana_cmpr_example"; + +static void example_etm_bind_ana_cmpr_event_with_gpio_task(ana_cmpr_handle_t cmpr) +{ + /* Allocate the analog comparator positive & negative cross events */ + esp_etm_event_handle_t cmpr_pos_evt = NULL; + esp_etm_event_handle_t cmpr_neg_evt = NULL; + ana_cmpr_etm_event_config_t evt_cfg = { + .event_type = ANA_CMPR_EVENT_POS_CROSS, + }; + ESP_ERROR_CHECK(ana_cmpr_new_etm_event(cmpr, &evt_cfg, &cmpr_pos_evt)); + evt_cfg.event_type = GPIO_ETM_EVENT_EDGE_NEG; + ESP_ERROR_CHECK(ana_cmpr_new_etm_event(cmpr, &evt_cfg, &cmpr_neg_evt)); + + /* Allocate the GPIO set & clear tasks */ + esp_etm_task_handle_t gpio_pos_task = NULL; + esp_etm_task_handle_t gpio_neg_task = NULL; + gpio_etm_task_config_t task_cfg = { + .action = GPIO_ETM_TASK_ACTION_SET, + }; + ESP_ERROR_CHECK(gpio_new_etm_task(&task_cfg, &gpio_pos_task)); + task_cfg.action = GPIO_ETM_TASK_ACTION_CLR; + ESP_ERROR_CHECK(gpio_new_etm_task(&task_cfg, &gpio_neg_task)); + /* Add task to the monitor GPIO */ + ESP_ERROR_CHECK(gpio_etm_task_add_gpio(gpio_pos_task, EXAMPLE_MONITOR_GPIO_NUM)); + ESP_ERROR_CHECK(gpio_etm_task_add_gpio(gpio_neg_task, EXAMPLE_MONITOR_GPIO_NUM)); + + /* Allocate the Event Task Matrix channels */ + esp_etm_channel_handle_t etm_pos_handle; + esp_etm_channel_handle_t etm_neg_handle; + esp_etm_channel_config_t etm_cfg = {}; + ESP_ERROR_CHECK(esp_etm_new_channel(&etm_cfg, &etm_pos_handle)); + ESP_ERROR_CHECK(esp_etm_new_channel(&etm_cfg, &etm_neg_handle)); + /* Bind the events and tasks */ + ESP_ERROR_CHECK(esp_etm_channel_connect(etm_pos_handle, cmpr_pos_evt, gpio_pos_task)); + ESP_ERROR_CHECK(esp_etm_channel_connect(etm_neg_handle, cmpr_neg_evt, gpio_neg_task)); + /* Enable the ETM channels */ + ESP_ERROR_CHECK(esp_etm_channel_enable(etm_pos_handle)); + ESP_ERROR_CHECK(esp_etm_channel_enable(etm_neg_handle)); +} + +ana_cmpr_handle_t example_init_analog_comparator_etm(void) +{ + /* Step 0: Show the source channel and reference channel GPIO */ + int src_gpio = -1; + int ext_ref_gpio = -1; + ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &src_gpio)); + ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_EXT_REF_CHAN, &ext_ref_gpio)); + ESP_LOGI(TAG, "Analog Comparator source gpio %d, external reference gpio %d", src_gpio, ext_ref_gpio); + + ana_cmpr_handle_t cmpr = NULL; + +#if CONFIG_EXAMPLE_INTERNAL_REF + /* Step 1: Allocate the new analog comparator unit */ + ana_cmpr_config_t config = { + .unit = EXAMPLE_ANA_CMPR_UNIT, + .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, + .ref_src = ANA_CMPR_REF_SRC_INTERNAL, + .cross_type = ANA_CMPR_CROSS_ANY, + }; + ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr)); + ESP_LOGI(TAG, "Allocate Analog Comparator with internal reference"); + + /* Step 1.1: As we are using the internal reference source, we need to configure the internal reference */ + ana_cmpr_internal_ref_config_t ref_cfg = { + .ref_volt = ANA_CMPR_REF_VOLT_50_PCT_VDD, + }; + ESP_ERROR_CHECK(ana_cmpr_set_internal_reference(cmpr, &ref_cfg)); +#else + /* Step 1: Allocate the new analog comparator unit */ + ana_cmpr_config_t config = { + .unit = EXAMPLE_ANA_CMPR_UNIT, + .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, + .ref_src = ANA_CMPR_REF_SRC_EXTERNAL, + .cross_type = ANA_CMPR_CROSS_ANY, + }; + ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr)); + ESP_LOGI(TAG, "Allocate Analog Comparator with external reference"); +#endif // CONFIG_EXAMPLE_INTERNAL_REF + + /* Step 2: (Optional) Set the debounce configuration + * It's an optional configuration, if the wait time is set in debounce configuration, + * the cross interrupt will be disabled temporary after it is triggered, and it will be enabled + * automatically enabled after `wait_us`, so that the duplicate interrupts + * can be suppressed while the source signal crossing the reference signal. */ + ana_cmpr_debounce_config_t dbc_cfg = { + /* Normally the `wait_us` is related to the relative frequency between the source and reference signal + * comparing to another one. This example adopts an approximate frequency as the relative signal + * frequency, and set the default wait time to EXAMPLE_WAIT_TIME_PROP of the relative signal period. + * We need to estimate an appropriate `freq_approx` and EXAMPLE_WAIT_TIME_PROP + * to make sure the interrupt neither triggers duplicate interrupts, nor misses the next crossing interrupt. + * Here we take 1 KHz for example */ + .wait_us = EXAMPLE_WAITE_TIME_US(1000), + }; + ESP_ERROR_CHECK(ana_cmpr_set_debounce(cmpr, &dbc_cfg)); + + /* Step 3: Enable the analog comparator unit */ + ESP_ERROR_CHECK(ana_cmpr_enable(cmpr)); + +#if CONFIG_EXAMPLE_INTERNAL_REF + ESP_LOGI(TAG, "Analog comparator enabled, reference voltage: %d%% * VDD", (int)ref_cfg.ref_volt * 10); +#else + ESP_LOGI(TAG, "Analog comparator enabled, external reference selected"); +#endif + return cmpr; +} + +void example_analog_comparator_etm_app(void) +{ + /* Initialize GPIO to monitor the comparator interrupt */ + example_init_monitor_gpio(); + /* Initialize Analog Comparator */ + ana_cmpr_handle_t cmpr = example_init_analog_comparator_etm(); + /* Connect the analog comparator events and gpio tasks via ETM channels */ + example_etm_bind_ana_cmpr_event_with_gpio_task(cmpr); +} diff --git a/examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c b/examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c new file mode 100644 index 000000000000..78fec3e9bc37 --- /dev/null +++ b/examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c @@ -0,0 +1,122 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "driver/ana_cmpr.h" +#include "esp_log.h" +#include "ana_cmpr_example_main.h" + +static const char *TAG = "ana_cmpr_example"; + +static bool example_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr, + const ana_cmpr_cross_event_data_t *edata, + void *user_ctx) +{ +#if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR + static ana_cmpr_internal_ref_config_t ref_cfg = { + .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD, + }; + bool is_70p = ref_cfg.ref_volt == ANA_CMPR_REF_VOLT_70_PCT_VDD; + /* Toggle the GPIO, monitor the gpio on an oscilloscope. */ + gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, is_70p); + /* Set the internal reference voltage to 30% VDD and 70 %VDD alternately */ + ana_cmpr_set_internal_reference(cmpr, &ref_cfg); + ref_cfg.ref_volt = is_70p ? ANA_CMPR_REF_VOLT_30_PCT_VDD : ANA_CMPR_REF_VOLT_70_PCT_VDD; +#else + static int lvl = 0; + /* Toggle the GPIO, monitor the gpio on a oscilloscope. */ + gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, lvl); + lvl = !lvl; +#endif + return false; +} + +void example_init_analog_comparator_intr(void) +{ + /* Step 0: Show the source channel and reference channel GPIO */ + int src_gpio = -1; + int ext_ref_gpio = -1; + ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &src_gpio)); + ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_EXT_REF_CHAN, &ext_ref_gpio)); + ESP_LOGI(TAG, "Analog Comparator source gpio %d, external reference gpio %d", src_gpio, ext_ref_gpio); + + ana_cmpr_handle_t cmpr = NULL; + +#if CONFIG_EXAMPLE_INTERNAL_REF + /* Step 1: Allocate the new analog comparator unit */ + ana_cmpr_config_t config = { + .unit = EXAMPLE_ANA_CMPR_UNIT, + .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, + .ref_src = ANA_CMPR_REF_SRC_INTERNAL, + .cross_type = ANA_CMPR_CROSS_ANY, + }; + ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr)); + ESP_LOGI(TAG, "Allocate Analog Comparator with internal reference"); + + /* Step 1.1: As we are using the internal reference source, we need to configure the internal reference */ + ana_cmpr_internal_ref_config_t ref_cfg = { +#if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR + /* Set the initial internal reference voltage to 70% VDD, it will be updated in the callback every time the interrupt triggered */ + .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD +#else + .ref_volt = ANA_CMPR_REF_VOLT_50_PCT_VDD, +#endif + }; + ESP_ERROR_CHECK(ana_cmpr_set_internal_reference(cmpr, &ref_cfg)); +#else + /* Step 1: Allocate the new analog comparator unit */ + ana_cmpr_config_t config = { + .unit = EXAMPLE_ANA_CMPR_UNIT, + .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, + .ref_src = ANA_CMPR_REF_SRC_EXTERNAL, + .cross_type = ANA_CMPR_CROSS_ANY, + }; + ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr)); + ESP_LOGI(TAG, "Allocate Analog Comparator with external reference"); +#endif + + /* Step 2: (Optional) Set the debounce configuration + * It's an optional configuration, if the wait time is set in debounce configuration, + * the cross interrupt will be disabled temporary after it is triggered, and it will be enabled + * automatically enabled after `wait_us`, so that the duplicate interrupts + * can be suppressed while the source signal crossing the reference signal. */ + ana_cmpr_debounce_config_t dbc_cfg = { + /* Normally the `wait_us` is related to the relative frequency between the source and reference signal + * comparing to another one. This example adopts an approximate frequency as the relative signal + * frequency, and set the default wait time to EXAMPLE_WAIT_TIME_PROP of the relative signal period. + * We need to estimate an appropriate `freq_approx` and EXAMPLE_WAIT_TIME_PROP + * to make sure the interrupt neither triggers duplicate interrupts, nor misses the next crossing interrupt. + * Here we take 1 KHz for example */ + .wait_us = EXAMPLE_WAITE_TIME_US(1000), + }; + ESP_ERROR_CHECK(ana_cmpr_set_debounce(cmpr, &dbc_cfg)); + + /* Step 3: Register the event callbacks */ + ana_cmpr_event_callbacks_t cbs = { + .on_cross = example_ana_cmpr_on_cross_callback, + }; + ESP_ERROR_CHECK(ana_cmpr_register_event_callbacks(cmpr, &cbs, NULL)); + + /* Step 4: Enable the analog comparator unit */ + ESP_ERROR_CHECK(ana_cmpr_enable(cmpr)); + +#if CONFIG_EXAMPLE_INTERNAL_REF + ESP_LOGI(TAG, "Analog comparator enabled, reference voltage: %d%% * VDD", (int)ref_cfg.ref_volt * 10); +#else + ESP_LOGI(TAG, "Analog comparator enabled, external reference selected"); +#endif +} + +void example_analog_comparator_intr_app(void) +{ + /* Initialize GPIO to monitor the comparator interrupt */ + example_init_monitor_gpio(); + /* Initialize Analog Comparator */ + example_init_analog_comparator_intr(); +} diff --git a/examples/peripherals/analog_comparator/main/ana_cmpr_example_main.c b/examples/peripherals/analog_comparator/main/ana_cmpr_example_main.c index dff400372460..49b7d6ca84a2 100644 --- a/examples/peripherals/analog_comparator/main/ana_cmpr_example_main.c +++ b/examples/peripherals/analog_comparator/main/ana_cmpr_example_main.c @@ -5,118 +5,8 @@ */ #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" #include "driver/gpio.h" -#include "driver/ana_cmpr.h" -#include "esp_log.h" - -#define EXAMPLE_ANA_CMPR_UNIT ANA_CMPR_UNIT_0 // Analog Comparator unit -#define EXAMPLE_WAIT_TIME_PROP (0.1) // The wait time proportion in one relative signal period -#define EXAMPLE_WAITE_TIME_US(freq_approx) (uint32_t)(1000000 * EXAMPLE_WAIT_TIME_PROP / (freq_approx)) - -#define EXAMPLE_MONITOR_GPIO_NUM (0) // The gpio to monitor the on cross callback - -static const char *TAG = "ana_cmpr_example"; - -static bool example_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr, - const ana_cmpr_cross_event_data_t *edata, - void *user_ctx) -{ -#if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR - static ana_cmpr_internal_ref_config_t ref_cfg = { - .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD, - }; - bool is_70p = ref_cfg.ref_volt == ANA_CMPR_REF_VOLT_70_PCT_VDD; - /* Toggle the GPIO, monitor the gpio on an oscilloscope. */ - gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, is_70p); - /* Set the internal reference voltage to 30% VDD and 70 %VDD alternately */ - ana_cmpr_set_internal_reference(cmpr, &ref_cfg); - ref_cfg.ref_volt = is_70p ? ANA_CMPR_REF_VOLT_30_PCT_VDD : ANA_CMPR_REF_VOLT_70_PCT_VDD; -#else - static int lvl = 0; - /* Toggle the GPIO, monitor the gpio on a oscilloscope. */ - gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, lvl); - lvl = !lvl; -#endif - return false; -} - -void example_init_analog_comparator(void) -{ - /* Step 0: Show the source channel and reference channel GPIO */ - int src_gpio = -1; - int ext_ref_gpio = -1; - ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &src_gpio)); - ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_EXT_REF_CHAN, &ext_ref_gpio)); - ESP_LOGI(TAG, "Analog Comparator source gpio %d, external reference gpio %d", src_gpio, ext_ref_gpio); - - ana_cmpr_handle_t cmpr = NULL; - -#if CONFIG_EXAMPLE_INTERNAL_REF - /* Step 1: Allocate the new analog comparator unit */ - ana_cmpr_config_t config = { - .unit = EXAMPLE_ANA_CMPR_UNIT, - .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, - .ref_src = ANA_CMPR_REF_SRC_INTERNAL, - .cross_type = ANA_CMPR_CROSS_ANY, - }; - ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr)); - ESP_LOGI(TAG, "Allocate Analog Comparator with internal reference"); - - /* Step 1.1: As we are using the internal reference source, we need to configure the internal reference */ - ana_cmpr_internal_ref_config_t ref_cfg = { -#if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR - /* Set the initial internal reference voltage to 70% VDD, it will be updated in the callback every time the interrupt triggered */ - .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD -#else - .ref_volt = ANA_CMPR_REF_VOLT_50_PCT_VDD, -#endif - }; - ESP_ERROR_CHECK(ana_cmpr_set_internal_reference(cmpr, &ref_cfg)); -#else - /* Step 1: Allocate the new analog comparator unit */ - ana_cmpr_config_t config = { - .unit = EXAMPLE_ANA_CMPR_UNIT, - .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, - .ref_src = ANA_CMPR_REF_SRC_EXTERNAL, - .cross_type = ANA_CMPR_CROSS_ANY, - }; - ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr)); - ESP_LOGI(TAG, "Allocate Analog Comparator with external reference"); -#endif - - /* Step 2: (Optional) Set the debounce configuration - * It's an optional configuration, if the wait time is set in debounce configuration, - * the cross interrupt will be disabled temporary after it is triggered, and it will be enabled - * automatically enabled after `wait_us`, so that the duplicate interrupts - * can be suppressed while the source signal crossing the reference signal. */ - ana_cmpr_debounce_config_t dbc_cfg = { - /* Normally the `wait_us` is related to the relative frequency between the source and reference signal - * comparing to another one. This example adopts an approximate frequency as the relative signal - * frequency, and set the default wait time to EXAMPLE_WAIT_TIME_PROP of the relative signal period. - * We need to estimate an appropriate `freq_approx` and EXAMPLE_WAIT_TIME_PROP - * to make sure the interrupt neither triggers duplicate interrupts, nor misses the next crossing interrupt. - * Here we take 1 KHz for example */ - .wait_us = EXAMPLE_WAITE_TIME_US(1000), - }; - ESP_ERROR_CHECK(ana_cmpr_set_debounce(cmpr, &dbc_cfg)); - - /* Step 3: Register the event callbacks */ - ana_cmpr_event_callbacks_t cbs = { - .on_cross = example_ana_cmpr_on_cross_callback, - }; - ESP_ERROR_CHECK(ana_cmpr_register_event_callbacks(cmpr, &cbs, NULL)); - - /* Step 4: Enable the analog comparator unit */ - ESP_ERROR_CHECK(ana_cmpr_enable(cmpr)); - -#if CONFIG_EXAMPLE_INTERNAL_REF - ESP_LOGI(TAG, "Analog comparator enabled, reference voltage: %d%% * VDD", (int)ref_cfg.ref_volt * 10); -#else - ESP_LOGI(TAG, "Analog comparator enabled, external reference selected"); -#endif -} +#include "ana_cmpr_example_main.h" void example_init_monitor_gpio(void) { @@ -133,8 +23,9 @@ void example_init_monitor_gpio(void) void app_main(void) { - /* Initialize GPIO to monitor the comparator interrupt */ - example_init_monitor_gpio(); - /* Initialize Analog Comparator */ - example_init_analog_comparator(); +#if CONFIG_EXAMPLE_USE_ETM + example_analog_comparator_etm_app(); +#else + example_analog_comparator_intr_app(); +#endif } diff --git a/examples/peripherals/analog_comparator/main/ana_cmpr_example_main.h b/examples/peripherals/analog_comparator/main/ana_cmpr_example_main.h new file mode 100644 index 000000000000..48e872b3ae9b --- /dev/null +++ b/examples/peripherals/analog_comparator/main/ana_cmpr_example_main.h @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#pragma once + +#include +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define EXAMPLE_ANA_CMPR_UNIT 0 // Analog Comparator unit +#define EXAMPLE_WAIT_TIME_PROP (0.1) // The wait time proportion in one relative signal period +#define EXAMPLE_WAITE_TIME_US(freq_approx) (uint32_t)(1000000 * EXAMPLE_WAIT_TIME_PROP / (freq_approx)) + +#define EXAMPLE_MONITOR_GPIO_NUM (0) // The gpio to monitor the on cross callback + +void example_init_monitor_gpio(void); + +#if CONFIG_EXAMPLE_USE_ETM +/** + * @brief Set or clear the monitor GPIO via Event Task Matrix when cross interrupt triggers. + * @note The interrupt of analog comparator is regarded as Event, + * and the the operation of setting/clearing the GPIO is regarded as the corresponding task of the event. +* CPU won't be involved by using Event Task Matrix, so it can achieve relatively higher interrupt frequency + */ +void example_analog_comparator_etm_app(void); +#endif + +/** + * @brief Set or clear the monitor GPIO in the cross interrupt callback. + * @note The GPIO level is set manually in the callback. + * It's more flexible so that we can realize some operation like hysteresis, + * But as the operations are done in callback, CPU is involved, so it can only achieve a low interrupt frequency + */ +void example_analog_comparator_intr_app(void); + +#ifdef __cplusplus +} +#endif From cb8a8d3e036dd3f3182bc3f1cbe669990468e30b Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Mon, 4 Sep 2023 16:42:10 +0800 Subject: [PATCH 067/142] feat(openthread): Add some configuration for customer using --- components/openthread/Kconfig | 52 +++++++++++++++++++ .../openthread-core-esp32x-ftd-config.h | 36 ++++++++++++- .../openthread-core-esp32x-mtd-config.h | 13 ++++- .../src/port/esp_openthread_radio.c | 10 ++-- 4 files changed, 105 insertions(+), 6 deletions(-) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 1742ccd2397a..48dfdf7baf72 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -177,6 +177,12 @@ menu "OpenThread" commissioner in the Thread network. A commissioner checks the pre-shared key from a joining device with the Thread commissioning protocol and shares the network parameter with the joining device upon success. + config OPENTHREAD_COMM_MAX_JOINER_ENTRIES + int "The size of max commissioning joiner entries" + depends on OPENTHREAD_COMMISSIONER + default 2 + range 2 50 + config OPENTHREAD_JOINER bool "Enable Joiner" depends on OPENTHREAD_ENABLED @@ -193,6 +199,14 @@ menu "OpenThread" Select this option to enable SRP Client in OpenThread. This allows a device to register SRP services to SRP Server. + config OPENTHREAD_SRP_CLIENT_MAX_SERVICES + int "Specifies number of service entries in the SRP client service pool" + depends on OPENTHREAD_SRP_CLIENT + default 5 + range 2 20 + help + Set the max buffer size of service entries in the SRP client service pool. + config OPENTHREAD_DNS_CLIENT bool "Enable DNS Client" depends on OPENTHREAD_ENABLED @@ -221,6 +235,24 @@ menu "OpenThread" range 10 100 if !OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT range 10 8191 if OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT + config OPENTHREAD_SPINEL_RX_FRAME_BUFFER_SIZE + int "The size of openthread spinel rx frame buffer" + depends on OPENTHREAD_ENABLED + default 1024 + range 512 8192 + + config OPENTHREAD_MLE_MAX_CHILDREN + int "The size of max MLE children entries" + depends on OPENTHREAD_ENABLED + default 10 + range 5 50 + + config OPENTHREAD_TMF_ADDR_CACHE_ENTRIES + int "The size of max TMF address cache entries" + depends on OPENTHREAD_ENABLED + default 20 + range 5 50 + config OPENTHREAD_DNS64_CLIENT bool "Use dns64 client" depends on OPENTHREAD_ENABLED && LWIP_IPV4 @@ -264,6 +296,26 @@ menu "OpenThread" help Select this option to enable CSL feature + config OPENTHREAD_XTAL_ACCURACY + int "The accuracy of the XTAL" + default 130 + help + The device's XTAL accuracy, in ppm. + + config OPENTHREAD_CSL_ACCURACY + int "The current CSL rx/tx scheduling drift, in units of ± ppm" + depends on OPENTHREAD_CSL_ENABLE + default 1 + help + The current accuracy of the clock used for scheduling CSL operations + + config OPENTHREAD_CSL_UNCERTAIN + int "The CSL Uncertainty in units of 10 us." + depends on OPENTHREAD_CSL_ENABLE + default 1 + help + The fixed uncertainty of the Device for scheduling CSL Transmissions in units of 10 microseconds. + config OPENTHREAD_CSL_DEBUG_ENABLE bool "Enable CSL debug" depends on OPENTHREAD_CSL_ENABLE 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 166edab9aae0..564271bf774d 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -361,7 +361,7 @@ * `RadioSpinel` platform is used. * */ -#define OPENTHREAD_CONFIG_PLATFORM_RADIO_SPINEL_RX_FRAME_BUFFER_SIZE 1024 +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_SPINEL_RX_FRAME_BUFFER_SIZE CONFIG_OPENTHREAD_SPINEL_RX_FRAME_BUFFER_SIZE /** * @def OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE @@ -381,6 +381,22 @@ */ #define OPENTHREAD_CONFIG_PING_SENDER_ENABLE 1 +/** + * @def OPENTHREAD_CONFIG_MLE_MAX_CHILDREN + * + * The maximum number of children. + * + */ +#define OPENTHREAD_CONFIG_MLE_MAX_CHILDREN CONFIG_OPENTHREAD_MLE_MAX_CHILDREN + +/** + * @def OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES + * + * The number of EID-to-RLOC cache entries. + * + */ +#define OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES CONFIG_OPENTHREAD_TMF_ADDR_CACHE_ENTRIES + #if CONFIG_OPENTHREAD_DUA_ENABLE /** * @def OPENTHREAD_CONFIG_DUA_ENABLE @@ -418,6 +434,14 @@ */ #if CONFIG_OPENTHREAD_COMMISSIONER #define OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_COMMISSIONER_MAX_JOINER_ENTRIES + * + * The maximum number of Joiner entries maintained by the Commissioner + * + */ +#define OPENTHREAD_CONFIG_COMMISSIONER_MAX_JOINER_ENTRIES CONFIG_OPENTHREAD_COMM_MAX_JOINER_ENTRIES #endif #if CONFIG_OPENTHREAD_MACFILTER_ENABLE @@ -440,6 +464,16 @@ #ifndef OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE #define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1 #endif + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES + * + * Specifies number of service entries in the SRP client service pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES CONFIG_OPENTHREAD_SRP_CLIENT_MAX_SERVICES #endif /** diff --git a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h index f84a6f80ebbc..e74f6e0ba575 100644 --- a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -232,6 +232,17 @@ #ifndef OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE #define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1 #endif + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES + * + * Specifies number of service entries in the SRP client service pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES CONFIG_OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES + #endif /** diff --git a/components/openthread/src/port/esp_openthread_radio.c b/components/openthread/src/port/esp_openthread_radio.c index 6ad310fd03e6..630ca4462156 100644 --- a/components/openthread/src/port/esp_openthread_radio.c +++ b/components/openthread/src/port/esp_openthread_radio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,9 +32,11 @@ #include "utils/mac_frame.h" #define ESP_RECEIVE_SENSITIVITY -120 -#define ESP_OPENTHREAD_XTAL_ACCURACY 130 -#define ESP_OPENTHREAD_CSL_ACCURACY 1 -#define ESP_OPENTHREAD_CSL_UNCERTAIN 1 +#define ESP_OPENTHREAD_XTAL_ACCURACY CONFIG_OPENTHREAD_XTAL_ACCURACY +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +#define ESP_OPENTHREAD_CSL_ACCURACY CONFIG_OPENTHREAD_CSL_ACCURACY +#define ESP_OPENTHREAD_CSL_UNCERTAIN CONFIG_OPENTHREAD_CSL_UNCERTAIN +#endif #define EVENT_TX_DONE (1 << 0) #define EVENT_TX_FAILED (1 << 1) From de148c3a5e19e2d5b2a7e95611edb5e4ceda561f Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Thu, 7 Sep 2023 20:38:12 +0800 Subject: [PATCH 068/142] feat(ble/bluedroid): Add APIs for BLE direct test mode on bluedroid host --- .../bt/host/bluedroid/api/esp_gap_ble_api.c | 97 +++++++++++++ .../api/include/api/esp_gap_ble_api.h | 133 +++++++++++++++++ .../bt/host/bluedroid/bta/dm/bta_dm_act.c | 28 ++++ .../bt/host/bluedroid/bta/dm/bta_dm_api.c | 76 ++++++++++ .../bt/host/bluedroid/bta/dm/bta_dm_main.c | 7 + .../bluedroid/bta/dm/include/bta_dm_int.h | 54 +++++++ .../host/bluedroid/bta/include/bta/bta_api.h | 10 ++ .../btc/profile/std/gap/btc_gap_ble.c | 136 ++++++++++++++++++ .../btc/profile/std/include/btc_gap_ble.h | 27 +++- .../bt/host/bluedroid/stack/hcic/hciblecmds.c | 8 +- .../bluedroid/stack/include/stack/btm_api.h | 2 + .../stack/include/stack/btm_ble_api.h | 5 + 12 files changed, 580 insertions(+), 3 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_gap_ble_api.c b/components/bt/host/bluedroid/api/esp_gap_ble_api.c index 68dba6bdf9b2..93175130461d 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -818,6 +818,103 @@ esp_err_t esp_gap_ble_set_authorization(esp_bd_addr_t bd_addr, bool authorize) return ESP_FAIL; } +#if (BLE_42_FEATURE_SUPPORT == TRUE) +esp_err_t esp_ble_dtm_tx_start(const esp_ble_dtm_tx_t *tx_params) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + if (!tx_params) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_DTM_TX_START; + + memcpy(&arg.dtm_tx_start, tx_params, sizeof(esp_ble_dtm_tx_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_dtm_rx_start(const esp_ble_dtm_rx_t *rx_params) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + if (!rx_params) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_DTM_RX_START; + + memcpy(&arg.dtm_rx_start, rx_params, sizeof(esp_ble_dtm_rx_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +esp_err_t esp_ble_dtm_enh_tx_start(const esp_ble_dtm_enh_tx_t *tx_params) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + if (!tx_params) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_DTM_ENH_TX_START; + + memcpy(&arg.dtm_tx_start, tx_params, sizeof(esp_ble_dtm_enh_tx_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_dtm_enh_rx_start(const esp_ble_dtm_enh_rx_t *rx_params) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + if (!rx_params) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_DTM_ENH_RX_START; + + memcpy(&arg.dtm_rx_start, rx_params, sizeof(esp_ble_dtm_enh_rx_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +esp_err_t esp_ble_dtm_stop(void) +{ + btc_msg_t msg = {0}; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_DTM_STOP; + + return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + #if (BLE_50_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gap_read_phy(esp_bd_addr_t bd_addr) diff --git a/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h b/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h index 284dbc0184f7..33f8b4804559 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h @@ -208,6 +208,8 @@ typedef enum { ESP_GAP_BLE_PERIODIC_ADV_SET_INFO_TRANS_COMPLETE_EVT, /*!< when periodic advertising set info transfer complete, the event comes */ ESP_GAP_BLE_SET_PAST_PARAMS_COMPLETE_EVT, /*!< when set periodic advertising sync transfer params complete, the event comes */ ESP_GAP_BLE_PERIODIC_ADV_SYNC_TRANS_RECV_EVT, /*!< when periodic advertising sync transfer received, the event comes */ + // DTM + ESP_GAP_BLE_DTM_TEST_UPDATE_EVT, /*!< when direct test mode state changes, the event comes */ ESP_GAP_BLE_EVT_MAX, /*!< when maximum advertising event complete, the event comes */ } esp_gap_ble_cb_event_t; @@ -339,7 +341,45 @@ typedef enum { ESP_BLE_SM_MAX_PARAM, } esp_ble_sm_param_t; +typedef enum { + /// DTM TX start event + DTM_TX_START_EVT = 0x00, + ///DTM RX start event + DTM_RX_START_EVT, + ///DTM test end event + DTM_TEST_STOP_EVT, +} esp_ble_dtm_update_evt_t; + +typedef enum { + BLE_DTM_PKT_PAYLOAD_0x00, /*!< PRBS9 sequence ‘11111111100000111101...’ (in transmission order) as described in [Vol 6] Part F, Section 4.1.5 */ + BLE_DTM_PKT_PAYLOAD_0x01, /*!< Repeated ‘11110000’ (in transmission order) sequence as described in [Vol 6] Part F, Section 4.1.5 */ + BLE_DTM_PKT_PAYLOAD_0x02, /*!< Repeated ‘10101010’ (in transmission order) sequence as described in [Vol 6] Part F, Section 4.1.5 */ + BLE_DTM_PKT_PAYLOAD_0x03, /*!< PRBS15 sequence as described in [Vol 6] Part F, Section 4.1.5 */ + BLE_DTM_PKT_PAYLOAD_0x04, /*!< Repeated ‘11111111’ (in transmission order) sequence */ + BLE_DTM_PKT_PAYLOAD_0x05, /*!< Repeated ‘00000000’ (in transmission order) sequence */ + BLE_DTM_PKT_PAYLOAD_0x06, /*!< Repeated ‘00001111’ (in transmission order) sequence */ + BLE_DTM_PKT_PAYLOAD_0x07, /*!< Repeated ‘01010101’ (in transmission order) sequence */ + BLE_DTM_PKT_PAYLOAD_MAX, /*!< 0x08 ~ 0xFF, Reserved for future use */ +} esp_ble_dtm_pkt_payload_t; + #if (BLE_42_FEATURE_SUPPORT == TRUE) +/** +* @brief DTM TX parameters +*/ +typedef struct +{ + uint8_t tx_channel; /*!< channel for sending test data, tx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */ + uint8_t len_of_data; /*!< length in bytes of payload data in each packet */ + esp_ble_dtm_pkt_payload_t pkt_payload; /*!< packet payload type. value range: 0x00-0x07 */ +} esp_ble_dtm_tx_t; +/** +* @brief DTM RX parameters +*/ +typedef struct +{ + uint8_t rx_channel; /*!< channel for test data reception, rx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */ +} esp_ble_dtm_rx_t; + /// Advertising parameters typedef struct { uint16_t adv_int_min; /*!< Minimum advertising interval for @@ -918,6 +958,27 @@ typedef struct { uint8_t adv_clk_accuracy; /*!< periodic advertising clock accuracy */ } esp_ble_gap_periodic_adv_sync_estab_t; +/** +* @brief DTM TX parameters +*/ +typedef struct +{ + uint8_t tx_channel; /*!< channel for sending test data, tx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */ + uint8_t len_of_data; /*!< length in bytes of payload data in each packet */ + esp_ble_dtm_pkt_payload_t pkt_payload; /*!< packet payload type. value range: 0x00-0x07 */ + esp_ble_gap_phy_t phy; /*!< the phy type used by the transmitter, coded phy with S=2:0x04 */ +} esp_ble_dtm_enh_tx_t; + +/** +* @brief DTM RX parameters +*/ +typedef struct +{ + uint8_t rx_channel; /*!< channel for test data reception, rx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */ + esp_ble_gap_phy_t phy; /*!< the phy type used by the receiver, 1M phy: 0x01, 2M phy:0x02, coded phy:0x03 */ + uint8_t modulation_idx; /*!< modulation index, 0x00:standard modulation index, 0x01:stable modulation index */ +} esp_ble_dtm_enh_rx_t; + #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) @@ -1381,6 +1442,14 @@ typedef union { uint8_t adv_clk_accuracy; /*!< Periodic advertising clock accuracy */ } past_received; /*!< Event parameter of ESP_GAP_BLE_PERIODIC_ADV_SYNC_TRANS_RECV_EVT */ #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) + /** + * @brief ESP_GAP_BLE_DTM_TEST_UPDATE_EVT + */ + struct ble_dtm_state_update_evt_param { + esp_bt_status_t status; /*!< Indicate DTM operation success status */ + esp_ble_dtm_update_evt_t update_evt; /*!< DTM state change event, 0x00: DTM TX start, 0x01: DTM RX start, 0x02:DTM end */ + uint16_t num_of_pkt; /*!< number of packets received, only valid if update_evt is DTM_TEST_STOP_EVT and shall be reported as 0 for a transmitter */ + } dtm_state_update; /*!< Event parameter of ESP_GAP_BLE_DTM_TEST_UPDATE_EVT */ } esp_ble_gap_cb_param_t; /** @@ -2366,6 +2435,70 @@ esp_err_t esp_ble_gap_set_periodic_adv_sync_trans_params(esp_bd_addr_t addr, const esp_ble_gap_past_params_t *params); #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_42_FEATURE_SUPPORT == TRUE) + +/** +* @brief This function is used to start a test where the DUT generates reference packets +* at a fixed interval. +* +* @param[in] tx_params : DTM Transmitter parameters +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_dtm_tx_start(const esp_ble_dtm_tx_t *tx_params); + +/** +* @brief This function is used to start a test where the DUT receives test reference packets +* at a fixed interval. +* +* @param[in] rx_params : DTM Receiver parameters +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_dtm_rx_start(const esp_ble_dtm_rx_t *rx_params); +#endif //#if (BLE_42_FEATURE_SUPPORT == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) + +/** +* @brief This function is used to start a test where the DUT generates reference packets +* at a fixed interval. +* +* @param[in] tx_params : DTM Transmitter parameters +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_dtm_enh_tx_start(const esp_ble_dtm_enh_tx_t *tx_params); + +/** +* @brief This function is used to start a test where the DUT receives test reference packets +* at a fixed interval. +* +* @param[in] rx_params : DTM Receiver parameters +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_dtm_enh_rx_start(const esp_ble_dtm_enh_rx_t *rx_params); +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +/** +* @brief This function is used to stop any test which is in progress +* +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_dtm_stop(void); + #ifdef __cplusplus } #endif diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index c99ff8745219..82fa8ff0fe6d 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -5686,7 +5686,35 @@ void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data) p_data->ble_multi_adv_disable.inst_id, p_ref, BTA_FAILURE); } } + +void bta_dm_ble_gap_dtm_tx_start(tBTA_DM_MSG *p_data) +{ + BTM_BleTransmitterTest(p_data->dtm_tx_start.tx_channel, p_data->dtm_tx_start.len_of_data, p_data->dtm_tx_start.pkt_payload, p_data->dtm_tx_start.p_dtm_cmpl_cback); +} + +void bta_dm_ble_gap_dtm_rx_start(tBTA_DM_MSG *p_data) +{ + BTM_BleReceiverTest(p_data->dtm_rx_start.rx_channel, p_data->dtm_rx_start.p_dtm_cmpl_cback); +} + +void bta_dm_ble_gap_dtm_stop(tBTA_DM_MSG *p_data) +{ + BTM_BleTestEnd(p_data->dtm_stop.p_dtm_cmpl_cback); +} + #if (BLE_50_FEATURE_SUPPORT == TRUE) +void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data) +{ + BTM_BleEnhancedTransmitterTest(p_data->dtm_enh_tx_start.tx_channel, p_data->dtm_enh_tx_start.len_of_data, + p_data->dtm_enh_tx_start.pkt_payload, p_data->dtm_enh_tx_start.phy, p_data->dtm_enh_tx_start.p_dtm_cmpl_cback); +} + +void bta_dm_ble_gap_dtm_enhance_rx_start(tBTA_DM_MSG *p_data) +{ + BTM_BleEnhancedReceiverTest(p_data->dtm_enh_rx_start.rx_channel, p_data->dtm_enh_rx_start.phy, + p_data->dtm_enh_rx_start.modulation_index, p_data->dtm_enh_rx_start.p_dtm_cmpl_cback); +} + void bta_dm_ble_gap_read_phy(tBTA_DM_MSG *p_data) { //tBTM_STATUS btm_status = 0; diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c index a214fa038bb0..ede373efde8a 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -2547,6 +2547,49 @@ void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length, tBTA_S } } +void BTA_DmBleDtmTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + tBTA_DM_API_BLE_DTM_TX_START *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_DTM_TX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_TX_START))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_DTM_TX_START_EVT; + p_msg->tx_channel = tx_channel; + p_msg->len_of_data = len_of_data; + p_msg->pkt_payload = pkt_payload; + p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback; + + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleDtmRxStart(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + tBTA_DM_API_BLE_DTM_RX_START *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_DTM_RX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_RX_START))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_DTM_RX_START_EVT; + p_msg->rx_channel= rx_channel; + p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback; + + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + tBTA_DM_API_BLE_DTM_STOP *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_DTM_STOP *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_STOP))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_DTM_STOP_EVT; + p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback; + + bta_sys_sendmsg(p_msg); + } +} + #endif /******************************************************************************* @@ -3228,6 +3271,39 @@ void BTA_DmBleGapExtConnect(tBLE_ADDR_TYPE own_addr_type, const BD_ADDR peer_add } +void BTA_DmBleDtmEnhTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + tBTA_DM_API_BLE_DTM_ENH_TX_START *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_DTM_ENH_TX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_ENH_TX_START))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_DTM_ENH_TX_START_EVT; + p_msg->tx_channel = tx_channel; + p_msg->len_of_data = len_of_data; + p_msg->pkt_payload = pkt_payload; + p_msg->phy = phy; + p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback; + + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleDtmEnhRxStart(uint8_t rx_channel, uint8_t phy, uint8_t modulation_index, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + tBTA_DM_API_BLE_DTM_ENH_RX_START *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_DTM_ENH_RX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_ENH_RX_START))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_DTM_ENH_RX_START_EVT; + p_msg->rx_channel= rx_channel; + p_msg->phy = phy; + p_msg->modulation_index = modulation_index; + p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback; + + bta_sys_sendmsg(p_msg); + } +} + #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c index 81866380c6b0..83e8b12ca825 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -211,6 +211,8 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_ble_gap_ext_scan, /* BTA_DM_API_START_EXT_SCAN_EVT */ bta_dm_ble_gap_set_prefer_ext_conn_params, /* BTA_DM_API_SET_PERF_EXT_CONN_PARAMS_EVT */ NULL, /* BTA_DM_API_EXT_CONN_EVT */ + bta_dm_ble_gap_dtm_enhance_tx_start, /* BTA_DM_API_DTM_ENH_TX_START_EVT */ + bta_dm_ble_gap_dtm_enhance_rx_start, /* BTA_DM_API_DTM_ENH_RX_START_EVT */ #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) bta_dm_ble_gap_periodic_adv_recv_enable, /* BTA_DM_API_PERIODIC_ADV_RECV_ENABLE_EVT */ @@ -218,6 +220,11 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_ble_gap_periodic_adv_set_info_trans, /* BTA_DM_API_PERIODIC_ADV_SET_INFO_TRANS_EVT */ bta_dm_ble_gap_set_periodic_adv_sync_trans_params, /* BTA_DM_API_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS_EVT */ #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if BLE_INCLUDED == TRUE + bta_dm_ble_gap_dtm_tx_start, /* BTA_DM_API_DTM_TX_START_EVT */ + bta_dm_ble_gap_dtm_rx_start, /* BTA_DM_API_DTM_RX_START_EVT */ + bta_dm_ble_gap_dtm_stop, /* BTA_DM_API_DTM_STOP_EVT */ +#endif }; diff --git a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index 386df1354c28..6694c0dfc2b7 100644 --- a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h @@ -204,6 +204,8 @@ enum { BTA_DM_API_START_EXT_SCAN_EVT, BTA_DM_API_SET_PERF_EXT_CONN_PARAMS_EVT, BTA_DM_API_EXT_CONN_EVT, + BTA_DM_API_DTM_ENH_TX_START_EVT, + BTA_DM_API_DTM_ENH_RX_START_EVT, #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) BTA_DM_API_PERIODIC_ADV_RECV_ENABLE_EVT, @@ -211,6 +213,11 @@ enum { BTA_DM_API_PERIODIC_ADV_SET_INFO_TRANS_EVT, BTA_DM_API_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS_EVT, #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if BLE_INCLUDED == TRUE + BTA_DM_API_DTM_TX_START_EVT, + BTA_DM_API_DTM_RX_START_EVT, + BTA_DM_API_DTM_STOP_EVT, +#endif BTA_DM_MAX_EVT }; @@ -870,6 +877,25 @@ typedef struct { BD_ADDR remote_bda; } tBTA_DM_API_BLE_DISCONNECT; +typedef struct { + BT_HDR hdr; + UINT8 tx_channel; + UINT8 len_of_data; + UINT8 pkt_payload; + tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback; +} tBTA_DM_API_BLE_DTM_TX_START; + +typedef struct { + BT_HDR hdr; + UINT8 rx_channel; + tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback; +} tBTA_DM_API_BLE_DTM_RX_START; + +typedef struct { + BT_HDR hdr; + tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback; +} tBTA_DM_API_BLE_DTM_STOP; + #endif /* BLE_INCLUDED */ /* data type for BTA_DM_API_REMOVE_ACL_EVT */ @@ -926,6 +952,22 @@ typedef struct { #endif #if (BLE_50_FEATURE_SUPPORT == TRUE) +typedef struct { + BT_HDR hdr; + UINT8 tx_channel; + UINT8 len_of_data; + UINT8 pkt_payload; + UINT8 phy; + tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback; +} tBTA_DM_API_BLE_DTM_ENH_TX_START; +typedef struct { + BT_HDR hdr; + UINT8 rx_channel; + UINT8 phy; + UINT8 modulation_index; + tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback; +} tBTA_DM_API_BLE_DTM_ENH_RX_START; + #define BTA_PHY_1M_MASK (1 << 0) #define BTA_PHY_2M_MASK (1 << 1) #define BTAS_PHY_CODED_MASK (1 << 2) @@ -1238,6 +1280,8 @@ typedef union { tBTA_DM_API_SET_EXT_SCAN_PARAMS ble_set_ext_scan_params; tBTA_DM_API_EXT_SCAN ble_ext_scan; tBTA_DM_API_SET_PER_EXT_CONN_PARAMS ble_set_per_ext_conn_params; + tBTA_DM_API_BLE_DTM_ENH_TX_START dtm_enh_tx_start; + tBTA_DM_API_BLE_DTM_ENH_RX_START dtm_enh_rx_start; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) tBTA_DM_API_PERIODIC_ADV_RECV_ENABLE ble_periodic_adv_recv_enable; @@ -1245,6 +1289,10 @@ typedef union { tBTA_DM_API_PERIODIC_ADV_SET_INFO_TRANS ble_periodic_adv_set_info_trans; tBTA_DM_API_SET_PAST_PARAMS ble_set_past_params; #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) + + tBTA_DM_API_BLE_DTM_TX_START dtm_tx_start; + tBTA_DM_API_BLE_DTM_RX_START dtm_rx_start; + tBTA_DM_API_BLE_DTM_STOP dtm_stop; #endif tBTA_DM_API_REMOVE_ACL remove_acl; @@ -1681,7 +1729,13 @@ extern void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_gap_dtm_tx_start(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_gap_dtm_rx_start(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_gap_dtm_stop(tBTA_DM_MSG *p_data); + #if (BLE_50_FEATURE_SUPPORT == TRUE) +extern void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_gap_dtm_enhance_rx_start(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_read_phy(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_prefer_default_phy(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_prefer_phy(tBTA_DM_MSG *p_data); diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_api.h index fd0d2350aad1..bddc51bc007c 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -425,6 +425,8 @@ typedef tBTM_UPDATE_WHITELIST_CBACK tBTA_UPDATE_WHITELIST_CBACK; typedef tBTM_SET_PKT_DATA_LENGTH_CBACK tBTA_SET_PKT_DATA_LENGTH_CBACK; +typedef tBTM_DTM_CMD_CMPL_CBACK tBTA_DTM_CMD_CMPL_CBACK; + typedef tBTM_SET_RAND_ADDR_CBACK tBTA_SET_RAND_ADDR_CBACK; typedef tBTM_SET_LOCAL_PRIVACY_CBACK tBTA_SET_LOCAL_PRIVACY_CBACK; @@ -2815,6 +2817,10 @@ extern void BTA_DmBleDisconnect(BD_ADDR bd_addr); *******************************************************************************/ extern void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length, tBTA_SET_PKT_DATA_LENGTH_CBACK *p_set_pkt_data_cback); +extern void BTA_DmBleDtmTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); +extern void BTA_DmBleDtmRxStart(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); +extern void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); + /******************************************************************************* ** ** Function BTA_DmBleSetStorageParams @@ -3069,6 +3075,10 @@ extern void BTA_DmBleGapPreferExtConnectParamsSet(BD_ADDR bd_addr, const tBTA_DM_BLE_CONN_PARAMS *phy_coded_conn_params); extern void BTA_DmBleGapExtConnect(tBLE_ADDR_TYPE own_addr_type, const BD_ADDR peer_addr); + +extern void BTA_DmBleDtmEnhTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); + +extern void BTA_DmBleDtmEnhRxStart(uint8_t rx_channel, uint8_t phy, uint8_t modulation_index, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) diff --git a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c index 7c33072b0152..4364f3802696 100644 --- a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -1145,6 +1145,91 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, } } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +void btc_dtm_tx_start_callback(void *p1) +{ + UINT8 status; + UINT8 *p; + p = (UINT8*) p1; + if (p1) { + STREAM_TO_UINT8(status, p); + BTC_TRACE_DEBUG("DTM TX start, status 0x%x\n", status); + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_DTM_TEST_UPDATE_EVT; + param.dtm_state_update.status = status; + param.dtm_state_update.update_evt = DTM_TX_START_EVT; + param.dtm_state_update.num_of_pkt = 0; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } + } +} + +void btc_dtm_rx_start_callback(void *p1) +{ + + UINT8 status; + UINT8 *p; + p = (UINT8*) p1; + if (p1) { + STREAM_TO_UINT8(status, p); + BTC_TRACE_DEBUG("DTM RX start, status 0x%x\n", status); + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_DTM_TEST_UPDATE_EVT; + param.dtm_state_update.status = status; + param.dtm_state_update.update_evt = DTM_RX_START_EVT; + param.dtm_state_update.num_of_pkt = 0; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } + } +} + +void btc_dtm_stop_callback(void *p1) +{ + UINT8 status; + UINT16 num_pkt; + UINT8 *p; + p = (UINT8*) p1; + if (p1) { + STREAM_TO_UINT8(status, p); + STREAM_TO_UINT16(num_pkt, p); + BTC_TRACE_DEBUG("DTM stop, status 0x%x num_pkt %d\n", status, num_pkt); + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_DTM_TEST_UPDATE_EVT; + param.dtm_state_update.status = status; + param.dtm_state_update.update_evt = DTM_TEST_STOP_EVT; + param.dtm_state_update.num_of_pkt = num_pkt; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } + } +} + void btc_get_whitelist_size(uint16_t *length) { BTM_BleGetWhiteListSize(length); @@ -1274,6 +1359,38 @@ static void btc_gap_ble_set_channels(esp_gap_ble_channels channels) BTA_DmBleSetChannels(channels, btc_gap_ble_set_channels_cmpl_callback); } +#if (BLE_42_FEATURE_SUPPORT == TRUE) +static void btc_ble_dtm_tx_start(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + BTA_DmBleDtmTxStart(tx_channel, len_of_data, pkt_payload, p_dtm_cmpl_cback); +} + +static void btc_ble_dtm_rx_start(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + + BTA_DmBleDtmRxStart(rx_channel, p_dtm_cmpl_cback); +} +#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +static void btc_ble_dtm_enhance_tx_start(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + BTA_DmBleDtmEnhTxStart(tx_channel, len_of_data, pkt_payload, phy, p_dtm_cmpl_cback); +} + +static void btc_ble_dtm_enhance_rx_start(uint8_t rx_channel, uint8_t phy, uint8_t modulation_index, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + + BTA_DmBleDtmEnhRxStart(rx_channel, phy, modulation_index, p_dtm_cmpl_cback); +} +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +static void btc_ble_dtm_stop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) +{ + + BTA_DmBleDtmStop(p_dtm_cmpl_cback); +} + void btc_gap_ble_cb_handler(btc_msg_t *msg) { @@ -2019,6 +2136,25 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) (tBTA_DM_BLE_PAST_PARAMS *)&arg_5->set_periodic_adv_sync_trans_params.params); break; #endif +#if (BLE_42_FEATURE_SUPPORT == TRUE) + case BTC_GAP_BLE_DTM_TX_START: + btc_ble_dtm_tx_start(arg->dtm_tx_start.tx_channel, arg->dtm_tx_start.len_of_data, arg->dtm_tx_start.pkt_payload, btc_dtm_tx_start_callback); + break; + case BTC_GAP_BLE_DTM_RX_START: + btc_ble_dtm_rx_start(arg->dtm_rx_start.rx_channel, btc_dtm_rx_start_callback); + break; +#endif // if (BLE_42_FEATURE_SUPPORT == TRUE) + case BTC_GAP_BLE_DTM_STOP: + btc_ble_dtm_stop(btc_dtm_stop_callback); + break; +#if (BLE_50_FEATURE_SUPPORT == TRUE) + case BTC_GAP_BLE_DTM_ENH_TX_START: + btc_ble_dtm_enhance_tx_start(arg_5->dtm_enh_tx_start.tx_channel, arg_5->dtm_enh_tx_start.len_of_data, arg_5->dtm_enh_tx_start.pkt_payload, arg_5->dtm_enh_tx_start.phy, btc_dtm_tx_start_callback); + break; + case BTC_GAP_BLE_DTM_ENH_RX_START: + btc_ble_dtm_enhance_rx_start(arg_5->dtm_enh_rx_start.rx_channel, arg_5->dtm_enh_rx_start.phy, arg_5->dtm_enh_rx_start.modulation_index, btc_dtm_rx_start_callback); + break; +#endif // if (BLE_50_FEATURE_SUPPORT == TRUE) default: break; } diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h index 38594b778322..89d72d05d566 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h @@ -84,6 +84,8 @@ typedef enum { BTC_GAP_BLE_START_EXT_SCAN, BTC_GAP_BLE_STOP_EXT_SCAN, BTC_GAP_BLE_SET_EXT_PEFER_CONNET_PARAMS, + BTC_GAP_BLE_DTM_ENH_TX_START, + BTC_GAP_BLE_DTM_ENH_RX_START, #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) BTC_GAP_BLE_ACT_GET_DEV_NAME, #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) @@ -92,6 +94,11 @@ typedef enum { BTC_GAP_BLE_PERIODIC_ADV_SET_INFO_TRANS, BTC_GAP_BLE_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS, #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_42_FEATURE_SUPPORT == TRUE) + BTC_GAP_BLE_DTM_TX_START, + BTC_GAP_BLE_DTM_RX_START, +#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) + BTC_GAP_BLE_DTM_STOP, } btc_gap_ble_act_t; /* btc_ble_gap_args_t */ @@ -230,6 +237,14 @@ typedef union { struct set_channels_args { esp_gap_ble_channels channels; } set_channels; + struct dtm_tx_start_args { + uint8_t tx_channel; + uint8_t len_of_data; + uint8_t pkt_payload; + } dtm_tx_start; + struct dtm_rx_start_args { + uint8_t rx_channel; + } dtm_rx_start; } btc_ble_gap_args_t; #if (BLE_50_FEATURE_SUPPORT == TRUE) @@ -373,7 +388,17 @@ typedef union { esp_ble_gap_past_params_t params; } set_periodic_adv_sync_trans_params; #endif - + struct dtm_enh_tx_start_args { + uint8_t tx_channel; + uint8_t len_of_data; + uint8_t pkt_payload; + uint8_t phy; + } dtm_enh_tx_start; + struct dtm_enh_rx_start_args { + uint8_t rx_channel; + uint8_t phy; + uint8_t modulation_index; + } dtm_enh_rx_start; } btc_ble_5_gap_args_t; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c index 729134686e2d..1f12c344b302 100644 --- a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c @@ -1169,7 +1169,9 @@ UINT8 btsnd_hcic_ble_enhand_rx_test(UINT8 rx_channel, UINT8 phy, UINT8_TO_STREAM(pp, phy); UINT8_TO_STREAM(pp, modulation_idx); - return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + + return TRUE; } UINT8 btsnd_hcic_ble_enhand_tx_test(UINT8 tx_channel, UINT8 len, @@ -1191,7 +1193,9 @@ UINT8 btsnd_hcic_ble_enhand_tx_test(UINT8 tx_channel, UINT8 len, UINT8_TO_STREAM(pp, packect); UINT8_TO_STREAM(pp, phy); - return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + + return TRUE; } UINT8 btsnd_hcic_ble_set_extend_rand_address(UINT8 adv_handle, BD_ADDR rand_addr) diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_api.h index 5120259ecce3..9e5b28915301 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_api.h @@ -189,6 +189,8 @@ typedef void (tBTM_UPDATE_CONN_PARAM_CBACK) (UINT8 status, BD_ADDR bd_addr, tBTM typedef void (tBTM_SET_PKT_DATA_LENGTH_CBACK) (UINT8 status, tBTM_LE_SET_PKT_DATA_LENGTH_PARAMS *data_length_params); +typedef void (tBTM_DTM_CMD_CMPL_CBACK) (void *p1); + typedef void (tBTM_SET_RAND_ADDR_CBACK) (UINT8 status); typedef void (tBTM_UPDATE_WHITELIST_CBACK) (UINT8 status, tBTM_WL_OPERATION wl_opration); diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h index 07fc0ee965c4..3df5120421a8 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h @@ -2688,6 +2688,11 @@ tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params); tBTM_STATUS BTM_BleExtendedScan(BOOLEAN enable, UINT16 duration, UINT16 period); void BTM_BleSetPreferExtenedConnParams(BD_ADDR bd_addr, tBTM_EXT_CONN_PARAMS *params); + +void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_index, tBTM_CMPL_CB *p_cmd_cmpl_cback); + +void BTM_BleEnhancedTransmitterTest(UINT8 tx_freq, UINT8 test_data_len, UINT8 packet_payload, UINT8 phy, tBTM_CMPL_CB *p_cmd_cmpl_cback); + #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) From 23a20e4b27633cc6a0722abcef758a223fd105dd Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Fri, 8 Sep 2023 19:41:16 +0800 Subject: [PATCH 069/142] feat(ble/bluedroid): Add API to update config file path --- components/bt/host/bluedroid/api/esp_bt_device.c | 10 +++++++++- .../bt/host/bluedroid/api/esp_gatt_common_api.c | 2 +- .../bluedroid/api/include/api/esp_bt_device.h | 14 +++++++++++++- .../bt/host/bluedroid/btc/core/btc_config.c | 16 ++++++++++++++-- .../host/bluedroid/btc/include/btc/btc_config.h | 1 + 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_bt_device.c b/components/bt/host/bluedroid/api/esp_bt_device.c index 0a323cfe2992..c37b9adb61e1 100644 --- a/components/bt/host/bluedroid/api/esp_bt_device.c +++ b/components/bt/host/bluedroid/api/esp_bt_device.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #include "device/controller.h" #include "btc/btc_task.h" #include "btc/btc_dev.h" +#include "btc/btc_config.h" const uint8_t *esp_bt_dev_get_address(void) { @@ -68,3 +69,10 @@ esp_err_t esp_bt_dev_coex_status_config(esp_bt_dev_coex_type_t type, esp_bt_dev_ return (btc_transfer_context(&msg, &arg, sizeof(btc_dev_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } #endif + +esp_err_t esp_bt_config_file_path_update(const char *file_path) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_UNINITIALIZED); + + return btc_config_file_path_update(file_path); +} diff --git a/components/bt/host/bluedroid/api/esp_gatt_common_api.c b/components/bt/host/bluedroid/api/esp_gatt_common_api.c index a6a52bf2e2b4..d0f3b0e02abd 100644 --- a/components/bt/host/bluedroid/api/esp_gatt_common_api.c +++ b/components/bt/host/bluedroid/api/esp_gatt_common_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/bt/host/bluedroid/api/include/api/esp_bt_device.h b/components/bt/host/bluedroid/api/include/api/esp_bt_device.h index 997d827f652f..5c00c45616c5 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_bt_device.h +++ b/components/bt/host/bluedroid/api/include/api/esp_bt_device.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -79,6 +79,18 @@ esp_err_t esp_bt_dev_set_device_name(const char *name); */ esp_err_t esp_bt_dev_coex_status_config(esp_bt_dev_coex_type_t type, esp_bt_dev_coex_op_t op, uint8_t status); +/** + * @brief This function is used to update the path name of bluetooth bond keys saved in the NVS module + * and need to be called before esp_bluedroid_init(). + * @param[in] file_path: the name of config file path, the length of file_path should be less than NVS_NS_NAME_MAX_SIZE + * + * @return + * - ESP_OK: success + * - other: failed + * + */ +esp_err_t esp_bt_config_file_path_update(const char *file_path); + #ifdef __cplusplus } #endif diff --git a/components/bt/host/bluedroid/btc/core/btc_config.c b/components/bt/host/bluedroid/btc/core/btc_config.c index 32393636e727..955d3d266fde 100644 --- a/components/bt/host/bluedroid/btc/core/btc_config.c +++ b/components/bt/host/bluedroid/btc/core/btc_config.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,14 +20,26 @@ #include "osi/mutex.h" #include "stack/bt_types.h" +#include "nvs.h" -static const char *CONFIG_FILE_PATH = "bt_config.conf"; +static char CONFIG_FILE_PATH[NVS_NS_NAME_MAX_SIZE] = "bt_config.conf"; static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000; static void btc_key_value_to_string(uint8_t *key_value, char *value_str, int key_length); static osi_mutex_t lock; // protects operations on |config|. static config_t *config; +int btc_config_file_path_update(const char *file_path) +{ + if (file_path != NULL && strlen(file_path) < NVS_NS_NAME_MAX_SIZE) { + memcpy(CONFIG_FILE_PATH, file_path, strlen(file_path)); + CONFIG_FILE_PATH[strlen(file_path)] = '\0'; + return 0; + } + BTC_TRACE_ERROR("Update failed, file_path is NULL or length should be less than %d\n", NVS_NS_NAME_MAX_SIZE); + return -1; +} + bool btc_compare_address_key_value(const char *section, const char *key_type, void *key_value, int key_length) { assert(key_value != NULL); diff --git a/components/bt/host/bluedroid/btc/include/btc/btc_config.h b/components/bt/host/bluedroid/btc/include/btc/btc_config.h index 731859a8cb23..eb3c89d54d45 100644 --- a/components/bt/host/bluedroid/btc/include/btc/btc_config.h +++ b/components/bt/host/bluedroid/btc/include/btc/btc_config.h @@ -47,4 +47,5 @@ bool btc_get_device_type(const BD_ADDR bd_addr, int *p_device_type); void btc_config_lock(void); void btc_config_unlock(void); +int btc_config_file_path_update(const char *file_path); #endif From eafa7230938ea1a0220ad99ef57e25c2899bfbe2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 21 Sep 2023 18:31:40 +0200 Subject: [PATCH 070/142] feat(bt): migrate the tests from unit-test-app --- components/bt/test/CMakeLists.txt | 6 --- components/bt/test_apps/.build-test-rules.yml | 8 ++++ components/bt/test_apps/CMakeLists.txt | 9 ++++ components/bt/test_apps/README.md | 21 ++++++++ components/bt/test_apps/main/CMakeLists.txt | 6 +++ .../{test => test_apps/main}/test_bt_common.c | 4 ++ components/bt/test_apps/main/test_bt_main.c | 48 +++++++++++++++++++ .../bt/{test => test_apps/main}/test_smp.c | 24 ++-------- components/bt/test_apps/pytest_bt.py | 12 +++++ .../bt/test_apps/sdkconfig.defaults | 3 +- 10 files changed, 114 insertions(+), 27 deletions(-) delete mode 100644 components/bt/test/CMakeLists.txt create mode 100644 components/bt/test_apps/.build-test-rules.yml create mode 100644 components/bt/test_apps/CMakeLists.txt create mode 100644 components/bt/test_apps/README.md create mode 100644 components/bt/test_apps/main/CMakeLists.txt rename components/bt/{test => test_apps/main}/test_bt_common.c (76%) create mode 100644 components/bt/test_apps/main/test_bt_main.c rename components/bt/{test => test_apps/main}/test_smp.c (90%) create mode 100644 components/bt/test_apps/pytest_bt.py rename tools/unit-test-app/configs/bt => components/bt/test_apps/sdkconfig.defaults (56%) diff --git a/components/bt/test/CMakeLists.txt b/components/bt/test/CMakeLists.txt deleted file mode 100644 index 180675d21da1..000000000000 --- a/components/bt/test/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -if(CONFIG_BT_ENABLED OR CMAKE_BUILD_EARLY_EXPANSION) - idf_component_register(SRC_DIRS "." - PRIV_INCLUDE_DIRS "." - PRIV_REQUIRES cmock nvs_flash bt esp_ringbuf) - target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") -endif() diff --git a/components/bt/test_apps/.build-test-rules.yml b/components/bt/test_apps/.build-test-rules.yml new file mode 100644 index 000000000000..f96777d2dabc --- /dev/null +++ b/components/bt/test_apps/.build-test-rules.yml @@ -0,0 +1,8 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/bt/test_apps: + disable: + - if: IDF_TARGET not in ["esp32", "esp32c3"] + reason: Sufficient to run the tests on one chip of each architecture + depends_components: + - bt diff --git a/components/bt/test_apps/CMakeLists.txt b/components/bt/test_apps/CMakeLists.txt new file mode 100644 index 000000000000..ab61d4b68ca6 --- /dev/null +++ b/components/bt/test_apps/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) +list(PREPEND SDKCONFIG_DEFAULTS + "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers" + "sdkconfig.defaults") + +project(bt_test) diff --git a/components/bt/test_apps/README.md b/components/bt/test_apps/README.md new file mode 100644 index 000000000000..fc828476cbbf --- /dev/null +++ b/components/bt/test_apps/README.md @@ -0,0 +1,21 @@ +| Supported Targets | ESP32 | ESP32-C3 | +| ----------------- | ----- | -------- | + +# `bt` component unit tests + +When adding new test cases, check if the `depends_components` list in `.build-test-rules.yml` needs to be updated to include additional components. The test app will only be built and tested when these components are modified. + +To build and run this test app, using esp32c3 target for example: + +```bash +idf.py set-target esp32c3 +idf.py build flash monitor +``` + +To run tests using pytest: + +```bash +idf.py set-target esp32c3 +idf.py build +pytest --target=esp32c3 +``` diff --git a/components/bt/test_apps/main/CMakeLists.txt b/components/bt/test_apps/main/CMakeLists.txt new file mode 100644 index 000000000000..6aecb24e3d69 --- /dev/null +++ b/components/bt/test_apps/main/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register(SRCS "test_bt_main.c" + "test_bt_common.c" + "test_smp.c" + INCLUDE_DIRS "." + PRIV_REQUIRES unity bt + WHOLE_ARCHIVE) diff --git a/components/bt/test/test_bt_common.c b/components/bt/test_apps/main/test_bt_common.c similarity index 76% rename from components/bt/test/test_bt_common.c rename to components/bt/test_apps/main/test_bt_common.c index 47182235f14f..402633d0a52c 100644 --- a/components/bt/test/test_bt_common.c +++ b/components/bt/test_apps/main/test_bt_common.c @@ -11,10 +11,14 @@ #include #include "unity.h" +#include "sdkconfig.h" +// btdm_controller_compile_version_check defined only for ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 extern bool btdm_controller_compile_version_check(void); TEST_CASE("bt_controller_git_commit_check", "[bt_common]") { TEST_ASSERT(btdm_controller_compile_version_check() == true); } +#endif diff --git a/components/bt/test_apps/main/test_bt_main.c b/components/bt/test_apps/main/test_bt_main.c new file mode 100644 index 000000000000..53a93c95d07c --- /dev/null +++ b/components/bt/test_apps/main/test_bt_main.c @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "esp_heap_caps.h" + +#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT 0 +static int leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT; +void set_leak_threshold(int threshold) +{ + leak_threshold = threshold; +} + +static size_t before_free_8bit; +static size_t before_free_32bit; + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= leak_threshold, "memory leak"); +} + +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); + + leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT; +} + +void app_main(void) +{ + printf("Running bt component tests\n"); + unity_run_menu(); +} diff --git a/components/bt/test/test_smp.c b/components/bt/test_apps/main/test_smp.c similarity index 90% rename from components/bt/test/test_smp.c rename to components/bt/test_apps/main/test_smp.c index 9cf51c41a718..4eefbe12f4bf 100644 --- a/components/bt/test/test_smp.c +++ b/components/bt/test_apps/main/test_smp.c @@ -1,46 +1,32 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ /* - Tests for the BLE SMP implementation -*/ + * Tests for the BLE SMP implementation + */ -#include -#include -#include -#include -#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" -#include "esp_heap_caps.h" -#include "esp_log.h" -#include "freertos/ringbuf.h" #include "esp_random.h" -#include "nvs_flash.h" #include "esp_bt.h" #include "esp_bt_main.h" #include "esp_bt_device.h" #include "esp_gap_ble_api.h" -#define TAG "ble_smp_test" - #define KEY_LENGTH_DWORDS_P256 8 typedef unsigned long DWORD; typedef uint32_t UINT32; typedef struct { -DWORD x[KEY_LENGTH_DWORDS_P256]; + DWORD x[KEY_LENGTH_DWORDS_P256]; DWORD y[KEY_LENGTH_DWORDS_P256]; DWORD z[KEY_LENGTH_DWORDS_P256]; } Point; @@ -79,7 +65,7 @@ static void bt_rand(void *buf, size_t len) for (int i = 0; i < (int)(len / sizeof(uint32_t)); i++) { uint32_t rand = esp_random(); - memcpy(buf + i*sizeof(uint32_t), &rand, sizeof(uint32_t)); + memcpy(buf + i * sizeof(uint32_t), &rand, sizeof(uint32_t)); } return; diff --git a/components/bt/test_apps/pytest_bt.py b/components/bt/test_apps/pytest_bt.py new file mode 100644 index 000000000000..74b0a76afc77 --- /dev/null +++ b/components/bt/test_apps/pytest_bt.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.generic +@pytest.mark.esp32 +@pytest.mark.esp32c3 +def test_bt(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/tools/unit-test-app/configs/bt b/components/bt/test_apps/sdkconfig.defaults similarity index 56% rename from tools/unit-test-app/configs/bt rename to components/bt/test_apps/sdkconfig.defaults index f10c710c521d..5847dd3c63f5 100644 --- a/tools/unit-test-app/configs/bt +++ b/components/bt/test_apps/sdkconfig.defaults @@ -1,4 +1,3 @@ -CONFIG_IDF_TARGET="esp32" -TEST_COMPONENTS=bt CONFIG_BT_ENABLED=y CONFIG_UNITY_FREERTOS_STACK_SIZE=12288 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n From 1fbee174af088d9e8c2b3fe7fb8e35ec6ab11c85 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 22 Sep 2023 20:00:53 +0200 Subject: [PATCH 071/142] fix(bt): fixed -Write-strings warning in btm_ble_5_gap.c --- components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c index 3f15dfc64de0..585a5eb9449a 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c @@ -35,7 +35,7 @@ typedef struct { tBTM_EXT_ADV_RECORD adv_record[MAX_BLE_ADV_INSTANCE] = {0}; extern void btm_ble_inter_set(bool extble_inter); -static char *btm_ble_hci_status_to_str(tHCI_STATUS status) +static const char *btm_ble_hci_status_to_str(tHCI_STATUS status) { switch(status) { case HCI_SUCCESS: From f2b238531a515243b245e2e77d17eea08c81d04b Mon Sep 17 00:00:00 2001 From: Martin Vychodil Date: Mon, 25 Sep 2023 21:47:05 +0800 Subject: [PATCH 072/142] Revert "Merge branch 'bugfix/uart_vfs_select_threadsafe' into 'master'" This reverts merge request !25389 --- .../vfs/test_apps/main/test_vfs_select.c | 108 ++---------------- components/vfs/vfs_uart.c | 24 ++-- 2 files changed, 19 insertions(+), 113 deletions(-) diff --git a/components/vfs/test_apps/main/test_vfs_select.c b/components/vfs/test_apps/main/test_vfs_select.c index 08b04728064c..ceab7004f7ea 100644 --- a/components/vfs/test_apps/main/test_vfs_select.c +++ b/components/vfs/test_apps/main/test_vfs_select.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -101,23 +101,6 @@ static void uart1_init(void) uart_param_config(UART_NUM_1, &uart_config); } -static void read_task(void *param) -{ - char recv_message[sizeof(message)]; - const test_task_param_t *test_task_param = param; - vTaskDelay(test_task_param->delay_ms / portTICK_PERIOD_MS); - read(test_task_param->fd, recv_message, sizeof(message)); - if (test_task_param->sem) { - xSemaphoreGive(test_task_param->sem); - } - vTaskDelete(NULL); -} - -static inline void start_read_task(const test_task_param_t *test_task_param) -{ - xTaskCreate(read_task, "read_task", 8*1024, (void *) test_task_param, 5, NULL); -} - static void send_task(void *param) { const test_task_param_t *test_task_param = param; @@ -129,7 +112,7 @@ static void send_task(void *param) vTaskDelete(NULL); } -static inline void start_write_task(const test_task_param_t *test_task_param) +static inline void start_task(const test_task_param_t *test_task_param) { xTaskCreate(send_task, "send_task", 8*1024, (void *) test_task_param, 5, NULL); } @@ -182,7 +165,7 @@ TEST_CASE("UART can do select()", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_write_task(&test_task_param); + start_task(&test_task_param); int s = select(uart_fd + 1, &rfds, NULL, NULL, &tv); TEST_ASSERT_EQUAL(s, 1); @@ -199,7 +182,7 @@ TEST_CASE("UART can do select()", "[vfs]") FD_SET(uart_fd, &rfds); FD_SET(socket_fd, &rfds); - start_write_task(&test_task_param); + start_task(&test_task_param); s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); TEST_ASSERT_EQUAL(s, 1); @@ -240,7 +223,7 @@ TEST_CASE("UART can do poll() with POLLIN event", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_write_task(&test_task_param); + start_task(&test_task_param); int s = poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(s, 1); @@ -258,7 +241,7 @@ TEST_CASE("UART can do poll() with POLLIN event", "[vfs]") poll_fds[1].fd = socket_fd; poll_fds[1].events = POLLIN; - start_write_task(&test_task_param); + start_task(&test_task_param); s = poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(s, 1); @@ -301,7 +284,7 @@ TEST_CASE("UART can do poll() with POLLOUT event", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_write_task(&test_task_param); + start_task(&test_task_param); poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(uart_fd, poll_fds[0].fd); @@ -347,7 +330,7 @@ TEST_CASE("socket can do select()", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_write_task(&test_task_param); + start_task(&test_task_param); const int s = select(MAX(MAX(uart_fd, socket_fd), dummy_socket_fd) + 1, &rfds, NULL, NULL, &tv); TEST_ASSERT_EQUAL(1, s); @@ -396,7 +379,7 @@ TEST_CASE("socket can do poll()", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_write_task(&test_task_param); + start_task(&test_task_param); int s = poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(s, 1); @@ -491,7 +474,8 @@ static void select_task(void *task_param) { const test_select_task_param_t *param = task_param; - select(param->maxfds, param->rdfds, param->wrfds, param->errfds, param->tv); + int s = select(param->maxfds, param->rdfds, param->wrfds, param->errfds, param->tv); + TEST_ASSERT_EQUAL(param->select_ret, s); if (param->sem) { xSemaphoreGive(param->sem); @@ -505,74 +489,6 @@ static void inline start_select_task(test_select_task_param_t *param) } #if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6782 -TEST_CASE("concurrent selects work for UART", "[vfs]") -{ - // This test case initiates two select tasks on the same UART FD, - // One task will wait for a write operation, while the other will wait for a read operation to occur. - // The first task will complete its operation before the second task proceeds with its operation on the same FD - // In this scenario, the write operation will be performed initially, - // followed by the subsequent continuation of the read operation. - - int uart_fd, socket_fd; - init(&uart_fd, &socket_fd); - - const test_task_param_t send_param = { - .fd = uart_fd, - .delay_ms = 0, - .sem = NULL, - }; - - fd_set wrfds1; - FD_ZERO(&wrfds1); - FD_SET(uart_fd, &wrfds1); - - test_select_task_param_t param_write = { - .rdfds = NULL, - .wrfds = &wrfds1, - .errfds = NULL, - .maxfds = uart_fd + 1, - .tv = NULL, - .select_ret = 1, - .sem = xSemaphoreCreateBinary(), - }; - TEST_ASSERT_NOT_NULL(param_write.sem); - //Start first task which will wait on select call for write operation on the UART FD - start_select_task(¶m_write); - - fd_set rdfds2; - FD_ZERO(&rdfds2); - FD_SET(uart_fd, &rdfds2); - - test_select_task_param_t param_read = { - .rdfds = &rdfds2, - .wrfds = NULL, - .errfds = NULL, - .maxfds = uart_fd + 1, - .tv = NULL, - .select_ret = 2, - .sem = xSemaphoreCreateBinary(), - }; - TEST_ASSERT_NOT_NULL(param_read.sem); - //Start second task which will wait on another select call for read operation on the same UART FD - start_select_task(¶m_read); - - //Start writing operation on the UART port - start_write_task(&send_param); - //Confirm the completion of the write operation - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param_write.sem, 1000 / portTICK_PERIOD_MS)); - vSemaphoreDelete(param_write.sem); - TEST_ASSERT(FD_ISSET(uart_fd, &wrfds1)); - - //Start reading operation on the same UART port - start_read_task(&send_param); - //Confirm the completion of the read operation - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param_read.sem, 1000 / portTICK_PERIOD_MS)); - vSemaphoreDelete(param_read.sem); - TEST_ASSERT(FD_ISSET(uart_fd, &rdfds2)); - - deinit(uart_fd, socket_fd); -} - TEST_CASE("concurrent selects work", "[vfs]") { int uart_fd, socket_fd; @@ -648,7 +564,7 @@ TEST_CASE("concurrent selects work", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(send_param.sem); - start_write_task(&send_param); // This task will write to UART which will be detected by select() + start_task(&send_param); // This task will write to UART which will be detected by select() start_select_task(¶m); vTaskDelay(100 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index 9e96d138c917..3e1fcf4a74b7 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,7 +21,6 @@ #include "esp_rom_uart.h" #include "soc/soc_caps.h" #include "hal/uart_ll.h" -#include "freertos/semphr.h" #define UART_NUM SOC_UART_HP_NUM @@ -56,7 +55,6 @@ static int uart_rx_char(int fd); // Functions for sending and receiving bytes which use UART driver static void uart_tx_char_via_driver(int fd, int c); static int uart_rx_char_via_driver(int fd); -static SemaphoreHandle_t uart_select_mutex[UART_NUM]; typedef struct { // Pointers to UART peripherals @@ -152,8 +150,6 @@ static int uart_open(const char *path, int flags, int mode) return -1; } - uart_select_mutex[fd] = xSemaphoreCreateMutex(); - xSemaphoreGive(uart_select_mutex[fd]); s_ctx[fd]->non_blocking = ((flags & O_NONBLOCK) == O_NONBLOCK); return fd; @@ -302,7 +298,6 @@ static int uart_fstat(int fd, struct stat * st) static int uart_close(int fd) { assert(fd >=0 && fd < 3); - vSemaphoreDelete(uart_select_mutex[fd]); return 0; } @@ -442,7 +437,6 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, esp_vfs_select_sem_t select_sem, void **end_select_args) { const int max_fds = MIN(nfds, UART_NUM); - int fd = -1; *end_select_args = NULL; for (int i = 0; i < max_fds; ++i) { @@ -450,7 +444,6 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, if (!uart_is_driver_installed(i)) { return ESP_ERR_INVALID_STATE; } - fd = i; } } @@ -471,11 +464,14 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, FD_ZERO(writefds); FD_ZERO(exceptfds); - xSemaphoreTake(uart_select_mutex[fd], portMAX_DELAY); portENTER_CRITICAL(uart_get_selectlock()); //uart_set_select_notif_callback sets the callbacks in UART ISR - uart_set_select_notif_callback(fd, select_notif_callback_isr); + for (int i = 0; i < max_fds; ++i) { + if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) { + uart_set_select_notif_callback(i, select_notif_callback_isr); + } + } for (int i = 0; i < max_fds; ++i) { if (FD_ISSET(i, &args->readfds_orig)) { @@ -504,23 +500,17 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, static esp_err_t uart_end_select(void *end_select_args) { uart_select_args_t *args = end_select_args; - int fd = -1; portENTER_CRITICAL(uart_get_selectlock()); esp_err_t ret = unregister_select(args); for (int i = 0; i < UART_NUM; ++i) { - if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) { - uart_set_select_notif_callback(i, NULL); - fd = i; - break; - } + uart_set_select_notif_callback(i, NULL); } portEXIT_CRITICAL(uart_get_selectlock()); if (args) { free(args); } - xSemaphoreGive(uart_select_mutex[fd]); return ret; } From 966b8620c2b64348ef60beaebbcaee741568bc10 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 19 Sep 2023 15:58:22 +0200 Subject: [PATCH 073/142] feat(esp_netif): PPP config option to allow disabling LCP runtime If LCP keepalive mechanism is enabled in menuconfig, it's statically configured on creation of an interface and cannot be changed runtime. In some cases it's useful to relax LCP criteria during runtime operation, for example before initiating OTA. This config option allows for disabling already enabled LCP echo (this setting becomes effective after reconnecting, i.e. initializing a new session) Closes https://github.com/espressif/esp-protocols/issues/287 --- components/esp_netif/include/esp_netif_ppp.h | 25 +++++++++---------- .../esp_netif/lwip/esp_netif_lwip_ppp.c | 21 +++++++++++++++- tools/ci/check_copyright_ignore.txt | 1 - 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/components/esp_netif/include/esp_netif_ppp.h b/components/esp_netif/include/esp_netif_ppp.h index 159388e80ea2..c9856c6206fc 100644 --- a/components/esp_netif/include/esp_netif_ppp.h +++ b/components/esp_netif/include/esp_netif_ppp.h @@ -1,16 +1,8 @@ -// Copyright 2019 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: 2019-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // #ifndef _ESP_NETIF_PPP_H_ @@ -29,6 +21,13 @@ ESP_EVENT_DECLARE_BASE(NETIF_PPP_STATUS); typedef struct esp_netif_ppp_config { bool ppp_phase_event_enabled; /**< Enables events coming from PPP PHASE change */ bool ppp_error_event_enabled; /**< Enables events from main PPP state machine producing errors */ +#ifdef CONFIG_LWIP_ENABLE_LCP_ECHO + bool ppp_lcp_echo_disabled; /**< Allows to temporarily disable LCP keepalive (runtime, if enabled compile time) + * When LCP echo is enabled in menuconfig, this option can be used to override the setting, + * if we have to relax LCP keepalive criteria during runtime operation, for example before OTA update. + * The current session must be closed, settings will be applied upon connecting. + * */ +#endif // CONFIG_LWIP_ENABLE_LCP_ECHO } esp_netif_ppp_config_t; /** @brief event id offset for PHASE related events diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c index 4bf697bc2782..b9a3846c5246 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.c +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,6 +31,9 @@ typedef struct lwip_peer2peer_ctx { // PPP specific fields follow bool ppp_phase_event_enabled; bool ppp_error_event_enabled; +#ifdef CONFIG_LWIP_ENABLE_LCP_ECHO + bool ppp_lcp_echo_disabled; +#endif ppp_pcb *ppp; } lwip_peer2peer_ctx_t; @@ -257,6 +260,16 @@ esp_err_t esp_netif_start_ppp(esp_netif_t *esp_netif) lwip_peer2peer_ctx_t *ppp_ctx = (lwip_peer2peer_ctx_t *)netif_related; assert(ppp_ctx->base.netif_type == PPP_LWIP_NETIF); +#ifdef CONFIG_LWIP_ENABLE_LCP_ECHO + if (ppp_ctx->ppp_lcp_echo_disabled) { + ppp_ctx->ppp->settings.lcp_echo_interval = 0; + ppp_ctx->ppp->settings.lcp_echo_fails = 0; + } else { + ppp_ctx->ppp->settings.lcp_echo_interval = LCP_ECHOINTERVAL; + ppp_ctx->ppp->settings.lcp_echo_fails = LCP_MAXECHOFAILS; + } +#endif + ESP_LOGD(TAG, "%s: Starting PPP connection: %p", __func__, ppp_ctx->ppp); esp_err_t err = pppapi_connect(ppp_ctx->ppp, 0); if (err != ESP_OK) { @@ -311,6 +324,9 @@ esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_confi struct lwip_peer2peer_ctx *obj = (struct lwip_peer2peer_ctx *)netif->related_data; obj->ppp_phase_event_enabled = config->ppp_phase_event_enabled; obj->ppp_error_event_enabled = config->ppp_error_event_enabled; +#ifdef CONFIG_LWIP_ENABLE_LCP_ECHO + obj->ppp_lcp_echo_disabled = config->ppp_lcp_echo_disabled; +#endif return ESP_OK; } @@ -323,5 +339,8 @@ esp_err_t esp_netif_ppp_get_params(esp_netif_t *netif, esp_netif_ppp_config_t *c struct lwip_peer2peer_ctx *obj = (struct lwip_peer2peer_ctx *)netif->related_data; config->ppp_phase_event_enabled = obj->ppp_phase_event_enabled; config->ppp_error_event_enabled = obj->ppp_error_event_enabled; +#ifdef CONFIG_LWIP_ENABLE_LCP_ECHO + config->ppp_lcp_echo_disabled = obj->ppp_lcp_echo_disabled; +#endif return ESP_OK; } diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 9405c40e159d..0c64d0b84121 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -422,7 +422,6 @@ components/esp_hid/src/esp_hid_common.c components/esp_local_ctrl/src/esp_local_ctrl_handler.c components/esp_local_ctrl/src/esp_local_ctrl_priv.h components/esp_local_ctrl/src/esp_local_ctrl_transport_ble.c -components/esp_netif/include/esp_netif_ppp.h components/esp_phy/test/test_phy_rtc.c components/esp_pm/include/esp_private/pm_trace.h components/esp_rom/esp32/ld/esp32.rom.api.ld From 10a5fcf99e4d94e2785cbb40fa74d7decfcd0ee5 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 19 Sep 2023 16:01:49 +0200 Subject: [PATCH 074/142] feat(esp_netif): PPP: Use RAM allocated pbufs instead of POOL (fixed size) PPP netif: Used allocated packet buffers of exact size for input to TCP/IP stack to consume less memory in download mode (compared to the previously used fixed sized packet buffers) --- components/esp_netif/CMakeLists.txt | 2 +- .../esp_netif/lwip/esp_netif_lwip_ppp.c | 3 +- components/esp_netif/lwip/netif/ppp.c | 28 +++++++++++++++++++ components/esp_netif/lwip/netif/pppif.h | 22 +++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 components/esp_netif/lwip/netif/ppp.c create mode 100644 components/esp_netif/lwip/netif/pppif.h diff --git a/components/esp_netif/CMakeLists.txt b/components/esp_netif/CMakeLists.txt index 77a10dad8428..7c6f04e41b61 100644 --- a/components/esp_netif/CMakeLists.txt +++ b/components/esp_netif/CMakeLists.txt @@ -24,7 +24,7 @@ if(${target} STREQUAL "linux") endif() if(CONFIG_PPP_SUPPORT) - list(APPEND srcs_lwip lwip/esp_netif_lwip_ppp.c) + list(APPEND srcs_lwip lwip/esp_netif_lwip_ppp.c lwip/netif/ppp.c) endif() diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c index b9a3846c5246..5233dd31a52e 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.c +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c @@ -17,6 +17,7 @@ #include "esp_netif_lwip_internal.h" #include #include "lwip/ip6_addr.h" +#include "netif/pppif.h" ESP_EVENT_DEFINE_BASE(NETIF_PPP_STATUS); @@ -285,7 +286,7 @@ esp_err_t esp_netif_start_ppp(esp_netif_t *esp_netif) esp_netif_recv_ret_t esp_netif_lwip_ppp_input(void *ppp_ctx, void *buffer, size_t len, void *eb) { struct lwip_peer2peer_ctx * obj = ppp_ctx; - err_t ret = pppos_input_tcpip(obj->ppp, buffer, len); + err_t ret = pppos_input_tcpip_as_ram_pbuf(obj->ppp, buffer, len); if (ret != ERR_OK) { ESP_LOGE(TAG, "pppos_input_tcpip failed with %d", ret); return ESP_NETIF_OPTIONAL_RETURN_CODE(ESP_FAIL); diff --git a/components/esp_netif/lwip/netif/ppp.c b/components/esp_netif/lwip/netif/ppp.c new file mode 100644 index 000000000000..f28627520c74 --- /dev/null +++ b/components/esp_netif/lwip/netif/ppp.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2001-2004 Swedish Institute of Computer Science + * + * SPDX-License-Identifier: BSD-3-Clause + * + * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD + */ +#include "pppif.h" +#include "lwip/tcpip.h" + +/* + * Similar to pppos_input_tcpip() from lwip's ppp netif, but instead + * of PBUF_POOL, we use PBUF_RAM type of the pbuf we pass to the stack + */ +err_t pppos_input_tcpip_as_ram_pbuf(ppp_pcb *ppp, u8_t *s, int l) +{ + struct pbuf *p = pbuf_alloc(PBUF_RAW, l, PBUF_RAM); + if (!p) { + return ERR_MEM; + } + pbuf_take(p, s, l); + + err_t err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys); + if (err != ERR_OK) { + pbuf_free(p); + } + return err; +} diff --git a/components/esp_netif/lwip/netif/pppif.h b/components/esp_netif/lwip/netif/pppif.h new file mode 100644 index 000000000000..968911655936 --- /dev/null +++ b/components/esp_netif/lwip/netif/pppif.h @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2001-2004 Swedish Institute of Computer Science + * + * SPDX-License-Identifier: BSD-3-Clause + * + * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD + */ +#include "lwip/pbuf.h" +#include "netif/ppp/pppos.h" + +/** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. + * + * This function uses allocated packet buffers of exact size for input to TCP/IP stack + * to consume less memory in download mode, compared to the pppos_input_tcpip() from lwIP. + * (original implementation uses `PBUF_POOL`, which on ESP port uses standard malloc + * to allocate a fixed size pbuf) + * + * @param ppp PPP descriptor index, returned by pppos_create() + * @param s received data + * @param l length of received data + */ + err_t pppos_input_tcpip_as_ram_pbuf(ppp_pcb *ppp, u8_t *s, int l); From a937efef1ac7e4971cde915cf5426fd109def29a Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Thu, 21 Sep 2023 17:45:55 +0800 Subject: [PATCH 075/142] feat(pthread): added pthread_condattr* stubs to avoid linker errors Closes https://github.com/espressif/esp-idf/issues/12171 --- components/newlib/pthread.c | 6 ----- components/pthread/pthread_cond_var.c | 35 ++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/components/newlib/pthread.c b/components/newlib/pthread.c index 0440e39e52b7..60dfe2e36254 100644 --- a/components/newlib/pthread.c +++ b/components/newlib/pthread.c @@ -8,12 +8,6 @@ const static char *TAG = "esp32_asio_pthread"; -int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) -{ - ESP_LOGW(TAG, "%s: not yet supported!", __func__); - return 0; -} - int pthread_setcancelstate(int state, int *oldstate) { return 0; diff --git a/components/pthread/pthread_cond_var.c b/components/pthread/pthread_cond_var.c index fc6f96e5aaf6..0395c2cca254 100644 --- a/components/pthread/pthread_cond_var.c +++ b/components/pthread/pthread_cond_var.c @@ -175,12 +175,45 @@ int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mut, const struc return ret; } +// The following pthread_condattr_* function definitions are placed here to enable builds of code +// that references these functions but does not actively use them. + int pthread_condattr_init(pthread_condattr_t *attr) { - ESP_LOGV(TAG, "%s not yet implemented (%p)", __FUNCTION__, attr); + ESP_LOGW(TAG, "%s not yet implemented (%p)", __FUNCTION__, attr); + return ENOSYS; +} + +int pthread_condattr_destroy(pthread_condattr_t *attr) +{ + ESP_LOGW(TAG, "%s not yet implemented (%p)", __FUNCTION__, attr); + return ENOSYS; +} + +int pthread_condattr_getpshared(const pthread_condattr_t *restrict attr, int *restrict pshared) +{ + ESP_LOGW(TAG, "%s not yet implemented (%p)", __FUNCTION__, attr); + return ENOSYS; +} + +int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared) +{ + ESP_LOGW(TAG, "%s not yet implemented (%p)", __FUNCTION__, attr); + return ENOSYS; +} + +int pthread_condattr_getclock(const pthread_condattr_t *restrict attr, clockid_t *restrict clock_id) +{ + ESP_LOGW(TAG, "%s not yet implemented (%p)", __FUNCTION__, attr); return ENOSYS; } +int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) +{ + ESP_LOGW(TAG, "%s: not yet supported!", __func__); + return 0; // moved here from newlib, where it was 0 instead of ENOSYS +} + int pthread_cond_init(pthread_cond_t *cv, const pthread_condattr_t *att) { (void) att; /* Unused argument as of now */ From 44757e94e184fd58a741bdcf92be67779ca1a5c0 Mon Sep 17 00:00:00 2001 From: "sonika.rathi" Date: Tue, 26 Sep 2023 08:46:55 +0200 Subject: [PATCH 076/142] fix(vfs): re-enable vfs tartget tests for esp32-h2 --- components/vfs/test_apps/main/test_vfs_select.c | 7 +------ components/vfs/test_apps/main/test_vfs_uart.c | 8 +------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/components/vfs/test_apps/main/test_vfs_select.c b/components/vfs/test_apps/main/test_vfs_select.c index ceab7004f7ea..7f46a88615ef 100644 --- a/components/vfs/test_apps/main/test_vfs_select.c +++ b/components/vfs/test_apps/main/test_vfs_select.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -141,7 +141,6 @@ static void deinit(int uart_fd, int socket_fd) close(socket_fd); } -#if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6782 TEST_CASE("UART can do select()", "[vfs]") { int uart_fd; @@ -303,8 +302,6 @@ TEST_CASE("UART can do poll() with POLLOUT event", "[vfs]") deinit(uart_fd, socket_fd); } -#endif - TEST_CASE("socket can do select()", "[vfs]") { int uart_fd; @@ -488,7 +485,6 @@ static void inline start_select_task(test_select_task_param_t *param) xTaskCreate(select_task, "select_task", 4*1024, (void *) param, 5, NULL); } -#if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6782 TEST_CASE("concurrent selects work", "[vfs]") { int uart_fd, socket_fd; @@ -590,7 +586,6 @@ TEST_CASE("concurrent selects work", "[vfs]") deinit(uart_fd, socket_fd); close(dummy_socket_fd); } -#endif TEST_CASE("select() works with concurrent mount", "[vfs][fatfs]") { diff --git a/components/vfs/test_apps/main/test_vfs_uart.c b/components/vfs/test_apps/main/test_vfs_uart.c index 37c0dcfd7672..18403fb560c7 100644 --- a/components/vfs/test_apps/main/test_vfs_uart.c +++ b/components/vfs/test_apps/main/test_vfs_uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,7 +23,6 @@ #include "test_utils.h" #include "sdkconfig.h" -#if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6782 static void fwrite_str_loopback(const char* str, size_t size) { esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); @@ -125,7 +124,6 @@ TEST_CASE("CRs are removed from the stdin correctly", "[vfs]") TEST_ASSERT_EQUAL(2, rb); TEST_ASSERT_EQUAL_UINT8_ARRAY("4\n", dst, 2); } -#endif struct read_task_arg_t { char* out_buffer; @@ -139,7 +137,6 @@ struct write_task_arg_t { SemaphoreHandle_t done; }; -#if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6782 static void read_task_fn(void* varg) { struct read_task_arg_t* parg = (struct read_task_arg_t*) varg; @@ -199,7 +196,6 @@ TEST_CASE("can write to UART while another task is reading", "[vfs]") vSemaphoreDelete(read_arg.done); vSemaphoreDelete(write_arg.done); } -#endif TEST_CASE("fcntl supported in UART VFS", "[vfs]") { @@ -212,7 +208,6 @@ TEST_CASE("fcntl supported in UART VFS", "[vfs]") TEST_ASSERT_NOT_EQUAL(-1, res); } -#if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6782 #ifdef CONFIG_VFS_SUPPORT_TERMIOS TEST_CASE("Can use termios for UART", "[vfs]") { @@ -353,4 +348,3 @@ TEST_CASE("Can use termios for UART", "[vfs]") uart_driver_delete(UART_NUM_1); } #endif // CONFIG_VFS_SUPPORT_TERMIOS -#endif From ecd1759a0ba6f6c2005fc9357cf56b21729ed055 Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Tue, 27 Jun 2023 10:06:32 +0200 Subject: [PATCH 077/142] feat(esp_eth): abstraction of SPI driver for SPI Ethernet modules --- components/esp_eth/include/esp_eth_mac.h | 135 ++++++++-- components/esp_eth/src/esp_eth_mac_dm9051.c | 237 ++++++++++-------- .../esp_eth/src/esp_eth_mac_ksz8851snl.c | 221 ++++++++++------ components/esp_eth/src/esp_eth_mac_w5500.c | 161 +++++++++--- 4 files changed, 521 insertions(+), 233 deletions(-) diff --git a/components/esp_eth/include/esp_eth_mac.h b/components/esp_eth/include/esp_eth_mac.h index dfc1af2c73b5..e7a162c12386 100644 --- a/components/esp_eth/include/esp_eth_mac.h +++ b/components/esp_eth/include/esp_eth_mac.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -470,15 +470,113 @@ typedef struct { esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config, const eth_mac_config_t *config); #endif // CONFIG_ETH_USE_ESP32_EMAC +#if CONFIG_ETH_USE_SPI_ETHERNET +/** + * @brief Custom SPI Driver Configuration. + * This structure declares configuration and callback functions to access Ethernet SPI module via + * user's custom SPI driver. + * + */ +typedef struct +{ + /** + * @brief Custom driver specific configuration data used by `init()` function. + * + * @note Type and its content is fully under user's control + * + */ + void *config; + + /** + * @brief Custom driver SPI Initialization + * + * @param[in] spi_config: Custom driver specific configuration + * + * @return + * - spi_ctx: when initialization is successful, a pointer to context structure holding all variables + * needed for subsequent SPI access operations (e.g. SPI bus identification, mutexes, etc.) + * - NULL: driver initialization failed + * + * @note return type and its content is fully under user's control + */ + void *(*init)(const void *spi_config); + + /** + * @brief Custom driver De-initialization + * + * @param[in] spi_ctx: a pointer to driver specific context structure + * + * @return + * - ESP_OK: driver de-initialization was successful + * - ESP_FAIL: driver de-initialization failed + * - any other failure codes are allowed to be used to provide failure isolation + */ + esp_err_t (*deinit)(void *spi_ctx); + + /** + * @brief Custom driver SPI read + * + * @note The read function is responsible to construct command, address and data fields + * of the SPI frame in format expected by particular SPI Ethernet module + * + * @param[in] spi_ctx: a pointer to driver specific context structure + * @param[in] cmd: command + * @param[in] addr: register address + * @param[out] data: read data + * @param[in] data_len: read data length in bytes + * + * @return + * - ESP_OK: read was successful + * - ESP_FAIL: read failed + * - any other failure codes are allowed to be used to provide failure isolation + */ + esp_err_t (*read)(void *spi_ctx, uint32_t cmd, uint32_t addr, void *data, uint32_t data_len); + + /** + * @brief Custom driver SPI write + * + * @note The write function is responsible to construct command, address and data fields + * of the SPI frame in format expected by particular SPI Ethernet module + * + * @param[in] spi_ctx: a pointer to driver specific context structure + * @param[in] cmd: command + * @param[in] addr: register address + * @param[in] data: data to write + * @param[in] data_len: length of data to write in bytes + * + * @return + * - ESP_OK: write was successful + * - ESP_FAIL: write failed + * - any other failure codes are allowed to be used to provide failure isolation + */ + esp_err_t (*write)(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len); +} eth_spi_custom_driver_config_t; + +/** + * @brief Default configuration of the custom SPI driver. + * Internal ESP-IDF SPI Master driver is used by default. + * + */ +#define ETH_DEFAULT_SPI \ + { \ + .config = NULL, \ + .init = NULL, \ + .deinit = NULL, \ + .read = NULL, \ + .write = NULL \ + } +#endif // CONFIG_ETH_USE_SPI_ETHERNET + #if CONFIG_ETH_SPI_ETHERNET_DM9051 /** * @brief DM9051 specific configuration * */ typedef struct { - spi_host_device_t spi_host_id; /*!< SPI peripheral */ - spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration */ - int int_gpio_num; /*!< Interrupt GPIO number */ + int int_gpio_num; /*!< Interrupt GPIO number */ + spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined) */ + spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined) */ + eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */ } eth_dm9051_config_t; /** @@ -487,9 +585,10 @@ typedef struct { */ #define ETH_DM9051_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \ { \ + .int_gpio_num = 4, \ .spi_host_id = spi_host, \ .spi_devcfg = spi_devcfg_p, \ - .int_gpio_num = 4, \ + .custom_spi_driver = ETH_DEFAULT_SPI, \ } /** @@ -511,9 +610,10 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, * */ typedef struct { - spi_host_device_t spi_host_id; /*!< SPI peripheral */ - spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration */ - int int_gpio_num; /*!< Interrupt GPIO number */ + int int_gpio_num; /*!< Interrupt GPIO number */ + spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined)*/ + spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined)*/ + eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */ } eth_w5500_config_t; /** @@ -521,10 +621,11 @@ typedef struct { * */ #define ETH_W5500_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \ - { \ - .spi_host_id = spi_host, \ - .spi_devcfg = spi_devcfg_p, \ - .int_gpio_num = 4, \ + { \ + .int_gpio_num = 4, \ + .spi_host_id = spi_host, \ + .spi_devcfg = spi_devcfg_p, \ + .custom_spi_driver = ETH_DEFAULT_SPI, \ } /** @@ -546,9 +647,10 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con * */ typedef struct { - spi_host_device_t spi_host_id; /*!< SPI peripheral */ - spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration */ - int int_gpio_num; /*!< Interrupt GPIO number */ + int int_gpio_num; /*!< Interrupt GPIO number */ + spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined) */ + spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined) */ + eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */ } eth_ksz8851snl_config_t; /** @@ -557,9 +659,10 @@ typedef struct { */ #define ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \ { \ + .int_gpio_num = 4, \ .spi_host_id = spi_host, \ .spi_devcfg = spi_devcfg_p, \ - .int_gpio_num = 14, \ + .custom_spi_driver = ETH_DEFAULT_SPI, \ } /** diff --git a/components/esp_eth/src/esp_eth_mac_dm9051.c b/components/esp_eth/src/esp_eth_mac_dm9051.c index b0d339cc93d1..f4c4a5049430 100644 --- a/components/esp_eth/src/esp_eth_mac_dm9051.c +++ b/components/esp_eth/src/esp_eth_mac_dm9051.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -47,11 +47,23 @@ typedef struct { uint8_t length_high; } dm9051_rx_header_t; +typedef struct { + spi_device_handle_t hdl; + SemaphoreHandle_t lock; +} eth_spi_info_t; + +typedef struct { + void *ctx; + void *(*init)(const void *spi_config); + esp_err_t (*deinit)(void *spi_ctx); + esp_err_t (*read)(void *spi_ctx, uint32_t cmd, uint32_t addr, void *data, uint32_t data_len); + esp_err_t (*write)(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len); +} eth_spi_custom_driver_t; + typedef struct { esp_eth_mac_t parent; esp_eth_mediator_t *eth; - spi_device_handle_t spi_hdl; - SemaphoreHandle_t spi_lock; + eth_spi_custom_driver_t spi; TaskHandle_t rx_task_hdl; uint32_t sw_reset_timeout_ms; int int_gpio_num; @@ -61,89 +73,137 @@ typedef struct { uint8_t *rx_buffer; } emac_dm9051_t; -static inline bool dm9051_lock(emac_dm9051_t *emac) +static void *dm9051_spi_init(const void *spi_config) +{ + void *ret = NULL; + eth_dm9051_config_t *dm9051_config = (eth_dm9051_config_t *)spi_config; + eth_spi_info_t *spi = calloc(1, sizeof(eth_spi_info_t)); + ESP_GOTO_ON_FALSE(spi, NULL, err, TAG, "no memory for SPI context data"); + + /* SPI device init */ + spi_device_interface_config_t spi_devcfg; + spi_devcfg = *(dm9051_config->spi_devcfg); + if (dm9051_config->spi_devcfg->command_bits == 0 && dm9051_config->spi_devcfg->address_bits == 0) { + /* configure default SPI frame format */ + spi_devcfg.command_bits = 1; + spi_devcfg.address_bits = 7; + } else { + ESP_GOTO_ON_FALSE(dm9051_config->spi_devcfg->command_bits == 1 && dm9051_config->spi_devcfg->address_bits == 7, + NULL, err, TAG, "incorrect SPI frame format (command_bits/address_bits)"); + } + ESP_GOTO_ON_FALSE(spi_bus_add_device(dm9051_config->spi_host_id, &spi_devcfg, &spi->hdl) == ESP_OK, + NULL, err, TAG, "adding device to SPI host #%d failed", dm9051_config->spi_host_id + 1); + + /* create mutex */ + spi->lock = xSemaphoreCreateMutex(); + ESP_GOTO_ON_FALSE(spi->lock, NULL, err, TAG, "create lock failed"); + + ret = spi; + return ret; +err: + if (spi) { + if (spi->lock) { + vSemaphoreDelete(spi->lock); + } + free(spi); + } + return ret; +} + +static esp_err_t dm9051_spi_deinit(void *spi_ctx) { - return xSemaphoreTake(emac->spi_lock, pdMS_TO_TICKS(DM9051_SPI_LOCK_TIMEOUT_MS)) == pdTRUE; + esp_err_t ret = ESP_OK; + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; + + spi_bus_remove_device(spi->hdl); + vSemaphoreDelete(spi->lock); + + free(spi); + return ret; } -static inline bool dm9051_unlock(emac_dm9051_t *emac) +static inline bool dm9051_spi_lock(eth_spi_info_t *spi) { - return xSemaphoreGive(emac->spi_lock) == pdTRUE; + return xSemaphoreTake(spi->lock, pdMS_TO_TICKS(DM9051_SPI_LOCK_TIMEOUT_MS)) == pdTRUE; } -/** - * @brief write value to dm9051 internal register - */ -static esp_err_t dm9051_register_write(emac_dm9051_t *emac, uint8_t reg_addr, uint8_t value) +static inline bool dm9051_spi_unlock(eth_spi_info_t *spi) +{ + return xSemaphoreGive(spi->lock) == pdTRUE; +} + +static esp_err_t dm9051_spi_write(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *value, uint32_t len) { esp_err_t ret = ESP_OK; + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; + spi_transaction_t trans = { - .cmd = DM9051_SPI_WR, - .addr = reg_addr, - .length = 8, - .flags = SPI_TRANS_USE_TXDATA + .cmd = cmd, + .addr = addr, + .length = 8 * len, + .tx_buffer = value }; - trans.tx_data[0] = value; - if (dm9051_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) { + if (dm9051_spi_lock(spi)) { + if (spi_device_polling_transmit(spi->hdl, &trans) != ESP_OK) { ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); ret = ESP_FAIL; } - dm9051_unlock(emac); + dm9051_spi_unlock(spi); } else { ret = ESP_ERR_TIMEOUT; } return ret; } -/** - * @brief read value from dm9051 internal register - */ -static esp_err_t dm9051_register_read(emac_dm9051_t *emac, uint8_t reg_addr, uint8_t *value) +static esp_err_t dm9051_spi_read(void *spi_ctx, uint32_t cmd, uint32_t addr, void *value, uint32_t len) { esp_err_t ret = ESP_OK; + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; + spi_transaction_t trans = { - .cmd = DM9051_SPI_RD, - .addr = reg_addr, - .length = 8, - .flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA + .flags = len <= 4 ? SPI_TRANS_USE_RXDATA : 0, // use direct reads for registers to prevent overwrites by 4-byte boundary writes + .cmd = cmd, + .addr = addr, + .length = 8 * len, + .rx_buffer = value }; - if (dm9051_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) { + if (dm9051_spi_lock(spi)) { + if (spi_device_polling_transmit(spi->hdl, &trans) != ESP_OK) { ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); ret = ESP_FAIL; - } else { - *value = trans.rx_data[0]; } - dm9051_unlock(emac); + dm9051_spi_unlock(spi); } else { ret = ESP_ERR_TIMEOUT; } + if ((trans.flags&SPI_TRANS_USE_RXDATA) && len <= 4) { + memcpy(value, trans.rx_data, len); // copy register values to output + } return ret; } +/** + * @brief write value to dm9051 internal register + */ +static esp_err_t dm9051_register_write(emac_dm9051_t *emac, uint8_t reg_addr, uint8_t value) +{ + return emac->spi.write(emac->spi.ctx, DM9051_SPI_WR, reg_addr, &value, 1); +} + +/** + * @brief read value from dm9051 internal register + */ +static esp_err_t dm9051_register_read(emac_dm9051_t *emac, uint8_t reg_addr, uint8_t *value) +{ + return emac->spi.read(emac->spi.ctx, DM9051_SPI_RD, reg_addr, value, 1); +} + /** * @brief write buffer to dm9051 internal memory */ static esp_err_t dm9051_memory_write(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len) { - esp_err_t ret = ESP_OK; - spi_transaction_t trans = { - .cmd = DM9051_SPI_WR, - .addr = DM9051_MWCMD, - .length = len * 8, - .tx_buffer = buffer - }; - if (dm9051_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) { - ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); - ret = ESP_FAIL; - } - dm9051_unlock(emac); - } else { - ret = ESP_ERR_TIMEOUT; - } - return ret; + return emac->spi.write(emac->spi.ctx, DM9051_SPI_WR, DM9051_MWCMD, buffer, len); } /** @@ -151,23 +211,7 @@ static esp_err_t dm9051_memory_write(emac_dm9051_t *emac, uint8_t *buffer, uint3 */ static esp_err_t dm9051_memory_read(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len) { - esp_err_t ret = ESP_OK; - spi_transaction_t trans = { - .cmd = DM9051_SPI_RD, - .addr = DM9051_MRCMD, - .length = len * 8, - .rx_buffer = buffer - }; - if (dm9051_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) { - ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); - ret = ESP_FAIL; - } - dm9051_unlock(emac); - } else { - ret = ESP_ERR_TIMEOUT; - } - return ret; + return emac->spi.read(emac->spi.ctx, DM9051_SPI_RD, DM9051_MRCMD, buffer, len); } /** @@ -175,23 +219,7 @@ static esp_err_t dm9051_memory_read(emac_dm9051_t *emac, uint8_t *buffer, uint32 */ static esp_err_t dm9051_memory_peek(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len) { - esp_err_t ret = ESP_OK; - spi_transaction_t trans = { - .cmd = DM9051_SPI_RD, - .addr = DM9051_MRCMDX1, - .length = len * 8, - .rx_buffer = buffer - }; - if (dm9051_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) { - ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); - ret = ESP_FAIL; - } - dm9051_unlock(emac); - } else { - ret = ESP_ERR_TIMEOUT; - } - return ret; + return emac->spi.read(emac->spi.ctx, DM9051_SPI_RD, DM9051_MRCMDX1, buffer, len); } /** @@ -840,8 +868,7 @@ static esp_err_t emac_dm9051_del(esp_eth_mac_t *mac) { emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent); vTaskDelete(emac->rx_task_hdl); - spi_bus_remove_device(emac->spi_hdl); - vSemaphoreDelete(emac->spi_lock); + emac->spi.deinit(emac->spi.ctx); heap_caps_free(emac->rx_buffer); free(emac); return ESP_OK; @@ -857,19 +884,6 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, ESP_GOTO_ON_FALSE(emac, NULL, err, TAG, "calloc emac failed"); /* dm9051 receive is driven by interrupt only for now*/ ESP_GOTO_ON_FALSE(dm9051_config->int_gpio_num >= 0, NULL, err, TAG, "error interrupt gpio number"); - /* SPI device init */ - spi_device_interface_config_t spi_devcfg; - memcpy(&spi_devcfg, dm9051_config->spi_devcfg, sizeof(spi_device_interface_config_t)); - if (dm9051_config->spi_devcfg->command_bits == 0 && dm9051_config->spi_devcfg->address_bits == 0) { - /* configure default SPI frame format */ - spi_devcfg.command_bits = 1; - spi_devcfg.address_bits = 7; - } else { - ESP_GOTO_ON_FALSE(dm9051_config->spi_devcfg->command_bits == 1 || dm9051_config->spi_devcfg->address_bits == 7, - NULL, err, TAG, "incorrect SPI frame format (command_bits/address_bits)"); - } - ESP_GOTO_ON_FALSE(spi_bus_add_device(dm9051_config->spi_host_id, &spi_devcfg, &emac->spi_hdl) == ESP_OK, - NULL, err, TAG, "adding device to SPI host #%d failed", dm9051_config->spi_host_id + 1); /* bind methods and attributes */ emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms; emac->int_gpio_num = dm9051_config->int_gpio_num; @@ -891,9 +905,26 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, emac->parent.enable_flow_ctrl = emac_dm9051_enable_flow_ctrl; emac->parent.transmit = emac_dm9051_transmit; emac->parent.receive = emac_dm9051_receive; - /* create mutex */ - emac->spi_lock = xSemaphoreCreateMutex(); - ESP_GOTO_ON_FALSE(emac->spi_lock, NULL, err, TAG, "create lock failed"); + + if (dm9051_config->custom_spi_driver.init != NULL && dm9051_config->custom_spi_driver.deinit != NULL + && dm9051_config->custom_spi_driver.read != NULL && dm9051_config->custom_spi_driver.write != NULL) { + ESP_LOGD(TAG, "Using user's custom SPI Driver"); + emac->spi.init = dm9051_config->custom_spi_driver.init; + emac->spi.deinit = dm9051_config->custom_spi_driver.deinit; + emac->spi.read = dm9051_config->custom_spi_driver.read; + emac->spi.write = dm9051_config->custom_spi_driver.write; + /* Custom SPI driver device init */ + ESP_GOTO_ON_FALSE((emac->spi.ctx = emac->spi.init(dm9051_config->custom_spi_driver.config)) != NULL, NULL, err, TAG, "SPI initialization failed"); + } else { + ESP_LOGD(TAG, "Using default SPI Driver"); + emac->spi.init = dm9051_spi_init; + emac->spi.deinit = dm9051_spi_deinit; + emac->spi.read = dm9051_spi_read; + emac->spi.write = dm9051_spi_write; + /* SPI device init */ + ESP_GOTO_ON_FALSE((emac->spi.ctx = emac->spi.init(dm9051_config)) != NULL, NULL, err, TAG, "SPI initialization failed"); + } + /* create dm9051 task */ BaseType_t core_num = tskNO_AFFINITY; if (mac_config->flags & ETH_MAC_FLAG_PIN_TO_CORE) { @@ -913,8 +944,8 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, if (emac->rx_task_hdl) { vTaskDelete(emac->rx_task_hdl); } - if (emac->spi_lock) { - vSemaphoreDelete(emac->spi_lock); + if (emac->spi.ctx) { + emac->spi.deinit(emac->spi.ctx); } heap_caps_free(emac->rx_buffer); free(emac); diff --git a/components/esp_eth/src/esp_eth_mac_ksz8851snl.c b/components/esp_eth/src/esp_eth_mac_ksz8851snl.c index b6aea4df90ea..10ab357fc4c6 100644 --- a/components/esp_eth/src/esp_eth_mac_ksz8851snl.c +++ b/components/esp_eth/src/esp_eth_mac_ksz8851snl.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: MIT * - * SPDX-FileContributor: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2021-2023 Espressif Systems (Shanghai) CO LTD */ #include @@ -22,10 +22,22 @@ #define KSZ8851_ETH_MAC_RX_BUF_SIZE_AUTO (0) +typedef struct { + spi_device_handle_t hdl; +} eth_spi_info_t; + +typedef struct { + void *ctx; + void *(*init)(const void *spi_config); + esp_err_t (*deinit)(void *spi_ctx); + esp_err_t (*read)(void *spi_ctx, uint32_t cmd,uint32_t addr, void *data, uint32_t data_len); + esp_err_t (*write)(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len); +} eth_spi_custom_driver_t; + typedef struct { esp_eth_mac_t parent; esp_eth_mediator_t *eth; - spi_device_handle_t spi_hdl; + eth_spi_custom_driver_t spi; SemaphoreHandle_t spi_lock; TaskHandle_t rx_task_hdl; uint32_t sw_reset_timeout_ms; @@ -73,6 +85,87 @@ IRAM_ATTR static void ksz8851_isr_handler(void *arg) } } +static void *ksz8851_spi_init(const void *spi_config) +{ + void *ret = NULL; + eth_ksz8851snl_config_t *ksz8851snl_config = (eth_ksz8851snl_config_t *)spi_config; + eth_spi_info_t *spi = calloc(1, sizeof(eth_spi_info_t)); + ESP_GOTO_ON_FALSE(spi, NULL, err, TAG, "no memory for SPI context data"); + + // SPI device init + ESP_GOTO_ON_FALSE(spi_bus_add_device(ksz8851snl_config->spi_host_id, ksz8851snl_config->spi_devcfg, &spi->hdl) == ESP_OK, NULL, + err, TAG, "adding device to SPI host #%d failed", ksz8851snl_config->spi_host_id + 1); + ret = spi; + return ret; +err: + if (spi) { + free(spi); + } + return ret; +} + +static esp_err_t ksz8851_spi_deinit(void *spi_ctx) +{ + esp_err_t ret = ESP_OK; + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; + + spi_bus_remove_device(spi->hdl); + + free(spi); + return ret; +} + +static esp_err_t ksz8851_spi_read(void *spi_ctx, uint32_t cmd, uint32_t addr, void *value, uint32_t len) +{ + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; + + spi_transaction_ext_t trans = { + .base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY | (len <= 4 ? SPI_TRANS_USE_RXDATA : 0), + .base.cmd = cmd, + .base.addr = addr, + .base.length = 8 * len, + .base.rx_buffer = value, + .command_bits = KSZ8851_SPI_COMMAND_BITS + }; + if (cmd >= KSZ8851_SPI_COMMAND_READ_FIFO) { + trans.address_bits = 8 - KSZ8851_SPI_COMMAND_BITS; + } else { + trans.address_bits = 16 - KSZ8851_SPI_COMMAND_BITS; + } + + // No need for mutex here since SPI access is protected at higher layer of this driver + ESP_RETURN_ON_ERROR(spi_device_polling_transmit(spi->hdl, &trans.base), TAG, "spi transmit failed"); + + if ((trans.base.flags & SPI_TRANS_USE_RXDATA) && len <= 4) { + memcpy(value, trans.base.rx_data, len); // copy register values to output + } + return ESP_OK; +} + +static esp_err_t ksz8851_spi_write(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *value, uint32_t len) +{ + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; + + spi_transaction_ext_t trans = { + .base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY, + .base.cmd = cmd, + .base.addr = addr, + .base.length = 8 * len, + .base.tx_buffer = value, + .command_bits = KSZ8851_SPI_COMMAND_BITS + }; + if (cmd >= KSZ8851_SPI_COMMAND_READ_FIFO) { + trans.address_bits = 8 - KSZ8851_SPI_COMMAND_BITS; + } else { + trans.address_bits = 16 - KSZ8851_SPI_COMMAND_BITS; + } + + // No need for mutex here since SPI access is protected at higher layer of this driver + ESP_RETURN_ON_ERROR(spi_device_polling_transmit(spi->hdl, &trans.base), TAG, "spi transmit failed"); + + return ESP_OK; +} + static inline bool ksz8851_mutex_lock(emac_ksz8851snl_t *emac) { return xSemaphoreTakeRecursive(emac->spi_lock, pdMS_TO_TICKS(KSZ8851_SPI_LOCK_TIMEOUT_MS)) == pdTRUE; @@ -83,70 +176,49 @@ static inline bool ksz8851_mutex_unlock(emac_ksz8851snl_t *emac) return xSemaphoreGiveRecursive(emac->spi_lock) == pdTRUE; } -static esp_err_t ksz8851_read_reg(emac_ksz8851snl_t *emac, uint32_t address, uint16_t *value) +static esp_err_t ksz8851_read_reg(emac_ksz8851snl_t *emac, uint32_t reg_addr, uint16_t *value) { esp_err_t ret = ESP_OK; ESP_GOTO_ON_FALSE(value != NULL, ESP_ERR_INVALID_ARG, err, TAG, "out pointer must not be null"); - ESP_GOTO_ON_FALSE((address & ~KSZ8851_VALID_ADDRESS_MASK) == 0U, ESP_ERR_INVALID_ARG, err, TAG, "address is out of bounds"); + ESP_GOTO_ON_FALSE((reg_addr & ~KSZ8851_VALID_ADDRESS_MASK) == 0U, ESP_ERR_INVALID_ARG, err, TAG, "address is out of bounds"); - const unsigned data_size = 16U; // NOTE(v.chistyakov): bits // NOTE(v.chistyakov): select upper or lower word inside a dword - const unsigned byte_mask = 0x3U << (KSZ8851_SPI_BYTE_MASK_SHIFT + (address & 0x2U)); - address <<= KSZ8851_SPI_ADDR_SHIFT; + const unsigned byte_mask = 0x3U << (KSZ8851_SPI_BYTE_MASK_SHIFT + (reg_addr & 0x2U)); + reg_addr <<= KSZ8851_SPI_ADDR_SHIFT; - spi_transaction_ext_t trans = { - .base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY | SPI_TRANS_USE_RXDATA, - .base.cmd = KSZ8851_SPI_COMMAND_READ_REG, - .base.addr = address | byte_mask, - .base.length = data_size, - .command_bits = KSZ8851_SPI_COMMAND_BITS, - .address_bits = 16 - KSZ8851_SPI_COMMAND_BITS, - }; + // Need to protect SPI access at higher layer of the driver since once packet transmit/receive is started (`SDA Start DMA Access` bit is set), + // all registers access are disabled. if (ksz8851_mutex_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans.base) != ESP_OK) { - ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); - ret = ESP_FAIL; - } - ksz8851_mutex_unlock(emac); - memcpy(value, trans.base.rx_data, data_size >> 3U); - ESP_LOGV(TAG, "reading reg 0x%02x == 0x%04x", address, *value); + ret = emac->spi.read(emac->spi.ctx, KSZ8851_SPI_COMMAND_READ_REG, reg_addr | byte_mask, value, 2); } else { ret = ESP_ERR_TIMEOUT; } + ksz8851_mutex_unlock(emac); + ESP_LOGV(TAG, "reading reg 0x%02x == 0x%02x", reg_addr, *value); + err: return ret; } -static esp_err_t ksz8851_write_reg(emac_ksz8851snl_t *emac, uint32_t address, uint16_t value) +static esp_err_t ksz8851_write_reg(emac_ksz8851snl_t *emac, uint32_t reg_addr, uint16_t value) { esp_err_t ret = ESP_OK; - ESP_GOTO_ON_FALSE((address & ~KSZ8851_VALID_ADDRESS_MASK) == 0U, ESP_ERR_INVALID_ARG, err, TAG, "address is out of bounds"); - ESP_LOGV(TAG, "writing reg 0x%02x = 0x%04x", address, value); + ESP_GOTO_ON_FALSE((reg_addr & ~KSZ8851_VALID_ADDRESS_MASK) == 0U, ESP_ERR_INVALID_ARG, err, TAG, "address is out of bounds"); + ESP_LOGV(TAG, "writing reg 0x%02x = 0x%02x", reg_addr, value); - const unsigned data_size = 16U; // NOTE(v.chistyakov): bits // NOTE(v.chistyakov): select upper or lower word inside a dword - const unsigned byte_mask = 0x3U << (KSZ8851_SPI_BYTE_MASK_SHIFT + (address & 0x2U)); - address <<= KSZ8851_SPI_ADDR_SHIFT; + const unsigned byte_mask = 0x3U << (KSZ8851_SPI_BYTE_MASK_SHIFT + (reg_addr & 0x2U)); + reg_addr <<= KSZ8851_SPI_ADDR_SHIFT; - spi_transaction_ext_t trans = { - .base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY | SPI_TRANS_USE_TXDATA, - .base.cmd = KSZ8851_SPI_COMMAND_WRITE_REG, - .base.addr = address | byte_mask, - .base.length = data_size, - .command_bits = KSZ8851_SPI_COMMAND_BITS, - .address_bits = 16 - KSZ8851_SPI_COMMAND_BITS, - }; - - memcpy(trans.base.tx_data, &value, data_size >> 3U); + // Need to protect SPI access at higher layer of the driver since once packet transmit/receive is started (`SDA Start DMA Access` bit is set), + // all registers access are disabled. if (ksz8851_mutex_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans.base) != ESP_OK) { - ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); - ret = ESP_FAIL; - } - ksz8851_mutex_unlock(emac); + ret = emac->spi.write(emac->spi.ctx, KSZ8851_SPI_COMMAND_WRITE_REG, reg_addr | byte_mask, &value, 2); } else { ret = ESP_ERR_TIMEOUT; } + ksz8851_mutex_unlock(emac); + err: return ret; } @@ -313,6 +385,7 @@ static esp_err_t emac_ksz8851snl_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint ESP_LOGV(TAG, "transmitting frame of size %u", length); esp_err_t ret = ESP_OK; emac_ksz8851snl_t *emac = __containerof(mac, emac_ksz8851snl_t, parent); + // Lock SPI since once `SDA Start DMA Access` bit is set, all registers access are disabled. if (!ksz8851_mutex_lock(emac)) { return ESP_ERR_TIMEOUT; } @@ -333,24 +406,12 @@ static esp_err_t emac_ksz8851snl_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint emac->tx_buffer[3] = (length >> 8U) & 0xFFU; memcpy(emac->tx_buffer + 4U, buf, length); - spi_transaction_ext_t trans = { - .base.flags = SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_CMD, - .base.cmd = KSZ8851_SPI_COMMAND_WRITE_FIFO, - .base.length = transmit_length * 8U, // NOTE(v.chistyakov): bits - .base.tx_buffer = emac->tx_buffer, - .command_bits = 2U, - .address_bits = 6U, - }; - uint16_t ier; ESP_GOTO_ON_ERROR(ksz8851_read_reg(emac, KSZ8851_IER, &ier), err, TAG, "IER read failed"); ESP_GOTO_ON_ERROR(ksz8851_write_reg(emac, KSZ8851_IER, 0), err, TAG, "IER write failed"); ESP_GOTO_ON_ERROR(ksz8851_set_bits(emac, KSZ8851_RXQCR, RXQCR_SDA), err, TAG, "RXQCR write failed"); - if (spi_device_polling_transmit(emac->spi_hdl, &trans.base) != ESP_OK) { - ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); - ret = ESP_FAIL; - } + ret = emac->spi.write(emac->spi.ctx, KSZ8851_SPI_COMMAND_WRITE_FIFO, 0, emac->tx_buffer, transmit_length); ESP_GOTO_ON_ERROR(ksz8851_clear_bits(emac, KSZ8851_RXQCR, RXQCR_SDA), err, TAG, "RXQCR write failed"); ESP_GOTO_ON_ERROR(ksz8851_write_reg(emac, KSZ8851_IER, ier), err, TAG, "IER write failed"); @@ -438,23 +499,13 @@ static esp_err_t emac_ksz8851_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t // NOTE(v.chistyakov): 4 dummy + 4 header + alignment const unsigned receive_size = 8U + ((byte_count + 3U) & ~0x3U); - spi_transaction_ext_t trans = { - .base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY, - .base.cmd = KSZ8851_SPI_COMMAND_READ_FIFO, - .base.length = receive_size * 8U, // NOTE(v.chistyakov): bits - .base.rx_buffer = emac->rx_buffer, - .command_bits = 2U, - .address_bits = 6U, - }; + // Lock SPI since once `SDA Start DMA Access` bit is set, all registers access are disabled. if (!ksz8851_mutex_lock(emac)) { return ESP_ERR_TIMEOUT; } ESP_GOTO_ON_ERROR(ksz8851_clear_bits(emac, KSZ8851_RXFDPR, RXFDPR_RXFP_MASK), err, TAG, "RXFDPR write failed"); ESP_GOTO_ON_ERROR(ksz8851_set_bits(emac, KSZ8851_RXQCR, RXQCR_SDA), err, TAG, "RXQCR write failed"); - if (spi_device_polling_transmit(emac->spi_hdl, &trans.base) != ESP_OK) { - ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); - ret = ESP_FAIL; - } + ret = emac->spi.read(emac->spi.ctx, KSZ8851_SPI_COMMAND_READ_FIFO, 0, emac->rx_buffer, receive_size); ESP_GOTO_ON_ERROR(ksz8851_clear_bits(emac, KSZ8851_RXQCR, RXQCR_SDA), err, TAG, "RXQCR write failed"); ksz8851_mutex_unlock(emac); // NOTE(v.chistyakov): skip 4 dummy, 4 header @@ -728,7 +779,7 @@ static esp_err_t emac_ksz8851_del(esp_eth_mac_t *mac) { emac_ksz8851snl_t *emac = __containerof(mac, emac_ksz8851snl_t, parent); vTaskDelete(emac->rx_task_hdl); - spi_bus_remove_device(emac->spi_hdl); + emac->spi.deinit(emac->spi.ctx); vSemaphoreDelete(emac->spi_lock); heap_caps_free(emac->rx_buffer); heap_caps_free(emac->tx_buffer); @@ -748,10 +799,6 @@ esp_eth_mac_t *esp_eth_mac_new_ksz8851snl(const eth_ksz8851snl_config_t *ksz8851 emac = calloc(1, sizeof(emac_ksz8851snl_t)); ESP_GOTO_ON_FALSE(emac, NULL, err, TAG, "no mem for MAC instance"); - /* SPI device init */ - ESP_GOTO_ON_FALSE(spi_bus_add_device(ksz8851snl_config->spi_host_id, ksz8851snl_config->spi_devcfg, &emac->spi_hdl) == ESP_OK, - NULL, err, TAG, "adding device to SPI host #%d failed", ksz8851snl_config->spi_host_id + 1); - emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms; emac->int_gpio_num = ksz8851snl_config->int_gpio_num; emac->parent.set_mediator = emac_ksz8851_set_mediator; @@ -772,8 +819,6 @@ esp_eth_mac_t *esp_eth_mac_new_ksz8851snl(const eth_ksz8851snl_config_t *ksz8851 emac->parent.enable_flow_ctrl = emac_ksz8851_enable_flow_ctrl; emac->parent.set_peer_pause_ability = emac_ksz8851_set_peer_pause_ability; emac->parent.del = emac_ksz8851_del; - emac->spi_lock = xSemaphoreCreateRecursiveMutex(); - ESP_GOTO_ON_FALSE(emac->spi_lock, NULL, err, TAG, "create lock failed"); emac->rx_buffer = NULL; emac->tx_buffer = NULL; emac->rx_buffer = heap_caps_malloc(KSZ8851_QMU_PACKET_LENGTH + KSZ8851_QMU_PACKET_PADDING, MALLOC_CAP_DMA); @@ -781,6 +826,29 @@ esp_eth_mac_t *esp_eth_mac_new_ksz8851snl(const eth_ksz8851snl_config_t *ksz8851 ESP_GOTO_ON_FALSE(emac->rx_buffer, NULL, err, TAG, "RX buffer allocation failed"); ESP_GOTO_ON_FALSE(emac->tx_buffer, NULL, err, TAG, "TX buffer allocation failed"); + /* create mutex */ + emac->spi_lock = xSemaphoreCreateRecursiveMutex(); + ESP_GOTO_ON_FALSE(emac->spi_lock, NULL, err, TAG, "create lock failed"); + + if (ksz8851snl_config->custom_spi_driver.init != NULL && ksz8851snl_config->custom_spi_driver.deinit != NULL + && ksz8851snl_config->custom_spi_driver.read != NULL && ksz8851snl_config->custom_spi_driver.write != NULL) { + ESP_LOGD(TAG, "Using user's custom SPI Driver"); + emac->spi.init = ksz8851snl_config->custom_spi_driver.init; + emac->spi.deinit = ksz8851snl_config->custom_spi_driver.deinit; + emac->spi.read = ksz8851snl_config->custom_spi_driver.read; + emac->spi.write = ksz8851snl_config->custom_spi_driver.write; + /* Custom SPI driver device init */ + ESP_GOTO_ON_FALSE((emac->spi.ctx = emac->spi.init(ksz8851snl_config->custom_spi_driver.config)) != NULL, NULL, err, TAG, "SPI initialization failed"); + } else { + ESP_LOGD(TAG, "Using default SPI Driver"); + emac->spi.init = ksz8851_spi_init; + emac->spi.deinit = ksz8851_spi_deinit; + emac->spi.read = ksz8851_spi_read; + emac->spi.write = ksz8851_spi_write; + /* SPI device init */ + ESP_GOTO_ON_FALSE((emac->spi.ctx = emac->spi.init(ksz8851snl_config)) != NULL, NULL, err, TAG, "SPI initialization failed"); + } + BaseType_t core_num = tskNO_AFFINITY; if (mac_config->flags & ETH_MAC_FLAG_PIN_TO_CORE) { core_num = esp_cpu_get_core_id(); @@ -798,6 +866,9 @@ esp_eth_mac_t *esp_eth_mac_new_ksz8851snl(const eth_ksz8851snl_config_t *ksz8851 if (emac->spi_lock) { vSemaphoreDelete(emac->spi_lock); } + if (emac->spi.ctx) { + emac->spi.deinit(emac->spi.ctx); + } // NOTE(v.chistyakov): safe to call with NULL heap_caps_free(emac->rx_buffer); heap_caps_free(emac->tx_buffer); diff --git a/components/esp_eth/src/esp_eth_mac_w5500.c b/components/esp_eth/src/esp_eth_mac_w5500.c index 7a7708d0ca8b..dbb5a9ba743e 100644 --- a/components/esp_eth/src/esp_eth_mac_w5500.c +++ b/components/esp_eth/src/esp_eth_mac_w5500.c @@ -37,11 +37,23 @@ typedef struct { uint32_t remain; }__attribute__((packed)) emac_w5500_auto_buf_info_t; +typedef struct { + spi_device_handle_t hdl; + SemaphoreHandle_t lock; +} eth_spi_info_t; + +typedef struct { + void *ctx; + void *(*init)(const void *spi_config); + esp_err_t (*deinit)(void *spi_ctx); + esp_err_t (*read)(void *spi_ctx, uint32_t cmd,uint32_t addr, void *data, uint32_t data_len); + esp_err_t (*write)(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len); +} eth_spi_custom_driver_t; + typedef struct { esp_eth_mac_t parent; esp_eth_mediator_t *eth; - spi_device_handle_t spi_hdl; - SemaphoreHandle_t spi_lock; + eth_spi_custom_driver_t spi; TaskHandle_t rx_task_hdl; uint32_t sw_reset_timeout_ms; int int_gpio_num; @@ -50,64 +62,132 @@ typedef struct { uint8_t *rx_buffer; } emac_w5500_t; -static inline bool w5500_lock(emac_w5500_t *emac) +static void *w5500_spi_init(const void *spi_config) { - return xSemaphoreTake(emac->spi_lock, pdMS_TO_TICKS(W5500_SPI_LOCK_TIMEOUT_MS)) == pdTRUE; + void *ret = NULL; + eth_w5500_config_t *w5500_config = (eth_w5500_config_t *)spi_config; + eth_spi_info_t *spi = calloc(1, sizeof(eth_spi_info_t)); + ESP_GOTO_ON_FALSE(spi, NULL, err, TAG, "no memory for SPI context data"); + + /* SPI device init */ + spi_device_interface_config_t spi_devcfg; + spi_devcfg = *(w5500_config->spi_devcfg); + if (w5500_config->spi_devcfg->command_bits == 0 && w5500_config->spi_devcfg->address_bits == 0) { + /* configure default SPI frame format */ + spi_devcfg.command_bits = 16; // Actually it's the address phase in W5500 SPI frame + spi_devcfg.address_bits = 8; // Actually it's the control phase in W5500 SPI frame + } else { + ESP_GOTO_ON_FALSE(w5500_config->spi_devcfg->command_bits == 16 && w5500_config->spi_devcfg->address_bits == 8, + NULL, err, TAG, "incorrect SPI frame format (command_bits/address_bits)"); + } + ESP_GOTO_ON_FALSE(spi_bus_add_device(w5500_config->spi_host_id, &spi_devcfg, &spi->hdl) == ESP_OK, NULL, + err, TAG, "adding device to SPI host #%d failed", w5500_config->spi_host_id + 1); + /* create mutex */ + spi->lock = xSemaphoreCreateMutex(); + ESP_GOTO_ON_FALSE(spi->lock, NULL, err, TAG, "create lock failed"); + + ret = spi; + return ret; +err: + if (spi) { + if (spi->lock) { + vSemaphoreDelete(spi->lock); + } + free(spi); + } + return ret; } -static inline bool w5500_unlock(emac_w5500_t *emac) +static esp_err_t w5500_spi_deinit(void *spi_ctx) { - return xSemaphoreGive(emac->spi_lock) == pdTRUE; + esp_err_t ret = ESP_OK; + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; + + spi_bus_remove_device(spi->hdl); + vSemaphoreDelete(spi->lock); + + free(spi); + return ret; } -static esp_err_t w5500_write(emac_w5500_t *emac, uint32_t address, const void *value, uint32_t len) +static inline bool w5500_spi_lock(eth_spi_info_t *spi) +{ + return xSemaphoreTake(spi->lock, pdMS_TO_TICKS(W5500_SPI_LOCK_TIMEOUT_MS)) == pdTRUE; +} + +static inline bool w5500_spi_unlock(eth_spi_info_t *spi) +{ + return xSemaphoreGive(spi->lock) == pdTRUE; +} + +static esp_err_t w5500_spi_write(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *value, uint32_t len) { esp_err_t ret = ESP_OK; + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; spi_transaction_t trans = { - .cmd = (address >> W5500_ADDR_OFFSET), - .addr = ((address & 0xFFFF) | (W5500_ACCESS_MODE_WRITE << W5500_RWB_OFFSET) | W5500_SPI_OP_MODE_VDM), + .cmd = cmd, + .addr = addr, .length = 8 * len, .tx_buffer = value }; - if (w5500_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) { + if (w5500_spi_lock(spi)) { + if (spi_device_polling_transmit(spi->hdl, &trans) != ESP_OK) { ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); ret = ESP_FAIL; } - w5500_unlock(emac); + w5500_spi_unlock(spi); } else { ret = ESP_ERR_TIMEOUT; } return ret; } -static esp_err_t w5500_read(emac_w5500_t *emac, uint32_t address, void *value, uint32_t len) +static esp_err_t w5500_spi_read(void *spi_ctx, uint32_t cmd, uint32_t addr, void *value, uint32_t len) { esp_err_t ret = ESP_OK; + eth_spi_info_t *spi = (eth_spi_info_t *)spi_ctx; spi_transaction_t trans = { .flags = len <= 4 ? SPI_TRANS_USE_RXDATA : 0, // use direct reads for registers to prevent overwrites by 4-byte boundary writes - .cmd = (address >> W5500_ADDR_OFFSET), - .addr = ((address & 0xFFFF) | (W5500_ACCESS_MODE_READ << W5500_RWB_OFFSET) | W5500_SPI_OP_MODE_VDM), + .cmd = cmd, + .addr = addr, .length = 8 * len, .rx_buffer = value }; - if (w5500_lock(emac)) { - if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) { + if (w5500_spi_lock(spi)) { + if (spi_device_polling_transmit(spi->hdl, &trans) != ESP_OK) { ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__); ret = ESP_FAIL; } - w5500_unlock(emac); + w5500_spi_unlock(spi); } else { ret = ESP_ERR_TIMEOUT; } - if ((trans.flags&SPI_TRANS_USE_RXDATA) && len <= 4) { + if ((trans.flags & SPI_TRANS_USE_RXDATA) && len <= 4) { memcpy(value, trans.rx_data, len); // copy register values to output } return ret; } +static esp_err_t w5500_read(emac_w5500_t *emac, uint32_t address, void *data, uint32_t len) +{ + uint32_t cmd = (address >> W5500_ADDR_OFFSET); // Actually it's the address phase in W5500 SPI frame + uint32_t addr = ((address & 0xFFFF) | (W5500_ACCESS_MODE_READ << W5500_RWB_OFFSET) + | W5500_SPI_OP_MODE_VDM); // Actually it's the command phase in W5500 SPI frame + + return emac->spi.read(emac->spi.ctx, cmd, addr, data, len); +} + +static esp_err_t w5500_write(emac_w5500_t *emac, uint32_t address, const void *data, uint32_t len) +{ + uint32_t cmd = (address >> W5500_ADDR_OFFSET); // Actually it's the address phase in W5500 SPI frame + uint32_t addr = ((address & 0xFFFF) | (W5500_ACCESS_MODE_WRITE << W5500_RWB_OFFSET) + | W5500_SPI_OP_MODE_VDM); // Actually it's the command phase in W5500 SPI frame + + return emac->spi.write(emac->spi.ctx, cmd, addr, data, len); +} + static esp_err_t w5500_send_command(emac_w5500_t *emac, uint8_t command, uint32_t timeout_ms) { esp_err_t ret = ESP_OK; @@ -738,8 +818,7 @@ static esp_err_t emac_w5500_del(esp_eth_mac_t *mac) { emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent); vTaskDelete(emac->rx_task_hdl); - spi_bus_remove_device(emac->spi_hdl); - vSemaphoreDelete(emac->spi_lock); + emac->spi.deinit(emac->spi.ctx); heap_caps_free(emac->rx_buffer); free(emac); return ESP_OK; @@ -754,19 +833,6 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con ESP_GOTO_ON_FALSE(emac, NULL, err, TAG, "no mem for MAC instance"); /* w5500 driver is interrupt driven */ ESP_GOTO_ON_FALSE(w5500_config->int_gpio_num >= 0, NULL, err, TAG, "invalid interrupt gpio number"); - /* SPI device init */ - spi_device_interface_config_t spi_devcfg; - memcpy(&spi_devcfg, w5500_config->spi_devcfg, sizeof(spi_device_interface_config_t)); - if (w5500_config->spi_devcfg->command_bits == 0 && w5500_config->spi_devcfg->address_bits == 0) { - /* configure default SPI frame format */ - spi_devcfg.command_bits = 16; // Actually it's the address phase in W5500 SPI frame - spi_devcfg.address_bits = 8; // Actually it's the control phase in W5500 SPI frame - } else { - ESP_GOTO_ON_FALSE(w5500_config->spi_devcfg->command_bits == 16 || w5500_config->spi_devcfg->address_bits == 8, - NULL, err, TAG, "incorrect SPI frame format (command_bits/address_bits)"); - } - ESP_GOTO_ON_FALSE(spi_bus_add_device(w5500_config->spi_host_id, &spi_devcfg, &emac->spi_hdl) == ESP_OK, - NULL, err, TAG, "adding device to SPI host #%d failed", w5500_config->spi_host_id + 1); /* bind methods and attributes */ emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms; emac->int_gpio_num = w5500_config->int_gpio_num; @@ -788,9 +854,26 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con emac->parent.enable_flow_ctrl = emac_w5500_enable_flow_ctrl; emac->parent.transmit = emac_w5500_transmit; emac->parent.receive = emac_w5500_receive; - /* create mutex */ - emac->spi_lock = xSemaphoreCreateMutex(); - ESP_GOTO_ON_FALSE(emac->spi_lock, NULL, err, TAG, "create lock failed"); + + if (w5500_config->custom_spi_driver.init != NULL && w5500_config->custom_spi_driver.deinit != NULL + && w5500_config->custom_spi_driver.read != NULL && w5500_config->custom_spi_driver.write != NULL) { + ESP_LOGD(TAG, "Using user's custom SPI Driver"); + emac->spi.init = w5500_config->custom_spi_driver.init; + emac->spi.deinit = w5500_config->custom_spi_driver.deinit; + emac->spi.read = w5500_config->custom_spi_driver.read; + emac->spi.write = w5500_config->custom_spi_driver.write; + /* Custom SPI driver device init */ + ESP_GOTO_ON_FALSE((emac->spi.ctx = emac->spi.init(w5500_config->custom_spi_driver.config)) != NULL, NULL, err, TAG, "SPI initialization failed"); + } else { + ESP_LOGD(TAG, "Using default SPI Driver"); + emac->spi.init = w5500_spi_init; + emac->spi.deinit = w5500_spi_deinit; + emac->spi.read = w5500_spi_read; + emac->spi.write = w5500_spi_write; + /* SPI device init */ + ESP_GOTO_ON_FALSE((emac->spi.ctx = emac->spi.init(w5500_config)) != NULL, NULL, err, TAG, "SPI initialization failed"); + } + /* create w5500 task */ BaseType_t core_num = tskNO_AFFINITY; if (mac_config->flags & ETH_MAC_FLAG_PIN_TO_CORE) { @@ -810,8 +893,8 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con if (emac->rx_task_hdl) { vTaskDelete(emac->rx_task_hdl); } - if (emac->spi_lock) { - vSemaphoreDelete(emac->spi_lock); + if (emac->spi.ctx) { + emac->spi.deinit(emac->spi.ctx); } heap_caps_free(emac->rx_buffer); free(emac); From 42b85dffb193aa9a4f1c88ecb6a195f2f8bb5559 Mon Sep 17 00:00:00 2001 From: chenjianhua Date: Fri, 22 Sep 2023 17:22:13 +0800 Subject: [PATCH 078/142] Update bt lib for ESP32-C3 and ESP32-S3(c8aa206) - Fixed extended adv address setting after adv restart - Fixed scan channel index setting for extended scan - Add API to set aux channel index for extended adv --- components/bt/controller/lib_esp32c3_family | 2 +- components/esp_rom/esp32c3/ld/esp32c3.rom.ld | 6 ++++++ components/esp_rom/esp32s3/ld/esp32s3.rom.ld | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/components/bt/controller/lib_esp32c3_family b/components/bt/controller/lib_esp32c3_family index e9ad3d704f10..27af69ccbb02 160000 --- a/components/bt/controller/lib_esp32c3_family +++ b/components/bt/controller/lib_esp32c3_family @@ -1 +1 @@ -Subproject commit e9ad3d704f1034310de8f747d503ea5443df6b67 +Subproject commit 27af69ccbb02f3b820436f47eaa0b1cd544edfbc diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index b2f63271c733..ccb936504f93 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld @@ -966,7 +966,9 @@ r_llc_loc_dl_upd_proc_continue = 0x40000f68; r_llc_loc_encrypt_proc_continue = 0x40000f6c; r_llc_loc_encrypt_proc_err_cb = 0x40000f70; r_llc_loc_feats_exch_proc_continue = 0x40000f74; +/* r_llc_loc_phy_upd_proc_continue = 0x40000f78; +*/ r_llc_loc_phy_upd_proc_err_cb = 0x40000f7c; r_llc_msg_handler_tab_p_get = 0x40000f80; r_llc_pref_param_compute = 0x40000f84; @@ -1145,13 +1147,17 @@ r_lld_process_cca_data = 0x4000120c; r_lld_ral_search = 0x40001210; r_lld_read_clock = 0x40001214; r_lld_res_list_add = 0x40001218; +/* r_lld_res_list_clear = 0x4000121c; +*/ r_lld_res_list_is_empty = 0x40001220; r_lld_res_list_local_rpa_get = 0x40001224; r_lld_res_list_peer_rpa_get = 0x40001228; r_lld_res_list_peer_update = 0x4000122c; r_lld_res_list_priv_mode_update = 0x40001230; +/* r_lld_res_list_rem = 0x40001234; +*/ r_lld_reset_reg = 0x40001238; r_lld_rpa_renew = 0x4000123c; r_lld_rpa_renew_evt_canceled_cbk = 0x40001240; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld index 8abdc1a04605..80a5b1136f2b 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld @@ -1239,7 +1239,9 @@ r_llc_loc_dl_upd_proc_continue = 0x40003e1c; r_llc_loc_encrypt_proc_continue = 0x40003e28; r_llc_loc_encrypt_proc_err_cb = 0x40003e34; r_llc_loc_feats_exch_proc_continue = 0x40003e40; +/* r_llc_loc_phy_upd_proc_continue = 0x40003e4c; +*/ r_llc_loc_phy_upd_proc_err_cb = 0x40003e58; r_llc_msg_handler_tab_p_get = 0x40003e64; r_llc_pref_param_compute = 0x40003e70; @@ -1418,13 +1420,17 @@ r_lld_process_cca_data = 0x40004608; r_lld_ral_search = 0x40004614; r_lld_read_clock = 0x40004620; r_lld_res_list_add = 0x4000462c; +/* r_lld_res_list_clear = 0x40004638; +*/ r_lld_res_list_is_empty = 0x40004644; r_lld_res_list_local_rpa_get = 0x40004650; r_lld_res_list_peer_rpa_get = 0x4000465c; r_lld_res_list_peer_update = 0x40004668; r_lld_res_list_priv_mode_update = 0x40004674; +/* r_lld_res_list_rem = 0x40004680; +*/ r_lld_reset_reg = 0x4000468c; r_lld_rpa_renew = 0x40004698; r_lld_rpa_renew_evt_canceled_cbk = 0x400046a4; From 12fcc66bace8cc5684d117e72325ea826300e0d2 Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Thu, 27 Jul 2023 12:11:01 +0800 Subject: [PATCH 079/142] feat(phy): Add modem type to phy init --- components/esp_phy/include/esp_phy_init.h | 28 +++++----- components/esp_phy/include/esp_private/phy.h | 30 +++++++++- components/esp_phy/lib | 2 +- components/esp_phy/src/phy_common.c | 55 +++++++++++++++++-- components/esp_phy/src/phy_init.c | 26 +++++---- components/esp_phy/src/phy_init_esp32hxx.c | 6 +- .../ieee802154/driver/esp_ieee802154_dev.c | 4 +- components/ieee802154/esp_ieee802154.c | 2 +- 8 files changed, 115 insertions(+), 38 deletions(-) diff --git a/components/esp_phy/include/esp_phy_init.h b/components/esp_phy/include/esp_phy_init.h index 40a77e96e1b1..b9c3c99d2a71 100644 --- a/components/esp_phy/include/esp_phy_init.h +++ b/components/esp_phy/include/esp_phy_init.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,6 +26,15 @@ typedef struct { uint8_t params[128]; /*!< opaque PHY initialization parameters */ } esp_phy_init_data_t; +/** + * @brief PHY enable or disable modem + */ +typedef enum { + PHY_MODEM_WIFI = 1, /*!< PHY modem WIFI */ + PHY_MODEM_BT = 2, /*!< PHY modem BT */ + PHY_MODEM_IEEE802154 = 4, /*!< PHY modem IEEE802154 */ +} esp_phy_modem_t; + /** * @brief Opaque PHY calibration data */ @@ -144,8 +153,9 @@ esp_err_t esp_phy_erase_cal_data_in_nvs(void); * Now PHY and RF enabling job is done automatically when start WiFi or BT. Users should not * call this API in their application. * + * @param modem the modem to call the phy enable. */ -void esp_phy_enable(void); +void esp_phy_enable(esp_phy_modem_t modem); /** * @brief Disable PHY and RF module @@ -154,8 +164,9 @@ void esp_phy_enable(void); * Now PHY and RF disabling job is done automatically when stop WiFi or BT. Users should not * call this API in their application. * + * @param modem the modem to call the phy disable. */ -void esp_phy_disable(void); +void esp_phy_disable(esp_phy_modem_t modem); /** * @brief Enable BTBB module @@ -258,17 +269,6 @@ esp_err_t esp_phy_apply_phy_init_data(uint8_t *init_data); */ char * get_phy_version_str(void); -/** - * @brief Enable phy track pll - * - */ -void phy_track_pll_init(void); - -/** - * @brief Disable phy track pll - * - */ -void phy_track_pll_deinit(void); #ifdef __cplusplus } #endif diff --git a/components/esp_phy/include/esp_private/phy.h b/components/esp_phy/include/esp_private/phy.h index 66c4248ddd37..5e23ded847c8 100644 --- a/components/esp_phy/include/esp_private/phy.h +++ b/components/esp_phy/include/esp_private/phy.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -140,6 +140,34 @@ void phy_eco_version_sel(uint8_t chip_ver); void phy_improve_rx_special(bool enable); #endif +/** + * @brief Enable phy track pll + * + */ +void phy_track_pll_init(void); + +/** + * @brief Disable phy track pll + * + */ +void phy_track_pll_deinit(void); + +/** + * @brief Set the flag recorded which modem has already enabled phy + * + */ +void phy_set_modem_flag(esp_phy_modem_t modem); + +/** + * @brief Clear the flag to record which modem calls phy disenable + */ +void phy_clr_modem_flag(esp_phy_modem_t modem); + +/** + * @brief Get the flag recorded which modem has already enabled phy + * + */ +esp_phy_modem_t phy_get_modem_flag(void); #ifdef __cplusplus } #endif diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 95c370089907..f1d9b9b5cb63 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 95c370089907f74805eac72975b0e85c62e175ed +Subproject commit f1d9b9b5cb63dac81b9027f50f7a46b1d840ce5c diff --git a/components/esp_phy/src/phy_common.c b/components/esp_phy/src/phy_common.c index c4824841c785..d51422779969 100644 --- a/components/esp_phy/src/phy_common.c +++ b/components/esp_phy/src/phy_common.c @@ -5,20 +5,42 @@ */ #include "esp_timer.h" +#include "esp_phy_init.h" #include +static volatile uint16_t s_phy_modem_flag = 0; -extern void bt_track_pll_cap(void); +extern void phy_param_track_tot(bool en_wifi, bool en_ble_154); static esp_timer_handle_t phy_track_pll_timer; -static volatile int64_t s_previous_timestamp; +static volatile int64_t s_wifi_prev_timestamp; +static volatile int64_t s_bt_154_prev_timestamp; #define PHY_TRACK_PLL_PERIOD_IN_US 1000000 +#if CONFIG_IEEE802154_ENABLED || CONFIG_BT_ENABLED || CONFIG_WIFI_ENABLED +bool phy_enabled_modem_contains(esp_phy_modem_t modem) +{ + return (s_phy_modem_flag & modem) != 0; +} +#endif + static void phy_track_pll_timer_callback(void* arg) { + bool wifi_track_pll = false; + bool ble_154_track_pll = false; +#if CONFIG_WIFI_ENABLED + if (phy_enabled_modem_contains(PHY_MODEM_WIFI)) { + wifi_track_pll = true; + s_wifi_prev_timestamp = esp_timer_get_time(); + } +#endif + #if CONFIG_IEEE802154_ENABLED || CONFIG_BT_ENABLED - bt_track_pll_cap(); + if (phy_enabled_modem_contains(PHY_MODEM_BT | PHY_MODEM_IEEE802154)) { + ble_154_track_pll = true; + s_bt_154_prev_timestamp = esp_timer_get_time(); + } #endif - s_previous_timestamp = esp_timer_get_time(); + phy_param_track_tot(wifi_track_pll, ble_154_track_pll); } void phy_track_pll_init(void) @@ -26,8 +48,14 @@ void phy_track_pll_init(void) // Light sleep scenario: enabling and disabling PHY frequently, the timer will not get triggered. // Using a variable to record the previously tracked time when PLL was last called. // If the duration is larger than PHY_TRACK_PLL_PERIOD_IN_US, then track PLL. - int64_t now = esp_timer_get_time(); - if (now - s_previous_timestamp > PHY_TRACK_PLL_PERIOD_IN_US) { + bool need_track_pll = false; +#if CONFIG_WIFI_ENABLED + need_track_pll = need_track_pll || ((esp_timer_get_time() - s_wifi_prev_timestamp) > PHY_TRACK_PLL_PERIOD_IN_US); +#endif +#if CONFIG_IEEE802154_ENABLED || CONFIG_BT_ENABLED + need_track_pll = need_track_pll || ((esp_timer_get_time() - s_bt_154_prev_timestamp) > PHY_TRACK_PLL_PERIOD_IN_US); +#endif + if (need_track_pll) { phy_track_pll_timer_callback((void* )0); } @@ -44,3 +72,18 @@ void phy_track_pll_deinit(void) ESP_ERROR_CHECK(esp_timer_stop(phy_track_pll_timer)); ESP_ERROR_CHECK(esp_timer_delete(phy_track_pll_timer)); } + +void phy_set_modem_flag(esp_phy_modem_t modem) +{ + s_phy_modem_flag |= modem; +} + +void phy_clr_modem_flag(esp_phy_modem_t modem) +{ + s_phy_modem_flag &= ~modem; +} + +esp_phy_modem_t phy_get_modem_flag(void) +{ + return s_phy_modem_flag; +} diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index 505b0bfee178..c8722a921867 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -66,9 +66,6 @@ static DRAM_ATTR struct { #endif // !SOC_PMU_SUPPORTED #endif // SOC_PM_SUPPORT_MODEM_PD || SOC_PM_SUPPORT_WIFI_PD -/* Reference count of enabling PHY */ -static uint8_t s_phy_access_ref = 0; - #if CONFIG_IDF_TARGET_ESP32 /* time stamp updated when the PHY/RF is turned on */ static int64_t s_phy_rf_en_ts = 0; @@ -233,11 +230,10 @@ static inline void phy_digital_regs_load(void) } #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA -void esp_phy_enable(void) +void esp_phy_enable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); - - if (s_phy_access_ref == 0) { + if (phy_get_modem_flag() == 0) { #if CONFIG_IDF_TARGET_ESP32 // Update time stamp s_phy_rf_en_ts = esp_timer_get_time(); @@ -275,18 +271,27 @@ void esp_phy_enable(void) #if CONFIG_IDF_TARGET_ESP32 coex_bt_high_prio(); #endif + +// ESP32 will track pll in the wifi/BT modem interrupt handler. +#if !CONFIG_IDF_TARGET_ESP32 + phy_track_pll_init(); +#endif } - s_phy_access_ref++; + phy_set_modem_flag(modem); _lock_release(&s_phy_access_lock); } -void esp_phy_disable(void) +void esp_phy_disable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); - s_phy_access_ref--; - if (s_phy_access_ref == 0) { + phy_clr_modem_flag(modem); + if (phy_get_modem_flag() == 0) { +// ESP32 will track pll in the wifi/BT modem interrupt handler. +#if !CONFIG_IDF_TARGET_ESP32 + phy_track_pll_deinit(); +#endif #if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA phy_digital_regs_store(); #endif @@ -310,7 +315,6 @@ void esp_phy_disable(void) // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG esp_phy_common_clock_disable(); } - _lock_release(&s_phy_access_lock); } diff --git a/components/esp_phy/src/phy_init_esp32hxx.c b/components/esp_phy/src/phy_init_esp32hxx.c index ea874b28b63d..9387af78af33 100644 --- a/components/esp_phy/src/phy_init_esp32hxx.c +++ b/components/esp_phy/src/phy_init_esp32hxx.c @@ -46,9 +46,10 @@ void IRAM_ATTR phy_exit_critical(uint32_t level) } } -void esp_phy_enable(void) +void esp_phy_enable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); + phy_set_modem_flag(modem); if (s_phy_access_ref == 0) { #if SOC_MODEM_CLOCK_IS_INDEPENDENT modem_clock_module_enable(PERIPH_PHY_MODULE); @@ -68,7 +69,7 @@ void esp_phy_enable(void) _lock_release(&s_phy_access_lock); } -void esp_phy_disable(void) +void esp_phy_disable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); @@ -85,5 +86,6 @@ void esp_phy_disable(void) #endif } + phy_clr_modem_flag(modem); _lock_release(&s_phy_access_lock); } diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index 7760c049ff32..f0db360374d8 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -796,7 +796,7 @@ IRAM_ATTR static void ieee802154_rf_disable(void) { #if CONFIG_FREERTOS_USE_TICKLESS_IDLE if (s_rf_closed == false) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_IEEE802154); s_rf_closed = true; } #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE @@ -806,7 +806,7 @@ IRAM_ATTR static void ieee802154_rf_enable(void) { #if CONFIG_FREERTOS_USE_TICKLESS_IDLE if (s_rf_closed) { - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_IEEE802154); s_rf_closed = false; } #endif //CONFIG_FREERTOS_USE_TICKLESS_IDLE diff --git a/components/ieee802154/esp_ieee802154.c b/components/ieee802154/esp_ieee802154.c index 64aef9ecea16..83900d2b02b2 100644 --- a/components/ieee802154/esp_ieee802154.c +++ b/components/ieee802154/esp_ieee802154.c @@ -22,7 +22,7 @@ esp_err_t esp_ieee802154_enable(void) { ieee802154_enable(); - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_IEEE802154); esp_btbb_enable(); return ieee802154_mac_init(); } From 503299fb329e1e52fcc73084fe35b09eb37646fb Mon Sep 17 00:00:00 2001 From: alanmaxwell Date: Fri, 4 Aug 2023 11:07:57 +0800 Subject: [PATCH 080/142] fix(phy): Fix PHY enabled enter WiFi RX state default --- components/esp_phy/include/esp_phy_init.h | 29 +++++++++++++++++++ components/esp_phy/src/phy_init.c | 7 +++++ components/esp_wifi/esp32/esp_adapter.c | 14 +++++++-- components/esp_wifi/esp32c2/esp_adapter.c | 16 ++++++++-- components/esp_wifi/esp32c3/esp_adapter.c | 16 ++++++++-- components/esp_wifi/esp32c6/esp_adapter.c | 16 ++++++++-- components/esp_wifi/esp32s2/esp_adapter.c | 14 +++++++-- components/esp_wifi/esp32s3/esp_adapter.c | 17 +++++++++-- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32/include/soc/soc_caps.h | 3 ++ .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32c2/include/soc/soc_caps.h | 1 + .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32c3/include/soc/soc_caps.h | 3 ++ .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32c6/include/soc/soc_caps.h | 3 ++ .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32s2/include/soc/soc_caps.h | 3 ++ .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32s3/include/soc/soc_caps.h | 3 ++ 20 files changed, 157 insertions(+), 12 deletions(-) diff --git a/components/esp_phy/include/esp_phy_init.h b/components/esp_phy/include/esp_phy_init.h index b9c3c99d2a71..7f3104a3ab8e 100644 --- a/components/esp_phy/include/esp_phy_init.h +++ b/components/esp_phy/include/esp_phy_init.h @@ -269,6 +269,35 @@ esp_err_t esp_phy_apply_phy_init_data(uint8_t *init_data); */ char * get_phy_version_str(void); +/** + * @brief Enable phy track pll + * + */ +void phy_track_pll_init(void); + +/** + * @brief Disable phy track pll + * + */ +void phy_track_pll_deinit(void); + +/** + * @brief Set PHY init parameters + * @param param is 1 means combo module + */ +void phy_init_param_set(uint8_t param); + +/** + * @brief Wi-Fi RX enable + */ +void phy_wifi_enable_set(uint8_t enable); + +/** + * @brief PHY temperature track + */ +void phy_param_track_tot(bool en_wifi, bool en_bt_154); + + #ifdef __cplusplus } #endif diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index c8722a921867..ae6c02f8da7c 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -773,6 +773,13 @@ void esp_phy_load_cal_and_init(void) #if CONFIG_IDF_TARGET_ESP32S2 phy_eco_version_sel(efuse_hal_chip_revision() / 100); #endif + + // Set PHY whether in combo module + // For comode mode, phy enable will be not in WiFi RX state +#if SOC_PHY_COMBO_MODULE + phy_init_param_set(1); +#endif + esp_phy_calibration_data_t* cal_data = (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1); if (cal_data == NULL) { diff --git a/components/esp_wifi/esp32/esp_adapter.c b/components/esp_wifi/esp32/esp_adapter.c index ba9974ef5cdc..9cadb7a6c0c7 100644 --- a/components/esp_wifi/esp32/esp_adapter.c +++ b/components/esp_wifi/esp32/esp_adapter.c @@ -547,6 +547,16 @@ static void IRAM_ATTR esp_empty_wrapper(void) } +static void esp_phy_enable_wrapper(void) +{ + esp_phy_enable(PHY_MODEM_WIFI); +} + +static void esp_phy_disable_wrapper(void) +{ + esp_phy_disable(PHY_MODEM_WIFI); +} + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -600,8 +610,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._dport_access_stall_other_cpu_end_wrap = s_esp_dport_access_stall_other_cpu_end, ._wifi_apb80m_request = wifi_apb80m_request_wrapper, ._wifi_apb80m_release = wifi_apb80m_release_wrapper, - ._phy_disable = esp_phy_disable, - ._phy_enable = esp_phy_enable, + ._phy_disable = esp_phy_disable_wrapper, + ._phy_enable = esp_phy_enable_wrapper, ._phy_common_clock_enable = esp_phy_common_clock_enable, ._phy_common_clock_disable = esp_phy_common_clock_disable, ._phy_update_country_info = esp_phy_update_country_info, diff --git a/components/esp_wifi/esp32c2/esp_adapter.c b/components/esp_wifi/esp32c2/esp_adapter.c index f2c6a41e1b21..d5e1772f8b0f 100644 --- a/components/esp_wifi/esp32c2/esp_adapter.c +++ b/components/esp_wifi/esp32c2/esp_adapter.c @@ -517,6 +517,18 @@ static void IRAM_ATTR esp_empty_wrapper(void) } +static void esp_phy_enable_wrapper(void) +{ + esp_phy_enable(PHY_MODEM_WIFI); + phy_wifi_enable_set(1); +} + +static void esp_phy_disable_wrapper(void) +{ + phy_wifi_enable_set(0); + esp_phy_disable(PHY_MODEM_WIFI); +} + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -570,8 +582,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper, ._wifi_apb80m_request = wifi_apb80m_request_wrapper, ._wifi_apb80m_release = wifi_apb80m_release_wrapper, - ._phy_disable = esp_phy_disable, - ._phy_enable = esp_phy_enable, + ._phy_disable = esp_phy_disable_wrapper, + ._phy_enable = esp_phy_enable_wrapper, ._phy_update_country_info = esp_phy_update_country_info, ._read_mac = esp_read_mac_wrapper, ._timer_arm = timer_arm_wrapper, diff --git a/components/esp_wifi/esp32c3/esp_adapter.c b/components/esp_wifi/esp32c3/esp_adapter.c index 0e17296bdc11..18fefbcea149 100644 --- a/components/esp_wifi/esp32c3/esp_adapter.c +++ b/components/esp_wifi/esp32c3/esp_adapter.c @@ -534,6 +534,18 @@ static void IRAM_ATTR esp_empty_wrapper(void) } +static void esp_phy_enable_wrapper(void) +{ + esp_phy_enable(PHY_MODEM_WIFI); + phy_wifi_enable_set(1); +} + +static void esp_phy_disable_wrapper(void) +{ + phy_wifi_enable_set(0); + esp_phy_disable(PHY_MODEM_WIFI); +} + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -587,8 +599,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper, ._wifi_apb80m_request = wifi_apb80m_request_wrapper, ._wifi_apb80m_release = wifi_apb80m_release_wrapper, - ._phy_disable = esp_phy_disable, - ._phy_enable = esp_phy_enable, + ._phy_disable = esp_phy_disable_wrapper, + ._phy_enable = esp_phy_enable_wrapper, ._phy_update_country_info = esp_phy_update_country_info, ._read_mac = esp_read_mac_wrapper, ._timer_arm = timer_arm_wrapper, diff --git a/components/esp_wifi/esp32c6/esp_adapter.c b/components/esp_wifi/esp32c6/esp_adapter.c index 8478ace8f78c..8c55440ffa07 100644 --- a/components/esp_wifi/esp32c6/esp_adapter.c +++ b/components/esp_wifi/esp32c6/esp_adapter.c @@ -523,6 +523,18 @@ static void IRAM_ATTR esp_empty_wrapper(void) } +static void esp_phy_enable_wrapper(void) +{ + esp_phy_enable(PHY_MODEM_WIFI); + phy_wifi_enable_set(1); +} + +static void esp_phy_disable_wrapper(void) +{ + phy_wifi_enable_set(0); + esp_phy_disable(PHY_MODEM_WIFI); +} + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -576,8 +588,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper, ._wifi_apb80m_request = wifi_apb80m_request_wrapper, ._wifi_apb80m_release = wifi_apb80m_release_wrapper, - ._phy_disable = esp_phy_disable, - ._phy_enable = esp_phy_enable, + ._phy_disable = esp_phy_disable_wrapper, + ._phy_enable = esp_phy_enable_wrapper, ._phy_update_country_info = esp_phy_update_country_info, ._read_mac = esp_read_mac_wrapper, ._timer_arm = timer_arm_wrapper, diff --git a/components/esp_wifi/esp32s2/esp_adapter.c b/components/esp_wifi/esp32s2/esp_adapter.c index a0966d2c83d4..4eb6db306ee6 100644 --- a/components/esp_wifi/esp32s2/esp_adapter.c +++ b/components/esp_wifi/esp32s2/esp_adapter.c @@ -542,6 +542,16 @@ static void IRAM_ATTR esp_empty_wrapper(void) } +static void esp_phy_enable_wrapper(void) +{ + esp_phy_enable(PHY_MODEM_WIFI); +} + +static void esp_phy_disable_wrapper(void) +{ + esp_phy_disable(PHY_MODEM_WIFI); +} + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -595,8 +605,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper, ._wifi_apb80m_request = wifi_apb80m_request_wrapper, ._wifi_apb80m_release = wifi_apb80m_release_wrapper, - ._phy_disable = esp_phy_disable, - ._phy_enable = esp_phy_enable, + ._phy_disable = esp_phy_disable_wrapper, + ._phy_enable = esp_phy_enable_wrapper, ._phy_common_clock_enable = esp_phy_common_clock_enable, ._phy_common_clock_disable = esp_phy_common_clock_disable, ._phy_update_country_info = esp_phy_update_country_info, diff --git a/components/esp_wifi/esp32s3/esp_adapter.c b/components/esp_wifi/esp32s3/esp_adapter.c index 169af254f242..3fbb3d5ec1e2 100644 --- a/components/esp_wifi/esp32s3/esp_adapter.c +++ b/components/esp_wifi/esp32s3/esp_adapter.c @@ -559,6 +559,19 @@ static void IRAM_ATTR esp_empty_wrapper(void) } + +static void esp_phy_enable_wrapper(void) +{ + esp_phy_enable(PHY_MODEM_WIFI); + phy_wifi_enable_set(1); +} + +static void esp_phy_disable_wrapper(void) +{ + phy_wifi_enable_set(0); + esp_phy_disable(PHY_MODEM_WIFI); +} + wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._env_is_chip = esp_coex_common_env_is_chip_wrapper, @@ -612,8 +625,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper, ._wifi_apb80m_request = wifi_apb80m_request_wrapper, ._wifi_apb80m_release = wifi_apb80m_release_wrapper, - ._phy_disable = esp_phy_disable, - ._phy_enable = esp_phy_enable, + ._phy_disable = esp_phy_disable_wrapper, + ._phy_enable = esp_phy_enable_wrapper, ._phy_update_country_info = esp_phy_update_country_info, ._read_mac = esp_read_mac, ._timer_arm = timer_arm_wrapper, diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 009094e571f1..a3348e60225c 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -894,3 +894,7 @@ config SOC_BLUFI_SUPPORTED config SOC_ULP_HAS_ADC bool default y + +config SOC_PHY_COMBO_MODULE + bool + default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index b29bc07d494d..ab27817b3461 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -435,3 +435,6 @@ /*-------------------------- ULP CAPS ----------------------------------------*/ #define SOC_ULP_HAS_ADC (1) /* ADC can be accessed from ULP */ + +/*------------------------------------- PHY CAPS -------------------------------------*/ +#define SOC_PHY_COMBO_MODULE (1) /*!< Support Wi-Fi, BT and BLE*/ diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 7e543e407a8f..00af044b05e1 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -710,3 +710,7 @@ config SOC_BLUFI_SUPPORTED config SOC_PHY_IMPROVE_RX_11B bool default y + +config SOC_PHY_COMBO_MODULE + bool + default y diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index f4134e46a861..d5490c0834e4 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -330,3 +330,4 @@ /*------------------------------------- PHY CAPS -------------------------------------*/ #define SOC_PHY_IMPROVE_RX_11B (1) +#define SOC_PHY_COMBO_MODULE (1) /*!< Support Wi-Fi and BLE*/ diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 1752b3901133..cbfadd5653c8 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -1026,3 +1026,7 @@ config SOC_BLE_DEVICE_PRIVACY_SUPPORTED config SOC_BLUFI_SUPPORTED bool default y + +config SOC_PHY_COMBO_MODULE + bool + default y diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index cc8d06657cfb..0c418a78c947 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -442,3 +442,6 @@ #define SOC_BLE_50_SUPPORTED (1) /*!< Support Bluetooth 5.0 */ #define SOC_BLE_DEVICE_PRIVACY_SUPPORTED (1) /*!< Support BLE device privacy mode */ #define SOC_BLUFI_SUPPORTED (1) /*!< Support BLUFI */ + +/*------------------------------------- PHY CAPS -------------------------------------*/ +#define SOC_PHY_COMBO_MODULE (1) /*!< Support Wi-Fi and BLE*/ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 3a0650ca9f05..99349bc831d1 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1346,3 +1346,7 @@ config SOC_BLE_MULTI_CONN_OPTIMIZATION config SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND bool default y + +config SOC_PHY_COMBO_MODULE + bool + default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 60ee051c52f7..7458d4a1ed83 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -550,3 +550,6 @@ #define SOC_BLE_MULTI_CONN_OPTIMIZATION (1) /*!< Support multiple connections optimization */ #define SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND (1) + +/*------------------------------------- PHY CAPS -------------------------------------*/ +#define SOC_PHY_COMBO_MODULE (1) /*!< Support Wi-Fi, BLE and 15.4*/ diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index a5a1f00895c0..8643908f4f27 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -1114,3 +1114,7 @@ config SOC_WIFI_NAN_SUPPORT config SOC_ULP_HAS_ADC bool default y + +config SOC_PHY_COMBO_MODULE + bool + default n diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 5944211d3048..6a3dff526e94 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -480,3 +480,6 @@ #define SOC_WIFI_NAN_SUPPORT (1) /*!< Support WIFI Aware (NAN) */ /*-------------------------- ULP CAPS ----------------------------------------*/ #define SOC_ULP_HAS_ADC (1) /* ADC can be accessed from ULP */ + +/*------------------------------------- PHY CAPS -------------------------------------*/ +#define SOC_PHY_COMBO_MODULE (0) /*!< Only support Wi-Fi*/ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index f22258f020da..e926918d1358 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -1322,3 +1322,7 @@ config SOC_BLUFI_SUPPORTED config SOC_ULP_HAS_ADC bool default y + +config SOC_PHY_COMBO_MODULE + bool + default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 7cd6c6c44bff..0d85ac8e2dbd 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -532,3 +532,6 @@ /*-------------------------- ULP CAPS ----------------------------------------*/ #define SOC_ULP_HAS_ADC (1) /* ADC can be accessed from ULP */ + +/*------------------------------------- PHY CAPS -------------------------------------*/ +#define SOC_PHY_COMBO_MODULE (1) /*!< Support Wi-Fi and BLE*/ From 355a4200556c38a0768759b616202efb5d44c900 Mon Sep 17 00:00:00 2001 From: zwl Date: Fri, 1 Sep 2023 18:08:33 +0800 Subject: [PATCH 081/142] fix(phy): Fix ble phy_enable/disable api invoking issue for esp32c2,esp32h2 and esp32c6 --- components/bt/controller/esp32c2/bt.c | 12 ++++++------ components/bt/controller/esp32c6/bt.c | 10 +++++----- components/bt/controller/esp32h2/bt.c | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index 38ce3362508c..25c585bd344a 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.c @@ -240,7 +240,7 @@ struct ext_funcs_t ext_funcs_ro = { ._ecc_gen_key_pair = esp_ecc_gen_key_pair, ._ecc_gen_dh_key = esp_ecc_gen_dh_key, ._esp_reset_rpa_moudle = esp_reset_rpa_moudle, - ._esp_bt_track_pll_cap = bt_track_pll_cap, + ._esp_bt_track_pll_cap = NULL, .magic = EXT_FUNC_MAGIC_VALUE, }; @@ -465,7 +465,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) r_ble_rtc_wake_up_state_clr(); esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); s_ble_active = false; } @@ -474,7 +474,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) if (s_ble_active) { return; } - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); // need to check if need to call pm lock here #ifdef CONFIG_PM_ENABLE esp_pm_lock_acquire(s_pm_lock); @@ -750,7 +750,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) esp_pm_lock_acquire(s_pm_lock); #endif // CONFIG_PM_ENABLE // init phy - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); s_ble_active = true; } // init bb @@ -772,7 +772,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) coex_disable(); #endif if (s_ble_active) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #if CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE @@ -792,7 +792,7 @@ esp_err_t esp_bt_controller_disable(void) } if (s_ble_active) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #if CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index eb3fb8621493..978f8b9db1ea 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -487,7 +487,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) sleep_retention_do_extra_retention(true); #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #ifdef CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE @@ -506,7 +506,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) sleep_retention_do_extra_retention(false); #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG */ #endif //CONFIG_PM_ENABLE - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); s_ble_active = true; } @@ -888,7 +888,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #if CONFIG_PM_ENABLE esp_pm_lock_acquire(s_pm_lock); #endif // CONFIG_PM_ENABLE - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); esp_btbb_enable(); s_ble_active = true; } @@ -909,7 +909,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #endif if (s_ble_active) { esp_btbb_disable(); - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #if CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE @@ -932,7 +932,7 @@ esp_err_t esp_bt_controller_disable(void) #endif if (s_ble_active) { esp_btbb_disable(); - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #if CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index 1336dd222c1a..99a33f6edec6 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -473,7 +473,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) #if CONFIG_FREERTOS_USE_TICKLESS_IDLE r_ble_rtc_wake_up_state_clr(); #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #ifdef CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE @@ -489,7 +489,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) esp_pm_lock_acquire(s_pm_lock); r_ble_rtc_wake_up_state_clr(); #endif //CONFIG_PM_ENABLE - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); s_ble_active = true; } @@ -867,7 +867,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #if CONFIG_PM_ENABLE esp_pm_lock_acquire(s_pm_lock); #endif // CONFIG_PM_ENABLE - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); s_ble_active = true; } esp_btbb_enable(); @@ -888,7 +888,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #endif esp_btbb_disable(); if (s_ble_active) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #if CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE @@ -911,7 +911,7 @@ esp_err_t esp_bt_controller_disable(void) #endif esp_btbb_disable(); if (s_ble_active) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #if CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE From 9e07fa931289f7cddb1faf1c346eb7ca89f9eb5d Mon Sep 17 00:00:00 2001 From: alanmaxwell Date: Mon, 4 Sep 2023 14:08:43 +0800 Subject: [PATCH 082/142] fix(phy): move phy tx power track to IDF --- components/esp_rom/esp32c2/ld/esp32c2.rom.ld | 2 +- components/esp_wifi/lib | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld index 13a24529c6e0..4eee3dd4f9b9 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld @@ -1665,7 +1665,7 @@ lmacProcessTxTimeout = 0x40001d78; lmacProcessCollision = 0x40001d80; lmacProcessTxRtsError = 0x40001d84; lmacProcessCtsTimeout = 0x40001d88; -lmacProcessTxComplete = 0x40001d8c; +/* lmacProcessTxComplete = 0x40001d8c;*/ lmacProcessAckTimeout = 0x40001d90; lmacProcessTxError = 0x40001d94; lmacProcessTxseckiderr = 0x40001d98; diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 7759f9bdf087..174341fbe17d 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 7759f9bdf087eb7fb31e4a612b4d310633fb4dcb +Subproject commit 174341fbe17d6527f25a1c4e936323b6f3e691e2 From e5b96c94b5f5f9ce11b8b6de278f297f0a68ffc4 Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Thu, 7 Sep 2023 15:30:48 +0800 Subject: [PATCH 083/142] fix(CI): fix CI build --- components/bt/controller/esp32/bt.c | 18 +++++++++--------- components/bt/controller/esp32c3/bt.c | 10 +++++----- components/esp_phy/include/esp_phy_init.h | 19 +------------------ components/esp_phy/src/phy_common.c | 4 ++++ components/esp_phy/test/test_phy_rtc.c | 12 +++++++++--- .../test_ieee802154/main/test_app_main.c | 1 - 6 files changed, 28 insertions(+), 36 deletions(-) diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index 64a08dc6e23b..36e82c9bed8f 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -938,7 +938,7 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles) static void btdm_sleep_enter_phase2_wrapper(void) { if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #ifdef CONFIG_PM_ENABLE if (s_pm_lock_acquired) { esp_pm_lock_release(s_pm_lock); @@ -946,7 +946,7 @@ static void btdm_sleep_enter_phase2_wrapper(void) } #endif } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); // pause bluetooth baseband periph_module_disable(PERIPH_BT_BASEBAND_MODULE); } @@ -962,7 +962,7 @@ static void btdm_sleep_exit_phase3_wrapper(void) #endif if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); btdm_check_and_init_bb(); #ifdef CONFIG_PM_ENABLE esp_timer_stop(s_btdm_slp_tmr); @@ -970,7 +970,7 @@ static void btdm_sleep_exit_phase3_wrapper(void) } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { // resume bluetooth baseband periph_module_enable(PERIPH_BT_BASEBAND_MODULE); - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); } } @@ -1642,7 +1642,7 @@ static void bt_shutdown(void) #else bt_controller_shutdown(NULL); #endif - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); return; } @@ -1668,7 +1668,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) esp_pm_lock_acquire(s_pm_lock); #endif - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); #if CONFIG_SW_COEXIST_ENABLE coex_enable(); @@ -1688,7 +1688,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); #ifdef CONFIG_PM_ENABLE if (!s_btdm_allow_light_sleep) { esp_pm_lock_release(s_light_sleep_pm_lock); @@ -1728,7 +1728,7 @@ esp_err_t esp_bt_controller_disable(void) coex_disable(); #endif - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; esp_unregister_shutdown_handler(bt_shutdown); diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index ea8e0c72e41e..ee425017c700 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -747,7 +747,7 @@ static void btdm_sleep_enter_phase2_wrapper(void) { if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1) { if (s_lp_stat.phy_enabled) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); s_lp_stat.phy_enabled = 0; } else { assert(0); @@ -776,7 +776,7 @@ static void btdm_sleep_exit_phase3_wrapper(void) if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1) { if (s_lp_stat.phy_enabled == 0) { - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); s_lp_stat.phy_enabled = 1; } } @@ -1442,7 +1442,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) /* Enable PHY when enabling controller to reduce power dissipation after controller init * Notice the init order: esp_phy_enable() -> bt_bb_v2_init_cmplx() -> coex_pti_v2() */ - esp_phy_enable(); + esp_phy_enable(PHY_MODEM_BT); s_lp_stat.phy_enabled = 1; #if CONFIG_SW_COEXIST_ENABLE @@ -1494,7 +1494,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) coex_disable(); #endif if (s_lp_stat.phy_enabled) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); s_lp_stat.phy_enabled = 0; } return ret; @@ -1516,7 +1516,7 @@ esp_err_t esp_bt_controller_disable(void) coex_disable(); #endif if (s_lp_stat.phy_enabled) { - esp_phy_disable(); + esp_phy_disable(PHY_MODEM_BT); s_lp_stat.phy_enabled = 0; } diff --git a/components/esp_phy/include/esp_phy_init.h b/components/esp_phy/include/esp_phy_init.h index 7f3104a3ab8e..27041b4dae38 100644 --- a/components/esp_phy/include/esp_phy_init.h +++ b/components/esp_phy/include/esp_phy_init.h @@ -269,18 +269,6 @@ esp_err_t esp_phy_apply_phy_init_data(uint8_t *init_data); */ char * get_phy_version_str(void); -/** - * @brief Enable phy track pll - * - */ -void phy_track_pll_init(void); - -/** - * @brief Disable phy track pll - * - */ -void phy_track_pll_deinit(void); - /** * @brief Set PHY init parameters * @param param is 1 means combo module @@ -289,15 +277,10 @@ void phy_init_param_set(uint8_t param); /** * @brief Wi-Fi RX enable + * @param enable True for enable wifi receiving mode as default, false for closing wifi receiving mode as default. */ void phy_wifi_enable_set(uint8_t enable); -/** - * @brief PHY temperature track - */ -void phy_param_track_tot(bool en_wifi, bool en_bt_154); - - #ifdef __cplusplus } #endif diff --git a/components/esp_phy/src/phy_common.c b/components/esp_phy/src/phy_common.c index d51422779969..825c9585d23b 100644 --- a/components/esp_phy/src/phy_common.c +++ b/components/esp_phy/src/phy_common.c @@ -12,8 +12,12 @@ static volatile uint16_t s_phy_modem_flag = 0; extern void phy_param_track_tot(bool en_wifi, bool en_ble_154); static esp_timer_handle_t phy_track_pll_timer; +#if CONFIG_WIFI_ENABLED static volatile int64_t s_wifi_prev_timestamp; +#endif +#if CONFIG_IEEE802154_ENABLED || CONFIG_BT_ENABLED static volatile int64_t s_bt_154_prev_timestamp; +#endif #define PHY_TRACK_PLL_PERIOD_IN_US 1000000 #if CONFIG_IEEE802154_ENABLED || CONFIG_BT_ENABLED || CONFIG_WIFI_ENABLED diff --git a/components/esp_phy/test/test_phy_rtc.c b/components/esp_phy/test/test_phy_rtc.c index 88e34e037ec2..7cfe722722cb 100644 --- a/components/esp_phy/test/test_phy_rtc.c +++ b/components/esp_phy/test/test_phy_rtc.c @@ -46,9 +46,15 @@ static void test_phy_rtc_init(void) ret = nvs_flash_init(); } TEST_ESP_OK(ret); - - esp_phy_enable(); - +#if CONFIG_WIFI_ENABLED + esp_phy_enable(PHY_MODEM_WIFI); +#endif +#if CONFIG_BT_ENABLED + esp_phy_enable(PHY_MODEM_BT); +#endif +#if CONFIG_IEEE802154_ENABLED + esp_phy_enable(PHY_MODEM_IEEE802154); +#endif //must run here, not blocking in above code TEST_ASSERT(1); nvs_flash_deinit(); diff --git a/components/ieee802154/test_apps/test_ieee802154/main/test_app_main.c b/components/ieee802154/test_apps/test_ieee802154/main/test_app_main.c index a19f5e08c056..5436e625bcc8 100644 --- a/components/ieee802154/test_apps/test_ieee802154/main/test_app_main.c +++ b/components/ieee802154/test_apps/test_ieee802154/main/test_app_main.c @@ -31,7 +31,6 @@ static void initialize_nvs(void) void app_main(void) { esp_ieee802154_enable(); - esp_phy_enable(); esp_console_repl_t *repl = NULL; esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); /* Prompt to be printed before each line. From 3cc06e472bc99df17e0b359615070d9043b4a24a Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Fri, 8 Sep 2023 15:44:00 +0800 Subject: [PATCH 084/142] change(ble/controller): disable pll track by default in BLE controller on ESP32-C3 and ESP32-S3 --- components/bt/controller/esp32c3/bt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index ee425017c700..8c2ed98d3313 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -246,6 +246,7 @@ extern bool btdm_deep_sleep_mem_init(void); extern void btdm_deep_sleep_mem_deinit(void); extern void btdm_ble_power_down_dma_copy(bool copy); extern uint8_t btdm_sleep_clock_sync(void); +extern void sdk_config_extend_set_pll_track(bool enable); #if CONFIG_MAC_BB_PD extern void esp_mac_bb_power_down(void); @@ -1464,6 +1465,9 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) } } while (0); + // Disable pll track by default in BLE controller on ESP32-C3 and ESP32-S3 + sdk_config_extend_set_pll_track(false); + if (btdm_controller_enable(mode) != 0) { ret = ESP_ERR_INVALID_STATE; goto error; From 99ac80741834dfd087d23c78d7dcc9e423851fa4 Mon Sep 17 00:00:00 2001 From: alanmaxwell Date: Mon, 11 Sep 2023 11:31:52 +0800 Subject: [PATCH 085/142] fix(wifi): Support ESP32 PHY enabled not enter WiFi RX state by default --- components/esp_wifi/esp32/esp_adapter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/esp_wifi/esp32/esp_adapter.c b/components/esp_wifi/esp32/esp_adapter.c index 9cadb7a6c0c7..62d44c53bcde 100644 --- a/components/esp_wifi/esp32/esp_adapter.c +++ b/components/esp_wifi/esp32/esp_adapter.c @@ -550,10 +550,12 @@ static void IRAM_ATTR esp_empty_wrapper(void) static void esp_phy_enable_wrapper(void) { esp_phy_enable(PHY_MODEM_WIFI); + phy_wifi_enable_set(1); } static void esp_phy_disable_wrapper(void) { + phy_wifi_enable_set(0); esp_phy_disable(PHY_MODEM_WIFI); } From 985b8ca948d941b4bbf2334f258eef679cd6b3d2 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 26 Sep 2023 13:33:25 +0800 Subject: [PATCH 086/142] fix(rmt): fixed unstable transfer during DFS Closes https://github.com/espressif/esp-idf/issues/12292 --- components/driver/rmt/rmt_common.c | 24 ++-- components/driver/rmt/rmt_rx.c | 4 +- components/driver/rmt/rmt_tx.c | 4 +- .../driver/test_apps/rmt/main/test_rmt_tx.c | 115 +++++++++--------- 4 files changed, 69 insertions(+), 78 deletions(-) diff --git a/components/driver/rmt/rmt_common.c b/components/driver/rmt/rmt_common.c index 0cb834d95973..2176f771ea58 100644 --- a/components/driver/rmt/rmt_common.c +++ b/components/driver/rmt/rmt_common.c @@ -160,17 +160,11 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t TAG, "get clock source frequency failed"); #if CONFIG_PM_ENABLE - bool need_pm_lock = true; - // to make the RMT work reliable, the source clock must stay alive and unchanged - // driver will create different pm lock for that purpose, according to different clock source - esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; - -#if SOC_RMT_SUPPORT_RC_FAST - if (clk_src == RMT_CLK_SRC_RC_FAST) { - // RC_FAST won't be turn off in sleep and won't change its frequency during DFS - need_pm_lock = false; - } -#endif // SOC_RMT_SUPPORT_RC_FAST + // if DMA is not used, we're using CPU to push the data to the RMT FIFO + // if the CPU frequency goes down, the transfer+encoding scheme could be unstable because CPU can't fill the data in time + // so, choose ESP_PM_CPU_FREQ_MAX lock for non-dma mode + // otherwise, chose lock type based on the clock source + esp_pm_lock_type_t pm_lock_type = chan->dma_chan ? ESP_PM_NO_LIGHT_SLEEP : ESP_PM_CPU_FREQ_MAX; #if SOC_RMT_SUPPORT_APB if (clk_src == RMT_CLK_SRC_APB) { @@ -179,11 +173,9 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t } #endif // SOC_RMT_SUPPORT_APB - if (need_pm_lock) { - sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, channel_id); // e.g. rmt_0_0 - ret = esp_pm_lock_create(pm_lock_type, 0, chan->pm_lock_name, &chan->pm_lock); - ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed"); - } + sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, channel_id); // e.g. rmt_0_0 + ret = esp_pm_lock_create(pm_lock_type, 0, chan->pm_lock_name, &chan->pm_lock); + ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed"); #endif // CONFIG_PM_ENABLE // no division for group clock source, to achieve highest resolution diff --git a/components/driver/rmt/rmt_rx.c b/components/driver/rmt/rmt_rx.c index eb490d17f86e..4a52515d1386 100644 --- a/components/driver/rmt/rmt_rx.c +++ b/components/driver/rmt/rmt_rx.c @@ -219,8 +219,6 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_ rmt_hal_context_t *hal = &group->hal; int channel_id = rx_channel->base.channel_id; int group_id = group->group_id; - // select the clock source - ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&rx_channel->base, config->clk_src), err, TAG, "set group clock failed"); // reset channel, make sure the RX engine is not working, and events are cleared portENTER_CRITICAL(&group->spinlock); @@ -249,6 +247,8 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_ ESP_GOTO_ON_ERROR(ret, err, TAG, "install rx interrupt failed"); } + // select the clock source + ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&rx_channel->base, config->clk_src), err, TAG, "set group clock failed"); // set channel clock resolution uint32_t real_div = group->resolution_hz / config->resolution_hz; rmt_ll_rx_set_channel_clock_div(hal->regs, channel_id, real_div); diff --git a/components/driver/rmt/rmt_tx.c b/components/driver/rmt/rmt_tx.c index 5c1136e51e58..80c719147475 100644 --- a/components/driver/rmt/rmt_tx.c +++ b/components/driver/rmt/rmt_tx.c @@ -250,8 +250,6 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_ rmt_hal_context_t *hal = &group->hal; int channel_id = tx_channel->base.channel_id; int group_id = group->group_id; - // select the clock source - ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&tx_channel->base, config->clk_src), err, TAG, "set group clock failed"); // reset channel, make sure the TX engine is not working, and events are cleared portENTER_CRITICAL(&group->spinlock); @@ -277,6 +275,8 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_ ESP_GOTO_ON_ERROR(rmt_tx_init_dma_link(tx_channel, config), err, TAG, "install tx DMA failed"); } #endif + // select the clock source + ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&tx_channel->base, config->clk_src), err, TAG, "set group clock failed"); // set channel clock resolution uint32_t real_div = group->resolution_hz / config->resolution_hz; rmt_ll_tx_set_channel_clock_div(hal->regs, channel_id, real_div); diff --git a/components/driver/test_apps/rmt/main/test_rmt_tx.c b/components/driver/test_apps/rmt/main/test_rmt_tx.c index 8da964f1c349..92892c35ebc9 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_tx.c +++ b/components/driver/test_apps/rmt/main/test_rmt_tx.c @@ -140,6 +140,10 @@ TEST_CASE("rmt single transaction", "[rmt]") static void test_rmt_ping_pong_trans(size_t mem_block_symbols, bool with_dma) { + const int test_led_num = 10000; + uint8_t *leds_grb = heap_caps_malloc(3 * test_led_num, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + TEST_ASSERT_NOT_NULL(leds_grb); + rmt_tx_channel_config_t tx_channel_cfg = { .mem_block_symbols = mem_block_symbols, .clk_src = RMT_CLK_SRC_DEFAULT, @@ -159,22 +163,21 @@ static void test_rmt_ping_pong_trans(size_t mem_block_symbols, bool with_dma) TEST_ESP_OK(rmt_enable(tx_channel_multi_leds)); // Mutiple LEDs (ping-pong in the background) - printf("ping pong transmission: light up 100 RGB LEDs\r\n"); + printf("ping pong transmission: light up %d RGB LEDs\r\n", test_led_num); rmt_transmit_config_t transmit_config = { .loop_count = 0, // no loop }; -#define TEST_LED_NUM 100 - uint8_t leds_grb[TEST_LED_NUM * 3] = {}; + // color: Material Design Green-A200 (#69F0AE) - for (int i = 0; i < TEST_LED_NUM * 3; i += 3) { + for (int i = 0; i < test_led_num * 3; i += 3) { leds_grb[i + 0] = 0xF0; leds_grb[i + 1] = 0x69; leds_grb[i + 2] = 0xAE; } printf("start transmission and stop immediately, only a few LEDs are light up\r\n"); - TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, TEST_LED_NUM * 3, &transmit_config)); + TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, test_led_num * 3, &transmit_config)); // this second transmission will stay in the queue and shouldn't be dispatched until we restart the tx channel later - TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, TEST_LED_NUM * 3, &transmit_config)); + TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, test_led_num * 3, &transmit_config)); esp_rom_delay_us(100); TEST_ESP_OK(rmt_disable(tx_channel_multi_leds)); vTaskDelay(pdTICKS_TO_MS(500)); @@ -184,33 +187,33 @@ static void test_rmt_ping_pong_trans(size_t mem_block_symbols, bool with_dma) // adding extra delay here for visualizing vTaskDelay(pdTICKS_TO_MS(500)); // color: Material Design Pink-A200 (#FF4081) - for (int i = 0; i < TEST_LED_NUM * 3; i += 3) { + for (int i = 0; i < test_led_num * 3; i += 3) { leds_grb[i + 0] = 0x40; leds_grb[i + 1] = 0xFF; leds_grb[i + 2] = 0x81; } - TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, TEST_LED_NUM * 3, &transmit_config)); + TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, test_led_num * 3, &transmit_config)); vTaskDelay(pdTICKS_TO_MS(500)); // color: Material Design Orange-900 (#E65100) - for (int i = 0; i < TEST_LED_NUM * 3; i += 3) { + for (int i = 0; i < test_led_num * 3; i += 3) { leds_grb[i + 0] = 0x51; leds_grb[i + 1] = 0xE6; leds_grb[i + 2] = 0x00; } - TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, TEST_LED_NUM * 3, &transmit_config)); - vTaskDelay(pdTICKS_TO_MS(500)); + TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, test_led_num * 3, &transmit_config)); + vTaskDelay(pdTICKS_TO_MS(2000)); printf("disable tx channel\r\n"); TEST_ESP_OK(rmt_disable(tx_channel_multi_leds)); printf("remove tx channel and led strip encoder\r\n"); TEST_ESP_OK(rmt_del_channel(tx_channel_multi_leds)); TEST_ESP_OK(rmt_del_encoder(led_strip_encoder)); -#undef TEST_LED_NUM + free(leds_grb); } TEST_CASE("rmt ping-pong transaction", "[rmt]") { - test_rmt_ping_pong_trans(SOC_RMT_MEM_WORDS_PER_CHANNEL, false); + test_rmt_ping_pong_trans(SOC_RMT_MEM_WORDS_PER_CHANNEL * 2, false); #if SOC_RMT_SUPPORT_DMA test_rmt_ping_pong_trans(1024, true); #endif @@ -257,15 +260,15 @@ static void test_rmt_trans_done_event(size_t mem_block_symbols, bool with_dma) }; printf("transmit dynamic number of LEDs\r\n"); -#define TEST_LED_NUM 40 - uint8_t leds_grb[TEST_LED_NUM * 3] = {}; + const int test_led_num = 40; + uint8_t leds_grb[test_led_num * 3]; // color: Material Design Purple-800 (6A1B9A) - for (int i = 0; i < TEST_LED_NUM * 3; i += 3) { + for (int i = 0; i < test_led_num * 3; i += 3) { leds_grb[i + 0] = 0x1B; leds_grb[i + 1] = 0x6A; leds_grb[i + 2] = 0x9A; } - for (int i = 1; i <= TEST_LED_NUM; i++) { + for (int i = 1; i <= test_led_num; i++) { expected_encoded_size = 2 + i * 24; // 2 = 1 reset symbol + 1 eof symbol, 24 = 8*3(RGB) TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, i * 3, &transmit_config)); // wait for the transmission finished and recycled @@ -277,7 +280,6 @@ static void test_rmt_trans_done_event(size_t mem_block_symbols, bool with_dma) printf("remove tx channel and led strip encoder\r\n"); TEST_ESP_OK(rmt_del_channel(tx_channel_multi_leds)); TEST_ESP_OK(rmt_del_encoder(led_strip_encoder)); -#undef TEST_LED_NUM } TEST_CASE("rmt trans_done event callback", "[rmt]") @@ -330,13 +332,13 @@ static void test_rmt_loop_trans(size_t mem_block_symbols, bool with_dma) rmt_transmit_config_t transmit_config = { .loop_count = 5, }; -#define TEST_LED_NUM 3 - uint8_t leds_grb[TEST_LED_NUM * 3] = {}; - for (int i = 0; i < TEST_LED_NUM * 3; i++) { + const int test_led_num = 3; + uint8_t leds_grb[test_led_num * 3]; + for (int i = 0; i < test_led_num * 3; i++) { leds_grb[i] = 0x10 + i; } - expected_encoded_size = 2 + 24 * TEST_LED_NUM; - TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, TEST_LED_NUM * 3, &transmit_config)); + expected_encoded_size = 2 + 24 * test_led_num; + TEST_ESP_OK(rmt_transmit(tx_channel_multi_leds, led_strip_encoder, leds_grb, test_led_num * 3, &transmit_config)); vTaskDelay(pdTICKS_TO_MS(100)); printf("wait for loop transactions done\r\n"); @@ -346,7 +348,6 @@ static void test_rmt_loop_trans(size_t mem_block_symbols, bool with_dma) printf("remove tx channel and led strip encoder\r\n"); TEST_ESP_OK(rmt_del_channel(tx_channel_multi_leds)); TEST_ESP_OK(rmt_del_encoder(led_strip_encoder)); -#undef TEST_LED_NUM } TEST_CASE("rmt finite loop transaction", "[rmt]") @@ -511,12 +512,11 @@ static bool test_rmt_tx_done_cb_record_time(rmt_channel_handle_t channel, const return false; } -static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, size_t channel1_mem_block_symbols, bool channel0_with_dma, bool channel1_with_dma) -{ -#define TEST_RMT_CHANS 2 -#define TEST_LED_NUM 1 #define TEST_STOP_TIME_NO_SYNCHRO_DELTA 300 #define TEST_STOP_TIME_SYNCHRO_DELTA 60 +static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, size_t channel1_mem_block_symbols, bool channel0_with_dma, bool channel1_with_dma) +{ + const int test_led_num = 1; rmt_tx_channel_config_t tx_channel_cfg = { .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution) @@ -524,11 +524,12 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz .intr_priority = 3 }; printf("install tx channels\r\n"); - rmt_channel_handle_t tx_channels[TEST_RMT_CHANS] = {NULL}; - int gpio_nums[TEST_RMT_CHANS] = {TEST_RMT_GPIO_NUM_A, TEST_RMT_GPIO_NUM_B}; - size_t mem_blk_syms[TEST_RMT_CHANS] = {channel0_mem_block_symbols, channel1_mem_block_symbols}; - bool dma_flags[TEST_RMT_CHANS] = {channel0_with_dma, channel1_with_dma}; - for (int i = 0; i < TEST_RMT_CHANS; i++) { + rmt_channel_handle_t tx_channels[] = {NULL, NULL}; + const int test_rmt_chans = sizeof(tx_channels) / sizeof(tx_channels[0]); + int gpio_nums[] = {TEST_RMT_GPIO_NUM_A, TEST_RMT_GPIO_NUM_B}; + size_t mem_blk_syms[] = {channel0_mem_block_symbols, channel1_mem_block_symbols}; + bool dma_flags[] = {channel0_with_dma, channel1_with_dma}; + for (int i = 0; i < test_rmt_chans; i++) { tx_channel_cfg.gpio_num = gpio_nums[i]; tx_channel_cfg.mem_block_symbols = mem_blk_syms[i]; tx_channel_cfg.flags.with_dma = dma_flags[i]; @@ -536,8 +537,8 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz } printf("install led strip encoders\r\n"); - rmt_encoder_handle_t led_strip_encoders[TEST_RMT_CHANS] = {NULL}; - for (int i = 0; i < TEST_RMT_CHANS; i++) { + rmt_encoder_handle_t led_strip_encoders[test_rmt_chans]; + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(test_rmt_new_led_strip_encoder(&led_strip_encoders[i])); } @@ -545,19 +546,19 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz rmt_tx_event_callbacks_t cbs = { .on_trans_done = test_rmt_tx_done_cb_record_time }; - int64_t record_stop_time[TEST_RMT_CHANS] = {}; - for (int i = 0; i < TEST_RMT_CHANS; i++) { + int64_t record_stop_time[test_rmt_chans]; + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_tx_register_event_callbacks(tx_channels[i], &cbs, &record_stop_time[i])); } printf("enable tx channels\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_enable(tx_channels[i])); } - uint8_t leds_grb[TEST_LED_NUM * 3] = {}; + uint8_t leds_grb[test_led_num * 3]; // color: Material Design Green-A200 (#69F0AE) - for (int i = 0; i < TEST_LED_NUM * 3; i += 3) { + for (int i = 0; i < test_led_num * 3; i += 3) { leds_grb[i + 0] = 0xF0; leds_grb[i + 1] = 0x69; leds_grb[i + 2] = 0xAE; @@ -568,14 +569,14 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz .loop_count = 0, // no loop }; // the channels should work independently, without synchronization - for (int i = 0; i < TEST_RMT_CHANS; i++) { - TEST_ESP_OK(rmt_transmit(tx_channels[i], led_strip_encoders[i], leds_grb, TEST_LED_NUM * 3, &transmit_config)); + for (int i = 0; i < test_rmt_chans; i++) { + TEST_ESP_OK(rmt_transmit(tx_channels[i], led_strip_encoders[i], leds_grb, test_led_num * 3, &transmit_config)); } - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_tx_wait_all_done(tx_channels[i], -1)); } printf("stop time (no sync):\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { printf("\t%lld\r\n", record_stop_time[i]); } // without synchronization, there will be obvious time shift @@ -585,7 +586,7 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz rmt_sync_manager_handle_t synchro = NULL; rmt_sync_manager_config_t synchro_config = { .tx_channel_array = tx_channels, - .array_size = TEST_RMT_CHANS, + .array_size = test_rmt_chans, }; #if SOC_RMT_SUPPORT_TX_SYNCHRO TEST_ESP_OK(rmt_new_sync_manager(&synchro_config, &synchro)); @@ -595,16 +596,16 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz #if SOC_RMT_SUPPORT_TX_SYNCHRO printf("transmit with synchronization\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { - TEST_ESP_OK(rmt_transmit(tx_channels[i], led_strip_encoders[i], leds_grb, TEST_LED_NUM * 3, &transmit_config)); + for (int i = 0; i < test_rmt_chans; i++) { + TEST_ESP_OK(rmt_transmit(tx_channels[i], led_strip_encoders[i], leds_grb, test_led_num * 3, &transmit_config)); // manually introduce the delay, to show the managed channels are indeed in sync vTaskDelay(pdMS_TO_TICKS(10)); } - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_tx_wait_all_done(tx_channels[i], -1)); } printf("stop time (with sync):\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { printf("\t%lld\r\n", record_stop_time[i]); } // because of synchronization, the managed channels will stop at the same time @@ -614,16 +615,16 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz printf("reset sync manager\r\n"); TEST_ESP_OK(rmt_sync_reset(synchro)); printf("transmit with synchronization again\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { - TEST_ESP_OK(rmt_transmit(tx_channels[i], led_strip_encoders[i], leds_grb, TEST_LED_NUM * 3, &transmit_config)); + for (int i = 0; i < test_rmt_chans; i++) { + TEST_ESP_OK(rmt_transmit(tx_channels[i], led_strip_encoders[i], leds_grb, test_led_num * 3, &transmit_config)); // manually introduce the delay, ensure the channels get synchronization vTaskDelay(pdMS_TO_TICKS(10)); } - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_tx_wait_all_done(tx_channels[i], -1)); } printf("stop time (with sync):\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { printf("\t%lld\r\n", record_stop_time[i]); } TEST_ASSERT_INT64_WITHIN(TEST_STOP_TIME_SYNCHRO_DELTA, record_stop_time[0], record_stop_time[1]); @@ -633,18 +634,16 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz #endif // SOC_RMT_SUPPORT_TX_SYNCHRO printf("disable tx channels\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_disable(tx_channels[i])); } printf("delete channels and encoders\r\n"); - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_del_channel(tx_channels[i])); } - for (int i = 0; i < TEST_RMT_CHANS; i++) { + for (int i = 0; i < test_rmt_chans; i++) { TEST_ESP_OK(rmt_del_encoder(led_strip_encoders[i])); } -#undef TEST_LED_NUM -#undef TEST_RMT_CHANS } TEST_CASE("rmt multiple channels transaction", "[rmt]") From 0ee304109133a707f5228d7213d702bfd1f4e5f2 Mon Sep 17 00:00:00 2001 From: Abhik Roy Date: Mon, 25 Sep 2023 19:53:55 +1000 Subject: [PATCH 087/142] feat(lwip): Fixes and Improvements for NAPT and SBOM Support - napt: restore to the initial state in deinit (espressif/esp-lwip@5c4f899f) - napt: Fix ip_portmap_add() to keep only one port mapping (espressif/esp-lwip@d65ad241) - napt: Fix clean compilation (espressif/esp-lwip@7033e26f) - napt: Fix IP forwarding when forward netif enable NAPT (espressif/esp-lwip@bc78df87) - napt/stats: Move some napt counters to stats module (espressif/esp-lwip@b55e64ae) - ip_napt_maint: Fix timestamp overflow handling (2.1.3) (espressif/esp-lwip@a7e0a50c) - napt: Fixes and improvements (2.1.3) (espressif/esp-lwip@fadb9109) - Add sbom descripton file for Software BOM (espressif/esp-lwip@f07097d7) --- components/lwip/lwip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/lwip/lwip b/components/lwip/lwip index 90009cc2b0b4..5c4f899f8e7b 160000 --- a/components/lwip/lwip +++ b/components/lwip/lwip @@ -1 +1 @@ -Subproject commit 90009cc2b0b487ab12688778f5fffc27e9b2b8c3 +Subproject commit 5c4f899f8e7b58ef53522b6f832fc940e29bf0b9 From dc75dc6ec7312d682f06a57fe4675c0b8cef1196 Mon Sep 17 00:00:00 2001 From: Wu Meng Shi Date: Mon, 25 Sep 2023 21:25:59 +0800 Subject: [PATCH 088/142] fix(ble_mesh): avoid executing bt_mesh_host_init() more than once when using nimble --- components/bt/esp_ble_mesh/core/nimble_host/adapter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index 398c1526a9a9..eec69f1080f1 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -87,7 +87,8 @@ int bt_mesh_host_init(void) int rc; if (init == true) { - return -EALREADY; + BT_WARN("Already initialized host for mesh!"); + return 0; } rc = btc_init(); From c4da3d4d32633a4a27e18cf3e09c8e13e4a544b1 Mon Sep 17 00:00:00 2001 From: Mike Krupicka Date: Thu, 14 Sep 2023 09:20:56 -0500 Subject: [PATCH 089/142] Keep export.sh Bourne Shell compatible --- export.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/export.sh b/export.sh index 4ef6ff84d963..e9c83866f567 100644 --- a/export.sh +++ b/export.sh @@ -19,7 +19,7 @@ __verbose() { __script_dir(){ # shellcheck disable=SC2169,SC2169,SC2039,SC3010,SC3028 # unreachable with 'dash' - if [[ "$OSTYPE" == "darwin"* ]]; then + if [ `uname -s` = "Darwin" ]; then # convert possibly relative path to absolute script_dir="$(__realpath "${self_path}")" # resolve any ../ references to make the path shorter From e8992f500cbd5c2c91f01cdb312631ee33058c35 Mon Sep 17 00:00:00 2001 From: "radek.tandler" Date: Fri, 25 Aug 2023 17:15:18 +0200 Subject: [PATCH 090/142] fix(nvs_flash): nvs_set with same key and different data type Function now always rewrites old value under same key regardless existing data type. Users requiring old API behaviour can enable it by kconfig option CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY --- components/nvs_flash/.build-test-rules.yml | 3 + components/nvs_flash/Kconfig | 9 +++ .../host_test/nvs_host_test/main/test_nvs.cpp | 65 +++++++++++++++++++ .../sdkconfig.ci.default_set_key | 1 + .../nvs_host_test/sdkconfig.ci.legacy_set_key | 1 + components/nvs_flash/src/nvs_page.cpp | 2 +- components/nvs_flash/src/nvs_storage.cpp | 30 +++++++-- docs/en/api-reference/storage/nvs_flash.rst | 7 +- .../zh_CN/api-reference/storage/nvs_flash.rst | 7 +- 9 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 components/nvs_flash/.build-test-rules.yml create mode 100644 components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.default_set_key create mode 100644 components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.legacy_set_key diff --git a/components/nvs_flash/.build-test-rules.yml b/components/nvs_flash/.build-test-rules.yml new file mode 100644 index 000000000000..93b76378a994 --- /dev/null +++ b/components/nvs_flash/.build-test-rules.yml @@ -0,0 +1,3 @@ +components/nvs_flash/host_test: + enable: + - if: IDF_TARGET == "linux" diff --git a/components/nvs_flash/Kconfig b/components/nvs_flash/Kconfig index 38d0a311f3cc..3689bfa1bfc1 100644 --- a/components/nvs_flash/Kconfig +++ b/components/nvs_flash/Kconfig @@ -25,4 +25,13 @@ menu "NVS" default n help This option switches error checking type between assertions (y) or return codes (n). + + config NVS_LEGACY_DUP_KEYS_COMPATIBILITY + bool "Enable legacy nvs_set function behavior when same key is reused with different data types" + default n + help + Enabling this will switch the nvs_set family of functions to the legacy mode. When called with same + key and different data type, existing value stored in NVS remains active and as a side effect, the + new value is also stored into NVS, although not accessible using respective nvs_get function. Use only + if your application relies on this NVS API behaviour. endmenu diff --git a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp index f7f9c6f7f5c3..44a9f44a9cfb 100644 --- a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp +++ b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp @@ -3255,6 +3255,71 @@ TEST_CASE("check and read data from partition generated via manufacturing utilit } } +TEST_CASE("nvs multiple write with same key but different types", "[nvs][xxx]") +{ + PartitionEmulationFixture f(0, 10); + + nvs_handle_t handle_1; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + TEMPORARILY_DISABLED(f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) + + for (uint16_t j = NVS_FLASH_SECTOR; j < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; ++j) { + f.erase(j); + } + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); + + nvs_erase_all(handle_1); + + int32_t v32; + int8_t v8; + + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", (int32_t)12345678)); + TEST_ESP_OK(nvs_set_i8(handle_1, "foo", (int8_t)12)); + TEST_ESP_OK(nvs_set_i8(handle_1, "foo", (int8_t)34)); + +#ifdef CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY + // Legacy behavior + // First use of key hooks data type until removed by nvs_erase_key. Alternative re-use of same key with different + // data type is written to the storage as hidden active value. It is returned by nvs_get function after nvs_erase_key is called. + // Mixing more than 2 data types brings undefined behavior. It is not tested here. + + TEST_ESP_ERR(nvs_get_i8(handle_1, "foo", &v8), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v32)); + TEST_ESP_OK(nvs_erase_key(handle_1, "foo")); + + TEST_ESP_OK(nvs_get_i8(handle_1, "foo", &v8)); + TEST_ESP_ERR(nvs_get_i32(handle_1, "foo", &v32), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_OK(nvs_erase_key(handle_1, "foo")); + + TEST_ESP_OK(nvs_get_i8(handle_1, "foo", &v8)); + TEST_ESP_ERR(nvs_get_i32(handle_1, "foo", &v32), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_OK(nvs_erase_key(handle_1, "foo")); + + TEST_ESP_ERR(nvs_erase_key(handle_1, "foo"), ESP_ERR_NVS_NOT_FOUND); +#else + // New behavior + // Latest nvs_set call replaces any existing value. Only one active value under the key exists in storage + + TEST_ESP_OK(nvs_get_i8(handle_1, "foo", &v8)); + TEST_ESP_ERR(nvs_get_i32(handle_1, "foo", &v32), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_OK(nvs_erase_key(handle_1, "foo")); + + TEST_ESP_ERR(nvs_get_i8(handle_1, "foo", &v8), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_ERR(nvs_get_i32(handle_1, "foo", &v32), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_ERR(nvs_erase_key(handle_1, "foo"), ESP_ERR_NVS_NOT_FOUND); +#endif + + nvs_close(handle_1); + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); +} + + /* Add new tests above */ /* This test has to be the final one */ diff --git a/components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.default_set_key b/components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.default_set_key new file mode 100644 index 000000000000..4ebf01d0f9ba --- /dev/null +++ b/components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.default_set_key @@ -0,0 +1 @@ +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY=n diff --git a/components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.legacy_set_key b/components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.legacy_set_key new file mode 100644 index 000000000000..226772f237a2 --- /dev/null +++ b/components/nvs_flash/host_test/nvs_host_test/sdkconfig.ci.legacy_set_key @@ -0,0 +1 @@ +CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY=y diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 36cde3db250b..b69bcfbdaf3f 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -878,7 +878,7 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si end = ENTRY_COUNT; } - if (nsIndex != NS_ANY && datatype != ItemType::ANY && key != NULL) { + if (nsIndex != NS_ANY && key != NULL) { size_t cachedIndex = mHashList.find(start, Item(nsIndex, datatype, 0, key, chunkIdx)); if (cachedIndex < ENTRY_COUNT) { start = cachedIndex; diff --git a/components/nvs_flash/src/nvs_storage.cpp b/components/nvs_flash/src/nvs_storage.cpp index 48c8a20fc08e..5153ae7447df 100644 --- a/components/nvs_flash/src/nvs_storage.cpp +++ b/components/nvs_flash/src/nvs_storage.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -285,13 +285,27 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key } Page* findPage = nullptr; + bool matchedTypePageFound = false; Item item; esp_err_t err; if (datatype == ItemType::BLOB) { err = findItem(nsIndex, ItemType::BLOB_IDX, key, findPage, item); + if(err == ESP_OK && findPage != nullptr) { + matchedTypePageFound = true; + } } else { +#ifdef CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY err = findItem(nsIndex, datatype, key, findPage, item); + if(err == ESP_OK && findPage != nullptr) { + matchedTypePageFound = true; + } +#else + err = findItem(nsIndex, ItemType::ANY, key, findPage, item); + if(err == ESP_OK && findPage != nullptr && datatype == item.datatype) { + matchedTypePageFound = true; + } +#endif } if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { @@ -301,7 +315,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key if (datatype == ItemType::BLOB) { VerOffset prevStart, nextStart; prevStart = nextStart = VerOffset::VER_0_OFFSET; - if (findPage) { + if (matchedTypePageFound) { // Do a sanity check that the item in question is actually being modified. // If it isn't, it is cheaper to purposefully not write out new data. // since it may invoke an erasure of flash. @@ -335,7 +349,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key return err; } - if (findPage) { + if (matchedTypePageFound) { /* Erase the blob with earlier version*/ err = eraseMultiPageBlob(nsIndex, key, prevStart); @@ -358,7 +372,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key // Do a sanity check that the item in question is actually being modified. // If it isn't, it is cheaper to purposefully not write out new data. // since it may invoke an erasure of flash. - if (findPage != nullptr && + if (matchedTypePageFound && findPage->cmpItem(nsIndex, datatype, key, data, dataSize) == ESP_OK) { return ESP_OK; } @@ -392,12 +406,20 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key if (findPage) { if (findPage->state() == Page::PageState::UNINITIALIZED || findPage->state() == Page::PageState::INVALID) { +#ifdef CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY err = findItem(nsIndex, datatype, key, findPage, item); +#else + err = findItem(nsIndex, ItemType::ANY, key, findPage, item); +#endif if (err != ESP_OK) { return err; } } +#ifdef CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY err = findPage->eraseItem(nsIndex, datatype, key); +#else + err = findPage->eraseItem(nsIndex, ItemType::ANY, key); +#endif if (err == ESP_ERR_FLASH_OP_FAIL) { return ESP_ERR_NVS_REMOVE_FAILED; } diff --git a/docs/en/api-reference/storage/nvs_flash.rst b/docs/en/api-reference/storage/nvs_flash.rst index 8e0bec9db67e..c25316c9025b 100644 --- a/docs/en/api-reference/storage/nvs_flash.rst +++ b/docs/en/api-reference/storage/nvs_flash.rst @@ -35,12 +35,9 @@ NVS operates on key-value pairs. Keys are ASCII strings; the maximum key length Additional types, such as ``float`` and ``double`` might be added later. -Keys are required to be unique. Assigning a new value to an existing key works as follows: +Keys are required to be unique. Assigning a new value to an existing key replaces the old value and data type with the value and data type specified by a write operation. -- If the new value is of the same type as the old one, value is updated. -- If the new value has a different data type, an error is returned. - -Data type check is also performed when reading a value. An error is returned if the data type of the read operation does not match the data type of the value. +A data type check is performed when reading a value. An error is returned if the data type expected by read operation does not match the data type of entry found for the key provided. Namespaces diff --git a/docs/zh_CN/api-reference/storage/nvs_flash.rst b/docs/zh_CN/api-reference/storage/nvs_flash.rst index fd494f1bee57..8f05d495d5bf 100644 --- a/docs/zh_CN/api-reference/storage/nvs_flash.rst +++ b/docs/zh_CN/api-reference/storage/nvs_flash.rst @@ -35,12 +35,9 @@ NVS 的操作对象为键值对,其中键是 ASCII 字符串,当前支持的 后续可能会增加对 ``float`` 和 ``double`` 等其他类型数据的支持。 -键必须唯一。为现有的键写入新的值可能产生如下结果: +键必须唯一。为现有的键写入新值时,会将旧的值及数据类型更新为写入操作指定的值和数据类型。 -- 如果新旧值数据类型相同,则更新值; -- 如果新旧值数据类型不同,则返回错误。 - -读取值时也会执行数据类型检查。如果读取操作的数据类型与该值的数据类型不匹配,则返回错误。 +读取值时会执行数据类型检查。如果读取操作预期的数据类型与对应键的数据类型不匹配,则返回错误。 命名空间 From 4f659b70e1eef889500a158ab24d2887d2a58118 Mon Sep 17 00:00:00 2001 From: "radek.tandler" Date: Tue, 5 Sep 2023 15:05:23 +0200 Subject: [PATCH 091/142] fix(nvs_flash): fixed failing nvs_page test --- components/nvs_flash/Kconfig | 9 +++--- .../nvs_page_test/main/nvs_page_test.cpp | 28 +++++++------------ components/nvs_flash/src/nvs_storage.cpp | 4 +-- tools/ci/check_copyright_ignore.txt | 1 - 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/components/nvs_flash/Kconfig b/components/nvs_flash/Kconfig index 3689bfa1bfc1..a432384ad9e4 100644 --- a/components/nvs_flash/Kconfig +++ b/components/nvs_flash/Kconfig @@ -30,8 +30,9 @@ menu "NVS" bool "Enable legacy nvs_set function behavior when same key is reused with different data types" default n help - Enabling this will switch the nvs_set family of functions to the legacy mode. When called with same - key and different data type, existing value stored in NVS remains active and as a side effect, the - new value is also stored into NVS, although not accessible using respective nvs_get function. Use only - if your application relies on this NVS API behaviour. + Enabling this option will switch the nvs_set() family of functions to the legacy mode: + when called repeatedly with the same key but different data type, the existing value + in the NVS remains active and the new value is just stored, actually not accessible through + corresponding nvs_get() call for the key given. Use this option only when your application + relies on such NVS API behaviour. endmenu diff --git a/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp b/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp index e5ca9ed08939..81704974ff3f 100644 --- a/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp +++ b/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp @@ -1,16 +1,8 @@ -// 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 - -// 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-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "unity.h" #include "test_fixtures.hpp" @@ -863,7 +855,7 @@ void test_Page_calcEntries__uninit() NVSPageFixture fix; TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); - nvs_stats_t nvsStats = {0, 0, 0, 0}; + nvs_stats_t nvsStats = {0, 0, 0, 0, 0}; TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats)); TEST_ASSERT_EQUAL(0, nvsStats.used_entries); @@ -888,7 +880,7 @@ void test_Page_calcEntries__corrupt() TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state()); - nvs_stats_t nvsStats = {0, 0, 0, 0}; + nvs_stats_t nvsStats = {0, 0, 0, 0, 0}; TEST_ASSERT_EQUAL(ESP_OK, page.calcEntries(nvsStats)); TEST_ASSERT_EQUAL(0, nvsStats.used_entries); @@ -901,7 +893,7 @@ void test_Page_calcEntries__active_wo_blob() { NVSValidPageFixture fix; - nvs_stats_t nvsStats = {0, 0, 0, 0}; + nvs_stats_t nvsStats = {0, 0, 0, 0, 0}; TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats)); TEST_ASSERT_EQUAL(2, nvsStats.used_entries); @@ -914,7 +906,7 @@ void test_Page_calcEntries__active_with_blob() { NVSValidBlobPageFixture fix; - nvs_stats_t nvsStats = {0, 0, 0, 0}; + nvs_stats_t nvsStats = {0, 0, 0, 0, 0}; TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats)); TEST_ASSERT_EQUAL(4, nvsStats.used_entries); @@ -927,7 +919,7 @@ void test_Page_calcEntries__invalid() { Page page; - nvs_stats_t nvsStats = {0, 0, 0, 0}; + nvs_stats_t nvsStats = {0, 0, 0, 0, 0}; TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); diff --git a/components/nvs_flash/src/nvs_storage.cpp b/components/nvs_flash/src/nvs_storage.cpp index 5153ae7447df..bac19955807a 100644 --- a/components/nvs_flash/src/nvs_storage.cpp +++ b/components/nvs_flash/src/nvs_storage.cpp @@ -291,7 +291,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key esp_err_t err; if (datatype == ItemType::BLOB) { err = findItem(nsIndex, ItemType::BLOB_IDX, key, findPage, item); - if(err == ESP_OK && findPage != nullptr) { + if(err == ESP_OK) { matchedTypePageFound = true; } } else { @@ -302,7 +302,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key } #else err = findItem(nsIndex, ItemType::ANY, key, findPage, item); - if(err == ESP_OK && findPage != nullptr && datatype == item.datatype) { + if(err == ESP_OK && datatype == item.datatype) { matchedTypePageFound = true; } #endif diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 9405c40e159d..9b35cbda3247 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -587,7 +587,6 @@ components/mbedtls/port/include/sha512_alt.h components/mbedtls/port/sha/dma/include/esp_sha_dma_priv.h components/mbedtls/port/sha/dma/sha.c components/mbedtls/port/sha/parallel_engine/sha.c -components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp components/nvs_flash/include/nvs_handle.hpp components/nvs_flash/src/nvs_cxx_api.cpp components/nvs_flash/src/nvs_encrypted_partition.hpp From 65b01e5ab1b51c5ae82466fc9d02f5aa496730f3 Mon Sep 17 00:00:00 2001 From: Cai Xin Ying Date: Wed, 27 Sep 2023 06:35:53 +0800 Subject: [PATCH 092/142] docs: provide CN translation for api-reference/peripherals/sdspi_share.rst --- .../api-reference/peripherals/sdspi_share.rst | 62 ++++++++------- .../api-reference/peripherals/sdspi_share.rst | 77 ++++++++++++++++++- 2 files changed, 110 insertions(+), 29 deletions(-) diff --git a/docs/en/api-reference/peripherals/sdspi_share.rst b/docs/en/api-reference/peripherals/sdspi_share.rst index 5b8d0c2d40d9..ea178813b734 100644 --- a/docs/en/api-reference/peripherals/sdspi_share.rst +++ b/docs/en/api-reference/peripherals/sdspi_share.rst @@ -1,70 +1,76 @@ -Sharing the SPI bus among SD card and other SPI devices -======================================================= +Sharing the SPI Bus Among SD Cards and Other SPI Devices +======================================================== -The SD card has a SPI mode, which allows it to be communicated to as a SPI device. But there are some restrictions that we need to pay attention to. +:link_to_translation:`zh_CN:[中文]` -Pin loading of other devices +The SD card has an SPI mode, enabling it to function as an SPI device, but there are some restrictions that we need to pay attention to. + +Pin Loading of Other Devices ---------------------------- When adding more devices onto the same bus, the overall pin loading increases. The loading consists of AC loading (pin capacitor) and DC loading (pull-ups). -AC loading +AC Loading ^^^^^^^^^^ -SD cards, which are designed for high-speed communications, have small pin capacitors (AC loading) to work until 50MHz. However, the other attached devices will increase the pin's AC loading. +SD cards, designed for high-speed communications, have small pin capacitors (AC loading) to work until 50 MHz. However, the other attached devices will increase the pin's AC loading. -Heavy AC loading of a pin may prevent the pin from being toggled quickly. By using an oscilloscope, you will see the edges of the pin become smoother and not ideal any more (the gradient of the edge is smaller). The setup timing requirements of an SD card may be violoated when the card is connected to such bus. Even worse, the clock from the host may not be recognized by the SD card and other SPI devices on the same bus. +Heavy AC loading of a pin may prevent the pin from being toggled quickly. By using an oscilloscope, you will see the edges of the pin become smoother, i.e., the gradient of the edge is smaller. The setup timing requirements of an SD card may be violated when the card is connected to a bus with a high AC load. Even worse, high AC loads may cause the SD card and other SPI devices to fail to properly resolve clock signals from the host, affecting communication stability. -This issue may be more obvious if other attached devices are not designed to work at the same frequency as the SD card, because they may have larger pin capacitors. +This issue may be more obvious if other attached devices are not designed to work at the same frequency as the SD card, because they may have larger pin capacitors. The larger the pin capacity, the greater the pin response time, the smaller the max frequency the SD bus can work. To see if your pin AC loading is too heavy, you can try the following tests: -(Terminology: **launch edge**: at which clock edge the data start to toggle; **latch edge**: at which clock edge the data is supposed to be sampled by the receiver, for SD cad, it's the rising edge.) +Terminology: + + - **launch edge**: at which clock edge the data starts to toggle; + - **latch edge**: at which clock edge the data is supposed to be sampled by the receiver. For SD card, it is the rising edge. + +1. Use an oscilloscope to see the clock and compare the data line to the clock. -1. Use an oscilloscope to see the clock and compare the data line to the clock. - - If you see the clock is not fast enough (for example, the rising/falling edge is longer than 1/4 of the clock cycle), it means the clock is skewed too much. + - If you see the clock is not fast enough, e.g., the rising/falling edge is longer than 1/4 of the clock cycle, it means the clock is skewed too much. - If you see the data line unstable before the latch edge of the clock, it means the load of the data line is too large. - You may also observed the corresponding phenomenon (data delayed largely from launching edge of clock) with logic analyzers. But it's not as obvious as with an oscilloscope. + You may also observe the corresponding phenomenon that data delayed largely from the launching edge of the clock with logic analyzers. But it is not as obvious as with an oscilloscope. -2. Try to use slower clock frequency. +2. Try to use a slower clock frequency. - If the lower frequency can work while the higher frequency can't, it's an indication of the AC loading on the pins is too large. + If the lower frequency can work while the higher frequency cannot, it is an indication that the AC loading on the pins is too large. -If the AC loading of the pins is too large, you can either use other faster devices (with lower pin load) or slow down the clock speed. +If the AC loading of the pins is too large, you can either use other faster devices with lower pin load or slow down the clock speed. -DC loading +DC Loading ^^^^^^^^^^ -The pull-ups required by SD cards are usually around 10 kOhm to 50 kOhm, which may be too strong for some other SPI devices. +The pull-ups required by SD cards are usually around 10 kOhm to 50 kOhm, which may be too strong for some other SPI devices. -Check the specification of your device about its DC output current , it should be larger than 700uA, otherwise the device output may not be read correctly. +Check the specification of your device about its DC output current, it should be larger than 700 μA, otherwise, the device output may not be read correctly. -Initialization sequence +Initialization Sequence ----------------------- .. note:: - If you see any problem in the following steps, please make sure the timing is correct first. You can try to slow down the clock speed (SDMMC_FREQ_PROBING = 400 KHz for SD card) to avoid the influence of pin AC loading (see above section). + If you see any problem in the following steps, please make sure the timing is correct first. You can try to slow down the clock speed, such as setting ``SDMMC_FREQ_PROBING`` to 400 kHz for SD card, to avoid the influence of pin AC loading, as discussed in the previous section. -When using ab SD card with other SPI devices on the same SPI bus, due to the restrictions of the SD card startup flow, the following initialization sequence should be followed: (See also :example:`storage/sd_card`) +When using an SD card with other SPI devices on the same SPI bus, due to the restrictions of the SD card startup flow, the following initialization sequence should be followed. Refer to :example:`storage/sd_card` for further details. -1. Initialize the SPI bus properly by `spi_bus_initialize`. +1. Initialize the SPI bus properly by :cpp:func:`spi_bus_initialize`. -2. Tie the CS lines of all other devices than the SD card to high. This is to avoid conflicts to the SD card in the following step. +2. Tie the CS lines of all other devices than the SD card to idle state (by default it's high). This is to avoid conflicts with the SD card in the following step. You can do this by either: - 1. Attach devices to the SPI bus by calling `spi_bus_add_device`. This function will initialize the GPIO that is used as CS to the idle level: high. + 1. Attach devices to the SPI bus by calling :cpp:func:`spi_bus_add_device`. This function will by default initialize the GPIO that is used as CS to the idle level: high. 2. Initialize GPIO on the CS pin that needs to be tied up before actually adding a new device. - 3. Rely on the internal/external pull-up (not recommended) to pull-up all the CS pins when the GPIOs of ESP are not initialized yet. You need to check carefull the pull-up is strong enough and there are no other pull-downs that will influence the pull-up (For example, internal pull-down should be enabled). + 3. Rely on the internal/external pull-up (**not recommended**) to pull up all the CS pins when the GPIOs of ESP are not initialized yet. You need to check carefully the pull-up is strong enough and there are no other pull-downs that will influence the pull-up. For example, internal pull-down should be enabled. -3. Mount the card to the filesystem by calling `esp_vfs_fat_sdspi_mount`. +3. Mount the card to the filesystem by calling :cpp:func:`esp_vfs_fat_sdspi_mount`. - This step will put the SD card into the SPI mode, which SHOULD be done before all other SPI communications on the same bus. Otherwise the card will stay in the SD mode, in which mode it may randomly respond to any SPI communications on the bus, even when its CS line is not addressed. + This step will put the SD card into the SPI mode, which **should** be done before all other SPI communications on the same bus. Otherwise, the card will stay in the SD mode, in which mode it may randomly respond to any SPI communications on the bus, even when its CS line is not addressed. - If you want to test this behavior, please also note that, once the card is put into SPI mode, it will not return to SD mode before next power cycle, i.e. powered down and powered up again. + If you want to test this behavior, please also note that, once the card is put into SPI mode, it will not return to SD mode before the next power cycle, i.e., powered down and powered up again. 4. Now you can talk to other SPI devices freely! diff --git a/docs/zh_CN/api-reference/peripherals/sdspi_share.rst b/docs/zh_CN/api-reference/peripherals/sdspi_share.rst index 9c7b44f91399..6dd2fc433a96 100644 --- a/docs/zh_CN/api-reference/peripherals/sdspi_share.rst +++ b/docs/zh_CN/api-reference/peripherals/sdspi_share.rst @@ -1 +1,76 @@ -.. include:: ../../../en/api-reference/peripherals/sdspi_share.rst +SD 卡与其他 SPI 设备共享 SPI 总线 +======================================================== + +:link_to_translation:`en:[English]` + +SD 卡支持 SPI 模式,使其能够作为 SPI 设备通信,但使用时需注意其限制。 + +其他设备的管脚负载 +---------------------------- + +向同一总线添加设备会增加管脚的整体负载,包括交流负载(管脚电容)和直流负载(上拉电阻)。 + +交流负载 +^^^^^^^^^^ + +在通信速率不超过 50 MHz 的情况下,专为高速通信设计的 SD 卡采用小型管脚电容(交流负载小)。但在同一 SPI 总线上连接其他设备后,会增加管脚的交流负载。 + +管脚交流负载过高时,可能无法实现电平快速切换。通过使用示波器,你可以观察到管脚状态变化的边缘变得更加平滑,即边缘变化率更低。当 SD 卡连接到交流负载较高的总线时,可能无法满足 SD 卡建立时间 (setup) 的时序要求。高交流负载甚至可能导致 SD 卡和其他 SPI 设备无法正确解析主机发出的时钟信号,影响通信稳定性。 + +如果连接的其他设备的工作频率与 SD 卡工作频率不同,上述问题可能会更加明显。这是因为其他设备可能具有更大的管脚电容。管脚容量越大,响应时间越长,SD 总线可工作的最高频率越低。 + +你可以尝试以下测试,判断管脚交流负载是否过重: + +术语 + + - **启动边沿 (launch edge)**:数据开始切换的时钟边沿; + - **锁存边沿 (latch edge)**:数据接收侧应进行数据采样的时钟边沿,对 SD 卡来说是上升沿。 + +1. 使用示波器观察时钟,并比较数据线与时钟。 + + - 如果时钟不够快,例如上升/下降沿长于时钟周期的 1/4,表明时钟偏斜过大。 + - 如果在时钟锁存边沿之前数据线不稳定,表明数据线负载过大。 + + 借助逻辑分析仪,也可以观察到数据与时钟启动沿相比,延迟较大。但比起用示波器,用逻辑分析仪观察到的现象可能不太明显。 + +2. 尝试使用较低的时钟频率。 + + 如果设备可以在较低的通信频率下正常工作,而在较高的通信频率下出现问题,说明管脚交流负载过大。 + +如果管脚的交流负载过大,你可以选择使用其他管脚负载更低但通信速度更快的设备,或降低时钟速度。 + +直流负载 +^^^^^^^^^^ + +SD 卡所需的上拉电阻通常在 10 kΩ 至 50 kΩ 之间,注意对某些 SPI 设备来说,这可能是过强的上拉电阻。 + +请查阅设备的规格说明书,了解其直流输出电流。此直流输出电流应大于 700 μA,否则可能无法正确读取设备输出。 + +初始化顺序 +----------------------- + +.. note:: + + 如果在执行以下步骤时遇到任何问题,请首先确保时序正确。如前文所述,你可以尝试降低时钟速度,例如将 SD 卡的 ``SDMMC_FREQ_PROBING`` 设置为 400 kHz,排除管脚交流负载的影响。 + +在同一 SPI 总线上与其他 SPI 设备一起使用 SD 卡时,由于 SD 卡启动流程的限制,应遵循以下初始化顺序。有关详情,请参阅 :example:`storage/sd_card`。 + +1. 通过 :cpp:func:`spi_bus_initialize` 正确初始化总线。 + +2. 将除 SD 卡外所有设备的 CS 线置为空闲状态(默认为高电平),避免在后续步骤中与 SD 卡发生冲突。 + + 这可以通过以下任一方式实现: + + 1. 调用 :cpp:func:`spi_bus_add_device` 将设备连接到 SPI 总线,该函数将初始化用作 CS 的 GPIO 管脚到空闲电平:默认为高电平。 + + 2. 在添加新设备前,初始化需要拉高的 CS 管脚 GPIO。 + + 3. 在 ESP 的 GPIO 未初始化前,依靠内部/外部上拉电阻拉高所有 CS 管脚(**不推荐**)。请确保上拉电阻拥有足够强度,且没有其他下拉电阻影响拉高。例如,应启用内部下拉电阻。 + +3. 调用 :cpp:func:`esp_vfs_fat_sdspi_mount` 将卡挂载到文件系统。 + + 此步骤将使 SD 卡进入 SPI 模式,**应该** 在同一总线上的所有其他 SPI 通信前完成。否则,SD 卡会保持在 SD 模式,即使在未选中其 CS 线的情况下,SD 卡也可能随机响应总线上的任何 SPI 通信。 + + 如果你想测试这种行为,请注意,一旦 SD 卡置于 SPI 模式,在下次上电前,也就是断电后重新上电之前,SD 卡将不会返回 SD 模式 + +4. 此时,即可与其他 SPI 设备自由通信。 From 43741ec80306f8395ee292d45f6610984aa16f0f Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 8 Sep 2022 08:48:30 +0200 Subject: [PATCH 093/142] ci: add astyle pre-commit check --- .pre-commit-config.yaml | 6 + docs/en/contribute/style-guide.rst | 12 +- tools/ci/astyle-rules.yml | 184 +++++++++++++++++++++++++ tools/ci/exclude_check_tools_files.txt | 2 +- tools/format-minimal.sh | 9 -- tools/format.sh | 17 ++- 6 files changed, 213 insertions(+), 17 deletions(-) create mode 100644 tools/ci/astyle-rules.yml delete mode 100644 tools/format-minimal.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 94f4af81dae1..92b6ac7e0719 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -202,3 +202,9 @@ repos: hooks: - id: conventional-precommit-linter stages: [commit-msg] + - repo: https://github.com/espressif/astyle_py.git + rev: v1.0.2 + hooks: + - id: astyle_py + # If you are modifying astyle version, update tools/format.sh as well + args: ['--astyle-version=3.4.7', '--rules=tools/ci/astyle_rules.yml'] diff --git a/docs/en/contribute/style-guide.rst b/docs/en/contribute/style-guide.rst index d3a5d84bf3b7..4e48b5d88ddf 100644 --- a/docs/en/contribute/style-guide.rst +++ b/docs/en/contribute/style-guide.rst @@ -193,15 +193,19 @@ For updating a single commit, it is possible to run ``dos2unix FILENAME`` and th Formatting Your Code ^^^^^^^^^^^^^^^^^^^^ -You can use ``astyle`` program to format your code according to the above recommendations. +ESP-IDF uses Astyle to format source code. The configuration is stored in :project_file:`tools/ci/astyle-rules.yml` file. -If you are writing a file from scratch, or doing a complete rewrite, feel free to re-format the entire file. If you are changing a small portion of file, do not re-format the code you did not change. This will help others when they review your changes. +Initially, all components are excluded from formatting checks. You can enable formatting checks for the component by removing it from ``components_not_formatted_temporary`` list. Then run: -To re-format a file, run: +.. code-block:: bash + + pre-commit run --files astyle_py + +Alternatively, you can run ``astyle_py`` manually. You can install it with ``pip install astyle_py==VERSION``. Make sure you have the same version installed as the one specified in :project_file:`.pre-commit-config.yaml` file. With ``astyle_py`` installed, run: .. code-block:: bash - tools/format.sh components/my_component/file.c + astyle_py --rules=$IDF_PATH/tools/ci/astyle-rules.yml Type Definitions diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml new file mode 100644 index 000000000000..7fa747ff2245 --- /dev/null +++ b/tools/ci/astyle-rules.yml @@ -0,0 +1,184 @@ +DEFAULT: + # These formatting options will be used by default. + # If you are modifying this, update tools/format.sh as well! + options: "--style=otbs --attach-namespaces --attach-classes --indent=spaces=4 --convert-tabs --align-reference=name --keep-one-line-statements --pad-header --pad-oper --unpad-paren --max-continuation-indent=120" + +submodules: + # Don't format the code in submodules + check: false + include: + - "/components/bootloader/subproject/components/micro-ecc/micro-ecc/" + - "/components/bt/controller/lib_esp32/" + - "/components/bt/controller/lib_esp32c2/esp32c2-bt-lib/" + - "/components/bt/controller/lib_esp32c3_family/" + - "/components/bt/controller/lib_esp32c6/esp32c6-bt-lib/" + - "/components/bt/controller/lib_esp32h2/esp32h2-bt-lib/" + - "/components/bt/host/nimble/nimble/" + - "/components/cmock/CMock/" + - "/components/esp_coex/lib/" + - "/components/esp_phy/lib/" + - "/components/esp_wifi/lib/" + - "/components/heap/tlsf/" + - "/components/ieee802154/lib/" + - "/components/json/cJSON/" + - "/components/lwip/lwip/" + - "/components/mbedtls/mbedtls/" + - "/components/mqtt/esp-mqtt/" + - "/components/openthread/lib/" + - "/components/openthread/openthread/" + - "/components/protobuf-c/protobuf-c/" + - "/components/spiffs/spiffs/" + - "/components/unity/unity/" + +components_not_formatted_temporary: + # Formatting in these components isn't checked yet. + # For each of these components, decide whether it should be formatted or not. + # 1. If yes, format the code and remove the component from the exclude list. + # Add special rules for upstream source files, if necessary. + # To reformat the files: + # - Remove the directory from this exclude list + # - Run 'git add .astyle-rules.yml' + # - Run 'pre-commit run --all-files' + # 2. If no, move it to 'components_not_formatted_permanent' section below. + check: false + include: + - "/components/app_trace/" + - "/components/app_update/" + - "/components/bootloader_support/" + - "/components/bootloader/" + - "/components/bt/" + - "/components/cmock/" + - "/components/console/" + - "/components/cxx/" + - "/components/driver/" + - "/components/efuse/" + - "/components/esp_adc/" + - "/components/esp_app_format/" + - "/components/esp_bootloader_format/" + - "/components/esp_coex/" + - "/components/esp_common/" + - "/components/esp_eth/" + - "/components/esp_event/" + - "/components/esp_gdbstub/" + - "/components/esp_hid/" + - "/components/esp_http_client/" + - "/components/esp_http_server/" + - "/components/esp_https_ota/" + - "/components/esp_https_server/" + - "/components/esp_hw_support/" + - "/components/esp_lcd/" + - "/components/esp_local_ctrl/" + - "/components/esp_mm/" + - "/components/esp_netif/" + - "/components/esp_partition/" + - "/components/esp_phy/" + - "/components/esp_pm/" + - "/components/esp_psram/" + - "/components/esp_ringbuf/" + - "/components/esp_rom/" + - "/components/esp_system/" + - "/components/esp_timer/" + - "/components/esp_wifi/" + - "/components/esp-tls/" + - "/components/espcoredump/" + - "/components/esptool_py/" + - "/components/fatfs/" + - "/components/freertos/" + - "/components/hal/" + - "/components/heap/" + - "/components/idf_test/" + - "/components/ieee802154/" + - "/components/json/" + - "/components/linux/" + - "/components/log/" + - "/components/lwip/" + - "/components/mbedtls/" + - "/components/mqtt/" + - "/components/newlib/" + - "/components/nvs_flash/" + - "/components/nvs_sec_provider/" + - "/components/openthread/" + - "/components/partition_table/" + - "/components/perfmon/" + - "/components/protobuf-c/" + - "/components/protocomm/" + - "/components/pthread/" + - "/components/riscv/" + - "/components/sdmmc/" + - "/components/soc/" + - "/components/spi_flash/" + - "/components/spiffs/" + - "/components/tcp_transport/" + - "/components/touch_element/" + - "/components/ulp/" + - "/components/unity/" + - "/components/usb/" + - "/components/vfs/" + - "/components/wear_levelling/" + - "/components/wifi_provisioning/" + - "/components/wpa_supplicant/" + - "/components/xtensa/" + - "/examples/bluetooth/" + - "/examples/build_system/" + - "/examples/common_components/" + - "/examples/custom_bootloader/" + - "/examples/cxx/" + - "/examples/ethernet/" + - "/examples/get-started/" + - "/examples/mesh/" + - "/examples/network/" + - "/examples/openthread/" + - "/examples/peripherals/" + - "/examples/phy/" + - "/examples/protocols/" + - "/examples/provisioning/" + - "/examples/security/" + - "/examples/storage/" + - "/examples/system/" + - "/examples/wifi/" + - "/examples/zigbee/" + - "/tools/esp_app_trace/test/" + - "/tools/mocks/" + - "/tools/test_apps/" + - "/tools/unit-test-app/" + +components_not_formatted_permanent: + # Files which are not supposed to be formatted. + # Typically, these are: + # - Upstream source code we don't want to modify + # - Generated files + check: false + include: + # Xtensa header files (generated) + - "/components/xtensa/esp32/" + - "/components/xtensa/esp32s2/" + - "/components/xtensa/esp32s3/" + - "/components/xtensa/include/xtensa/" + # FAT FS (upstream source code) + - "/components/fatfs/src/" + # Nginx HTTP parser (upstream source code) + - "/components/http_parser/" + # Argtable (upstream source code) + - "/components/console/argtable3/" + # Linenoise (upstream source code) + - "/components/console/linenoise/" + # Catch (upstream source code) + - "/tools/catch/catch.hpp" + # FreeRTOS kernel files (upstream source code). + - "/components/freertos/FreeRTOS-Kernel/" + - "/components/freertos/FreeRTOS-Kernel-SMP/" + - "/components/freertos/FreeRTOS-Kernel-V10.5.1/" + # Segger SystemView (upstream source code). + # Could also try to find suitable astyle options, instead. + - "/components/app_trace/sys_view/Config/" + - "/components/app_trace/sys_view/Sample/" + - "/components/app_trace/sys_view/SEGGER/" + # SoC header files (generated) + - "/components/soc/*/include/soc/" + +docs: + # Docs directory contains some .inc files, which are not C include files + # and should not be formatted + check: false + include: + - "/docs/**/*.inc" diff --git a/tools/ci/exclude_check_tools_files.txt b/tools/ci/exclude_check_tools_files.txt index eac77c20c938..e9521402f27f 100644 --- a/tools/ci/exclude_check_tools_files.txt +++ b/tools/ci/exclude_check_tools_files.txt @@ -11,6 +11,7 @@ tools/check_term.py tools/check_python_dependencies.py tools/python_version_checker.py tools/generate_debug_prefix_map.py +tools/ci/astyle-rules.yml tools/ci/checkout_project_ref.py tools/ci/ci_fetch_submodule.py tools/ci/ci_get_mr_info.py @@ -31,7 +32,6 @@ tools/ci/push_to_github.sh tools/ci/python_packages/wifi_tools.py tools/ci/utils.sh tools/eclipse-code-style.xml -tools/format-minimal.sh tools/format.sh tools/mocks/**/* tools/set-submodules-to-github.sh diff --git a/tools/format-minimal.sh b/tools/format-minimal.sh deleted file mode 100644 index 36787d22ddcc..000000000000 --- a/tools/format-minimal.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -# Runs astyle with parameters which should be checked in a pre-commit hook -astyle \ - --style=otbs \ - --indent=spaces=4 \ - --convert-tabs \ - --keep-one-line-statements \ - --pad-header \ - "$@" diff --git a/tools/format.sh b/tools/format.sh index e9b8b2dd3fe6..62778b3b7535 100755 --- a/tools/format.sh +++ b/tools/format.sh @@ -1,14 +1,25 @@ #!/usr/bin/env bash -# Runs astyle with the full set of formatting options -astyle \ +set -euo pipefail + +if [ ! -x "$(command -v astyle_py)" ]; then + echo "astyle_py not found, please install astyle_py:" + echo " pip install -U astyle_py==VERSION" + echo "where VERSION is the same as in .pre-commit-config.yaml." + exit 1 +fi + +# "--astyle-version" here has to be in sync with pre-commit-config.yaml. +# The rest of the options have to be in sync with the default rules in tools/ci/astyle-rules.yml. +astyle_py --astyle-version=3.4.7 \ --style=otbs \ --attach-namespaces \ --attach-classes \ --indent=spaces=4 \ --convert-tabs \ - --align-pointer=name \ --align-reference=name \ --keep-one-line-statements \ --pad-header \ --pad-oper \ + --unpad-paren \ + --max-continuation-indent=120 \ "$@" From 4dbe541f8096ab5d5ea6a64479304353dacb8249 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Thu, 21 Sep 2023 16:32:39 +0200 Subject: [PATCH 094/142] ci: replace internal clang-tidy runner with the pypi project --- .gitlab-ci.yml | 2 -- .gitlab/ci/static-code-analysis.yml | 15 ++++----------- docs/en/api-guides/tools/idf-clang-tidy.rst | 8 -------- docs/zh_CN/api-guides/tools/idf-clang-tidy.rst | 8 -------- tools/ci/utils.sh | 10 ---------- tools/requirements/requirements.core.txt | 1 + 6 files changed, 5 insertions(+), 39 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1ffce6e9b456..061a6f75b376 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -58,8 +58,6 @@ variables: CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py" PYTHON_VER: 3.8.17 - CLANG_TIDY_RUNNER_PROJ: 2107 # idf/clang-tidy-runner - # Docker images BOT_DOCKER_IMAGE_TAG: ":latest" diff --git a/.gitlab/ci/static-code-analysis.yml b/.gitlab/ci/static-code-analysis.yml index 212911ecb752..7ad423e62c05 100644 --- a/.gitlab/ci/static-code-analysis.yml +++ b/.gitlab/ci/static-code-analysis.yml @@ -5,23 +5,16 @@ clang_tidy_check: - .rules:patterns:clang_tidy artifacts: paths: - - $OUTPUT_DIR + - clang_tidy_reports/ when: always expire_in: 1 day variables: - CLANG_TIDY_DIRS_TXT: ${CI_PROJECT_DIR}/tools/ci/clang_tidy_dirs.txt - RULES_FILE: ${CI_PROJECT_DIR}/tools/ci/static-analysis-rules.yml - OUTPUT_DIR: ${CI_PROJECT_DIR}/clang_tidy_reports IDF_TOOLCHAIN: clang script: - - internal_pip_install $CLANG_TIDY_RUNNER_PROJ pyclang - - export PATH=$PATH:$(python -c "import sys; print(sys.executable.rsplit('/', 1)[0])") - - dirs=$(cat ${CLANG_TIDY_DIRS_TXT} | while read line; do echo ${CI_PROJECT_DIR}/${line}; done | xargs) - - run_cmd idf_clang ${dirs} - --output-path ${OUTPUT_DIR} - --limit-file ${RULES_FILE} + - run_cmd idf_clang_tidy $(cat tools/ci/clang_tidy_dirs.txt | xargs) + --output-path clang_tidy_reports + --limit-file tools/ci/static-analysis-rules.yml --xtensa-include-dir - --run-clang-tidy-py run-clang-tidy check_pylint: extends: diff --git a/docs/en/api-guides/tools/idf-clang-tidy.rst b/docs/en/api-guides/tools/idf-clang-tidy.rst index 812009e7d6e1..7d3e7a802d6f 100644 --- a/docs/en/api-guides/tools/idf-clang-tidy.rst +++ b/docs/en/api-guides/tools/idf-clang-tidy.rst @@ -21,20 +21,12 @@ Prerequisites If you have never run this tool before, take the following steps to get this tool prepared. -#. Run the export scripts (``export.sh``, ``export.bat``, or others) to set up the environment variables. -#. Run ``pip install --upgrade pyclang`` to install this plugin. The extra commands would be activated in ``idf.py`` automatically. #. Run ``idf_tools.py install esp-clang`` to install the clang-tidy required binaries .. note:: This toolchain is still under development. After the final release, you do not have to install them manually. -#. Get the file from the `llvm repository `__ and add the folder of this script to the ``$PATH``. Or you could pass an optional argument ``--run-clang-tidy-py`` later when you call ``idf.py clang-check``. Please do not forget to make the script executable. - - .. note:: - - This file would be bundled in future toolchain releases. This is a temporary workaround. - #. Run the export scripts (``export.sh`` / ``export.bat`` / ... ) again to refresh the environment variables. Extra Commands diff --git a/docs/zh_CN/api-guides/tools/idf-clang-tidy.rst b/docs/zh_CN/api-guides/tools/idf-clang-tidy.rst index 1c837eda9775..e66f75fbaa33 100644 --- a/docs/zh_CN/api-guides/tools/idf-clang-tidy.rst +++ b/docs/zh_CN/api-guides/tools/idf-clang-tidy.rst @@ -21,20 +21,12 @@ IDF clang-tidy 是使用 `clang-tidy ` 初次运行此工具时,请按照以下步骤准备该工具: -#. 运行导出脚本(如 ``export.sh``、``export.bat`` 等),设置环境变量。 -#. 运行 ``pip install --upgrade pyclang`` 安装插件,其他命令将在 ``idf.py`` 中自动激活。 #. 运行 ``idf_tools.py install esp-clang`` 安装 clang-tidy 所需的二进制文件。 .. note:: 该工具链尚在开发中,最终版本发布后,将无需手动安装工具链。 -#. 从 `llvm 仓库 `__ 获取文件,并将该脚本所在的文件夹添加到 ``$PATH`` 中,或在调用 ``idf.py clang-check`` 时传递可选参数 ``--run-clang-tidy-py``。请将脚本设置为可执行。 - - .. note:: - - 在未来工具链版本中,该文件将一并捆绑。目前为临时解决方案。 - #. 再次运行导出脚本(如 ``export.sh``、``export.bat`` 等),刷新环境变量。 其他命令 diff --git a/tools/ci/utils.sh b/tools/ci/utils.sh index 719d68adf90c..f860fef110de 100644 --- a/tools/ci/utils.sh +++ b/tools/ci/utils.sh @@ -117,16 +117,6 @@ function retry_failed() { return $exitCode } -function internal_pip_install() { - project=$1 - package=$2 - token_name=${3:-${BOT_TOKEN_NAME}} - token=${4:-${BOT_TOKEN}} - python=${5:-python} - - $python -m pip install --index-url https://${token_name}:${token}@${GITLAB_HTTPS_HOST}/api/v4/projects/${project}/packages/pypi/simple --force-reinstall --no-deps ${package} -} - function join_by { local d=${1-} f=${2-} if shift 2; then diff --git a/tools/requirements/requirements.core.txt b/tools/requirements/requirements.core.txt index 1c0ba96bc599..d1d4c930c22c 100644 --- a/tools/requirements/requirements.core.txt +++ b/tools/requirements/requirements.core.txt @@ -16,6 +16,7 @@ esp-idf-kconfig esp-idf-monitor esp-idf-size esp-idf-panic-decoder +pyclang # gdb extensions dependencies freertos_gdb From 7d41744b16d377216e683c00b7d2694bcb944182 Mon Sep 17 00:00:00 2001 From: renpeiying Date: Fri, 1 Sep 2023 11:33:28 +0800 Subject: [PATCH 095/142] docs: Provide Chinese translation for api-reference/system/wdts.rst --- docs/en/api-reference/system/wdts.rst | 64 +++++---- docs/zh_CN/api-reference/system/wdts.rst | 160 ++++++++++++++++++++++- 2 files changed, 195 insertions(+), 29 deletions(-) diff --git a/docs/en/api-reference/system/wdts.rst b/docs/en/api-reference/system/wdts.rst index 1e70a5b9c61c..7f73aaf085cc 100644 --- a/docs/en/api-reference/system/wdts.rst +++ b/docs/en/api-reference/system/wdts.rst @@ -1,18 +1,20 @@ Watchdogs ========= +:link_to_translation:`zh_CN:[中文]` + Overview -------- -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 instances where FreeRTOS task switching is blocked for a prolonged period of time. The TWDT is responsible for detecting instances of tasks running without yielding for a prolonged period. - -ESP-IDF has support for the following types of watchdog timers: +ESP-IDF supports multiple types of watchdogs: .. list:: - - Interrupt Watchdog Timer (IWDT) - - Task Watchdog Timer (TWDT) - :SOC_XT_WDT_SUPPORTED: - Crystal 32K Watchdog Timer (XTWDT) + - Interrupt Watchdog Timer (IWDT) + - Task Watchdog Timer (TWDT) + :SOC_XT_WDT_SUPPORTED: - XTAL32K Watchdog Timer (Crystal 32K Watchdog Timer, i.e., XTWDT) + +The Interrupt Watchdog is responsible for ensuring that ISRs (Interrupt Service Routines) are not blocked for a prolonged period of time. The TWDT is responsible for detecting instances of tasks running without yielding for a prolonged period. The various watchdog timers can be enabled using the :ref:`project-configuration-menu`. However, the TWDT can also be enabled during runtime. @@ -21,17 +23,17 @@ Interrupt Watchdog Timer (IWDT) {IDF_TARGET_IWDT_TIMER_GROUP:default="Timer Group 1", esp32c2="Timer Group 0"} -The purpose of the IWDT is to ensure that interrupt service routines (ISRs) are not blocked from running for a prolonged period of time (i.e., the IWDT timeout period). Blocking ISRs from running in a timely manner is undesirable as it can increases ISR latency, and also prevents task switching (as task switching is executed form an ISR). The things that can block ISRs from running include: +The purpose of the IWDT is to ensure that interrupt service routines (ISRs) are not blocked from running for a prolonged period of time (i.e., the IWDT timeout period). Preventing ISRs from running in a timely manner is undesirable as it can increase ISR latency, and also prevent task switching (as task switching is executed form an ISR). The things that can block ISRs from running include: - Disabling interrupts - Critical Sections (also disables interrupts) -- Other same/higher priority ISRs ( blocks same/lower priority ISRs from running it completes execution) +- Other same/higher priority ISRs which block same/lower priority ISRs from running The IWDT utilizes the watchdog timer in {IDF_TARGET_IWDT_TIMER_GROUP} as its underlying hardware timer and leverages the FreeRTOS tick interrupt on each CPU to feed the watchdog timer. If the tick interrupt on a particular CPU is not run at within the IWDT timeout period, it is indicative that something is blocking ISRs from being run on that CPU (see the list of reasons above). When the IWDT times out, the default action is to invoke the panic handler and display the panic reason as ``Interrupt wdt timeout on CPU0`` or ``Interrupt wdt timeout on CPU1`` (as applicable). Depending on the panic handler's configured behavior (see :ref:`CONFIG_ESP_SYSTEM_PANIC`), users can then debug the source of the IWDT timeout (via the backtrace, OpenOCD, gdbstub etc) or simply reset the chip (which may be preferred in a production environment). -If for whatever reason the panic handler is unable to run after an IWDT timeout, the IWDT has a secondary timeout that will hard-reset the chip (i.e., a system reset). +If for whatever reason the panic handler is unable to run after an IWDT timeout, the IWDT has a second stage timeout that will hard-reset the chip (i.e., a system reset). Configuration ^^^^^^^^^^^^^ @@ -39,8 +41,8 @@ Configuration - The IWDT is enabled by default via the :ref:`CONFIG_ESP_INT_WDT` option. - The IWDT's timeout is configured by setting the :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` option. - - Note that the default timeout is higher if PSRAM support is enabled, as a critical section or interrupt routine that accesses a large amount of PSRAM takes longer to complete in some circumstances. - - The timeout should always at least twice longer than the period between FreeRTOS ticks (see :ref:`CONFIG_FREERTOS_HZ`). + - Note that the default timeout is higher if PSRAM support is enabled, as a critical section or interrupt routine that accesses a large amount of PSRAM takes longer to complete in some circumstances. + - The timeout should always at least twice longer than the period between FreeRTOS ticks (see :ref:`CONFIG_FREERTOS_HZ`). Tuning ^^^^^^ @@ -61,11 +63,14 @@ The Task Watchdog Timer (TWDT) is used to monitor particular tasks, ensuring tha .. only:: not esp32c2 - The TWDT is built around the Hardware Watchdog Timer in Timer Group 0. When a timeout occurs, an interrupt is triggered. Users can define the function ``esp_task_wdt_isr_user_handler`` in the user code, in order to receive the timeout event and extend the default behavior. + The TWDT is built around the Hardware Watchdog Timer in Timer Group 0. When a timeout occurs, an interrupt is triggered. .. only:: esp32c2 - The {IDF_TARGET_NAME} has only a single Timer Group, used by Interrupt Watchdog (IWDT). Thus, the Task Watchdog is built around the ``esp_timer`` component in order to implement a software timer. When a timeout occurs, an interrupt is triggered, notifying the ``esp_timer``'s main task. The latter then executes the TWDT callback previously registered. Users can define the function ``esp_task_wdt_isr_user_handler`` in the user code, in order to receive the timeout event and extend the default behavior. + The {IDF_TARGET_NAME} has only a single Timer Group, used by Interrupt Watchdog (IWDT). Thus, the Task Watchdog is built around the ``esp_timer`` component in order to implement a software timer. When a timeout occurs, an interrupt is triggered, notifying the ``esp_timer``'s main task. The latter then executes the TWDT callback previously registered. + +Users can define the function ``esp_task_wdt_isr_user_handler`` in the user code, in order to receive the timeout event and extend the default behavior. + Usage ^^^^^ @@ -75,11 +80,11 @@ The following functions can be used to watch tasks using the TWDT: - :cpp:func:`esp_task_wdt_init` to initialize the TWDT and subscribe the idle tasks. - :cpp:func:`esp_task_wdt_add` subscribes other tasks to the TWDT. - Once subscribed, :cpp:func:`esp_task_wdt_reset` should be called from the task to feed the TWDT. -- :cpp:func:`esp_task_wdt_delete()` unsubscribes a previously subscribed task -- :cpp:func:`esp_task_wdt_deinit()` unsubscribes the idle tasks and deinitializes the TWDT +- :cpp:func:`esp_task_wdt_delete()` unsubscribes a previously subscribed task. +- :cpp:func:`esp_task_wdt_deinit()` unsubscribes the idle tasks and deinitializes the TWDT. -In the case where applications need to watch at a more granular level (i.e., ensure that a particular functions/stub/code-path is called), the TWDT allows subscription of "users". +In the case where applications need to watch at a more granular level (i.e., ensure that a particular functions/stub/code-path is called), the TWDT allows subscription of ``users``. - :cpp:func:`esp_task_wdt_add_user` to subscribe an arbitrary user of the TWDT. This function returns a user handle to the added user. - :cpp:func:`esp_task_wdt_reset_user` must be called using the user handle in order to prevent a TWDT timeout. @@ -97,7 +102,7 @@ The default timeout period for the TWDT is set using config item :ref:`CONFIG_ES - Increase :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` in menuconfig for a larger watchdog timeout period. - You can also call :cpp:func:`esp_task_wdt_init` to increase the watchdog timeout period before erasing a large flash area. - For more information, you can refer to :doc:`SPI Flash <../peripherals/spi_flash/index>`. + For more information, you can refer to :doc:`../peripherals/spi_flash/index`. The following config options control TWDT configuration. They are all enabled by default: @@ -110,6 +115,7 @@ The following config options control TWDT configuration. They are all enabled by - :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_init` again. :not CONFIG_FREERTOS_UNICORE: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 Idle task is subscribed to the TWDT during startup. + .. note:: On a TWDT timeout the default behaviour is to simply print a warning and a backtrace before continuing running the app. If you want a timeout to cause a panic and a system reset then this can be configured through :ref:`CONFIG_ESP_TASK_WDT_PANIC`. @@ -117,29 +123,31 @@ The following config options control TWDT configuration. They are all enabled by .. only:: SOC_XT_WDT_SUPPORTED - XTAL32K Watchdog Timer (XTWDT) - ------------------------------ + XTAL32K Watchdog Timer (XTWDT) + ------------------------------ - One of the optional clock inputs to the {IDF_TARGET_NAME} is an external 32 KHz crystal or oscillator (XTAL32K) that is used as a clock source (``XTAL32K_CLK``) to various subsystems (such as the RTC). + One of the optional clock inputs to the {IDF_TARGET_NAME} is an external 32 kHz crystal oscillator (XTAL32K) that is used as a clock source (``XTAL32K_CLK``) to various subsystems (such as the RTC). - The XTWDT is a dedicated watchdog timer used to ensure that the XTAL32K is functioning correctly. When ``XTAL32K_CLK`` works as the clock source of ``RTC_SLOW_CLK`` and stops oscillating, the XTWDT 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. + The XTWDT is a dedicated watchdog timer used to ensure that the XTAL32K is functioning correctly. When ``XTAL32K_CLK`` works as the clock source of ``RTC_SLOW_CLK`` and stops oscillating, the XTWDT 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 is still able to wake-up as planned. + 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 is in Deep Sleep, waiting for a timer to expire, it is still 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. + 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 - """"""""""""" + Configuration + """"""""""""" + + - When the external 32 KHz crystal or oscillator is selected (:ref:`CONFIG_RTC_CLK_SRC`) the XTWDT can be enabled via the :ref:`CONFIG_ESP_XT_WDT` configuration option. + - The timeout is configured by setting the :ref:`CONFIG_ESP_XT_WDT_TIMEOUT` option. + - The automatic backup clock functionality is enabled via the ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` configuration option. - - When the external 32 KHz crystal or oscillator is selected (:ref:`CONFIG_RTC_CLK_SRC`) the XTWDT can be enabled via the :ref:`CONFIG_ESP_XT_WDT` configuration option. - - The timeout is configured by setting the :ref:`CONFIG_ESP_XT_WDT_TIMEOUT` option. - - The automatic backup clock functionality is enabled via the ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` configuration option. JTAG & Watchdogs ---------------- While debugging using OpenOCD, the CPUs are halted every time a breakpoint is reached. However if the watchdog timers continue to run when a breakpoint is encountered, they will eventually trigger a reset making it very difficult to debug code. Therefore OpenOCD will disable the hardware timers of both the interrupt and task watchdogs at every breakpoint. Moreover, OpenOCD will not reenable them upon leaving the breakpoint. This means that interrupt watchdog and task watchdog functionality will essentially be disabled. No warnings or panics from either watchdogs will be generated when the {IDF_TARGET_NAME} is connected to OpenOCD via JTAG. + API Reference ------------- diff --git a/docs/zh_CN/api-reference/system/wdts.rst b/docs/zh_CN/api-reference/system/wdts.rst index 65f9c73d2ad3..bb582b962b0c 100644 --- a/docs/zh_CN/api-reference/system/wdts.rst +++ b/docs/zh_CN/api-reference/system/wdts.rst @@ -1 +1,159 @@ -.. include:: ../../../en/api-reference/system/wdts.rst \ No newline at end of file +看门狗 +========= + +:link_to_translation:`en:[English]` + +概述 +-------- + +ESP-IDF 支持以下类型的看门狗定时器: + +.. list:: + + - 中断看门狗定时器 (IWDT) + - 任务看门狗定时器 (TWDT) + :SOC_XT_WDT_SUPPORTED: - XTAL32K 看门狗定时器 (Crystal 32K 看门狗定时器,即 XTWDT) + +中断看门狗负责确保 ISR(中断服务程序)不被长时间阻塞,TWDT 负责检测任务长时间运行而不让步的情况。 + +通过 :ref:`project-configuration-menu` 可启用各种看门狗定时器。其中,TWDT 也可以在程序运行时启用。 + +中断看门狗定时器 (IWDT) +------------------------------- + +{IDF_TARGET_IWDT_TIMER_GROUP:default="定时器组 1", esp32c2="定时器组 0"} + +IWDT 的目的是,确保中断服务例程 (ISR) 运行不会受到长时间阻塞(即 IWDT 超时)。阻塞 ISR 及时运行会增加 ISR 延迟,也会阻止任务切换(因为任务切换是从 ISR 执行的)。阻止 ISR 运行的事项包括: + +- 禁用中断 +- 临界区(也会禁用中断) +- 其他相同或更高优先级的 ISR,在完成前会阻止相同或较低优先级的 ISR + +IWDT 利用 {IDF_TARGET_IWDT_TIMER_GROUP} 中的看门狗定时器作为其底层硬件定时器,并在每个 CPU 上使用 FreeRTOS 时钟滴答中断,即 tick 中断。如果某个 CPU 上的 tick 中断没有在 IWDT 超时前运行,就表明该 CPU 上的 ISR 运行受阻(参见上文原因列表)。 + +当 IWDT 超时后,默认操作是调用紧急处理程序 (Panic Handler),并显示 出错原因( ``Interrupt wdt timeout on CPU0`` 或 ``Interrupt wdt timeout on CPU1``,视情况而定)。根据紧急处理程序的配置行为(参见 :ref:`CONFIG_ESP_SYSTEM_PANIC`),用户可通过回溯、OpenOCD、gdbstub 等来调试 IWDT 超时问题,也可以重置芯片(这在生产环境中可能是首选)。 + +如果出于某种原因,IWDT 超时后紧急处理程序无法运行,IWDT 还可以通过其二阶段超时来硬重置芯片(即系统重置)。 + +配置 +^^^^^^^^^^^^^ + +- IWDT 默认通过 :ref:`CONFIG_ESP_INT_WDT` 选项启用。 +- 通过 :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 选项设置 IWDT 超时。 + + - 注意,如果启用了 PSRAM 支持,那么默认的超时时间会更长,因为在某些情况下,临界区或中断例程访问大量 PSRAM 需要更长时间。 + - 超时时间至少应是 FreeRTOS tick 周期的两倍时长(参见 :ref:`CONFIG_FREERTOS_HZ`)。 + +调优 +^^^^^^ + +如果 IWDT 超时是中断或临界区运行超时导致的,可以考虑重写代码: + +- 临界区应尽可能短。任何非关键的代码或计算都应放在临界区外。 +- 中断处理程序也应尽可能减少计算量。考虑让 ISR 使用队列向任务推送数据,从而将计算推迟到任务中进行。 + +临界区或中断处理程序都不应阻塞其他事件。如果不能或不希望通过更改代码减少处理时间,可以通过设置 :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 延长超时时间。 + +.. _task-watchdog-timer: + +任务看门狗定时器 (TWDT) +-------------------------- + +任务看门狗定时器 (TWDT) 用于监视特定任务,确保任务在配置的超时时间内执行。TWDT 主要监视每个 CPU 的空闲任务,但其他任务也可以订阅 TWDT 监视。通过监视每个 CPU 的空闲任务,TWDT 可以检测到任务长时间运行没有让出的情况。这可能表明代码编写不当,在外设上自旋循环,或者任务陷入了无限循环。 + +.. only:: not esp32c2 + + TWDT 是基于定时器组 0 中的硬件看门狗定时器构建的。超时发生时会触发中断。 + +.. only:: esp32c2 + + {IDF_TARGET_NAME} 只有一个定时器组,由中断看门狗 (IWDT) 使用。因此,任务看门狗是基于 ``esp_timer`` 组件构建的,以实现软件定时器的作用。超时发生时会触发中断,并通知 ``esp_timer`` 的主任务,后者接到通知后会执行之前注册的 TWDT 回调。 + +可以在用户代码中定义函数 ``esp_task_wdt_isr_user_handler`` 来接收超时事件,并扩展默认行为。 + + +使用 +^^^^^ + +调用以下函数,用 TWDT 监视任务: + +- :cpp:func:`esp_task_wdt_init` 初始化 TWDT 并订阅空闲任务。 +- :cpp:func:`esp_task_wdt_add` 为其他任务订阅 TWDT。 +- 订阅后,应从任务中调用 :cpp:func:`esp_task_wdt_reset` 来喂 TWDT。 +- :cpp:func:`esp_task_wdt_delete()` 可以取消之前订阅的任务。 +- :cpp:func:`esp_task_wdt_deinit()` 取消订阅空闲任务并反初始化 TWDT。 + + +在需要更细粒度级别监视的情况下(即确保调用特定的函数、存根、代码路径),TWDT 允许订阅 ``users``。 + +- :cpp:func:`esp_task_wdt_add_user` 订阅 TWDT 的任意用户。此函数返回添加用户的用户句柄。 +- 必须使用用户句柄调用 :cpp:func:`esp_task_wdt_reset_user`,防止 TWDT 超时。 +- :cpp:func:`esp_task_wdt_delete_user` 取消订阅 TWDT 的任意用户。 + +配置 +^^^^^^^^^^^^^ + +TWDT 的默认超时时间可以通过 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 配置项进行设置,并应至少设置为任何单个任务预计需要独占 CPU 的时长,例如某应用程序将进行长时间的密集计算且不让位给其他任务时的预计时长。也可以调用 :cpp:func:`esp_task_wdt_init`,在运行时更改此时间。 + +.. note:: + + 擦除较大的 flash 区域可能会非常耗时,并可能导致任务连续运行,触发 TWDT 超时。以下两种方法可以避免这种情况: + + - 在 menuconfig 中增加 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S`,延长看门狗超时时间。 + - 在擦除 flash 区域前,调用 :cpp:func:`esp_task_wdt_init` 增加看门狗超时时间。 + + 如需了解更多信息,请参考 :doc:`../peripherals/spi_flash/index`。 + +以下配置选项控制 TWDT 配置,默认情况下全部启用: + +{IDF_TARGET_IDLE_TASK:default="空闲任务", esp32="CPU0 空闲任务", esp32s3="CPU0 空闲任务"} + +.. list:: + + - :ref:`CONFIG_ESP_TASK_WDT_EN` - 启用 TWDT 功能。如果禁用此选项, TWDT 即使运行时已初始化也无法使用。 + - :ref:`CONFIG_ESP_TASK_WDT_INIT` - TWDT 在启动期间自动初始化。禁用此选项时,仍可以调用 :cpp:func:`esp_task_wdt_init` 在运行时初始化 TWDT。 + - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0` - {IDF_TARGET_IDLE_TASK}在启动时订阅了 TWDT。如果此选项被禁用,仍可以调用 :cpp:func:`esp_task_wdt_init` 再次订阅。 + :not CONFIG_FREERTOS_UNICORE: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 空闲任务在启动时订阅了 TWDT。 + + +.. note:: + + 如果 TWDT 超时,会默认在继续运行应用程序前打印警告和回溯。如希望超时触发系统严重错误和系统重置,可以通过 :ref:`CONFIG_ESP_TASK_WDT_PANIC` 进行配置。 + + +.. only:: SOC_XT_WDT_SUPPORTED + + XTAL32K 看门狗定时器 (XTWDT) + ------------------------------ + + {IDF_TARGET_NAME} 的一个可选时钟输入是外部 32 kHz 无源晶振 (XTAL32K),它常用作各种子系统(如 RTC)的时钟源 (``XTAL32K_CLK``)。 + + XTWDT 是一个专用看门狗定时器,用于确保 XTAL32K 正常工作。如果 ``XTAL32K_CLK`` 是 ``RTC_SLOW_CLK`` 的时钟源,当它停止振荡时,XTWDT 会检测到并生成中断。XTWDT 还具有切换振荡器功能,可以自动切换到内部振荡器(准确度较低)作为 ``RTC_SLOW_CLK`` 的时钟源。 + + 由于切换到备用时钟是在硬件中完成的,因此切换也可以在 Deep-sleep 期间发生。这也说明,即使在芯片处于 Deep-sleep 并等待定时器超时时, ``XTAL32K_CLK`` 停止工作,芯片还是能按计划唤醒。 + + 如果 ``XTAL32K_CLK`` 重新开始正常工作,则可以调用 ``esp_xt_wdt_restore_clk`` 切换回时钟源,重新启用看门狗定时器。 + + 配置 + """"""""""""" + + - 选择外部 32 KHz 晶体或振荡器时 (:ref:`CONFIG_RTC_CLK_SRC`),通过 :ref:`CONFIG_ESP_XT_WDT` 配置选项启用 XTWDT。 + - 设置 :ref:`CONFIG_ESP_XT_WDT_TIMEOUT` 选项来配置超时时间。 + - 通过 :ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` 配置选项启用自动切换备用时钟功能。 + + +JTAG & 看门狗 +---------------- + +在使用 OpenOCD 进行调试时,CPU 会在每次达到断点时停止运行。然而,如果遇到断点后看门狗定时器继续运行,就会最终触发复位,为调试代码带来巨大的困难。因此, OpenOCD 会在每个断点处禁用中断和任务的看门狗的硬件定时器。此外,在离开断点时,OpenOCD 也不会重新启用定时器,也就是说,中断看门狗和任务看门狗实际上被禁用。当 {IDF_TARGET_NAME} 通过 JTAG 连接到 OpenOCD 时,看门狗不会打印任何警告或出现严重错误。 + + +API 参考 +------------- + +任务看门狗 +^^^^^^^^^^^^^ + +在 ESP-IDF 中使用任务看门狗的完整示例::example:`system/task_watchdog` + +.. include-build-file:: inc/esp_task_wdt.inc From 4697f9d00977da316e86ae8bb05c30d97c093833 Mon Sep 17 00:00:00 2001 From: Robert Lipe Date: Wed, 20 Sep 2023 01:15:03 -0500 Subject: [PATCH 096/142] Typo fix in dedic_gpio.rst: fasted->fastest. --- docs/en/api-reference/peripherals/dedic_gpio.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-reference/peripherals/dedic_gpio.rst b/docs/en/api-reference/peripherals/dedic_gpio.rst index 1049674d2ac5..54b6618a406d 100644 --- a/docs/en/api-reference/peripherals/dedic_gpio.rst +++ b/docs/en/api-reference/peripherals/dedic_gpio.rst @@ -90,7 +90,7 @@ For advanced users, they can always manipulate the GPIOs by writing assembly cod 1. Allocate a GPIO bundle: :cpp:func:`dedic_gpio_new_bundle` 2. Query the mask occupied by that bundle: :cpp:func:`dedic_gpio_get_out_mask` or/and :cpp:func:`dedic_gpio_get_in_mask` 3. Call CPU LL apis (e.g., `dedic_gpio_cpu_ll_write_mask`) or write assembly code with that mask -4. The fasted way of toggling IO is to use the dedicated "set/clear" instructions: +4. The fastest way of toggling IO is to use the dedicated "set/clear" instructions: .. only:: esp32s2 or esp32s3 From 00d77e7a75f4458465a8c53c578674511cc849c9 Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Wed, 27 Sep 2023 12:50:25 +0200 Subject: [PATCH 097/142] fix(hints): properly identify source component If there is a component(child) within a component(parent), like for test_apps, the parent component may be wrongly identified as source component for the failed include. This may lead to a false bug report if the parent component has component, which provides the missing header, in requirements. Fix this by looking for the longest matching source component directory. Suggested-by: Ivan Grokhotkov Signed-off-by: Frantisek Hrbata --- .../hint_modules/component_requirements.py | 5 +- tools/test_idf_py/test_hints.py | 79 +++++++++++++++---- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/tools/idf_py_actions/hint_modules/component_requirements.py b/tools/idf_py_actions/hint_modules/component_requirements.py index 3ce6dd9dba23..ab555b954575 100644 --- a/tools/idf_py_actions/hint_modules/component_requirements.py +++ b/tools/idf_py_actions/hint_modules/component_requirements.py @@ -64,9 +64,10 @@ def generate_hint(output: str) -> Optional[str]: # from header file, which is not present in component_info['sources'] component_dir = os.path.normpath(component_info['dir']) if source_filename.startswith(component_dir): - found_source_component_name = component_name + if found_source_component_info and len(found_source_component_info['dir']) >= len(component_dir): + continue found_source_component_info = component_info - break + found_source_component_name = component_name if not found_source_component_name: # The source file is not in any component. # It could be in a subproject added via ExternalProject_Add, in which case diff --git a/tools/test_idf_py/test_hints.py b/tools/test_idf_py/test_hints.py index d1164ff0a12c..18c609243052 100755 --- a/tools/test_idf_py/test_hints.py +++ b/tools/test_idf_py/test_hints.py @@ -48,16 +48,17 @@ def tearDown(self) -> None: self.tmpdir.cleanup() -class TestHintModuleComponentRequirements(unittest.TestCase): - def run_idf(self, args: List[str]) -> str: - # Simple helper to run idf command and return it's stdout. - cmd = [ - sys.executable, - os.path.join(os.environ['IDF_PATH'], 'tools', 'idf.py') - ] - proc = run(cmd + args, capture_output=True, cwd=str(self.projectdir), text=True) - return proc.stdout + proc.stderr +def run_idf(args: List[str], cwd: Path) -> str: + # Simple helper to run idf command and return it's stdout. + cmd = [ + sys.executable, + os.path.join(os.environ['IDF_PATH'], 'tools', 'idf.py') + ] + proc = run(cmd + args, capture_output=True, cwd=cwd, text=True) + return str(proc.stdout + proc.stderr) + +class TestHintModuleComponentRequirements(unittest.TestCase): def setUp(self) -> None: # Set up a dummy project in tmp directory with main and component1 component. # The main component includes component1.h from component1, but the header dir is @@ -87,44 +88,88 @@ def test_component_requirements(self) -> None: # The main component uses component1.h, but this header is not in component1 public # interface. Hints should suggest that component1.h should be added into INCLUDE_DIRS # of component1. - output = self.run_idf(['app']) + output = run_idf(['app'], self.projectdir) self.assertIn('Missing "component1.h" file name found in the following component(s): component1(', output) # Based on previous hint the component1.h is added to INCLUDE_DIRS, but main still doesn't # have dependency on compoment1. Hints should suggest to add component1 into main component # PRIV_REQUIRES, because foo.h is not in main public interface. - self.run_idf(['fullclean']) + run_idf(['fullclean'], self.projectdir) component1cmake = self.projectdir / 'components' / 'component1' / 'CMakeLists.txt' component1cmake.write_text('idf_component_register(INCLUDE_DIRS ".")') - output = self.run_idf(['app']) + output = run_idf(['app'], self.projectdir) self.assertIn('To fix this, add component1 to PRIV_REQUIRES list of idf_component_register call', output) # Add foo.h into main public interface. Now the hint should suggest to use # REQUIRES instead of PRIV_REQUIRES. - self.run_idf(['fullclean']) + run_idf(['fullclean'], self.projectdir) maincmake = self.projectdir / 'main' / 'CMakeLists.txt' maincmake.write_text(('idf_component_register(SRCS "foo.c" ' 'REQUIRES esp_timer ' 'INCLUDE_DIRS ".")')) - output = self.run_idf(['app']) + output = run_idf(['app'], self.projectdir) self.assertIn('To fix this, add component1 to REQUIRES list of idf_component_register call', output) # Add component1 to REQUIRES as suggested by previous hint, but also # add esp_psram as private req for component1 and add esp_psram.h - # to component1.h. New the hint should report that esp_psram should + # to component1.h. Now the hint should report that esp_psram should # be moved from PRIV_REQUIRES to REQUIRES for component1. - self.run_idf(['fullclean']) + run_idf(['fullclean'], self.projectdir) maincmake.write_text(('idf_component_register(SRCS "foo.c" ' 'REQUIRES esp_timer component1 ' 'INCLUDE_DIRS ".")')) (self.projectdir / 'components' / 'component1' / 'component1.h').write_text('#include "esp_psram.h"') component1cmake.write_text('idf_component_register(INCLUDE_DIRS "." PRIV_REQUIRES esp_psram)') - output = self.run_idf(['app']) + output = run_idf(['app'], self.projectdir) self.assertIn('To fix this, move esp_psram from PRIV_REQUIRES into REQUIRES', output) def tearDown(self) -> None: self.tmpdir.cleanup() +class TestNestedModuleComponentRequirements(unittest.TestCase): + def setUp(self) -> None: + # Set up a nested component structure. The components directory contains + # component1, which also contains foo project with main component. + # components/component1/project/main + # ^^^^^^^^^^ ^^^^ + # component nested component + # Both components include esp_timer.h, but only component1 has esp_timer + # in requirements. + self.tmpdir = tempfile.TemporaryDirectory() + self.tmpdirpath = Path(self.tmpdir.name) + + components = self.tmpdirpath / 'components' + maindir = components / 'component1' + maindir.mkdir(parents=True) + (maindir / 'CMakeLists.txt').write_text('idf_component_register(SRCS "component1.c" PRIV_REQUIRES esp_timer)') + (maindir / 'component1.c').write_text('#include "esp_timer.h"') + + self.projectdir = maindir / 'project' + self.projectdir.mkdir(parents=True) + (self.projectdir / 'CMakeLists.txt').write_text(( + 'cmake_minimum_required(VERSION 3.16)\n' + f'set(EXTRA_COMPONENT_DIRS "{components}")\n' + 'set(COMPONENTS main)\n' + 'include($ENV{IDF_PATH}/tools/cmake/project.cmake)\n' + 'project(foo)')) + + maindir = self.projectdir / 'main' + maindir.mkdir() + (maindir / 'CMakeLists.txt').write_text('idf_component_register(SRCS "foo.c" REQUIRES component1)') + (maindir / 'foo.c').write_text('#include "esp_timer.h"\nvoid app_main(){}') + + def test_nested_component_requirements(self) -> None: + # Verify that source component for a failed include is properly identified + # when components are nested. The main component should be identified as the + # real source, not the component1 component. + output = run_idf(['app'], self.projectdir) + self.assertNotIn('BUG: esp_timer.h found in component esp_timer which is already in the requirements list of component1', output) + self.assertIn('To fix this, add esp_timer to PRIV_REQUIRES list of idf_component_register call', output) + + def tearDown(self) -> None: + self.tmpdir.cleanup() + + if __name__ == '__main__': unittest.main() From 2120d8312fbee96f225dc16b1f2791d853f435d2 Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Wed, 13 Sep 2023 11:38:36 +0530 Subject: [PATCH 098/142] docs: Add documentation for using ECDSA peripheral with TLS --- docs/en/api-reference/protocols/esp_tls.rst | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index 0f96533d8b45..8440dced5ff2 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -201,6 +201,28 @@ The following table shows a typical comparison between WolfSSL and MbedTLS when * An example of mutual authentication with the DS peripheral can be found at :example:`ssl mutual auth` which internally uses (ESP-TLS) for the TLS connection. +.. only:: SOC_ECDSA_SUPPORTED + + ECDSA Peripheral with ESP-TLS + ----------------------------- + + ESP-TLS provides support for using the ECDSA peripheral with {IDF_TARGET_NAME}. The use of ECDSA peripheral is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. The ECDSA private key should be present in the efuse for using the ECDSA peripheral. Please refer to `espefuse.py `_ documentation for programming the ECDSA key in the efuse. + To use ECDSA peripheral with ESP-TLS, set ``use_ecdsa_peripheral`` to `true` and set ``ecdsa_key_efuse_blk`` to the efuse block id in which ECDSA private key is stored in the :cpp:type:`esp_tls_cfg_t` config structure. + This will enable the use of ECDSA peripheral for private key operations. As the client private key is already present in the eFuse, it need not be supplied to the :cpp:type:`esp_tls_cfg_t` structure. + + .. code-block:: c + + #include "esp_tls.h" + esp_tls_cfg_t cfg = { + .use_ecdsa_peripheral = true, + .ecdsa_key_efuse_blk = /* efuse block with ecdsa private key */, + }; + + .. note:: + + When using ECDSA peripheral with TLS, only ``MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`` ciphersuite is supported. If using TLS v1.3, ``MBEDTLS_TLS1_3_AES_128_GCM_SHA256`` ciphersuite is supported. + + TLS Ciphersuites ------------------------------------ From c5cd97d84fe2fbbfc26fa64e175bf4b35ee0e5d9 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 27 Sep 2023 16:35:26 +0200 Subject: [PATCH 099/142] fix(precommit): correct typo in astyle-format.yml file name --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 92b6ac7e0719..a1964a9c9766 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -207,4 +207,4 @@ repos: hooks: - id: astyle_py # If you are modifying astyle version, update tools/format.sh as well - args: ['--astyle-version=3.4.7', '--rules=tools/ci/astyle_rules.yml'] + args: ['--astyle-version=3.4.7', '--rules=tools/ci/astyle-rules.yml'] From c86cd4623e64e60a13e11d4b41c5498a87a49e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Thu, 28 Sep 2023 07:04:25 +0800 Subject: [PATCH 100/142] Revert "Merge branch 'ci/perf_monitor_spiflash_build_test_enable_esp32p4' into 'master'" This reverts merge request !25636 --- examples/storage/.build-test-rules.yml | 6 +++--- examples/storage/perf_benchmark/README.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/storage/.build-test-rules.yml b/examples/storage/.build-test-rules.yml index b3012a887910..8fd1f02eec87 100644 --- a/examples/storage/.build-test-rules.yml +++ b/examples/storage/.build-test-rules.yml @@ -112,10 +112,10 @@ examples/storage/parttool: reason: lack of runners examples/storage/perf_benchmark: - disable_test: - - if: IDF_TARGET in ["esp32p4"] + disable: + - if: IDF_TARGET == "esp32p4" temporary: true - reason: target esp32p4 is not supported yet, only build test (for spiflash, not sdspi or sdmmc) + reason: target esp32p4 is not supported yet examples/storage/sd_card/sdmmc: disable: diff --git a/examples/storage/perf_benchmark/README.md b/examples/storage/perf_benchmark/README.md index c30959cac850..f9dd9440fb1a 100644 --- a/examples/storage/perf_benchmark/README.md +++ b/examples/storage/perf_benchmark/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # Storage performance benchmark example From 1b2484214c29fbfc744ac157e7e56f1f088663e2 Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 27 Sep 2023 22:39:34 +0800 Subject: [PATCH 101/142] refactor(esp_lcd): reformat code with astyle_py --- components/esp_lcd/include/esp_lcd_panel_io.h | 1 - components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c | 11 +++++------ components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c | 5 ++--- components/esp_lcd/src/esp_lcd_panel_io_i80.c | 4 ++-- components/esp_lcd/src/esp_lcd_panel_io_spi.c | 2 +- components/esp_lcd/src/esp_lcd_panel_ssd1306.c | 4 ++-- components/esp_lcd/src/esp_lcd_panel_st7789.c | 2 +- .../test_apps/i80_lcd/main/test_i80_lcd_panel.c | 1 - .../esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c | 2 +- tools/ci/astyle-rules.yml | 1 - 10 files changed, 14 insertions(+), 19 deletions(-) diff --git a/components/esp_lcd/include/esp_lcd_panel_io.h b/components/esp_lcd/include/esp_lcd_panel_io.h index 6505a10127e4..7fe5bc974707 100644 --- a/components/esp_lcd/include/esp_lcd_panel_io.h +++ b/components/esp_lcd/include/esp_lcd_panel_io.h @@ -44,7 +44,6 @@ typedef struct { esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; /*!< Callback invoked when color data transfer has finished */ } esp_lcd_panel_io_callbacks_t; - /** * @brief Transmit LCD command and receive corresponding parameters * diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c index 6ad986cee821..ba7731b2dc29 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -94,7 +94,7 @@ static esp_err_t panel_io_i2c_register_event_callbacks(esp_lcd_panel_io_handle_t { lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base); - if(i2c_panel_io->on_color_trans_done != NULL) { + if (i2c_panel_io->on_color_trans_done != NULL) { ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!"); } @@ -117,7 +117,7 @@ static esp_err_t panel_io_i2c_rx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, voi if (send_param) { if (i2c_panel_io->control_phase_enabled) { ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, i2c_panel_io->control_phase_cmd, true), - err, TAG, "write control phase failed"); // control phase + err, TAG, "write control phase failed"); // control phase } uint8_t cmds[4] = {BYTESHIFT(lcd_cmd, 3), BYTESHIFT(lcd_cmd, 2), BYTESHIFT(lcd_cmd, 1), BYTESHIFT(lcd_cmd, 0)}; size_t cmds_size = i2c_panel_io->lcd_cmd_bits / 8; @@ -157,12 +157,11 @@ static esp_err_t panel_io_i2c_tx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, con ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, (i2c_panel_io->dev_addr << 1) | I2C_MASTER_WRITE, true), err, TAG, "write address failed"); // address phase if (i2c_panel_io->control_phase_enabled) { ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, is_param ? i2c_panel_io->control_phase_cmd : i2c_panel_io->control_phase_data, true), - err, TAG, "write control phase failed"); // control phase + err, TAG, "write control phase failed"); // control phase } // some displays don't want any additional commands on data transfers - if (send_param) - { + if (send_param) { uint8_t cmds[4] = {BYTESHIFT(lcd_cmd, 3), BYTESHIFT(lcd_cmd, 2), BYTESHIFT(lcd_cmd, 1), BYTESHIFT(lcd_cmd, 0)}; size_t cmds_size = i2c_panel_io->lcd_cmd_bits / 8; if (cmds_size > 0 && cmds_size <= sizeof(cmds)) { diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c index 3bab7b832948..fa2c834adce2 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c @@ -105,7 +105,7 @@ static esp_err_t panel_io_i2c_register_event_callbacks(esp_lcd_panel_io_handle_t { lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base); - if(i2c_panel_io->on_color_trans_done != NULL) { + if (i2c_panel_io->on_color_trans_done != NULL) { ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!"); } @@ -159,8 +159,7 @@ static esp_err_t panel_io_i2c_tx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, con } // some displays don't want any additional commands on data transfers - if (send_param) - { + if (send_param) { uint8_t cmds[4] = {BYTESHIFT(lcd_cmd, 3), BYTESHIFT(lcd_cmd, 2), BYTESHIFT(lcd_cmd, 1), BYTESHIFT(lcd_cmd, 0)}; size_t cmds_size = i2c_panel_io->lcd_cmd_bits / 8; if (cmds_size > 0 && cmds_size <= sizeof(cmds)) { diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i80.c b/components/esp_lcd/src/esp_lcd_panel_io_i80.c index db86c75f03b5..d90d57fe36ab 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i80.c @@ -425,8 +425,8 @@ static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons // wait all pending transaction in the queue to finish size_t num_trans_inflight = next_device->num_trans_inflight; for (size_t i = 0; i < num_trans_inflight; i++) { - ESP_RETURN_ON_FALSE( xQueueReceive(next_device->done_queue, &trans_desc, portMAX_DELAY) == pdTRUE, - ESP_FAIL, TAG, "recycle inflight transactions failed"); + ESP_RETURN_ON_FALSE(xQueueReceive(next_device->done_queue, &trans_desc, portMAX_DELAY) == pdTRUE, + ESP_FAIL, TAG, "recycle inflight transactions failed"); next_device->num_trans_inflight--; } diff --git a/components/esp_lcd/src/esp_lcd_panel_io_spi.c b/components/esp_lcd/src/esp_lcd_panel_io_spi.c index 7c731451ba2e..663e3f2a62cb 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_spi.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_spi.c @@ -330,7 +330,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode lcd_trans->base.length = spi_panel_io->lcd_cmd_bits; lcd_trans->base.tx_buffer = &lcd_cmd; - if(color && color_size) { + if (color && color_size) { lcd_trans->base.flags |= SPI_TRANS_CS_KEEP_ACTIVE; } if (spi_panel_io->flags.octal_mode) { diff --git a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c b/components/esp_lcd/src/esp_lcd_panel_ssd1306.c index 0520146c1012..d2a94aefb1a4 100644 --- a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c +++ b/components/esp_lcd/src/esp_lcd_panel_ssd1306.c @@ -141,10 +141,10 @@ static esp_err_t panel_ssd1306_init(esp_lcd_panel_t *panel) ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_OFF, NULL, 0), TAG, "io tx param SSD1306_CMD_DISP_OFF failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_MEMORY_ADDR_MODE, (uint8_t[]) { - 0x00 // horizontal addressing mode + 0x00 // horizontal addressing mode }, 1), TAG, "io tx param SSD1306_CMD_SET_MEMORY_ADDR_MODE failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_CHARGE_PUMP, (uint8_t[]) { - 0x14 // enable charge pump + 0x14 // enable charge pump }, 1), TAG, "io tx param SSD1306_CMD_SET_CHARGE_PUMP failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, SSD1306_CMD_MIRROR_X_OFF, NULL, 0), TAG, "io tx param SSD1306_CMD_MIRROR_X_OFF failed"); diff --git a/components/esp_lcd/src/esp_lcd_panel_st7789.c b/components/esp_lcd/src/esp_lcd_panel_st7789.c index fb3f7349f48a..36c39110bf5c 100644 --- a/components/esp_lcd/src/esp_lcd_panel_st7789.c +++ b/components/esp_lcd/src/esp_lcd_panel_st7789.c @@ -106,7 +106,7 @@ esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel st7789->ramctl_val_1 = 0x00; st7789->ramctl_val_2 = 0xf0; // Use big endian by default - if((panel_dev_config->data_endian) == LCD_RGB_DATA_ENDIAN_LITTLE) { + if ((panel_dev_config->data_endian) == LCD_RGB_DATA_ENDIAN_LITTLE) { // Use little endian st7789->ramctl_val_2 |= ST7789_DATA_LITTLE_ENDIAN_BIT; } diff --git a/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c b/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c index 7f18e14c86cd..e2f6e2cf1823 100644 --- a/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c +++ b/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c @@ -43,7 +43,6 @@ TEST_CASE("i80_and_i2s_driver_co-existence", "[lcd][i2s]") }; TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); - i2s_chan_handle_t tx_handle = NULL; i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); // I2S driver won't be installed as the same I2S port has been used by LCD diff --git a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c index 5923da521c76..4e1eb3edd39d 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c +++ b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c @@ -26,7 +26,7 @@ #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t)) static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, size_t bpp, size_t bb_pixels, bool refresh_on_demand, - esp_lcd_rgb_panel_vsync_cb_t vsync_cb, void *user_data) + esp_lcd_rgb_panel_vsync_cb_t vsync_cb, void *user_data) { esp_lcd_panel_handle_t panel_handle = NULL; esp_lcd_rgb_panel_config_t panel_config = { diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index 7fa747ff2245..8ed56bfe89eb 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -66,7 +66,6 @@ components_not_formatted_temporary: - "/components/esp_https_ota/" - "/components/esp_https_server/" - "/components/esp_hw_support/" - - "/components/esp_lcd/" - "/components/esp_local_ctrl/" - "/components/esp_mm/" - "/components/esp_netif/" From b12e250b2cffaac04e7aca321f05e9ad55532893 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 28 Sep 2023 09:43:12 +0800 Subject: [PATCH 102/142] refactor(examples): reformat peripheral examples with astyle_py --- .../main/continuous_read_main.c | 3 +- .../adc/oneshot_read/main/oneshot_read_main.c | 3 - .../main/ana_cmpr_example_intr.c | 6 +- .../dac_audio/main/dac_audio_example_main.c | 2 +- .../main/dac_continuous_example_dma.c | 30 ++-- .../main/dac_continuous_example_main.c | 2 +- .../main/dac_continuous_example_timer.c | 38 ++-- .../soft_i2c_master/include/soft_i2c_master.h | 9 +- .../soft_i2c_master/soft_i2c_master.c | 32 ++-- .../components/soft_spi/include/soft_spi.h | 7 +- .../soft_spi/components/soft_spi/soft_spi.c | 12 +- .../components/soft_uart/include/soft_uart.h | 7 +- .../components/soft_uart/soft_uart.c | 30 ++-- .../generic_gpio/main/gpio_example_main.c | 6 +- .../matrix_keyboard/src/matrix_keyboard.c | 14 +- .../i2c/i2c_eeprom/main/i2c_eeprom_main.c | 4 +- .../i2c/i2c_self_test/main/i2c_example_main.c | 14 +- .../i2c/i2c_simple/main/i2c_simple_main.c | 1 - .../i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c | 2 - .../i2s/i2s_basic/i2s_pdm/main/i2s_pdm_tx.c | 17 +- .../i2s_std/main/i2s_std_example_main.c | 42 ++--- .../i2s_tdm/main/i2s_tdm_example_main.c | 10 +- .../main/i2s_es7210_record_example.c | 17 +- .../i2s_es8311/main/example_config.h | 2 - .../i2s_es8311/main/i2s_es8311_example.c | 1 - .../lcd/tjpgd/main/pretty_effect.c | 33 ++-- .../lcd/tjpgd/main/pretty_effect.h | 2 - .../ledc_fade/main/ledc_fade_example_main.c | 8 +- .../main/ledc_gamma_curve_fade_example_main.c | 3 - .../mcpwm_bldc_hall_control_example_main.c | 18 +- .../mcpwm_foc_svpwm_open_loop/main/app_main.c | 3 +- .../main/foc/esp_foc.c | 9 +- .../main/foc/esp_foc.h | 11 +- .../main/svpwm/esp_svpwm.c | 7 +- .../main/mcpwm_servo_control_example_main.c | 4 +- .../mcpwm_sync/main/mcpwm_sync_example_main.c | 8 +- .../led_strip/main/led_strip_example_main.c | 1 - .../peripherals/sdio/host/main/app_main.c | 11 +- .../peripherals/sdio/slave/main/app_main.c | 69 ++++---- .../atecc608_ecdsa/main/ecdsa_example_main.c | 24 +-- .../hd_eeprom/components/eeprom/spi_eeprom.c | 41 +++-- .../hd_eeprom/main/spi_eeprom_main.c | 6 +- .../spi_master/lcd/main/pretty_effect.c | 31 ++-- .../spi_master/lcd/main/pretty_effect.h | 2 - .../lcd/main/spi_master_example_main.c | 167 +++++++++--------- .../spi_slave/receiver/main/app_main.c | 60 +++---- .../spi_slave/sender/main/app_main.c | 73 ++++---- .../append_mode/master/main/app_main.c | 20 +-- .../append_mode/slave/main/app_main.c | 6 +- .../segment_mode/seg_master/main/app_main.c | 4 +- .../segment_mode/seg_slave/main/app_main.c | 2 - .../main/temp_sensor_monitor_main.c | 1 - .../main/timer_group_example_main.c | 1 - .../main/touch_button_example_main.c | 4 +- .../main/waterproof_example_main.c | 4 +- .../main/touch_elements_example_main.c | 8 +- .../main/touch_matrix_example_main.c | 16 +- .../main/touch_slider_example_main.c | 2 +- .../touch_pad_read/main/tp_read_main.c | 2 +- .../twai_network_example_listen_only_main.c | 13 +- .../main/twai_network_example_master_main.c | 11 +- .../main/twai_network_example_slave_main.c | 12 +- .../main/uart_async_rxtxtasks_main.c | 9 +- .../uart/uart_echo_rs485/main/rs485_example.c | 2 +- .../main/uart_events_example_main.c | 128 +++++++------- .../uart_repl/main/uart_repl_example_main.c | 25 +-- .../main/uart_select_example_main.c | 4 +- .../tusb_hid/main/tusb_hid_example_main.c | 16 +- .../usb/device/tusb_msc/main/tusb_msc_main.c | 3 +- .../usb/device/tusb_ncm/main/tusb_ncm_main.c | 1 - .../cdc_acm_host/main/usb_cdc_example_main.c | 30 ++-- .../main/cdc_acm_vcp_example_main.cpp | 24 +-- .../usb/host/hid/main/hid_host_example.c | 35 ++-- .../usb/host/msc/main/msc_example_main.c | 20 +-- .../usb/host/usb_host_lib/main/class_driver.c | 36 ++-- .../usb_host_lib/main/usb_host_lib_main.c | 2 +- examples/peripherals/usb/host/uvc/main/main.c | 22 +-- .../usb/host/uvc/main/tcp_server.c | 11 +- tools/ci/astyle-rules.yml | 4 +- 79 files changed, 677 insertions(+), 703 deletions(-) diff --git a/examples/peripherals/adc/continuous_read/main/continuous_read_main.c b/examples/peripherals/adc/continuous_read/main/continuous_read_main.c index 35a95d14865a..307b8da97958 100644 --- a/examples/peripherals/adc/continuous_read/main/continuous_read_main.c +++ b/examples/peripherals/adc/continuous_read/main/continuous_read_main.c @@ -41,7 +41,6 @@ static adc_channel_t channel[2] = {ADC_CHANNEL_2, ADC_CHANNEL_3}; static TaskHandle_t s_task_handle; static const char *TAG = "EXAMPLE"; - static bool IRAM_ATTR s_conv_done_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data) { BaseType_t mustYield = pdFALSE; @@ -103,7 +102,7 @@ void app_main(void) ESP_ERROR_CHECK(adc_continuous_register_event_callbacks(handle, &cbs, NULL)); ESP_ERROR_CHECK(adc_continuous_start(handle)); - while(1) { + while (1) { /** * This is to show you the way to use the ADC continuous mode driver event callback. diff --git a/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c b/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c index 25ffc14d8bf0..1183d0fddf73 100644 --- a/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c +++ b/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c @@ -52,7 +52,6 @@ static int voltage[2][10]; static bool example_adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle); static void example_adc_calibration_deinit(adc_cali_handle_t handle); - void app_main(void) { //-------------ADC1 Init---------------// @@ -76,7 +75,6 @@ void app_main(void) bool do_calibration1_chan0 = example_adc_calibration_init(ADC_UNIT_1, EXAMPLE_ADC1_CHAN0, EXAMPLE_ADC_ATTEN, &adc1_cali_chan0_handle); bool do_calibration1_chan1 = example_adc_calibration_init(ADC_UNIT_1, EXAMPLE_ADC1_CHAN1, EXAMPLE_ADC_ATTEN, &adc1_cali_chan1_handle); - #if EXAMPLE_USE_ADC2 //-------------ADC2 Init---------------// adc_oneshot_unit_handle_t adc2_handle; @@ -139,7 +137,6 @@ void app_main(void) #endif //#if EXAMPLE_USE_ADC2 } - /*--------------------------------------------------------------- ADC Calibration ---------------------------------------------------------------*/ diff --git a/examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c b/examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c index 78fec3e9bc37..29e1e453042b 100644 --- a/examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c +++ b/examples/peripherals/analog_comparator/main/ana_cmpr_example_intr.c @@ -15,8 +15,8 @@ static const char *TAG = "ana_cmpr_example"; static bool example_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr, - const ana_cmpr_cross_event_data_t *edata, - void *user_ctx) + const ana_cmpr_cross_event_data_t *edata, + void *user_ctx) { #if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR static ana_cmpr_internal_ref_config_t ref_cfg = { @@ -70,7 +70,7 @@ void example_init_analog_comparator_intr(void) }; ESP_ERROR_CHECK(ana_cmpr_set_internal_reference(cmpr, &ref_cfg)); #else - /* Step 1: Allocate the new analog comparator unit */ + /* Step 1: Allocate the new analog comparator unit */ ana_cmpr_config_t config = { .unit = EXAMPLE_ANA_CMPR_UNIT, .clk_src = ANA_CMPR_CLK_SRC_DEFAULT, diff --git a/examples/peripherals/dac/dac_continuous/dac_audio/main/dac_audio_example_main.c b/examples/peripherals/dac/dac_continuous/dac_audio/main/dac_audio_example_main.c index cc1cf9d0f6bf..b0ceb64c1b48 100644 --- a/examples/peripherals/dac/dac_continuous/dac_audio/main/dac_audio_example_main.c +++ b/examples/peripherals/dac/dac_continuous/dac_audio/main/dac_audio_example_main.c @@ -43,7 +43,7 @@ static void dac_write_data_asynchronously(dac_continuous_handle_t handle, QueueH xQueueReceive(que, &evt_data, portMAX_DELAY); size_t loaded_bytes = 0; ESP_ERROR_CHECK(dac_continuous_write_asynchronously(handle, evt_data.buf, evt_data.buf_size, - data + byte_written, data_size - byte_written, &loaded_bytes)); + data + byte_written, data_size - byte_written, &loaded_bytes)); byte_written += loaded_bytes; } /* Clear the legacy data in DMA, clear times equal to the 'dac_continuous_config_t::desc_num' */ diff --git a/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_dma.c b/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_dma.c index f96f6403e9f1..fe3fa3eb6506 100644 --- a/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_dma.c +++ b/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_dma.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -32,20 +32,20 @@ static void dac_dma_write_task(void *args) while (1) { /* The wave in the buffer will be converted cyclically */ switch (wav_sel) { - case DAC_SINE_WAVE: - ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)sin_wav, buf_len, NULL)); - break; - case DAC_TRIANGLE_WAVE: - ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)tri_wav, buf_len, NULL)); - break; - case DAC_SAWTOOTH_WAVE: - ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)saw_wav, buf_len, NULL)); - break; - case DAC_SQUARE_WAVE: - ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)squ_wav, buf_len, NULL)); - break; - default: - break; + case DAC_SINE_WAVE: + ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)sin_wav, buf_len, NULL)); + break; + case DAC_TRIANGLE_WAVE: + ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)tri_wav, buf_len, NULL)); + break; + case DAC_SAWTOOTH_WAVE: + ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)saw_wav, buf_len, NULL)); + break; + case DAC_SQUARE_WAVE: + ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)squ_wav, buf_len, NULL)); + break; + default: + break; } /* Switch wave every CONFIG_EXAMPLE_WAVE_PERIOD_SEC seconds */ vTaskDelay(pdMS_TO_TICKS(CONFIG_EXAMPLE_WAVE_PERIOD_SEC * 1000)); diff --git a/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_main.c b/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_main.c index d182850f4e4f..a20c65e93914 100644 --- a/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_main.c +++ b/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_main.c @@ -54,7 +54,7 @@ static void example_generate_wave(void) uint32_t pnt_num = EXAMPLE_ARRAY_LEN; for (int i = 0; i < pnt_num; i ++) { - sin_wav[i] = (uint8_t)((sin( i * CONST_PERIOD_2_PI / pnt_num) + 1) * (double)(EXAMPLE_DAC_AMPLITUDE) / 2 + 0.5); + sin_wav[i] = (uint8_t)((sin(i * CONST_PERIOD_2_PI / pnt_num) + 1) * (double)(EXAMPLE_DAC_AMPLITUDE) / 2 + 0.5); tri_wav[i] = (i > (pnt_num / 2)) ? (2 * EXAMPLE_DAC_AMPLITUDE * (pnt_num - i) / pnt_num) : (2 * EXAMPLE_DAC_AMPLITUDE * i / pnt_num); saw_wav[i] = (i == pnt_num) ? 0 : (i * EXAMPLE_DAC_AMPLITUDE / pnt_num); squ_wav[i] = (i < (pnt_num / 2)) ? EXAMPLE_DAC_AMPLITUDE : 0; diff --git a/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_timer.c b/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_timer.c index 821ae8860eb4..ae6402dddb0e 100644 --- a/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_timer.c +++ b/examples/peripherals/dac/dac_continuous/signal_generator/main/dac_continuous_example_timer.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -42,24 +42,24 @@ static bool IRAM_ATTR on_timer_alarm_cb(gptimer_handle_t timer, const gptimer_al // Switch wave every CONFIG_EXAMPLE_WAVE_PERIOD_SEC second if (point_cnt < EXAMPLE_CONVERT_FREQ_HZ * CONFIG_EXAMPLE_WAVE_PERIOD_SEC) { switch (wav_sel) { - case DAC_SINE_WAVE: - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, sin_wav[index])); - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, sin_wav[index])); - break; - case DAC_TRIANGLE_WAVE: - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, tri_wav[index])); - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, tri_wav[index])); - break; - case DAC_SAWTOOTH_WAVE: - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, saw_wav[index])); - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, saw_wav[index])); - break; - case DAC_SQUARE_WAVE: - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, squ_wav[index])); - ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, squ_wav[index])); - break; - default: - break; + case DAC_SINE_WAVE: + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, sin_wav[index])); + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, sin_wav[index])); + break; + case DAC_TRIANGLE_WAVE: + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, tri_wav[index])); + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, tri_wav[index])); + break; + case DAC_SAWTOOTH_WAVE: + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, saw_wav[index])); + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, saw_wav[index])); + break; + case DAC_SQUARE_WAVE: + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, squ_wav[index])); + ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, squ_wav[index])); + break; + default: + break; } point_cnt++; index++; diff --git a/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/include/soft_i2c_master.h b/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/include/soft_i2c_master.h index fb28aeec9e8c..c7f3df608448 100644 --- a/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/include/soft_i2c_master.h +++ b/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/include/soft_i2c_master.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -23,7 +23,6 @@ typedef enum { SOFT_I2C_FREQ_END } soft_i2c_master_freq_t; - /** * @brief Structure defining the configuration for the software I2C master bus */ @@ -33,13 +32,11 @@ typedef struct { soft_i2c_master_freq_t freq; } soft_i2c_master_config_t; - /** * @brief Abstract type representing a software I2C bus. */ typedef struct i2c_master_bus_impl_t* soft_i2c_master_bus_t; - /** * @brief Create and configure the software I2C bus. * @@ -50,7 +47,6 @@ typedef struct i2c_master_bus_impl_t* soft_i2c_master_bus_t; */ esp_err_t soft_i2c_master_new(soft_i2c_master_config_t *config, soft_i2c_master_bus_t *bus); - /** * @brief Delete a previously initialized I2C software bus. * @@ -60,7 +56,6 @@ esp_err_t soft_i2c_master_new(soft_i2c_master_config_t *config, soft_i2c_master_ */ esp_err_t soft_i2c_master_del(soft_i2c_master_bus_t bus); - /** * @brief Perform a write to the given device on the software I2C bus. * @@ -75,7 +70,6 @@ esp_err_t soft_i2c_master_write(soft_i2c_master_bus_t bus, uint8_t device_address, const uint8_t* write_buffer, size_t write_size); - /** * @brief Perform a read from the given device on the software I2C bus. * @@ -90,7 +84,6 @@ esp_err_t soft_i2c_master_read(soft_i2c_master_bus_t bus, uint8_t device_address, uint8_t* read_buffer, size_t read_size); - /** * @brief Perform a write followed by a read to the given device on the software I2C bus. * diff --git a/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/soft_i2c_master.c b/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/soft_i2c_master.c index 9ddff9b11b04..cf283c980039 100644 --- a/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/soft_i2c_master.c +++ b/examples/peripherals/dedicated_gpio/soft_i2c/components/soft_i2c_master/soft_i2c_master.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -24,10 +24,9 @@ /* Forward declaration of static functions */ static uint32_t freq_to_delay(soft_i2c_master_freq_t freq); static esp_err_t emulate_i2c_transfer(uint8_t device_address, - const uint8_t* write_buffer, uint32_t write_size, - uint8_t* read_buffer, uint32_t read_size, - soft_i2c_master_bus_t bus); - + const uint8_t* write_buffer, uint32_t write_size, + uint8_t* read_buffer, uint32_t read_size, + soft_i2c_master_bus_t bus); /* Mutex required to enter critical sections */ static portMUX_TYPE g_lock = portMUX_INITIALIZER_UNLOCKED; @@ -42,7 +41,6 @@ struct i2c_master_bus_impl_t { dedic_gpio_bundle_handle_t bundle; }; - esp_err_t soft_i2c_master_new(soft_i2c_master_config_t *config, soft_i2c_master_bus_t *bus) { esp_err_t ret; @@ -103,7 +101,6 @@ esp_err_t soft_i2c_master_new(soft_i2c_master_config_t *config, soft_i2c_master_ return ret; } - esp_err_t soft_i2c_master_del(soft_i2c_master_bus_t bus) { esp_err_t ret; @@ -117,7 +114,6 @@ esp_err_t soft_i2c_master_del(soft_i2c_master_bus_t bus) return ret; } - esp_err_t soft_i2c_master_write(soft_i2c_master_bus_t bus, uint8_t device_address, const uint8_t* write_buffer, size_t write_size) @@ -159,7 +155,6 @@ esp_err_t soft_i2c_master_read(soft_i2c_master_bus_t bus, return ret; } - esp_err_t soft_i2c_master_write_read(soft_i2c_master_bus_t bus, uint8_t device_address, const uint8_t* write_buffer, size_t write_size, @@ -184,18 +179,17 @@ esp_err_t soft_i2c_master_write_read(soft_i2c_master_bus_t bus, return ret; } - /***** Private implementation *****/ static uint32_t freq_to_delay(soft_i2c_master_freq_t freq) { - switch(freq) { - case SOFT_I2C_100KHZ: return 3; - case SOFT_I2C_200KHZ: return 2; - case SOFT_I2C_300KHZ: return 1; - default: - assert(false); - return 0; + switch (freq) { + case SOFT_I2C_100KHZ: return 3; + case SOFT_I2C_200KHZ: return 2; + case SOFT_I2C_300KHZ: return 1; + default: + assert(false); + return 0; } } @@ -232,7 +226,6 @@ static inline void emulate_start(soft_i2c_master_bus_t bus) set_sda(bidir_bundle, 0, delay); } - static inline void emulate_stop(soft_i2c_master_bus_t bus) { dedic_gpio_bundle_handle_t bidir_bundle = bus->bundle; @@ -287,8 +280,7 @@ static inline uint8_t emulate_read_byte(soft_i2c_master_bus_t bus, int send_ack) set_scl(bidir_bundle, 0, delay); set_sda(bidir_bundle, 1, delay); - for (int i = 7; i >= 0; i--) - { + for (int i = 7; i >= 0; i--) { /* Set SCL to low */ set_scl(bidir_bundle, 0, delay); /* Get SDA value now and store it in the final result */ diff --git a/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/include/soft_spi.h b/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/include/soft_spi.h index ecf5f1c9abf4..e6c9f83870b9 100644 --- a/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/include/soft_spi.h +++ b/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/include/soft_spi.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -23,13 +23,11 @@ typedef struct { uint32_t cs_pin; } soft_spi_config_t; - /** * @brief Abstract type representing a software SPI bus. */ typedef struct soft_spi_bus_impl_t* soft_spi_bus_t; - /** * @brief Create and configure the software SPI bus. * @@ -40,7 +38,6 @@ typedef struct soft_spi_bus_impl_t* soft_spi_bus_t; */ esp_err_t soft_spi_new(soft_spi_config_t *config, soft_spi_bus_t *bus); - /** * @brief Delete a previously initialized software SPI bus. * @@ -50,7 +47,6 @@ esp_err_t soft_spi_new(soft_spi_config_t *config, soft_spi_bus_t *bus); */ esp_err_t soft_spi_del(soft_spi_bus_t bus); - /** * @brief Send the given bytes on the software SPI bus. * @@ -65,7 +61,6 @@ esp_err_t soft_spi_transfer(soft_spi_bus_t bus, const uint8_t* write_buffer, uint8_t* read_buffer, size_t buf_size); - #ifdef __cplusplus } #endif diff --git a/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/soft_spi.c b/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/soft_spi.c index 25b081d59eb7..2171fb11cd49 100644 --- a/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/soft_spi.c +++ b/examples/peripherals/dedicated_gpio/soft_spi/components/soft_spi/soft_spi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -31,7 +31,6 @@ static portMUX_TYPE g_lock = portMUX_INITIALIZER_UNLOCKED; const char* __attribute__((used)) SOFT_SPI_TAG = "soft_spi"; - struct soft_spi_bus_impl_t { uint32_t clk_bit; uint32_t mosi_bit; @@ -41,7 +40,6 @@ struct soft_spi_bus_impl_t { dedic_gpio_bundle_handle_t in_bundle; }; - esp_err_t soft_spi_new(soft_spi_config_t *config, soft_spi_bus_t *bus) { esp_err_t ret; @@ -121,7 +119,6 @@ esp_err_t soft_spi_new(soft_spi_config_t *config, soft_spi_bus_t *bus) return ret; } - esp_err_t soft_spi_del(soft_spi_bus_t bus) { esp_err_t ret; @@ -135,7 +132,6 @@ esp_err_t soft_spi_del(soft_spi_bus_t bus) return ret; } - esp_err_t soft_spi_transfer(soft_spi_bus_t bus, const uint8_t* write_buffer, uint8_t* read_buffer, size_t buf_size) { esp_err_t ret = ESP_OK; @@ -145,9 +141,9 @@ esp_err_t soft_spi_transfer(soft_spi_bus_t bus, const uint8_t* write_buffer, uin portENTER_CRITICAL(&g_lock); asm_emulate_spi_shift_byte(write_buffer, read_buffer, buf_size, - /* Provide the offset in special dedicated GPIO register for Clock, MOSI and Clock - * respectively */ - bus->clk_bit, bus->mosi_bit, bus->cs_bit, bus->miso_bit); + /* Provide the offset in special dedicated GPIO register for Clock, MOSI and Clock + * respectively */ + bus->clk_bit, bus->mosi_bit, bus->cs_bit, bus->miso_bit); portEXIT_CRITICAL(&g_lock); error: diff --git a/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/include/soft_uart.h b/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/include/soft_uart.h index d35dc6362fa1..0ff0221cd8d6 100644 --- a/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/include/soft_uart.h +++ b/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/include/soft_uart.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -24,7 +24,6 @@ typedef enum { SOFT_UART_BAUD_END } soft_uart_baudrate_t; - /** * @brief Structure defining the configuration for the software UART port */ @@ -34,13 +33,11 @@ typedef struct { soft_uart_baudrate_t baudrate; } soft_uart_config_t; - /** * @brief Abstract type representing a software UART port. */ typedef struct soft_uart_port_impl_t* soft_uart_port_t; - /** * @brief Create and configure the software UART port. * @@ -51,7 +48,6 @@ typedef struct soft_uart_port_impl_t* soft_uart_port_t; */ esp_err_t soft_uart_new(soft_uart_config_t *config, soft_uart_port_t *port); - /** * @brief Delete a previously initialized software UART port. * @@ -61,7 +57,6 @@ esp_err_t soft_uart_new(soft_uart_config_t *config, soft_uart_port_t *port); */ esp_err_t soft_uart_del(soft_uart_port_t port); - /** * @brief Send the given bytes on the software UART port. * diff --git a/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/soft_uart.c b/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/soft_uart.c index 2b0a70912a85..c214ca24365c 100644 --- a/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/soft_uart.c +++ b/examples/peripherals/dedicated_gpio/soft_uart/components/soft_uart/soft_uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -33,7 +33,6 @@ struct soft_uart_port_impl_t { dedic_gpio_bundle_handle_t rx_bundle; }; - esp_err_t soft_uart_new(soft_uart_config_t *config, soft_uart_port_t *port) { esp_err_t ret; @@ -82,7 +81,6 @@ esp_err_t soft_uart_new(soft_uart_config_t *config, soft_uart_port_t *port) } }; - /* Allocate the master port structure now that we need it */ port_impl = malloc(sizeof(struct soft_uart_port_impl_t)); ESP_GOTO_ON_FALSE(port_impl != NULL, ESP_ERR_NO_MEM, error, SOFT_UART_TAG, "No more memory available in the system"); @@ -118,7 +116,6 @@ esp_err_t soft_uart_new(soft_uart_config_t *config, soft_uart_port_t *port) return ret; } - esp_err_t soft_uart_del(soft_uart_port_t port) { esp_err_t ret; @@ -132,7 +129,6 @@ esp_err_t soft_uart_del(soft_uart_port_t port) return ret; } - esp_err_t soft_uart_send(soft_uart_port_t port, const uint8_t* write_buffer, size_t write_size) { esp_err_t ret = ESP_OK; @@ -172,17 +168,17 @@ static uint32_t baudrate_to_cycles(soft_uart_baudrate_t baudrate) * For each delay, subtract a small amount of clock cycles which compensate for the instructions * used to prepare the next bits (loop, shifts, logic...). */ - switch(baudrate) { - case SOFT_UART_115200: // 115200, 8.63us per bit - return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 863)/100 - 20); - case SOFT_UART_230400: // 4.34us per bit - return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 434)/100 - 24); - case SOFT_UART_460800: // 2.17us per bit - return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 217)/100 - 20); - case SOFT_UART_921600: // 1.085us per bit - return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 108)/100 - 23); - default: - assert(false); - return 0; + switch (baudrate) { + case SOFT_UART_115200: // 115200, 8.63us per bit + return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 863) / 100 - 20); + case SOFT_UART_230400: // 4.34us per bit + return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 434) / 100 - 24); + case SOFT_UART_460800: // 2.17us per bit + return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 217) / 100 - 20); + case SOFT_UART_921600: // 1.085us per bit + return ((CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 108) / 100 - 23); + default: + assert(false); + return 0; } } 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 1ef2491e6e8f..27b22cdaa4d9 100644 --- a/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c +++ b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c @@ -68,8 +68,8 @@ static void IRAM_ATTR gpio_isr_handler(void* arg) static void gpio_task_example(void* arg) { uint32_t io_num; - for(;;) { - if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { + for (;;) { + if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num)); } } @@ -125,7 +125,7 @@ void app_main(void) printf("Minimum free heap size: %"PRIu32" bytes\n", esp_get_minimum_free_heap_size()); int cnt = 0; - while(1) { + while (1) { printf("cnt: %d\n", cnt++); vTaskDelay(1000 / portTICK_PERIOD_MS); gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2); diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c index b19d4eea7104..daf1b6a3416f 100644 --- a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -86,7 +86,7 @@ static void matrix_kbd_debounce_timer_callback(TimerHandle_t xTimer) // col lines set to low level dedic_gpio_bundle_write(mkbd->col_bundle, (1 << mkbd->nr_col_gpios) - 1, 0); dedic_gpio_bundle_set_interrupt_and_callback(mkbd->row_bundle, (1 << mkbd->nr_row_gpios) - 1, - DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd); + DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd); } esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handle_t *mkbd_handle) @@ -145,9 +145,9 @@ esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handl // Disable interrupt dedic_gpio_bundle_set_interrupt_and_callback(mkbd->row_bundle, (1 << config->nr_row_gpios) - 1, - DEDIC_GPIO_INTR_NONE, NULL, NULL); + DEDIC_GPIO_INTR_NONE, NULL, NULL); dedic_gpio_bundle_set_interrupt_and_callback(mkbd->col_bundle, (1 << config->nr_col_gpios) - 1, - DEDIC_GPIO_INTR_NONE, NULL, NULL); + DEDIC_GPIO_INTR_NONE, NULL, NULL); // Create a ont-shot os timer, used for key debounce mkbd->debounce_timer = xTimerCreate("kb_debounce", pdMS_TO_TICKS(config->debounce_ms), pdFALSE, mkbd, matrix_kbd_debounce_timer_callback); @@ -200,7 +200,7 @@ esp_err_t matrix_kbd_start(matrix_kbd_handle_t mkbd_handle) // only enable row line interrupt dedic_gpio_bundle_set_interrupt_and_callback(mkbd_handle->row_bundle, (1 << mkbd_handle->nr_row_gpios) - 1, - DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd_handle); + DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd_handle); return ESP_OK; err: @@ -216,9 +216,9 @@ esp_err_t matrix_kbd_stop(matrix_kbd_handle_t mkbd_handle) // Disable interrupt dedic_gpio_bundle_set_interrupt_and_callback(mkbd_handle->row_bundle, (1 << mkbd_handle->nr_row_gpios) - 1, - DEDIC_GPIO_INTR_NONE, NULL, NULL); + DEDIC_GPIO_INTR_NONE, NULL, NULL); dedic_gpio_bundle_set_interrupt_and_callback(mkbd_handle->col_bundle, (1 << mkbd_handle->nr_col_gpios) - 1, - DEDIC_GPIO_INTR_NONE, NULL, NULL); + DEDIC_GPIO_INTR_NONE, NULL, NULL); return ESP_OK; err: diff --git a/examples/peripherals/i2c/i2c_eeprom/main/i2c_eeprom_main.c b/examples/peripherals/i2c/i2c_eeprom/main/i2c_eeprom_main.c index 1b925ad22c82..cab8d281a6dc 100644 --- a/examples/peripherals/i2c/i2c_eeprom/main/i2c_eeprom_main.c +++ b/examples/peripherals/i2c/i2c_eeprom/main/i2c_eeprom_main.c @@ -23,7 +23,7 @@ static void disp_buf(uint8_t *buf, int len) int i; for (i = 0; i < len; i++) { printf("%02x ", buf[i]); - if (( i + 1 ) % 16 == 0) { + if ((i + 1) % 16 == 0) { printf("\n"); } } @@ -59,7 +59,7 @@ void app_main(void) uint8_t read_buf[LENGTH]; ESP_ERROR_CHECK(i2c_eeprom_init(bus_handle, &eeprom_config, &eeprom_handle)); - while(1) { + while (1) { ESP_ERROR_CHECK(i2c_eeprom_write(eeprom_handle, block_addr, buf, LENGTH)); // Needs wait for eeprom hardware done, referring from datasheet i2c_eeprom_wait_idle(eeprom_handle); diff --git a/examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c b/examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c index d9629ba09aab..993548c479d8 100644 --- a/examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c +++ b/examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c @@ -31,12 +31,12 @@ static const char *TAG = "i2c-example"; #define DELAY_TIME_BETWEEN_ITEMS_MS 1000 /*!< delay time between different test items */ #if SOC_I2C_NUM > 1 - #define I2C_SLAVE_SCL_IO CONFIG_I2C_SLAVE_SCL /*!< gpio number for i2c slave clock */ - #define I2C_SLAVE_SDA_IO CONFIG_I2C_SLAVE_SDA /*!< gpio number for i2c slave data */ - #define I2C_SLAVE_NUM I2C_NUMBER(CONFIG_I2C_SLAVE_PORT_NUM) /*!< I2C port number for slave dev */ - #define I2C_SLAVE_TX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave tx buffer size */ - #define I2C_SLAVE_RX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave rx buffer size */ - #define ESP_SLAVE_ADDR CONFIG_I2C_SLAVE_ADDRESS /*!< ESP32 slave address, you can set any 7bit value */ +#define I2C_SLAVE_SCL_IO CONFIG_I2C_SLAVE_SCL /*!< gpio number for i2c slave clock */ +#define I2C_SLAVE_SDA_IO CONFIG_I2C_SLAVE_SDA /*!< gpio number for i2c slave data */ +#define I2C_SLAVE_NUM I2C_NUMBER(CONFIG_I2C_SLAVE_PORT_NUM) /*!< I2C port number for slave dev */ +#define I2C_SLAVE_TX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave tx buffer size */ +#define I2C_SLAVE_RX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave rx buffer size */ +#define ESP_SLAVE_ADDR CONFIG_I2C_SLAVE_ADDRESS /*!< ESP32 slave address, you can set any 7bit value */ #endif #define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< gpio number for I2C master clock */ @@ -280,7 +280,7 @@ static void i2c_test_task(void *arg) ret = i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH); if (ret == ESP_OK) { size = i2c_slave_read_buffer(I2C_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_PERIOD_MS); - } + } if (ret == ESP_ERR_TIMEOUT) { ESP_LOGE(TAG, "I2C Timeout"); } else if (ret == ESP_OK) { diff --git a/examples/peripherals/i2c/i2c_simple/main/i2c_simple_main.c b/examples/peripherals/i2c/i2c_simple/main/i2c_simple_main.c index 6e63a361b116..e95b38cf16a8 100644 --- a/examples/peripherals/i2c/i2c_simple/main/i2c_simple_main.c +++ b/examples/peripherals/i2c/i2c_simple/main/i2c_simple_main.c @@ -78,7 +78,6 @@ static esp_err_t i2c_master_init(void) return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); } - void app_main(void) { uint8_t data[2]; diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c index 08f091b41d25..174c37a37052 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c @@ -24,7 +24,6 @@ #define EXAMPLE_PDM_RX_FREQ_HZ 16000 // I2S PDM RX frequency - static i2s_chan_handle_t i2s_example_init_pdm_rx(void) { i2s_chan_handle_t rx_chan; // I2S rx channel handler @@ -72,7 +71,6 @@ static i2s_chan_handle_t i2s_example_init_pdm_rx(void) return rx_chan; } - void i2s_example_pdm_rx_task(void *args) { int16_t *r_buf = (int16_t *)calloc(1, EXAMPLE_BUFF_SIZE); diff --git a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_tx.c b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_tx.c index 5bee1954b307..332fed0e3e65 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_tx.c +++ b/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_tx.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -25,14 +25,17 @@ #define EXAMPLE_BYTE_NUM_EVERY_TONE (EXAMPLE_TONE_LAST_TIME_MS * EXAMPLE_PDM_TX_FREQ_HZ / 1000) /* The frequency of tones: do, re, mi, fa, so, la, si, in Hz. */ -static const uint32_t tone[3][7] = {{262, 294, 330, 349, 392, 440, 494}, // bass - {523, 587, 659, 698, 784, 880, 988}, // alto - {1046, 1175, 1318, 1397, 1568, 1760, 1976}}; // treble +static const uint32_t tone[3][7] = { + {262, 294, 330, 349, 392, 440, 494}, // bass + {523, 587, 659, 698, 784, 880, 988}, // alto + {1046, 1175, 1318, 1397, 1568, 1760, 1976}, // treble +}; /* Numbered musical notation of 'twinkle twinkle little star' */ static const uint8_t song[28] = {1, 1, 5, 5, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 5, 5, 4, 4, 3, 3, 2, - 5, 5, 4, 4, 3, 3, 2}; + 5, 5, 4, 4, 3, 3, 2 + }; /* Rhythm of 'twinkle twinkle little star', it's repeated in four sections */ static const uint8_t rhythm[7] = {1, 1, 1, 1, 1, 1, 2}; @@ -92,10 +95,10 @@ void i2s_example_pdm_tx_task(void *args) printf("Playing %s `twinkle twinkle little star`\n", tone_name[tone_select]); while (1) { - int tone_point = EXAMPLE_SINE_WAVE_LEN(tone[tone_select][song[cnt]-1]); + int tone_point = EXAMPLE_SINE_WAVE_LEN(tone[tone_select][song[cnt] - 1]); /* Generate the tone buffer */ for (int i = 0; i < tone_point; i++) { - w_buf[i] = (int16_t)((sin(2 * (float)i * CONST_PI / tone_point)) * EXAMPLE_WAVE_AMPLITUDE); + w_buf[i] = (int16_t)((sin(2 * (float)i * CONST_PI / tone_point)) * EXAMPLE_WAVE_AMPLITUDE); } for (int tot_bytes = 0; tot_bytes < EXAMPLE_BYTE_NUM_EVERY_TONE * rhythm[cnt % 7]; tot_bytes += w_bytes) { /* Play the tone */ diff --git a/examples/peripherals/i2s/i2s_basic/i2s_std/main/i2s_std_example_main.c b/examples/peripherals/i2s/i2s_basic/i2s_std/main/i2s_std_example_main.c index 827602298370..ac3caade607e 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_std/main/i2s_std_example_main.c +++ b/examples/peripherals/i2s/i2s_basic/i2s_std/main/i2s_std_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -20,27 +20,27 @@ #define EXAMPLE_I2S_DUPLEX_MODE CONFIG_USE_DUPLEX #if CONFIG_IDF_TARGET_ESP32 - #define EXAMPLE_STD_BCLK_IO1 GPIO_NUM_4 // I2S bit clock io number - #define EXAMPLE_STD_WS_IO1 GPIO_NUM_5 // I2S word select io number - #define EXAMPLE_STD_DOUT_IO1 GPIO_NUM_18 // I2S data out io number - #define EXAMPLE_STD_DIN_IO1 GPIO_NUM_19 // I2S data in io number - #if !EXAMPLE_I2S_DUPLEX_MODE - #define EXAMPLE_STD_BCLK_IO2 GPIO_NUM_22 // I2S bit clock io number - #define EXAMPLE_STD_WS_IO2 GPIO_NUM_23 // I2S word select io number - #define EXAMPLE_STD_DOUT_IO2 GPIO_NUM_25 // I2S data out io number - #define EXAMPLE_STD_DIN_IO2 GPIO_NUM_26 // I2S data in io number - #endif +#define EXAMPLE_STD_BCLK_IO1 GPIO_NUM_4 // I2S bit clock io number +#define EXAMPLE_STD_WS_IO1 GPIO_NUM_5 // I2S word select io number +#define EXAMPLE_STD_DOUT_IO1 GPIO_NUM_18 // I2S data out io number +#define EXAMPLE_STD_DIN_IO1 GPIO_NUM_19 // I2S data in io number +#if !EXAMPLE_I2S_DUPLEX_MODE +#define EXAMPLE_STD_BCLK_IO2 GPIO_NUM_22 // I2S bit clock io number +#define EXAMPLE_STD_WS_IO2 GPIO_NUM_23 // I2S word select io number +#define EXAMPLE_STD_DOUT_IO2 GPIO_NUM_25 // I2S data out io number +#define EXAMPLE_STD_DIN_IO2 GPIO_NUM_26 // I2S data in io number +#endif #else - #define EXAMPLE_STD_BCLK_IO1 GPIO_NUM_2 // I2S bit clock io number - #define EXAMPLE_STD_WS_IO1 GPIO_NUM_3 // I2S word select io number - #define EXAMPLE_STD_DOUT_IO1 GPIO_NUM_4 // I2S data out io number - #define EXAMPLE_STD_DIN_IO1 GPIO_NUM_5 // I2S data in io number - #if !EXAMPLE_I2S_DUPLEX_MODE - #define EXAMPLE_STD_BCLK_IO2 GPIO_NUM_6 // I2S bit clock io number - #define EXAMPLE_STD_WS_IO2 GPIO_NUM_7 // I2S word select io number - #define EXAMPLE_STD_DOUT_IO2 GPIO_NUM_8 // I2S data out io number - #define EXAMPLE_STD_DIN_IO2 GPIO_NUM_9 // I2S data in io number - #endif +#define EXAMPLE_STD_BCLK_IO1 GPIO_NUM_2 // I2S bit clock io number +#define EXAMPLE_STD_WS_IO1 GPIO_NUM_3 // I2S word select io number +#define EXAMPLE_STD_DOUT_IO1 GPIO_NUM_4 // I2S data out io number +#define EXAMPLE_STD_DIN_IO1 GPIO_NUM_5 // I2S data in io number +#if !EXAMPLE_I2S_DUPLEX_MODE +#define EXAMPLE_STD_BCLK_IO2 GPIO_NUM_6 // I2S bit clock io number +#define EXAMPLE_STD_WS_IO2 GPIO_NUM_7 // I2S word select io number +#define EXAMPLE_STD_DOUT_IO2 GPIO_NUM_8 // I2S data out io number +#define EXAMPLE_STD_DIN_IO2 GPIO_NUM_9 // I2S data in io number +#endif #endif #define EXAMPLE_BUFF_SIZE 2048 diff --git a/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/i2s_tdm_example_main.c b/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/i2s_tdm_example_main.c index 38a132a1df87..ad09af1e7891 100644 --- a/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/i2s_tdm_example_main.c +++ b/examples/peripherals/i2s/i2s_basic/i2s_tdm/main/i2s_tdm_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -22,10 +22,10 @@ #define EXAMPLE_TDM_DOUT_IO1 GPIO_NUM_4 // I2S data out io number #define EXAMPLE_TDM_DIN_IO1 GPIO_NUM_5 // I2S data in io number #if !EXAMPLE_I2S_DUPLEX_MODE - #define EXAMPLE_TDM_BCLK_IO2 GPIO_NUM_6 // I2S bit clock io number - #define EXAMPLE_TDM_WS_IO2 GPIO_NUM_7 // I2S word select io number - #define EXAMPLE_TDM_DOUT_IO2 GPIO_NUM_8 // I2S data out io number - #define EXAMPLE_TDM_DIN_IO2 GPIO_NUM_9 // I2S data in io number +#define EXAMPLE_TDM_BCLK_IO2 GPIO_NUM_6 // I2S bit clock io number +#define EXAMPLE_TDM_WS_IO2 GPIO_NUM_7 // I2S word select io number +#define EXAMPLE_TDM_DOUT_IO2 GPIO_NUM_8 // I2S data out io number +#define EXAMPLE_TDM_DIN_IO2 GPIO_NUM_9 // I2S data in io number #endif #define EXAMPLE_BUFF_SIZE 2048 diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/i2s_es7210_record_example.c b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/i2s_es7210_record_example.c index 9bd65e93a73e..bdc10b366cde 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/i2s_es7210_record_example.c +++ b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/main/i2s_es7210_record_example.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -71,7 +71,6 @@ static const char *TAG = "example"; - static i2s_chan_handle_t es7210_i2s_init(void) { i2s_chan_handle_t i2s_rx_chan = NULL; @@ -151,8 +150,8 @@ sdmmc_card_t * mount_sdcard(void) } ESP_LOGI(TAG, "Card size: %lluMB, speed: %dMHz", - (((uint64_t)sdmmc_card->csd.capacity) * sdmmc_card->csd.sector_size) >> 20, - sdmmc_card->max_freq_khz / 1000); + (((uint64_t)sdmmc_card->csd.capacity) * sdmmc_card->csd.sector_size) >> 20, + sdmmc_card->max_freq_khz / 1000); return sdmmc_card; } @@ -217,13 +216,13 @@ static esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan) static int16_t i2s_readraw_buff[4096]; ESP_GOTO_ON_ERROR(i2s_channel_enable(i2s_rx_chan), err, TAG, "error while starting i2s rx channel"); while (wav_written < wav_size) { - if(wav_written % byte_rate < sizeof(i2s_readraw_buff)) { - ESP_LOGI(TAG, "Recording: %"PRIu32"/%ds", wav_written/byte_rate + 1, EXAMPLE_RECORD_TIME_SEC); + if (wav_written % byte_rate < sizeof(i2s_readraw_buff)) { + ESP_LOGI(TAG, "Recording: %"PRIu32"/%ds", wav_written / byte_rate + 1, EXAMPLE_RECORD_TIME_SEC); } size_t bytes_read = 0; /* Read RAW samples from ES7210 */ ESP_GOTO_ON_ERROR(i2s_channel_read(i2s_rx_chan, i2s_readraw_buff, sizeof(i2s_readraw_buff), &bytes_read, - pdMS_TO_TICKS(1000)), err, TAG, "error while reading samples from i2s"); + pdMS_TO_TICKS(1000)), err, TAG, "error while reading samples from i2s"); /* Write the samples to the WAV file */ ESP_GOTO_ON_FALSE(fwrite(i2s_readraw_buff, bytes_read, 1, f), ESP_FAIL, err, TAG, "error while writing samples to wav file"); @@ -250,9 +249,9 @@ void app_main(void) esp_err_t err = record_wav(i2s_rx_chan); /* Unmount SD card */ esp_vfs_fat_sdcard_unmount(EXAMPLE_SD_MOUNT_POINT, sdmmc_card); - if(err == ESP_OK) { + if (err == ESP_OK) { ESP_LOGI(TAG, "Audio was successfully recorded into "EXAMPLE_RECORD_FILE_PATH - ". You can now remove the SD card safely"); + ". You can now remove the SD card safely"); } else { ESP_LOGE(TAG, "Record failed, "EXAMPLE_RECORD_FILE_PATH" on SD card may not be playable."); } diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h index 72835af59230..afab7b4408ae 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/example_config.h @@ -18,7 +18,6 @@ #define EXAMPLE_MIC_GAIN CONFIG_EXAMPLE_MIC_GAIN #endif - #if !defined(CONFIG_EXAMPLE_BSP) /* I2C port and GPIOs */ @@ -47,7 +46,6 @@ #define I2S_DI_IO (GPIO_NUM_3) #endif - #else // CONFIG_EXAMPLE_BSP #include "bsp/esp-bsp.h" #define I2C_NUM BSP_I2C_NUM diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c index 66012e47b17f..3abbb23efd7a 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/main/i2s_es8311_example.c @@ -15,7 +15,6 @@ #include "es8311.h" #include "example_config.h" - static const char *TAG = "i2s_es8311"; static const char err_reason[][30] = {"input param is invalid", "operation timeout" diff --git a/examples/peripherals/lcd/tjpgd/main/pretty_effect.c b/examples/peripherals/lcd/tjpgd/main/pretty_effect.c index b7e557f99019..d12c52bcc1c5 100644 --- a/examples/peripherals/lcd/tjpgd/main/pretty_effect.c +++ b/examples/peripherals/lcd/tjpgd/main/pretty_effect.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -15,11 +15,11 @@ uint16_t *pixels; static inline uint16_t get_bgnd_pixel(int x, int y) { //Get color of the pixel on x,y coords - return (uint16_t) *(pixels + (y * IMAGE_W) + x); + return (uint16_t) * (pixels + (y * IMAGE_W) + x); } //This variable is used to detect the next frame. -static int prev_frame=-1; +static int prev_frame = -1; //Instead of calculating the offsets for each pixel we grab, we pre-calculate the valueswhenever a frame changes, then re-use //these as we go through all the pixels in the frame. This is much, much faster. @@ -31,23 +31,30 @@ static int8_t xcomp[320], ycomp[240]; //is displayed; this is used to go to the next frame of animation. void pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect) { - if (frame!=prev_frame) { + if (frame != prev_frame) { //We need to calculate a new set of offset coefficients. Take some random sines as offsets to make everything //look pretty and fluid-y. - for (int x=0; x<320; x++) xofs[x]=sin(frame*0.15+x*0.06)*4; - for (int y=0; y<240; y++) yofs[y]=sin(frame*0.1+y*0.05)*4; - for (int x=0; x<320; x++) xcomp[x]=sin(frame*0.11+x*0.12)*4; - for (int y=0; y<240; y++) ycomp[y]=sin(frame*0.07+y*0.15)*4; - prev_frame=frame; + for (int x = 0; x < 320; x++) { + xofs[x] = sin(frame * 0.15 + x * 0.06) * 4; + } + for (int y = 0; y < 240; y++) { + yofs[y] = sin(frame * 0.1 + y * 0.05) * 4; + } + for (int x = 0; x < 320; x++) { + xcomp[x] = sin(frame * 0.11 + x * 0.12) * 4; + } + for (int y = 0; y < 240; y++) { + ycomp[y] = sin(frame * 0.07 + y * 0.15) * 4; + } + prev_frame = frame; } - for (int y=line; y #include "esp_err.h" - /** * @brief Calculate the effect for a bunch of lines. * @@ -19,7 +18,6 @@ */ void pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect); - /** * @brief Initialize the effect * diff --git a/examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c b/examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c index 6c961959aa67..ada11d47bb9d 100644 --- a/examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c +++ b/examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c @@ -195,9 +195,9 @@ void app_main(void) printf("1. LEDC fade up to duty = %d\n", LEDC_TEST_DUTY); for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { ledc_set_fade_with_time(ledc_channel[ch].speed_mode, - ledc_channel[ch].channel, LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME); + ledc_channel[ch].channel, LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME); ledc_fade_start(ledc_channel[ch].speed_mode, - ledc_channel[ch].channel, LEDC_FADE_NO_WAIT); + ledc_channel[ch].channel, LEDC_FADE_NO_WAIT); } for (int i = 0; i < LEDC_TEST_CH_NUM; i++) { @@ -207,9 +207,9 @@ void app_main(void) printf("2. LEDC fade down to duty = 0\n"); for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { ledc_set_fade_with_time(ledc_channel[ch].speed_mode, - ledc_channel[ch].channel, 0, LEDC_TEST_FADE_TIME); + ledc_channel[ch].channel, 0, LEDC_TEST_FADE_TIME); ledc_fade_start(ledc_channel[ch].speed_mode, - ledc_channel[ch].channel, LEDC_FADE_NO_WAIT); + ledc_channel[ch].channel, LEDC_FADE_NO_WAIT); } for (int i = 0; i < LEDC_TEST_CH_NUM; i++) { diff --git a/examples/peripherals/ledc/ledc_gamma_curve_fade/main/ledc_gamma_curve_fade_example_main.c b/examples/peripherals/ledc/ledc_gamma_curve_fade/main/ledc_gamma_curve_fade_example_main.c index 24cc72fb7d3f..9277866e8e6f 100644 --- a/examples/peripherals/ledc/ledc_gamma_curve_fade/main/ledc_gamma_curve_fade_example_main.c +++ b/examples/peripherals/ledc/ledc_gamma_curve_fade/main/ledc_gamma_curve_fade_example_main.c @@ -64,7 +64,6 @@ static rgb_channel_config_t rgb_led_2_channels = { .blue_channel = LEDC_CHANNEL_GAMMA_BLUE, }; - // Define some colors R, G, B channel PWM duty cycles #define RGB_TO_DUTY(x) (x * (1 << LEDC_DUTY_RES) / 255) @@ -126,7 +125,6 @@ static rgb_channel_config_t rgb_led_2_channels = { #define BLUEISH_PURPLE_G RGB_TO_DUTY(102) #define BLUEISH_PURPLE_B RGB_TO_DUTY(255) - #if CONFIG_GAMMA_CORRECTION_WITH_LUT // Brightness 0 - 100% gamma correction look up table (gamma = 2.6) // Y = B ^ 2.6 @@ -158,7 +156,6 @@ static uint32_t gamma_correction_calculator(uint32_t duty) } #endif // CONFIG_GAMMA_CORRECTION_WITH_LUT - static void rgb_set_duty_and_update(rgb_channel_config_t rgb_channels, uint32_t target_r_duty, uint32_t target_g_duty, uint32_t target_b_duty) { 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 index d437c7242154..a0726322f3af 100644 --- 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 @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -261,22 +261,22 @@ void app_main(void) // we will use the dead time module to add edge delay, also make gen_high and gen_low complementary for (int i = 0; i < 3; i++) { ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], - MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); + MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], - MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW))); + MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], - MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); + MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], - MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); + MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generators[i][BLDC_MCPWM_GEN_INDEX_LOW], - MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); + MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(generators[i][BLDC_MCPWM_GEN_INDEX_LOW], - MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW))); + MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_LOW], - MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); + MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_LOW], - MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); + MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW))); } ESP_LOGI(TAG, "Setup deadtime"); diff --git a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/app_main.c b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/app_main.c index 1e6f14e5dfe4..e21301adf127 100644 --- a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/app_main.c +++ b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/app_main.c @@ -51,12 +51,11 @@ static const char *TAG = "example_foc"; #define EXAMPLE_FOC_WAVE_FREQ 10 // 50Hz 3 phase AC wave #define EXAMPLE_FOC_WAVE_AMPL 100 // Wave amplitude, Use up-down timer mode, max value should be (EXAMPLE_FOC_MCPWM_PERIOD/2) - void bsp_bridge_driver_init(void) { gpio_config_t drv_en_config = { - .pin_bit_mask = 1ULL << EXAMPLE_FOC_DRV_EN_GPIO, .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << EXAMPLE_FOC_DRV_EN_GPIO, }; ESP_ERROR_CHECK(gpio_config(&drv_en_config)); } diff --git a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.c b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.c index 10ce36844019..ab70f12158d7 100644 --- a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.c +++ b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.c @@ -5,12 +5,11 @@ */ #include "esp_foc.h" - /** * alpha = u - (v + w)sin(30) * (2/3), (2/3): Equal amplitude transformation const * beta = (v - w)cos(30) * (2/3) */ -void foc_clarke_transform (const foc_uvw_coord_t *v_uvw, foc_ab_coord_t *v_ab) +void foc_clarke_transform(const foc_uvw_coord_t *v_uvw, foc_ab_coord_t *v_ab) { const _iq foc_clark_k1_iq = _IQ(2.0 / 3.0); const _iq foc_clark_k2_iq = _IQ(1.0 / 3.0); @@ -20,14 +19,14 @@ void foc_clarke_transform (const foc_uvw_coord_t *v_uvw, foc_ab_coord_t *v_ab) v_ab->beta = _IQmpy(v_uvw->v - v_uvw->w, foc_clark_k3_iq); } -void foc_inverse_clarke_transform (const foc_ab_coord_t *v_ab, foc_uvw_coord_t *v_uvw) +void foc_inverse_clarke_transform(const foc_ab_coord_t *v_ab, foc_uvw_coord_t *v_uvw) { v_uvw->u = v_ab->alpha; v_uvw->v = _IQdiv2(_IQmpy(v_ab->beta, _IQ(M_SQRT3)) - v_ab->alpha); v_uvw->w = -v_uvw->u - v_uvw->v; } -void foc_park_transform (_iq theta_rad, const foc_ab_coord_t *v_ab, foc_dq_coord_t *v_dq) +void foc_park_transform(_iq theta_rad, const foc_ab_coord_t *v_ab, foc_dq_coord_t *v_dq) { _iq sin = _IQsin(theta_rad); _iq cos = _IQcos(theta_rad); @@ -36,7 +35,7 @@ void foc_park_transform (_iq theta_rad, const foc_ab_coord_t *v_ab, foc_dq_coord v_dq->q = _IQmpy(v_ab->beta, cos) - _IQmpy(v_ab->alpha, sin); } -void foc_inverse_park_transform (_iq theta_rad, const foc_dq_coord_t *v_dq, foc_ab_coord_t *v_ab) +void foc_inverse_park_transform(_iq theta_rad, const foc_dq_coord_t *v_dq, foc_ab_coord_t *v_ab) { _iq sin = _IQsin(theta_rad); _iq cos = _IQcos(theta_rad); diff --git a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.h b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.h index c478a80d6655..2bd195276893 100644 --- a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.h +++ b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/foc/esp_foc.h @@ -10,7 +10,6 @@ #define GLOBAL_IQ 18 #include "IQmathLib.h" - // 3-phase uvw coord data type typedef struct foc_uvw_coord { _iq u; // U phase data in IQ type @@ -36,7 +35,7 @@ typedef struct foc_dq_coord { * @param[in] v_uvw data in 3-phase coord to be transformed * @param[out] v_ab output data in alpha-beta coord */ -void foc_clarke_transform (const foc_uvw_coord_t *v_uvw, foc_ab_coord_t *v_ab); +void foc_clarke_transform(const foc_uvw_coord_t *v_uvw, foc_ab_coord_t *v_ab); /** * @brief inverse clark transform, to transform value in alpha_beta system to 3phase uvw system @@ -44,7 +43,7 @@ void foc_clarke_transform (const foc_uvw_coord_t *v_uvw, foc_ab_coord_t *v_ab); * @param[in] v_ab data in alpha-beta coord to be transformed * @param[out] v_uvw output data in 3-phase coord */ -void foc_inverse_clarke_transform (const foc_ab_coord_t *v_ab, foc_uvw_coord_t *v_uvw); +void foc_inverse_clarke_transform(const foc_ab_coord_t *v_ab, foc_uvw_coord_t *v_uvw); /** * @brief park transform, to transform value in static alpha_beta system to rotate d-q system @@ -53,7 +52,7 @@ void foc_inverse_clarke_transform (const foc_ab_coord_t *v_ab, foc_uvw_coord_t * * @param[in] v_ab data in alpha-beta coord to be transformed * @param[out] v_dq output data in dq coord */ -void foc_park_transform (_iq theta_rad, const foc_ab_coord_t *v_ab, foc_dq_coord_t *v_dq); +void foc_park_transform(_iq theta_rad, const foc_ab_coord_t *v_ab, foc_dq_coord_t *v_dq); /** * @brief inverse park transform, to transform value in rotate d-q system to alpha_beta system @@ -62,7 +61,7 @@ void foc_park_transform (_iq theta_rad, const foc_ab_coord_t *v_ab, foc_dq_coord * @param[in] v_dq data in dq coord to be transformed * @param[out] v_ab output data in alpha-beta coord */ -void foc_inverse_park_transform (_iq theta_rad, const foc_dq_coord_t *v_dq, foc_ab_coord_t *v_ab); +void foc_inverse_park_transform(_iq theta_rad, const foc_dq_coord_t *v_dq, foc_ab_coord_t *v_ab); /** * @brief 7-segment svpwm modulation @@ -70,4 +69,4 @@ void foc_inverse_park_transform (_iq theta_rad, const foc_dq_coord_t *v_dq, foc_ * @param v_ab[in] input value in alpha-beta coord * @param out_uvw[out] output modulated pwm duty in IQ type */ -void foc_svpwm_duty_calculate (const foc_ab_coord_t *v_ab, foc_uvw_coord_t *out_uvw); +void foc_svpwm_duty_calculate(const foc_ab_coord_t *v_ab, foc_uvw_coord_t *out_uvw); diff --git a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/svpwm/esp_svpwm.c b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/svpwm/esp_svpwm.c index f05a1643f360..ee0887bc5f31 100644 --- a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/svpwm/esp_svpwm.c +++ b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/main/svpwm/esp_svpwm.c @@ -18,7 +18,6 @@ typedef struct mcpwm_svpwm_ctx { mcpwm_gen_handle_t generators[3][2]; } mcpwm_svpwm_ctx_t; - esp_err_t svpwm_new_inverter(const inverter_config_t *config, inverter_handle_t *ret_inverter) { esp_err_t ret; @@ -51,9 +50,9 @@ esp_err_t svpwm_new_inverter(const inverter_config_t *config, inverter_handle_t for (int i = 0; i < 3; i++) { ESP_GOTO_ON_ERROR(mcpwm_generator_set_actions_on_compare_event(svpwm_dev->generators[i][0], - MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, svpwm_dev->comparators[i], MCPWM_GEN_ACTION_LOW), - MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, svpwm_dev->comparators[i], MCPWM_GEN_ACTION_HIGH), - MCPWM_GEN_COMPARE_EVENT_ACTION_END()), err, TAG, "Set generator actions failed"); + MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, svpwm_dev->comparators[i], MCPWM_GEN_ACTION_LOW), + MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, svpwm_dev->comparators[i], MCPWM_GEN_ACTION_HIGH), + MCPWM_GEN_COMPARE_EVENT_ACTION_END()), err, TAG, "Set generator actions failed"); } for (int i = 0; i < 3; i++) { diff --git a/examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c b/examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c index 7440cfa1ddcc..47dc4b29904b 100644 --- a/examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c +++ b/examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c @@ -67,10 +67,10 @@ void app_main(void) ESP_LOGI(TAG, "Set generator action on timer and compare event"); // go high on counter empty ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generator, - MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); + MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); // go low on compare threshold ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(generator, - MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparator, MCPWM_GEN_ACTION_LOW))); + MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparator, MCPWM_GEN_ACTION_LOW))); ESP_LOGI(TAG, "Enable and start timer"); ESP_ERROR_CHECK(mcpwm_timer_enable(timer)); diff --git a/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c b/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c index 60b6a1c06fe7..c05aa0e00005 100644 --- a/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c +++ b/examples/peripherals/mcpwm/mcpwm_sync/main/mcpwm_sync_example_main.c @@ -176,11 +176,11 @@ void app_main(void) ESP_LOGI(TAG, "Set generator actions on timer and compare event"); for (int i = 0; i < 3; i++) { ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generators[i], - // when the timer value is zero, and is counting up, set output to high - MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); + // when the timer value is zero, and is counting up, set output to high + MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH))); ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(generators[i], - // when compare event happens, and timer is counting up, set output to low - MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW))); + // when compare event happens, and timer is counting up, set output to low + MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW))); } ESP_LOGI(TAG, "Start timers one by one, so they are not synced"); diff --git a/examples/peripherals/rmt/led_strip/main/led_strip_example_main.c b/examples/peripherals/rmt/led_strip/main/led_strip_example_main.c index 65cb57e0669c..ccfbb383b4ea 100644 --- a/examples/peripherals/rmt/led_strip/main/led_strip_example_main.c +++ b/examples/peripherals/rmt/led_strip/main/led_strip_example_main.c @@ -10,7 +10,6 @@ #include "driver/rmt_tx.h" #include "led_strip_encoder.h" - #define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) #define RMT_LED_STRIP_GPIO_NUM 0 diff --git a/examples/peripherals/sdio/host/main/app_main.c b/examples/peripherals/sdio/host/main/app_main.c index 0676d6da94ae..f9542ac01e95 100644 --- a/examples/peripherals/sdio/host/main/app_main.c +++ b/examples/peripherals/sdio/host/main/app_main.c @@ -28,7 +28,6 @@ #include "sdkconfig.h" #include "sdmmc_cmd.h" - #define TIMEOUT_MAX UINT32_MAX #define GPIO_B1 21 @@ -55,7 +54,6 @@ #define PIN_D3 SDMMC_SLOT1_IOMUX_PIN_NUM_D3 #endif - /* sdio host example. @@ -298,7 +296,6 @@ esp_err_t slave_init(essl_handle_t* handle) return ret; } - void slave_power_on(void) { #ifdef SLAVE_PWR_GPIO @@ -338,9 +335,13 @@ static esp_err_t get_intr(essl_handle_t handle, uint32_t* out_raw, uint32_t* out #endif ret = essl_get_intr(handle, out_raw, out_st, TIMEOUT_MAX); - if (ret != ESP_OK) return ret; + if (ret != ESP_OK) { + return ret; + } ret = essl_clear_intr(handle, *out_raw, TIMEOUT_MAX); - if (ret != ESP_OK) return ret; + if (ret != ESP_OK) { + return ret; + } ESP_LOGD(TAG, "intr: %08"PRIX32, *out_raw); return ESP_OK; } diff --git a/examples/peripherals/sdio/slave/main/app_main.c b/examples/peripherals/sdio/slave/main/app_main.c index f78ad9107086..607f3af21ba4 100644 --- a/examples/peripherals/sdio/slave/main/app_main.c +++ b/examples/peripherals/sdio/slave/main/app_main.c @@ -75,8 +75,8 @@ typedef enum { static const char TAG[] = "example_slave"; static int s_job = JOB_IDLE; -DMA_ATTR uint8_t data_to_send[BUFFER_SIZE] = {0x97, 0x84, 0x43, 0x67, 0xc1, 0xdd, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x56, 0x55, 0x44, 0x33 ,0x22, 0x11, 0x00 }; -DMA_ATTR uint8_t data_to_recv[BUFFER_SIZE] = {0x97, 0x84, 0x43, 0x67, 0xc1, 0xdd, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x56, 0x55, 0x44, 0x33 ,0x22, 0x11, 0x00 }; +DMA_ATTR uint8_t data_to_send[BUFFER_SIZE] = {0x97, 0x84, 0x43, 0x67, 0xc1, 0xdd, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x56, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 }; +DMA_ATTR uint8_t data_to_recv[BUFFER_SIZE] = {0x97, 0x84, 0x43, 0x67, 0xc1, 0xdd, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x56, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 }; static const char job_desc[][32] = { "JOB_IDLE", @@ -85,22 +85,27 @@ static const char job_desc[][32] = { "JOB_WRITE_REG", }; - //reset counters of the slave hardware, and clean the receive buffer (normally they should be sent back to the host) static esp_err_t slave_reset(void) { esp_err_t ret; sdio_slave_stop(); ret = sdio_slave_reset(); - if (ret != ESP_OK) return ret; + if (ret != ESP_OK) { + return ret; + } ret = sdio_slave_start(); - if (ret != ESP_OK) return ret; + if (ret != ESP_OK) { + return ret; + } //Since the buffer will not be sent any more, we return them back to receving driver - while(1) { + while (1) { sdio_slave_buf_handle_t handle; ret = sdio_slave_send_get_finished(&handle, 0); - if (ret != ESP_OK) break; + if (ret != ESP_OK) { + break; + } ret = sdio_slave_recv_load_buf(handle); ESP_ERROR_CHECK(ret); } @@ -110,12 +115,14 @@ static esp_err_t slave_reset(void) //sent interrupts to the host in turns static esp_err_t task_hostint(void) { - for(int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { ESP_LOGV(TAG, "send intr: %d", i); sdio_slave_send_host_int(i); //check reset for quick response to RESET signal - if (s_job & JOB_RESET) break; - vTaskDelay(500/portTICK_PERIOD_MS); + if (s_job & JOB_RESET) { + break; + } + vTaskDelay(500 / portTICK_PERIOD_MS); } return ESP_OK; } @@ -127,7 +134,7 @@ static esp_err_t task_write_reg(void) //the host write REG1, the slave should write its registers according to value of REG1 uint8_t read = sdio_slave_read_reg(1); for (int i = 0; i < 60; i++) { - sdio_slave_write_reg(SLAVE_ADDR(i), read + 3*i); + sdio_slave_write_reg(SLAVE_ADDR(i), read + 3 * i); } uint8_t reg[60] = {0}; for (int i = 0; i < 60; i++) { @@ -144,11 +151,11 @@ static esp_err_t task_write_reg(void) static void event_cb(uint8_t pos) { ESP_EARLY_LOGD(TAG, "event: %d", pos); - switch(pos) { - case 0: - s_job = sdio_slave_read_reg(0); - sdio_slave_write_reg(0, JOB_IDLE); - break; + switch (pos) { + case 0: + s_job = sdio_slave_read_reg(0); + sdio_slave_write_reg(0, JOB_IDLE); + break; } } @@ -185,7 +192,7 @@ void app_main(void) sdio_slave_write_reg(0, JOB_IDLE); - for(int i = 0; i < BUFFER_NUM; i++) { + for (int i = 0; i < BUFFER_NUM; i++) { sdio_slave_buf_handle_t handle = sdio_slave_recv_register_buf(buffer[i]); assert(handle != NULL); @@ -194,21 +201,21 @@ void app_main(void) } sdio_slave_set_host_intena(SDIO_SLAVE_HOSTINT_SEND_NEW_PACKET | - SDIO_SLAVE_HOSTINT_BIT0 | - SDIO_SLAVE_HOSTINT_BIT1 | - SDIO_SLAVE_HOSTINT_BIT2 | - SDIO_SLAVE_HOSTINT_BIT3 | - SDIO_SLAVE_HOSTINT_BIT4 | - SDIO_SLAVE_HOSTINT_BIT5 | - SDIO_SLAVE_HOSTINT_BIT6 | - SDIO_SLAVE_HOSTINT_BIT7 - ); + SDIO_SLAVE_HOSTINT_BIT0 | + SDIO_SLAVE_HOSTINT_BIT1 | + SDIO_SLAVE_HOSTINT_BIT2 | + SDIO_SLAVE_HOSTINT_BIT3 | + SDIO_SLAVE_HOSTINT_BIT4 | + SDIO_SLAVE_HOSTINT_BIT5 | + SDIO_SLAVE_HOSTINT_BIT6 | + SDIO_SLAVE_HOSTINT_BIT7 + ); sdio_slave_start(); ESP_LOGI(TAG, EV_STR("slave ready")); - for(;;) { + for (;;) { const TickType_t non_blocking = 0, blocking = portMAX_DELAY; sdio_slave_buf_handle_t recv_queue[BUFFER_NUM]; int packet_size = 0; @@ -266,7 +273,7 @@ void app_main(void) } // if there's finished sending desc, return the buffer to receiving driver - for(;;){ + for (;;) { void* send_args = NULL; ret = sdio_slave_send_get_finished(&send_args, 0); @@ -281,12 +288,12 @@ void app_main(void) } if (s_job != 0) { - for(int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { if (s_job & BIT(i)) { - ESP_LOGI(TAG, EV_STR("%s"), job_desc[i+1]); + ESP_LOGI(TAG, EV_STR("%s"), job_desc[i + 1]); s_job &= ~BIT(i); - switch(BIT(i)) { + switch (BIT(i)) { case JOB_SEND_INT: ret = task_hostint(); ESP_ERROR_CHECK(ret); diff --git a/examples/peripherals/secure_element/atecc608_ecdsa/main/ecdsa_example_main.c b/examples/peripherals/secure_element/atecc608_ecdsa/main/ecdsa_example_main.c index 4f0ad17a4213..516a03c929e2 100644 --- a/examples/peripherals/secure_element/atecc608_ecdsa/main/ecdsa_example_main.c +++ b/examples/peripherals/secure_element/atecc608_ecdsa/main/ecdsa_example_main.c @@ -5,7 +5,7 @@ * * SPDX-License-Identifier: Apache-2.0 * - * SPDX-FileContributor: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2015-2023 Espressif Systems (Shanghai) CO LTD */ /* This is mbedtls boilerplate for library configuration */ @@ -46,7 +46,7 @@ static int configure_mbedtls_rng(void) mbedtls_entropy_init(&entropy); ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, - (const unsigned char *)seed, strlen(seed)); + (const unsigned char *)seed, strlen(seed)); if (ret != 0) { ESP_LOGI(TAG, " failed ! mbedtls_ctr_drbg_seed returned %d", ret); } else { @@ -108,7 +108,7 @@ static int atca_ecdsa_test(void) #ifdef MBEDTLS_ECDSA_SIGN_ALT /* Convert to an mbedtls key */ - ESP_LOGI(TAG, " Using a hardware private key ..." ); + ESP_LOGI(TAG, " Using a hardware private key ..."); ret = atca_mbedtls_pk_init(&pkey, 0); if (ret != 0) { ESP_LOGI(TAG, " failed ! atca_mbedtls_pk_init returned %02x", ret); @@ -116,20 +116,20 @@ static int atca_ecdsa_test(void) } ESP_LOGI(TAG, " ok"); #else - ESP_LOGI(TAG, " Generating a software private key ..." ); + ESP_LOGI(TAG, " Generating a software private key ..."); mbedtls_pk_init(&pkey); ret = mbedtls_pk_setup(&pkey, - mbedtls_pk_info_from_type( MBEDTLS_PK_ECDSA )); + mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA)); if (ret != 0) { - ESP_LOGI(TAG, " failed ! mbedtls_pk_setup returned -0x%04x", -ret ); + ESP_LOGI(TAG, " failed ! mbedtls_pk_setup returned -0x%04x", -ret); goto exit; } - ret = mbedtls_ecp_gen_key( MBEDTLS_ECP_DP_SECP256R1, - mbedtls_pk_ec( pkey ), - mbedtls_ctr_drbg_random, &ctr_drbg ); + ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, + mbedtls_pk_ec(pkey), + mbedtls_ctr_drbg_random, &ctr_drbg); if (ret != 0) { - ESP_LOGI(TAG, " failed ! mbedtls_ecp_gen_key returned -0x%04x", -ret ); + ESP_LOGI(TAG, " failed ! mbedtls_ecp_gen_key returned -0x%04x", -ret); goto exit; } ESP_LOGI(TAG, " ok"); @@ -137,7 +137,7 @@ static int atca_ecdsa_test(void) ESP_LOGI(TAG, " Generating ECDSA Signature..."); ret = mbedtls_pk_sign(&pkey, MBEDTLS_MD_SHA256, hash, 0, buf, MBEDTLS_MPI_MAX_SIZE, &olen, - mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ctr_drbg_random, &ctr_drbg); if (ret != 0) { ESP_LOGI(TAG, " failed ! mbedtls_pk_sign returned -0x%04x", -ret); goto exit; @@ -146,7 +146,7 @@ static int atca_ecdsa_test(void) ESP_LOGI(TAG, " Verifying ECDSA Signature..."); ret = mbedtls_pk_verify(&pkey, MBEDTLS_MD_SHA256, hash, 0, - buf, olen); + buf, olen); if (ret != 0) { ESP_LOGI(TAG, " failed ! mbedtls_pk_verify returned -0x%04x", -ret); goto exit; diff --git a/examples/peripherals/spi_master/hd_eeprom/components/eeprom/spi_eeprom.c b/examples/peripherals/spi_master/hd_eeprom/components/eeprom/spi_eeprom.c index 0c4f488c4452..4d0148239714 100644 --- a/examples/peripherals/spi_master/hd_eeprom/components/eeprom/spi_eeprom.c +++ b/examples/peripherals/spi_master/hd_eeprom/components/eeprom/spi_eeprom.c @@ -19,7 +19,6 @@ #include #include "sdkconfig.h" - #define EEPROM_BUSY_TIMEOUT_MS 5 #define EEPROM_CLK_FREQ (1*1000*1000) //When powered by 3.3V, EEPROM max freq is 1MHz @@ -42,7 +41,7 @@ #define ADD_EWEN 0x60 /// Context (config and data) of the spi_eeprom -struct eeprom_context_t{ +struct eeprom_context_t { eeprom_config_t cfg; ///< Configuration by the caller. spi_device_handle_t spi; ///< SPI device handle SemaphoreHandle_t ready_sem; ///< Semaphore for ready signal @@ -52,7 +51,6 @@ typedef struct eeprom_context_t eeprom_context_t; static const char TAG[] = "eeprom"; - // Workaround: The driver depends on some data in the flash and cannot be placed to DRAM easily for // now. Using the version in LL instead. #define gpio_set_level gpio_set_level_patch @@ -63,7 +61,6 @@ static inline esp_err_t gpio_set_level_patch(gpio_num_t gpio_num, uint32_t level return ESP_OK; } - static esp_err_t eeprom_simple_cmd(eeprom_context_t *ctx, uint16_t cmd) { spi_transaction_t t = { @@ -89,7 +86,9 @@ static esp_err_t eeprom_wait_done(eeprom_context_t* ctx) gpio_intr_disable(ctx->cfg.miso_io); gpio_set_level(ctx->cfg.cs_io, 0); - if (ret != pdTRUE) return ESP_ERR_TIMEOUT; + if (ret != pdTRUE) { + return ESP_ERR_TIMEOUT; + } } else { bool timeout = true; gpio_set_level(ctx->cfg.cs_io, 1); @@ -101,7 +100,9 @@ static esp_err_t eeprom_wait_done(eeprom_context_t* ctx) usleep(1); } gpio_set_level(ctx->cfg.cs_io, 0); - if (timeout) return ESP_ERR_TIMEOUT; + if (timeout) { + return ESP_ERR_TIMEOUT; + } } return ESP_OK; } @@ -144,13 +145,15 @@ esp_err_t spi_eeprom_init(const eeprom_config_t *cfg, eeprom_context_t** out_ctx } eeprom_context_t* ctx = (eeprom_context_t*)malloc(sizeof(eeprom_context_t)); - if (!ctx) return ESP_ERR_NO_MEM; + if (!ctx) { + return ESP_ERR_NO_MEM; + } *ctx = (eeprom_context_t) { .cfg = *cfg, }; - spi_device_interface_config_t devcfg={ + spi_device_interface_config_t devcfg = { .command_bits = 10, .clock_speed_hz = EEPROM_CLK_FREQ, .mode = 0, //SPI mode 0 @@ -167,7 +170,7 @@ esp_err_t spi_eeprom_init(const eeprom_config_t *cfg, eeprom_context_t** out_ctx }; //Attach the EEPROM to the SPI bus err = spi_bus_add_device(ctx->cfg.host, &devcfg, &ctx->spi); - if (err != ESP_OK) { + if (err != ESP_OK) { goto cleanup; } @@ -217,7 +220,9 @@ esp_err_t spi_eeprom_read(eeprom_context_t* ctx, uint8_t addr, uint8_t* out_data .user = ctx, }; esp_err_t err = spi_device_polling_transmit(ctx->spi, &t); - if (err!= ESP_OK) return err; + if (err != ESP_OK) { + return err; + } *out_data = t.rx_data[0]; return ESP_OK; @@ -227,7 +232,9 @@ esp_err_t spi_eeprom_erase(eeprom_context_t* ctx, uint8_t addr) { esp_err_t err; err = spi_device_acquire_bus(ctx->spi, portMAX_DELAY); - if (err != ESP_OK) return err; + if (err != ESP_OK) { + return err; + } err = eeprom_simple_cmd(ctx, CMD_ERASE | (addr & ADDR_MASK)); @@ -243,7 +250,9 @@ esp_err_t spi_eeprom_write(eeprom_context_t* ctx, uint8_t addr, uint8_t data) { esp_err_t err; err = spi_device_acquire_bus(ctx->spi, portMAX_DELAY); - if (err != ESP_OK) return err; + if (err != ESP_OK) { + return err; + } spi_transaction_t t = { .cmd = CMD_WRITE | (addr & ADDR_MASK), @@ -282,7 +291,9 @@ esp_err_t spi_eeprom_erase_all(eeprom_context_t* ctx) esp_err_t err; err = spi_device_acquire_bus(ctx->spi, portMAX_DELAY); - if (err != ESP_OK) return err; + if (err != ESP_OK) { + return err; + } err = eeprom_simple_cmd(ctx, CMD_ERAL | ADD_ERAL); @@ -304,7 +315,9 @@ esp_err_t spi_eeprom_write_all(eeprom_context_t* ctx, uint8_t data) esp_err_t err; err = spi_device_acquire_bus(ctx->spi, portMAX_DELAY); - if (err != ESP_OK) return err; + if (err != ESP_OK) { + return err; + } spi_transaction_t t = { .cmd = CMD_WRAL | ADD_WRAL, diff --git a/examples/peripherals/spi_master/hd_eeprom/main/spi_eeprom_main.c b/examples/peripherals/spi_master/hd_eeprom/main/spi_eeprom_main.c index 071d02a73f4f..e9cdb5cc9cb7 100644 --- a/examples/peripherals/spi_master/hd_eeprom/main/spi_eeprom_main.c +++ b/examples/peripherals/spi_master/hd_eeprom/main/spi_eeprom_main.c @@ -18,7 +18,6 @@ #include "esp_log.h" #include "spi_eeprom.h" - /* This code demonstrates how to use the SPI master half duplex mode to read/write a AT932C46D EEPROM (8-bit mode). */ @@ -70,15 +69,14 @@ # define PIN_NUM_CS 1 #endif - static const char TAG[] = "main"; void app_main(void) { esp_err_t ret; #ifndef CONFIG_EXAMPLE_USE_SPI1_PINS - ESP_LOGI(TAG, "Initializing bus SPI%d...", EEPROM_HOST+1); - spi_bus_config_t buscfg={ + ESP_LOGI(TAG, "Initializing bus SPI%d...", EEPROM_HOST + 1); + spi_bus_config_t buscfg = { .miso_io_num = PIN_NUM_MISO, .mosi_io_num = PIN_NUM_MOSI, .sclk_io_num = PIN_NUM_CLK, diff --git a/examples/peripherals/spi_master/lcd/main/pretty_effect.c b/examples/peripherals/spi_master/lcd/main/pretty_effect.c index 9c6887977ef5..9ccd6fd0206a 100644 --- a/examples/peripherals/spi_master/lcd/main/pretty_effect.c +++ b/examples/peripherals/spi_master/lcd/main/pretty_effect.c @@ -20,11 +20,11 @@ uint16_t *pixels; static inline uint16_t get_bgnd_pixel(int x, int y) { //Get color of the pixel on x,y coords - return (uint16_t) *(pixels + (y * IMAGE_W) + x); + return (uint16_t) * (pixels + (y * IMAGE_W) + x); } //This variable is used to detect the next frame. -static int prev_frame=-1; +static int prev_frame = -1; //Instead of calculating the offsets for each pixel we grab, we pre-calculate the valueswhenever a frame changes, then re-use //these as we go through all the pixels in the frame. This is much, much faster. @@ -36,23 +36,30 @@ static int8_t xcomp[320], ycomp[240]; //is displayed; this is used to go to the next frame of animation. void pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect) { - if (frame!=prev_frame) { + if (frame != prev_frame) { //We need to calculate a new set of offset coefficients. Take some random sines as offsets to make everything //look pretty and fluid-y. - for (int x=0; x<320; x++) xofs[x]=sin(frame*0.15+x*0.06)*4; - for (int y=0; y<240; y++) yofs[y]=sin(frame*0.1+y*0.05)*4; - for (int x=0; x<320; x++) xcomp[x]=sin(frame*0.11+x*0.12)*4; - for (int y=0; y<240; y++) ycomp[y]=sin(frame*0.07+y*0.15)*4; - prev_frame=frame; + for (int x = 0; x < 320; x++) { + xofs[x] = sin(frame * 0.15 + x * 0.06) * 4; + } + for (int y = 0; y < 240; y++) { + yofs[y] = sin(frame * 0.1 + y * 0.05) * 4; + } + for (int x = 0; x < 320; x++) { + xcomp[x] = sin(frame * 0.11 + x * 0.12) * 4; + } + for (int y = 0; y < 240; y++) { + ycomp[y] = sin(frame * 0.07 + y * 0.15) * 4; + } + prev_frame = frame; } - for (int y=line; yuser; + int dc = (int)t->user; gpio_set_level(PIN_NUM_DC, dc); } @@ -250,12 +252,12 @@ uint32_t lcd_get_id(spi_device_handle_t spi) spi_transaction_t t; memset(&t, 0, sizeof(t)); - t.length=8*3; + t.length = 8 * 3; t.flags = SPI_TRANS_USE_RXDATA; t.user = (void*)1; esp_err_t ret = spi_device_polling_transmit(spi, &t); - assert( ret == ESP_OK ); + assert(ret == ESP_OK); // Release bus spi_device_release_bus(spi); @@ -266,12 +268,12 @@ uint32_t lcd_get_id(spi_device_handle_t spi) //Initialize the display void lcd_init(spi_device_handle_t spi) { - int cmd=0; + int cmd = 0; const lcd_init_cmd_t* lcd_init_cmds; //Initialize non-SPI GPIOs gpio_config_t io_conf = {}; - io_conf.pin_bit_mask = ((1ULL<>8; //End Col High - trans[1].tx_data[3]=(320)&0xff; //End Col Low - trans[2].tx_data[0]=0x2B; //Page address set - trans[3].tx_data[0]=ypos>>8; //Start page high - trans[3].tx_data[1]=ypos&0xff; //start page low - trans[3].tx_data[2]=(ypos+PARALLEL_LINES)>>8; //end page high - trans[3].tx_data[3]=(ypos+PARALLEL_LINES)&0xff; //end page low - trans[4].tx_data[0]=0x2C; //memory write - trans[5].tx_buffer=linedata; //finally send the line data - trans[5].length=320*2*8*PARALLEL_LINES; //Data length, in bits - trans[5].flags=0; //undo SPI_TRANS_USE_TXDATA flag + trans[0].tx_data[0] = 0x2A; //Column Address Set + trans[1].tx_data[0] = 0; //Start Col High + trans[1].tx_data[1] = 0; //Start Col Low + trans[1].tx_data[2] = (320) >> 8; //End Col High + trans[1].tx_data[3] = (320) & 0xff; //End Col Low + trans[2].tx_data[0] = 0x2B; //Page address set + trans[3].tx_data[0] = ypos >> 8; //Start page high + trans[3].tx_data[1] = ypos & 0xff; //start page low + trans[3].tx_data[2] = (ypos + PARALLEL_LINES) >> 8; //end page high + trans[3].tx_data[3] = (ypos + PARALLEL_LINES) & 0xff; //end page low + trans[4].tx_data[0] = 0x2C; //memory write + trans[5].tx_buffer = linedata; //finally send the line data + trans[5].length = 320 * 2 * 8 * PARALLEL_LINES; //Data length, in bits + trans[5].flags = 0; //undo SPI_TRANS_USE_TXDATA flag //Queue all transactions. - for (x=0; x<6; x++) { - ret=spi_device_queue_trans(spi, &trans[x], portMAX_DELAY); - assert(ret==ESP_OK); + for (x = 0; x < 6; x++) { + ret = spi_device_queue_trans(spi, &trans[x], portMAX_DELAY); + assert(ret == ESP_OK); } //When we are here, the SPI driver is busy (in the background) getting the transactions sent. That happens @@ -387,20 +388,18 @@ static void send_lines(spi_device_handle_t spi, int ypos, uint16_t *linedata) //send_line_finish, which will wait for the transfers to be done and check their status. } - static void send_line_finish(spi_device_handle_t spi) { spi_transaction_t *rtrans; esp_err_t ret; //Wait for all 6 transactions to be done and get back the results. - for (int x=0; x<6; x++) { - ret=spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY); - assert(ret==ESP_OK); + for (int x = 0; x < 6; x++) { + ret = spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY); + assert(ret == ESP_OK); //We could inspect rtrans now if we received any info back. The LCD is treated as write-only, though. } } - //Simple routine to generate some patterns and send them to the LCD. Don't expect anything too //impressive. Because the SPI driver handles transactions in the background, we can calculate the next line //while the previous one is being sent. @@ -408,25 +407,27 @@ static void display_pretty_colors(spi_device_handle_t spi) { uint16_t *lines[2]; //Allocate memory for the pixel buffers - for (int i=0; i<2; i++) { - lines[i]=heap_caps_malloc(320*PARALLEL_LINES*sizeof(uint16_t), MALLOC_CAP_DMA); - assert(lines[i]!=NULL); + for (int i = 0; i < 2; i++) { + lines[i] = heap_caps_malloc(320 * PARALLEL_LINES * sizeof(uint16_t), MALLOC_CAP_DMA); + assert(lines[i] != NULL); } - int frame=0; + int frame = 0; //Indexes of the line currently being sent to the LCD and the line we're calculating. - int sending_line=-1; - int calc_line=0; + int sending_line = -1; + int calc_line = 0; - while(1) { + while (1) { frame++; - for (int y=0; y<240; y+=PARALLEL_LINES) { + for (int y = 0; y < 240; y += PARALLEL_LINES) { //Calculate a line. pretty_effect_calc_lines(lines[calc_line], y, frame, PARALLEL_LINES); //Finish up the sending process of the previous line, if any - if (sending_line!=-1) send_line_finish(spi); + if (sending_line != -1) { + send_line_finish(spi); + } //Swap sending_line and calc_line - sending_line=calc_line; - calc_line=(calc_line==1)?0:1; + sending_line = calc_line; + calc_line = (calc_line == 1) ? 0 : 1; //Send the line we currently calculated. send_lines(spi, y, lines[sending_line]); //The line set is queued up for sending now; the actual sending happens in the @@ -440,35 +441,35 @@ void app_main(void) { esp_err_t ret; spi_device_handle_t spi; - spi_bus_config_t buscfg={ - .miso_io_num=PIN_NUM_MISO, - .mosi_io_num=PIN_NUM_MOSI, - .sclk_io_num=PIN_NUM_CLK, - .quadwp_io_num=-1, - .quadhd_io_num=-1, - .max_transfer_sz=PARALLEL_LINES*320*2+8 + spi_bus_config_t buscfg = { + .miso_io_num = PIN_NUM_MISO, + .mosi_io_num = PIN_NUM_MOSI, + .sclk_io_num = PIN_NUM_CLK, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = PARALLEL_LINES * 320 * 2 + 8 }; - spi_device_interface_config_t devcfg={ + spi_device_interface_config_t devcfg = { #ifdef CONFIG_LCD_OVERCLOCK - .clock_speed_hz=26*1000*1000, //Clock out at 26 MHz + .clock_speed_hz = 26 * 1000 * 1000, //Clock out at 26 MHz #else - .clock_speed_hz=10*1000*1000, //Clock out at 10 MHz + .clock_speed_hz = 10 * 1000 * 1000, //Clock out at 10 MHz #endif - .mode=0, //SPI mode 0 - .spics_io_num=PIN_NUM_CS, //CS pin - .queue_size=7, //We want to be able to queue 7 transactions at a time - .pre_cb=lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line + .mode = 0, //SPI mode 0 + .spics_io_num = PIN_NUM_CS, //CS pin + .queue_size = 7, //We want to be able to queue 7 transactions at a time + .pre_cb = lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line }; //Initialize the SPI bus - ret=spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO); + ret = spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO); ESP_ERROR_CHECK(ret); //Attach the LCD to the SPI bus - ret=spi_bus_add_device(LCD_HOST, &devcfg, &spi); + ret = spi_bus_add_device(LCD_HOST, &devcfg, &spi); ESP_ERROR_CHECK(ret); //Initialize the LCD lcd_init(spi); //Initialize the effect displayed - ret=pretty_effect_init(); + ret = pretty_effect_init(); ESP_ERROR_CHECK(ret); //Go do nice stuff. diff --git a/examples/peripherals/spi_slave/receiver/main/app_main.c b/examples/peripherals/spi_slave/receiver/main/app_main.c index b6c7c30802ad..1dde14944789 100644 --- a/examples/peripherals/spi_slave/receiver/main/app_main.c +++ b/examples/peripherals/spi_slave/receiver/main/app_main.c @@ -18,7 +18,6 @@ #include "driver/spi_slave.h" #include "driver/gpio.h" - /* SPI receiver (slave) example. @@ -71,7 +70,6 @@ Pins in use. The SPI Master can use the GPIO mux, so feel free to change these i #endif //CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 - #ifdef CONFIG_IDF_TARGET_ESP32 #define RCV_HOST HSPI_HOST @@ -80,48 +78,48 @@ Pins in use. The SPI Master can use the GPIO mux, so feel free to change these i #endif - - //Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high. -void my_post_setup_cb(spi_slave_transaction_t *trans) { +void my_post_setup_cb(spi_slave_transaction_t *trans) +{ gpio_set_level(GPIO_HANDSHAKE, 1); } //Called after transaction is sent/received. We use this to set the handshake line low. -void my_post_trans_cb(spi_slave_transaction_t *trans) { +void my_post_trans_cb(spi_slave_transaction_t *trans) +{ gpio_set_level(GPIO_HANDSHAKE, 0); } //Main application void app_main(void) { - int n=0; + int n = 0; esp_err_t ret; //Configuration for the SPI bus - spi_bus_config_t buscfg={ - .mosi_io_num=GPIO_MOSI, - .miso_io_num=GPIO_MISO, - .sclk_io_num=GPIO_SCLK, + spi_bus_config_t buscfg = { + .mosi_io_num = GPIO_MOSI, + .miso_io_num = GPIO_MISO, + .sclk_io_num = GPIO_SCLK, .quadwp_io_num = -1, .quadhd_io_num = -1, }; //Configuration for the SPI slave interface - spi_slave_interface_config_t slvcfg={ - .mode=0, - .spics_io_num=GPIO_CS, - .queue_size=3, - .flags=0, - .post_setup_cb=my_post_setup_cb, - .post_trans_cb=my_post_trans_cb + spi_slave_interface_config_t slvcfg = { + .mode = 0, + .spics_io_num = GPIO_CS, + .queue_size = 3, + .flags = 0, + .post_setup_cb = my_post_setup_cb, + .post_trans_cb = my_post_trans_cb }; //Configuration for the handshake line - gpio_config_t io_conf={ - .intr_type=GPIO_INTR_DISABLE, - .mode=GPIO_MODE_OUTPUT, - .pin_bit_mask=(1<= sizeof(sendbuf)) { printf("Data truncated\n"); } - t.length=sizeof(sendbuf)*8; - t.tx_buffer=sendbuf; - t.rx_buffer=recvbuf; + t.length = sizeof(sendbuf) * 8; + t.tx_buffer = sendbuf; + t.rx_buffer = recvbuf; //Wait for slave to be ready for next byte before sending xSemaphoreTake(rdySem, portMAX_DELAY); //Wait until slave is ready - ret=spi_device_transmit(handle, &t); + ret = spi_device_transmit(handle, &t); printf("Received: %s\n", recvbuf); n++; } //Never reached. - ret=spi_bus_remove_device(handle); - assert(ret==ESP_OK); + ret = spi_bus_remove_device(handle); + assert(ret == ESP_OK); } diff --git a/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c b/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c index 177344bdde05..d34696ca4b52 100644 --- a/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c @@ -53,14 +53,14 @@ static void init_driver(spi_device_handle_t *out_spi, essl_handle_t *out_essl) ESP_ERROR_CHECK(spi_bus_initialize(HOST_ID, &bus_cfg, SPI_DMA_CH_AUTO)); spi_device_interface_config_t dev_cfg = { - .clock_speed_hz = 1 * 1 * 1000, - .flags = SPI_DEVICE_HALFDUPLEX, - .spics_io_num = GPIO_CS, - .queue_size = 16, - .command_bits = 8, - .address_bits = 8, - .dummy_bits = 8, - .mode = 0 + .clock_speed_hz = 1 * 1 * 1000, + .flags = SPI_DEVICE_HALFDUPLEX, + .spics_io_num = GPIO_CS, + .queue_size = 16, + .command_bits = 8, + .address_bits = 8, + .dummy_bits = 8, + .mode = 0 }; ESP_ERROR_CHECK(spi_bus_add_device(HOST_ID, &dev_cfg, &spi)); *out_spi = spi; @@ -88,7 +88,7 @@ static esp_err_t receiver(essl_handle_t essl) while (n--) { size_t actual_rx_length = 0; - ret = essl_get_packet(essl, recv_buf, TRANSACTION_LEN/2, &actual_rx_length, portMAX_DELAY); + ret = essl_get_packet(essl, recv_buf, TRANSACTION_LEN / 2, &actual_rx_length, portMAX_DELAY); if (ret == ESP_OK || ret == ESP_ERR_NOT_FINISHED) { ESP_LOGI("Receiver", "%d bytes are actually received:", actual_rx_length); ESP_LOG_BUFFER_HEX("Receiver", recv_buf, actual_rx_length); @@ -124,7 +124,7 @@ static esp_err_t sender(essl_handle_t essl) int n = EXAMPLE_CYCLES; while (n--) { for (int i = 0; i < TRANSACTION_LEN; i++) { - send_buf[i] = data+i; + send_buf[i] = data + i; } ret = essl_send_packet(essl, send_buf, TRANSACTION_LEN, portMAX_DELAY); diff --git a/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c b/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c index 9e6d1ef57833..8b7160abe182 100644 --- a/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c @@ -29,7 +29,6 @@ #define SLAVE_READY_FLAG 0x88 #define READY_FLAG_REG 0 - struct trans_link_s { spi_slave_hd_data_t trans; struct trans_link_s *next; @@ -41,7 +40,6 @@ typedef struct trans_link_s trans_link_t; trans_link_t *tx_curr_trans; trans_link_t *rx_curr_trans; - static void init_slave_hd(void) { spi_bus_config_t bus_cfg = {}; @@ -81,7 +79,7 @@ static esp_err_t create_transaction_pool(uint8_t **data_buf, trans_link_t *trans //link the recycling transaction descriptors if (i != QUEUE_SIZE - 1) { - trans_link[i].next = &trans_link[i+1]; + trans_link[i].next = &trans_link[i + 1]; } else { trans_link[i].next = &trans_link[0]; } @@ -100,7 +98,7 @@ static void prepare_tx_data(trans_link_t *tx_trans) */ uint8_t data = rand() % 50; tx_trans->trans.len = TRANSACTION_LEN; - for(int i = 0; i < tx_trans->trans.len; i++) { + for (int i = 0; i < tx_trans->trans.len; i++) { tx_trans->trans.data[i] = data + i; } tx_trans->recycled = 0; diff --git a/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c b/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c index eb20b9818ae3..f5571b09e296 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c @@ -68,7 +68,6 @@ static const char TAG[] = "SEG_MASTER"; - static void get_spi_bus_default_config(spi_bus_config_t *bus_cfg) { memset(bus_cfg, 0x0, sizeof(spi_bus_config_t)); @@ -85,7 +84,7 @@ static void get_spi_bus_default_config(spi_bus_config_t *bus_cfg) static void get_spi_device_default_config(spi_device_interface_config_t *dev_cfg) { memset(dev_cfg, 0x0, sizeof(spi_device_interface_config_t)); - dev_cfg->clock_speed_hz = 10*1000*1000; + dev_cfg->clock_speed_hz = 10 * 1000 * 1000; dev_cfg->mode = 0; dev_cfg->spics_io_num = GPIO_CS; dev_cfg->cs_ena_pretrans = 0; @@ -114,7 +113,6 @@ static void init_master_hd(spi_device_handle_t* out_spi) ESP_ERROR_CHECK(spi_bus_add_device(MASTER_HOST, &dev_cfg, out_spi)); } - //-------------------------------Function used for Master-Slave Synchronization---------------------------// //Wait for Slave to init the shared registers for its configurations, see the Helper Macros above static esp_err_t wait_for_slave_ready(spi_device_handle_t spi) diff --git a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c index b4345efdef93..18f61b6c0de8 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c @@ -66,7 +66,6 @@ //Value in these 4 registers indicates number of the RX buffer that Slave has loaded to the DMA #define SLAVE_RX_READY_BUF_NUM_REG 16 - static const char TAG[] = "SEG_SLAVE"; /* Used for Master-Slave synchronization */ @@ -75,7 +74,6 @@ static uint32_t s_rx_ready_buf_num; //See ``cb_set_rx_ready_buf_num()`` static uint32_t s_tx_data_id; - //-------------------------------Function used for Master-Slave Synchronization---------------------------// /** * NOTE: Only if all the counters are in same size (here uint32_t), the calculation is safe (when the shared register overflows). diff --git a/examples/peripherals/temperature_sensor/temp_sensor_monitor/main/temp_sensor_monitor_main.c b/examples/peripherals/temperature_sensor/temp_sensor_monitor/main/temp_sensor_monitor_main.c index 34e5dfbf2e29..96e4e981c20d 100644 --- a/examples/peripherals/temperature_sensor/temp_sensor_monitor/main/temp_sensor_monitor_main.c +++ b/examples/peripherals/temperature_sensor/temp_sensor_monitor/main/temp_sensor_monitor_main.c @@ -25,7 +25,6 @@ void app_main(void) temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50); ESP_ERROR_CHECK(temperature_sensor_install(&temp_sensor_config, &temp_sensor)); - temperature_sensor_event_callbacks_t cbs = { .on_threshold = temp_sensor_monitor_cbs, }; diff --git a/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c b/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c index 697cf501de31..90090deb714f 100644 --- a/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c +++ b/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c @@ -102,7 +102,6 @@ void app_main(void) user_data->timer_idx = 0; user_data->alarm_value = TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ; - ESP_LOGI(TAG, "Init timer with auto-reload"); user_data->auto_reload = true; example_tg_timer_init(user_data); diff --git a/examples/peripherals/touch_sensor/touch_element/touch_button/main/touch_button_example_main.c b/examples/peripherals/touch_sensor/touch_element/touch_button/main/touch_button_example_main.c index 1456c0857124..a957a73d1e65 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_button/main/touch_button_example_main.c +++ b/examples/peripherals/touch_sensor/touch_element/touch_button/main/touch_button_example_main.c @@ -108,8 +108,8 @@ void app_main(void) ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i])); /* Subscribe touch button events (On Press, On Release, On LongPress) */ ESP_ERROR_CHECK(touch_button_subscribe_event(button_handle[i], - TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, - (void *)channel_array[i])); + TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, + (void *)channel_array[i])); #ifdef CONFIG_TOUCH_ELEM_EVENT /* Set EVENT as the dispatch method */ ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT)); diff --git a/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/main/waterproof_example_main.c b/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/main/waterproof_example_main.c index 631670de8db8..86b3ec21fce8 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/main/waterproof_example_main.c +++ b/examples/peripherals/touch_sensor/touch_element/touch_element_waterproof/main/waterproof_example_main.c @@ -75,8 +75,8 @@ void app_main(void) ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i])); /* Subscribe touch button event(Press, Release, LongPress) */ ESP_ERROR_CHECK(touch_button_subscribe_event(button_handle[i], - TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, - (void *)channel_array[i])); + TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, + (void *)channel_array[i])); /* Button set dispatch method */ ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT)); #ifdef CONFIG_TOUCH_WATERPROOF_GUARD_ENABLE diff --git a/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/main/touch_elements_example_main.c b/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/main/touch_elements_example_main.c index 7b8396527bec..4d7a013b57a1 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/main/touch_elements_example_main.c +++ b/examples/peripherals/touch_sensor/touch_element/touch_elements_combination/main/touch_elements_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -109,8 +109,8 @@ void button_example_init(void) ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i])); /* Subscribe touch button events (On Press, On Release, On LongPress) */ ESP_ERROR_CHECK(touch_button_subscribe_event(button_handle[i], - TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, - (void *)button_channel_array[i])); + TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, + (void *)button_channel_array[i])); /* Set EVENT as the dispatch method */ ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT)); /* Set LongPress event trigger threshold time */ @@ -134,7 +134,7 @@ void slider_example_init(void) ESP_ERROR_CHECK(touch_slider_create(&slider_config, &slider_handle)); /* Subscribe touch slider events (On Press, On Release, On Calculation) */ ESP_ERROR_CHECK(touch_slider_subscribe_event(slider_handle, - TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_CALCULATION, NULL)); + TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_CALCULATION, NULL)); /* Set EVENT as the dispatch method */ ESP_ERROR_CHECK(touch_slider_set_dispatch_method(slider_handle, TOUCH_ELEM_DISP_EVENT)); ESP_LOGI(TAG, "Touch slider created"); diff --git a/examples/peripherals/touch_sensor/touch_element/touch_matrix/main/touch_matrix_example_main.c b/examples/peripherals/touch_sensor/touch_element/touch_matrix/main/touch_matrix_example_main.c index de6c09216015..a8d248a09222 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_matrix/main/touch_matrix_example_main.c +++ b/examples/peripherals/touch_sensor/touch_element/touch_matrix/main/touch_matrix_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -60,13 +60,13 @@ static void matrix_handler_task(void *arg) const touch_matrix_message_t *matrix_message = touch_matrix_get_message(&element_message); if (matrix_message->event == TOUCH_MATRIX_EVT_ON_PRESS) { ESP_LOGI(TAG, "Matrix Press, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, matrix_message->position.x_axis, - matrix_message->position.y_axis, matrix_message->position.index); + matrix_message->position.y_axis, matrix_message->position.index); } else if (matrix_message->event == TOUCH_MATRIX_EVT_ON_RELEASE) { ESP_LOGI(TAG, "Matrix Release, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, matrix_message->position.x_axis, - matrix_message->position.y_axis, matrix_message->position.index); + matrix_message->position.y_axis, matrix_message->position.index); } else if (matrix_message->event == TOUCH_MATRIX_EVT_ON_LONGPRESS) { ESP_LOGI(TAG, "Matrix LongPress, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, matrix_message->position.x_axis, - matrix_message->position.y_axis, matrix_message->position.index); + matrix_message->position.y_axis, matrix_message->position.index); } } } @@ -80,13 +80,13 @@ void matrix_handler(touch_matrix_handle_t out_handle, touch_matrix_message_t *ou } if (out_message->event == TOUCH_MATRIX_EVT_ON_PRESS) { ESP_LOGI(TAG, "Matrix Press, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, out_message->position.x_axis, - out_message->position.y_axis, out_message->position.index); + out_message->position.y_axis, out_message->position.index); } else if (out_message->event == TOUCH_MATRIX_EVT_ON_RELEASE) { ESP_LOGI(TAG, "Matrix Release, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, out_message->position.x_axis, - out_message->position.y_axis, out_message->position.index); + out_message->position.y_axis, out_message->position.index); } else if (out_message->event == TOUCH_MATRIX_EVT_ON_LONGPRESS) { ESP_LOGI(TAG, "Matrix LongPress, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, out_message->position.x_axis, - out_message->position.y_axis, out_message->position.index); + out_message->position.y_axis, out_message->position.index); } } #endif @@ -113,7 +113,7 @@ void app_main(void) ESP_ERROR_CHECK(touch_matrix_create(&matrix_config, &matrix_handle)); /* Subscribe touch matrix events (On Press, On Release, On LongPress) */ ESP_ERROR_CHECK(touch_matrix_subscribe_event(matrix_handle, - TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, NULL)); + TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, NULL)); #ifdef CONFIG_TOUCH_ELEM_EVENT /* Set EVENT as the dispatch method */ ESP_ERROR_CHECK(touch_matrix_set_dispatch_method(matrix_handle, TOUCH_ELEM_DISP_EVENT)); diff --git a/examples/peripherals/touch_sensor/touch_element/touch_slider/main/touch_slider_example_main.c b/examples/peripherals/touch_sensor/touch_element/touch_slider/main/touch_slider_example_main.c index 4df27f288257..4257adcc83a5 100644 --- a/examples/peripherals/touch_sensor/touch_element/touch_slider/main/touch_slider_example_main.c +++ b/examples/peripherals/touch_sensor/touch_element/touch_slider/main/touch_slider_example_main.c @@ -99,7 +99,7 @@ void app_main(void) ESP_ERROR_CHECK(touch_slider_create(&slider_config, &slider_handle)); /* Subscribe touch slider events (On Press, On Release, On Calculation) */ ESP_ERROR_CHECK(touch_slider_subscribe_event(slider_handle, - TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_CALCULATION, NULL)); + TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_CALCULATION, NULL)); #ifdef CONFIG_TOUCH_ELEM_EVENT /* Set EVENT as the dispatch method */ ESP_ERROR_CHECK(touch_slider_set_dispatch_method(slider_handle, TOUCH_ELEM_DISP_EVENT)); diff --git a/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/main/tp_read_main.c b/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/main/tp_read_main.c index 59ba5955e3c9..0df84f9673f2 100644 --- a/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/main/tp_read_main.c +++ b/examples/peripherals/touch_sensor/touch_sensor_v1/touch_pad_read/main/tp_read_main.c @@ -47,7 +47,7 @@ static void tp_example_read_task(void *pvParameter) static void tp_example_touch_pad_init(void) { - for (int i = 0;i< TOUCH_PAD_MAX;i++) { + for (int i = 0; i < TOUCH_PAD_MAX; i++) { touch_pad_config(i, TOUCH_THRESH_NO_USE); } } diff --git a/examples/peripherals/twai/twai_network/twai_network_listen_only/main/twai_network_example_listen_only_main.c b/examples/peripherals/twai/twai_network/twai_network_listen_only/main/twai_network_example_listen_only_main.c index 3e2e02994b7a..dcfd828740b2 100644 --- a/examples/peripherals/twai/twai_network/twai_network_listen_only/main/twai_network_example_listen_only_main.c +++ b/examples/peripherals/twai/twai_network/twai_network_listen_only/main/twai_network_example_listen_only_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -43,11 +43,12 @@ static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS(); //Set TX queue length to 0 due to listen only mode static const twai_general_config_t g_config = {.mode = TWAI_MODE_LISTEN_ONLY, - .tx_io = TX_GPIO_NUM, .rx_io = RX_GPIO_NUM, - .clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, - .tx_queue_len = 0, .rx_queue_len = 5, - .alerts_enabled = TWAI_ALERT_NONE, - .clkout_divider = 0}; + .tx_io = TX_GPIO_NUM, .rx_io = RX_GPIO_NUM, + .clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, + .tx_queue_len = 0, .rx_queue_len = 5, + .alerts_enabled = TWAI_ALERT_NONE, + .clkout_divider = 0 + }; static SemaphoreHandle_t rx_sem; diff --git a/examples/peripherals/twai/twai_network/twai_network_master/main/twai_network_example_master_main.c b/examples/peripherals/twai/twai_network/twai_network_master/main/twai_network_example_master_main.c index 5d1b4b0c459c..820bcfb7704c 100644 --- a/examples/peripherals/twai/twai_network/twai_network_master/main/twai_network_example_master_main.c +++ b/examples/peripherals/twai/twai_network/twai_network_master/main/twai_network_example_master_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -64,11 +64,14 @@ static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL); static const twai_message_t ping_message = {.identifier = ID_MASTER_PING, .data_length_code = 0, - .ss = 1, .data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}}; + .ss = 1, .data = {0, 0, 0, 0, 0, 0, 0, 0} + }; static const twai_message_t start_message = {.identifier = ID_MASTER_START_CMD, .data_length_code = 0, - .data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}}; + .data = {0, 0, 0, 0, 0, 0, 0, 0} + }; static const twai_message_t stop_message = {.identifier = ID_MASTER_STOP_CMD, .data_length_code = 0, - .data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}}; + .data = {0, 0, 0, 0, 0, 0, 0, 0} + }; static QueueHandle_t tx_task_queue; static QueueHandle_t rx_task_queue; diff --git a/examples/peripherals/twai/twai_network/twai_network_slave/main/twai_network_example_slave_main.c b/examples/peripherals/twai/twai_network/twai_network_slave/main/twai_network_example_slave_main.c index 30a022cd0578..73b79e340704 100644 --- a/examples/peripherals/twai/twai_network/twai_network_slave/main/twai_network_example_slave_main.c +++ b/examples/peripherals/twai/twai_network/twai_network_slave/main/twai_network_example_slave_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -64,12 +64,15 @@ static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPI static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS(); static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); static const twai_message_t ping_resp = {.identifier = ID_SLAVE_PING_RESP, .data_length_code = 0, - .data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}}; + .data = {0, 0, 0, 0, 0, 0, 0, 0} + }; static const twai_message_t stop_resp = {.identifier = ID_SLAVE_STOP_RESP, .data_length_code = 0, - .data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}}; + .data = {0, 0, 0, 0, 0, 0, 0, 0} + }; //Data bytes of data message will be initialized in the transmit task static twai_message_t data_message = {.identifier = ID_SLAVE_DATA, .data_length_code = 4, - .data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}}; + .data = {0, 0, 0, 0, 0, 0, 0, 0} + }; static QueueHandle_t tx_task_queue; static QueueHandle_t rx_task_queue; @@ -230,7 +233,6 @@ void app_main(void) vTaskDelay(pdMS_TO_TICKS(1000)); } - //Create semaphores and tasks tx_task_queue = xQueueCreate(1, sizeof(tx_task_action_t)); rx_task_queue = xQueueCreate(1, sizeof(rx_task_action_t)); diff --git a/examples/peripherals/uart/uart_async_rxtxtasks/main/uart_async_rxtxtasks_main.c b/examples/peripherals/uart/uart_async_rxtxtasks/main/uart_async_rxtxtasks_main.c index 3a5402f2374e..94c18378abf6 100644 --- a/examples/peripherals/uart/uart_async_rxtxtasks/main/uart_async_rxtxtasks_main.c +++ b/examples/peripherals/uart/uart_async_rxtxtasks/main/uart_async_rxtxtasks_main.c @@ -19,7 +19,8 @@ static const int RX_BUF_SIZE = 1024; #define TXD_PIN (GPIO_NUM_4) #define RXD_PIN (GPIO_NUM_5) -void init(void) { +void init(void) +{ const uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, @@ -56,7 +57,7 @@ static void rx_task(void *arg) { static const char *RX_TASK_TAG = "RX_TASK"; esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO); - uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE+1); + uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE + 1); while (1) { const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 1000 / portTICK_PERIOD_MS); if (rxBytes > 0) { @@ -71,6 +72,6 @@ static void rx_task(void *arg) void app_main(void) { init(); - xTaskCreate(rx_task, "uart_rx_task", 1024*2, NULL, configMAX_PRIORITIES, NULL); - xTaskCreate(tx_task, "uart_tx_task", 1024*2, NULL, configMAX_PRIORITIES-1, NULL); + xTaskCreate(rx_task, "uart_rx_task", 1024 * 2, NULL, configMAX_PRIORITIES, NULL); + xTaskCreate(tx_task, "uart_tx_task", 1024 * 2, NULL, configMAX_PRIORITIES - 1, NULL); } diff --git a/examples/peripherals/uart/uart_echo_rs485/main/rs485_example.c b/examples/peripherals/uart/uart_echo_rs485/main/rs485_example.c index 8a64c7841d55..63ff45e30c08 100644 --- a/examples/peripherals/uart/uart_echo_rs485/main/rs485_example.c +++ b/examples/peripherals/uart/uart_echo_rs485/main/rs485_example.c @@ -98,7 +98,7 @@ static void echo_task(void *arg) ESP_LOGI(TAG, "UART start recieve loop.\r"); echo_send(uart_num, "Start RS485 UART test.\r\n", 24); - while(1) { + while (1) { //Read data from UART int len = uart_read_bytes(uart_num, data, BUF_SIZE, PACKET_READ_TICS); diff --git a/examples/peripherals/uart/uart_events/main/uart_events_example_main.c b/examples/peripherals/uart/uart_events/main/uart_events_example_main.c index dcf2614b149c..d5200164bdad 100644 --- a/examples/peripherals/uart/uart_events/main/uart_events_example_main.c +++ b/examples/peripherals/uart/uart_events/main/uart_events_example_main.c @@ -41,74 +41,74 @@ static void uart_event_task(void *pvParameters) uart_event_t event; size_t buffered_size; uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE); - for(;;) { + for (;;) { //Waiting for UART event. - if(xQueueReceive(uart0_queue, (void * )&event, (TickType_t)portMAX_DELAY)) { + if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY)) { bzero(dtmp, RD_BUF_SIZE); ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM); - switch(event.type) { - //Event of UART receving data - /*We'd better handler data event fast, there would be much more data events than - other types of events. If we take too much time on data event, the queue might - be full.*/ - case UART_DATA: - ESP_LOGI(TAG, "[UART DATA]: %d", event.size); - uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY); - ESP_LOGI(TAG, "[DATA EVT]:"); - uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size); - break; - //Event of HW FIFO overflow detected - case UART_FIFO_OVF: - ESP_LOGI(TAG, "hw fifo overflow"); - // If fifo overflow happened, you should consider adding flow control for your application. - // The ISR has already reset the rx FIFO, - // As an example, we directly flush the rx buffer here in order to read more data. + switch (event.type) { + //Event of UART receving data + /*We'd better handler data event fast, there would be much more data events than + other types of events. If we take too much time on data event, the queue might + be full.*/ + case UART_DATA: + ESP_LOGI(TAG, "[UART DATA]: %d", event.size); + uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY); + ESP_LOGI(TAG, "[DATA EVT]:"); + uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size); + break; + //Event of HW FIFO overflow detected + case UART_FIFO_OVF: + ESP_LOGI(TAG, "hw fifo overflow"); + // If fifo overflow happened, you should consider adding flow control for your application. + // The ISR has already reset the rx FIFO, + // As an example, we directly flush the rx buffer here in order to read more data. + uart_flush_input(EX_UART_NUM); + xQueueReset(uart0_queue); + break; + //Event of UART ring buffer full + case UART_BUFFER_FULL: + ESP_LOGI(TAG, "ring buffer full"); + // If buffer full happened, you should consider increasing your buffer size + // As an example, we directly flush the rx buffer here in order to read more data. + uart_flush_input(EX_UART_NUM); + xQueueReset(uart0_queue); + break; + //Event of UART RX break detected + case UART_BREAK: + ESP_LOGI(TAG, "uart rx break"); + break; + //Event of UART parity check error + case UART_PARITY_ERR: + ESP_LOGI(TAG, "uart parity error"); + break; + //Event of UART frame error + case UART_FRAME_ERR: + ESP_LOGI(TAG, "uart frame error"); + break; + //UART_PATTERN_DET + case UART_PATTERN_DET: + uart_get_buffered_data_len(EX_UART_NUM, &buffered_size); + int pos = uart_pattern_pop_pos(EX_UART_NUM); + ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size); + if (pos == -1) { + // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not + // record the position. We should set a larger queue size. + // As an example, we directly flush the rx buffer here. uart_flush_input(EX_UART_NUM); - xQueueReset(uart0_queue); - break; - //Event of UART ring buffer full - case UART_BUFFER_FULL: - ESP_LOGI(TAG, "ring buffer full"); - // If buffer full happened, you should consider increasing your buffer size - // As an example, we directly flush the rx buffer here in order to read more data. - uart_flush_input(EX_UART_NUM); - xQueueReset(uart0_queue); - break; - //Event of UART RX break detected - case UART_BREAK: - ESP_LOGI(TAG, "uart rx break"); - break; - //Event of UART parity check error - case UART_PARITY_ERR: - ESP_LOGI(TAG, "uart parity error"); - break; - //Event of UART frame error - case UART_FRAME_ERR: - ESP_LOGI(TAG, "uart frame error"); - break; - //UART_PATTERN_DET - case UART_PATTERN_DET: - uart_get_buffered_data_len(EX_UART_NUM, &buffered_size); - int pos = uart_pattern_pop_pos(EX_UART_NUM); - ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size); - if (pos == -1) { - // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not - // record the position. We should set a larger queue size. - // As an example, we directly flush the rx buffer here. - uart_flush_input(EX_UART_NUM); - } else { - uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS); - uint8_t pat[PATTERN_CHR_NUM + 1]; - memset(pat, 0, sizeof(pat)); - uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS); - ESP_LOGI(TAG, "read data: %s", dtmp); - ESP_LOGI(TAG, "read pat : %s", pat); - } - break; - //Others - default: - ESP_LOGI(TAG, "uart event type: %d", event.type); - break; + } else { + uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS); + uint8_t pat[PATTERN_CHR_NUM + 1]; + memset(pat, 0, sizeof(pat)); + uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "read data: %s", dtmp); + ESP_LOGI(TAG, "read pat : %s", pat); + } + break; + //Others + default: + ESP_LOGI(TAG, "uart event type: %d", event.type); + break; } } } diff --git a/examples/peripherals/uart/uart_repl/main/uart_repl_example_main.c b/examples/peripherals/uart/uart_repl/main/uart_repl_example_main.c index 9e70780aac9c..efe04475287e 100644 --- a/examples/peripherals/uart/uart_repl/main/uart_repl_example_main.c +++ b/examples/peripherals/uart/uart_repl/main/uart_repl_example_main.c @@ -84,7 +84,6 @@ static void configure_uarts(void) ESP_ERROR_CHECK(uart_set_pin(DEFAULT_UART_CHANNEL, DEFAULT_UART_TX_PIN, DEFAULT_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); - connect_uarts(); } @@ -92,7 +91,8 @@ static void configure_uarts(void) * @brief Function called when command `consoletest` will be invoked. * It will simply print `test_message` defined above. */ -static int console_test(int argc, char **argv) { +static int console_test(int argc, char **argv) +{ printf("%s\n", test_message); return 0; } @@ -104,7 +104,8 @@ static int console_test(int argc, char **argv) { * the response on RX. * The response shall contain the test_message string. */ -static void send_commands(void* arg) { +static void send_commands(void* arg) +{ static char data[READ_BUF_SIZE]; char command[] = "consoletest\n"; int len = 0; @@ -115,12 +116,12 @@ static void send_commands(void* arg) { len = uart_read_bytes(DEFAULT_UART_CHANNEL, data, READ_BUF_SIZE, 100 / portTICK_PERIOD_MS); } while (len == 0); - if ( len == -1 ) { + if (len == -1) { goto end; } /* Send the command `consoletest` to the console UART. */ len = uart_write_bytes(DEFAULT_UART_CHANNEL, command, sizeof(command)); - if ( len == -1 ) { + if (len == -1) { goto end; } @@ -129,7 +130,7 @@ static void send_commands(void* arg) { len = uart_read_bytes(DEFAULT_UART_CHANNEL, data, READ_BUF_SIZE - 1, 250 / portTICK_PERIOD_MS); } while (len == 0); - if ( len == -1 ) { + if (len == -1) { goto end; } @@ -158,11 +159,11 @@ void app_main(void) .func = &console_test, }; esp_console_dev_uart_config_t uart_config = { - .channel = CONSOLE_UART_CHANNEL, - .baud_rate = UARTS_BAUD_RATE, - .tx_gpio_num = CONSOLE_UART_TX_PIN, - .rx_gpio_num = CONSOLE_UART_RX_PIN, - }; + .channel = CONSOLE_UART_CHANNEL, + .baud_rate = UARTS_BAUD_RATE, + .tx_gpio_num = CONSOLE_UART_TX_PIN, + .rx_gpio_num = CONSOLE_UART_RX_PIN, + }; /** * As we don't have a real serial terminal, (we just use default UART to * send and receive commands, ) we won't handle any escape sequence, so the @@ -172,7 +173,7 @@ void app_main(void) ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl)); configure_uarts(); - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); /* Create a task for sending and receiving commands to and from the second UART. */ xTaskCreate(send_commands, "send_commands_task", TASK_STACK_SIZE, NULL, 10, NULL); diff --git a/examples/peripherals/uart/uart_select/main/uart_select_example_main.c b/examples/peripherals/uart/uart_select/main/uart_select_example_main.c index e9d5e28dceb3..065837e4449b 100644 --- a/examples/peripherals/uart/uart_select/main/uart_select_example_main.c +++ b/examples/peripherals/uart/uart_select/main/uart_select_example_main.c @@ -22,7 +22,7 @@ static const char* TAG = "uart_select_example"; static void uart_select_task(void *arg) { - if (uart_driver_install(UART_NUM_0, 2*1024, 0, 0, NULL, 0) != ESP_OK) { + if (uart_driver_install(UART_NUM_0, 2 * 1024, 0, 0, NULL, 0) != ESP_OK) { ESP_LOGE(TAG, "Driver installation failed"); vTaskDelete(NULL); } @@ -95,5 +95,5 @@ static void uart_select_task(void *arg) void app_main(void) { - xTaskCreate(uart_select_task, "uart_select_task", 4*1024, NULL, 5, NULL); + xTaskCreate(uart_select_task, "uart_select_task", 4 * 1024, NULL, 5, NULL); } diff --git a/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c b/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c index 022a46dfbe0a..8f3420d5c4e1 100644 --- a/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c +++ b/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c @@ -26,8 +26,8 @@ static const char *TAG = "example"; * so we must define both report descriptors */ const uint8_t hid_report_descriptor[] = { - TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_ITF_PROTOCOL_KEYBOARD) ), - TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(HID_ITF_PROTOCOL_MOUSE) ) + TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_ITF_PROTOCOL_KEYBOARD)), + TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(HID_ITF_PROTOCOL_MOUSE)) }; /** @@ -70,13 +70,13 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) // Return zero will cause the stack to STALL request uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { - (void) instance; - (void) report_id; - (void) report_type; - (void) buffer; - (void) reqlen; + (void) instance; + (void) report_id; + (void) report_type; + (void) buffer; + (void) reqlen; - return 0; + return 0; } // Invoked when received SET_REPORT control request or diff --git a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c b/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c index c1d468469006..9d44945ce871 100644 --- a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c +++ b/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c @@ -131,7 +131,6 @@ static void _mount(void) ESP_LOGI(TAG, "Mount storage..."); ESP_ERROR_CHECK(tinyusb_msc_storage_mount(BASE_PATH)); - // List all the files in this directory ESP_LOGI(TAG, "\nls command output:"); struct dirent *d; @@ -388,7 +387,7 @@ void app_main(void) esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl)); for (int count = 0; count < sizeof(cmds) / sizeof(esp_console_cmd_t); count++) { - ESP_ERROR_CHECK( esp_console_cmd_register(&cmds[count]) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&cmds[count])); } ESP_ERROR_CHECK(esp_console_start_repl(repl)); } diff --git a/examples/peripherals/usb/device/tusb_ncm/main/tusb_ncm_main.c b/examples/peripherals/usb/device/tusb_ncm/main/tusb_ncm_main.c index be38d1b9e90a..79efe53a9b3d 100644 --- a/examples/peripherals/usb/device/tusb_ncm/main/tusb_ncm_main.c +++ b/examples/peripherals/usb/device/tusb_ncm/main/tusb_ncm_main.c @@ -24,7 +24,6 @@ #include "tinyusb.h" #include "tinyusb_net.h" - static const char *TAG = "USB_NCM"; static esp_err_t usb_recv_callback(void *buffer, uint16_t len, void *ctx) diff --git a/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb_cdc_example_main.c b/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb_cdc_example_main.c index 01a5862202e3..f8c548e01a84 100644 --- a/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb_cdc_example_main.c +++ b/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb_cdc_example_main.c @@ -56,21 +56,21 @@ static bool handle_rx(const uint8_t *data, size_t data_len, void *arg) static void handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_ctx) { switch (event->type) { - case CDC_ACM_HOST_ERROR: - ESP_LOGE(TAG, "CDC-ACM error has occurred, err_no = %i", event->data.error); - break; - case CDC_ACM_HOST_DEVICE_DISCONNECTED: - ESP_LOGI(TAG, "Device suddenly disconnected"); - ESP_ERROR_CHECK(cdc_acm_host_close(event->data.cdc_hdl)); - xSemaphoreGive(device_disconnected_sem); - break; - case CDC_ACM_HOST_SERIAL_STATE: - ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val); - break; - case CDC_ACM_HOST_NETWORK_CONNECTION: - default: - ESP_LOGW(TAG, "Unsupported CDC event: %i", event->type); - break; + case CDC_ACM_HOST_ERROR: + ESP_LOGE(TAG, "CDC-ACM error has occurred, err_no = %i", event->data.error); + break; + case CDC_ACM_HOST_DEVICE_DISCONNECTED: + ESP_LOGI(TAG, "Device suddenly disconnected"); + ESP_ERROR_CHECK(cdc_acm_host_close(event->data.cdc_hdl)); + xSemaphoreGive(device_disconnected_sem); + break; + case CDC_ACM_HOST_SERIAL_STATE: + ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val); + break; + case CDC_ACM_HOST_NETWORK_CONNECTION: + default: + ESP_LOGW(TAG, "Unsupported CDC event: %i", event->type); + break; } } diff --git a/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cdc_acm_vcp_example_main.cpp b/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cdc_acm_vcp_example_main.cpp index f90620ec879a..1ffd33c222f2 100644 --- a/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cdc_acm_vcp_example_main.cpp +++ b/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cdc_acm_vcp_example_main.cpp @@ -60,18 +60,18 @@ static bool handle_rx(const uint8_t *data, size_t data_len, void *arg) static void handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_ctx) { switch (event->type) { - case CDC_ACM_HOST_ERROR: - ESP_LOGE(TAG, "CDC-ACM error has occurred, err_no = %d", event->data.error); - break; - case CDC_ACM_HOST_DEVICE_DISCONNECTED: - ESP_LOGI(TAG, "Device suddenly disconnected"); - xSemaphoreGive(device_disconnected_sem); - break; - case CDC_ACM_HOST_SERIAL_STATE: - ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val); - break; - case CDC_ACM_HOST_NETWORK_CONNECTION: - default: break; + case CDC_ACM_HOST_ERROR: + ESP_LOGE(TAG, "CDC-ACM error has occurred, err_no = %d", event->data.error); + break; + case CDC_ACM_HOST_DEVICE_DISCONNECTED: + ESP_LOGI(TAG, "Device suddenly disconnected"); + xSemaphoreGive(device_disconnected_sem); + break; + case CDC_ACM_HOST_SERIAL_STATE: + ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val); + break; + case CDC_ACM_HOST_NETWORK_CONNECTION: + default: break; } } diff --git a/examples/peripherals/usb/host/hid/main/hid_host_example.c b/examples/peripherals/usb/host/hid/main/hid_host_example.c index 7a37d95e9021..2ed93839199b 100644 --- a/examples/peripherals/usb/host/hid/main/hid_host_example.c +++ b/examples/peripherals/usb/host/hid/main/hid_host_example.c @@ -180,8 +180,8 @@ static inline bool hid_keyboard_is_modifier_shift(uint8_t modifier) * @return false Key scancode unknown */ static inline bool hid_keyboard_get_char(uint8_t modifier, - uint8_t key_code, - unsigned char *key_char) + uint8_t key_code, + unsigned char *key_char) { uint8_t mod = (hid_keyboard_is_modifier_shift(modifier)) ? 1 : 0; @@ -342,7 +342,6 @@ static void hid_host_generic_report_callback(const uint8_t *const data, const in putchar('\r'); } - /** * @brief USB HID Host interface callback * @@ -357,14 +356,14 @@ void hid_host_interface_callback(hid_host_device_handle_t hid_device_handle, uint8_t data[64] = { 0 }; size_t data_length = 0; hid_host_dev_params_t dev_params; - ESP_ERROR_CHECK( hid_host_device_get_params(hid_device_handle, &dev_params)); + ESP_ERROR_CHECK(hid_host_device_get_params(hid_device_handle, &dev_params)); switch (event) { case HID_HOST_INTERFACE_EVENT_INPUT_REPORT: - ESP_ERROR_CHECK( hid_host_device_get_raw_input_report_data(hid_device_handle, - data, - 64, - &data_length)); + ESP_ERROR_CHECK(hid_host_device_get_raw_input_report_data(hid_device_handle, + data, + 64, + &data_length)); if (HID_SUBCLASS_BOOT_INTERFACE == dev_params.sub_class) { if (HID_PROTOCOL_KEYBOARD == dev_params.proto) { @@ -380,7 +379,7 @@ void hid_host_interface_callback(hid_host_device_handle_t hid_device_handle, case HID_HOST_INTERFACE_EVENT_DISCONNECTED: ESP_LOGI(TAG, "HID Device, protocol '%s' DISCONNECTED", hid_proto_name_str[dev_params.proto]); - ESP_ERROR_CHECK( hid_host_device_close(hid_device_handle) ); + ESP_ERROR_CHECK(hid_host_device_close(hid_device_handle)); break; case HID_HOST_INTERFACE_EVENT_TRANSFER_ERROR: ESP_LOGI(TAG, "HID Device, protocol '%s' TRANSFER_ERROR", @@ -405,7 +404,7 @@ void hid_host_device_event(hid_host_device_handle_t hid_device_handle, void *arg) { hid_host_dev_params_t dev_params; - ESP_ERROR_CHECK( hid_host_device_get_params(hid_device_handle, &dev_params)); + ESP_ERROR_CHECK(hid_host_device_get_params(hid_device_handle, &dev_params)); switch (event) { case HID_HOST_DRIVER_EVENT_CONNECTED: @@ -417,14 +416,14 @@ void hid_host_device_event(hid_host_device_handle_t hid_device_handle, .callback_arg = NULL }; - ESP_ERROR_CHECK( hid_host_device_open(hid_device_handle, &dev_config) ); + ESP_ERROR_CHECK(hid_host_device_open(hid_device_handle, &dev_config)); if (HID_SUBCLASS_BOOT_INTERFACE == dev_params.sub_class) { - ESP_ERROR_CHECK( hid_class_request_set_protocol(hid_device_handle, HID_REPORT_PROTOCOL_BOOT)); + ESP_ERROR_CHECK(hid_class_request_set_protocol(hid_device_handle, HID_REPORT_PROTOCOL_BOOT)); if (HID_PROTOCOL_KEYBOARD == dev_params.proto) { - ESP_ERROR_CHECK( hid_class_request_set_idle(hid_device_handle, 0, 0)); + ESP_ERROR_CHECK(hid_class_request_set_idle(hid_device_handle, 0, 0)); } } - ESP_ERROR_CHECK( hid_host_device_start(hid_device_handle) ); + ESP_ERROR_CHECK(hid_host_device_start(hid_device_handle)); break; default: break; @@ -443,14 +442,14 @@ static void usb_lib_task(void *arg) .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_ENABLE, }; - ESP_ERROR_CHECK( gpio_config(&input_pin) ); + ESP_ERROR_CHECK(gpio_config(&input_pin)); const usb_host_config_t host_config = { .skip_phy_setup = false, .intr_flags = ESP_INTR_FLAG_LEVEL1, }; - ESP_ERROR_CHECK( usb_host_install(&host_config) ); + ESP_ERROR_CHECK(usb_host_install(&host_config)); xTaskNotifyGive(arg); while (gpio_get_level(APP_QUIT_PIN) != 0) { @@ -472,7 +471,7 @@ static void usb_lib_task(void *arg) ESP_LOGI(TAG, "USB shutdown"); // Clean up USB Host vTaskDelay(10); // Short delay to allow clients clean-up - ESP_ERROR_CHECK( usb_host_uninstall()); + ESP_ERROR_CHECK(usb_host_uninstall()); vTaskDelete(NULL); } @@ -558,7 +557,7 @@ void app_main(void) .callback_arg = NULL }; - ESP_ERROR_CHECK( hid_host_install(&hid_host_driver_config) ); + ESP_ERROR_CHECK(hid_host_install(&hid_host_driver_config)); // Task is working until the devices are gone (while 'user_shutdown' if false) user_shutdown = false; diff --git a/examples/peripherals/usb/host/msc/main/msc_example_main.c b/examples/peripherals/usb/host/msc/main/msc_example_main.c index 1e690e1e73c8..53c28bc26e87 100644 --- a/examples/peripherals/usb/host/msc/main/msc_example_main.c +++ b/examples/peripherals/usb/host/msc/main/msc_example_main.c @@ -164,13 +164,13 @@ void app_main(void) .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_ENABLE, }; - ESP_ERROR_CHECK( gpio_config(&input_pin) ); + ESP_ERROR_CHECK(gpio_config(&input_pin)); usb_flags = xEventGroupCreate(); assert(usb_flags); const usb_host_config_t host_config = { .intr_flags = ESP_INTR_FLAG_LEVEL1 }; - ESP_ERROR_CHECK( usb_host_install(&host_config) ); + ESP_ERROR_CHECK(usb_host_install(&host_config)); task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL); assert(task_created); @@ -180,7 +180,7 @@ void app_main(void) .stack_size = 4096, .callback = msc_event_cb, }; - ESP_ERROR_CHECK( msc_host_install(&msc_config) ); + ESP_ERROR_CHECK(msc_host_install(&msc_config)); const esp_vfs_fat_mount_config_t mount_config = { .format_if_mount_failed = false, @@ -191,28 +191,28 @@ void app_main(void) do { uint8_t device_address = wait_for_msc_device(); - ESP_ERROR_CHECK( msc_host_install_device(device_address, &msc_device) ); + ESP_ERROR_CHECK(msc_host_install_device(device_address, &msc_device)); msc_host_print_descriptors(msc_device); - ESP_ERROR_CHECK( msc_host_get_device_info(msc_device, &info) ); + ESP_ERROR_CHECK(msc_host_get_device_info(msc_device, &info)); print_device_info(&info); - ESP_ERROR_CHECK( msc_host_vfs_register(msc_device, "/usb", &mount_config, &vfs_handle) ); + ESP_ERROR_CHECK(msc_host_vfs_register(msc_device, "/usb", &mount_config, &vfs_handle)); while (!wait_for_event(DEVICE_DISCONNECTED, 200)) { file_operations(); } xEventGroupClearBits(usb_flags, READY_TO_UNINSTALL); - ESP_ERROR_CHECK( msc_host_vfs_unregister(vfs_handle) ); - ESP_ERROR_CHECK( msc_host_uninstall_device(msc_device) ); + ESP_ERROR_CHECK(msc_host_vfs_unregister(vfs_handle)); + ESP_ERROR_CHECK(msc_host_uninstall_device(msc_device)); } while (gpio_get_level(USB_DISCONNECT_PIN) != 0); ESP_LOGI(TAG, "Uninitializing USB ..."); - ESP_ERROR_CHECK( msc_host_uninstall() ); + ESP_ERROR_CHECK(msc_host_uninstall()); wait_for_event(READY_TO_UNINSTALL, portMAX_DELAY); - ESP_ERROR_CHECK( usb_host_uninstall() ); + ESP_ERROR_CHECK(usb_host_uninstall()); ESP_LOGI(TAG, "Done"); } diff --git a/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c b/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c index 15ae3201f840..ce7ee4448700 100644 --- a/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c +++ b/examples/peripherals/usb/host/usb_host_lib/main/class_driver.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -33,22 +33,22 @@ static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void * { class_driver_t *driver_obj = (class_driver_t *)arg; switch (event_msg->event) { - case USB_HOST_CLIENT_EVENT_NEW_DEV: - if (driver_obj->dev_addr == 0) { - driver_obj->dev_addr = event_msg->new_dev.address; - //Open the device next - driver_obj->actions |= ACTION_OPEN_DEV; - } - break; - case USB_HOST_CLIENT_EVENT_DEV_GONE: - if (driver_obj->dev_hdl != NULL) { - //Cancel any other actions and close the device next - driver_obj->actions = ACTION_CLOSE_DEV; - } - break; - default: - //Should never occur - abort(); + case USB_HOST_CLIENT_EVENT_NEW_DEV: + if (driver_obj->dev_addr == 0) { + driver_obj->dev_addr = event_msg->new_dev.address; + //Open the device next + driver_obj->actions |= ACTION_OPEN_DEV; + } + break; + case USB_HOST_CLIENT_EVENT_DEV_GONE: + if (driver_obj->dev_hdl != NULL) { + //Cancel any other actions and close the device next + driver_obj->actions = ACTION_CLOSE_DEV; + } + break; + default: + //Should never occur + abort(); } } @@ -146,7 +146,7 @@ void class_driver_task(void *arg) .max_num_event_msg = CLIENT_NUM_EVENT_MSG, .async = { .client_event_callback = client_event_cb, - .callback_arg = (void *)&driver_obj, + .callback_arg = (void *) &driver_obj, }, }; ESP_ERROR_CHECK(usb_host_client_register(&client_config, &driver_obj.client_hdl)); diff --git a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c index 9ee388a2845d..f73880cabcb3 100644 --- a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c +++ b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c @@ -35,7 +35,7 @@ static void host_lib_daemon_task(void *arg) bool has_clients = true; bool has_devices = true; - while (has_clients || has_devices ) { + while (has_clients || has_devices) { uint32_t event_flags; ESP_ERROR_CHECK(usb_host_lib_handle_events(portMAX_DELAY, &event_flags)); if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { diff --git a/examples/peripherals/usb/host/uvc/main/main.c b/examples/peripherals/usb/host/uvc/main/main.c index 7cf4f476b644..9f87bdf412a3 100644 --- a/examples/peripherals/usb/host/uvc/main/main.c +++ b/examples/peripherals/usb/host/uvc/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -99,7 +99,7 @@ static void uninitialize_usb_host_lib(void) xSemaphoreTake(ready_to_uninstall_usb, portMAX_DELAY); vSemaphoreDelete(ready_to_uninstall_usb); - if ( usb_host_uninstall() != ESP_OK) { + if (usb_host_uninstall() != ESP_OK) { ESP_LOGE(TAG, "Failed to uninstall usb_host"); } } @@ -163,9 +163,9 @@ int app_main(int argc, char **argv) .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_ENABLE, }; - ESP_ERROR_CHECK( gpio_config(&input_pin) ); + ESP_ERROR_CHECK(gpio_config(&input_pin)); - ESP_ERROR_CHECK( initialize_usb_host_lib() ); + ESP_ERROR_CHECK(initialize_usb_host_lib()); libuvc_adapter_config_t config = { .create_background_task = true, @@ -176,20 +176,20 @@ int app_main(int argc, char **argv) libuvc_adapter_set_config(&config); - UVC_CHECK( uvc_init(&ctx, NULL) ); + UVC_CHECK(uvc_init(&ctx, NULL)); // Streaming takes place only when enabled in menuconfig - ESP_ERROR_CHECK( tcp_server_wait_for_connection() ); + ESP_ERROR_CHECK(tcp_server_wait_for_connection()); do { printf("Waiting for device\n"); wait_for_event(UVC_DEVICE_CONNECTED); - UVC_CHECK( uvc_find_device(ctx, &dev, PID, VID, SERIAL_NUMBER) ); + UVC_CHECK(uvc_find_device(ctx, &dev, PID, VID, SERIAL_NUMBER)); puts("Device found"); - UVC_CHECK( uvc_open(dev, &devh) ); + UVC_CHECK(uvc_open(dev, &devh)); // Uncomment to print configuration descriptor // libuvc_adapter_print_descriptors(devh); @@ -200,10 +200,10 @@ int app_main(int argc, char **argv) uvc_print_diag(devh, stderr); // Negotiate stream profile - res = uvc_get_stream_ctrl_format_size(devh, &ctrl, FORMAT, WIDTH, HEIGHT, FPS ); + res = uvc_get_stream_ctrl_format_size(devh, &ctrl, FORMAT, WIDTH, HEIGHT, FPS); while (res != UVC_SUCCESS) { printf("Negotiating streaming format failed, trying again...\n"); - res = uvc_get_stream_ctrl_format_size(devh, &ctrl, FORMAT, WIDTH, HEIGHT, FPS ); + res = uvc_get_stream_ctrl_format_size(devh, &ctrl, FORMAT, WIDTH, HEIGHT, FPS); sleep(1); } @@ -213,7 +213,7 @@ int app_main(int argc, char **argv) uvc_print_stream_ctrl(&ctrl, stderr); - UVC_CHECK( uvc_start_streaming(devh, &ctrl, frame_callback, NULL, 0) ); + UVC_CHECK(uvc_start_streaming(devh, &ctrl, frame_callback, NULL, 0)); puts("Streaming..."); wait_for_event(UVC_DEVICE_DISCONNECTED); diff --git a/examples/peripherals/usb/host/uvc/main/tcp_server.c b/examples/peripherals/usb/host/uvc/main/tcp_server.c index d11c8b3a4ed5..0d2a3ee5449e 100644 --- a/examples/peripherals/usb/host/uvc/main/tcp_server.c +++ b/examples/peripherals/usb/host/uvc/main/tcp_server.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -53,7 +53,7 @@ static void sender_task(void *arg) while (1) { size_t bytes_received = 0; char *payload = (char *)xRingbufferReceiveUpTo( - server->buffer, &bytes_received, pdMS_TO_TICKS(2500), 20000); + server->buffer, &bytes_received, pdMS_TO_TICKS(2500), 20000); if (payload != NULL && server->is_active) { int sent = send(server->sock, payload, bytes_received, 0); @@ -82,7 +82,7 @@ esp_err_t tcp_server_send(uint8_t *payload, size_t size) return ESP_OK; } - if ( xRingbufferSend(s_server->buffer, payload, size, pdMS_TO_TICKS(1)) != pdTRUE ) { + if (xRingbufferSend(s_server->buffer, payload, size, pdMS_TO_TICKS(1)) != pdTRUE) { ESP_LOGW(TAG, "Failed to send frame to ring buffer."); return ESP_FAIL; } @@ -179,18 +179,17 @@ esp_err_t tcp_server_wait_for_connection(void) } server->buffer = xRingbufferCreate(100000, RINGBUF_TYPE_BYTEBUF); - if ( server->buffer == NULL) { + if (server->buffer == NULL) { free(server); return ESP_ERR_NO_MEM;; } - if ( create_server(server) != ESP_OK) { + if (create_server(server) != ESP_OK) { vRingbufferDelete(server->buffer); free(server); return ESP_FAIL; } - BaseType_t task_created = xTaskCreate(sender_task, "sender_task", 4096, server, 10, &task_handle); if (!task_created) { socket_close(server); diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index 8ed56bfe89eb..b09def62d560 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -127,7 +127,6 @@ components_not_formatted_temporary: - "/examples/mesh/" - "/examples/network/" - "/examples/openthread/" - - "/examples/peripherals/" - "/examples/phy/" - "/examples/protocols/" - "/examples/provisioning/" @@ -174,6 +173,9 @@ components_not_formatted_permanent: - "/components/app_trace/sys_view/SEGGER/" # SoC header files (generated) - "/components/soc/*/include/soc/" + # Example resource files (generated) + - "/examples/peripherals/lcd/i80_controller/main/images/" + - "/examples/peripherals/dac/dac_continuous/dac_audio/main/audio_example_file.h" docs: # Docs directory contains some .inc files, which are not C include files From cdc905ffe0c61685b1961341c2e4fe0ecd636b35 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 25 Sep 2023 11:36:16 +0800 Subject: [PATCH 103/142] feat(dw_gdma): initial low level driver feat(dw_gdma): initial low level driver --- components/hal/CMakeLists.txt | 4 + components/hal/dw_gdma_hal.c | 15 + .../hal/esp32p4/include/hal/dw_gdma_ll.h | 841 +++ components/hal/gdma_hal_ahb_v1.c | 1 + components/hal/gdma_hal_ahb_v2.c | 1 + components/hal/gdma_hal_axi.c | 1 + components/hal/include/hal/adc_hal.h | 1 - components/hal/include/hal/dw_gdma_hal.h | 46 + .../include/soc/{gdma_reg.h => dw_gdma_reg.h} | 0 .../soc/esp32p4/include/soc/dw_gdma_struct.h | 1780 ++++++ .../soc/esp32p4/include/soc/gdma_struct.h | 5183 ----------------- .../soc/esp32p4/include/soc/interrupts.h | 2 +- components/soc/esp32p4/interrupts.c | 2 +- .../soc/esp32p4/ld/esp32p4.peripherals.ld | 2 +- 14 files changed, 2692 insertions(+), 5187 deletions(-) create mode 100644 components/hal/dw_gdma_hal.c create mode 100644 components/hal/esp32p4/include/hal/dw_gdma_ll.h create mode 100644 components/hal/include/hal/dw_gdma_hal.h rename components/soc/esp32p4/include/soc/{gdma_reg.h => dw_gdma_reg.h} (100%) create mode 100644 components/soc/esp32p4/include/soc/dw_gdma_struct.h delete mode 100644 components/soc/esp32p4/include/soc/gdma_struct.h diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 7019d2280413..d73f44574202 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -108,6 +108,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "gdma_hal_axi.c") endif() + if(CONFIG_SOC_DW_GDMA_SUPPORTED) + list(APPEND srcs "dw_gdma_hal.c") + endif() + if(CONFIG_SOC_I2S_SUPPORTED) list(APPEND srcs "i2s_hal.c") endif() diff --git a/components/hal/dw_gdma_hal.c b/components/hal/dw_gdma_hal.c new file mode 100644 index 000000000000..b1e576f34dec --- /dev/null +++ b/components/hal/dw_gdma_hal.c @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "hal/dw_gdma_hal.h" +#include "hal/dw_gdma_ll.h" + +void dw_gdma_hal_init(dw_gdma_hal_context_t *hal, const dw_gdma_hal_config_t *config) +{ + hal->dev = DW_GDMA_LL_GET_HW(); +} diff --git a/components/hal/esp32p4/include/hal/dw_gdma_ll.h b/components/hal/esp32p4/include/hal/dw_gdma_ll.h new file mode 100644 index 000000000000..b710340d1a29 --- /dev/null +++ b/components/hal/esp32p4/include/hal/dw_gdma_ll.h @@ -0,0 +1,841 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "hal/assert.h" +#include "soc/dw_gdma_struct.h" +#include "soc/hp_sys_clkrst_struct.h" + +#define DW_GDMA_LL_GET_HW() (&DW_GDMA) + +#define DW_GDMA_LL_MASTER_PORT_MIPI_DSI 0 // DW_GDMA master 0 can access DSI bridge +#define DW_GDMA_LL_MASTER_PORT_MIPI_CSI 0 // DW_GDMA master 0 can access CSI bridge +#define DW_GDMA_LL_MASTER_PORT_MEMORY 1 // DW_GDMA master 1 can only access L2MEM & ROM & MSPI Flash/PSRAM + +// Common event bitmap +#define DW_GDMA_LL_COMMON_EVENT_SLVIF_DEC_ERR (0x1 << 0) +#define DW_GDMA_LL_COMMON_EVENT_SLVIF_WR2RO_ERR (0x1 << 1) +#define DW_GDMA_LL_COMMON_EVENT_SLVIF_RD2WO_ERR (0x1 << 2) +#define DW_GDMA_LL_COMMON_EVENT_SLVIF_WRONHOLD_ERR (0x1 << 3) +#define DW_GDMA_LL_COMMON_EVENT_SLVIF_WRPARITY_ERR (0x1 << 7) +#define DW_GDMA_LL_COMMON_EVENT_SLVIF_UNDEFINEDREG_DEC_ERR (0x1 << 8) +#define DW_GDMA_LL_COMMON_EVENT_MXIF1_RCH0_ECCPROT_CORRERR (0x1 << 9) +#define DW_GDMA_LL_COMMON_EVENT_MXIF1_RCH0_ECCPROT_UNCORRERR (0x1 << 10) +#define DW_GDMA_LL_COMMON_EVENT_MXIF1_RECCPROT_CORRERR (0x1 << 11) +#define DW_GDMA_LL_COMMON_EVENT_MXIF1_RECCPROT_UNCORRERR (0x1 << 12) +#define DW_GDMA_LL_COMMON_EVENT_MXIF1_BCH_ECCPROT_CORRERR (0x1 << 13) +#define DW_GDMA_LL_COMMON_EVENT_MXIF1_BCH_ECCPROT_UNCORRERR (0x1 << 14) +#define DW_GDMA_LL_COMMON_EVENT_MXIF2_RCH0_ECCPROT_CORRERR (0x1 << 15) +#define DW_GDMA_LL_COMMON_EVENT_MXIF2_RCH0_ECCPROT_UNCORRERR (0x1 << 16) +#define DW_GDMA_LL_COMMON_EVENT_MXIF2_RECCPROT_CORRERR (0x1 << 17) +#define DW_GDMA_LL_COMMON_EVENT_MXIF2_RECCPROT_UNCORRERR (0x1 << 18) +#define DW_GDMA_LL_COMMON_EVENT_MXIF2_BCH_ECCPROT_CORRERR (0x1 << 19) +#define DW_GDMA_LL_COMMON_EVENT_MXIF2_BCH_ECCPROT_UNCORRERR (0x1 << 20) + +// Channel event bitmap +#define DW_GDMA_LL_CHANNEL_EVENT_BLOCK_TFR_DONE (0x1 << 0) +#define DW_GDMA_LL_CHANNEL_EVENT_DMA_TFR_DONE (0x1 << 1) +#define DW_GDMA_LL_CHANNEL_EVENT_SRC_TRANSCOMP (0x1 << 3) +#define DW_GDMA_LL_CHANNEL_EVENT_DST_TRANSCOMP (0x1 << 4) +#define DW_GDMA_LL_CHANNEL_EVENT_SRC_DEC_ERR (0x1 << 5) +#define DW_GDMA_LL_CHANNEL_EVENT_DST_DEC_ERR (0x1 << 6) +#define DW_GDMA_LL_CHANNEL_EVENT_SRC_SLV_ERR (0x1 << 7) +#define DW_GDMA_LL_CHANNEL_EVENT_DST_SLV_ERR (0x1 << 8) +#define DW_GDMA_LL_CHANNEL_EVENT_LLI_RD_DEC_ERR (0x1 << 9) +#define DW_GDMA_LL_CHANNEL_EVENT_LLI_WR_DEC_ERR (0x1 << 10) +#define DW_GDMA_LL_CHANNEL_EVENT_LLI_RD_SLV_ERR (0x1 << 11) +#define DW_GDMA_LL_CHANNEL_EVENT_LLI_WR_SLV_ERR (0x1 << 12) +#define DW_GDMA_LL_CHANNEL_EVENT_SHADOWREG_OR_LLI_INVALID_ERR (0x1 << 13) +#define DW_GDMA_LL_CHANNEL_EVENT_LOCK_CLEARED (0x1 << 27) +#define DW_GDMA_LL_CHANNEL_EVENT_SRC_SUSPENDED (0x1 << 28) +#define DW_GDMA_LL_CHANNEL_EVENT_SUSPENDED (0x1 << 29) +#define DW_GDMA_LL_CHANNEL_EVENT_DISABLED (0x1 << 30) +#define DW_GDMA_LL_CHANNEL_EVENT_ABORTED (0x1 << 31) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief DW_GDMA transfer width + */ +typedef enum { + DW_GDMA_LL_TRANS_WIDTH_8, /*!< Data transfer width: 8 bits */ + DW_GDMA_LL_TRANS_WIDTH_16, /*!< Data transfer width: 16 bits */ + DW_GDMA_LL_TRANS_WIDTH_32, /*!< Data transfer width: 32 bits */ + DW_GDMA_LL_TRANS_WIDTH_64, /*!< Data transfer width: 64 bits */ + DW_GDMA_LL_TRANS_WIDTH_128, /*!< Data transfer width: 128 bits */ + DW_GDMA_LL_TRANS_WIDTH_256, /*!< Data transfer width: 256 bits */ + DW_GDMA_LL_TRANS_WIDTH_512, /*!< Data transfer width: 512 bits */ +} dw_gdma_ll_transfer_width_t; + +/** + * @brief DW_GDMA burst items + */ +typedef enum { + DW_GDMA_LL_BURST_ITEMS_1, /*!< 1 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_4, /*!< 4 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_8, /*!< 8 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_16, /*!< 16 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_32, /*!< 32 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_64, /*!< 64 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_128, /*!< 128 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_256, /*!< 256 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_512, /*!< 512 data items in the burst transaction */ + DW_GDMA_LL_BURST_ITEMS_1024, /*!< 1024 data items in the burst transaction */ +} dw_gdma_ll_burst_items_t; + +/** + * @brief Multi block transfer type + */ +typedef enum { + DW_GDMA_LL_MULTI_BLOCK_CONTIGUOUS, /*!< Contiguous */ + DW_GDMA_LL_MULTI_BLOCK_RELOAD, /*!< Reload */ + DW_GDMA_LL_MULTI_BLOCK_SHADOW_REG, /*!< Shadow register */ + DW_GDMA_LL_MULTI_BLOCK_LINK_LIST, /*!< Link list */ +} dw_gdma_ll_multi_block_type_t; + +/** + * @brief Transfer type and flow control + */ +typedef enum { + DW_GDMA_LL_FLOW_M2M_DMAC, /*!< Flow: memory to memory, controller: DMA engine */ + DW_GDMA_LL_FLOW_M2P_DMAC, /*!< Flow: memory to peripheral, controller: DMA engine */ + DW_GDMA_LL_FLOW_P2M_DMAC, /*!< Flow: peripheral to memory, controller: DMA engine */ + DW_GDMA_LL_FLOW_P2P_DMAC, /*!< Flow: peripheral to peripheral, controller: DMA engine */ + DW_GDMA_LL_FLOW_P2M_SRC, /*!< Flow: peripheral to memory, controller: source peripheral */ + DW_GDMA_LL_FLOW_P2P_SRC, /*!< Flow: peripheral to peripheral, controller: source peripheral */ + DW_GDMA_LL_FLOW_M2P_DST, /*!< Flow: memory to peripheral, controller: destination peripheral */ + DW_GDMA_LL_FLOW_P2P_DST, /*!< Flow: peripheral to peripheral, controller: destination peripheral */ +} dw_gdma_ll_trans_flow_t; + +/** + * @brief Handshake interface + */ +typedef enum { + DW_GDMA_LL_HANDSHAKE_HW, /*!< Transaction requests are initiated by hardware */ + DW_GDMA_LL_HANDSHAKE_SW, /*!< Transaction requests are initiated by software */ +} dw_gdma_ll_handshake_interface_t; + +/** + * @brief Handshake number for different peripherals + */ +typedef enum { + DW_GDMA_LL_HW_HANDSHAKE_PERIPH_DSI, /*!< Handshake peripheral is DSI */ + DW_GDMA_LL_HW_HANDSHAKE_PERIPH_CSI, /*!< Handshake peripheral is CSI */ + DW_GDMA_LL_HW_HANDSHAKE_PERIPH_ISP, /*!< Handshake peripheral is ISP */ +} dw_gdma_ll_hw_handshake_periph_t; + +/** + * @brief Channel lock level + */ +typedef enum { + DW_GDMA_LL_LOCK_LEVEL_FULL_TRANS, /*!< Lock over complete DMA transfer */ + DW_GDMA_LL_LOCK_LEVEL_BLOCK_TRANS, /*!< Lock over DMA block transfer */ +} dw_gdma_ll_lock_level_t; + +/** + * @brief Enable the bus clock for the DMA module + */ +static inline void dw_gdma_ll_enable_bus_clock(int group_id, bool enable) +{ + (void) group_id; + HP_SYS_CLKRST.soc_clk_ctrl0.reg_gdma_cpu_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_gdma_sys_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define dw_gdma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; dw_gdma_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the DMA module + */ +static inline void dw_gdma_ll_reset_register(int group_id) +{ + (void)group_id; + HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_gdma = 1; + HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_gdma = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define dw_gdma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dw_gdma_ll_reset_register(__VA_ARGS__) + +/** + * @brief Reset the DMA controller by software + * + * @param dev Pointer to the DW_GDMA registers + */ +static inline void dw_gdma_ll_reset(dw_gdma_dev_t *dev) +{ + dev->reset0.dmac_rst = 1; + while (dev->reset0.dmac_rst); +} + +/** + * @brief Enable the DMA controller + * + * @note If disable the controller while any channel is active, the controller won't stop + * until all activity on all channels are terminated. + * + * @param dev Pointer to the DW_GDMA registers + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_enable_controller(dw_gdma_dev_t *dev, bool en) +{ + dev->cfg0.dmac_en = en; +} + +/** + * @brief Enable the interrupt generation globally + * + * @param dev Pointer to the DW_GDMA registers + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_enable_intr_global(dw_gdma_dev_t *dev, bool en) +{ + dev->cfg0.int_en = en; +} + +/** + * @brief Check if the common register interrupt is active + * + * @param dev Pointer to the DW_GDMA registers + * @return True: common register interrupt is active, False: common register interrupt is inactive + */ +static inline bool dw_gdma_ll_is_common_intr_active(dw_gdma_dev_t *dev) +{ + return dev->int_st0.commonreg_intstat; +} + +/** + * @brief Clear the common interrupt by mask + * + * @param dev Pointer to the DW_GDMA registers + * @param mask Mask of the interrupt to clear + */ +static inline void dw_gdma_ll_clear_common_intr(dw_gdma_dev_t *dev, uint32_t mask) +{ + dev->common_int_clr0.val = mask; +} + +/** + * @brief Enable the generation of common interrupt + * + * @param dev Pointer to the DW_GDMA registers + * @param mask Mask of the interrupt to enable + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_enable_common_intr_generation(dw_gdma_dev_t *dev, uint32_t mask, bool en) +{ + if (en) { + dev->common_int_st_ena0.val |= mask; + } else { + dev->common_int_st_ena0.val &= ~mask; + } +} + +/** + * @brief Enable the propagation of common interrupt to the CPU + * + * @param dev Pointer to the DW_GDMA registers + * @param mask Mask of the interrupt to enable + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_enable_common_intr_propagation(dw_gdma_dev_t *dev, uint32_t mask, bool en) +{ + if (en) { + dev->common_int_sig_ena0.val |= mask; + } else { + dev->common_int_sig_ena0.val &= ~mask; + } +} + +/** + * @brief Get the common interrupt status + * + * @note This register captures Slave interface access errors + * + * @param dev Pointer to the DW_GDMA registers + * @return Mask of the common interrupt status + */ +static inline uint32_t dw_gdma_ll_get_common_intr_status(dw_gdma_dev_t *dev) +{ + return dev->common_int_st0.val; +} + +/** + * @brief Enable the generation of the channel interrupt + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param mask Mask of the interrupt to enable + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_channel_enable_intr_generation(dw_gdma_dev_t *dev, uint8_t channel, uint32_t mask, bool en) +{ + if (en) { + dev->ch[channel].int_st_ena0.val |= mask; + } else { + dev->ch[channel].int_st_ena0.val &= ~mask; + } +} + +/** + * @brief Enable the propagation of channel interrupt to the CPU + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param mask Mask of the interrupt to enable + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_channel_enable_intr_propagation(dw_gdma_dev_t *dev, uint8_t channel, uint32_t mask, bool en) +{ + if (en) { + dev->ch[channel].int_sig_ena0.val |= mask; + } else { + dev->ch[channel].int_sig_ena0.val &= ~mask; + } +} + +/** + * @brief Get the channel interrupt status + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @return Mask of the channel interrupt status + */ +static inline uint32_t dw_gdma_ll_channel_get_inr_status(dw_gdma_dev_t *dev, uint8_t channel) +{ + return dev->ch[channel].int_st0.val; +} + +/** + * @brief Clear the channel interrupt by mask + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param mask Mask of the interrupt to clear + */ +static inline void dw_gdma_ll_channel_clear_intr(dw_gdma_dev_t *dev, uint8_t channel, uint32_t mask) +{ + dev->ch[channel].int_clr0.val = mask; +} + +/** + * @brief Enable the DMA channel to start the transfer + * + * @note When the DMA transfer finished, the channel will be disabled automatically + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_channel_enable(dw_gdma_dev_t *dev, uint8_t channel, bool en) +{ + if (en) { + dev->chen0.val = 0x101 << channel; + } else { + dev->chen0.val = 0x100 << channel; + } +} + +/** + * @brief Suspend the DMA channel + * + * @note There is no guarantee that the current dma transaction will complete + * @note The suspend bit is cleared when the channel is disabled + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param en True to enter suspend mode, false to exit suspend mode + */ +static inline void dw_gdma_ll_channel_suspend(dw_gdma_dev_t *dev, uint8_t channel, bool en) +{ + if (en) { + dev->chen0.val = 0x1010000 << channel; + } else { + dev->chen0.val = 0x1000000 << channel; + } +} + +/** + * @brief Abort the DMA channel + * + * @note Abort should only be used in situations where a particular channel hangs due to no response. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + */ +static inline void dw_gdma_ll_channel_abort(dw_gdma_dev_t *dev, uint8_t channel) +{ + // the abort bit clears itself after the abort is done + dev->chen1.val = 0x101 << channel; +} + +/** + * @brief Check if the DMA channel interrupt is active + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @return True: channel interrupt is active, False: channel interrupt is inactive + */ +static inline bool dw_gdma_ll_channel_is_interrupt_active(dw_gdma_dev_t *dev, uint8_t channel) +{ + return dev->int_st0.val & (1 << channel); +} + +/** + * @brief Set the source address of the DMA transfer + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param src_addr Source address + */ +static inline void dw_gdma_ll_channel_set_src_addr(dw_gdma_dev_t *dev, uint8_t channel, uint32_t src_addr) +{ + dev->ch[channel].sar0.sar0 = src_addr; +} + +/** + * @brief Set the destination address of the DMA transfer + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param dst_addr Destination address + */ +static inline void dw_gdma_ll_channel_set_dst_addr(dw_gdma_dev_t *dev, uint8_t channel, uint32_t dst_addr) +{ + dev->ch[channel].dar0.dar0 = dst_addr; +} + +/** + * @brief Set the number of data to be transferred + * + * @note data_transfer_width * item_amount determins the total bytes in one block transfer. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param item_numbers Number of transfer items + */ +static inline void dw_gdma_ll_channel_set_trans_amount(dw_gdma_dev_t *dev, uint8_t channel, uint32_t item_numbers) +{ + dev->ch[channel].block_ts0.block_ts = item_numbers - 1; +} + +/** + * @brief Set the source master port + * + * @note The choice of master port depends on the location of the source data. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param port Source master port + */ +static inline void dw_gdma_ll_channel_set_src_master_port(dw_gdma_dev_t *dev, uint8_t channel, uint32_t port) +{ + dev->ch[channel].ctl0.sms = port; +} + +/** + * @brief Set the destination master port + * + * @note The choice of master port depends on the location of the destination data. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param port Destination master port + */ +static inline void dw_gdma_ll_channel_set_dst_master_port(dw_gdma_dev_t *dev, uint8_t channel, uint32_t port) +{ + dev->ch[channel].ctl0.dms = port; +} + +/** + * @brief Enable the source address increment + * + * @note Increase the source address by the data width after each transfer + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_channel_enable_src_addr_increment(dw_gdma_dev_t *dev, uint8_t channel, bool en) +{ + dev->ch[channel].ctl0.sinc = !en; +} + +/** + * @brief Enable the destination address increment + * + * @note Increase the destination address by the data width after each transfer + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_channel_enable_dst_addr_increment(dw_gdma_dev_t *dev, uint8_t channel, bool en) +{ + dev->ch[channel].ctl0.dinc = !en; +} + +/** + * @brief Set the transfer width of the source data + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param width Transfer width + */ +static inline void dw_gdma_ll_channel_set_src_trans_width(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_transfer_width_t width) +{ + dev->ch[channel].ctl0.src_tr_width = width; +} + +/** + * @brief Set the transfer width of the destination data + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param width Transfer width + */ +static inline void dw_gdma_ll_channel_set_dst_trans_width(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_transfer_width_t width) +{ + dev->ch[channel].ctl0.dst_tr_width = width; +} + +/** + * @brief Set the number of data items that can be transferred in a single burst transaction for the source master port + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param items Number of data items + */ +static inline void dw_gdma_ll_channel_set_src_burst_items(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_burst_items_t items) +{ + dev->ch[channel].ctl0.src_msize = items; +} + +/** + * @brief Set the number of data items that can be transferred in a single burst transaction for the destination master port + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param items Number of data items + */ +static inline void dw_gdma_ll_channel_set_dst_burst_items(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_burst_items_t items) +{ + dev->ch[channel].ctl0.dst_msize = items; +} + +/** + * @brief Set the source burst length + * + * @note This controls how many times the DMA controller will ask for data from the source device in a single burst transaction. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param len Burst length + */ +static inline void dw_gdma_ll_channel_set_src_burst_len(dw_gdma_dev_t *dev, uint8_t channel, uint32_t len) +{ + dev->ch[channel].ctl1.arlen_en = 1; + dev->ch[channel].ctl1.arlen = len - 1; +} + +/** + * @brief Set the destination burst length + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param len Burst length + */ +static inline void dw_gdma_ll_channel_set_dst_burst_len(dw_gdma_dev_t *dev, uint8_t channel, uint32_t len) +{ + dev->ch[channel].ctl1.awlen_en = 1; + dev->ch[channel].ctl1.awlen = len - 1; +} + +/** + * @brief Enable to generate an interrupt when the block transfer is done + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param en True to enable, false to disable + */ +static inline void dw_gdma_ll_channel_enable_intr_block_trans_done(dw_gdma_dev_t *dev, uint8_t channel, bool en) +{ + dev->ch[channel].ctl1.ioc_blktfr = en; +} + +/** + * @brief Set the multi block transfer type for the source peripheral + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param type Multi block transfer type + */ +static inline void dw_gdma_ll_channel_set_src_multi_block_type(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_multi_block_type_t type) +{ + dev->ch[channel].cfg0.src_multblk_type = type; +} + +/** + * @brief Set the multi block transfer type for the destination peripheral + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param type Multi block transfer type + */ +static inline void dw_gdma_ll_channel_set_dst_multi_block_type(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_multi_block_type_t type) +{ + dev->ch[channel].cfg0.dst_multblk_type = type; +} + +/** + * @brief Set the unique ID for the source peripheral + * + * @note This ID is related to Out-of-order transaction + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param uid Unique ID + */ +static inline void dw_gdma_ll_channel_set_src_uid(dw_gdma_dev_t *dev, uint8_t channel, uint32_t uid) +{ + dev->ch[channel].cfg0.rd_uid = uid; +} + +/** + * @brief Set the unique ID for the destination peripheral + * + * @note This ID is related to Out-of-order transaction + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param uid Unique ID + */ +static inline void dw_gdma_ll_channel_set_dst_uid(dw_gdma_dev_t *dev, uint8_t channel, uint32_t uid) +{ + dev->ch[channel].cfg0.wr_uid = uid; +} + +/** + * @brief Set transfer type and flow control + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param flow Transfer flow control + */ +static inline void dw_gdma_ll_channel_set_trans_flow(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_trans_flow_t flow) +{ + dev->ch[channel].cfg1.tt_fc = flow; +} + +/** + * @brief Set the handshaking interface for source requests + * + * @note If source peripheral is memory, this configuration is ignored. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param hs Handshaking interface + */ +static inline void dw_gdma_ll_channel_set_src_handshake_interface(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_handshake_interface_t hs) +{ + dev->ch[channel].cfg1.hs_sel_src = hs; +} + +/** + * @brief Set the handshaking interface for destination requests + * + * @note If destination peripheral is memory, this configuration is ignored. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param hs Handshaking interface + */ +static inline void dw_gdma_ll_channel_set_dst_handshake_interface(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_handshake_interface_t hs) +{ + dev->ch[channel].cfg1.hs_sel_dst = hs; +} + +/** + * @brief Set the source handshaking peripheral + * + * @note Only valid for hardware handshake interface + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param periph Peripheral ID + */ +static inline void dw_gdma_ll_channel_set_src_handshake_periph(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_hw_handshake_periph_t periph) +{ + dev->ch[channel].cfg1.src_per = periph; +} + +/** + * @brief Set the destination handshaking peripheral + * + * @note Only valid for hardware handshake interface + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param periph Peripheral ID + */ +static inline void dw_gdma_ll_channel_set_dst_handshake_periph(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_hw_handshake_periph_t periph) +{ + dev->ch[channel].cfg1.dst_per = periph; +} + +/** + * @brief Set channel priority + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param priority Priority number, bigger number means higher priority + */ +static inline void dw_gdma_ll_channel_set_priority(dw_gdma_dev_t *dev, uint8_t channel, uint32_t priority) +{ + dev->ch[channel].cfg1.ch_prior = priority; +} + +/** + * @brief Lock the DMA channel, so the channel can have exclusive access to the bus + * + * @note channel locking is supported only for M2M transfer at Block transfer and DMA transfer levels + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param lock_level At which level the lock is applied + */ +static inline void dw_gdma_ll_channel_lock(dw_gdma_dev_t *dev, uint8_t channel, dw_gdma_ll_lock_level_t lock_level) +{ + dev->ch[channel].cfg1.lock_ch_l = lock_level; + dev->ch[channel].cfg1.lock_ch = 1; +} + +/** + * @brief Unlock the DMA channel + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + */ +static inline void dw_gdma_ll_channel_unlock(dw_gdma_dev_t *dev, uint8_t channel) +{ + dev->ch[channel].cfg1.lock_ch = 0; +} + +/** + * @brief Set the outstanding request limit for the source peripheral + * + * @note The actual number of outstanding requests are limited by the capabilities of the source and destination interfaces. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param limit Outstanding request limit + */ +static inline void dw_gdma_ll_channel_set_src_outstanding_limit(dw_gdma_dev_t *dev, uint8_t channel, uint32_t limit) +{ + dev->ch[channel].cfg1.src_osr_lmt = limit - 1; +} + +/** + * @brief Set the outstanding request limit for the destination peripheral + * + * @note The actual number of outstanding requests are limited by the capabilities of the source and destination interfaces. + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param limit Outstanding request limit + */ +static inline void dw_gdma_ll_channel_set_dst_outstanding_limit(dw_gdma_dev_t *dev, uint8_t channel, uint32_t limit) +{ + dev->ch[channel].cfg1.dst_osr_lmt = limit - 1; +} + +/** + * @brief Set the address of the first link list item + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param addr Address of the first link list item, it must be aligned 64 + */ +static inline void dw_gdma_ll_channel_set_link_list_head_addr(dw_gdma_dev_t *dev, uint8_t channel, uint32_t addr) +{ + dev->ch[channel].llp0.loc0 = addr >> 6; +} + +/** + * @brief Set the master port of the memory which holds the link list + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param port Master port + */ +static inline void dw_gdma_ll_channel_set_link_list_master_port(dw_gdma_dev_t *dev, uint8_t channel, uint32_t port) +{ + dev->ch[channel].llp0.lms = port; +} + +/** + * @brief Get the total number of data that transferred for the previous block transfer. + * + * @note for normal transfer, this value is the same as the value of `dw_gdma_ll_channel_set_trans_amount` + * @note if any error occurs, the transfer might be terminated early, this function returns actual data transferred without error. + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @return Total number of data that transferred for the previous block transfer + */ +static inline uint32_t dw_gdma_ll_channel_get_trans_amount(dw_gdma_dev_t *dev, uint8_t channel) +{ + return dev->ch[channel].status0.cmpltd_blk_tfr_size; +} + +/** + * @brief Resume the multi-block transfer + * + * @note This function is only valid for linked list or shadow register based multi-block transfer + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + */ +static inline void dw_gdma_ll_channel_resume_multi_block_transfer(dw_gdma_dev_t *dev, uint8_t channel) +{ + // this register is write-only, we can't do read-modify-write + dev->ch[channel].blk_tfr_resumereq0.val = 0x01; +} + +/** + * @brief Set the address to fetch the source status of the DMA channel + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param addr Address to fetch the source status of the DMA channel + */ +static inline void dw_gdma_ll_channel_set_src_status_fetch_addr(dw_gdma_dev_t *dev, uint8_t channel, uint32_t addr) +{ + dev->ch[channel].sstatar0.sstatar0 = addr; +} + +/** + * @brief Set the address to fetch the destination status of the DMA channel + * + * @param dev Pointer to the DW_GDMA registers + * @param channel Channel number + * @param addr Address to fetch the destination status of the DMA channel + */ +static inline void dw_gdma_ll_channel_set_dst_status_fetch_addr(dw_gdma_dev_t *dev, uint8_t channel, uint32_t addr) +{ + dev->ch[channel].dstatar0.dstatar0 = addr; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/gdma_hal_ahb_v1.c b/components/hal/gdma_hal_ahb_v1.c index 38d02a887bc0..4c8cf98b6a95 100644 --- a/components/hal/gdma_hal_ahb_v1.c +++ b/components/hal/gdma_hal_ahb_v1.c @@ -106,6 +106,7 @@ void gdma_ahb_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channe { if (dir == GDMA_CHANNEL_DIRECTION_RX) { gdma_ll_rx_enable_owner_check(hal->dev, chan_id, en_owner_check); + // RX direction always has the descriptor write-back feature enabled } else { gdma_ll_tx_enable_owner_check(hal->dev, chan_id, en_owner_check); gdma_ll_tx_enable_auto_write_back(hal->dev, chan_id, en_desc_write_back); diff --git a/components/hal/gdma_hal_ahb_v2.c b/components/hal/gdma_hal_ahb_v2.c index 58a0dcfa1ca3..5ba655d96331 100644 --- a/components/hal/gdma_hal_ahb_v2.c +++ b/components/hal/gdma_hal_ahb_v2.c @@ -95,6 +95,7 @@ void gdma_ahb_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channe { if (dir == GDMA_CHANNEL_DIRECTION_RX) { ahb_dma_ll_rx_enable_owner_check(hal->ahb_dma_dev, chan_id, en_owner_check); + // RX direction always has the descriptor write-back feature enabled } else { ahb_dma_ll_tx_enable_owner_check(hal->ahb_dma_dev, chan_id, en_owner_check); ahb_dma_ll_tx_enable_auto_write_back(hal->ahb_dma_dev, chan_id, en_desc_write_back); diff --git a/components/hal/gdma_hal_axi.c b/components/hal/gdma_hal_axi.c index 9b23c035a694..ce22fb2f010e 100644 --- a/components/hal/gdma_hal_axi.c +++ b/components/hal/gdma_hal_axi.c @@ -95,6 +95,7 @@ void gdma_axi_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channe { if (dir == GDMA_CHANNEL_DIRECTION_RX) { axi_dma_ll_rx_enable_owner_check(hal->axi_dma_dev, chan_id, en_owner_check); + // RX direction always has the descriptor write-back feature enabled } else { axi_dma_ll_tx_enable_owner_check(hal->axi_dma_dev, chan_id, en_owner_check); axi_dma_ll_tx_enable_auto_write_back(hal->axi_dma_dev, chan_id, en_desc_write_back); diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index 850447700583..1ad7f3e04636 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -16,7 +16,6 @@ #endif #if SOC_GDMA_SUPPORTED -#include "soc/gdma_struct.h" #include "hal/gdma_ll.h" #endif diff --git a/components/hal/include/hal/dw_gdma_hal.h b/components/hal/include/hal/dw_gdma_hal.h new file mode 100644 index 000000000000..fa030c46eaf7 --- /dev/null +++ b/components/hal/include/hal/dw_gdma_hal.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief DW_GDMA SOC layer representation + */ +typedef struct dw_gdma_dev_t *dw_gdma_soc_handle_t; + +/** + * @brief DW_GDMA HAL driver context + */ +typedef struct { + dw_gdma_soc_handle_t dev; /*!< Pointer to the DW_GDMA registers */ +} dw_gdma_hal_context_t; + +/** + * @brief DW_GDMA HAL driver configuration + */ +typedef struct { +} dw_gdma_hal_config_t; + +/** + * @brief DW_GDMA HAL driver initialization + * + * @note Caller should malloc the memory for the hal context + * + * @param hal Pointer to the HAL driver context + * @param config Pointer to the HAL driver configuration + */ +void dw_gdma_hal_init(dw_gdma_hal_context_t *hal, const dw_gdma_hal_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32p4/include/soc/gdma_reg.h b/components/soc/esp32p4/include/soc/dw_gdma_reg.h similarity index 100% rename from components/soc/esp32p4/include/soc/gdma_reg.h rename to components/soc/esp32p4/include/soc/dw_gdma_reg.h diff --git a/components/soc/esp32p4/include/soc/dw_gdma_struct.h b/components/soc/esp32p4/include/soc/dw_gdma_struct.h new file mode 100644 index 000000000000..6b08a95c6e85 --- /dev/null +++ b/components/soc/esp32p4/include/soc/dw_gdma_struct.h @@ -0,0 +1,1780 @@ +/** + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** Group: Version Register */ +/** Type of id0 register + * NA + */ +typedef union { + struct { + /** dmac_id : RO; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t dmac_id: 32; + }; + uint32_t val; +} dmac_id0_reg_t; + +/** Type of compver0 register + * NA + */ +typedef union { + struct { + /** dmac_compver : RO; bitpos: [31:0]; default: 842018858; + * NA + */ + uint32_t dmac_compver: 32; + }; + uint32_t val; +} dmac_compver0_reg_t; + +/** Group: Configuration Registers */ +/** Type of cfg0 register + * NA + */ +typedef union { + struct { + /** dmac_en : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t dmac_en: 1; + /** int_en : R/W; bitpos: [1]; default: 0; + * NA + */ + uint32_t int_en: 1; + uint32_t reserved_2: 30; + }; + uint32_t val; +} dmac_cfg0_reg_t; + +/** Type of chen0 register + * NA + */ +typedef union { + struct { + /** ch1_en : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t ch1_en: 1; + /** ch2_en : R/W; bitpos: [1]; default: 0; + * NA + */ + uint32_t ch2_en: 1; + /** ch3_en : R/W; bitpos: [2]; default: 0; + * NA + */ + uint32_t ch3_en: 1; + /** ch4_en : R/W; bitpos: [3]; default: 0; + * NA + */ + uint32_t ch4_en: 1; + uint32_t reserved_4: 4; + /** ch1_en_we : WO; bitpos: [8]; default: 0; + * NA + */ + uint32_t ch1_en_we: 1; + /** ch2_en_we : WO; bitpos: [9]; default: 0; + * NA + */ + uint32_t ch2_en_we: 1; + /** ch3_en_we : WO; bitpos: [10]; default: 0; + * NA + */ + uint32_t ch3_en_we: 1; + /** ch4_en_we : WO; bitpos: [11]; default: 0; + * NA + */ + uint32_t ch4_en_we: 1; + uint32_t reserved_12: 4; + /** ch1_susp : R/W; bitpos: [16]; default: 0; + * NA + */ + uint32_t ch1_susp: 1; + /** ch2_susp : R/W; bitpos: [17]; default: 0; + * NA + */ + uint32_t ch2_susp: 1; + /** ch3_susp : R/W; bitpos: [18]; default: 0; + * NA + */ + uint32_t ch3_susp: 1; + /** ch4_susp : R/W; bitpos: [19]; default: 0; + * NA + */ + uint32_t ch4_susp: 1; + uint32_t reserved_20: 4; + /** ch1_susp_we : WO; bitpos: [24]; default: 0; + * NA + */ + uint32_t ch1_susp_we: 1; + /** ch2_susp_we : WO; bitpos: [25]; default: 0; + * NA + */ + uint32_t ch2_susp_we: 1; + /** ch3_susp_we : WO; bitpos: [26]; default: 0; + * NA + */ + uint32_t ch3_susp_we: 1; + /** ch4_susp_we : WO; bitpos: [27]; default: 0; + * NA + */ + uint32_t ch4_susp_we: 1; + uint32_t reserved_28: 4; + }; + uint32_t val; +} dmac_chen0_reg_t; + +/** Type of chen1 register + * NA + */ +typedef union { + struct { + /** ch1_abort : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t ch1_abort: 1; + /** ch2_abort : R/W; bitpos: [1]; default: 0; + * NA + */ + uint32_t ch2_abort: 1; + /** ch3_abort : R/W; bitpos: [2]; default: 0; + * NA + */ + uint32_t ch3_abort: 1; + /** ch4_abort : R/W; bitpos: [3]; default: 0; + * NA + */ + uint32_t ch4_abort: 1; + uint32_t reserved_4: 4; + /** ch1_abort_we : WO; bitpos: [8]; default: 0; + * NA + */ + uint32_t ch1_abort_we: 1; + /** ch2_abort_we : WO; bitpos: [9]; default: 0; + * NA + */ + uint32_t ch2_abort_we: 1; + /** ch3_abort_we : WO; bitpos: [10]; default: 0; + * NA + */ + uint32_t ch3_abort_we: 1; + /** ch4_abort_we : WO; bitpos: [11]; default: 0; + * NA + */ + uint32_t ch4_abort_we: 1; + uint32_t reserved_12: 20; + }; + uint32_t val; +} dmac_chen1_reg_t; + +/** Type of reset0 register + * NA + */ +typedef union { + struct { + /** dmac_rst : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t dmac_rst: 1; + uint32_t reserved_1: 31; + }; + uint32_t val; +} dmac_reset0_reg_t; + +/** Type of lowpower_cfg0 register + * NA + */ +typedef union { + struct { + /** gbl_cslp_en : R/W; bitpos: [0]; default: 1; + * NA + */ + uint32_t gbl_cslp_en: 1; + /** chnl_cslp_en : R/W; bitpos: [1]; default: 1; + * NA + */ + uint32_t chnl_cslp_en: 1; + /** sbiu_cslp_en : R/W; bitpos: [2]; default: 1; + * NA + */ + uint32_t sbiu_cslp_en: 1; + /** mxif_cslp_en : R/W; bitpos: [3]; default: 1; + * NA + */ + uint32_t mxif_cslp_en: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} dmac_lowpower_cfg0_reg_t; + +/** Type of lowpower_cfg1 register + * NA + */ +typedef union { + struct { + /** glch_lpdly : R/W; bitpos: [7:0]; default: 64; + * NA + */ + uint32_t glch_lpdly: 8; + /** sbiu_lpdly : R/W; bitpos: [15:8]; default: 64; + * NA + */ + uint32_t sbiu_lpdly: 8; + /** mxif_lpdly : R/W; bitpos: [23:16]; default: 64; + * NA + */ + uint32_t mxif_lpdly: 8; + uint32_t reserved_24: 8; + }; + uint32_t val; +} dmac_lowpower_cfg1_reg_t; + +/** Type of chn_sar0 register + * NA + */ +typedef union { + struct { + /** sar0 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t sar0: 32; + }; + uint32_t val; +} dmac_chn_sar0_reg_t; + +/** Type of chn_sar1 register + * NA + */ +typedef union { + struct { + /** sar1 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t sar1: 32; + }; + uint32_t val; +} dmac_chn_sar1_reg_t; + +/** Type of chn_dar0 register + * NA + */ +typedef union { + struct { + /** dar0 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t dar0: 32; + }; + uint32_t val; +} dmac_chn_dar0_reg_t; + +/** Type of chn_dar1 register + * NA + */ +typedef union { + struct { + /** dar1 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t dar1: 32; + }; + uint32_t val; +} dmac_chn_dar1_reg_t; + +/** Type of chn_block_ts0 register + * NA + */ +typedef union { + struct { + /** block_ts : R/W; bitpos: [21:0]; default: 0; + * NA + */ + uint32_t block_ts: 22; + uint32_t reserved_22: 10; + }; + uint32_t val; +} dmac_chn_block_ts0_reg_t; + +/** Type of chn_ctl0 register + * NA + */ +typedef union { + struct { + /** sms : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t sms: 1; + uint32_t reserved_1: 1; + /** dms : R/W; bitpos: [2]; default: 0; + * NA + */ + uint32_t dms: 1; + uint32_t reserved_3: 1; + /** sinc : R/W; bitpos: [4]; default: 0; + * NA + */ + uint32_t sinc: 1; + uint32_t reserved_5: 1; + /** dinc : R/W; bitpos: [6]; default: 0; + * NA + */ + uint32_t dinc: 1; + uint32_t reserved_7: 1; + /** src_tr_width : R/W; bitpos: [10:8]; default: 2; + * NA + */ + uint32_t src_tr_width: 3; + /** dst_tr_width : R/W; bitpos: [13:11]; default: 2; + * NA + */ + uint32_t dst_tr_width: 3; + /** src_msize : R/W; bitpos: [17:14]; default: 0; + * NA + */ + uint32_t src_msize: 4; + /** dst_msize : R/W; bitpos: [21:18]; default: 0; + * NA + */ + uint32_t dst_msize: 4; + /** ar_cache : R/W; bitpos: [25:22]; default: 0; + * NA + */ + uint32_t ar_cache: 4; + /** aw_cache : R/W; bitpos: [29:26]; default: 0; + * NA + */ + uint32_t aw_cache: 4; + /** nonposted_lastwrite_en : R/W; bitpos: [30]; default: 0; + * NA + */ + uint32_t nonposted_lastwrite_en: 1; + uint32_t reserved_31: 1; + }; + uint32_t val; +} dmac_chn_ctl0_reg_t; + +/** Type of chn_ctl1 register + * NA + */ +typedef union { + struct { + /** ar_prot : R/W; bitpos: [2:0]; default: 0; + * NA + */ + uint32_t ar_prot: 3; + /** aw_prot : R/W; bitpos: [5:3]; default: 0; + * NA + */ + uint32_t aw_prot: 3; + /** arlen_en : R/W; bitpos: [6]; default: 0; + * NA + */ + uint32_t arlen_en: 1; + /** arlen : R/W; bitpos: [14:7]; default: 0; + * NA + */ + uint32_t arlen: 8; + /** awlen_en : R/W; bitpos: [15]; default: 0; + * NA + */ + uint32_t awlen_en: 1; + /** awlen : R/W; bitpos: [23:16]; default: 0; + * NA + */ + uint32_t awlen: 8; + /** src_stat_en : R/W; bitpos: [24]; default: 0; + * NA + */ + uint32_t src_stat_en: 1; + /** dst_stat_en : R/W; bitpos: [25]; default: 0; + * NA + */ + uint32_t dst_stat_en: 1; + /** ioc_blktfr : R/W; bitpos: [26]; default: 0; + * NA + */ + uint32_t ioc_blktfr: 1; + uint32_t reserved_27: 3; + /** shadowreg_or_lli_last : R/W; bitpos: [30]; default: 0; + * NA + */ + uint32_t shadowreg_or_lli_last: 1; + /** shadowreg_or_lli_valid : R/W; bitpos: [31]; default: 0; + * NA + */ + uint32_t shadowreg_or_lli_valid: 1; + }; + uint32_t val; +} dmac_chn_ctl1_reg_t; + +/** Type of chn_cfg0 register + * NA + */ +typedef union { + struct { + /** src_multblk_type : R/W; bitpos: [1:0]; default: 0; + * NA + */ + uint32_t src_multblk_type: 2; + /** dst_multblk_type : R/W; bitpos: [3:2]; default: 0; + * NA + */ + uint32_t dst_multblk_type: 2; + uint32_t reserved_4: 14; + /** rd_uid : RO; bitpos: [21:18]; default: 0; + * NA + */ + uint32_t rd_uid: 4; + uint32_t reserved_22: 3; + /** wr_uid : RO; bitpos: [28:25]; default: 0; + * NA + */ + uint32_t wr_uid: 4; + uint32_t reserved_29: 3; + }; + uint32_t val; +} dmac_chn_cfg0_reg_t; + +/** Type of chn_cfg1 register + * NA + */ +typedef union { + struct { + /** tt_fc : R/W; bitpos: [2:0]; default: 3; + * NA + */ + uint32_t tt_fc: 3; + /** hs_sel_src : R/W; bitpos: [3]; default: 1; + * NA + */ + uint32_t hs_sel_src: 1; + /** hs_sel_dst : R/W; bitpos: [4]; default: 1; + * NA + */ + uint32_t hs_sel_dst: 1; + /** src_hwhs_pol : RO; bitpos: [5]; default: 0; + * NA + */ + uint32_t src_hwhs_pol: 1; + /** dst_hwhs_pol : RO; bitpos: [6]; default: 0; + * NA + */ + uint32_t dst_hwhs_pol: 1; + /** src_per : R/W; bitpos: [8:7]; default: 0; + * NA + */ + uint32_t src_per: 2; + uint32_t reserved_9: 3; + /** dst_per : R/W; bitpos: [13:12]; default: 0; + * NA + */ + uint32_t dst_per: 2; + uint32_t reserved_14: 3; + /** ch_prior : R/W; bitpos: [19:17]; default: 3; + * NA + */ + uint32_t ch_prior: 3; + /** lock_ch : RO; bitpos: [20]; default: 0; + * NA + */ + uint32_t lock_ch: 1; + /** lock_ch_l : RO; bitpos: [22:21]; default: 0; + * NA + */ + uint32_t lock_ch_l: 2; + /** src_osr_lmt : R/W; bitpos: [26:23]; default: 0; + * NA + */ + uint32_t src_osr_lmt: 4; + /** dst_osr_lmt : R/W; bitpos: [30:27]; default: 0; + * NA + */ + uint32_t dst_osr_lmt: 4; + uint32_t reserved_31: 1; + }; + uint32_t val; +} dmac_chn_cfg1_reg_t; + +/** Type of chn_llp0 register + * NA + */ +typedef union { + struct { + /** lms : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t lms: 1; + uint32_t reserved_1: 5; + /** loc0 : R/W; bitpos: [31:6]; default: 0; + * NA + */ + uint32_t loc0: 26; + }; + uint32_t val; +} dmac_chn_llp0_reg_t; + +/** Type of chn_llp1 register + * NA + */ +typedef union { + struct { + /** loc1 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t loc1: 32; + }; + uint32_t val; +} dmac_chn_llp1_reg_t; + +/** Type of chn_swhssrc0 register + * NA + */ +typedef union { + struct { + /** swhs_req_src : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t swhs_req_src: 1; + /** swhs_req_src_we : WO; bitpos: [1]; default: 0; + * NA + */ + uint32_t swhs_req_src_we: 1; + /** swhs_sglreq_src : R/W; bitpos: [2]; default: 0; + * NA + */ + uint32_t swhs_sglreq_src: 1; + /** swhs_sglreq_src_we : WO; bitpos: [3]; default: 0; + * NA + */ + uint32_t swhs_sglreq_src_we: 1; + /** swhs_lst_src : R/W; bitpos: [4]; default: 0; + * NA + */ + uint32_t swhs_lst_src: 1; + /** swhs_lst_src_we : WO; bitpos: [5]; default: 0; + * NA + */ + uint32_t swhs_lst_src_we: 1; + uint32_t reserved_6: 26; + }; + uint32_t val; +} dmac_chn_swhssrc0_reg_t; + +/** Type of chn_swhsdst0 register + * NA + */ +typedef union { + struct { + /** swhs_req_dst : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t swhs_req_dst: 1; + /** swhs_req_dst_we : WO; bitpos: [1]; default: 0; + * NA + */ + uint32_t swhs_req_dst_we: 1; + /** swhs_sglreq_dst : R/W; bitpos: [2]; default: 0; + * NA + */ + uint32_t swhs_sglreq_dst: 1; + /** swhs_sglreq_dst_we : WO; bitpos: [3]; default: 0; + * NA + */ + uint32_t swhs_sglreq_dst_we: 1; + /** swhs_lst_dst : R/W; bitpos: [4]; default: 0; + * NA + */ + uint32_t swhs_lst_dst: 1; + /** swhs_lst_dst_we : WO; bitpos: [5]; default: 0; + * NA + */ + uint32_t swhs_lst_dst_we: 1; + uint32_t reserved_6: 26; + }; + uint32_t val; +} dmac_chn_swhsdst0_reg_t; + +/** Type of chn_blk_tfr_resumereq0 register + * NA + */ +typedef union { + struct { + /** blk_tfr_resumereq : WO; bitpos: [0]; default: 0; + * NA + */ + uint32_t blk_tfr_resumereq: 1; + uint32_t reserved_1: 31; + }; + uint32_t val; +} dmac_chn_blk_tfr_resumereq0_reg_t; + +/** Type of chn_axi_id0 register + * NA + */ +typedef union { + struct { + /** axi_read_id_suffix : R/W; bitpos: [0]; default: 0; + * NA + */ + uint32_t axi_read_id_suffix: 1; + uint32_t reserved_1: 15; + /** axi_write_id_suffix : R/W; bitpos: [16]; default: 0; + * NA + */ + uint32_t axi_write_id_suffix: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} dmac_chn_axi_id0_reg_t; + +/** Type of chn_axi_qos0 register + * NA + */ +typedef union { + struct { + /** axi_awqos : R/W; bitpos: [3:0]; default: 0; + * NA + */ + uint32_t axi_awqos: 4; + /** axi_arqos : R/W; bitpos: [7:4]; default: 0; + * NA + */ + uint32_t axi_arqos: 4; + uint32_t reserved_8: 24; + }; + uint32_t val; +} dmac_chn_axi_qos0_reg_t; + +/** Group: Interrupt Registers */ +/** Type of intstatus0 register + * NA + */ +typedef union { + struct { + /** ch1_intstat : RO; bitpos: [0]; default: 0; + * NA + */ + uint32_t ch1_intstat: 1; + /** ch2_intstat : RO; bitpos: [1]; default: 0; + * NA + */ + uint32_t ch2_intstat: 1; + /** ch3_intstat : RO; bitpos: [2]; default: 0; + * NA + */ + uint32_t ch3_intstat: 1; + /** ch4_intstat : RO; bitpos: [3]; default: 0; + * NA + */ + uint32_t ch4_intstat: 1; + uint32_t reserved_4: 12; + /** commonreg_intstat : RO; bitpos: [16]; default: 0; + * NA + */ + uint32_t commonreg_intstat: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} dmac_intstatus0_reg_t; + +/** Type of commonreg_intclear0 register + * NA + */ +typedef union { + struct { + /** clear_slvif_commonreg_dec_err_intstat : WO; bitpos: [0]; default: 0; + * NA + */ + uint32_t clear_slvif_commonreg_dec_err_intstat: 1; + /** clear_slvif_commonreg_wr2ro_err_intstat : WO; bitpos: [1]; default: 0; + * NA + */ + uint32_t clear_slvif_commonreg_wr2ro_err_intstat: 1; + /** clear_slvif_commonreg_rd2wo_err_intstat : WO; bitpos: [2]; default: 0; + * NA + */ + uint32_t clear_slvif_commonreg_rd2wo_err_intstat: 1; + /** clear_slvif_commonreg_wronhold_err_intstat : WO; bitpos: [3]; default: 0; + * NA + */ + uint32_t clear_slvif_commonreg_wronhold_err_intstat: 1; + uint32_t reserved_4: 3; + /** clear_slvif_commonreg_wrparity_err_intstat : WO; bitpos: [7]; default: 0; + * NA + */ + uint32_t clear_slvif_commonreg_wrparity_err_intstat: 1; + /** clear_slvif_undefinedreg_dec_err_intstat : WO; bitpos: [8]; default: 0; + * NA + */ + uint32_t clear_slvif_undefinedreg_dec_err_intstat: 1; + /** clear_mxif1_rch0_eccprot_correrr_intstat : WO; bitpos: [9]; default: 0; + * NA + */ + uint32_t clear_mxif1_rch0_eccprot_correrr_intstat: 1; + /** clear_mxif1_rch0_eccprot_uncorrerr_intstat : WO; bitpos: [10]; default: 0; + * NA + */ + uint32_t clear_mxif1_rch0_eccprot_uncorrerr_intstat: 1; + /** clear_mxif1_rch1_eccprot_correrr_intstat : WO; bitpos: [11]; default: 0; + * NA + */ + uint32_t clear_mxif1_rch1_eccprot_correrr_intstat: 1; + /** clear_mxif1_rch1_eccprot_uncorrerr_intstat : WO; bitpos: [12]; default: 0; + * NA + */ + uint32_t clear_mxif1_rch1_eccprot_uncorrerr_intstat: 1; + /** clear_mxif1_bch_eccprot_correrr_intstat : WO; bitpos: [13]; default: 0; + * NA + */ + uint32_t clear_mxif1_bch_eccprot_correrr_intstat: 1; + /** clear_mxif1_bch_eccprot_uncorrerr_intstat : WO; bitpos: [14]; default: 0; + * NA + */ + uint32_t clear_mxif1_bch_eccprot_uncorrerr_intstat: 1; + /** clear_mxif2_rch0_eccprot_correrr_intstat : WO; bitpos: [15]; default: 0; + * NA + */ + uint32_t clear_mxif2_rch0_eccprot_correrr_intstat: 1; + /** clear_mxif2_rch0_eccprot_uncorrerr_intstat : WO; bitpos: [16]; default: 0; + * NA + */ + uint32_t clear_mxif2_rch0_eccprot_uncorrerr_intstat: 1; + /** clear_mxif2_rch1_eccprot_correrr_intstat : WO; bitpos: [17]; default: 0; + * NA + */ + uint32_t clear_mxif2_rch1_eccprot_correrr_intstat: 1; + /** clear_mxif2_rch1_eccprot_uncorrerr_intstat : WO; bitpos: [18]; default: 0; + * NA + */ + uint32_t clear_mxif2_rch1_eccprot_uncorrerr_intstat: 1; + /** clear_mxif2_bch_eccprot_correrr_intstat : WO; bitpos: [19]; default: 0; + * NA + */ + uint32_t clear_mxif2_bch_eccprot_correrr_intstat: 1; + /** clear_mxif2_bch_eccprot_uncorrerr_intstat : WO; bitpos: [20]; default: 0; + * NA + */ + uint32_t clear_mxif2_bch_eccprot_uncorrerr_intstat: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} dmac_commonreg_intclear0_reg_t; + +/** Type of commonreg_intstatus_enable0 register + * NA + */ +typedef union { + struct { + /** enable_slvif_commonreg_dec_err_intstat : R/W; bitpos: [0]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_dec_err_intstat: 1; + /** enable_slvif_commonreg_wr2ro_err_intstat : R/W; bitpos: [1]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_wr2ro_err_intstat: 1; + /** enable_slvif_commonreg_rd2wo_err_intstat : R/W; bitpos: [2]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_rd2wo_err_intstat: 1; + /** enable_slvif_commonreg_wronhold_err_intstat : R/W; bitpos: [3]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_wronhold_err_intstat: 1; + uint32_t reserved_4: 3; + /** enable_slvif_commonreg_wrparity_err_intstat : RO; bitpos: [7]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_wrparity_err_intstat: 1; + /** enable_slvif_undefinedreg_dec_err_intstat : R/W; bitpos: [8]; default: 1; + * NA + */ + uint32_t enable_slvif_undefinedreg_dec_err_intstat: 1; + /** enable_mxif1_rch0_eccprot_correrr_intstat : RO; bitpos: [9]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch0_eccprot_correrr_intstat: 1; + /** enable_mxif1_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [10]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch0_eccprot_uncorrerr_intstat: 1; + /** enable_mxif1_rch1_eccprot_correrr_intstat : RO; bitpos: [11]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch1_eccprot_correrr_intstat: 1; + /** enable_mxif1_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [12]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch1_eccprot_uncorrerr_intstat: 1; + /** enable_mxif1_bch_eccprot_correrr_intstat : RO; bitpos: [13]; default: 1; + * NA + */ + uint32_t enable_mxif1_bch_eccprot_correrr_intstat: 1; + /** enable_mxif1_bch_eccprot_uncorrerr_intstat : RO; bitpos: [14]; default: 1; + * NA + */ + uint32_t enable_mxif1_bch_eccprot_uncorrerr_intstat: 1; + /** enable_mxif2_rch0_eccprot_correrr_intstat : RO; bitpos: [15]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch0_eccprot_correrr_intstat: 1; + /** enable_mxif2_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [16]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch0_eccprot_uncorrerr_intstat: 1; + /** enable_mxif2_rch1_eccprot_correrr_intstat : RO; bitpos: [17]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch1_eccprot_correrr_intstat: 1; + /** enable_mxif2_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [18]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch1_eccprot_uncorrerr_intstat: 1; + /** enable_mxif2_bch_eccprot_correrr_intstat : RO; bitpos: [19]; default: 1; + * NA + */ + uint32_t enable_mxif2_bch_eccprot_correrr_intstat: 1; + /** enable_mxif2_bch_eccprot_uncorrerr_intstat : RO; bitpos: [20]; default: 1; + * NA + */ + uint32_t enable_mxif2_bch_eccprot_uncorrerr_intstat: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} dmac_commonreg_intstatus_enable0_reg_t; + +/** Type of commonreg_intsignal_enable0 register + * NA + */ +typedef union { + struct { + /** enable_slvif_commonreg_dec_err_intsignal : R/W; bitpos: [0]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_dec_err_intsignal: 1; + /** enable_slvif_commonreg_wr2ro_err_intsignal : R/W; bitpos: [1]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_wr2ro_err_intsignal: 1; + /** enable_slvif_commonreg_rd2wo_err_intsignal : R/W; bitpos: [2]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_rd2wo_err_intsignal: 1; + /** enable_slvif_commonreg_wronhold_err_intsignal : R/W; bitpos: [3]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_wronhold_err_intsignal: 1; + uint32_t reserved_4: 3; + /** enable_slvif_commonreg_wrparity_err_intsignal : RO; bitpos: [7]; default: 1; + * NA + */ + uint32_t enable_slvif_commonreg_wrparity_err_intsignal: 1; + /** enable_slvif_undefinedreg_dec_err_intsignal : R/W; bitpos: [8]; default: 1; + * NA + */ + uint32_t enable_slvif_undefinedreg_dec_err_intsignal: 1; + /** enable_mxif1_rch0_eccprot_correrr_intsignal : RO; bitpos: [9]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch0_eccprot_correrr_intsignal: 1; + /** enable_mxif1_rch0_eccprot_uncorrerr_intsignal : RO; bitpos: [10]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch0_eccprot_uncorrerr_intsignal: 1; + /** enable_mxif1_rch1_eccprot_correrr_intsignal : RO; bitpos: [11]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch1_eccprot_correrr_intsignal: 1; + /** enable_mxif1_rch1_eccprot_uncorrerr_intsignal : RO; bitpos: [12]; default: 1; + * NA + */ + uint32_t enable_mxif1_rch1_eccprot_uncorrerr_intsignal: 1; + /** enable_mxif1_bch_eccprot_correrr_intsignal : RO; bitpos: [13]; default: 1; + * NA + */ + uint32_t enable_mxif1_bch_eccprot_correrr_intsignal: 1; + /** enable_mxif1_bch_eccprot_uncorrerr_intsignal : RO; bitpos: [14]; default: 1; + * NA + */ + uint32_t enable_mxif1_bch_eccprot_uncorrerr_intsignal: 1; + /** enable_mxif2_rch0_eccprot_correrr_intsignal : RO; bitpos: [15]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch0_eccprot_correrr_intsignal: 1; + /** enable_mxif2_rch0_eccprot_uncorrerr_intsignal : RO; bitpos: [16]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch0_eccprot_uncorrerr_intsignal: 1; + /** enable_mxif2_rch1_eccprot_correrr_intsignal : RO; bitpos: [17]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch1_eccprot_correrr_intsignal: 1; + /** enable_mxif2_rch1_eccprot_uncorrerr_intsignal : RO; bitpos: [18]; default: 1; + * NA + */ + uint32_t enable_mxif2_rch1_eccprot_uncorrerr_intsignal: 1; + /** enable_mxif2_bch_eccprot_correrr_intsignal : RO; bitpos: [19]; default: 1; + * NA + */ + uint32_t enable_mxif2_bch_eccprot_correrr_intsignal: 1; + /** enable_mxif2_bch_eccprot_uncorrerr_intsignal : RO; bitpos: [20]; default: 1; + * NA + */ + uint32_t enable_mxif2_bch_eccprot_uncorrerr_intsignal: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} dmac_commonreg_intsignal_enable0_reg_t; + +/** Type of commonreg_intstatus0 register + * NA + */ +typedef union { + struct { + /** slvif_commonreg_dec_err_intstat : RO; bitpos: [0]; default: 0; + * NA + */ + uint32_t slvif_commonreg_dec_err_intstat: 1; + /** slvif_commonreg_wr2ro_err_intstat : RO; bitpos: [1]; default: 0; + * NA + */ + uint32_t slvif_commonreg_wr2ro_err_intstat: 1; + /** slvif_commonreg_rd2wo_err_intstat : RO; bitpos: [2]; default: 0; + * NA + */ + uint32_t slvif_commonreg_rd2wo_err_intstat: 1; + /** slvif_commonreg_wronhold_err_intstat : RO; bitpos: [3]; default: 0; + * NA + */ + uint32_t slvif_commonreg_wronhold_err_intstat: 1; + uint32_t reserved_4: 3; + /** slvif_commonreg_wrparity_err_intstat : RO; bitpos: [7]; default: 0; + * NA + */ + uint32_t slvif_commonreg_wrparity_err_intstat: 1; + /** slvif_undefinedreg_dec_err_intstat : RO; bitpos: [8]; default: 0; + * NA + */ + uint32_t slvif_undefinedreg_dec_err_intstat: 1; + /** mxif1_rch0_eccprot_correrr_intstat : RO; bitpos: [9]; default: 0; + * NA + */ + uint32_t mxif1_rch0_eccprot_correrr_intstat: 1; + /** mxif1_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [10]; default: 0; + * NA + */ + uint32_t mxif1_rch0_eccprot_uncorrerr_intstat: 1; + /** mxif1_rch1_eccprot_correrr_intstat : RO; bitpos: [11]; default: 0; + * NA + */ + uint32_t mxif1_rch1_eccprot_correrr_intstat: 1; + /** mxif1_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [12]; default: 0; + * NA + */ + uint32_t mxif1_rch1_eccprot_uncorrerr_intstat: 1; + /** mxif1_bch_eccprot_correrr_intstat : RO; bitpos: [13]; default: 0; + * NA + */ + uint32_t mxif1_bch_eccprot_correrr_intstat: 1; + /** mxif1_bch_eccprot_uncorrerr_intstat : RO; bitpos: [14]; default: 0; + * NA + */ + uint32_t mxif1_bch_eccprot_uncorrerr_intstat: 1; + /** mxif2_rch0_eccprot_correrr_intstat : RO; bitpos: [15]; default: 0; + * NA + */ + uint32_t mxif2_rch0_eccprot_correrr_intstat: 1; + /** mxif2_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [16]; default: 0; + * NA + */ + uint32_t mxif2_rch0_eccprot_uncorrerr_intstat: 1; + /** mxif2_rch1_eccprot_correrr_intstat : RO; bitpos: [17]; default: 0; + * NA + */ + uint32_t mxif2_rch1_eccprot_correrr_intstat: 1; + /** mxif2_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [18]; default: 0; + * NA + */ + uint32_t mxif2_rch1_eccprot_uncorrerr_intstat: 1; + /** mxif2_bch_eccprot_correrr_intstat : RO; bitpos: [19]; default: 0; + * NA + */ + uint32_t mxif2_bch_eccprot_correrr_intstat: 1; + /** mxif2_bch_eccprot_uncorrerr_intstat : RO; bitpos: [20]; default: 0; + * NA + */ + uint32_t mxif2_bch_eccprot_uncorrerr_intstat: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} dmac_commonreg_intstatus0_reg_t; + +/** Type of chn_intstatus_enable0 register + * NA + */ +typedef union { + struct { + /** enable_block_tfr_done_intstat : R/W; bitpos: [0]; default: 1; + * NA + */ + uint32_t enable_block_tfr_done_intstat: 1; + /** enable_dma_tfr_done_intstat : R/W; bitpos: [1]; default: 1; + * NA + */ + uint32_t enable_dma_tfr_done_intstat: 1; + uint32_t reserved_2: 1; + /** enable_src_transcomp_intstat : R/W; bitpos: [3]; default: 1; + * NA + */ + uint32_t enable_src_transcomp_intstat: 1; + /** enable_dst_transcomp_intstat : R/W; bitpos: [4]; default: 1; + * NA + */ + uint32_t enable_dst_transcomp_intstat: 1; + /** enable_src_dec_err_intstat : R/W; bitpos: [5]; default: 1; + * NA + */ + uint32_t enable_src_dec_err_intstat: 1; + /** enable_dst_dec_err_intstat : R/W; bitpos: [6]; default: 1; + * NA + */ + uint32_t enable_dst_dec_err_intstat: 1; + /** enable_src_slv_err_intstat : R/W; bitpos: [7]; default: 1; + * NA + */ + uint32_t enable_src_slv_err_intstat: 1; + /** enable_dst_slv_err_intstat : R/W; bitpos: [8]; default: 1; + * NA + */ + uint32_t enable_dst_slv_err_intstat: 1; + /** enable_lli_rd_dec_err_intstat : R/W; bitpos: [9]; default: 1; + * NA + */ + uint32_t enable_lli_rd_dec_err_intstat: 1; + /** enable_lli_wr_dec_err_intstat : R/W; bitpos: [10]; default: 1; + * NA + */ + uint32_t enable_lli_wr_dec_err_intstat: 1; + /** enable_lli_rd_slv_err_intstat : R/W; bitpos: [11]; default: 1; + * NA + */ + uint32_t enable_lli_rd_slv_err_intstat: 1; + /** enable_lli_wr_slv_err_intstat : R/W; bitpos: [12]; default: 1; + * NA + */ + uint32_t enable_lli_wr_slv_err_intstat: 1; + /** enable_shadowreg_or_lli_invalid_err_intstat : R/W; bitpos: [13]; default: 1; + * NA + */ + uint32_t enable_shadowreg_or_lli_invalid_err_intstat: 1; + /** enable_slvif_multiblktype_err_intstat : R/W; bitpos: [14]; default: 1; + * NA + */ + uint32_t enable_slvif_multiblktype_err_intstat: 1; + uint32_t reserved_15: 1; + /** enable_slvif_dec_err_intstat : R/W; bitpos: [16]; default: 1; + * NA + */ + uint32_t enable_slvif_dec_err_intstat: 1; + /** enable_slvif_wr2ro_err_intstat : R/W; bitpos: [17]; default: 1; + * NA + */ + uint32_t enable_slvif_wr2ro_err_intstat: 1; + /** enable_slvif_rd2rwo_err_intstat : R/W; bitpos: [18]; default: 1; + * NA + */ + uint32_t enable_slvif_rd2rwo_err_intstat: 1; + /** enable_slvif_wronchen_err_intstat : R/W; bitpos: [19]; default: 1; + * NA + */ + uint32_t enable_slvif_wronchen_err_intstat: 1; + /** enable_slvif_shadowreg_wron_valid_err_intstat : R/W; bitpos: [20]; default: 1; + * NA + */ + uint32_t enable_slvif_shadowreg_wron_valid_err_intstat: 1; + /** enable_slvif_wronhold_err_intstat : R/W; bitpos: [21]; default: 1; + * NA + */ + uint32_t enable_slvif_wronhold_err_intstat: 1; + uint32_t reserved_22: 3; + /** enable_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 1; + * NA + */ + uint32_t enable_slvif_wrparity_err_intstat: 1; + uint32_t reserved_26: 1; + /** enable_ch_lock_cleared_intstat : R/W; bitpos: [27]; default: 1; + * NA + */ + uint32_t enable_ch_lock_cleared_intstat: 1; + /** enable_ch_src_suspended_intstat : R/W; bitpos: [28]; default: 1; + * NA + */ + uint32_t enable_ch_src_suspended_intstat: 1; + /** enable_ch_suspended_intstat : R/W; bitpos: [29]; default: 1; + * NA + */ + uint32_t enable_ch_suspended_intstat: 1; + /** enable_ch_disabled_intstat : R/W; bitpos: [30]; default: 1; + * NA + */ + uint32_t enable_ch_disabled_intstat: 1; + /** enable_ch_aborted_intstat : R/W; bitpos: [31]; default: 1; + * NA + */ + uint32_t enable_ch_aborted_intstat: 1; + }; + uint32_t val; +} dmac_chn_intstatus_enable0_reg_t; + +/** Type of chn_intstatus_enable1 register + * NA + */ +typedef union { + struct { + /** enable_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_chmem_correrr_intstat: 1; + /** enable_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_chmem_uncorrerr_intstat: 1; + /** enable_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_uidmem_correrr_intstat: 1; + /** enable_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_uidmem_uncorrerr_intstat: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} dmac_chn_intstatus_enable1_reg_t; + +/** Type of chn_intstatus0 register + * NA + */ +typedef union { + struct { + /** block_tfr_done_intstat : RO; bitpos: [0]; default: 0; + * NA + */ + uint32_t block_tfr_done_intstat: 1; + /** dma_tfr_done_intstat : RO; bitpos: [1]; default: 0; + * NA + */ + uint32_t dma_tfr_done_intstat: 1; + uint32_t reserved_2: 1; + /** src_transcomp_intstat : RO; bitpos: [3]; default: 0; + * NA + */ + uint32_t src_transcomp_intstat: 1; + /** dst_transcomp_intstat : RO; bitpos: [4]; default: 0; + * NA + */ + uint32_t dst_transcomp_intstat: 1; + /** src_dec_err_intstat : RO; bitpos: [5]; default: 0; + * NA + */ + uint32_t src_dec_err_intstat: 1; + /** dst_dec_err_intstat : RO; bitpos: [6]; default: 0; + * NA + */ + uint32_t dst_dec_err_intstat: 1; + /** src_slv_err_intstat : RO; bitpos: [7]; default: 0; + * NA + */ + uint32_t src_slv_err_intstat: 1; + /** dst_slv_err_intstat : RO; bitpos: [8]; default: 0; + * NA + */ + uint32_t dst_slv_err_intstat: 1; + /** lli_rd_dec_err_intstat : RO; bitpos: [9]; default: 0; + * NA + */ + uint32_t lli_rd_dec_err_intstat: 1; + /** lli_wr_dec_err_intstat : RO; bitpos: [10]; default: 0; + * NA + */ + uint32_t lli_wr_dec_err_intstat: 1; + /** lli_rd_slv_err_intstat : RO; bitpos: [11]; default: 0; + * NA + */ + uint32_t lli_rd_slv_err_intstat: 1; + /** lli_wr_slv_err_intstat : RO; bitpos: [12]; default: 0; + * NA + */ + uint32_t lli_wr_slv_err_intstat: 1; + /** shadowreg_or_lli_invalid_err_intstat : RO; bitpos: [13]; default: 0; + * NA + */ + uint32_t shadowreg_or_lli_invalid_err_intstat: 1; + /** slvif_multiblktype_err_intstat : RO; bitpos: [14]; default: 0; + * NA + */ + uint32_t slvif_multiblktype_err_intstat: 1; + uint32_t reserved_15: 1; + /** slvif_dec_err_intstat : RO; bitpos: [16]; default: 0; + * NA + */ + uint32_t slvif_dec_err_intstat: 1; + /** slvif_wr2ro_err_intstat : RO; bitpos: [17]; default: 0; + * NA + */ + uint32_t slvif_wr2ro_err_intstat: 1; + /** slvif_rd2rwo_err_intstat : RO; bitpos: [18]; default: 0; + * NA + */ + uint32_t slvif_rd2rwo_err_intstat: 1; + /** slvif_wronchen_err_intstat : RO; bitpos: [19]; default: 0; + * NA + */ + uint32_t slvif_wronchen_err_intstat: 1; + /** slvif_shadowreg_wron_valid_err_intstat : RO; bitpos: [20]; default: 0; + * NA + */ + uint32_t slvif_shadowreg_wron_valid_err_intstat: 1; + /** slvif_wronhold_err_intstat : RO; bitpos: [21]; default: 0; + * NA + */ + uint32_t slvif_wronhold_err_intstat: 1; + uint32_t reserved_22: 3; + /** slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 0; + * NA + */ + uint32_t slvif_wrparity_err_intstat: 1; + uint32_t reserved_26: 1; + /** ch_lock_cleared_intstat : RO; bitpos: [27]; default: 0; + * NA + */ + uint32_t ch_lock_cleared_intstat: 1; + /** ch_src_suspended_intstat : RO; bitpos: [28]; default: 0; + * NA + */ + uint32_t ch_src_suspended_intstat: 1; + /** ch_suspended_intstat : RO; bitpos: [29]; default: 0; + * NA + */ + uint32_t ch_suspended_intstat: 1; + /** ch_disabled_intstat : RO; bitpos: [30]; default: 0; + * NA + */ + uint32_t ch_disabled_intstat: 1; + /** ch_aborted_intstat : RO; bitpos: [31]; default: 0; + * NA + */ + uint32_t ch_aborted_intstat: 1; + }; + uint32_t val; +} dmac_chn_intstatus0_reg_t; + +/** Type of chn_intstatus1 register + * NA + */ +typedef union { + struct { + /** ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 0; + * NA + */ + uint32_t ecc_prot_chmem_correrr_intstat: 1; + /** ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 0; + * NA + */ + uint32_t ecc_prot_chmem_uncorrerr_intstat: 1; + /** ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 0; + * NA + */ + uint32_t ecc_prot_uidmem_correrr_intstat: 1; + /** ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 0; + * NA + */ + uint32_t ecc_prot_uidmem_uncorrerr_intstat: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} dmac_chn_intstatus1_reg_t; + +/** Type of chn_intsignal_enable0 register + * NA + */ +typedef union { + struct { + /** enable_block_tfr_done_intsignal : R/W; bitpos: [0]; default: 1; + * NA + */ + uint32_t enable_block_tfr_done_intsignal: 1; + /** enable_dma_tfr_done_intsignal : R/W; bitpos: [1]; default: 1; + * NA + */ + uint32_t enable_dma_tfr_done_intsignal: 1; + uint32_t reserved_2: 1; + /** enable_src_transcomp_intsignal : R/W; bitpos: [3]; default: 1; + * NA + */ + uint32_t enable_src_transcomp_intsignal: 1; + /** enable_dst_transcomp_intsignal : R/W; bitpos: [4]; default: 1; + * NA + */ + uint32_t enable_dst_transcomp_intsignal: 1; + /** enable_src_dec_err_intsignal : R/W; bitpos: [5]; default: 1; + * NA + */ + uint32_t enable_src_dec_err_intsignal: 1; + /** enable_dst_dec_err_intsignal : R/W; bitpos: [6]; default: 1; + * NA + */ + uint32_t enable_dst_dec_err_intsignal: 1; + /** enable_src_slv_err_intsignal : R/W; bitpos: [7]; default: 1; + * NA + */ + uint32_t enable_src_slv_err_intsignal: 1; + /** enable_dst_slv_err_intsignal : R/W; bitpos: [8]; default: 1; + * NA + */ + uint32_t enable_dst_slv_err_intsignal: 1; + /** enable_lli_rd_dec_err_intsignal : R/W; bitpos: [9]; default: 1; + * NA + */ + uint32_t enable_lli_rd_dec_err_intsignal: 1; + /** enable_lli_wr_dec_err_intsignal : R/W; bitpos: [10]; default: 1; + * NA + */ + uint32_t enable_lli_wr_dec_err_intsignal: 1; + /** enable_lli_rd_slv_err_intsignal : R/W; bitpos: [11]; default: 1; + * NA + */ + uint32_t enable_lli_rd_slv_err_intsignal: 1; + /** enable_lli_wr_slv_err_intsignal : R/W; bitpos: [12]; default: 1; + * NA + */ + uint32_t enable_lli_wr_slv_err_intsignal: 1; + /** enable_shadowreg_or_lli_invalid_err_intsignal : R/W; bitpos: [13]; default: 1; + * NA + */ + uint32_t enable_shadowreg_or_lli_invalid_err_intsignal: 1; + /** enable_slvif_multiblktype_err_intsignal : R/W; bitpos: [14]; default: 1; + * NA + */ + uint32_t enable_slvif_multiblktype_err_intsignal: 1; + uint32_t reserved_15: 1; + /** enable_slvif_dec_err_intsignal : R/W; bitpos: [16]; default: 1; + * NA + */ + uint32_t enable_slvif_dec_err_intsignal: 1; + /** enable_slvif_wr2ro_err_intsignal : R/W; bitpos: [17]; default: 1; + * NA + */ + uint32_t enable_slvif_wr2ro_err_intsignal: 1; + /** enable_slvif_rd2rwo_err_intsignal : R/W; bitpos: [18]; default: 1; + * NA + */ + uint32_t enable_slvif_rd2rwo_err_intsignal: 1; + /** enable_slvif_wronchen_err_intsignal : R/W; bitpos: [19]; default: 1; + * NA + */ + uint32_t enable_slvif_wronchen_err_intsignal: 1; + /** enable_slvif_shadowreg_wron_valid_err_intsignal : R/W; bitpos: [20]; default: 1; + * NA + */ + uint32_t enable_slvif_shadowreg_wron_valid_err_intsignal: 1; + /** enable_slvif_wronhold_err_intsignal : R/W; bitpos: [21]; default: 1; + * NA + */ + uint32_t enable_slvif_wronhold_err_intsignal: 1; + uint32_t reserved_22: 3; + /** enable_slvif_wrparity_err_intsignal : RO; bitpos: [25]; default: 1; + * NA + */ + uint32_t enable_slvif_wrparity_err_intsignal: 1; + uint32_t reserved_26: 1; + /** enable_ch_lock_cleared_intsignal : R/W; bitpos: [27]; default: 1; + * NA + */ + uint32_t enable_ch_lock_cleared_intsignal: 1; + /** enable_ch_src_suspended_intsignal : R/W; bitpos: [28]; default: 1; + * NA + */ + uint32_t enable_ch_src_suspended_intsignal: 1; + /** enable_ch_suspended_intsignal : R/W; bitpos: [29]; default: 1; + * NA + */ + uint32_t enable_ch_suspended_intsignal: 1; + /** enable_ch_disabled_intsignal : R/W; bitpos: [30]; default: 1; + * NA + */ + uint32_t enable_ch_disabled_intsignal: 1; + /** enable_ch_aborted_intsignal : R/W; bitpos: [31]; default: 1; + * NA + */ + uint32_t enable_ch_aborted_intsignal: 1; + }; + uint32_t val; +} dmac_chn_intsignal_enable0_reg_t; + +/** Type of chn_intsignal_enable1 register + * NA + */ +typedef union { + struct { + /** enable_ecc_prot_chmem_correrr_intsignal : RO; bitpos: [0]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_chmem_correrr_intsignal: 1; + /** enable_ecc_prot_chmem_uncorrerr_intsignal : RO; bitpos: [1]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_chmem_uncorrerr_intsignal: 1; + /** enable_ecc_prot_uidmem_correrr_intsignal : RO; bitpos: [2]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_uidmem_correrr_intsignal: 1; + /** enable_ecc_prot_uidmem_uncorrerr_intsignal : RO; bitpos: [3]; default: 1; + * NA + */ + uint32_t enable_ecc_prot_uidmem_uncorrerr_intsignal: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} dmac_chn_intsignal_enable1_reg_t; + +/** Type of chn_intclear0 register + * NA + */ +typedef union { + struct { + /** clear_block_tfr_done_intstat : WO; bitpos: [0]; default: 0; + * NA + */ + uint32_t clear_block_tfr_done_intstat: 1; + /** clear_dma_tfr_done_intstat : WO; bitpos: [1]; default: 0; + * NA + */ + uint32_t clear_dma_tfr_done_intstat: 1; + uint32_t reserved_2: 1; + /** clear_src_transcomp_intstat : WO; bitpos: [3]; default: 0; + * NA + */ + uint32_t clear_src_transcomp_intstat: 1; + /** clear_dst_transcomp_intstat : WO; bitpos: [4]; default: 0; + * NA + */ + uint32_t clear_dst_transcomp_intstat: 1; + /** clear_src_dec_err_intstat : WO; bitpos: [5]; default: 0; + * NA + */ + uint32_t clear_src_dec_err_intstat: 1; + /** clear_dst_dec_err_intstat : WO; bitpos: [6]; default: 0; + * NA + */ + uint32_t clear_dst_dec_err_intstat: 1; + /** clear_src_slv_err_intstat : WO; bitpos: [7]; default: 0; + * NA + */ + uint32_t clear_src_slv_err_intstat: 1; + /** clear_dst_slv_err_intstat : WO; bitpos: [8]; default: 0; + * NA + */ + uint32_t clear_dst_slv_err_intstat: 1; + /** clear_lli_rd_dec_err_intstat : WO; bitpos: [9]; default: 0; + * NA + */ + uint32_t clear_lli_rd_dec_err_intstat: 1; + /** clear_lli_wr_dec_err_intstat : WO; bitpos: [10]; default: 0; + * NA + */ + uint32_t clear_lli_wr_dec_err_intstat: 1; + /** clear_lli_rd_slv_err_intstat : WO; bitpos: [11]; default: 0; + * NA + */ + uint32_t clear_lli_rd_slv_err_intstat: 1; + /** clear_lli_wr_slv_err_intstat : WO; bitpos: [12]; default: 0; + * NA + */ + uint32_t clear_lli_wr_slv_err_intstat: 1; + /** clear_shadowreg_or_lli_invalid_err_intstat : WO; bitpos: [13]; default: 0; + * NA + */ + uint32_t clear_shadowreg_or_lli_invalid_err_intstat: 1; + /** clear_slvif_multiblktype_err_intstat : WO; bitpos: [14]; default: 0; + * NA + */ + uint32_t clear_slvif_multiblktype_err_intstat: 1; + uint32_t reserved_15: 1; + /** clear_slvif_dec_err_intstat : WO; bitpos: [16]; default: 0; + * NA + */ + uint32_t clear_slvif_dec_err_intstat: 1; + /** clear_slvif_wr2ro_err_intstat : WO; bitpos: [17]; default: 0; + * NA + */ + uint32_t clear_slvif_wr2ro_err_intstat: 1; + /** clear_slvif_rd2rwo_err_intstat : WO; bitpos: [18]; default: 0; + * NA + */ + uint32_t clear_slvif_rd2rwo_err_intstat: 1; + /** clear_slvif_wronchen_err_intstat : WO; bitpos: [19]; default: 0; + * NA + */ + uint32_t clear_slvif_wronchen_err_intstat: 1; + /** clear_slvif_shadowreg_wron_valid_err_intstat : WO; bitpos: [20]; default: 0; + * NA + */ + uint32_t clear_slvif_shadowreg_wron_valid_err_intstat: 1; + /** clear_slvif_wronhold_err_intstat : WO; bitpos: [21]; default: 0; + * NA + */ + uint32_t clear_slvif_wronhold_err_intstat: 1; + uint32_t reserved_22: 3; + /** clear_slvif_wrparity_err_intstat : WO; bitpos: [25]; default: 0; + * NA + */ + uint32_t clear_slvif_wrparity_err_intstat: 1; + uint32_t reserved_26: 1; + /** clear_ch_lock_cleared_intstat : WO; bitpos: [27]; default: 0; + * NA + */ + uint32_t clear_ch_lock_cleared_intstat: 1; + /** clear_ch_src_suspended_intstat : WO; bitpos: [28]; default: 0; + * NA + */ + uint32_t clear_ch_src_suspended_intstat: 1; + /** clear_ch_suspended_intstat : WO; bitpos: [29]; default: 0; + * NA + */ + uint32_t clear_ch_suspended_intstat: 1; + /** clear_ch_disabled_intstat : WO; bitpos: [30]; default: 0; + * NA + */ + uint32_t clear_ch_disabled_intstat: 1; + /** clear_ch_aborted_intstat : WO; bitpos: [31]; default: 0; + * NA + */ + uint32_t clear_ch_aborted_intstat: 1; + }; + uint32_t val; +} dmac_chn_intclear0_reg_t; + +/** Type of chn_intclear1 register + * NA + */ +typedef union { + struct { + /** clear_ecc_prot_chmem_correrr_intstat : WO; bitpos: [0]; default: 0; + * NA + */ + uint32_t clear_ecc_prot_chmem_correrr_intstat: 1; + /** clear_ecc_prot_chmem_uncorrerr_intstat : WO; bitpos: [1]; default: 0; + * NA + */ + uint32_t clear_ecc_prot_chmem_uncorrerr_intstat: 1; + /** clear_ecc_prot_uidmem_correrr_intstat : WO; bitpos: [2]; default: 0; + * NA + */ + uint32_t clear_ecc_prot_uidmem_correrr_intstat: 1; + /** clear_ecc_prot_uidmem_uncorrerr_intstat : WO; bitpos: [3]; default: 0; + * NA + */ + uint32_t clear_ecc_prot_uidmem_uncorrerr_intstat: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} dmac_chn_intclear1_reg_t; + +/** Group: Status Registers */ +/** Type of chn_status0 register + * NA + */ +typedef union { + struct { + /** cmpltd_blk_tfr_size : RO; bitpos: [21:0]; default: 0; + * NA + */ + uint32_t cmpltd_blk_tfr_size: 22; + uint32_t reserved_22: 10; + }; + uint32_t val; +} dmac_chn_status0_reg_t; + +/** Type of chn_status1 register + * NA + */ +typedef union { + struct { + /** data_left_in_fifo : RO; bitpos: [14:0]; default: 0; + * NA + */ + uint32_t data_left_in_fifo: 15; + uint32_t reserved_15: 17; + }; + uint32_t val; +} dmac_chn_status1_reg_t; + +/** Type of chn_sstat0 register + * NA + */ +typedef union { + struct { + /** sstat : RO; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t sstat: 32; + }; + uint32_t val; +} dmac_chn_sstat0_reg_t; + +/** Type of chn_dstat0 register + * NA + */ +typedef union { + struct { + /** dstat : RO; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t dstat: 32; + }; + uint32_t val; +} dmac_chn_dstat0_reg_t; + +/** Type of chn_sstatar0 register + * NA + */ +typedef union { + struct { + /** sstatar0 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t sstatar0: 32; + }; + uint32_t val; +} dmac_chn_sstatar0_reg_t; + +/** Type of chn_sstatar1 register + * NA + */ +typedef union { + struct { + /** sstatar1 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t sstatar1: 32; + }; + uint32_t val; +} dmac_chn_sstatar1_reg_t; + +/** Type of chn_dstatar0 register + * NA + */ +typedef union { + struct { + /** dstatar0 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t dstatar0: 32; + }; + uint32_t val; +} dmac_chn_dstatar0_reg_t; + +/** Type of chn_dstatar1 register + * NA + */ +typedef union { + struct { + /** dstatar1 : R/W; bitpos: [31:0]; default: 0; + * NA + */ + uint32_t dstatar1: 32; + }; + uint32_t val; +} dmac_chn_dstatar1_reg_t; + +typedef struct { + volatile dmac_chn_sar0_reg_t sar0; + volatile dmac_chn_sar1_reg_t sar1; + volatile dmac_chn_dar0_reg_t dar0; + volatile dmac_chn_dar1_reg_t dar1; + volatile dmac_chn_block_ts0_reg_t block_ts0; + uint32_t reserved_114; + volatile dmac_chn_ctl0_reg_t ctl0; + volatile dmac_chn_ctl1_reg_t ctl1; + volatile dmac_chn_cfg0_reg_t cfg0; + volatile dmac_chn_cfg1_reg_t cfg1; + volatile dmac_chn_llp0_reg_t llp0; + volatile dmac_chn_llp1_reg_t llp1; + volatile dmac_chn_status0_reg_t status0; + volatile dmac_chn_status1_reg_t status1; + volatile dmac_chn_swhssrc0_reg_t swhssrc0; + uint32_t reserved_13c; + volatile dmac_chn_swhsdst0_reg_t swhsdst0; + uint32_t reserved_144; + volatile dmac_chn_blk_tfr_resumereq0_reg_t blk_tfr_resumereq0; + uint32_t reserved_14c; + volatile dmac_chn_axi_id0_reg_t axi_id0; + uint32_t reserved_154; + volatile dmac_chn_axi_qos0_reg_t axi_qos0; + uint32_t reserved_15c; + volatile dmac_chn_sstat0_reg_t sstat0; + uint32_t reserved_164; + volatile dmac_chn_dstat0_reg_t dstat0; + uint32_t reserved_16c; + volatile dmac_chn_sstatar0_reg_t sstatar0; + volatile dmac_chn_sstatar1_reg_t sstatar1; + volatile dmac_chn_dstatar0_reg_t dstatar0; + volatile dmac_chn_dstatar1_reg_t dstatar1; + volatile dmac_chn_intstatus_enable0_reg_t int_st_ena0; + volatile dmac_chn_intstatus_enable1_reg_t int_st_ena1; + volatile dmac_chn_intstatus0_reg_t int_st0; + volatile dmac_chn_intstatus1_reg_t int_st1; + volatile dmac_chn_intsignal_enable0_reg_t int_sig_ena0; + volatile dmac_chn_intsignal_enable1_reg_t int_sig_ena1; + volatile dmac_chn_intclear0_reg_t int_clr0; + volatile dmac_chn_intclear1_reg_t int_clr1; + uint32_t reserved_1a0[24]; +} dmac_channel_reg_t; + +typedef struct dw_gdma_dev_t { + volatile dmac_id0_reg_t id0; + uint32_t reserved_004; + volatile dmac_compver0_reg_t compver0; + uint32_t reserved_00c; + volatile dmac_cfg0_reg_t cfg0; + uint32_t reserved_014; + volatile dmac_chen0_reg_t chen0; + volatile dmac_chen1_reg_t chen1; + uint32_t reserved_020[4]; + volatile dmac_intstatus0_reg_t int_st0; + uint32_t reserved_034; + volatile dmac_commonreg_intclear0_reg_t common_int_clr0; + uint32_t reserved_03c; + volatile dmac_commonreg_intstatus_enable0_reg_t common_int_st_ena0; + uint32_t reserved_044; + volatile dmac_commonreg_intsignal_enable0_reg_t common_int_sig_ena0; + uint32_t reserved_04c; + volatile dmac_commonreg_intstatus0_reg_t common_int_st0; + uint32_t reserved_054; + volatile dmac_reset0_reg_t reset0; + uint32_t reserved_05c; + volatile dmac_lowpower_cfg0_reg_t lowpower_cfg0; + volatile dmac_lowpower_cfg1_reg_t lowpower_cfg1; + uint32_t reserved_068[38]; + volatile dmac_channel_reg_t ch[4]; +} dw_gdma_dev_t; + +extern dw_gdma_dev_t DW_GDMA; + +#ifndef __cplusplus +_Static_assert(sizeof(dw_gdma_dev_t) == 0x500, "Invalid size of dw_gdma_dev_t structure"); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32p4/include/soc/gdma_struct.h b/components/soc/esp32p4/include/soc/gdma_struct.h deleted file mode 100644 index 55a0d955b768..000000000000 --- a/components/soc/esp32p4/include/soc/gdma_struct.h +++ /dev/null @@ -1,5183 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#ifdef __cplusplus -extern "C" { -#endif - -/** Group: Version Register */ -/** Type of id0 register - * NA - */ -typedef union { - struct { - /** dmac_id : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t dmac_id:32; - }; - uint32_t val; -} dmac_id0_reg_t; - -/** Type of compver0 register - * NA - */ -typedef union { - struct { - /** dmac_compver : RO; bitpos: [31:0]; default: 842018858; - * NA - */ - uint32_t dmac_compver:32; - }; - uint32_t val; -} dmac_compver0_reg_t; - - -/** Group: Configuration Registers */ -/** Type of cfg0 register - * NA - */ -typedef union { - struct { - /** dmac_en : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t dmac_en:1; - /** int_en : R/W; bitpos: [1]; default: 0; - * NA - */ - uint32_t int_en:1; - uint32_t reserved_2:30; - }; - uint32_t val; -} dmac_cfg0_reg_t; - -/** Type of chen0 register - * NA - */ -typedef union { - struct { - /** ch1_en : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_en:1; - /** ch2_en : R/W; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_en:1; - /** ch3_en : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_en:1; - /** ch4_en : R/W; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_en:1; - uint32_t reserved_4:4; - /** ch1_en_we : WO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch1_en_we:1; - /** ch2_en_we : WO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch2_en_we:1; - /** ch3_en_we : WO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch3_en_we:1; - /** ch4_en_we : WO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch4_en_we:1; - uint32_t reserved_12:4; - /** ch1_susp : R/W; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch1_susp:1; - /** ch2_susp : R/W; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch2_susp:1; - /** ch3_susp : R/W; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch3_susp:1; - /** ch4_susp : R/W; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch4_susp:1; - uint32_t reserved_20:4; - /** ch1_susp_we : WO; bitpos: [24]; default: 0; - * NA - */ - uint32_t ch1_susp_we:1; - /** ch2_susp_we : WO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch2_susp_we:1; - /** ch3_susp_we : WO; bitpos: [26]; default: 0; - * NA - */ - uint32_t ch3_susp_we:1; - /** ch4_susp_we : WO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch4_susp_we:1; - uint32_t reserved_28:4; - }; - uint32_t val; -} dmac_chen0_reg_t; - -/** Type of chen1 register - * NA - */ -typedef union { - struct { - /** ch1_abort : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_abort:1; - /** ch2_abort : R/W; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_abort:1; - /** ch3_abort : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_abort:1; - /** ch4_abort : R/W; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_abort:1; - uint32_t reserved_4:4; - /** ch1_abort_we : WO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch1_abort_we:1; - /** ch2_abort_we : WO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch2_abort_we:1; - /** ch3_abort_we : WO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch3_abort_we:1; - /** ch4_abort_we : WO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch4_abort_we:1; - uint32_t reserved_12:20; - }; - uint32_t val; -} dmac_chen1_reg_t; - -/** Type of reset0 register - * NA - */ -typedef union { - struct { - /** dmac_rst : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t dmac_rst:1; - uint32_t reserved_1:31; - }; - uint32_t val; -} dmac_reset0_reg_t; - -/** Type of lowpower_cfg0 register - * NA - */ -typedef union { - struct { - /** gbl_cslp_en : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t gbl_cslp_en:1; - /** chnl_cslp_en : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t chnl_cslp_en:1; - /** sbiu_cslp_en : R/W; bitpos: [2]; default: 1; - * NA - */ - uint32_t sbiu_cslp_en:1; - /** mxif_cslp_en : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t mxif_cslp_en:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_lowpower_cfg0_reg_t; - -/** Type of lowpower_cfg1 register - * NA - */ -typedef union { - struct { - /** glch_lpdly : R/W; bitpos: [7:0]; default: 64; - * NA - */ - uint32_t glch_lpdly:8; - /** sbiu_lpdly : R/W; bitpos: [15:8]; default: 64; - * NA - */ - uint32_t sbiu_lpdly:8; - /** mxif_lpdly : R/W; bitpos: [23:16]; default: 64; - * NA - */ - uint32_t mxif_lpdly:8; - uint32_t reserved_24:8; - }; - uint32_t val; -} dmac_lowpower_cfg1_reg_t; - -/** Type of ch1_sar0 register - * NA - */ -typedef union { - struct { - /** ch1_sar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_sar0:32; - }; - uint32_t val; -} dmac_ch1_sar0_reg_t; - -/** Type of ch1_sar1 register - * NA - */ -typedef union { - struct { - /** ch1_sar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_sar1:32; - }; - uint32_t val; -} dmac_ch1_sar1_reg_t; - -/** Type of ch1_dar0 register - * NA - */ -typedef union { - struct { - /** ch1_dar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_dar0:32; - }; - uint32_t val; -} dmac_ch1_dar0_reg_t; - -/** Type of ch1_dar1 register - * NA - */ -typedef union { - struct { - /** ch1_dar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_dar1:32; - }; - uint32_t val; -} dmac_ch1_dar1_reg_t; - -/** Type of ch1_block_ts0 register - * NA - */ -typedef union { - struct { - /** ch1_block_ts : R/W; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch1_block_ts:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch1_block_ts0_reg_t; - -/** Type of ch1_ctl0 register - * NA - */ -typedef union { - struct { - /** ch1_sms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_sms:1; - uint32_t reserved_1:1; - /** ch1_dms : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch1_dms:1; - uint32_t reserved_3:1; - /** ch1_sinc : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch1_sinc:1; - uint32_t reserved_5:1; - /** ch1_dinc : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch1_dinc:1; - uint32_t reserved_7:1; - /** ch1_src_tr_width : R/W; bitpos: [10:8]; default: 2; - * NA - */ - uint32_t ch1_src_tr_width:3; - /** ch1_dst_tr_width : R/W; bitpos: [13:11]; default: 2; - * NA - */ - uint32_t ch1_dst_tr_width:3; - /** ch1_src_msize : R/W; bitpos: [17:14]; default: 0; - * NA - */ - uint32_t ch1_src_msize:4; - /** ch1_dst_msize : R/W; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch1_dst_msize:4; - /** ch1_ar_cache : R/W; bitpos: [25:22]; default: 0; - * NA - */ - uint32_t ch1_ar_cache:4; - /** ch1_aw_cache : R/W; bitpos: [29:26]; default: 0; - * NA - */ - uint32_t ch1_aw_cache:4; - /** ch1_nonposted_lastwrite_en : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch1_nonposted_lastwrite_en:1; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch1_ctl0_reg_t; - -/** Type of ch1_ctl1 register - * NA - */ -typedef union { - struct { - /** ch1_ar_prot : R/W; bitpos: [2:0]; default: 0; - * NA - */ - uint32_t ch1_ar_prot:3; - /** ch1_aw_prot : R/W; bitpos: [5:3]; default: 0; - * NA - */ - uint32_t ch1_aw_prot:3; - /** ch1_arlen_en : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch1_arlen_en:1; - /** ch1_arlen : R/W; bitpos: [14:7]; default: 0; - * NA - */ - uint32_t ch1_arlen:8; - /** ch1_awlen_en : R/W; bitpos: [15]; default: 0; - * NA - */ - uint32_t ch1_awlen_en:1; - /** ch1_awlen : R/W; bitpos: [23:16]; default: 0; - * NA - */ - uint32_t ch1_awlen:8; - /** ch1_src_stat_en : R/W; bitpos: [24]; default: 0; - * NA - */ - uint32_t ch1_src_stat_en:1; - /** ch1_dst_stat_en : R/W; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch1_dst_stat_en:1; - /** ch1_ioc_blktfr : R/W; bitpos: [26]; default: 0; - * NA - */ - uint32_t ch1_ioc_blktfr:1; - uint32_t reserved_27:3; - /** ch1_shadowreg_or_lli_last : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch1_shadowreg_or_lli_last:1; - /** ch1_shadowreg_or_lli_valid : R/W; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch1_shadowreg_or_lli_valid:1; - }; - uint32_t val; -} dmac_ch1_ctl1_reg_t; - -/** Type of ch1_cfg0 register - * NA - */ -typedef union { - struct { - /** ch1_src_multblk_type : R/W; bitpos: [1:0]; default: 0; - * NA - */ - uint32_t ch1_src_multblk_type:2; - /** ch1_dst_multblk_type : R/W; bitpos: [3:2]; default: 0; - * NA - */ - uint32_t ch1_dst_multblk_type:2; - uint32_t reserved_4:14; - /** ch1_rd_uid : RO; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch1_rd_uid:4; - uint32_t reserved_22:3; - /** ch1_wr_uid : RO; bitpos: [28:25]; default: 0; - * NA - */ - uint32_t ch1_wr_uid:4; - uint32_t reserved_29:3; - }; - uint32_t val; -} dmac_ch1_cfg0_reg_t; - -/** Type of ch1_cfg1 register - * NA - */ -typedef union { - struct { - /** ch1_tt_fc : R/W; bitpos: [2:0]; default: 3; - * NA - */ - uint32_t ch1_tt_fc:3; - /** ch1_hs_sel_src : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch1_hs_sel_src:1; - /** ch1_hs_sel_dst : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch1_hs_sel_dst:1; - /** ch1_src_hwhs_pol : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch1_src_hwhs_pol:1; - /** ch1_dst_hwhs_pol : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch1_dst_hwhs_pol:1; - /** ch1_src_per : R/W; bitpos: [8:7]; default: 0; - * NA - */ - uint32_t ch1_src_per:2; - uint32_t reserved_9:3; - /** ch1_dst_per : R/W; bitpos: [13:12]; default: 0; - * NA - */ - uint32_t ch1_dst_per:2; - uint32_t reserved_14:3; - /** ch1_ch_prior : R/W; bitpos: [19:17]; default: 3; - * NA - */ - uint32_t ch1_ch_prior:3; - /** ch1_lock_ch : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch1_lock_ch:1; - /** ch1_lock_ch_l : RO; bitpos: [22:21]; default: 0; - * NA - */ - uint32_t ch1_lock_ch_l:2; - /** ch1_src_osr_lmt : R/W; bitpos: [26:23]; default: 0; - * NA - */ - uint32_t ch1_src_osr_lmt:4; - /** ch1_dst_osr_lmt : R/W; bitpos: [30:27]; default: 0; - * NA - */ - uint32_t ch1_dst_osr_lmt:4; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch1_cfg1_reg_t; - -/** Type of ch1_llp0 register - * NA - */ -typedef union { - struct { - /** ch1_lms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_lms:1; - uint32_t reserved_1:5; - /** ch1_loc0 : R/W; bitpos: [31:6]; default: 0; - * NA - */ - uint32_t ch1_loc0:26; - }; - uint32_t val; -} dmac_ch1_llp0_reg_t; - -/** Type of ch1_llp1 register - * NA - */ -typedef union { - struct { - /** ch1_loc1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_loc1:32; - }; - uint32_t val; -} dmac_ch1_llp1_reg_t; - -/** Type of ch1_swhssrc0 register - * NA - */ -typedef union { - struct { - /** ch1_swhs_req_src : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_swhs_req_src:1; - /** ch1_swhs_req_src_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch1_swhs_req_src_we:1; - /** ch1_swhs_sglreq_src : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch1_swhs_sglreq_src:1; - /** ch1_swhs_sglreq_src_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch1_swhs_sglreq_src_we:1; - /** ch1_swhs_lst_src : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch1_swhs_lst_src:1; - /** ch1_swhs_lst_src_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch1_swhs_lst_src_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch1_swhssrc0_reg_t; - -/** Type of ch1_swhsdst0 register - * NA - */ -typedef union { - struct { - /** ch1_swhs_req_dst : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_swhs_req_dst:1; - /** ch1_swhs_req_dst_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch1_swhs_req_dst_we:1; - /** ch1_swhs_sglreq_dst : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch1_swhs_sglreq_dst:1; - /** ch1_swhs_sglreq_dst_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch1_swhs_sglreq_dst_we:1; - /** ch1_swhs_lst_dst : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch1_swhs_lst_dst:1; - /** ch1_swhs_lst_dst_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch1_swhs_lst_dst_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch1_swhsdst0_reg_t; - -/** Type of ch1_blk_tfr_resumereq0 register - * NA - */ -typedef union { - struct { - /** ch1_blk_tfr_resumereq : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_blk_tfr_resumereq:1; - uint32_t reserved_1:31; - }; - uint32_t val; -} dmac_ch1_blk_tfr_resumereq0_reg_t; - -/** Type of ch1_axi_id0 register - * NA - */ -typedef union { - struct { - /** ch1_axi_read_id_suffix : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_axi_read_id_suffix:1; - uint32_t reserved_1:15; - /** ch1_axi_write_id_suffix : R/W; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch1_axi_write_id_suffix:1; - uint32_t reserved_17:15; - }; - uint32_t val; -} dmac_ch1_axi_id0_reg_t; - -/** Type of ch1_axi_qos0 register - * NA - */ -typedef union { - struct { - /** ch1_axi_awqos : R/W; bitpos: [3:0]; default: 0; - * NA - */ - uint32_t ch1_axi_awqos:4; - /** ch1_axi_arqos : R/W; bitpos: [7:4]; default: 0; - * NA - */ - uint32_t ch1_axi_arqos:4; - uint32_t reserved_8:24; - }; - uint32_t val; -} dmac_ch1_axi_qos0_reg_t; - -/** Type of ch2_sar0 register - * NA - */ -typedef union { - struct { - /** ch2_sar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_sar0:32; - }; - uint32_t val; -} dmac_ch2_sar0_reg_t; - -/** Type of ch2_sar1 register - * NA - */ -typedef union { - struct { - /** ch2_sar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_sar1:32; - }; - uint32_t val; -} dmac_ch2_sar1_reg_t; - -/** Type of ch2_dar0 register - * NA - */ -typedef union { - struct { - /** ch2_dar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_dar0:32; - }; - uint32_t val; -} dmac_ch2_dar0_reg_t; - -/** Type of ch2_dar1 register - * NA - */ -typedef union { - struct { - /** ch2_dar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_dar1:32; - }; - uint32_t val; -} dmac_ch2_dar1_reg_t; - -/** Type of ch2_block_ts0 register - * NA - */ -typedef union { - struct { - /** ch2_block_ts : R/W; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch2_block_ts:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch2_block_ts0_reg_t; - -/** Type of ch2_ctl0 register - * NA - */ -typedef union { - struct { - /** ch2_sms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_sms:1; - uint32_t reserved_1:1; - /** ch2_dms : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch2_dms:1; - uint32_t reserved_3:1; - /** ch2_sinc : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch2_sinc:1; - uint32_t reserved_5:1; - /** ch2_dinc : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch2_dinc:1; - uint32_t reserved_7:1; - /** ch2_src_tr_width : R/W; bitpos: [10:8]; default: 2; - * NA - */ - uint32_t ch2_src_tr_width:3; - /** ch2_dst_tr_width : R/W; bitpos: [13:11]; default: 2; - * NA - */ - uint32_t ch2_dst_tr_width:3; - /** ch2_src_msize : R/W; bitpos: [17:14]; default: 0; - * NA - */ - uint32_t ch2_src_msize:4; - /** ch2_dst_msize : R/W; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch2_dst_msize:4; - /** ch2_ar_cache : R/W; bitpos: [25:22]; default: 0; - * NA - */ - uint32_t ch2_ar_cache:4; - /** ch2_aw_cache : R/W; bitpos: [29:26]; default: 0; - * NA - */ - uint32_t ch2_aw_cache:4; - /** ch2_nonposted_lastwrite_en : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch2_nonposted_lastwrite_en:1; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch2_ctl0_reg_t; - -/** Type of ch2_ctl1 register - * NA - */ -typedef union { - struct { - /** ch2_ar_prot : R/W; bitpos: [2:0]; default: 0; - * NA - */ - uint32_t ch2_ar_prot:3; - /** ch2_aw_prot : R/W; bitpos: [5:3]; default: 0; - * NA - */ - uint32_t ch2_aw_prot:3; - /** ch2_arlen_en : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch2_arlen_en:1; - /** ch2_arlen : R/W; bitpos: [14:7]; default: 0; - * NA - */ - uint32_t ch2_arlen:8; - /** ch2_awlen_en : R/W; bitpos: [15]; default: 0; - * NA - */ - uint32_t ch2_awlen_en:1; - /** ch2_awlen : R/W; bitpos: [23:16]; default: 0; - * NA - */ - uint32_t ch2_awlen:8; - /** ch2_src_stat_en : R/W; bitpos: [24]; default: 0; - * NA - */ - uint32_t ch2_src_stat_en:1; - /** ch2_dst_stat_en : R/W; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch2_dst_stat_en:1; - /** ch2_ioc_blktfr : R/W; bitpos: [26]; default: 0; - * NA - */ - uint32_t ch2_ioc_blktfr:1; - uint32_t reserved_27:3; - /** ch2_shadowreg_or_lli_last : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch2_shadowreg_or_lli_last:1; - /** ch2_shadowreg_or_lli_valid : R/W; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch2_shadowreg_or_lli_valid:1; - }; - uint32_t val; -} dmac_ch2_ctl1_reg_t; - -/** Type of ch2_cfg0 register - * NA - */ -typedef union { - struct { - /** ch2_src_multblk_type : R/W; bitpos: [1:0]; default: 0; - * NA - */ - uint32_t ch2_src_multblk_type:2; - /** ch2_dst_multblk_type : R/W; bitpos: [3:2]; default: 0; - * NA - */ - uint32_t ch2_dst_multblk_type:2; - uint32_t reserved_4:14; - /** ch2_rd_uid : RO; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch2_rd_uid:4; - uint32_t reserved_22:3; - /** ch2_wr_uid : RO; bitpos: [28:25]; default: 0; - * NA - */ - uint32_t ch2_wr_uid:4; - uint32_t reserved_29:3; - }; - uint32_t val; -} dmac_ch2_cfg0_reg_t; - -/** Type of ch2_cfg1 register - * NA - */ -typedef union { - struct { - /** ch2_tt_fc : R/W; bitpos: [2:0]; default: 3; - * NA - */ - uint32_t ch2_tt_fc:3; - /** ch2_hs_sel_src : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch2_hs_sel_src:1; - /** ch2_hs_sel_dst : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch2_hs_sel_dst:1; - /** ch2_src_hwhs_pol : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch2_src_hwhs_pol:1; - /** ch2_dst_hwhs_pol : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch2_dst_hwhs_pol:1; - /** ch2_src_per : R/W; bitpos: [8:7]; default: 0; - * NA - */ - uint32_t ch2_src_per:2; - uint32_t reserved_9:3; - /** ch2_dst_per : R/W; bitpos: [13:12]; default: 0; - * NA - */ - uint32_t ch2_dst_per:2; - uint32_t reserved_14:3; - /** ch2_ch_prior : R/W; bitpos: [19:17]; default: 2; - * NA - */ - uint32_t ch2_ch_prior:3; - /** ch2_lock_ch : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch2_lock_ch:1; - /** ch2_lock_ch_l : RO; bitpos: [22:21]; default: 0; - * NA - */ - uint32_t ch2_lock_ch_l:2; - /** ch2_src_osr_lmt : R/W; bitpos: [26:23]; default: 0; - * NA - */ - uint32_t ch2_src_osr_lmt:4; - /** ch2_dst_osr_lmt : R/W; bitpos: [30:27]; default: 0; - * NA - */ - uint32_t ch2_dst_osr_lmt:4; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch2_cfg1_reg_t; - -/** Type of ch2_llp0 register - * NA - */ -typedef union { - struct { - /** ch2_lms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_lms:1; - uint32_t reserved_1:5; - /** ch2_loc0 : R/W; bitpos: [31:6]; default: 0; - * NA - */ - uint32_t ch2_loc0:26; - }; - uint32_t val; -} dmac_ch2_llp0_reg_t; - -/** Type of ch2_llp1 register - * NA - */ -typedef union { - struct { - /** ch2_loc1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_loc1:32; - }; - uint32_t val; -} dmac_ch2_llp1_reg_t; - -/** Type of ch2_swhssrc0 register - * NA - */ -typedef union { - struct { - /** ch2_swhs_req_src : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_swhs_req_src:1; - /** ch2_swhs_req_src_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_swhs_req_src_we:1; - /** ch2_swhs_sglreq_src : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch2_swhs_sglreq_src:1; - /** ch2_swhs_sglreq_src_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch2_swhs_sglreq_src_we:1; - /** ch2_swhs_lst_src : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch2_swhs_lst_src:1; - /** ch2_swhs_lst_src_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch2_swhs_lst_src_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch2_swhssrc0_reg_t; - -/** Type of ch2_swhsdst0 register - * NA - */ -typedef union { - struct { - /** ch2_swhs_req_dst : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_swhs_req_dst:1; - /** ch2_swhs_req_dst_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_swhs_req_dst_we:1; - /** ch2_swhs_sglreq_dst : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch2_swhs_sglreq_dst:1; - /** ch2_swhs_sglreq_dst_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch2_swhs_sglreq_dst_we:1; - /** ch2_swhs_lst_dst : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch2_swhs_lst_dst:1; - /** ch2_swhs_lst_dst_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch2_swhs_lst_dst_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch2_swhsdst0_reg_t; - -/** Type of ch2_blk_tfr_resumereq0 register - * NA - */ -typedef union { - struct { - /** ch2_blk_tfr_resumereq : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_blk_tfr_resumereq:1; - uint32_t reserved_1:31; - }; - uint32_t val; -} dmac_ch2_blk_tfr_resumereq0_reg_t; - -/** Type of ch2_axi_id0 register - * NA - */ -typedef union { - struct { - /** ch2_axi_read_id_suffix : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_axi_read_id_suffix:1; - uint32_t reserved_1:15; - /** ch2_axi_write_id_suffix : R/W; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch2_axi_write_id_suffix:1; - uint32_t reserved_17:15; - }; - uint32_t val; -} dmac_ch2_axi_id0_reg_t; - -/** Type of ch2_axi_qos0 register - * NA - */ -typedef union { - struct { - /** ch2_axi_awqos : R/W; bitpos: [3:0]; default: 0; - * NA - */ - uint32_t ch2_axi_awqos:4; - /** ch2_axi_arqos : R/W; bitpos: [7:4]; default: 0; - * NA - */ - uint32_t ch2_axi_arqos:4; - uint32_t reserved_8:24; - }; - uint32_t val; -} dmac_ch2_axi_qos0_reg_t; - -/** Type of ch3_sar0 register - * NA - */ -typedef union { - struct { - /** ch3_sar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_sar0:32; - }; - uint32_t val; -} dmac_ch3_sar0_reg_t; - -/** Type of ch3_sar1 register - * NA - */ -typedef union { - struct { - /** ch3_sar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_sar1:32; - }; - uint32_t val; -} dmac_ch3_sar1_reg_t; - -/** Type of ch3_dar0 register - * NA - */ -typedef union { - struct { - /** ch3_dar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_dar0:32; - }; - uint32_t val; -} dmac_ch3_dar0_reg_t; - -/** Type of ch3_dar1 register - * NA - */ -typedef union { - struct { - /** ch3_dar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_dar1:32; - }; - uint32_t val; -} dmac_ch3_dar1_reg_t; - -/** Type of ch3_block_ts0 register - * NA - */ -typedef union { - struct { - /** ch3_block_ts : R/W; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch3_block_ts:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch3_block_ts0_reg_t; - -/** Type of ch3_ctl0 register - * NA - */ -typedef union { - struct { - /** ch3_sms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_sms:1; - uint32_t reserved_1:1; - /** ch3_dms : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_dms:1; - uint32_t reserved_3:1; - /** ch3_sinc : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch3_sinc:1; - uint32_t reserved_5:1; - /** ch3_dinc : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch3_dinc:1; - uint32_t reserved_7:1; - /** ch3_src_tr_width : R/W; bitpos: [10:8]; default: 2; - * NA - */ - uint32_t ch3_src_tr_width:3; - /** ch3_dst_tr_width : R/W; bitpos: [13:11]; default: 2; - * NA - */ - uint32_t ch3_dst_tr_width:3; - /** ch3_src_msize : R/W; bitpos: [17:14]; default: 0; - * NA - */ - uint32_t ch3_src_msize:4; - /** ch3_dst_msize : R/W; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch3_dst_msize:4; - /** ch3_ar_cache : R/W; bitpos: [25:22]; default: 0; - * NA - */ - uint32_t ch3_ar_cache:4; - /** ch3_aw_cache : R/W; bitpos: [29:26]; default: 0; - * NA - */ - uint32_t ch3_aw_cache:4; - /** ch3_nonposted_lastwrite_en : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch3_nonposted_lastwrite_en:1; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch3_ctl0_reg_t; - -/** Type of ch3_ctl1 register - * NA - */ -typedef union { - struct { - /** ch3_ar_prot : R/W; bitpos: [2:0]; default: 0; - * NA - */ - uint32_t ch3_ar_prot:3; - /** ch3_aw_prot : R/W; bitpos: [5:3]; default: 0; - * NA - */ - uint32_t ch3_aw_prot:3; - /** ch3_arlen_en : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch3_arlen_en:1; - /** ch3_arlen : R/W; bitpos: [14:7]; default: 0; - * NA - */ - uint32_t ch3_arlen:8; - /** ch3_awlen_en : R/W; bitpos: [15]; default: 0; - * NA - */ - uint32_t ch3_awlen_en:1; - /** ch3_awlen : R/W; bitpos: [23:16]; default: 0; - * NA - */ - uint32_t ch3_awlen:8; - /** ch3_src_stat_en : R/W; bitpos: [24]; default: 0; - * NA - */ - uint32_t ch3_src_stat_en:1; - /** ch3_dst_stat_en : R/W; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch3_dst_stat_en:1; - /** ch3_ioc_blktfr : R/W; bitpos: [26]; default: 0; - * NA - */ - uint32_t ch3_ioc_blktfr:1; - uint32_t reserved_27:3; - /** ch3_shadowreg_or_lli_last : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch3_shadowreg_or_lli_last:1; - /** ch3_shadowreg_or_lli_valid : R/W; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch3_shadowreg_or_lli_valid:1; - }; - uint32_t val; -} dmac_ch3_ctl1_reg_t; - -/** Type of ch3_cfg0 register - * NA - */ -typedef union { - struct { - /** ch3_src_multblk_type : R/W; bitpos: [1:0]; default: 0; - * NA - */ - uint32_t ch3_src_multblk_type:2; - /** ch3_dst_multblk_type : R/W; bitpos: [3:2]; default: 0; - * NA - */ - uint32_t ch3_dst_multblk_type:2; - uint32_t reserved_4:14; - /** ch3_rd_uid : RO; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch3_rd_uid:4; - uint32_t reserved_22:3; - /** ch3_wr_uid : RO; bitpos: [28:25]; default: 0; - * NA - */ - uint32_t ch3_wr_uid:4; - uint32_t reserved_29:3; - }; - uint32_t val; -} dmac_ch3_cfg0_reg_t; - -/** Type of ch3_cfg1 register - * NA - */ -typedef union { - struct { - /** ch3_tt_fc : R/W; bitpos: [2:0]; default: 3; - * NA - */ - uint32_t ch3_tt_fc:3; - /** ch3_hs_sel_src : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch3_hs_sel_src:1; - /** ch3_hs_sel_dst : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch3_hs_sel_dst:1; - /** ch3_src_hwhs_pol : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch3_src_hwhs_pol:1; - /** ch3_dst_hwhs_pol : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch3_dst_hwhs_pol:1; - /** ch3_src_per : R/W; bitpos: [8:7]; default: 0; - * NA - */ - uint32_t ch3_src_per:2; - uint32_t reserved_9:3; - /** ch3_dst_per : R/W; bitpos: [13:12]; default: 0; - * NA - */ - uint32_t ch3_dst_per:2; - uint32_t reserved_14:3; - /** ch3_ch_prior : R/W; bitpos: [19:17]; default: 1; - * NA - */ - uint32_t ch3_ch_prior:3; - /** ch3_lock_ch : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch3_lock_ch:1; - /** ch3_lock_ch_l : RO; bitpos: [22:21]; default: 0; - * NA - */ - uint32_t ch3_lock_ch_l:2; - /** ch3_src_osr_lmt : R/W; bitpos: [26:23]; default: 0; - * NA - */ - uint32_t ch3_src_osr_lmt:4; - /** ch3_dst_osr_lmt : R/W; bitpos: [30:27]; default: 0; - * NA - */ - uint32_t ch3_dst_osr_lmt:4; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch3_cfg1_reg_t; - -/** Type of ch3_llp0 register - * NA - */ -typedef union { - struct { - /** ch3_lms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_lms:1; - uint32_t reserved_1:5; - /** ch3_loc0 : R/W; bitpos: [31:6]; default: 0; - * NA - */ - uint32_t ch3_loc0:26; - }; - uint32_t val; -} dmac_ch3_llp0_reg_t; - -/** Type of ch3_llp1 register - * NA - */ -typedef union { - struct { - /** ch3_loc1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_loc1:32; - }; - uint32_t val; -} dmac_ch3_llp1_reg_t; - -/** Type of ch3_swhssrc0 register - * NA - */ -typedef union { - struct { - /** ch3_swhs_req_src : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_swhs_req_src:1; - /** ch3_swhs_req_src_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch3_swhs_req_src_we:1; - /** ch3_swhs_sglreq_src : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_swhs_sglreq_src:1; - /** ch3_swhs_sglreq_src_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch3_swhs_sglreq_src_we:1; - /** ch3_swhs_lst_src : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch3_swhs_lst_src:1; - /** ch3_swhs_lst_src_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch3_swhs_lst_src_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch3_swhssrc0_reg_t; - -/** Type of ch3_swhsdst0 register - * NA - */ -typedef union { - struct { - /** ch3_swhs_req_dst : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_swhs_req_dst:1; - /** ch3_swhs_req_dst_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch3_swhs_req_dst_we:1; - /** ch3_swhs_sglreq_dst : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_swhs_sglreq_dst:1; - /** ch3_swhs_sglreq_dst_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch3_swhs_sglreq_dst_we:1; - /** ch3_swhs_lst_dst : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch3_swhs_lst_dst:1; - /** ch3_swhs_lst_dst_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch3_swhs_lst_dst_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch3_swhsdst0_reg_t; - -/** Type of ch3_blk_tfr_resumereq0 register - * NA - */ -typedef union { - struct { - /** ch3_blk_tfr_resumereq : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_blk_tfr_resumereq:1; - uint32_t reserved_1:31; - }; - uint32_t val; -} dmac_ch3_blk_tfr_resumereq0_reg_t; - -/** Type of ch3_axi_id0 register - * NA - */ -typedef union { - struct { - /** ch3_axi_read_id_suffix : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_axi_read_id_suffix:1; - uint32_t reserved_1:15; - /** ch3_axi_write_id_suffix : R/W; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch3_axi_write_id_suffix:1; - uint32_t reserved_17:15; - }; - uint32_t val; -} dmac_ch3_axi_id0_reg_t; - -/** Type of ch3_axi_qos0 register - * NA - */ -typedef union { - struct { - /** ch3_axi_awqos : R/W; bitpos: [3:0]; default: 0; - * NA - */ - uint32_t ch3_axi_awqos:4; - /** ch3_axi_arqos : R/W; bitpos: [7:4]; default: 0; - * NA - */ - uint32_t ch3_axi_arqos:4; - uint32_t reserved_8:24; - }; - uint32_t val; -} dmac_ch3_axi_qos0_reg_t; - -/** Type of ch4_sar0 register - * NA - */ -typedef union { - struct { - /** ch4_sar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_sar0:32; - }; - uint32_t val; -} dmac_ch4_sar0_reg_t; - -/** Type of ch4_sar1 register - * NA - */ -typedef union { - struct { - /** ch4_sar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_sar1:32; - }; - uint32_t val; -} dmac_ch4_sar1_reg_t; - -/** Type of ch4_dar0 register - * NA - */ -typedef union { - struct { - /** ch4_dar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_dar0:32; - }; - uint32_t val; -} dmac_ch4_dar0_reg_t; - -/** Type of ch4_dar1 register - * NA - */ -typedef union { - struct { - /** ch4_dar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_dar1:32; - }; - uint32_t val; -} dmac_ch4_dar1_reg_t; - -/** Type of ch4_block_ts0 register - * NA - */ -typedef union { - struct { - /** ch4_block_ts : R/W; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch4_block_ts:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch4_block_ts0_reg_t; - -/** Type of ch4_ctl0 register - * NA - */ -typedef union { - struct { - /** ch4_sms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_sms:1; - uint32_t reserved_1:1; - /** ch4_dms : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch4_dms:1; - uint32_t reserved_3:1; - /** ch4_sinc : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch4_sinc:1; - uint32_t reserved_5:1; - /** ch4_dinc : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch4_dinc:1; - uint32_t reserved_7:1; - /** ch4_src_tr_width : R/W; bitpos: [10:8]; default: 2; - * NA - */ - uint32_t ch4_src_tr_width:3; - /** ch4_dst_tr_width : R/W; bitpos: [13:11]; default: 2; - * NA - */ - uint32_t ch4_dst_tr_width:3; - /** ch4_src_msize : R/W; bitpos: [17:14]; default: 0; - * NA - */ - uint32_t ch4_src_msize:4; - /** ch4_dst_msize : R/W; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch4_dst_msize:4; - /** ch4_ar_cache : R/W; bitpos: [25:22]; default: 0; - * NA - */ - uint32_t ch4_ar_cache:4; - /** ch4_aw_cache : R/W; bitpos: [29:26]; default: 0; - * NA - */ - uint32_t ch4_aw_cache:4; - /** ch4_nonposted_lastwrite_en : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch4_nonposted_lastwrite_en:1; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch4_ctl0_reg_t; - -/** Type of ch4_ctl1 register - * NA - */ -typedef union { - struct { - /** ch4_ar_prot : R/W; bitpos: [2:0]; default: 0; - * NA - */ - uint32_t ch4_ar_prot:3; - /** ch4_aw_prot : R/W; bitpos: [5:3]; default: 0; - * NA - */ - uint32_t ch4_aw_prot:3; - /** ch4_arlen_en : R/W; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch4_arlen_en:1; - /** ch4_arlen : R/W; bitpos: [14:7]; default: 0; - * NA - */ - uint32_t ch4_arlen:8; - /** ch4_awlen_en : R/W; bitpos: [15]; default: 0; - * NA - */ - uint32_t ch4_awlen_en:1; - /** ch4_awlen : R/W; bitpos: [23:16]; default: 0; - * NA - */ - uint32_t ch4_awlen:8; - /** ch4_src_stat_en : R/W; bitpos: [24]; default: 0; - * NA - */ - uint32_t ch4_src_stat_en:1; - /** ch4_dst_stat_en : R/W; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch4_dst_stat_en:1; - /** ch4_ioc_blktfr : R/W; bitpos: [26]; default: 0; - * NA - */ - uint32_t ch4_ioc_blktfr:1; - uint32_t reserved_27:3; - /** ch4_shadowreg_or_lli_last : R/W; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch4_shadowreg_or_lli_last:1; - /** ch4_shadowreg_or_lli_valid : R/W; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch4_shadowreg_or_lli_valid:1; - }; - uint32_t val; -} dmac_ch4_ctl1_reg_t; - -/** Type of ch4_cfg0 register - * NA - */ -typedef union { - struct { - /** ch4_src_multblk_type : R/W; bitpos: [1:0]; default: 0; - * NA - */ - uint32_t ch4_src_multblk_type:2; - /** ch4_dst_multblk_type : R/W; bitpos: [3:2]; default: 0; - * NA - */ - uint32_t ch4_dst_multblk_type:2; - uint32_t reserved_4:14; - /** ch4_rd_uid : RO; bitpos: [21:18]; default: 0; - * NA - */ - uint32_t ch4_rd_uid:4; - uint32_t reserved_22:3; - /** ch4_wr_uid : RO; bitpos: [28:25]; default: 0; - * NA - */ - uint32_t ch4_wr_uid:4; - uint32_t reserved_29:3; - }; - uint32_t val; -} dmac_ch4_cfg0_reg_t; - -/** Type of ch4_cfg1 register - * NA - */ -typedef union { - struct { - /** ch4_tt_fc : R/W; bitpos: [2:0]; default: 3; - * NA - */ - uint32_t ch4_tt_fc:3; - /** ch4_hs_sel_src : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch4_hs_sel_src:1; - /** ch4_hs_sel_dst : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch4_hs_sel_dst:1; - /** ch4_src_hwhs_pol : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch4_src_hwhs_pol:1; - /** ch4_dst_hwhs_pol : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch4_dst_hwhs_pol:1; - /** ch4_src_per : R/W; bitpos: [8:7]; default: 0; - * NA - */ - uint32_t ch4_src_per:2; - uint32_t reserved_9:3; - /** ch4_dst_per : R/W; bitpos: [13:12]; default: 0; - * NA - */ - uint32_t ch4_dst_per:2; - uint32_t reserved_14:3; - /** ch4_ch_prior : R/W; bitpos: [19:17]; default: 0; - * NA - */ - uint32_t ch4_ch_prior:3; - /** ch4_lock_ch : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch4_lock_ch:1; - /** ch4_lock_ch_l : RO; bitpos: [22:21]; default: 0; - * NA - */ - uint32_t ch4_lock_ch_l:2; - /** ch4_src_osr_lmt : R/W; bitpos: [26:23]; default: 0; - * NA - */ - uint32_t ch4_src_osr_lmt:4; - /** ch4_dst_osr_lmt : R/W; bitpos: [30:27]; default: 0; - * NA - */ - uint32_t ch4_dst_osr_lmt:4; - uint32_t reserved_31:1; - }; - uint32_t val; -} dmac_ch4_cfg1_reg_t; - -/** Type of ch4_llp0 register - * NA - */ -typedef union { - struct { - /** ch4_lms : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_lms:1; - uint32_t reserved_1:5; - /** ch4_loc0 : R/W; bitpos: [31:6]; default: 0; - * NA - */ - uint32_t ch4_loc0:26; - }; - uint32_t val; -} dmac_ch4_llp0_reg_t; - -/** Type of ch4_llp1 register - * NA - */ -typedef union { - struct { - /** ch4_loc1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_loc1:32; - }; - uint32_t val; -} dmac_ch4_llp1_reg_t; - -/** Type of ch4_swhssrc0 register - * NA - */ -typedef union { - struct { - /** ch4_swhs_req_src : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_swhs_req_src:1; - /** ch4_swhs_req_src_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch4_swhs_req_src_we:1; - /** ch4_swhs_sglreq_src : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch4_swhs_sglreq_src:1; - /** ch4_swhs_sglreq_src_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_swhs_sglreq_src_we:1; - /** ch4_swhs_lst_src : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch4_swhs_lst_src:1; - /** ch4_swhs_lst_src_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch4_swhs_lst_src_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch4_swhssrc0_reg_t; - -/** Type of ch4_swhsdst0 register - * NA - */ -typedef union { - struct { - /** ch4_swhs_req_dst : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_swhs_req_dst:1; - /** ch4_swhs_req_dst_we : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch4_swhs_req_dst_we:1; - /** ch4_swhs_sglreq_dst : R/W; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch4_swhs_sglreq_dst:1; - /** ch4_swhs_sglreq_dst_we : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_swhs_sglreq_dst_we:1; - /** ch4_swhs_lst_dst : R/W; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch4_swhs_lst_dst:1; - /** ch4_swhs_lst_dst_we : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch4_swhs_lst_dst_we:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} dmac_ch4_swhsdst0_reg_t; - -/** Type of ch4_blk_tfr_resumereq0 register - * NA - */ -typedef union { - struct { - /** ch4_blk_tfr_resumereq : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_blk_tfr_resumereq:1; - uint32_t reserved_1:31; - }; - uint32_t val; -} dmac_ch4_blk_tfr_resumereq0_reg_t; - -/** Type of ch4_axi_id0 register - * NA - */ -typedef union { - struct { - /** ch4_axi_read_id_suffix : R/W; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_axi_read_id_suffix:1; - uint32_t reserved_1:15; - /** ch4_axi_write_id_suffix : R/W; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch4_axi_write_id_suffix:1; - uint32_t reserved_17:15; - }; - uint32_t val; -} dmac_ch4_axi_id0_reg_t; - -/** Type of ch4_axi_qos0 register - * NA - */ -typedef union { - struct { - /** ch4_axi_awqos : R/W; bitpos: [3:0]; default: 0; - * NA - */ - uint32_t ch4_axi_awqos:4; - /** ch4_axi_arqos : R/W; bitpos: [7:4]; default: 0; - * NA - */ - uint32_t ch4_axi_arqos:4; - uint32_t reserved_8:24; - }; - uint32_t val; -} dmac_ch4_axi_qos0_reg_t; - - -/** Group: Interrupt Registers */ -/** Type of intstatus0 register - * NA - */ -typedef union { - struct { - /** ch1_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_intstat:1; - /** ch2_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_intstat:1; - /** ch3_intstat : RO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_intstat:1; - /** ch4_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_intstat:1; - uint32_t reserved_4:12; - /** commonreg_intstat : RO; bitpos: [16]; default: 0; - * NA - */ - uint32_t commonreg_intstat:1; - uint32_t reserved_17:15; - }; - uint32_t val; -} dmac_intstatus0_reg_t; - -/** Type of commonreg_intclear0 register - * NA - */ -typedef union { - struct { - /** clear_slvif_commonreg_dec_err_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t clear_slvif_commonreg_dec_err_intstat:1; - /** clear_slvif_commonreg_wr2ro_err_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t clear_slvif_commonreg_wr2ro_err_intstat:1; - /** clear_slvif_commonreg_rd2wo_err_intstat : WO; bitpos: [2]; default: 0; - * NA - */ - uint32_t clear_slvif_commonreg_rd2wo_err_intstat:1; - /** clear_slvif_commonreg_wronhold_err_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t clear_slvif_commonreg_wronhold_err_intstat:1; - uint32_t reserved_4:3; - /** clear_slvif_commonreg_wrparity_err_intstat : WO; bitpos: [7]; default: 0; - * NA - */ - uint32_t clear_slvif_commonreg_wrparity_err_intstat:1; - /** clear_slvif_undefinedreg_dec_err_intstat : WO; bitpos: [8]; default: 0; - * NA - */ - uint32_t clear_slvif_undefinedreg_dec_err_intstat:1; - /** clear_mxif1_rch0_eccprot_correrr_intstat : WO; bitpos: [9]; default: 0; - * NA - */ - uint32_t clear_mxif1_rch0_eccprot_correrr_intstat:1; - /** clear_mxif1_rch0_eccprot_uncorrerr_intstat : WO; bitpos: [10]; default: 0; - * NA - */ - uint32_t clear_mxif1_rch0_eccprot_uncorrerr_intstat:1; - /** clear_mxif1_rch1_eccprot_correrr_intstat : WO; bitpos: [11]; default: 0; - * NA - */ - uint32_t clear_mxif1_rch1_eccprot_correrr_intstat:1; - /** clear_mxif1_rch1_eccprot_uncorrerr_intstat : WO; bitpos: [12]; default: 0; - * NA - */ - uint32_t clear_mxif1_rch1_eccprot_uncorrerr_intstat:1; - /** clear_mxif1_bch_eccprot_correrr_intstat : WO; bitpos: [13]; default: 0; - * NA - */ - uint32_t clear_mxif1_bch_eccprot_correrr_intstat:1; - /** clear_mxif1_bch_eccprot_uncorrerr_intstat : WO; bitpos: [14]; default: 0; - * NA - */ - uint32_t clear_mxif1_bch_eccprot_uncorrerr_intstat:1; - /** clear_mxif2_rch0_eccprot_correrr_intstat : WO; bitpos: [15]; default: 0; - * NA - */ - uint32_t clear_mxif2_rch0_eccprot_correrr_intstat:1; - /** clear_mxif2_rch0_eccprot_uncorrerr_intstat : WO; bitpos: [16]; default: 0; - * NA - */ - uint32_t clear_mxif2_rch0_eccprot_uncorrerr_intstat:1; - /** clear_mxif2_rch1_eccprot_correrr_intstat : WO; bitpos: [17]; default: 0; - * NA - */ - uint32_t clear_mxif2_rch1_eccprot_correrr_intstat:1; - /** clear_mxif2_rch1_eccprot_uncorrerr_intstat : WO; bitpos: [18]; default: 0; - * NA - */ - uint32_t clear_mxif2_rch1_eccprot_uncorrerr_intstat:1; - /** clear_mxif2_bch_eccprot_correrr_intstat : WO; bitpos: [19]; default: 0; - * NA - */ - uint32_t clear_mxif2_bch_eccprot_correrr_intstat:1; - /** clear_mxif2_bch_eccprot_uncorrerr_intstat : WO; bitpos: [20]; default: 0; - * NA - */ - uint32_t clear_mxif2_bch_eccprot_uncorrerr_intstat:1; - uint32_t reserved_21:11; - }; - uint32_t val; -} dmac_commonreg_intclear0_reg_t; - -/** Type of commonreg_intstatus_enable0 register - * NA - */ -typedef union { - struct { - /** enable_slvif_commonreg_dec_err_intstat : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_dec_err_intstat:1; - /** enable_slvif_commonreg_wr2ro_err_intstat : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_wr2ro_err_intstat:1; - /** enable_slvif_commonreg_rd2wo_err_intstat : R/W; bitpos: [2]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_rd2wo_err_intstat:1; - /** enable_slvif_commonreg_wronhold_err_intstat : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_wronhold_err_intstat:1; - uint32_t reserved_4:3; - /** enable_slvif_commonreg_wrparity_err_intstat : RO; bitpos: [7]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_wrparity_err_intstat:1; - /** enable_slvif_undefinedreg_dec_err_intstat : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t enable_slvif_undefinedreg_dec_err_intstat:1; - /** enable_mxif1_rch0_eccprot_correrr_intstat : RO; bitpos: [9]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch0_eccprot_correrr_intstat:1; - /** enable_mxif1_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [10]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch0_eccprot_uncorrerr_intstat:1; - /** enable_mxif1_rch1_eccprot_correrr_intstat : RO; bitpos: [11]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch1_eccprot_correrr_intstat:1; - /** enable_mxif1_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [12]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch1_eccprot_uncorrerr_intstat:1; - /** enable_mxif1_bch_eccprot_correrr_intstat : RO; bitpos: [13]; default: 1; - * NA - */ - uint32_t enable_mxif1_bch_eccprot_correrr_intstat:1; - /** enable_mxif1_bch_eccprot_uncorrerr_intstat : RO; bitpos: [14]; default: 1; - * NA - */ - uint32_t enable_mxif1_bch_eccprot_uncorrerr_intstat:1; - /** enable_mxif2_rch0_eccprot_correrr_intstat : RO; bitpos: [15]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch0_eccprot_correrr_intstat:1; - /** enable_mxif2_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [16]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch0_eccprot_uncorrerr_intstat:1; - /** enable_mxif2_rch1_eccprot_correrr_intstat : RO; bitpos: [17]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch1_eccprot_correrr_intstat:1; - /** enable_mxif2_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [18]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch1_eccprot_uncorrerr_intstat:1; - /** enable_mxif2_bch_eccprot_correrr_intstat : RO; bitpos: [19]; default: 1; - * NA - */ - uint32_t enable_mxif2_bch_eccprot_correrr_intstat:1; - /** enable_mxif2_bch_eccprot_uncorrerr_intstat : RO; bitpos: [20]; default: 1; - * NA - */ - uint32_t enable_mxif2_bch_eccprot_uncorrerr_intstat:1; - uint32_t reserved_21:11; - }; - uint32_t val; -} dmac_commonreg_intstatus_enable0_reg_t; - -/** Type of commonreg_intsignal_enable0 register - * NA - */ -typedef union { - struct { - /** enable_slvif_commonreg_dec_err_intsignal : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_dec_err_intsignal:1; - /** enable_slvif_commonreg_wr2ro_err_intsignal : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_wr2ro_err_intsignal:1; - /** enable_slvif_commonreg_rd2wo_err_intsignal : R/W; bitpos: [2]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_rd2wo_err_intsignal:1; - /** enable_slvif_commonreg_wronhold_err_intsignal : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_wronhold_err_intsignal:1; - uint32_t reserved_4:3; - /** enable_slvif_commonreg_wrparity_err_intsignal : RO; bitpos: [7]; default: 1; - * NA - */ - uint32_t enable_slvif_commonreg_wrparity_err_intsignal:1; - /** enable_slvif_undefinedreg_dec_err_intsignal : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t enable_slvif_undefinedreg_dec_err_intsignal:1; - /** enable_mxif1_rch0_eccprot_correrr_intsignal : RO; bitpos: [9]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch0_eccprot_correrr_intsignal:1; - /** enable_mxif1_rch0_eccprot_uncorrerr_intsignal : RO; bitpos: [10]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch0_eccprot_uncorrerr_intsignal:1; - /** enable_mxif1_rch1_eccprot_correrr_intsignal : RO; bitpos: [11]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch1_eccprot_correrr_intsignal:1; - /** enable_mxif1_rch1_eccprot_uncorrerr_intsignal : RO; bitpos: [12]; default: 1; - * NA - */ - uint32_t enable_mxif1_rch1_eccprot_uncorrerr_intsignal:1; - /** enable_mxif1_bch_eccprot_correrr_intsignal : RO; bitpos: [13]; default: 1; - * NA - */ - uint32_t enable_mxif1_bch_eccprot_correrr_intsignal:1; - /** enable_mxif1_bch_eccprot_uncorrerr_intsignal : RO; bitpos: [14]; default: 1; - * NA - */ - uint32_t enable_mxif1_bch_eccprot_uncorrerr_intsignal:1; - /** enable_mxif2_rch0_eccprot_correrr_intsignal : RO; bitpos: [15]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch0_eccprot_correrr_intsignal:1; - /** enable_mxif2_rch0_eccprot_uncorrerr_intsignal : RO; bitpos: [16]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch0_eccprot_uncorrerr_intsignal:1; - /** enable_mxif2_rch1_eccprot_correrr_intsignal : RO; bitpos: [17]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch1_eccprot_correrr_intsignal:1; - /** enable_mxif2_rch1_eccprot_uncorrerr_intsignal : RO; bitpos: [18]; default: 1; - * NA - */ - uint32_t enable_mxif2_rch1_eccprot_uncorrerr_intsignal:1; - /** enable_mxif2_bch_eccprot_correrr_intsignal : RO; bitpos: [19]; default: 1; - * NA - */ - uint32_t enable_mxif2_bch_eccprot_correrr_intsignal:1; - /** enable_mxif2_bch_eccprot_uncorrerr_intsignal : RO; bitpos: [20]; default: 1; - * NA - */ - uint32_t enable_mxif2_bch_eccprot_uncorrerr_intsignal:1; - uint32_t reserved_21:11; - }; - uint32_t val; -} dmac_commonreg_intsignal_enable0_reg_t; - -/** Type of commonreg_intstatus0 register - * NA - */ -typedef union { - struct { - /** slvif_commonreg_dec_err_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t slvif_commonreg_dec_err_intstat:1; - /** slvif_commonreg_wr2ro_err_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t slvif_commonreg_wr2ro_err_intstat:1; - /** slvif_commonreg_rd2wo_err_intstat : RO; bitpos: [2]; default: 0; - * NA - */ - uint32_t slvif_commonreg_rd2wo_err_intstat:1; - /** slvif_commonreg_wronhold_err_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t slvif_commonreg_wronhold_err_intstat:1; - uint32_t reserved_4:3; - /** slvif_commonreg_wrparity_err_intstat : RO; bitpos: [7]; default: 0; - * NA - */ - uint32_t slvif_commonreg_wrparity_err_intstat:1; - /** slvif_undefinedreg_dec_err_intstat : RO; bitpos: [8]; default: 0; - * NA - */ - uint32_t slvif_undefinedreg_dec_err_intstat:1; - /** mxif1_rch0_eccprot_correrr_intstat : RO; bitpos: [9]; default: 0; - * NA - */ - uint32_t mxif1_rch0_eccprot_correrr_intstat:1; - /** mxif1_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [10]; default: 0; - * NA - */ - uint32_t mxif1_rch0_eccprot_uncorrerr_intstat:1; - /** mxif1_rch1_eccprot_correrr_intstat : RO; bitpos: [11]; default: 0; - * NA - */ - uint32_t mxif1_rch1_eccprot_correrr_intstat:1; - /** mxif1_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [12]; default: 0; - * NA - */ - uint32_t mxif1_rch1_eccprot_uncorrerr_intstat:1; - /** mxif1_bch_eccprot_correrr_intstat : RO; bitpos: [13]; default: 0; - * NA - */ - uint32_t mxif1_bch_eccprot_correrr_intstat:1; - /** mxif1_bch_eccprot_uncorrerr_intstat : RO; bitpos: [14]; default: 0; - * NA - */ - uint32_t mxif1_bch_eccprot_uncorrerr_intstat:1; - /** mxif2_rch0_eccprot_correrr_intstat : RO; bitpos: [15]; default: 0; - * NA - */ - uint32_t mxif2_rch0_eccprot_correrr_intstat:1; - /** mxif2_rch0_eccprot_uncorrerr_intstat : RO; bitpos: [16]; default: 0; - * NA - */ - uint32_t mxif2_rch0_eccprot_uncorrerr_intstat:1; - /** mxif2_rch1_eccprot_correrr_intstat : RO; bitpos: [17]; default: 0; - * NA - */ - uint32_t mxif2_rch1_eccprot_correrr_intstat:1; - /** mxif2_rch1_eccprot_uncorrerr_intstat : RO; bitpos: [18]; default: 0; - * NA - */ - uint32_t mxif2_rch1_eccprot_uncorrerr_intstat:1; - /** mxif2_bch_eccprot_correrr_intstat : RO; bitpos: [19]; default: 0; - * NA - */ - uint32_t mxif2_bch_eccprot_correrr_intstat:1; - /** mxif2_bch_eccprot_uncorrerr_intstat : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t mxif2_bch_eccprot_uncorrerr_intstat:1; - uint32_t reserved_21:11; - }; - uint32_t val; -} dmac_commonreg_intstatus0_reg_t; - -/** Type of ch1_intstatus_enable0 register - * NA - */ -typedef union { - struct { - /** ch1_enable_block_tfr_done_intstat : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch1_enable_block_tfr_done_intstat:1; - /** ch1_enable_dma_tfr_done_intstat : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch1_enable_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch1_enable_src_transcomp_intstat : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch1_enable_src_transcomp_intstat:1; - /** ch1_enable_dst_transcomp_intstat : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch1_enable_dst_transcomp_intstat:1; - /** ch1_enable_src_dec_err_intstat : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch1_enable_src_dec_err_intstat:1; - /** ch1_enable_dst_dec_err_intstat : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch1_enable_dst_dec_err_intstat:1; - /** ch1_enable_src_slv_err_intstat : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch1_enable_src_slv_err_intstat:1; - /** ch1_enable_dst_slv_err_intstat : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch1_enable_dst_slv_err_intstat:1; - /** ch1_enable_lli_rd_dec_err_intstat : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_rd_dec_err_intstat:1; - /** ch1_enable_lli_wr_dec_err_intstat : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_wr_dec_err_intstat:1; - /** ch1_enable_lli_rd_slv_err_intstat : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_rd_slv_err_intstat:1; - /** ch1_enable_lli_wr_slv_err_intstat : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_wr_slv_err_intstat:1; - /** ch1_enable_shadowreg_or_lli_invalid_err_intstat : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch1_enable_shadowreg_or_lli_invalid_err_intstat:1; - /** ch1_enable_slvif_multiblktype_err_intstat : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch1_enable_slvif_dec_err_intstat : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_dec_err_intstat:1; - /** ch1_enable_slvif_wr2ro_err_intstat : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wr2ro_err_intstat:1; - /** ch1_enable_slvif_rd2rwo_err_intstat : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_rd2rwo_err_intstat:1; - /** ch1_enable_slvif_wronchen_err_intstat : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wronchen_err_intstat:1; - /** ch1_enable_slvif_shadowreg_wron_valid_err_intstat : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch1_enable_slvif_wronhold_err_intstat : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch1_enable_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch1_enable_ch_lock_cleared_intstat : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_lock_cleared_intstat:1; - /** ch1_enable_ch_src_suspended_intstat : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_src_suspended_intstat:1; - /** ch1_enable_ch_suspended_intstat : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_suspended_intstat:1; - /** ch1_enable_ch_disabled_intstat : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_disabled_intstat:1; - /** ch1_enable_ch_aborted_intstat : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch1_intstatus_enable0_reg_t; - -/** Type of ch1_intstatus_enable1 register - * NA - */ -typedef union { - struct { - /** ch1_enable_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_chmem_correrr_intstat:1; - /** ch1_enable_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch1_enable_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_uidmem_correrr_intstat:1; - /** ch1_enable_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch1_intstatus_enable1_reg_t; - -/** Type of ch1_intstatus0 register - * NA - */ -typedef union { - struct { - /** ch1_block_tfr_done_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_block_tfr_done_intstat:1; - /** ch1_dma_tfr_done_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch1_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch1_src_transcomp_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch1_src_transcomp_intstat:1; - /** ch1_dst_transcomp_intstat : RO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch1_dst_transcomp_intstat:1; - /** ch1_src_dec_err_intstat : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch1_src_dec_err_intstat:1; - /** ch1_dst_dec_err_intstat : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch1_dst_dec_err_intstat:1; - /** ch1_src_slv_err_intstat : RO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch1_src_slv_err_intstat:1; - /** ch1_dst_slv_err_intstat : RO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch1_dst_slv_err_intstat:1; - /** ch1_lli_rd_dec_err_intstat : RO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch1_lli_rd_dec_err_intstat:1; - /** ch1_lli_wr_dec_err_intstat : RO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch1_lli_wr_dec_err_intstat:1; - /** ch1_lli_rd_slv_err_intstat : RO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch1_lli_rd_slv_err_intstat:1; - /** ch1_lli_wr_slv_err_intstat : RO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch1_lli_wr_slv_err_intstat:1; - /** ch1_shadowreg_or_lli_invalid_err_intstat : RO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch1_shadowreg_or_lli_invalid_err_intstat:1; - /** ch1_slvif_multiblktype_err_intstat : RO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch1_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch1_slvif_dec_err_intstat : RO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch1_slvif_dec_err_intstat:1; - /** ch1_slvif_wr2ro_err_intstat : RO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch1_slvif_wr2ro_err_intstat:1; - /** ch1_slvif_rd2rwo_err_intstat : RO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch1_slvif_rd2rwo_err_intstat:1; - /** ch1_slvif_wronchen_err_intstat : RO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch1_slvif_wronchen_err_intstat:1; - /** ch1_slvif_shadowreg_wron_valid_err_intstat : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch1_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch1_slvif_wronhold_err_intstat : RO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch1_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch1_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch1_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch1_ch_lock_cleared_intstat : RO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch1_ch_lock_cleared_intstat:1; - /** ch1_ch_src_suspended_intstat : RO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch1_ch_src_suspended_intstat:1; - /** ch1_ch_suspended_intstat : RO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch1_ch_suspended_intstat:1; - /** ch1_ch_disabled_intstat : RO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch1_ch_disabled_intstat:1; - /** ch1_ch_aborted_intstat : RO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch1_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch1_intstatus0_reg_t; - -/** Type of ch1_intstatus1 register - * NA - */ -typedef union { - struct { - /** ch1_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_ecc_prot_chmem_correrr_intstat:1; - /** ch1_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch1_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch1_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch1_ecc_prot_uidmem_correrr_intstat:1; - /** ch1_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch1_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch1_intstatus1_reg_t; - -/** Type of ch1_intsignal_enable0 register - * NA - */ -typedef union { - struct { - /** ch1_enable_block_tfr_done_intsignal : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch1_enable_block_tfr_done_intsignal:1; - /** ch1_enable_dma_tfr_done_intsignal : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch1_enable_dma_tfr_done_intsignal:1; - uint32_t reserved_2:1; - /** ch1_enable_src_transcomp_intsignal : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch1_enable_src_transcomp_intsignal:1; - /** ch1_enable_dst_transcomp_intsignal : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch1_enable_dst_transcomp_intsignal:1; - /** ch1_enable_src_dec_err_intsignal : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch1_enable_src_dec_err_intsignal:1; - /** ch1_enable_dst_dec_err_intsignal : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch1_enable_dst_dec_err_intsignal:1; - /** ch1_enable_src_slv_err_intsignal : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch1_enable_src_slv_err_intsignal:1; - /** ch1_enable_dst_slv_err_intsignal : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch1_enable_dst_slv_err_intsignal:1; - /** ch1_enable_lli_rd_dec_err_intsignal : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_rd_dec_err_intsignal:1; - /** ch1_enable_lli_wr_dec_err_intsignal : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_wr_dec_err_intsignal:1; - /** ch1_enable_lli_rd_slv_err_intsignal : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_rd_slv_err_intsignal:1; - /** ch1_enable_lli_wr_slv_err_intsignal : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch1_enable_lli_wr_slv_err_intsignal:1; - /** ch1_enable_shadowreg_or_lli_invalid_err_intsignal : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch1_enable_shadowreg_or_lli_invalid_err_intsignal:1; - /** ch1_enable_slvif_multiblktype_err_intsignal : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_multiblktype_err_intsignal:1; - uint32_t reserved_15:1; - /** ch1_enable_slvif_dec_err_intsignal : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_dec_err_intsignal:1; - /** ch1_enable_slvif_wr2ro_err_intsignal : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wr2ro_err_intsignal:1; - /** ch1_enable_slvif_rd2rwo_err_intsignal : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_rd2rwo_err_intsignal:1; - /** ch1_enable_slvif_wronchen_err_intsignal : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wronchen_err_intsignal:1; - /** ch1_enable_slvif_shadowreg_wron_valid_err_intsignal : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_shadowreg_wron_valid_err_intsignal:1; - /** ch1_enable_slvif_wronhold_err_intsignal : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wronhold_err_intsignal:1; - uint32_t reserved_22:3; - /** ch1_enable_slvif_wrparity_err_intsignal : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch1_enable_slvif_wrparity_err_intsignal:1; - uint32_t reserved_26:1; - /** ch1_enable_ch_lock_cleared_intsignal : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_lock_cleared_intsignal:1; - /** ch1_enable_ch_src_suspended_intsignal : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_src_suspended_intsignal:1; - /** ch1_enable_ch_suspended_intsignal : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_suspended_intsignal:1; - /** ch1_enable_ch_disabled_intsignal : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_disabled_intsignal:1; - /** ch1_enable_ch_aborted_intsignal : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch1_enable_ch_aborted_intsignal:1; - }; - uint32_t val; -} dmac_ch1_intsignal_enable0_reg_t; - -/** Type of ch1_intsignal_enable1 register - * NA - */ -typedef union { - struct { - /** ch1_enable_ecc_prot_chmem_correrr_intsignal : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_chmem_correrr_intsignal:1; - /** ch1_enable_ecc_prot_chmem_uncorrerr_intsignal : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_chmem_uncorrerr_intsignal:1; - /** ch1_enable_ecc_prot_uidmem_correrr_intsignal : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_uidmem_correrr_intsignal:1; - /** ch1_enable_ecc_prot_uidmem_uncorrerr_intsignal : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch1_enable_ecc_prot_uidmem_uncorrerr_intsignal:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch1_intsignal_enable1_reg_t; - -/** Type of ch1_intclear0 register - * NA - */ -typedef union { - struct { - /** ch1_clear_block_tfr_done_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_clear_block_tfr_done_intstat:1; - /** ch1_clear_dma_tfr_done_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch1_clear_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch1_clear_src_transcomp_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch1_clear_src_transcomp_intstat:1; - /** ch1_clear_dst_transcomp_intstat : WO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch1_clear_dst_transcomp_intstat:1; - /** ch1_clear_src_dec_err_intstat : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch1_clear_src_dec_err_intstat:1; - /** ch1_clear_dst_dec_err_intstat : WO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch1_clear_dst_dec_err_intstat:1; - /** ch1_clear_src_slv_err_intstat : WO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch1_clear_src_slv_err_intstat:1; - /** ch1_clear_dst_slv_err_intstat : WO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch1_clear_dst_slv_err_intstat:1; - /** ch1_clear_lli_rd_dec_err_intstat : WO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch1_clear_lli_rd_dec_err_intstat:1; - /** ch1_clear_lli_wr_dec_err_intstat : WO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch1_clear_lli_wr_dec_err_intstat:1; - /** ch1_clear_lli_rd_slv_err_intstat : WO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch1_clear_lli_rd_slv_err_intstat:1; - /** ch1_clear_lli_wr_slv_err_intstat : WO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch1_clear_lli_wr_slv_err_intstat:1; - /** ch1_clear_shadowreg_or_lli_invalid_err_intstat : WO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch1_clear_shadowreg_or_lli_invalid_err_intstat:1; - /** ch1_clear_slvif_multiblktype_err_intstat : WO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch1_clear_slvif_dec_err_intstat : WO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_dec_err_intstat:1; - /** ch1_clear_slvif_wr2ro_err_intstat : WO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_wr2ro_err_intstat:1; - /** ch1_clear_slvif_rd2rwo_err_intstat : WO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_rd2rwo_err_intstat:1; - /** ch1_clear_slvif_wronchen_err_intstat : WO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_wronchen_err_intstat:1; - /** ch1_clear_slvif_shadowreg_wron_valid_err_intstat : WO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch1_clear_slvif_wronhold_err_intstat : WO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch1_clear_slvif_wrparity_err_intstat : WO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch1_clear_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch1_clear_ch_lock_cleared_intstat : WO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch1_clear_ch_lock_cleared_intstat:1; - /** ch1_clear_ch_src_suspended_intstat : WO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch1_clear_ch_src_suspended_intstat:1; - /** ch1_clear_ch_suspended_intstat : WO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch1_clear_ch_suspended_intstat:1; - /** ch1_clear_ch_disabled_intstat : WO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch1_clear_ch_disabled_intstat:1; - /** ch1_clear_ch_aborted_intstat : WO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch1_clear_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch1_intclear0_reg_t; - -/** Type of ch1_intclear1 register - * NA - */ -typedef union { - struct { - /** ch1_clear_ecc_prot_chmem_correrr_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch1_clear_ecc_prot_chmem_correrr_intstat:1; - /** ch1_clear_ecc_prot_chmem_uncorrerr_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch1_clear_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch1_clear_ecc_prot_uidmem_correrr_intstat : WO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch1_clear_ecc_prot_uidmem_correrr_intstat:1; - /** ch1_clear_ecc_prot_uidmem_uncorrerr_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch1_clear_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch1_intclear1_reg_t; - -/** Type of ch2_intstatus_enable0 register - * NA - */ -typedef union { - struct { - /** ch2_enable_block_tfr_done_intstat : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch2_enable_block_tfr_done_intstat:1; - /** ch2_enable_dma_tfr_done_intstat : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch2_enable_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch2_enable_src_transcomp_intstat : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch2_enable_src_transcomp_intstat:1; - /** ch2_enable_dst_transcomp_intstat : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch2_enable_dst_transcomp_intstat:1; - /** ch2_enable_src_dec_err_intstat : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch2_enable_src_dec_err_intstat:1; - /** ch2_enable_dst_dec_err_intstat : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch2_enable_dst_dec_err_intstat:1; - /** ch2_enable_src_slv_err_intstat : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch2_enable_src_slv_err_intstat:1; - /** ch2_enable_dst_slv_err_intstat : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch2_enable_dst_slv_err_intstat:1; - /** ch2_enable_lli_rd_dec_err_intstat : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_rd_dec_err_intstat:1; - /** ch2_enable_lli_wr_dec_err_intstat : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_wr_dec_err_intstat:1; - /** ch2_enable_lli_rd_slv_err_intstat : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_rd_slv_err_intstat:1; - /** ch2_enable_lli_wr_slv_err_intstat : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_wr_slv_err_intstat:1; - /** ch2_enable_shadowreg_or_lli_invalid_err_intstat : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch2_enable_shadowreg_or_lli_invalid_err_intstat:1; - /** ch2_enable_slvif_multiblktype_err_intstat : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch2_enable_slvif_dec_err_intstat : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_dec_err_intstat:1; - /** ch2_enable_slvif_wr2ro_err_intstat : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wr2ro_err_intstat:1; - /** ch2_enable_slvif_rd2rwo_err_intstat : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_rd2rwo_err_intstat:1; - /** ch2_enable_slvif_wronchen_err_intstat : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wronchen_err_intstat:1; - /** ch2_enable_slvif_shadowreg_wron_valid_err_intstat : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch2_enable_slvif_wronhold_err_intstat : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch2_enable_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch2_enable_ch_lock_cleared_intstat : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_lock_cleared_intstat:1; - /** ch2_enable_ch_src_suspended_intstat : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_src_suspended_intstat:1; - /** ch2_enable_ch_suspended_intstat : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_suspended_intstat:1; - /** ch2_enable_ch_disabled_intstat : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_disabled_intstat:1; - /** ch2_enable_ch_aborted_intstat : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch2_intstatus_enable0_reg_t; - -/** Type of ch2_intstatus_enable1 register - * NA - */ -typedef union { - struct { - /** ch2_enable_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_chmem_correrr_intstat:1; - /** ch2_enable_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch2_enable_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_uidmem_correrr_intstat:1; - /** ch2_enable_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch2_intstatus_enable1_reg_t; - -/** Type of ch2_intstatus0 register - * NA - */ -typedef union { - struct { - /** ch2_block_tfr_done_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_block_tfr_done_intstat:1; - /** ch2_dma_tfr_done_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch2_src_transcomp_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch2_src_transcomp_intstat:1; - /** ch2_dst_transcomp_intstat : RO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch2_dst_transcomp_intstat:1; - /** ch2_src_dec_err_intstat : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch2_src_dec_err_intstat:1; - /** ch2_dst_dec_err_intstat : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch2_dst_dec_err_intstat:1; - /** ch2_src_slv_err_intstat : RO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch2_src_slv_err_intstat:1; - /** ch2_dst_slv_err_intstat : RO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch2_dst_slv_err_intstat:1; - /** ch2_lli_rd_dec_err_intstat : RO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch2_lli_rd_dec_err_intstat:1; - /** ch2_lli_wr_dec_err_intstat : RO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch2_lli_wr_dec_err_intstat:1; - /** ch2_lli_rd_slv_err_intstat : RO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch2_lli_rd_slv_err_intstat:1; - /** ch2_lli_wr_slv_err_intstat : RO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch2_lli_wr_slv_err_intstat:1; - /** ch2_shadowreg_or_lli_invalid_err_intstat : RO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch2_shadowreg_or_lli_invalid_err_intstat:1; - /** ch2_slvif_multiblktype_err_intstat : RO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch2_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch2_slvif_dec_err_intstat : RO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch2_slvif_dec_err_intstat:1; - /** ch2_slvif_wr2ro_err_intstat : RO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch2_slvif_wr2ro_err_intstat:1; - /** ch2_slvif_rd2rwo_err_intstat : RO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch2_slvif_rd2rwo_err_intstat:1; - /** ch2_slvif_wronchen_err_intstat : RO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch2_slvif_wronchen_err_intstat:1; - /** ch2_slvif_shadowreg_wron_valid_err_intstat : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch2_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch2_slvif_wronhold_err_intstat : RO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch2_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch2_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch2_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch2_ch_lock_cleared_intstat : RO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch2_ch_lock_cleared_intstat:1; - /** ch2_ch_src_suspended_intstat : RO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch2_ch_src_suspended_intstat:1; - /** ch2_ch_suspended_intstat : RO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch2_ch_suspended_intstat:1; - /** ch2_ch_disabled_intstat : RO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch2_ch_disabled_intstat:1; - /** ch2_ch_aborted_intstat : RO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch2_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch2_intstatus0_reg_t; - -/** Type of ch2_intstatus1 register - * NA - */ -typedef union { - struct { - /** ch2_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_ecc_prot_chmem_correrr_intstat:1; - /** ch2_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch2_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch2_ecc_prot_uidmem_correrr_intstat:1; - /** ch2_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch2_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch2_intstatus1_reg_t; - -/** Type of ch2_intsignal_enable0 register - * NA - */ -typedef union { - struct { - /** ch2_enable_block_tfr_done_intsignal : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch2_enable_block_tfr_done_intsignal:1; - /** ch2_enable_dma_tfr_done_intsignal : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch2_enable_dma_tfr_done_intsignal:1; - uint32_t reserved_2:1; - /** ch2_enable_src_transcomp_intsignal : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch2_enable_src_transcomp_intsignal:1; - /** ch2_enable_dst_transcomp_intsignal : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch2_enable_dst_transcomp_intsignal:1; - /** ch2_enable_src_dec_err_intsignal : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch2_enable_src_dec_err_intsignal:1; - /** ch2_enable_dst_dec_err_intsignal : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch2_enable_dst_dec_err_intsignal:1; - /** ch2_enable_src_slv_err_intsignal : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch2_enable_src_slv_err_intsignal:1; - /** ch2_enable_dst_slv_err_intsignal : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch2_enable_dst_slv_err_intsignal:1; - /** ch2_enable_lli_rd_dec_err_intsignal : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_rd_dec_err_intsignal:1; - /** ch2_enable_lli_wr_dec_err_intsignal : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_wr_dec_err_intsignal:1; - /** ch2_enable_lli_rd_slv_err_intsignal : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_rd_slv_err_intsignal:1; - /** ch2_enable_lli_wr_slv_err_intsignal : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch2_enable_lli_wr_slv_err_intsignal:1; - /** ch2_enable_shadowreg_or_lli_invalid_err_intsignal : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch2_enable_shadowreg_or_lli_invalid_err_intsignal:1; - /** ch2_enable_slvif_multiblktype_err_intsignal : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_multiblktype_err_intsignal:1; - uint32_t reserved_15:1; - /** ch2_enable_slvif_dec_err_intsignal : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_dec_err_intsignal:1; - /** ch2_enable_slvif_wr2ro_err_intsignal : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wr2ro_err_intsignal:1; - /** ch2_enable_slvif_rd2rwo_err_intsignal : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_rd2rwo_err_intsignal:1; - /** ch2_enable_slvif_wronchen_err_intsignal : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wronchen_err_intsignal:1; - /** ch2_enable_slvif_shadowreg_wron_valid_err_intsignal : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_shadowreg_wron_valid_err_intsignal:1; - /** ch2_enable_slvif_wronhold_err_intsignal : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wronhold_err_intsignal:1; - uint32_t reserved_22:3; - /** ch2_enable_slvif_wrparity_err_intsignal : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch2_enable_slvif_wrparity_err_intsignal:1; - uint32_t reserved_26:1; - /** ch2_enable_ch_lock_cleared_intsignal : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_lock_cleared_intsignal:1; - /** ch2_enable_ch_src_suspended_intsignal : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_src_suspended_intsignal:1; - /** ch2_enable_ch_suspended_intsignal : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_suspended_intsignal:1; - /** ch2_enable_ch_disabled_intsignal : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_disabled_intsignal:1; - /** ch2_enable_ch_aborted_intsignal : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch2_enable_ch_aborted_intsignal:1; - }; - uint32_t val; -} dmac_ch2_intsignal_enable0_reg_t; - -/** Type of ch2_intsignal_enable1 register - * NA - */ -typedef union { - struct { - /** ch2_enable_ecc_prot_chmem_correrr_intsignal : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_chmem_correrr_intsignal:1; - /** ch2_enable_ecc_prot_chmem_uncorrerr_intsignal : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_chmem_uncorrerr_intsignal:1; - /** ch2_enable_ecc_prot_uidmem_correrr_intsignal : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_uidmem_correrr_intsignal:1; - /** ch2_enable_ecc_prot_uidmem_uncorrerr_intsignal : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch2_enable_ecc_prot_uidmem_uncorrerr_intsignal:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch2_intsignal_enable1_reg_t; - -/** Type of ch2_intclear0 register - * NA - */ -typedef union { - struct { - /** ch2_clear_block_tfr_done_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_clear_block_tfr_done_intstat:1; - /** ch2_clear_dma_tfr_done_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_clear_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch2_clear_src_transcomp_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch2_clear_src_transcomp_intstat:1; - /** ch2_clear_dst_transcomp_intstat : WO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch2_clear_dst_transcomp_intstat:1; - /** ch2_clear_src_dec_err_intstat : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch2_clear_src_dec_err_intstat:1; - /** ch2_clear_dst_dec_err_intstat : WO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch2_clear_dst_dec_err_intstat:1; - /** ch2_clear_src_slv_err_intstat : WO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch2_clear_src_slv_err_intstat:1; - /** ch2_clear_dst_slv_err_intstat : WO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch2_clear_dst_slv_err_intstat:1; - /** ch2_clear_lli_rd_dec_err_intstat : WO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch2_clear_lli_rd_dec_err_intstat:1; - /** ch2_clear_lli_wr_dec_err_intstat : WO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch2_clear_lli_wr_dec_err_intstat:1; - /** ch2_clear_lli_rd_slv_err_intstat : WO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch2_clear_lli_rd_slv_err_intstat:1; - /** ch2_clear_lli_wr_slv_err_intstat : WO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch2_clear_lli_wr_slv_err_intstat:1; - /** ch2_clear_shadowreg_or_lli_invalid_err_intstat : WO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch2_clear_shadowreg_or_lli_invalid_err_intstat:1; - /** ch2_clear_slvif_multiblktype_err_intstat : WO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch2_clear_slvif_dec_err_intstat : WO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_dec_err_intstat:1; - /** ch2_clear_slvif_wr2ro_err_intstat : WO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_wr2ro_err_intstat:1; - /** ch2_clear_slvif_rd2rwo_err_intstat : WO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_rd2rwo_err_intstat:1; - /** ch2_clear_slvif_wronchen_err_intstat : WO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_wronchen_err_intstat:1; - /** ch2_clear_slvif_shadowreg_wron_valid_err_intstat : WO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch2_clear_slvif_wronhold_err_intstat : WO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch2_clear_slvif_wrparity_err_intstat : WO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch2_clear_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch2_clear_ch_lock_cleared_intstat : WO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch2_clear_ch_lock_cleared_intstat:1; - /** ch2_clear_ch_src_suspended_intstat : WO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch2_clear_ch_src_suspended_intstat:1; - /** ch2_clear_ch_suspended_intstat : WO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch2_clear_ch_suspended_intstat:1; - /** ch2_clear_ch_disabled_intstat : WO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch2_clear_ch_disabled_intstat:1; - /** ch2_clear_ch_aborted_intstat : WO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch2_clear_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch2_intclear0_reg_t; - -/** Type of ch2_intclear1 register - * NA - */ -typedef union { - struct { - /** ch2_clear_ecc_prot_chmem_correrr_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch2_clear_ecc_prot_chmem_correrr_intstat:1; - /** ch2_clear_ecc_prot_chmem_uncorrerr_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch2_clear_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch2_clear_ecc_prot_uidmem_correrr_intstat : WO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch2_clear_ecc_prot_uidmem_correrr_intstat:1; - /** ch2_clear_ecc_prot_uidmem_uncorrerr_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch2_clear_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch2_intclear1_reg_t; - -/** Type of ch3_intstatus_enable0 register - * NA - */ -typedef union { - struct { - /** ch3_enable_block_tfr_done_intstat : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch3_enable_block_tfr_done_intstat:1; - /** ch3_enable_dma_tfr_done_intstat : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch3_enable_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch3_enable_src_transcomp_intstat : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch3_enable_src_transcomp_intstat:1; - /** ch3_enable_dst_transcomp_intstat : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch3_enable_dst_transcomp_intstat:1; - /** ch3_enable_src_dec_err_intstat : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch3_enable_src_dec_err_intstat:1; - /** ch3_enable_dst_dec_err_intstat : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch3_enable_dst_dec_err_intstat:1; - /** ch3_enable_src_slv_err_intstat : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch3_enable_src_slv_err_intstat:1; - /** ch3_enable_dst_slv_err_intstat : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch3_enable_dst_slv_err_intstat:1; - /** ch3_enable_lli_rd_dec_err_intstat : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_rd_dec_err_intstat:1; - /** ch3_enable_lli_wr_dec_err_intstat : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_wr_dec_err_intstat:1; - /** ch3_enable_lli_rd_slv_err_intstat : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_rd_slv_err_intstat:1; - /** ch3_enable_lli_wr_slv_err_intstat : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_wr_slv_err_intstat:1; - /** ch3_enable_shadowreg_or_lli_invalid_err_intstat : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch3_enable_shadowreg_or_lli_invalid_err_intstat:1; - /** ch3_enable_slvif_multiblktype_err_intstat : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch3_enable_slvif_dec_err_intstat : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_dec_err_intstat:1; - /** ch3_enable_slvif_wr2ro_err_intstat : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wr2ro_err_intstat:1; - /** ch3_enable_slvif_rd2rwo_err_intstat : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_rd2rwo_err_intstat:1; - /** ch3_enable_slvif_wronchen_err_intstat : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wronchen_err_intstat:1; - /** ch3_enable_slvif_shadowreg_wron_valid_err_intstat : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch3_enable_slvif_wronhold_err_intstat : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch3_enable_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch3_enable_ch_lock_cleared_intstat : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_lock_cleared_intstat:1; - /** ch3_enable_ch_src_suspended_intstat : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_src_suspended_intstat:1; - /** ch3_enable_ch_suspended_intstat : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_suspended_intstat:1; - /** ch3_enable_ch_disabled_intstat : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_disabled_intstat:1; - /** ch3_enable_ch_aborted_intstat : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch3_intstatus_enable0_reg_t; - -/** Type of ch3_intstatus_enable1 register - * NA - */ -typedef union { - struct { - /** ch3_enable_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_chmem_correrr_intstat:1; - /** ch3_enable_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch3_enable_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_uidmem_correrr_intstat:1; - /** ch3_enable_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch3_intstatus_enable1_reg_t; - -/** Type of ch3_intstatus0 register - * NA - */ -typedef union { - struct { - /** ch3_block_tfr_done_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_block_tfr_done_intstat:1; - /** ch3_dma_tfr_done_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch3_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch3_src_transcomp_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch3_src_transcomp_intstat:1; - /** ch3_dst_transcomp_intstat : RO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch3_dst_transcomp_intstat:1; - /** ch3_src_dec_err_intstat : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch3_src_dec_err_intstat:1; - /** ch3_dst_dec_err_intstat : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch3_dst_dec_err_intstat:1; - /** ch3_src_slv_err_intstat : RO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch3_src_slv_err_intstat:1; - /** ch3_dst_slv_err_intstat : RO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch3_dst_slv_err_intstat:1; - /** ch3_lli_rd_dec_err_intstat : RO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch3_lli_rd_dec_err_intstat:1; - /** ch3_lli_wr_dec_err_intstat : RO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch3_lli_wr_dec_err_intstat:1; - /** ch3_lli_rd_slv_err_intstat : RO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch3_lli_rd_slv_err_intstat:1; - /** ch3_lli_wr_slv_err_intstat : RO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch3_lli_wr_slv_err_intstat:1; - /** ch3_shadowreg_or_lli_invalid_err_intstat : RO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch3_shadowreg_or_lli_invalid_err_intstat:1; - /** ch3_slvif_multiblktype_err_intstat : RO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch3_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch3_slvif_dec_err_intstat : RO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch3_slvif_dec_err_intstat:1; - /** ch3_slvif_wr2ro_err_intstat : RO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch3_slvif_wr2ro_err_intstat:1; - /** ch3_slvif_rd2rwo_err_intstat : RO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch3_slvif_rd2rwo_err_intstat:1; - /** ch3_slvif_wronchen_err_intstat : RO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch3_slvif_wronchen_err_intstat:1; - /** ch3_slvif_shadowreg_wron_valid_err_intstat : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch3_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch3_slvif_wronhold_err_intstat : RO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch3_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch3_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch3_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch3_ch_lock_cleared_intstat : RO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch3_ch_lock_cleared_intstat:1; - /** ch3_ch_src_suspended_intstat : RO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch3_ch_src_suspended_intstat:1; - /** ch3_ch_suspended_intstat : RO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch3_ch_suspended_intstat:1; - /** ch3_ch_disabled_intstat : RO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch3_ch_disabled_intstat:1; - /** ch3_ch_aborted_intstat : RO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch3_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch3_intstatus0_reg_t; - -/** Type of ch3_intstatus1 register - * NA - */ -typedef union { - struct { - /** ch3_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_ecc_prot_chmem_correrr_intstat:1; - /** ch3_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch3_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch3_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_ecc_prot_uidmem_correrr_intstat:1; - /** ch3_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch3_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch3_intstatus1_reg_t; - -/** Type of ch3_intsignal_enable0 register - * NA - */ -typedef union { - struct { - /** ch3_enable_block_tfr_done_intsignal : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch3_enable_block_tfr_done_intsignal:1; - /** ch3_enable_dma_tfr_done_intsignal : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch3_enable_dma_tfr_done_intsignal:1; - uint32_t reserved_2:1; - /** ch3_enable_src_transcomp_intsignal : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch3_enable_src_transcomp_intsignal:1; - /** ch3_enable_dst_transcomp_intsignal : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch3_enable_dst_transcomp_intsignal:1; - /** ch3_enable_src_dec_err_intsignal : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch3_enable_src_dec_err_intsignal:1; - /** ch3_enable_dst_dec_err_intsignal : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch3_enable_dst_dec_err_intsignal:1; - /** ch3_enable_src_slv_err_intsignal : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch3_enable_src_slv_err_intsignal:1; - /** ch3_enable_dst_slv_err_intsignal : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch3_enable_dst_slv_err_intsignal:1; - /** ch3_enable_lli_rd_dec_err_intsignal : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_rd_dec_err_intsignal:1; - /** ch3_enable_lli_wr_dec_err_intsignal : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_wr_dec_err_intsignal:1; - /** ch3_enable_lli_rd_slv_err_intsignal : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_rd_slv_err_intsignal:1; - /** ch3_enable_lli_wr_slv_err_intsignal : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch3_enable_lli_wr_slv_err_intsignal:1; - /** ch3_enable_shadowreg_or_lli_invalid_err_intsignal : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch3_enable_shadowreg_or_lli_invalid_err_intsignal:1; - /** ch3_enable_slvif_multiblktype_err_intsignal : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_multiblktype_err_intsignal:1; - uint32_t reserved_15:1; - /** ch3_enable_slvif_dec_err_intsignal : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_dec_err_intsignal:1; - /** ch3_enable_slvif_wr2ro_err_intsignal : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wr2ro_err_intsignal:1; - /** ch3_enable_slvif_rd2rwo_err_intsignal : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_rd2rwo_err_intsignal:1; - /** ch3_enable_slvif_wronchen_err_intsignal : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wronchen_err_intsignal:1; - /** ch3_enable_slvif_shadowreg_wron_valid_err_intsignal : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_shadowreg_wron_valid_err_intsignal:1; - /** ch3_enable_slvif_wronhold_err_intsignal : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wronhold_err_intsignal:1; - uint32_t reserved_22:3; - /** ch3_enable_slvif_wrparity_err_intsignal : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch3_enable_slvif_wrparity_err_intsignal:1; - uint32_t reserved_26:1; - /** ch3_enable_ch_lock_cleared_intsignal : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_lock_cleared_intsignal:1; - /** ch3_enable_ch_src_suspended_intsignal : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_src_suspended_intsignal:1; - /** ch3_enable_ch_suspended_intsignal : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_suspended_intsignal:1; - /** ch3_enable_ch_disabled_intsignal : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_disabled_intsignal:1; - /** ch3_enable_ch_aborted_intsignal : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch3_enable_ch_aborted_intsignal:1; - }; - uint32_t val; -} dmac_ch3_intsignal_enable0_reg_t; - -/** Type of ch3_intsignal_enable1 register - * NA - */ -typedef union { - struct { - /** ch3_enable_ecc_prot_chmem_correrr_intsignal : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_chmem_correrr_intsignal:1; - /** ch3_enable_ecc_prot_chmem_uncorrerr_intsignal : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_chmem_uncorrerr_intsignal:1; - /** ch3_enable_ecc_prot_uidmem_correrr_intsignal : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_uidmem_correrr_intsignal:1; - /** ch3_enable_ecc_prot_uidmem_uncorrerr_intsignal : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch3_enable_ecc_prot_uidmem_uncorrerr_intsignal:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch3_intsignal_enable1_reg_t; - -/** Type of ch3_intclear0 register - * NA - */ -typedef union { - struct { - /** ch3_clear_block_tfr_done_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_clear_block_tfr_done_intstat:1; - /** ch3_clear_dma_tfr_done_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch3_clear_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch3_clear_src_transcomp_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch3_clear_src_transcomp_intstat:1; - /** ch3_clear_dst_transcomp_intstat : WO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch3_clear_dst_transcomp_intstat:1; - /** ch3_clear_src_dec_err_intstat : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch3_clear_src_dec_err_intstat:1; - /** ch3_clear_dst_dec_err_intstat : WO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch3_clear_dst_dec_err_intstat:1; - /** ch3_clear_src_slv_err_intstat : WO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch3_clear_src_slv_err_intstat:1; - /** ch3_clear_dst_slv_err_intstat : WO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch3_clear_dst_slv_err_intstat:1; - /** ch3_clear_lli_rd_dec_err_intstat : WO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch3_clear_lli_rd_dec_err_intstat:1; - /** ch3_clear_lli_wr_dec_err_intstat : WO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch3_clear_lli_wr_dec_err_intstat:1; - /** ch3_clear_lli_rd_slv_err_intstat : WO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch3_clear_lli_rd_slv_err_intstat:1; - /** ch3_clear_lli_wr_slv_err_intstat : WO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch3_clear_lli_wr_slv_err_intstat:1; - /** ch3_clear_shadowreg_or_lli_invalid_err_intstat : WO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch3_clear_shadowreg_or_lli_invalid_err_intstat:1; - /** ch3_clear_slvif_multiblktype_err_intstat : WO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch3_clear_slvif_dec_err_intstat : WO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_dec_err_intstat:1; - /** ch3_clear_slvif_wr2ro_err_intstat : WO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_wr2ro_err_intstat:1; - /** ch3_clear_slvif_rd2rwo_err_intstat : WO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_rd2rwo_err_intstat:1; - /** ch3_clear_slvif_wronchen_err_intstat : WO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_wronchen_err_intstat:1; - /** ch3_clear_slvif_shadowreg_wron_valid_err_intstat : WO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch3_clear_slvif_wronhold_err_intstat : WO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch3_clear_slvif_wrparity_err_intstat : WO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch3_clear_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch3_clear_ch_lock_cleared_intstat : WO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch3_clear_ch_lock_cleared_intstat:1; - /** ch3_clear_ch_src_suspended_intstat : WO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch3_clear_ch_src_suspended_intstat:1; - /** ch3_clear_ch_suspended_intstat : WO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch3_clear_ch_suspended_intstat:1; - /** ch3_clear_ch_disabled_intstat : WO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch3_clear_ch_disabled_intstat:1; - /** ch3_clear_ch_aborted_intstat : WO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch3_clear_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch3_intclear0_reg_t; - -/** Type of ch3_intclear1 register - * NA - */ -typedef union { - struct { - /** ch3_clear_ecc_prot_chmem_correrr_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch3_clear_ecc_prot_chmem_correrr_intstat:1; - /** ch3_clear_ecc_prot_chmem_uncorrerr_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch3_clear_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch3_clear_ecc_prot_uidmem_correrr_intstat : WO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch3_clear_ecc_prot_uidmem_correrr_intstat:1; - /** ch3_clear_ecc_prot_uidmem_uncorrerr_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch3_clear_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch3_intclear1_reg_t; - -/** Type of ch4_intstatus_enable0 register - * NA - */ -typedef union { - struct { - /** ch4_enable_block_tfr_done_intstat : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch4_enable_block_tfr_done_intstat:1; - /** ch4_enable_dma_tfr_done_intstat : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch4_enable_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch4_enable_src_transcomp_intstat : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch4_enable_src_transcomp_intstat:1; - /** ch4_enable_dst_transcomp_intstat : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch4_enable_dst_transcomp_intstat:1; - /** ch4_enable_src_dec_err_intstat : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch4_enable_src_dec_err_intstat:1; - /** ch4_enable_dst_dec_err_intstat : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch4_enable_dst_dec_err_intstat:1; - /** ch4_enable_src_slv_err_intstat : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch4_enable_src_slv_err_intstat:1; - /** ch4_enable_dst_slv_err_intstat : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch4_enable_dst_slv_err_intstat:1; - /** ch4_enable_lli_rd_dec_err_intstat : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_rd_dec_err_intstat:1; - /** ch4_enable_lli_wr_dec_err_intstat : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_wr_dec_err_intstat:1; - /** ch4_enable_lli_rd_slv_err_intstat : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_rd_slv_err_intstat:1; - /** ch4_enable_lli_wr_slv_err_intstat : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_wr_slv_err_intstat:1; - /** ch4_enable_shadowreg_or_lli_invalid_err_intstat : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch4_enable_shadowreg_or_lli_invalid_err_intstat:1; - /** ch4_enable_slvif_multiblktype_err_intstat : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch4_enable_slvif_dec_err_intstat : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_dec_err_intstat:1; - /** ch4_enable_slvif_wr2ro_err_intstat : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wr2ro_err_intstat:1; - /** ch4_enable_slvif_rd2rwo_err_intstat : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_rd2rwo_err_intstat:1; - /** ch4_enable_slvif_wronchen_err_intstat : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wronchen_err_intstat:1; - /** ch4_enable_slvif_shadowreg_wron_valid_err_intstat : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch4_enable_slvif_wronhold_err_intstat : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch4_enable_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch4_enable_ch_lock_cleared_intstat : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_lock_cleared_intstat:1; - /** ch4_enable_ch_src_suspended_intstat : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_src_suspended_intstat:1; - /** ch4_enable_ch_suspended_intstat : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_suspended_intstat:1; - /** ch4_enable_ch_disabled_intstat : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_disabled_intstat:1; - /** ch4_enable_ch_aborted_intstat : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch4_intstatus_enable0_reg_t; - -/** Type of ch4_intstatus_enable1 register - * NA - */ -typedef union { - struct { - /** ch4_enable_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_chmem_correrr_intstat:1; - /** ch4_enable_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch4_enable_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_uidmem_correrr_intstat:1; - /** ch4_enable_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch4_intstatus_enable1_reg_t; - -/** Type of ch4_intstatus0 register - * NA - */ -typedef union { - struct { - /** ch4_block_tfr_done_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_block_tfr_done_intstat:1; - /** ch4_dma_tfr_done_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch4_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch4_src_transcomp_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_src_transcomp_intstat:1; - /** ch4_dst_transcomp_intstat : RO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch4_dst_transcomp_intstat:1; - /** ch4_src_dec_err_intstat : RO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch4_src_dec_err_intstat:1; - /** ch4_dst_dec_err_intstat : RO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch4_dst_dec_err_intstat:1; - /** ch4_src_slv_err_intstat : RO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch4_src_slv_err_intstat:1; - /** ch4_dst_slv_err_intstat : RO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch4_dst_slv_err_intstat:1; - /** ch4_lli_rd_dec_err_intstat : RO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch4_lli_rd_dec_err_intstat:1; - /** ch4_lli_wr_dec_err_intstat : RO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch4_lli_wr_dec_err_intstat:1; - /** ch4_lli_rd_slv_err_intstat : RO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch4_lli_rd_slv_err_intstat:1; - /** ch4_lli_wr_slv_err_intstat : RO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch4_lli_wr_slv_err_intstat:1; - /** ch4_shadowreg_or_lli_invalid_err_intstat : RO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch4_shadowreg_or_lli_invalid_err_intstat:1; - /** ch4_slvif_multiblktype_err_intstat : RO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch4_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch4_slvif_dec_err_intstat : RO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch4_slvif_dec_err_intstat:1; - /** ch4_slvif_wr2ro_err_intstat : RO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch4_slvif_wr2ro_err_intstat:1; - /** ch4_slvif_rd2rwo_err_intstat : RO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch4_slvif_rd2rwo_err_intstat:1; - /** ch4_slvif_wronchen_err_intstat : RO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch4_slvif_wronchen_err_intstat:1; - /** ch4_slvif_shadowreg_wron_valid_err_intstat : RO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch4_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch4_slvif_wronhold_err_intstat : RO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch4_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch4_slvif_wrparity_err_intstat : RO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch4_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch4_ch_lock_cleared_intstat : RO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch4_ch_lock_cleared_intstat:1; - /** ch4_ch_src_suspended_intstat : RO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch4_ch_src_suspended_intstat:1; - /** ch4_ch_suspended_intstat : RO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch4_ch_suspended_intstat:1; - /** ch4_ch_disabled_intstat : RO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch4_ch_disabled_intstat:1; - /** ch4_ch_aborted_intstat : RO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch4_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch4_intstatus0_reg_t; - -/** Type of ch4_intstatus1 register - * NA - */ -typedef union { - struct { - /** ch4_ecc_prot_chmem_correrr_intstat : RO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_ecc_prot_chmem_correrr_intstat:1; - /** ch4_ecc_prot_chmem_uncorrerr_intstat : RO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch4_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch4_ecc_prot_uidmem_correrr_intstat : RO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch4_ecc_prot_uidmem_correrr_intstat:1; - /** ch4_ecc_prot_uidmem_uncorrerr_intstat : RO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch4_intstatus1_reg_t; - -/** Type of ch4_intsignal_enable0 register - * NA - */ -typedef union { - struct { - /** ch4_enable_block_tfr_done_intsignal : R/W; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch4_enable_block_tfr_done_intsignal:1; - /** ch4_enable_dma_tfr_done_intsignal : R/W; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch4_enable_dma_tfr_done_intsignal:1; - uint32_t reserved_2:1; - /** ch4_enable_src_transcomp_intsignal : R/W; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch4_enable_src_transcomp_intsignal:1; - /** ch4_enable_dst_transcomp_intsignal : R/W; bitpos: [4]; default: 1; - * NA - */ - uint32_t ch4_enable_dst_transcomp_intsignal:1; - /** ch4_enable_src_dec_err_intsignal : R/W; bitpos: [5]; default: 1; - * NA - */ - uint32_t ch4_enable_src_dec_err_intsignal:1; - /** ch4_enable_dst_dec_err_intsignal : R/W; bitpos: [6]; default: 1; - * NA - */ - uint32_t ch4_enable_dst_dec_err_intsignal:1; - /** ch4_enable_src_slv_err_intsignal : R/W; bitpos: [7]; default: 1; - * NA - */ - uint32_t ch4_enable_src_slv_err_intsignal:1; - /** ch4_enable_dst_slv_err_intsignal : R/W; bitpos: [8]; default: 1; - * NA - */ - uint32_t ch4_enable_dst_slv_err_intsignal:1; - /** ch4_enable_lli_rd_dec_err_intsignal : R/W; bitpos: [9]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_rd_dec_err_intsignal:1; - /** ch4_enable_lli_wr_dec_err_intsignal : R/W; bitpos: [10]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_wr_dec_err_intsignal:1; - /** ch4_enable_lli_rd_slv_err_intsignal : R/W; bitpos: [11]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_rd_slv_err_intsignal:1; - /** ch4_enable_lli_wr_slv_err_intsignal : R/W; bitpos: [12]; default: 1; - * NA - */ - uint32_t ch4_enable_lli_wr_slv_err_intsignal:1; - /** ch4_enable_shadowreg_or_lli_invalid_err_intsignal : R/W; bitpos: [13]; default: 1; - * NA - */ - uint32_t ch4_enable_shadowreg_or_lli_invalid_err_intsignal:1; - /** ch4_enable_slvif_multiblktype_err_intsignal : R/W; bitpos: [14]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_multiblktype_err_intsignal:1; - uint32_t reserved_15:1; - /** ch4_enable_slvif_dec_err_intsignal : R/W; bitpos: [16]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_dec_err_intsignal:1; - /** ch4_enable_slvif_wr2ro_err_intsignal : R/W; bitpos: [17]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wr2ro_err_intsignal:1; - /** ch4_enable_slvif_rd2rwo_err_intsignal : R/W; bitpos: [18]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_rd2rwo_err_intsignal:1; - /** ch4_enable_slvif_wronchen_err_intsignal : R/W; bitpos: [19]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wronchen_err_intsignal:1; - /** ch4_enable_slvif_shadowreg_wron_valid_err_intsignal : R/W; bitpos: [20]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_shadowreg_wron_valid_err_intsignal:1; - /** ch4_enable_slvif_wronhold_err_intsignal : R/W; bitpos: [21]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wronhold_err_intsignal:1; - uint32_t reserved_22:3; - /** ch4_enable_slvif_wrparity_err_intsignal : RO; bitpos: [25]; default: 1; - * NA - */ - uint32_t ch4_enable_slvif_wrparity_err_intsignal:1; - uint32_t reserved_26:1; - /** ch4_enable_ch_lock_cleared_intsignal : R/W; bitpos: [27]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_lock_cleared_intsignal:1; - /** ch4_enable_ch_src_suspended_intsignal : R/W; bitpos: [28]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_src_suspended_intsignal:1; - /** ch4_enable_ch_suspended_intsignal : R/W; bitpos: [29]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_suspended_intsignal:1; - /** ch4_enable_ch_disabled_intsignal : R/W; bitpos: [30]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_disabled_intsignal:1; - /** ch4_enable_ch_aborted_intsignal : R/W; bitpos: [31]; default: 1; - * NA - */ - uint32_t ch4_enable_ch_aborted_intsignal:1; - }; - uint32_t val; -} dmac_ch4_intsignal_enable0_reg_t; - -/** Type of ch4_intsignal_enable1 register - * NA - */ -typedef union { - struct { - /** ch4_enable_ecc_prot_chmem_correrr_intsignal : RO; bitpos: [0]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_chmem_correrr_intsignal:1; - /** ch4_enable_ecc_prot_chmem_uncorrerr_intsignal : RO; bitpos: [1]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_chmem_uncorrerr_intsignal:1; - /** ch4_enable_ecc_prot_uidmem_correrr_intsignal : RO; bitpos: [2]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_uidmem_correrr_intsignal:1; - /** ch4_enable_ecc_prot_uidmem_uncorrerr_intsignal : RO; bitpos: [3]; default: 1; - * NA - */ - uint32_t ch4_enable_ecc_prot_uidmem_uncorrerr_intsignal:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch4_intsignal_enable1_reg_t; - -/** Type of ch4_intclear0 register - * NA - */ -typedef union { - struct { - /** ch4_clear_block_tfr_done_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_clear_block_tfr_done_intstat:1; - /** ch4_clear_dma_tfr_done_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch4_clear_dma_tfr_done_intstat:1; - uint32_t reserved_2:1; - /** ch4_clear_src_transcomp_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_clear_src_transcomp_intstat:1; - /** ch4_clear_dst_transcomp_intstat : WO; bitpos: [4]; default: 0; - * NA - */ - uint32_t ch4_clear_dst_transcomp_intstat:1; - /** ch4_clear_src_dec_err_intstat : WO; bitpos: [5]; default: 0; - * NA - */ - uint32_t ch4_clear_src_dec_err_intstat:1; - /** ch4_clear_dst_dec_err_intstat : WO; bitpos: [6]; default: 0; - * NA - */ - uint32_t ch4_clear_dst_dec_err_intstat:1; - /** ch4_clear_src_slv_err_intstat : WO; bitpos: [7]; default: 0; - * NA - */ - uint32_t ch4_clear_src_slv_err_intstat:1; - /** ch4_clear_dst_slv_err_intstat : WO; bitpos: [8]; default: 0; - * NA - */ - uint32_t ch4_clear_dst_slv_err_intstat:1; - /** ch4_clear_lli_rd_dec_err_intstat : WO; bitpos: [9]; default: 0; - * NA - */ - uint32_t ch4_clear_lli_rd_dec_err_intstat:1; - /** ch4_clear_lli_wr_dec_err_intstat : WO; bitpos: [10]; default: 0; - * NA - */ - uint32_t ch4_clear_lli_wr_dec_err_intstat:1; - /** ch4_clear_lli_rd_slv_err_intstat : WO; bitpos: [11]; default: 0; - * NA - */ - uint32_t ch4_clear_lli_rd_slv_err_intstat:1; - /** ch4_clear_lli_wr_slv_err_intstat : WO; bitpos: [12]; default: 0; - * NA - */ - uint32_t ch4_clear_lli_wr_slv_err_intstat:1; - /** ch4_clear_shadowreg_or_lli_invalid_err_intstat : WO; bitpos: [13]; default: 0; - * NA - */ - uint32_t ch4_clear_shadowreg_or_lli_invalid_err_intstat:1; - /** ch4_clear_slvif_multiblktype_err_intstat : WO; bitpos: [14]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_multiblktype_err_intstat:1; - uint32_t reserved_15:1; - /** ch4_clear_slvif_dec_err_intstat : WO; bitpos: [16]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_dec_err_intstat:1; - /** ch4_clear_slvif_wr2ro_err_intstat : WO; bitpos: [17]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_wr2ro_err_intstat:1; - /** ch4_clear_slvif_rd2rwo_err_intstat : WO; bitpos: [18]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_rd2rwo_err_intstat:1; - /** ch4_clear_slvif_wronchen_err_intstat : WO; bitpos: [19]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_wronchen_err_intstat:1; - /** ch4_clear_slvif_shadowreg_wron_valid_err_intstat : WO; bitpos: [20]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_shadowreg_wron_valid_err_intstat:1; - /** ch4_clear_slvif_wronhold_err_intstat : WO; bitpos: [21]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_wronhold_err_intstat:1; - uint32_t reserved_22:3; - /** ch4_clear_slvif_wrparity_err_intstat : WO; bitpos: [25]; default: 0; - * NA - */ - uint32_t ch4_clear_slvif_wrparity_err_intstat:1; - uint32_t reserved_26:1; - /** ch4_clear_ch_lock_cleared_intstat : WO; bitpos: [27]; default: 0; - * NA - */ - uint32_t ch4_clear_ch_lock_cleared_intstat:1; - /** ch4_clear_ch_src_suspended_intstat : WO; bitpos: [28]; default: 0; - * NA - */ - uint32_t ch4_clear_ch_src_suspended_intstat:1; - /** ch4_clear_ch_suspended_intstat : WO; bitpos: [29]; default: 0; - * NA - */ - uint32_t ch4_clear_ch_suspended_intstat:1; - /** ch4_clear_ch_disabled_intstat : WO; bitpos: [30]; default: 0; - * NA - */ - uint32_t ch4_clear_ch_disabled_intstat:1; - /** ch4_clear_ch_aborted_intstat : WO; bitpos: [31]; default: 0; - * NA - */ - uint32_t ch4_clear_ch_aborted_intstat:1; - }; - uint32_t val; -} dmac_ch4_intclear0_reg_t; - -/** Type of ch4_intclear1 register - * NA - */ -typedef union { - struct { - /** ch4_clear_ecc_prot_chmem_correrr_intstat : WO; bitpos: [0]; default: 0; - * NA - */ - uint32_t ch4_clear_ecc_prot_chmem_correrr_intstat:1; - /** ch4_clear_ecc_prot_chmem_uncorrerr_intstat : WO; bitpos: [1]; default: 0; - * NA - */ - uint32_t ch4_clear_ecc_prot_chmem_uncorrerr_intstat:1; - /** ch4_clear_ecc_prot_uidmem_correrr_intstat : WO; bitpos: [2]; default: 0; - * NA - */ - uint32_t ch4_clear_ecc_prot_uidmem_correrr_intstat:1; - /** ch4_clear_ecc_prot_uidmem_uncorrerr_intstat : WO; bitpos: [3]; default: 0; - * NA - */ - uint32_t ch4_clear_ecc_prot_uidmem_uncorrerr_intstat:1; - uint32_t reserved_4:28; - }; - uint32_t val; -} dmac_ch4_intclear1_reg_t; - - -/** Group: Status Registers */ -/** Type of ch1_status0 register - * NA - */ -typedef union { - struct { - /** ch1_cmpltd_blk_tfr_size : RO; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch1_cmpltd_blk_tfr_size:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch1_status0_reg_t; - -/** Type of ch1_status1 register - * NA - */ -typedef union { - struct { - /** ch1_data_left_in_fifo : RO; bitpos: [14:0]; default: 0; - * NA - */ - uint32_t ch1_data_left_in_fifo:15; - uint32_t reserved_15:17; - }; - uint32_t val; -} dmac_ch1_status1_reg_t; - -/** Type of ch1_sstat0 register - * NA - */ -typedef union { - struct { - /** ch1_sstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_sstat:32; - }; - uint32_t val; -} dmac_ch1_sstat0_reg_t; - -/** Type of ch1_dstat0 register - * NA - */ -typedef union { - struct { - /** ch1_dstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_dstat:32; - }; - uint32_t val; -} dmac_ch1_dstat0_reg_t; - -/** Type of ch1_sstatar0 register - * NA - */ -typedef union { - struct { - /** ch1_sstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_sstatar0:32; - }; - uint32_t val; -} dmac_ch1_sstatar0_reg_t; - -/** Type of ch1_sstatar1 register - * NA - */ -typedef union { - struct { - /** ch1_sstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_sstatar1:32; - }; - uint32_t val; -} dmac_ch1_sstatar1_reg_t; - -/** Type of ch1_dstatar0 register - * NA - */ -typedef union { - struct { - /** ch1_dstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_dstatar0:32; - }; - uint32_t val; -} dmac_ch1_dstatar0_reg_t; - -/** Type of ch1_dstatar1 register - * NA - */ -typedef union { - struct { - /** ch1_dstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch1_dstatar1:32; - }; - uint32_t val; -} dmac_ch1_dstatar1_reg_t; - -/** Type of ch2_status0 register - * NA - */ -typedef union { - struct { - /** ch2_cmpltd_blk_tfr_size : RO; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch2_cmpltd_blk_tfr_size:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch2_status0_reg_t; - -/** Type of ch2_status1 register - * NA - */ -typedef union { - struct { - /** ch2_data_left_in_fifo : RO; bitpos: [14:0]; default: 0; - * NA - */ - uint32_t ch2_data_left_in_fifo:15; - uint32_t reserved_15:17; - }; - uint32_t val; -} dmac_ch2_status1_reg_t; - -/** Type of ch2_sstat0 register - * NA - */ -typedef union { - struct { - /** ch2_sstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_sstat:32; - }; - uint32_t val; -} dmac_ch2_sstat0_reg_t; - -/** Type of ch2_dstat0 register - * NA - */ -typedef union { - struct { - /** ch2_dstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_dstat:32; - }; - uint32_t val; -} dmac_ch2_dstat0_reg_t; - -/** Type of ch2_sstatar0 register - * NA - */ -typedef union { - struct { - /** ch2_sstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_sstatar0:32; - }; - uint32_t val; -} dmac_ch2_sstatar0_reg_t; - -/** Type of ch2_sstatar1 register - * NA - */ -typedef union { - struct { - /** ch2_sstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_sstatar1:32; - }; - uint32_t val; -} dmac_ch2_sstatar1_reg_t; - -/** Type of ch2_dstatar0 register - * NA - */ -typedef union { - struct { - /** ch2_dstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_dstatar0:32; - }; - uint32_t val; -} dmac_ch2_dstatar0_reg_t; - -/** Type of ch2_dstatar1 register - * NA - */ -typedef union { - struct { - /** ch2_dstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch2_dstatar1:32; - }; - uint32_t val; -} dmac_ch2_dstatar1_reg_t; - -/** Type of ch3_status0 register - * NA - */ -typedef union { - struct { - /** ch3_cmpltd_blk_tfr_size : RO; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch3_cmpltd_blk_tfr_size:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch3_status0_reg_t; - -/** Type of ch3_status1 register - * NA - */ -typedef union { - struct { - /** ch3_data_left_in_fifo : RO; bitpos: [14:0]; default: 0; - * NA - */ - uint32_t ch3_data_left_in_fifo:15; - uint32_t reserved_15:17; - }; - uint32_t val; -} dmac_ch3_status1_reg_t; - -/** Type of ch3_sstat0 register - * NA - */ -typedef union { - struct { - /** ch3_sstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_sstat:32; - }; - uint32_t val; -} dmac_ch3_sstat0_reg_t; - -/** Type of ch3_dstat0 register - * NA - */ -typedef union { - struct { - /** ch3_dstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_dstat:32; - }; - uint32_t val; -} dmac_ch3_dstat0_reg_t; - -/** Type of ch3_sstatar0 register - * NA - */ -typedef union { - struct { - /** ch3_sstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_sstatar0:32; - }; - uint32_t val; -} dmac_ch3_sstatar0_reg_t; - -/** Type of ch3_sstatar1 register - * NA - */ -typedef union { - struct { - /** ch3_sstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_sstatar1:32; - }; - uint32_t val; -} dmac_ch3_sstatar1_reg_t; - -/** Type of ch3_dstatar0 register - * NA - */ -typedef union { - struct { - /** ch3_dstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_dstatar0:32; - }; - uint32_t val; -} dmac_ch3_dstatar0_reg_t; - -/** Type of ch3_dstatar1 register - * NA - */ -typedef union { - struct { - /** ch3_dstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch3_dstatar1:32; - }; - uint32_t val; -} dmac_ch3_dstatar1_reg_t; - -/** Type of ch4_status0 register - * NA - */ -typedef union { - struct { - /** ch4_cmpltd_blk_tfr_size : RO; bitpos: [21:0]; default: 0; - * NA - */ - uint32_t ch4_cmpltd_blk_tfr_size:22; - uint32_t reserved_22:10; - }; - uint32_t val; -} dmac_ch4_status0_reg_t; - -/** Type of ch4_status1 register - * NA - */ -typedef union { - struct { - /** ch4_data_left_in_fifo : RO; bitpos: [14:0]; default: 0; - * NA - */ - uint32_t ch4_data_left_in_fifo:15; - uint32_t reserved_15:17; - }; - uint32_t val; -} dmac_ch4_status1_reg_t; - -/** Type of ch4_sstat0 register - * NA - */ -typedef union { - struct { - /** ch4_sstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_sstat:32; - }; - uint32_t val; -} dmac_ch4_sstat0_reg_t; - -/** Type of ch4_dstat0 register - * NA - */ -typedef union { - struct { - /** ch4_dstat : RO; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_dstat:32; - }; - uint32_t val; -} dmac_ch4_dstat0_reg_t; - -/** Type of ch4_sstatar0 register - * NA - */ -typedef union { - struct { - /** ch4_sstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_sstatar0:32; - }; - uint32_t val; -} dmac_ch4_sstatar0_reg_t; - -/** Type of ch4_sstatar1 register - * NA - */ -typedef union { - struct { - /** ch4_sstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_sstatar1:32; - }; - uint32_t val; -} dmac_ch4_sstatar1_reg_t; - -/** Type of ch4_dstatar0 register - * NA - */ -typedef union { - struct { - /** ch4_dstatar0 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_dstatar0:32; - }; - uint32_t val; -} dmac_ch4_dstatar0_reg_t; - -/** Type of ch4_dstatar1 register - * NA - */ -typedef union { - struct { - /** ch4_dstatar1 : R/W; bitpos: [31:0]; default: 0; - * NA - */ - uint32_t ch4_dstatar1:32; - }; - uint32_t val; -} dmac_ch4_dstatar1_reg_t; - - -typedef struct { - volatile dmac_id0_reg_t id0; - uint32_t reserved_004; - volatile dmac_compver0_reg_t compver0; - uint32_t reserved_00c; - volatile dmac_cfg0_reg_t cfg0; - uint32_t reserved_014; - volatile dmac_chen0_reg_t chen0; - volatile dmac_chen1_reg_t chen1; - uint32_t reserved_020[4]; - volatile dmac_intstatus0_reg_t intstatus0; - uint32_t reserved_034; - volatile dmac_commonreg_intclear0_reg_t commonreg_intclear0; - uint32_t reserved_03c; - volatile dmac_commonreg_intstatus_enable0_reg_t commonreg_intstatus_enable0; - uint32_t reserved_044; - volatile dmac_commonreg_intsignal_enable0_reg_t commonreg_intsignal_enable0; - uint32_t reserved_04c; - volatile dmac_commonreg_intstatus0_reg_t commonreg_intstatus0; - uint32_t reserved_054; - volatile dmac_reset0_reg_t reset0; - uint32_t reserved_05c; - volatile dmac_lowpower_cfg0_reg_t lowpower_cfg0; - volatile dmac_lowpower_cfg1_reg_t lowpower_cfg1; - uint32_t reserved_068[38]; - volatile dmac_ch1_sar0_reg_t ch1_sar0; - volatile dmac_ch1_sar1_reg_t ch1_sar1; - volatile dmac_ch1_dar0_reg_t ch1_dar0; - volatile dmac_ch1_dar1_reg_t ch1_dar1; - volatile dmac_ch1_block_ts0_reg_t ch1_block_ts0; - uint32_t reserved_114; - volatile dmac_ch1_ctl0_reg_t ch1_ctl0; - volatile dmac_ch1_ctl1_reg_t ch1_ctl1; - volatile dmac_ch1_cfg0_reg_t ch1_cfg0; - volatile dmac_ch1_cfg1_reg_t ch1_cfg1; - volatile dmac_ch1_llp0_reg_t ch1_llp0; - volatile dmac_ch1_llp1_reg_t ch1_llp1; - volatile dmac_ch1_status0_reg_t ch1_status0; - volatile dmac_ch1_status1_reg_t ch1_status1; - volatile dmac_ch1_swhssrc0_reg_t ch1_swhssrc0; - uint32_t reserved_13c; - volatile dmac_ch1_swhsdst0_reg_t ch1_swhsdst0; - uint32_t reserved_144; - volatile dmac_ch1_blk_tfr_resumereq0_reg_t ch1_blk_tfr_resumereq0; - uint32_t reserved_14c; - volatile dmac_ch1_axi_id0_reg_t ch1_axi_id0; - uint32_t reserved_154; - volatile dmac_ch1_axi_qos0_reg_t ch1_axi_qos0; - uint32_t reserved_15c; - volatile dmac_ch1_sstat0_reg_t ch1_sstat0; - uint32_t reserved_164; - volatile dmac_ch1_dstat0_reg_t ch1_dstat0; - uint32_t reserved_16c; - volatile dmac_ch1_sstatar0_reg_t ch1_sstatar0; - volatile dmac_ch1_sstatar1_reg_t ch1_sstatar1; - volatile dmac_ch1_dstatar0_reg_t ch1_dstatar0; - volatile dmac_ch1_dstatar1_reg_t ch1_dstatar1; - volatile dmac_ch1_intstatus_enable0_reg_t ch1_intstatus_enable0; - volatile dmac_ch1_intstatus_enable1_reg_t ch1_intstatus_enable1; - volatile dmac_ch1_intstatus0_reg_t ch1_intstatus0; - volatile dmac_ch1_intstatus1_reg_t ch1_intstatus1; - volatile dmac_ch1_intsignal_enable0_reg_t ch1_intsignal_enable0; - volatile dmac_ch1_intsignal_enable1_reg_t ch1_intsignal_enable1; - volatile dmac_ch1_intclear0_reg_t ch1_intclear0; - volatile dmac_ch1_intclear1_reg_t ch1_intclear1; - uint32_t reserved_1a0[24]; - volatile dmac_ch2_sar0_reg_t ch2_sar0; - volatile dmac_ch2_sar1_reg_t ch2_sar1; - volatile dmac_ch2_dar0_reg_t ch2_dar0; - volatile dmac_ch2_dar1_reg_t ch2_dar1; - volatile dmac_ch2_block_ts0_reg_t ch2_block_ts0; - uint32_t reserved_214; - volatile dmac_ch2_ctl0_reg_t ch2_ctl0; - volatile dmac_ch2_ctl1_reg_t ch2_ctl1; - volatile dmac_ch2_cfg0_reg_t ch2_cfg0; - volatile dmac_ch2_cfg1_reg_t ch2_cfg1; - volatile dmac_ch2_llp0_reg_t ch2_llp0; - volatile dmac_ch2_llp1_reg_t ch2_llp1; - volatile dmac_ch2_status0_reg_t ch2_status0; - volatile dmac_ch2_status1_reg_t ch2_status1; - volatile dmac_ch2_swhssrc0_reg_t ch2_swhssrc0; - uint32_t reserved_23c; - volatile dmac_ch2_swhsdst0_reg_t ch2_swhsdst0; - uint32_t reserved_244; - volatile dmac_ch2_blk_tfr_resumereq0_reg_t ch2_blk_tfr_resumereq0; - uint32_t reserved_24c; - volatile dmac_ch2_axi_id0_reg_t ch2_axi_id0; - uint32_t reserved_254; - volatile dmac_ch2_axi_qos0_reg_t ch2_axi_qos0; - uint32_t reserved_25c; - volatile dmac_ch2_sstat0_reg_t ch2_sstat0; - uint32_t reserved_264; - volatile dmac_ch2_dstat0_reg_t ch2_dstat0; - uint32_t reserved_26c; - volatile dmac_ch2_sstatar0_reg_t ch2_sstatar0; - volatile dmac_ch2_sstatar1_reg_t ch2_sstatar1; - volatile dmac_ch2_dstatar0_reg_t ch2_dstatar0; - volatile dmac_ch2_dstatar1_reg_t ch2_dstatar1; - volatile dmac_ch2_intstatus_enable0_reg_t ch2_intstatus_enable0; - volatile dmac_ch2_intstatus_enable1_reg_t ch2_intstatus_enable1; - volatile dmac_ch2_intstatus0_reg_t ch2_intstatus0; - volatile dmac_ch2_intstatus1_reg_t ch2_intstatus1; - volatile dmac_ch2_intsignal_enable0_reg_t ch2_intsignal_enable0; - volatile dmac_ch2_intsignal_enable1_reg_t ch2_intsignal_enable1; - volatile dmac_ch2_intclear0_reg_t ch2_intclear0; - volatile dmac_ch2_intclear1_reg_t ch2_intclear1; - uint32_t reserved_2a0[24]; - volatile dmac_ch3_sar0_reg_t ch3_sar0; - volatile dmac_ch3_sar1_reg_t ch3_sar1; - volatile dmac_ch3_dar0_reg_t ch3_dar0; - volatile dmac_ch3_dar1_reg_t ch3_dar1; - volatile dmac_ch3_block_ts0_reg_t ch3_block_ts0; - uint32_t reserved_314; - volatile dmac_ch3_ctl0_reg_t ch3_ctl0; - volatile dmac_ch3_ctl1_reg_t ch3_ctl1; - volatile dmac_ch3_cfg0_reg_t ch3_cfg0; - volatile dmac_ch3_cfg1_reg_t ch3_cfg1; - volatile dmac_ch3_llp0_reg_t ch3_llp0; - volatile dmac_ch3_llp1_reg_t ch3_llp1; - volatile dmac_ch3_status0_reg_t ch3_status0; - volatile dmac_ch3_status1_reg_t ch3_status1; - volatile dmac_ch3_swhssrc0_reg_t ch3_swhssrc0; - uint32_t reserved_33c; - volatile dmac_ch3_swhsdst0_reg_t ch3_swhsdst0; - uint32_t reserved_344; - volatile dmac_ch3_blk_tfr_resumereq0_reg_t ch3_blk_tfr_resumereq0; - uint32_t reserved_34c; - volatile dmac_ch3_axi_id0_reg_t ch3_axi_id0; - uint32_t reserved_354; - volatile dmac_ch3_axi_qos0_reg_t ch3_axi_qos0; - uint32_t reserved_35c; - volatile dmac_ch3_sstat0_reg_t ch3_sstat0; - uint32_t reserved_364; - volatile dmac_ch3_dstat0_reg_t ch3_dstat0; - uint32_t reserved_36c; - volatile dmac_ch3_sstatar0_reg_t ch3_sstatar0; - volatile dmac_ch3_sstatar1_reg_t ch3_sstatar1; - volatile dmac_ch3_dstatar0_reg_t ch3_dstatar0; - volatile dmac_ch3_dstatar1_reg_t ch3_dstatar1; - volatile dmac_ch3_intstatus_enable0_reg_t ch3_intstatus_enable0; - volatile dmac_ch3_intstatus_enable1_reg_t ch3_intstatus_enable1; - volatile dmac_ch3_intstatus0_reg_t ch3_intstatus0; - volatile dmac_ch3_intstatus1_reg_t ch3_intstatus1; - volatile dmac_ch3_intsignal_enable0_reg_t ch3_intsignal_enable0; - volatile dmac_ch3_intsignal_enable1_reg_t ch3_intsignal_enable1; - volatile dmac_ch3_intclear0_reg_t ch3_intclear0; - volatile dmac_ch3_intclear1_reg_t ch3_intclear1; - uint32_t reserved_3a0[24]; - volatile dmac_ch4_sar0_reg_t ch4_sar0; - volatile dmac_ch4_sar1_reg_t ch4_sar1; - volatile dmac_ch4_dar0_reg_t ch4_dar0; - volatile dmac_ch4_dar1_reg_t ch4_dar1; - volatile dmac_ch4_block_ts0_reg_t ch4_block_ts0; - uint32_t reserved_414; - volatile dmac_ch4_ctl0_reg_t ch4_ctl0; - volatile dmac_ch4_ctl1_reg_t ch4_ctl1; - volatile dmac_ch4_cfg0_reg_t ch4_cfg0; - volatile dmac_ch4_cfg1_reg_t ch4_cfg1; - volatile dmac_ch4_llp0_reg_t ch4_llp0; - volatile dmac_ch4_llp1_reg_t ch4_llp1; - volatile dmac_ch4_status0_reg_t ch4_status0; - volatile dmac_ch4_status1_reg_t ch4_status1; - volatile dmac_ch4_swhssrc0_reg_t ch4_swhssrc0; - uint32_t reserved_43c; - volatile dmac_ch4_swhsdst0_reg_t ch4_swhsdst0; - uint32_t reserved_444; - volatile dmac_ch4_blk_tfr_resumereq0_reg_t ch4_blk_tfr_resumereq0; - uint32_t reserved_44c; - volatile dmac_ch4_axi_id0_reg_t ch4_axi_id0; - uint32_t reserved_454; - volatile dmac_ch4_axi_qos0_reg_t ch4_axi_qos0; - uint32_t reserved_45c; - volatile dmac_ch4_sstat0_reg_t ch4_sstat0; - uint32_t reserved_464; - volatile dmac_ch4_dstat0_reg_t ch4_dstat0; - uint32_t reserved_46c; - volatile dmac_ch4_sstatar0_reg_t ch4_sstatar0; - volatile dmac_ch4_sstatar1_reg_t ch4_sstatar1; - volatile dmac_ch4_dstatar0_reg_t ch4_dstatar0; - volatile dmac_ch4_dstatar1_reg_t ch4_dstatar1; - volatile dmac_ch4_intstatus_enable0_reg_t ch4_intstatus_enable0; - volatile dmac_ch4_intstatus_enable1_reg_t ch4_intstatus_enable1; - volatile dmac_ch4_intstatus0_reg_t ch4_intstatus0; - volatile dmac_ch4_intstatus1_reg_t ch4_intstatus1; - volatile dmac_ch4_intsignal_enable0_reg_t ch4_intsignal_enable0; - volatile dmac_ch4_intsignal_enable1_reg_t ch4_intsignal_enable1; - volatile dmac_ch4_intclear0_reg_t ch4_intclear0; - volatile dmac_ch4_intclear1_reg_t ch4_intclear1; -} dmac_dev_t; - - -#ifndef __cplusplus -_Static_assert(sizeof(dmac_dev_t) == 0x4a0, "Invalid size of dmac_dev_t structure"); -#endif - -#ifdef __cplusplus -} -#endif diff --git a/components/soc/esp32p4/include/soc/interrupts.h b/components/soc/esp32p4/include/soc/interrupts.h index fdce7edc2170..881aee45195e 100644 --- a/components/soc/esp32p4/include/soc/interrupts.h +++ b/components/soc/esp32p4/include/soc/interrupts.h @@ -39,7 +39,7 @@ typedef enum { ETS_SYS_ICM_INTR_SOURCE, ETS_USB_DEVICE_INTR_SOURCE, ETS_SDIO_HOST_INTR_SOURCE, - ETS_GDMA_INTR_SOURCE, + ETS_DW_GDMA_INTR_SOURCE, ETS_SPI2_INTR_SOURCE, ETS_SPI3_INTR_SOURCE, ETS_I2S0_INTR_SOURCE, diff --git a/components/soc/esp32p4/interrupts.c b/components/soc/esp32p4/interrupts.c index e6ceba0453f2..be8694e6b947 100644 --- a/components/soc/esp32p4/interrupts.c +++ b/components/soc/esp32p4/interrupts.c @@ -31,7 +31,7 @@ const char *const esp_isr_names[] = { [ETS_SYS_ICM_INTR_SOURCE] = "SYS_ICM", [ETS_USB_DEVICE_INTR_SOURCE] = "USB_DEVICE", [ETS_SDIO_HOST_INTR_SOURCE] = "SDIO_HOST", - [ETS_GDMA_INTR_SOURCE] = "GDMA", + [ETS_DW_GDMA_INTR_SOURCE] = "DW_GDMA", [ETS_SPI2_INTR_SOURCE] = "SPI2", [ETS_SPI3_INTR_SOURCE] = "SPI3", [ETS_I2S0_INTR_SOURCE] = "I2S0", diff --git a/components/soc/esp32p4/ld/esp32p4.peripherals.ld b/components/soc/esp32p4/ld/esp32p4.peripherals.ld index f4223a2f01ce..40e8213dfda5 100644 --- a/components/soc/esp32p4/ld/esp32p4.peripherals.ld +++ b/components/soc/esp32p4/ld/esp32p4.peripherals.ld @@ -90,7 +90,7 @@ PROVIDE ( MIPI_DSI_HOST = 0x500A0000 ); PROVIDE ( MIPI_CSI_MEM = 0x50104000 ); PROVIDE ( MIPI_DSI_MEM = 0x50105000 ); PROVIDE ( ISP = 0x500A1000 ); -PROVIDE ( GDMA = 0x50081000 ); +PROVIDE ( DW_GDMA = 0x50081000 ); PROVIDE ( I3C_MST = 0x500DA000 ); PROVIDE ( I3C_MST_MEM = 0x500DA000 ); PROVIDE ( I3C_SLV = 0x500DB000 ); From b221f87e0099a25104979537db2fa6fd7730a38c Mon Sep 17 00:00:00 2001 From: zlq Date: Wed, 6 Sep 2023 16:09:26 +0800 Subject: [PATCH 104/142] feat(volt): chip auto adjust volt for esp32c6 & esp32h2 --- .../include/esp_private/esp_pmu.h | 26 + .../include/esp_private/esp_regdma.h | 1 + .../include/esp_private/sleep_retention.h | 1 + components/esp_hw_support/linker.lf | 4 + .../port/esp32c6/CMakeLists.txt | 1 + .../esp_hw_support/port/esp32c6/pmu_init.c | 11 +- .../esp_hw_support/port/esp32c6/pmu_param.c | 10 +- .../port/esp32c6/pmu_pvt_pump.c | 85 ++ .../esp_hw_support/port/esp32c6/pmu_sleep.c | 1 + .../esp_hw_support/port/esp32c6/rtc_clk.c | 13 + .../port/esp32c6/rtc_clk_init.c | 6 + .../port/esp32h2/CMakeLists.txt | 1 + .../esp_hw_support/port/esp32h2/pmu_init.c | 12 +- .../esp_hw_support/port/esp32h2/pmu_param.c | 6 +- .../port/esp32h2/pmu_pvt_pump.c | 86 ++ .../esp_hw_support/port/esp32h2/pmu_sleep.c | 2 + .../esp_hw_support/port/esp32h2/rtc_clk.c | 17 + .../port/esp32h2/rtc_clk_init.c | 6 + .../esp_hw_support/sleep_system_peripheral.c | 53 +- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c6/include/soc/pvt_reg.h | 876 +++++++++++++++++ components/soc/esp32c6/include/soc/rtc.h | 20 + components/soc/esp32c6/include/soc/soc_caps.h | 1 + .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32h2/include/soc/pvt_reg.h | 881 ++++++++++++++++++ components/soc/esp32h2/include/soc/rtc.h | 22 +- components/soc/esp32h2/include/soc/soc.h | 2 +- components/soc/esp32h2/include/soc/soc_caps.h | 1 + 28 files changed, 2132 insertions(+), 21 deletions(-) create mode 100644 components/esp_hw_support/port/esp32c6/pmu_pvt_pump.c create mode 100644 components/esp_hw_support/port/esp32h2/pmu_pvt_pump.c create mode 100644 components/soc/esp32c6/include/soc/pvt_reg.h create mode 100644 components/soc/esp32h2/include/soc/pvt_reg.h diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 187784fae640..db743763aebc 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -249,6 +249,32 @@ bool pmu_sleep_finish(void); */ void pmu_init(void); +/** + * @brief Initialize PVT related parameters + */ +void pvt_auto_dbias_init(void); + +/** + * @brief Enable or disable PVT functions + */ +void pvt_func_enable(bool enable); + +/** + * @brief Initialize charge pump related parameters + */ +void charge_pump_init(void); + +/** + * @brief Enable or disable charge pump functions + */ +void charge_pump_enable(bool enable); + +/** + * @brief Get Hp_dbias from register + */ +uint32_t get_pvt_dbias(void); + + /** * @brief Enable or disable system clock in PMU HP sleep state * diff --git a/components/esp_hw_support/include/esp_private/esp_regdma.h b/components/esp_hw_support/include/esp_private/esp_regdma.h index ebf7ed423caa..7ca796bc1631 100644 --- a/components/esp_hw_support/include/esp_private/esp_regdma.h +++ b/components/esp_hw_support/include/esp_private/esp_regdma.h @@ -31,6 +31,7 @@ extern "C" { #define REGDMA_MODEMSYSCON_LINK(_pri) ((0x02 << 8) | _pri) #define REGDMA_MODEMLPCON_LINK(_pri) ((0x03 << 8) | _pri) +#define REGDMA_PVT_LINK(_pri) ((0x0c << 8) | _pri) #define REGDMA_INTMTX_LINK(_pri) ((0x0d << 8) | _pri) #define REGDMA_HPSYS_LINK(_pri) ((0x0e << 8) | _pri) #define REGDMA_TEEAPM_LINK(_pri) ((0x0f << 8) | _pri) diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_retention.h index e64a95a9c04f..08b69edb6d36 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -45,6 +45,7 @@ typedef enum sleep_retention_module_bitmap { SLEEP_RETENTION_MODULE_IOMUX = BIT(21), SLEEP_RETENTION_MODULE_SPIMEM = BIT(22), SLEEP_RETENTION_MODULE_SYSTIMER = BIT(23), + SLEEP_RETENTION_MODULE_PVT = BIT(24), SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1 } sleep_retention_module_bitmap_t; diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index f7b88173cbea..28d9c7698dc0 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -23,6 +23,10 @@ entries: rtc_time (noflash_text) if SOC_PMU_SUPPORTED = y: pmu_sleep (noflash) + if SOC_PMU_PVT_SUPPORTED = y: + pmu_pvt_pump: pvt_func_enable (noflash) + pmu_pvt_pump: charge_pump_enable (noflash) + pmu_pvt_pump: get_pvt_dbias (noflash) if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y: rtc_wdt (noflash_text) if PERIPH_CTRL_FUNC_IN_IRAM = y: diff --git a/components/esp_hw_support/port/esp32c6/CMakeLists.txt b/components/esp_hw_support/port/esp32c6/CMakeLists.txt index e82e407cb0e9..ee688dbc1414 100644 --- a/components/esp_hw_support/port/esp32c6/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c6/CMakeLists.txt @@ -6,6 +6,7 @@ set(srcs "rtc_clk_init.c" "rtc_time.c" "chip_info.c" "ocode_init.c" + "pmu_pvt_pump.c" ) if(NOT BOOTLOADER_BUILD) diff --git a/components/esp_hw_support/port/esp32c6/pmu_init.c b/components/esp_hw_support/port/esp32c6/pmu_init.c index 8c04486f02d3..d5ebf98c024f 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_init.c +++ b/components/esp_hw_support/port/esp32c6/pmu_init.c @@ -13,6 +13,7 @@ #include "soc/pmu_struct.h" #include "hal/pmu_hal.h" #include "pmu_param.h" +#include "esp_rom_sys.h" #include "esp_private/esp_pmu.h" #include "soc/regi2c_dig_reg.h" #include "regi2c_ctrl.h" @@ -195,8 +196,6 @@ void pmu_init(void) /* Peripheral reg i2c power up */ SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); @@ -204,4 +203,12 @@ void pmu_init(void) pmu_lp_system_init_default(PMU_instance()); pmu_power_domain_force_default(PMU_instance()); + + pvt_auto_dbias_init(); + charge_pump_init(); + + //HP dbias initialization + pvt_func_enable(1); + charge_pump_enable(1); + esp_rom_delay_us(1000); } diff --git a/components/esp_hw_support/port/esp32c6/pmu_param.c b/components/esp_hw_support/port/esp32c6/pmu_param.c index 6e0a8ea8cbc6..6c8a63af07e4 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_param.c +++ b/components/esp_hw_support/port/esp32c6/pmu_param.c @@ -211,7 +211,7 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .xpd = 1, \ .slp_mem_dbias = 0, \ .slp_logic_dbias = 0, \ - .dbias = 0x19 \ + .dbias = HP_CALI_DBIAS \ }, \ .regulator1 = { \ .drv_b = 0x0 \ @@ -231,7 +231,7 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .xpd = 1, \ .slp_mem_dbias = 0, \ .slp_logic_dbias = 0, \ - .dbias = 0x1a \ + .dbias = HP_CALI_DBIAS \ }, \ .regulator1 = { \ .drv_b = 0x0 \ @@ -294,7 +294,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ BIT(PMU_ICG_FUNC_ENA_SPI2) | \ BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) | \ + BIT(PMU_ICG_FUNC_ENA_PVT_MONITOR) \ ) \ } @@ -343,7 +344,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ BIT(PMU_ICG_FUNC_ENA_SPI2) | \ BIT(PMU_ICG_FUNC_ENA_UART0) | \ - BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) | \ + BIT(PMU_ICG_FUNC_ENA_PVT_MONITOR) \ ) \ } diff --git a/components/esp_hw_support/port/esp32c6/pmu_pvt_pump.c b/components/esp_hw_support/port/esp32c6/pmu_pvt_pump.c new file mode 100644 index 000000000000..344027b37bdb --- /dev/null +++ b/components/esp_hw_support/port/esp32c6/pmu_pvt_pump.c @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "soc/pvt_reg.h" +#include "soc/pmu_reg.h" +#include "soc/pcr_reg.h" +#include "pmu_param.h" +#include "esp_private/esp_pmu.h" +#include "soc/regi2c_dig_reg.h" +#include "regi2c_ctrl.h" +#include "soc/rtc.h" + +static __attribute__((unused)) const char *TAG = "pmu_pvt_pump"; + +void pvt_auto_dbias_init(void) +{ + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + /*config for dbias func*/ + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL0_SEL, PVT_CHANNEL0_SEL, PVT_DBIAS_CHANNEL0_SEL_S); + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL1_SEL, PVT_CHANNEL1_SEL, PVT_DBIAS_CHANNEL1_SEL_S); // Select monitor cell ,which used to monitor PVT situation + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL0_SEL_REG, PVT_DBIAS_CHANNEL0_CFG, PVT_CHANNEL0_CFG, PVT_DBIAS_CHANNEL0_CFG_S); + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL1_SEL_REG, PVT_DBIAS_CHANNEL1_CFG, PVT_CHANNEL1_CFG, PVT_DBIAS_CHANNEL1_CFG_S); + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL2_SEL_REG, PVT_DBIAS_CHANNEL2_CFG, PVT_CHANNEL2_CFG, PVT_DBIAS_CHANNEL2_CFG_S); // Configure filter threshold for avoiding auto-dbias overly sensitive regulation + SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0, PVT_CMD0, PVT_DBIAS_CMD0_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1, PVT_CMD1, PVT_DBIAS_CMD1_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2, PVT_CMD2, PVT_DBIAS_CMD2_S); // Configure auto-dbias adjust property, such as adjusting step + SET_PERI_REG_BITS(PVT_DBIAS_TIMER_REG, PVT_TIMER_TARGET, PVT_TARGET, PVT_TIMER_TARGET_S); // Configure auto-dbias voltage regulation cycle + + SET_PERI_REG_BITS(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM, PVT_CLK_DIV, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_S); //pvt function clock divider number + + /*config for pvt cell: unit0; site2; vt2*/ + SET_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_SEL); //pvt function clock source select + SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT0_VT2_CONF2_REG, PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT0, PVT_EDG_MODE, PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT0_S); // Select edge_mode + SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT0_VT2_CONF1_REG, PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT0, PVT_DELAY_NUM_HIGH, PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT0_S); // The threshold for determining whether the voltage is too high + SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT1_VT2_CONF1_REG, PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT1, PVT_DELAY_NUM_LOW, PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT1_S); // The threshold for determining whether the voltage is too low +} + +void pvt_func_enable(bool enable) +{ + if (enable) { + SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT); + CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pvt + SET_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN); + SET_PERI_REG_MASK(PVT_COMB_PD_SITE2_UNIT0_VT2_CONF1_REG, PVT_MONITOR_EN_VT2_PD_SITE2_UNIT0); // enable pvt clk + SET_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); // enable auto dbias + } else { + uint32_t pvt_cali_dbias = get_pvt_dbias(); // update pvt_cali_dbias + SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_V, pvt_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S); + SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pmu + CLEAR_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); //disable auto dbias + CLEAR_PERI_REG_MASK(PVT_COMB_PD_SITE2_UNIT0_VT2_CONF1_REG, PVT_MONITOR_EN_VT2_PD_SITE2_UNIT0); + CLEAR_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN); + } +} + +void charge_pump_init(void) +{ + /*config for charge pump*/ + SET_PERI_REG_BITS(PVT_PMUP_CHANNEL_CFG_REG, PVT_PUMP_CHANNEL_CODE0, PVT_PUMP_CHANNEL_CODE, PVT_PUMP_CHANNEL_CODE0_S); //Set channel code + WRITE_PERI_REG(PVT_PMUP_BITMAP_LOW0_REG, PVT_PUMP_BITMAP); // Select monitor cell for charge pump + SET_PERI_REG_BITS(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_DRV0, PVT_PUMP_DRV, PVT_PUMP_DRV0_S); //Configure the charging intensity +} + +void charge_pump_enable(bool enable) +{ + if (enable) { + SET_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); // enable charge pump + } else { + CLEAR_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); //disable charge pump + } +} + +inline uint32_t get_pvt_dbias() +{ + return REG_GET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_DBIAS_VOL); +} diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index cdeeb43fa906..812cfccc95e2 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -208,6 +208,7 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd); pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b); + pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(MODEM), get_pvt_dbias()); pmu_ll_lp_set_dbg_atten (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbg_atten); pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur); diff --git a/components/esp_hw_support/port/esp32c6/rtc_clk.c b/components/esp_hw_support/port/esp32c6/rtc_clk.c index ed6eb4126f22..bdccc8af60c0 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c6/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32c6/rom/rtc.h" #include "soc/rtc.h" #include "esp_private/rtc_clk.h" +#include "esp_private/esp_pmu.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" #include "hal/clk_tree_ll.h" @@ -184,6 +185,10 @@ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) clk_ll_cpu_set_ls_divider(div); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); esp_rom_set_cpu_ticks_per_us(cpu_freq); +#ifndef BOOTLOADER_BUILD + charge_pump_enable(0); + pvt_func_enable(0); +#endif } static void rtc_clk_cpu_freq_to_8m(void) @@ -192,6 +197,10 @@ static void rtc_clk_cpu_freq_to_8m(void) clk_ll_cpu_set_ls_divider(1); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); esp_rom_set_cpu_ticks_per_us(20); +#ifndef BOOTLOADER_BUILD + charge_pump_enable(0); + pvt_func_enable(0); +#endif } /** @@ -201,6 +210,10 @@ static void rtc_clk_cpu_freq_to_8m(void) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { +#ifndef BOOTLOADER_BUILD + pvt_func_enable(1); + charge_pump_enable(1); +#endif clk_ll_cpu_set_hs_divider(CLK_LL_PLL_480M_FREQ_MHZ / cpu_freq_mhz); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); diff --git a/components/esp_hw_support/port/esp32c6/rtc_clk_init.c b/components/esp_hw_support/port/esp32c6/rtc_clk_init.c index 0f911ace88a9..2884550febd2 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32c6/rtc_clk_init.c @@ -24,6 +24,8 @@ #include "hal/pmu_ll.h" #include "hal/modem_syscon_ll.h" #include "hal/modem_lpcon_ll.h" +#include "soc/pmu_reg.h" +#include "pmu_param.h" static const char *TAG = "rtc_clk_init"; @@ -72,6 +74,10 @@ void rtc_clk_init(rtc_clk_config_t cfg) REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, cfg.clk_8m_dfreq); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, cfg.slow_clk_dcap); REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS); + REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS); clk_ll_rc_fast_tick_conf(); diff --git a/components/esp_hw_support/port/esp32h2/CMakeLists.txt b/components/esp_hw_support/port/esp32h2/CMakeLists.txt index 9c1949a12c15..ec544172422f 100644 --- a/components/esp_hw_support/port/esp32h2/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h2/CMakeLists.txt @@ -5,6 +5,7 @@ set(srcs "rtc_clk_init.c" "pmu_sleep.c" "rtc_time.c" "chip_info.c" + "pmu_pvt_pump.c" ) if(NOT BOOTLOADER_BUILD) diff --git a/components/esp_hw_support/port/esp32h2/pmu_init.c b/components/esp_hw_support/port/esp32h2/pmu_init.c index 0548461a2bb4..d8e247b8d90d 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_init.c +++ b/components/esp_hw_support/port/esp32h2/pmu_init.c @@ -13,6 +13,7 @@ #include "soc/pmu_struct.h" #include "hal/pmu_hal.h" #include "pmu_param.h" +#include "esp_rom_sys.h" #include "esp_private/esp_pmu.h" #include "soc/regi2c_pmu.h" #include "soc/regi2c_bias.h" @@ -193,9 +194,6 @@ static void pmu_lp_system_init_default(pmu_context_t *ctx) void pmu_init() { /* No peripheral reg i2c power up required on the target */ - - REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0); - REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0); REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG_SLP, 0); REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG_SLP, 0); REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_REG, 0); @@ -215,4 +213,12 @@ void pmu_init() pmu_lp_system_init_default(PMU_instance()); pmu_power_domain_force_default(PMU_instance()); + + pvt_auto_dbias_init(); + charge_pump_init(); + + //HP dbias initialization + pvt_func_enable(1); + charge_pump_enable(1); + esp_rom_delay_us(1000); } diff --git a/components/esp_hw_support/port/esp32h2/pmu_param.c b/components/esp_hw_support/port/esp32h2/pmu_param.c index 83bf887aa31e..10fdceca5535 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_param.c +++ b/components/esp_hw_support/port/esp32h2/pmu_param.c @@ -295,7 +295,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m | BIT(PMU_ICG_FUNC_ENA_SEC) \ | BIT(PMU_ICG_FUNC_ENA_PWM) \ | BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - | BIT(PMU_ICG_FUNC_ENA_UART0)), \ + | BIT(PMU_ICG_FUNC_ENA_UART0)) \ + | BIT(PMU_ICG_FUNC_ENA_PVT_MONITOR), \ } #define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ @@ -342,7 +343,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m | BIT(PMU_ICG_FUNC_ENA_SEC) \ | BIT(PMU_ICG_FUNC_ENA_PWM) \ | BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ - | BIT(PMU_ICG_FUNC_ENA_UART0)), \ + | BIT(PMU_ICG_FUNC_ENA_UART0)) \ + | BIT(PMU_ICG_FUNC_ENA_PVT_MONITOR), \ } const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) diff --git a/components/esp_hw_support/port/esp32h2/pmu_pvt_pump.c b/components/esp_hw_support/port/esp32h2/pmu_pvt_pump.c new file mode 100644 index 000000000000..7aa1bd03d0ec --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/pmu_pvt_pump.c @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "soc/pvt_reg.h" +#include "soc/pmu_reg.h" +#include "soc/pcr_reg.h" +#include "pmu_param.h" +#include "esp_private/esp_pmu.h" +#include "soc/regi2c_pmu.h" +#include "soc/regi2c_bias.h" +#include "regi2c_ctrl.h" +#include "soc/rtc.h" + +static __attribute__((unused)) const char *TAG = "pmu_pvt_pump"; + +void pvt_auto_dbias_init(void) +{ + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0); + /*config for dbias func*/ + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL0_SEL, PVT_CHANNEL0_SEL, PVT_DBIAS_CHANNEL0_SEL_S); + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL1_SEL, PVT_CHANNEL1_SEL, PVT_DBIAS_CHANNEL1_SEL_S); // Select monitor cell ,which used to monitor PVT situation + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL0_SEL_REG, PVT_DBIAS_CHANNEL0_CFG, PVT_CHANNEL0_CFG, PVT_DBIAS_CHANNEL0_CFG_S); + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL1_SEL_REG, PVT_DBIAS_CHANNEL1_CFG, PVT_CHANNEL1_CFG, PVT_DBIAS_CHANNEL1_CFG_S); + SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL2_SEL_REG, PVT_DBIAS_CHANNEL2_CFG, PVT_CHANNEL2_CFG, PVT_DBIAS_CHANNEL2_CFG_S); // Configure filter threshold for avoiding auto-dbias overly sensitive regulation + SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0, PVT_CMD0, PVT_DBIAS_CMD0_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1, PVT_CMD1, PVT_DBIAS_CMD1_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2, PVT_CMD2, PVT_DBIAS_CMD2_S); // Configure auto-dbias adjust property, such as adjusting step + SET_PERI_REG_BITS(PVT_DBIAS_TIMER_REG, PVT_TIMER_TARGET, PVT_TARGET, PVT_TIMER_TARGET_S); // Configure auto-dbias voltage regulation cycle + + SET_PERI_REG_BITS(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM, PVT_CLK_DIV, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_S); //pvt function clock divider number + + /*config for pvt cell: unit0; site2; vt0*/ + SET_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_SEL); //pvt function clock source select + SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF2_REG, PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0, PVT_EDG_MODE, PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0_S); // Select edge_mode + SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0, PVT_DELAY_NUM_HIGH, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0_S); // The threshold for determining whether the voltage is too high + SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT1_VT0_CONF1_REG, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1, PVT_DELAY_NUM_LOW, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1_S); // The threshold for determining whether the voltage is too low +} + +void pvt_func_enable(bool enable) +{ + if (enable) { + SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT); + CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pvt + SET_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN); + SET_PERI_REG_MASK(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG, PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0); // enable pvt clk + SET_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); // enable auto dbias + } else { + uint32_t pvt_cali_dbias = get_pvt_dbias(); // update pvt_cali_dbias + SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_V, pvt_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S); + SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pmu + CLEAR_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); //disable auto dbias + CLEAR_PERI_REG_MASK(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG, PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0); + CLEAR_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN); + } +} + +void charge_pump_init(void) +{ + /*config for charge pump*/ + SET_PERI_REG_BITS(PVT_PMUP_CHANNEL_CFG_REG, PVT_PUMP_CHANNEL_CODE0, PVT_PUMP_CHANNEL_CODE, PVT_PUMP_CHANNEL_CODE0_S); //Set channel code + WRITE_PERI_REG(PVT_PMUP_BITMAP_LOW0_REG, PVT_PUMP_BITMAP); // Select monitor cell for charge pump + SET_PERI_REG_BITS(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_DRV0, PVT_PUMP_DRV, PVT_PUMP_DRV0_S); //Configure the charging intensity +} + +void charge_pump_enable(bool enable) +{ + if (enable) { + SET_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); // enable charge pump + } else { + CLEAR_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); //disable charge pump + } +} + +inline uint32_t get_pvt_dbias() +{ + return REG_GET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_DBIAS_VOL); +} diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index 1f39dd0a7fc7..c6210b475b35 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -164,6 +164,8 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b); pmu_ll_hp_set_trx_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd_trx); + pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(MODEM), get_pvt_dbias()); + pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur); pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep); pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_xpd); diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index ce0a0e260b86..7c6720492a40 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32h2/rom/rtc.h" #include "soc/rtc.h" #include "esp_private/rtc_clk.h" +#include "esp_private/esp_pmu.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" #include "hal/clk_tree_ll.h" @@ -203,6 +204,10 @@ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); clk_ll_bus_update(); esp_rom_set_cpu_ticks_per_us(cpu_freq); +#ifndef BOOTLOADER_BUILD + charge_pump_enable(0); + pvt_func_enable(0); +#endif } static void rtc_clk_cpu_freq_to_8m(void) @@ -213,6 +218,10 @@ static void rtc_clk_cpu_freq_to_8m(void) clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); clk_ll_bus_update(); esp_rom_set_cpu_ticks_per_us(8); +#ifndef BOOTLOADER_BUILD + charge_pump_enable(0); + pvt_func_enable(0); +#endif } /** @@ -222,6 +231,10 @@ static void rtc_clk_cpu_freq_to_8m(void) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { +#ifndef BOOTLOADER_BUILD + pvt_func_enable(1); + charge_pump_enable(1); +#endif // f_hp_root = 96MHz uint32_t cpu_divider = CLK_LL_PLL_96M_FREQ_MHZ / cpu_freq_mhz; clk_ll_cpu_set_divider(cpu_divider); @@ -241,6 +254,10 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) */ static void rtc_clk_cpu_freq_to_flash_pll(uint32_t cpu_freq_mhz, uint32_t cpu_divider) { +#ifndef BOOTLOADER_BUILD + pvt_func_enable(1); + charge_pump_enable(1); +#endif // f_hp_root = 64MHz clk_ll_cpu_set_divider(cpu_divider); // Constraint: f_ahb <= 32MHz; f_cpu = N * f_ahb (N = 1, 2, 3...) 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 aaa476e5b6f8..02d8b9bc4a3e 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c @@ -20,6 +20,8 @@ #include "sdkconfig.h" #include "esp_rom_uart.h" #include "hal/clk_tree_ll.h" +#include "soc/pmu_reg.h" +#include "pmu_param.h" static const char *TAG = "rtc_clk_init"; @@ -39,6 +41,10 @@ void rtc_clk_init(rtc_clk_config_t cfg) REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, cfg.clk_8m_dfreq); REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OC_SCK_DCAP, cfg.slow_clk_dcap); REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0); + REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS); + REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS); clk_ll_rc_fast_tick_conf(); diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 22d236dcd6a3..4d24028f8e51 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -28,6 +28,10 @@ #include "soc/gpio_reg.h" #include "soc/io_mux_reg.h" #include "soc/interrupt_matrix_reg.h" +#if SOC_PMU_PVT_SUPPORTED +#include "soc/pvt_reg.h" +#endif + #include "hal/mwdt_ll.h" static __attribute__((unused)) const char *TAG = "sleep_sys_periph"; @@ -220,6 +224,30 @@ esp_err_t sleep_sys_periph_systimer_retention_init(void) return ESP_OK; } +#if SOC_PMU_PVT_SUPPORTED +esp_err_t sleep_sys_periph_pvt_retention_init(void) +{ +#if CONFIG_IDF_TARGET_ESP32C6 + #define PVT_RETENTION_REGS_CNT 14 + #define PVT_RETENTION_MAP_BASE PVT_PMUP_BITMAP_LOW0_REG + const static uint32_t pvt_regs_map[4] = {0x139D61, 0x600000, 0x2000000, 0}; +#elif CONFIG_IDF_TARGET_ESP32H2 + #define PVT_RETENTION_REGS_CNT 14 + #define PVT_RETENTION_MAP_BASE PVT_PMUP_BITMAP_LOW0_REG + const static uint32_t pvt_regs_map[4] = {0x139D61, 0x6000, 0x20000, 0}; +#endif + + const static sleep_retention_entries_config_t pvt_regs_retention[] = { + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PVT_LINK(0x00), PVT_RETENTION_MAP_BASE, PVT_RETENTION_MAP_BASE, PVT_RETENTION_REGS_CNT, 0, 0, pvt_regs_map[0], pvt_regs_map[1], pvt_regs_map[2], pvt_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) }, + }; + + esp_err_t err = sleep_retention_entries_create(pvt_regs_retention, ARRAY_SIZE(pvt_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_PVT); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (PVT) retention"); + ESP_LOGI(TAG, "PVT sleep retention initialization"); + return ESP_OK; +} +#endif + esp_err_t sleep_sys_periph_retention_init(void) { esp_err_t err; @@ -238,6 +266,11 @@ esp_err_t sleep_sys_periph_retention_init(void) err = sleep_sys_periph_spimem_retention_init(); if(err) goto error; err = sleep_sys_periph_systimer_retention_init(); + if(err) goto error; +#if SOC_PMU_PVT_SUPPORTED + err = sleep_sys_periph_pvt_retention_init(); + if(err) goto error; +#endif error: return err; @@ -247,14 +280,18 @@ bool peripheral_domain_pd_allowed(void) { const uint32_t modules = sleep_retention_get_modules(); const uint32_t mask = (const uint32_t) ( - SLEEP_RETENTION_MODULE_INTR_MATRIX | \ - SLEEP_RETENTION_MODULE_HP_SYSTEM | \ - SLEEP_RETENTION_MODULE_TEE_APM | \ - SLEEP_RETENTION_MODULE_UART0 | \ - SLEEP_RETENTION_MODULE_TG0 | \ - SLEEP_RETENTION_MODULE_IOMUX | \ - SLEEP_RETENTION_MODULE_SPIMEM | \ - SLEEP_RETENTION_MODULE_SYSTIMER); + SLEEP_RETENTION_MODULE_INTR_MATRIX | + SLEEP_RETENTION_MODULE_HP_SYSTEM | + SLEEP_RETENTION_MODULE_TEE_APM | + SLEEP_RETENTION_MODULE_UART0 | + SLEEP_RETENTION_MODULE_TG0 | + SLEEP_RETENTION_MODULE_IOMUX | + SLEEP_RETENTION_MODULE_SPIMEM | + SLEEP_RETENTION_MODULE_SYSTIMER | +#if SOC_PMU_PVT_SUPPORTED + SLEEP_RETENTION_MODULE_PVT | +#endif + 0); return ((modules & mask) == mask); } diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 99349bc831d1..fb87ce8dc265 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -179,6 +179,10 @@ config SOC_PMU_SUPPORTED bool default y +config SOC_PMU_PVT_SUPPORTED + bool + default y + config SOC_PAU_SUPPORTED bool default y diff --git a/components/soc/esp32c6/include/soc/pvt_reg.h b/components/soc/esp32c6/include/soc/pvt_reg.h new file mode 100644 index 000000000000..138d1230c129 --- /dev/null +++ b/components/soc/esp32c6/include/soc/pvt_reg.h @@ -0,0 +1,876 @@ +/** + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "soc/soc.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define PVT_PMUP_BITMAP_HIGH0_REG (DR_REG_PVT_MONITOR_BASE + 0x0000) +#define PVT_PUMP_BITMAP_HIGH0 0xFFFFFFFF +#define PVT_PUMP_BITMAP_HIGH0_S 0 + +#define PVT_PMUP_BITMAP_HIGH1_REG (DR_REG_PVT_MONITOR_BASE + 0x0004) +#define PVT_PUMP_BITMAP_HIGH1 0xFFFFFFFF +#define PVT_PUMP_BITMAP_HIGH1_S 0 + +#define PVT_PMUP_BITMAP_HIGH2_REG (DR_REG_PVT_MONITOR_BASE + 0x0008) +#define PVT_PUMP_BITMAP_HIGH2 0xFFFFFFFF +#define PVT_PUMP_BITMAP_HIGH2_S 0 + +#define PVT_PMUP_BITMAP_HIGH3_REG (DR_REG_PVT_MONITOR_BASE + 0x000C) +#define PVT_PUMP_BITMAP_HIGH3 0xFFFFFFFF +#define PVT_PUMP_BITMAP_HIGH3_S 0 + +#define PVT_PMUP_BITMAP_HIGH4_REG (DR_REG_PVT_MONITOR_BASE + 0x0010) +#define PVT_PUMP_BITMAP_HIGH4 0xFFFFFFFF +#define PVT_PUMP_BITMAP_HIGH4_S 0 + +#define PVT_PMUP_BITMAP_LOW0_REG (DR_REG_PVT_MONITOR_BASE + 0x0014) +#define PVT_PUMP_BITMAP_LOW0 0xFFFFFFFF +#define PVT_PUMP_BITMAP_LOW0_S 0 + +#define PVT_PMUP_BITMAP_LOW1_REG (DR_REG_PVT_MONITOR_BASE + 0x0018) +#define PVT_PUMP_BITMAP_LOW1 0xFFFFFFFF +#define PVT_PUMP_BITMAP_LOW1_S 0 + +#define PVT_PMUP_BITMAP_LOW2_REG (DR_REG_PVT_MONITOR_BASE + 0x001C) +#define PVT_PUMP_BITMAP_LOW2 0xFFFFFFFF +#define PVT_PUMP_BITMAP_LOW2_S 0 + +#define PVT_PMUP_BITMAP_LOW3_REG (DR_REG_PVT_MONITOR_BASE + 0x0020) +#define PVT_PUMP_BITMAP_LOW3 0xFFFFFFFF +#define PVT_PUMP_BITMAP_LOW3_S 0 + +#define PVT_PMUP_BITMAP_LOW4_REG (DR_REG_PVT_MONITOR_BASE + 0x0024) +#define PVT_PUMP_BITMAP_LOW4 0xFFFFFFFF +#define PVT_PUMP_BITMAP_LOW4_S 0 + +#define PVT_PMUP_DRV_CFG_REG (DR_REG_PVT_MONITOR_BASE + 0x0028) +#define PVT_PUMP_DRV0 0x0000000F +#define PVT_PUMP_DRV0_S 27 +#define PVT_PUMP_DRV1 0x0000000F +#define PVT_PUMP_DRV1_S 23 +#define PVT_PUMP_DRV2 0x0000000F +#define PVT_PUMP_DRV2_S 19 +#define PVT_PUMP_DRV3 0x0000000F +#define PVT_PUMP_DRV3_S 15 +#define PVT_PUMP_DRV4 0x0000000F +#define PVT_PUMP_DRV4_S 11 +#define PVT_CLK_EN (BIT(10)) +#define PVT_CLK_EN_S 10 +#define PVT_PUMP_EN (BIT(9)) +#define PVT_PUMP_EN_S 9 + +#define PVT_PMUP_CHANNEL_CFG_REG (DR_REG_PVT_MONITOR_BASE + 0x002C) +#define PVT_PUMP_CHANNEL_CODE0 0x0000001F +#define PVT_PUMP_CHANNEL_CODE0_S 27 +#define PVT_PUMP_CHANNEL_CODE1 0x0000001F +#define PVT_PUMP_CHANNEL_CODE1_S 22 +#define PVT_PUMP_CHANNEL_CODE2 0x0000001F +#define PVT_PUMP_CHANNEL_CODE2_S 17 +#define PVT_PUMP_CHANNEL_CODE3 0x0000001F +#define PVT_PUMP_CHANNEL_CODE3_S 12 +#define PVT_PUMP_CHANNEL_CODE4 0x0000001F +#define PVT_PUMP_CHANNEL_CODE4_S 7 + +#define PVT_CLK_CFG_REG (DR_REG_PVT_MONITOR_BASE + 0x0030) +#define PVT_CLK_SEL (BIT(31)) +#define PVT_CLK_SEL_S 31 +#define PVT_MONITOR_CLK_PVT_EN (BIT(8)) +#define PVT_MONITOR_CLK_PVT_EN_S 8 +#define PVT_PUMP_CLK_DIV_NUM 0x000000FF +#define PVT_PUMP_CLK_DIV_NUM_S 0 + +#define PVT_DBIAS_CHANNEL_SEL0_REG (DR_REG_PVT_MONITOR_BASE + 0x0034) +#define PVT_DBIAS_CHANNEL0_SEL 0x0000007F +#define PVT_DBIAS_CHANNEL0_SEL_S 25 +#define PVT_DBIAS_CHANNEL1_SEL 0x0000007F +#define PVT_DBIAS_CHANNEL1_SEL_S 18 +#define PVT_DBIAS_CHANNEL2_SEL 0x0000007F +#define PVT_DBIAS_CHANNEL2_SEL_S 11 +#define PVT_DBIAS_CHANNEL3_SEL 0x0000007F +#define PVT_DBIAS_CHANNEL3_SEL_S 4 + +#define PVT_DBIAS_CHANNEL_SEL1_REG (DR_REG_PVT_MONITOR_BASE + 0x0038) +#define PVT_DBIAS_CHANNEL4_SEL 0x0000007F +#define PVT_DBIAS_CHANNEL4_SEL_S 25 + +#define PVT_DBIAS_CHANNEL0_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x003C) +#define PVT_DBIAS_CHANNEL0_CFG 0x0001FFFF +#define PVT_DBIAS_CHANNEL0_CFG_S 0 + +#define PVT_DBIAS_CHANNEL1_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x0040) +#define PVT_DBIAS_CHANNEL1_CFG 0x0001FFFF +#define PVT_DBIAS_CHANNEL1_CFG_S 0 + +#define PVT_DBIAS_CHANNEL2_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x0044) +#define PVT_DBIAS_CHANNEL2_CFG 0x0001FFFF +#define PVT_DBIAS_CHANNEL2_CFG_S 0 + +#define PVT_DBIAS_CHANNEL3_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x0048) +#define PVT_DBIAS_CHANNEL3_CFG 0x0001FFFF +#define PVT_DBIAS_CHANNEL3_CFG_S 0 + +#define PVT_DBIAS_CHANNEL4_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x004C) +#define PVT_DBIAS_CHANNEL4_CFG 0x0001FFFF +#define PVT_DBIAS_CHANNEL4_CFG_S 0 + +#define PVT_DBIAS_CMD0_REG (DR_REG_PVT_MONITOR_BASE + 0x0050) +#define PVT_DBIAS_CMD0 0x0001FFFF +#define PVT_DBIAS_CMD0_S 0 + +#define PVT_DBIAS_CMD1_REG (DR_REG_PVT_MONITOR_BASE + 0x0054) +#define PVT_DBIAS_CMD1 0x0001FFFF +#define PVT_DBIAS_CMD1_S 0 + +#define PVT_DBIAS_CMD2_REG (DR_REG_PVT_MONITOR_BASE + 0x0058) +#define PVT_DBIAS_CMD2 0x0001FFFF +#define PVT_DBIAS_CMD2_S 0 + +#define PVT_DBIAS_CMD3_REG (DR_REG_PVT_MONITOR_BASE + 0x005C) +#define PVT_DBIAS_CMD3 0x0001FFFF +#define PVT_DBIAS_CMD3_S 0 + +#define PVT_DBIAS_CMD4_REG (DR_REG_PVT_MONITOR_BASE + 0x0060) +#define PVT_DBIAS_CMD4 0x0001FFFF +#define PVT_DBIAS_CMD4_S 0 + +#define PVT_DBIAS_TIMER_REG (DR_REG_PVT_MONITOR_BASE + 0x0064) +#define PVT_TIMER_EN (BIT(31)) +#define PVT_TIMER_EN_S 31 +#define PVT_TIMER_TARGET 0x0000FFFF +#define PVT_TIMER_TARGET_S 15 + +#define PVT_COMB_PD_SITE0_UNIT0_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0068) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT0_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x006C) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT1_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0070) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT2_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0074) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT3_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0078) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT0_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x007C) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT1_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0080) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT2_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0084) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT3_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0088) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT0_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x008C) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT1_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0090) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT2_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0094) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT3_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0098) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT0_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x009C) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT1_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00A0) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT2_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00A4) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT3_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00A8) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT0_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00AC) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT1_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00B0) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT2_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00B4) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT3_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00B8) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT0_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00BC) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT1_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00C0) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT2_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00C4) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT3_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00C8) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT0_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00CC) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT1_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00D0) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT2_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00D4) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT3_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00D8) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT0_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00DC) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT1_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00E0) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT2_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00E4) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT3_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00E8) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT0 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT0 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT0 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT0 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT0_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT0 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00EC) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT1 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT1 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT1 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT1 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT1_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT1 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00F0) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT2 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT2 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT2 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT2 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT2_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT2 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00F4) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT3 (BIT(31)) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT3 0x000000FF +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT3 0x000000FF +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT3 (BIT(1)) +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT3_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT3 (BIT(0)) +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x00F8) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT0_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x00FC) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT1_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0100) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT2_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0104) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT3_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0108) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT0_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x010C) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT1_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0110) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT2_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0114) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT3_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0118) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT0_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x011C) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT1_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0120) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT2_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0124) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT3_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0128) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT0_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x012C) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT1_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0130) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT2_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0134) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT3_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0138) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT0_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x013C) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT1_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0140) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT2_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0144) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT3_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0148) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT0_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x014C) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT1_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0150) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT2_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0154) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT3_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0158) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT0_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x015C) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT1_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0160) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT2_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0164) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT3_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0168) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT0_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x016C) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT1_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0170) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT2_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0174) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT3_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0178) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT0 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT0_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT0 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x017C) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT1 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT1_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT1 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0180) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT2 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT2_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT2 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0184) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT3 0x0000FFFF +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT3_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT3 (BIT(15)) +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT3_S 0 + +#define PVT_DATE_REG (DR_REG_PVT_MONITOR_BASE + 0xFFC) +#define PVT_DATE 0xFFFFFFFF +#define PVT_DATE_S 0 + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32c6/include/soc/rtc.h b/components/soc/esp32c6/include/soc/rtc.h index 716424dcc065..0999650d5f95 100644 --- a/components/soc/esp32c6/include/soc/rtc.h +++ b/components/soc/esp32c6/include/soc/rtc.h @@ -117,6 +117,26 @@ set sleep_init default param #define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 #define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 254 +/* +set pvt default param +*/ +#define PVT_CHANNEL0_SEL 34 +#define PVT_CHANNEL1_SEL 38 +#define PVT_CHANNEL0_CFG 0x1033e +#define PVT_CHANNEL1_CFG 0x1033e +#define PVT_CHANNEL2_CFG 0x10000 +#define PVT_CMD0 0x24 +#define PVT_CMD1 0x5 +#define PVT_CMD2 0x427 +#define PVT_TARGET 0x1f40 +#define PVT_CLK_DIV 1 +#define PVT_EDG_MODE 1 +#define PVT_DELAY_NUM_HIGH 108 +#define PVT_DELAY_NUM_LOW 98 +#define PVT_PUMP_CHANNEL_CODE 1 +#define PVT_PUMP_BITMAP 512 +#define PVT_PUMP_DRV 0 + /* The follow value is used to get a reasonable rtc voltage dbias value according to digital dbias & some other value storing in efuse (based on ATE 5k ECO3 chips) diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 7458d4a1ed83..0e2aec367aef 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -69,6 +69,7 @@ #define SOC_BOD_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 +#define SOC_PMU_PVT_SUPPORTED 1 #define SOC_PAU_SUPPORTED 1 #define SOC_LP_TIMER_SUPPORTED 1 #define SOC_LP_AON_SUPPORTED 1 diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index fa5fd53e6cca..096b39ff309d 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -175,6 +175,10 @@ config SOC_PMU_SUPPORTED bool default y +config SOC_PMU_PVT_SUPPORTED + bool + default y + config SOC_LP_TIMER_SUPPORTED bool default y diff --git a/components/soc/esp32h2/include/soc/pvt_reg.h b/components/soc/esp32h2/include/soc/pvt_reg.h new file mode 100644 index 000000000000..732eb501fe62 --- /dev/null +++ b/components/soc/esp32h2/include/soc/pvt_reg.h @@ -0,0 +1,881 @@ +/** + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "soc/soc.h" +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PVT_REG_H +#define PVT_REG_H + +#define PVT_PMUP_BITMAP_HIGH0_REG (DR_REG_PVT_MONITOR_BASE + 0x0000) +#define PVT_PUMP_BITMAP_HIGH0 0xffffffff +#define PVT_PUMP_BITMAP_HIGH0_S 0 + +#define PVT_PMUP_BITMAP_HIGH1_REG (DR_REG_PVT_MONITOR_BASE + 0x0004) +#define PVT_PUMP_BITMAP_HIGH1 0xffffffff +#define PVT_PUMP_BITMAP_HIGH1_S 0 + +#define PVT_PMUP_BITMAP_HIGH2_REG (DR_REG_PVT_MONITOR_BASE + 0x0008) +#define PVT_PUMP_BITMAP_HIGH2 0xffffffff +#define PVT_PUMP_BITMAP_HIGH2_S 0 + +#define PVT_PMUP_BITMAP_HIGH3_REG (DR_REG_PVT_MONITOR_BASE + 0x000C) +#define PVT_PUMP_BITMAP_HIGH3 0xffffffff +#define PVT_PUMP_BITMAP_HIGH3_S 0 + +#define PVT_PMUP_BITMAP_HIGH4_REG (DR_REG_PVT_MONITOR_BASE + 0x0010) +#define PVT_PUMP_BITMAP_HIGH4 0xffffffff +#define PVT_PUMP_BITMAP_HIGH4_S 0 + +#define PVT_PMUP_BITMAP_LOW0_REG (DR_REG_PVT_MONITOR_BASE + 0x0014) +#define PVT_PUMP_BITMAP_LOW0 0xffffffff +#define PVT_PUMP_BITMAP_LOW0_S 0 + +#define PVT_PMUP_BITMAP_LOW1_REG (DR_REG_PVT_MONITOR_BASE + 0x0018) +#define PVT_PUMP_BITMAP_LOW1 0xffffffff +#define PVT_PUMP_BITMAP_LOW1_S 0 + +#define PVT_PMUP_BITMAP_LOW2_REG (DR_REG_PVT_MONITOR_BASE + 0x001C) +#define PVT_PUMP_BITMAP_LOW2 0xffffffff +#define PVT_PUMP_BITMAP_LOW2_S 0 + +#define PVT_PMUP_BITMAP_LOW3_REG (DR_REG_PVT_MONITOR_BASE + 0x0020) +#define PVT_PUMP_BITMAP_LOW3 0xffffffff +#define PVT_PUMP_BITMAP_LOW3_S 0 + +#define PVT_PMUP_BITMAP_LOW4_REG (DR_REG_PVT_MONITOR_BASE + 0x0024) +#define PVT_PUMP_BITMAP_LOW4 0xffffffff +#define PVT_PUMP_BITMAP_LOW4_S 0 + +#define PVT_PMUP_DRV_CFG_REG (DR_REG_PVT_MONITOR_BASE + 0x0028) +#define PVT_PUMP_DRV0 0x0000000f +#define PVT_PUMP_DRV0_S 27 +#define PVT_PUMP_DRV1 0x0000000f +#define PVT_PUMP_DRV1_S 23 +#define PVT_PUMP_DRV2 0x0000000f +#define PVT_PUMP_DRV2_S 19 +#define PVT_PUMP_DRV3 0x0000000f +#define PVT_PUMP_DRV3_S 15 +#define PVT_PUMP_DRV4 0x0000000f +#define PVT_PUMP_DRV4_S 11 +#define PVT_CLK_EN 0x00000400 +#define PVT_CLK_EN_S 10 +#define PVT_PUMP_EN 0x00000200 +#define PVT_PUMP_EN_S 9 + +#define PVT_PMUP_CHANNEL_CFG_REG (DR_REG_PVT_MONITOR_BASE + 0x002C) +#define PVT_PUMP_CHANNEL_CODE0 0x0000001f +#define PVT_PUMP_CHANNEL_CODE0_S 27 +#define PVT_PUMP_CHANNEL_CODE1 0x0000001f +#define PVT_PUMP_CHANNEL_CODE1_S 22 +#define PVT_PUMP_CHANNEL_CODE2 0x0000001f +#define PVT_PUMP_CHANNEL_CODE2_S 17 +#define PVT_PUMP_CHANNEL_CODE3 0x0000001f +#define PVT_PUMP_CHANNEL_CODE3_S 12 +#define PVT_PUMP_CHANNEL_CODE4 0x0000001f +#define PVT_PUMP_CHANNEL_CODE4_S 7 + +#define PVT_CLK_CFG_REG (DR_REG_PVT_MONITOR_BASE + 0x0030) +#define PVT_CLK_SEL 0x80000000 +#define PVT_CLK_SEL_S 31 +#define PVT_MONITOR_CLK_PVT_EN 0x00000100 +#define PVT_MONITOR_CLK_PVT_EN_S 8 +#define PVT_PUMP_CLK_DIV_NUM 0x000000ff +#define PVT_PUMP_CLK_DIV_NUM_S 0 + +#define PVT_DBIAS_CHANNEL_SEL0_REG (DR_REG_PVT_MONITOR_BASE + 0x0034) +#define PVT_DBIAS_CHANNEL0_SEL 0x0000007f +#define PVT_DBIAS_CHANNEL0_SEL_S 25 +#define PVT_DBIAS_CHANNEL1_SEL 0x0000007f +#define PVT_DBIAS_CHANNEL1_SEL_S 18 +#define PVT_DBIAS_CHANNEL2_SEL 0x0000007f +#define PVT_DBIAS_CHANNEL2_SEL_S 11 +#define PVT_DBIAS_CHANNEL3_SEL 0x0000007f +#define PVT_DBIAS_CHANNEL3_SEL_S 4 + +#define PVT_DBIAS_CHANNEL_SEL1_REG (DR_REG_PVT_MONITOR_BASE + 0x0038) +#define PVT_DBIAS_CHANNEL4_SEL 0x0000007f +#define PVT_DBIAS_CHANNEL4_SEL_S 25 + +#define PVT_DBIAS_CHANNEL0_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x003C) +#define PVT_DBIAS_CHANNEL0_CFG 0x0001ffff +#define PVT_DBIAS_CHANNEL0_CFG_S 0 + +#define PVT_DBIAS_CHANNEL1_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x0040) +#define PVT_DBIAS_CHANNEL1_CFG 0x0001ffff +#define PVT_DBIAS_CHANNEL1_CFG_S 0 + +#define PVT_DBIAS_CHANNEL2_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x0044) +#define PVT_DBIAS_CHANNEL2_CFG 0x0001ffff +#define PVT_DBIAS_CHANNEL2_CFG_S 0 + +#define PVT_DBIAS_CHANNEL3_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x0048) +#define PVT_DBIAS_CHANNEL3_CFG 0x0001ffff +#define PVT_DBIAS_CHANNEL3_CFG_S 0 + +#define PVT_DBIAS_CHANNEL4_SEL_REG (DR_REG_PVT_MONITOR_BASE + 0x004C) +#define PVT_DBIAS_CHANNEL4_CFG 0x0001ffff +#define PVT_DBIAS_CHANNEL4_CFG_S 0 + +#define PVT_DBIAS_CMD0_REG (DR_REG_PVT_MONITOR_BASE + 0x0050) +#define PVT_DBIAS_CMD0 0x0001ffff +#define PVT_DBIAS_CMD0_S 0 + +#define PVT_DBIAS_CMD1_REG (DR_REG_PVT_MONITOR_BASE + 0x0054) +#define PVT_DBIAS_CMD1 0x0001ffff +#define PVT_DBIAS_CMD1_S 0 + +#define PVT_DBIAS_CMD2_REG (DR_REG_PVT_MONITOR_BASE + 0x0058) +#define PVT_DBIAS_CMD2 0x0001ffff +#define PVT_DBIAS_CMD2_S 0 + +#define PVT_DBIAS_CMD3_REG (DR_REG_PVT_MONITOR_BASE + 0x005C) +#define PVT_DBIAS_CMD3 0x0001ffff +#define PVT_DBIAS_CMD3_S 0 + +#define PVT_DBIAS_CMD4_REG (DR_REG_PVT_MONITOR_BASE + 0x0060) +#define PVT_DBIAS_CMD4 0x0001ffff +#define PVT_DBIAS_CMD4_S 0 + +#define PVT_DBIAS_TIMER_REG (DR_REG_PVT_MONITOR_BASE + 0x0064) +#define PVT_TIMER_EN 0x80000000 +#define PVT_TIMER_EN_S 31 +#define PVT_TIMER_TARGET 0x0000ffff +#define PVT_TIMER_TARGET_S 15 + +#define PVT_COMB_PD_SITE0_UNIT0_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0068) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT0_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x006C) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT1_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0070) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT2_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0074) +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE0_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE0_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE0_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE0_UNIT3_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0078) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT0_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x007C) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT1_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0080) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT2_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0084) +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE0_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE0_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE0_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE0_UNIT3_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0088) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT0_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x008C) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT1_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0090) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT2_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0094) +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE0_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE0_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE0_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE0_UNIT3_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x0098) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT0_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x009C) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT1_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00A0) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT2_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00A4) +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE1_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE1_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE1_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE1_UNIT3_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00A8) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT0_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00AC) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT1_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00B0) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT2_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00B4) +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE1_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE1_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE1_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE1_UNIT3_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00B8) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT0_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00BC) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT1_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00C0) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT2_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00C4) +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE1_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE1_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE1_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE1_UNIT3_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00C8) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT0_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00CC) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT1_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00D0) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT2_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT0_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00D4) +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT0_PD_SITE2_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT0_PD_SITE2_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT0_PD_SITE2_UNIT3_S 1 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT0_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00D8) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT0_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00DC) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT1_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00E0) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT2_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT1_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00E4) +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT1_PD_SITE2_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT1_PD_SITE2_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT1_PD_SITE2_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT1_PD_SITE2_UNIT3_S 1 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT1_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00E8) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT0 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT0_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT0 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT0_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT0 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT0_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT0 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT0_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT0 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00EC) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT1 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT1_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT1 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT1_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT1 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT1_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT1 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT1_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT1 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00F0) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT2 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT2_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT2 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT2_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT2 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT2_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT2 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT2_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT2 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT2_CONF1_REG (DR_REG_PVT_MONITOR_BASE + 0x00F4) +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT3 0x80000000 +#define PVT_TIMING_ERR_VT2_PD_SITE2_UNIT3_S 31 +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT3 0x000000ff +#define PVT_DELAY_NUM_O_VT2_PD_SITE2_UNIT3_S 23 +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT3 0x000000ff +#define PVT_DELAY_LIMIT_VT2_PD_SITE2_UNIT3_S 2 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT3 0x00000002 +#define PVT_TIMING_ERR_CNT_CLR_VT2_PD_SITE2_UNIT3_S 1 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT3 0x00000001 +#define PVT_MONITOR_EN_VT2_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x00F8) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT0_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x00FC) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT1_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0100) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT2_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0104) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE0_UNIT3_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE0_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0108) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT0_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x010C) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT1_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0110) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT2_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0114) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE0_UNIT3_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE0_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE0_UNIT0_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0118) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT0_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT0_S 0 + +#define PVT_COMB_PD_SITE0_UNIT1_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x011C) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT1_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT1_S 0 + +#define PVT_COMB_PD_SITE0_UNIT2_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0120) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT2_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT2_S 0 + +#define PVT_COMB_PD_SITE0_UNIT3_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0124) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE0_UNIT3_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE0_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE0_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0128) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT0_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x012C) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT1_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0130) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT2_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0134) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE1_UNIT3_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE1_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0138) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT0_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x013C) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT1_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0140) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT2_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0144) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE1_UNIT3_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE1_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE1_UNIT0_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0148) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT0_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT0_S 0 + +#define PVT_COMB_PD_SITE1_UNIT1_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x014C) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT1_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT1_S 0 + +#define PVT_COMB_PD_SITE1_UNIT2_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0150) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT2_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT2_S 0 + +#define PVT_COMB_PD_SITE1_UNIT3_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0154) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE1_UNIT3_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE1_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE1_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0158) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT0_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x015C) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT1_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0160) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT2_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT0_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0164) +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT0_PD_SITE2_UNIT3_S 16 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT0_PD_SITE2_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0168) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT0_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x016C) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT1_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0170) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT2_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT1_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0174) +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT1_PD_SITE2_UNIT3_S 16 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT1_PD_SITE2_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT1_PD_SITE2_UNIT3_S 0 + +#define PVT_COMB_PD_SITE2_UNIT0_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0178) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT0 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT0_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT0 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT0_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT0 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT0_S 0 + +#define PVT_COMB_PD_SITE2_UNIT1_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x017C) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT1 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT1_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT1 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT1_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT1 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT1_S 0 + +#define PVT_COMB_PD_SITE2_UNIT2_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0180) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT2 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT2_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT2 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT2_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT2 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT2_S 0 + +#define PVT_COMB_PD_SITE2_UNIT3_VT2_CONF2_REG (DR_REG_PVT_MONITOR_BASE + 0x0184) +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT3 0x0000ffff +#define PVT_TIMING_ERR_CNT_O_VT2_PD_SITE2_UNIT3_S 16 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT3 0x00008000 +#define PVT_DELAY_OVF_VT2_PD_SITE2_UNIT3_S 15 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT3 0x00000003 +#define PVT_MONITOR_EDG_MOD_VT2_PD_SITE2_UNIT3_S 0 + +#define PVT_DATE_REG (DR_REG_PVT_MONITOR_BASE + 0xFFC) +#define PVT_DATE 0xffffffff +#define PVT_DATE_S 0 + +#endif//PVT_REG_H + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/include/soc/rtc.h b/components/soc/esp32h2/include/soc/rtc.h index 1730c29980db..10cc5a598dfe 100644 --- a/components/soc/esp32h2/include/soc/rtc.h +++ b/components/soc/esp32h2/include/soc/rtc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -120,6 +120,26 @@ set sleep_init default param #define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 #define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 254 +/* +set pvt default param +*/ +#define PVT_CHANNEL0_SEL 32 +#define PVT_CHANNEL1_SEL 36 +#define PVT_CHANNEL0_CFG 0x1033e +#define PVT_CHANNEL1_CFG 0x1033e +#define PVT_CHANNEL2_CFG 0x10000 +#define PVT_CMD0 0x24 +#define PVT_CMD1 0x5 +#define PVT_CMD2 0x427 +#define PVT_TARGET 0x1f40 +#define PVT_CLK_DIV 1 +#define PVT_EDG_MODE 1 +#define PVT_DELAY_NUM_HIGH 108 +#define PVT_DELAY_NUM_LOW 97 +#define PVT_PUMP_CHANNEL_CODE 1 +#define PVT_PUMP_BITMAP 512 +#define PVT_PUMP_DRV 0 + /* The follow value is used to get a reasonable rtc voltage dbias value according to digital dbias & some other value storing in efuse (based on ATE 5k ECO3 chips) diff --git a/components/soc/esp32h2/include/soc/soc.h b/components/soc/esp32h2/include/soc/soc.h index a560492e7fde..20a5f057c38d 100644 --- a/components/soc/esp32h2/include/soc/soc.h +++ b/components/soc/esp32h2/include/soc/soc.h @@ -137,7 +137,7 @@ #define APB_CLK_FREQ_ROM ( 32*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM #define EFUSE_CLK_FREQ_ROM ( 20*1000000) -#define CPU_CLK_FREQ_MHZ_BTLD (96) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration +#define CPU_CLK_FREQ_MHZ_BTLD (64) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration #define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ ( 32*1000000 ) #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 32*1000000 ) diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 87112e06131e..e21fb158a72b 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -69,6 +69,7 @@ #define SOC_BOD_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 +#define SOC_PMU_PVT_SUPPORTED 1 #define SOC_LP_TIMER_SUPPORTED 1 #define SOC_LP_AON_SUPPORTED 1 #define SOC_PAU_SUPPORTED 1 From cf889f3c6d7b489409a15b32c06661b4e276b3ce Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Fri, 16 Jun 2023 15:15:23 +0800 Subject: [PATCH 105/142] feat(i2s): support i2s on esp32p4 --- components/driver/deprecated/i2s_legacy.c | 4 +- .../driver/i2s/include/driver/i2s_pdm.h | 24 + .../i2s_test_apps/i2s/main/test_i2s.c | 2 + .../esp_hw_support/port/esp32p4/rtc_clk.c | 16 + components/hal/esp32/include/hal/i2s_ll.h | 2 +- components/hal/esp32c3/include/hal/i2s_ll.h | 2 +- components/hal/esp32c6/include/hal/i2s_ll.h | 2 +- components/hal/esp32h2/include/hal/i2s_ll.h | 2 +- components/hal/esp32p4/include/i2s_ll.h | 1244 +++++++++++++++++ components/hal/esp32s2/include/hal/i2s_ll.h | 2 +- components/hal/esp32s3/include/hal/i2s_ll.h | 2 +- components/hal/i2s_hal.c | 49 +- components/hal/include/hal/i2s_hal.h | 8 +- .../soc/esp32c6/include/soc/i2s_struct.h | 124 +- .../soc/esp32h2/include/soc/i2s_struct.h | 124 +- components/soc/esp32p4/i2s_periph.c | 69 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 36 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 15 + .../soc/esp32p4/include/soc/i2s_struct.h | 184 +-- components/soc/esp32p4/include/soc/soc_caps.h | 19 +- examples/peripherals/.build-test-rules.yml | 10 +- 21 files changed, 1568 insertions(+), 372 deletions(-) create mode 100644 components/hal/esp32p4/include/i2s_ll.h diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c index 9b7ded01445c..f687cf917072 100644 --- a/components/driver/deprecated/i2s_legacy.c +++ b/components/driver/deprecated/i2s_legacy.c @@ -654,12 +654,12 @@ static uint32_t i2s_config_source_clock(i2s_port_t i2s_num, bool use_apll, uint3 /* In APLL mode, there is no sclk but only mclk, so return 0 here to indicate APLL mode */ return real_freq; } - return I2S_LL_DEFAULT_PLL_CLK_FREQ; + return I2S_LL_DEFAULT_CLK_FREQ; #else if (use_apll) { ESP_LOGW(TAG, "APLL not supported on current chip, use I2S_CLK_SRC_DEFAULT as default clock source"); } - return I2S_LL_DEFAULT_PLL_CLK_FREQ; + return I2S_LL_DEFAULT_CLK_FREQ; #endif } diff --git a/components/driver/i2s/include/driver/i2s_pdm.h b/components/driver/i2s/include/driver/i2s_pdm.h index 2265c7908a97..d8bd632c9995 100644 --- a/components/driver/i2s/include/driver/i2s_pdm.h +++ b/components/driver/i2s/include/driver/i2s_pdm.h @@ -48,6 +48,24 @@ extern "C" { .bclk_div = 8, \ } +#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER +/** + * @brief PDM format in 2 slots(RX) + * @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode + * @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO + */ +#define I2S_PDM_RX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \ + .data_bit_width = bits_per_sample, \ + .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \ + .slot_mode = mono_or_stereo, \ + .slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ + I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \ + .hp_en = true, \ + .hp_cut_off_freq_hz = 35.5, \ + .amplify_num = 1, \ /* TODO: maybe need an enum */ +} +#endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER + /** * @brief I2S slot configuration for pdm rx mode */ @@ -58,6 +76,12 @@ typedef struct { i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */ /* Particular fields */ i2s_pdm_slot_mask_t slot_mask; /*!< Choose the slots to activate */ +#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER + bool hp_en; /*!< High pass filter enable */ + float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */ + uint32_t amplify_num; /*!< The amplification number of the final conversion result, range 1~15, default 1 */ +#endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER + } i2s_pdm_rx_slot_config_t; /** diff --git a/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c b/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c index e9e81cde62b0..a419ea6c2e15 100644 --- a/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c +++ b/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c @@ -803,7 +803,9 @@ TEST_CASE("I2S_default_PLL_clock_test", "[i2s]") TEST_ESP_OK(i2s_new_channel(&chan_cfg, NULL, &rx_handle)); TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg)); +#if SOC_I2S_SUPPORTS_PLL_F160M || SOC_I2S_SUPPORTS_PLL_F96M i2s_test_common_sample_rate(rx_handle, &std_cfg.clk_cfg); +#endif // SOC_I2S_SUPPORTS_PLL_F160M || SOC_I2S_SUPPORTS_PLL_F96M #if SOC_I2S_SUPPORTS_XTAL std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_XTAL; i2s_test_common_sample_rate(rx_handle, &std_cfg.clk_cfg); diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk.c b/components/esp_hw_support/port/esp32p4/rtc_clk.c index 2abac0e6fb98..6c67021a9b29 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk.c @@ -368,6 +368,22 @@ uint32_t rtc_clk_apb_freq_get(void) return rtc_clk_ahb_freq_get() / clk_ll_apb_get_divider() * MHZ; } +void rtc_clk_apll_enable(bool enable) +{ + // TODO: IDF-7526 +} + +uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2) +{ + // TODO: IDF-7526 + return 0; +} + +void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2) +{ + // TODO: IDF-7526 +} + void rtc_dig_clk8m_enable(void) { clk_ll_rc_fast_digi_enable(); diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 8f621d92e21d..c03f56ce028a 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -48,7 +48,7 @@ extern "C" { #define I2S_LL_RX_EVENT_MASK I2S_LL_EVENT_RX_EOF #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz -#define I2S_LL_DEFAULT_PLL_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** * @brief Enable DMA descriptor owner check diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 6f8dac94ee9d..1bf9d1ecc40e 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -34,7 +34,7 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz -#define I2S_LL_DEFAULT_PLL_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** * @brief I2S module general init, enable I2S clock. diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index 687ef3162fb2..33da02f677ae 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -35,7 +35,7 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz -#define I2S_LL_DEFAULT_PLL_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** * @brief I2S module general init, enable I2S clock. diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 8ebfa8518bb5..c7cd73dd4fc4 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -36,7 +36,7 @@ extern "C" { #define I2S_LL_PLL_F96M_CLK_FREQ (96 * 1000000) // PLL_F96M_CLK: 96MHz #define I2S_LL_PLL_F64M_CLK_FREQ (64 * 1000000) // PLL_F64M_CLK: 64MHz -#define I2S_LL_DEFAULT_PLL_CLK_FREQ I2S_LL_PLL_F96M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F96M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** * @brief I2S module general init, enable I2S clock. diff --git a/components/hal/esp32p4/include/i2s_ll.h b/components/hal/esp32p4/include/i2s_ll.h new file mode 100644 index 000000000000..c2ce486e048d --- /dev/null +++ b/components/hal/esp32p4/include/i2s_ll.h @@ -0,0 +1,1244 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for I2S register operations +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in hal/include/hal/readme.md + ******************************************************************************/ + +#pragma once +#include +#include "hal/misc.h" +#include "hal/assert.h" +#include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" +#include "soc/pcr_struct.h" +#include "hal/i2s_types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2S_LL_GET_HW(num) (((num) == 0)? (&I2S0) : ((num) == 1) ? (&I2S1) : (&I2S2)) + +#define I2S_LL_TDM_CH_MASK (0xffff) +#define I2S_LL_PDM_BCK_FACTOR (64) + +#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) +#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) + +#define I2S_LL_XTAL_CLK_FREQ (40 * 1000000) // XTAL_CLK: 40MHz +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_XTAL_CLK_FREQ // No PLL clock source on P4, use XTAL as default + +/** + * @brief I2S clock configuration structure + * @note Fmclk = Fsclk /(integ+numer/denom) + */ +typedef struct { + uint16_t integ; // Integer part of I2S module clock divider + uint16_t denom; // Denominator part of I2S module clock divider + uint16_t numer; // Numerator part of I2S module clock divider +} i2s_ll_mclk_div_t; + +/** + * @brief I2S module general init, enable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +{ + // The clock gate enabling is moved to `periph_module_enable` + (void)hw; +} + +/** + * @brief I2S module disable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + // The clock gate disabling is moved to `periph_module_disable` + (void)hw; +} + +/** + * @brief Enable I2S tx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 1; +} + +/** + * @brief Enable I2S rx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 1; +} + +/** + * @brief Disable I2S tx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 0; +} + +/** + * @brief Disable I2S rx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 0; +} + +/** + * @brief I2S mclk use tx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 0; +} + +/** + * @brief I2S mclk use rx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_mclk_bind_to_rx_clk(i2s_dev_t *hw) +{ + (void)hw; + PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 1; +} + +/** + * @brief Enable I2S TX slave mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slave_en Set true to enable slave mode + */ +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) +{ + hw->tx_conf.tx_slave_mod = slave_en; +} + +/** + * @brief Enable I2S RX slave mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slave_en Set true to enable slave mode + */ +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) +{ + hw->rx_conf.rx_slave_mod = slave_en; +} + +/** + * @brief Reset I2S TX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) +{ + hw->tx_conf.tx_reset = 1; + hw->tx_conf.tx_reset = 0; +} + +/** + * @brief Reset I2S RX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) +{ + hw->rx_conf.rx_reset = 1; + hw->rx_conf.rx_reset = 0; +} + +/** + * @brief Reset I2S TX FIFO + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) +{ + hw->tx_conf.tx_fifo_reset = 1; + hw->tx_conf.tx_fifo_reset = 0; +} + +/** + * @brief Reset I2S RX FIFO + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) +{ + hw->rx_conf.rx_fifo_reset = 1; + hw->rx_conf.rx_fifo_reset = 0; +} + +/** + * @brief Set TX source clock + * + * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock. + */ +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) +{ + (void)hw; + switch (src) + { + case I2S_CLK_SRC_XTAL: + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 0; + break; + case I2S_CLK_SRC_APLL: + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 1; + break; + default: + HAL_ASSERT(false && "unsupported clock source"); + break; + } +} + +/** + * @brief Set RX source clock + * + * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock + */ +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) +{ + (void)hw; + switch (src) + { + case I2S_CLK_SRC_XTAL: + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 0; + break; + case I2S_CLK_SRC_APLL: + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 1; + break; + default: + HAL_ASSERT(false && "unsupported clock source"); + break; + } +} + +/** + * @brief Set I2S tx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx bck div num + */ +static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->tx_conf.tx_bck_div_num = val - 1; +} + +/** + * @brief Set I2S tx raw clock division + * + * @param hw Peripheral I2S hardware instance address. + * @param div_int Integer part of division + * @param x div x + * @param y div y + * @param z div z + * @param yn1 yn1 + */ +static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) +{ + (void)hw; + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); + typeof(PCR.i2s_tx_clkm_div_conf) div = {}; + div.i2s_tx_clkm_div_x = x; + div.i2s_tx_clkm_div_y = y; + div.i2s_tx_clkm_div_z = z; + div.i2s_tx_clkm_div_yn1 = yn1; + PCR.i2s_tx_clkm_div_conf.val = div.val; +} + +/** + * @brief Set I2S rx raw clock division + * + * @param hw Peripheral I2S hardware instance address. + * @param div_int Integer part of division + * @param x div x + * @param y div y + * @param z div z + * @param yn1 yn1 + */ +static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) +{ + (void)hw; + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); + typeof(PCR.i2s_rx_clkm_div_conf) div = {}; + div.i2s_rx_clkm_div_x = x; + div.i2s_rx_clkm_div_y = y; + div.i2s_rx_clkm_div_z = z; + div.i2s_rx_clkm_div_yn1 = yn1; + PCR.i2s_rx_clkm_div_conf.val = div.val; +} + +/** + * @brief Configure I2S TX module clock divider + * + * @param hw Peripheral I2S hardware instance address. + * @param mclk_div The mclk division coefficients + */ +static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) +{ + /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate + * Set to particular coefficients first then update to the target coefficients, + * otherwise the clock division might be inaccurate. + * the general idea is to set a value that impossible to calculate from the regular decimal */ + i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); + + uint32_t div_x = 0; + uint32_t div_y = 0; + uint32_t div_z = 0; + uint32_t div_yn1 = 0; + /* If any of denominator and numerator is 0, set all the coefficients to 0 */ + if (mclk_div->denom && mclk_div->numer) { + div_yn1 = mclk_div->numer * 2 > mclk_div->denom; + div_z = div_yn1 ? mclk_div->denom - mclk_div->numer : mclk_div->numer; + div_x = mclk_div->denom / div_z - 1; + div_y = mclk_div->denom % div_z; + } + i2s_ll_tx_set_raw_clk_div(hw, mclk_div->integ, div_x, div_y, div_z, div_yn1); +} + +/** + * @brief Set I2S rx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx bck div num + */ +static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->rx_conf.rx_bck_div_num = val - 1; +} + +/** + * @brief Configure I2S RX module clock divider + * @note mclk on ESP32 is shared by both TX and RX channel + * + * @param hw Peripheral I2S hardware instance address. + * @param mclk_div The mclk division coefficients + */ +static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) +{ + /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate + * Set to particular coefficients first then update to the target coefficients, + * otherwise the clock division might be inaccurate. + * the general idea is to set a value that impossible to calculate from the regular decimal */ + i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); + + uint32_t div_x = 0; + uint32_t div_y = 0; + uint32_t div_z = 0; + uint32_t div_yn1 = 0; + /* If any of denominator and numerator is 0, set all the coefficients to 0 */ + if (mclk_div->denom && mclk_div->numer) { + div_yn1 = mclk_div->numer * 2 > mclk_div->denom; + div_z = div_yn1 ? mclk_div->denom - mclk_div->numer : mclk_div->numer; + div_x = mclk_div->denom / div_z - 1; + div_y = mclk_div->denom % div_z; + } + i2s_ll_rx_set_raw_clk_div(hw, mclk_div->integ, div_x, div_y, div_z, div_yn1); +} + +/** + * @brief Start I2S TX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_start(i2s_dev_t *hw) +{ + // Have to update registers before start + hw->tx_conf.tx_update = 1; + while (hw->tx_conf.tx_update); + hw->tx_conf.tx_start = 1; +} + +/** + * @brief Start I2S RX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_start(i2s_dev_t *hw) +{ + // Have to update registers before start + hw->rx_conf.rx_update = 1; + while (hw->rx_conf.rx_update); + hw->rx_conf.rx_start = 1; +} + +/** + * @brief Stop I2S TX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) +{ + hw->tx_conf.tx_start = 0; +} + +/** + * @brief Stop I2S RX + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) +{ + hw->rx_conf.rx_start = 0; +} + +/** + * @brief Configure TX WS signal width + * + * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle + */ +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) +{ + hw->tx_conf1.tx_tdm_ws_width = width - 1; +} + +/** + * @brief Configure RX WS signal width + * + * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle + */ +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) +{ + hw->rx_conf1.rx_tdm_ws_width = width - 1; +} + +/** + * @brief Configure the received length to trigger in_suc_eof interrupt + * + * @param hw Peripheral I2S hardware instance address. + * @param eof_num the byte length to trigger in_suc_eof interrupt + */ +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) +{ + hw->rx_eof_num.rx_eof_num = eof_num; +} + +/** + * @brief Congfigure TX chan bit and audio data bit + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width + */ +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) +{ + hw->tx_conf1.tx_bits_mod = data_bit - 1; + hw->tx_conf1.tx_tdm_chan_bits = chan_bit - 1; +} + +/** + * @brief Congfigure RX chan bit and audio data bit + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width + */ +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) +{ + hw->rx_conf1.rx_bits_mod = data_bit - 1; + hw->rx_conf1.rx_tdm_chan_bits = chan_bit - 1; +} + +/** + * @brief Configure RX half_sample_bit + * + * @param hw Peripheral I2S hardware instance address. + * @param half_sample_bits half sample bit width + */ +static inline void i2s_ll_tx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_conf1, tx_half_sample_bits, half_sample_bits - 1); +} + +/** + * @brief Configure RX half_sample_bit + * + * @param hw Peripheral I2S hardware instance address. + * @param half_sample_bits half sample bit width + */ +static inline void i2s_ll_rx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_conf1, rx_half_sample_bits, half_sample_bits - 1); +} + +/** + * @brief Enable TX MSB shift, the data will be launch at the first BCK clock + * + * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift + */ +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) +{ + hw->tx_conf.tx_msb_shift = msb_shift_enable; +} + +/** + * @brief Enable RX MSB shift, the data will be launch at the first BCK clock + * + * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift + */ +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) +{ + hw->rx_conf.rx_msb_shift = msb_shift_enable; +} + +/** + * @brief Configure TX total chan number + * + * @param hw Peripheral I2S hardware instance address. + * @param total_num Total chan number + */ +static inline void i2s_ll_tx_set_chan_num(i2s_dev_t *hw, int total_num) +{ + hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1; +} + +/** + * @brief Configure RX total chan number + * + * @param hw Peripheral I2S hardware instance address. + * @param total_num Total chan number + */ +static inline void i2s_ll_rx_set_chan_num(i2s_dev_t *hw, int total_num) +{ + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1; +} + +/** + * @brief Set the bimap of the active TX chan, only the active chan can launch audio data. + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_mask mask of tx active chan + */ +static inline void i2s_ll_tx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +{ + uint32_t tdm_ctrl = hw->tx_tdm_ctrl.val; + tdm_ctrl &= 0xFFFF0000; + tdm_ctrl |= chan_mask; + hw->tx_tdm_ctrl.val = tdm_ctrl; +} + +/** + * @brief Set the bimap of the active RX chan, only the active chan can receive audio data. + * + * @param hw Peripheral I2S hardware instance address. + * @param chan_mask mask of rx active chan + */ +static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +{ + uint32_t tdm_ctrl = hw->rx_tdm_ctrl.val; + tdm_ctrl &= 0xFFFF0000; + tdm_ctrl |= chan_mask; + hw->rx_tdm_ctrl.val = tdm_ctrl; +} + +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_mask select slot to send data + */ +static inline void i2s_ll_tx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = 1; // tx_tdm_tot_chan_num = 2 slots - 1 = 1 + uint32_t chan_mask = 0; + switch (slot_mask) + { + case I2S_STD_SLOT_LEFT: + chan_mask |= 0x01; + break; + case I2S_STD_SLOT_RIGHT: + chan_mask |= 0x02; + break; + case I2S_STD_SLOT_BOTH: + chan_mask |= 0x03; + break; + default: + break; + } + i2s_ll_tx_set_active_chan_mask(hw, chan_mask); +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param slot_mask select slot to receive data + */ +static inline void i2s_ll_rx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask) +{ + /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot + * Otherwise always enable the first two slots */ + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = 1; // rx_tdm_tot_chan_num = 2 slots - 1 = 1 + uint32_t chan_mask = 0; + switch (slot_mask) + { + case I2S_STD_SLOT_LEFT: + chan_mask |= 0x01; + break; + case I2S_STD_SLOT_RIGHT: + chan_mask |= 0x02; + break; + case I2S_STD_SLOT_BOTH: + chan_mask |= 0x03; + break; + default: + break; + } + i2s_ll_rx_set_active_chan_mask(hw, chan_mask); +} + +/** + * @brief PDM slot mode + * + * @param hw Peripheral I2S hardware instance address. + * @param mod Channel mode + * while tx_ws_idle_pol = 0: + * 0: stereo + * 1: Both slots transmit left + * 2: Both slots transmit right + * 3: Left transmits `conf_single_data` right transmits data + * 4: Right transmits `conf_single_data` left transmits data + * while tx_ws_idle_pol = 1: + 0: stereo + * 1: Both slots transmit right + * 2: Both slots transmit left + * 3: Right transmits `conf_single_data` left transmits data + * 4: Left transmits `conf_single_data` right transmits data + */ +static inline void i2s_ll_tx_set_pdm_chan_mod(i2s_dev_t *hw, uint32_t mod) +{ + hw->tx_conf.tx_chan_mod = mod; +} + +/** + * @brief Set TX WS signal pol level + * + * @param hw Peripheral I2S hardware instance address. + * @param ws_pol_level pin level of WS(output) when receiving left channel data + */ +static inline void i2s_ll_tx_set_ws_idle_pol(i2s_dev_t *hw, bool ws_pol_level) +{ + hw->tx_conf.tx_ws_idle_pol = ws_pol_level; +} + +/** + * @brief Set RX WS signal pol level + * + * @param hw Peripheral I2S hardware instance address. + * @param ws_pol_level pin level of WS(input) when receiving left channel data + */ +static inline void i2s_ll_rx_set_ws_idle_pol(i2s_dev_t *hw, bool ws_pol_level) +{ + hw->rx_conf.rx_ws_idle_pol = ws_pol_level; +} + +/** + * @brief Enable I2S TX TDM mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_tdm(i2s_dev_t *hw) +{ + hw->tx_conf.tx_pdm_en = false; + hw->tx_conf.tx_tdm_en = true; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = false; +} + +/** + * @brief Enable I2S RX TDM mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_tdm(i2s_dev_t *hw) +{ + hw->rx_conf.rx_pdm_en = false; + hw->rx_conf.rx_tdm_en = true; + hw->rx_pdm2pcm_conf.rx_pdm2pcm_en = false; +} + +/** + * @brief Enable I2S TX STD mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw) +{ + i2s_ll_tx_enable_tdm(hw); +} + +/** + * @brief Enable I2S RX STD mode + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw) +{ + i2s_ll_rx_enable_tdm(hw); +} + +/** + * @brief Enable TX PDM mode. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw) +{ + hw->tx_conf.tx_pdm_en = true; + hw->tx_conf.tx_tdm_en = false; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = true; +} + +/** + * @brief Set I2S TX PDM prescale + * + * @param hw Peripheral I2S hardware instance address. + * @param prescale I2S TX PDM prescale + */ +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_pcm2pdm_conf, tx_pdm_prescale, prescale); +} + +/** + * @brief Set I2S TX PDM high pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM low pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_lp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sinc filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sinc_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sigma-delta filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM high pass filter param0 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + I2S_TX_IIR_HP_MULT12_0[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param0(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_0 = param; +} + +/** + * @brief Set I2S TX PDM high pass filter param5 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + I2S_TX_IIR_HP_MULT12_5[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param5(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_5 = param; +} + +/** + * @brief Enable I2S TX PDM high pass filter + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable I2S TX PDM high pass filter, set false to bypass it + */ +static inline void i2s_ll_tx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_bypass = !enable; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither(i2s_dev_t *hw, uint32_t dither) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither = dither; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither2 I2S TX PDM sigmadelta dither2 value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither2 = dither2; +} + +/** + * @brief Set the PDM TX over sampling ratio + * + * @param hw Peripheral I2S hardware instance address. + * @param ovr Over sampling ratio + */ +static inline void i2s_ll_tx_set_pdm_over_sample_ratio(i2s_dev_t *hw, uint32_t ovr) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sinc_osr2 = ovr; +} + +/** + * @brief Configure I2S TX PDM sample rate + * Fpdm = 64*Fpcm*fp/fs + * + * @param hw Peripheral I2S hardware instance address. + * @param fp The fp value of TX PDM filter module group0. + * @param fs The fs value of TX PDM filter module group0. + */ +static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t fs) +{ + hw->tx_pcm2pdm_conf1.tx_pdm_fp = fp; + hw->tx_pcm2pdm_conf1.tx_pdm_fs = fs; +} + +/** + * @brief Get I2S TX PDM fp configuration paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fp configuration paramater + */ +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) +{ + return hw->tx_pcm2pdm_conf1.tx_pdm_fp; +} + +/** + * @brief Get I2S TX PDM fs configuration paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fs configuration paramater + */ +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) +{ + return hw->tx_pcm2pdm_conf1.tx_pdm_fs; +} + +/** + * @brief Enable RX PDM mode. + * + * @param hw Peripheral I2S hardware instance address. + * @param pdm_enable Set true to RX enable PDM mode + */ +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) +{ + hw->rx_conf.rx_pdm_en = pdm_enable; + hw->rx_conf.rx_tdm_en = !pdm_enable; + hw->rx_pdm2pcm_conf.rx_pdm2pcm_en = pdm_enable; +} + +/** + * @brief Configure RX PDM downsample + * + * @param hw Peripheral I2S hardware instance address. + * @param dsr PDM downsample configuration paramater + */ +static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) +{ + hw->rx_pdm2pcm_conf.rx_pdm_sinc_dsr_16_en = dsr; +} + +/** + * @brief Get RX PDM downsample configuration + * + * @param hw Peripheral I2S hardware instance address. + * @param dsr Pointer to accept PDM downsample configuration + */ +static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) +{ + *dsr = (i2s_pdm_dsr_t)hw->rx_pdm2pcm_conf.rx_pdm_sinc_dsr_16_en; +} + +/** + * @brief Configure RX PDM amplify number + * @note This is the amplification number of the digital amplifier, + * which is added after the PDM to PCM conversion result and mainly used for + * amplify the small PDM signal under the VAD scenario + * pcm_result = pdm_input * amplify_num + * pcm_result = 0 if amplify_num = 0 + * + * @param hw Peripheral I2S hardware instance address. + * @param amp_num PDM RX amplify number + */ +static inline void i2s_ll_rx_set_pdm_amplify_num(i2s_dev_t *hw, uint32_t amp_num) +{ + hw->rx_pdm2pcm_conf.rx_pdm2pcm_amplify_num = amp_num; +} + + +/** + * @brief Set I2S RX PDM high pass filter param0 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM RX IIR_HP filter stage 1 is (504 + I2S_RX_IIR_HP_MULT12_0[2:0]) + */ +static inline void i2s_ll_rx_set_pdm_hp_filter_param0(i2s_dev_t *hw, uint32_t param) +{ + hw->rx_pdm2pcm_conf.rx_iir_hp_mult12_0 = param; +} + +/** + * @brief Set I2S RX PDM high pass filter param5 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM RX IIR_HP filter stage 2 is (504 + I2S_RX_IIR_HP_MULT12_5[2:0]) + */ +static inline void i2s_ll_rx_set_pdm_hp_filter_param5(i2s_dev_t *hw, uint32_t param) +{ + hw->rx_pdm2pcm_conf.rx_iir_hp_mult12_5 = param; +} + +/** + * @brief Enable I2S RX PDM high pass filter + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable I2S RX PDM high pass filter, set false to bypass it + */ +static inline void i2s_ll_rx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) +{ + hw->rx_pdm2pcm_conf.rx_pdm_hp_bypass = !enable; +} + + +/** + * @brief Configura TX a/u-law decompress or compress + * + * @param hw Peripheral I2S hardware instance address. + * @param pcm_cfg PCM configuration paramater + */ +static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) +{ + hw->tx_conf.tx_pcm_conf = pcm_cfg; + hw->tx_conf.tx_pcm_bypass = !pcm_cfg; +} + +/** + * @brief Configure RX a/u-law decompress or compress + * + * @param hw Peripheral I2S hardware instance address. + * @param pcm_cfg PCM configuration paramater + */ +static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) +{ + hw->rx_conf.rx_pcm_conf = pcm_cfg; + hw->rx_conf.rx_pcm_bypass = !pcm_cfg; +} + +/** + * @brief Enable TX audio data left alignment + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable left alignment + */ +static inline void i2s_ll_tx_enable_left_align(i2s_dev_t *hw, bool ena) +{ + hw->tx_conf.tx_left_align = ena; +} + +/** + * @brief Enable RX audio data left alignment + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable left alignment + */ +static inline void i2s_ll_rx_enable_left_align(i2s_dev_t *hw, bool ena) +{ + hw->rx_conf.rx_left_align = ena; +} + +/** + * @brief Enable TX big endian mode + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable big endian mode + */ +static inline void i2s_ll_rx_enable_big_endian(i2s_dev_t *hw, bool ena) +{ + hw->rx_conf.rx_big_endian = ena; +} + +/** + * @brief Enable RX big endian mode + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to enable big endian mode + */ +static inline void i2s_ll_tx_enable_big_endian(i2s_dev_t *hw, bool ena) +{ + hw->tx_conf.tx_big_endian = ena; +} + +/** + * @brief Configure TX bit order + * + * @param hw Peripheral I2S hardware instance address. + * @param lsb_order_ena Set true to enable LSB bit order + */ +static inline void i2s_ll_tx_set_bit_order(i2s_dev_t *hw, bool lsb_order_ena) +{ + hw->tx_conf.tx_bit_order = lsb_order_ena; +} + +/** + * @brief Configure RX bit order + * + * @param hw Peripheral I2S hardware instance address. + * @param lsb_order_ena Set true to enable LSB bit order + */ +static inline void i2s_ll_rx_set_bit_order(i2s_dev_t *hw, bool lsb_order_ena) +{ + hw->rx_conf.rx_bit_order = lsb_order_ena; +} + +/** + * @brief Configure TX skip mask enable + * + * @param hw Peripheral I2S hardware instance address. + * @param skip_mask_ena Set true to skip inactive channels. + */ +static inline void i2s_ll_tx_set_skip_mask(i2s_dev_t *hw, bool skip_mask_ena) +{ + hw->tx_tdm_ctrl.tx_tdm_skip_msk_en = skip_mask_ena; +} + + +/** + * @brief Configure single data + * + * @param hw Peripheral I2S hardware instance address. + * @param data Single data to be set + */ +static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) +{ + hw->conf_single_data.val = 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. + */ +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 + * + * @param hw Peripheral I2S hardware instance address. + * @param ena Set true to share BCK and WS signal for tx module and rx module. + */ +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool ena) +{ + hw->tx_conf.sig_loopback = ena; +} + +/** + * @brief PDM TX DMA data take mode + * + * @param hw Peripheral I2S hardware instance address. + * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) + * @param is_fst_valid Whether take the DMA data at the first half period + * Only take effet when 'is_mono' is true + */ +static inline void i2s_ll_tx_pdm_dma_take_mode(i2s_dev_t *hw, bool is_mono, bool is_fst_valid) +{ + hw->tx_conf.tx_mono = is_mono; + hw->tx_conf.tx_mono_fst_vld = is_fst_valid; +} + +/** + * @brief PDM TX slot mode + * @note Mode Left Slot Right Slot Chan Mode WS Pol + * ----------------------------------------------------------------- + * Stereo Left Right 0 x + * ----------------------------------------------------------------- + * Mono Left Left 1 0 + * Mono Right Right 2 0 + * Mono Single Right 3 0 + * Mono Left Single 4 0 + * ----------------------------------------------------------------- + * Mono Right Right 1 1 + * Mono Left Left 2 1 + * Mono Left Single 3 1 + * Mono Single Right 4 1 + * @note The 'Single' above means always sending the value of `conf_single_data` reg + * The default value of `conf_single_data` reg is '0', it is not public for now + * + * @param hw Peripheral I2S hardware instance address. + * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) + * @param is_copy Whether the un-selected slot copies the data from the selected one + * If not, the un-selected slot will transmit the data from 'conf_single_data' + * @param mask The slot mask to selet the slot + */ +static inline void i2s_ll_tx_pdm_slot_mode(i2s_dev_t *hw, bool is_mono, bool is_copy, i2s_pdm_slot_mask_t mask) +{ + if (is_mono) { + /* The default tx_ws_idle_pol is false */ + if (is_copy) { + hw->tx_conf.tx_chan_mod = mask == I2S_PDM_SLOT_LEFT ? 1 : 2; + } else { + hw->tx_conf.tx_chan_mod = mask == I2S_PDM_SLOT_LEFT ? 4 : 3; + } + } else { + hw->tx_conf.tx_chan_mod = 0; + } +} + +/** + * @brief PDM TX line mode + * @note Mode DAC Mode 2 lines output + * ------------------------------------------- + * PDM codec 0 1 + * DAC 1-line 1 0 + * DAC 2-line 1 1 + * + * @param hw Peripheral I2S hardware instance address. + * @param line_mode PDM TX line mode + */ +static inline void i2s_ll_tx_pdm_line_mode(i2s_dev_t *hw, i2s_pdm_tx_line_mode_t line_mode) +{ + hw->tx_pcm2pdm_conf.tx_pdm_dac_mode_en = line_mode > I2S_PDM_TX_ONE_LINE_CODEC; + hw->tx_pcm2pdm_conf.tx_pdm_dac_2out_en = line_mode != I2S_PDM_TX_ONE_LINE_DAC; +} + +/** + * @brief Reset TX FIFO synchronization counter + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset_fifo_sync_counter(i2s_dev_t *hw) +{ + hw->fifo_cnt.tx_fifo_cnt_rst = 1; + hw->fifo_cnt.tx_fifo_cnt_rst = 0; +} + +/** + * @brief Get TX FIFO synchronization count value + * + * @param hw Peripheral I2S hardware instance address. + * @return + * count value + */ +static inline uint32_t i2s_ll_tx_get_fifo_sync_count(i2s_dev_t *hw) +{ + return hw->fifo_cnt.tx_fifo_cnt; +} + +/** + * @brief Reset TX bclk synchronization counter + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset_bclk_sync_counter(i2s_dev_t *hw) +{ + hw->bck_cnt.tx_bck_cnt_rst = 1; + hw->bck_cnt.tx_bck_cnt_rst = 0; +} + +/** + * @brief Get TX bclk synchronization count value + * + * @param hw Peripheral I2S hardware instance address. + * @return + * count value + */ +static inline void i2s_ll_tx_get_bclk_sync_count(i2s_dev_t *hw) +{ + return hw->bck_cnt.tx_bck_cnt; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 4b419047e5a5..30d481d9c867 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -45,7 +45,7 @@ extern "C" { #define I2S_LL_RX_EVENT_MASK I2S_LL_EVENT_RX_EOF #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz -#define I2S_LL_DEFAULT_PLL_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** * @brief Enable DMA descriptor owner check diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 1beb845b2dbd..4880c6850da1 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -35,7 +35,7 @@ extern "C" { #define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz -#define I2S_LL_DEFAULT_PLL_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT +#define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** * @brief I2S module general init, enable I2S clock. diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index ee3c94c29c24..1803bd51f8c9 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -10,7 +10,7 @@ #include "soc/soc.h" #include "hal/i2s_hal.h" -#if SOC_I2S_HW_VERSION_2 && SOC_I2S_SUPPORTS_PDM_TX +#if SOC_I2S_HW_VERSION_2 && (SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER) /* PDM tx high pass filter cut-off frequency and coefficients list * [0]: cut-off frequency; [1]: param0; [2]: param5 */ static const float cut_off_coef[21][3] = { @@ -22,6 +22,22 @@ static const float cut_off_coef[21][3] = { {63, 4, 7}, {58, 5, 6}, {49, 5, 7}, {46, 6, 6}, {35.5, 6, 7}, {23.3, 7, 7} }; + +static void s_i2s_hal_get_cut_off_coef(float freq, uint32_t *param0, uint32_t *param5) +{ + uint8_t cnt = 0; + float min = 1000; + /* Find the closest cut-off frequency and its coefficients */ + for (int i = 0; i < 21; i++) { + float tmp = cut_off_coef[i][0] < freq ? freq - cut_off_coef[i][0] : cut_off_coef[i][0] - freq; + if (tmp < min) { + min = tmp; + cnt = i; + } + } + *param0 = (uint32_t)cut_off_coef[cnt][1]; + *param5 = (uint32_t)cut_off_coef[cnt][2]; +} #endif /** @@ -183,20 +199,12 @@ void i2s_hal_pdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha i2s_ll_tx_set_ws_idle_pol(hal->dev, false); /* Slot mode seems not take effect according to the test, leave it default here */ i2s_ll_tx_pdm_slot_mode(hal->dev, is_mono, false, I2S_PDM_SLOT_BOTH); - uint8_t cnt = 0; - float min = 1000; - float expt_cut_off = slot_cfg->pdm_tx.hp_cut_off_freq_hz; - /* Find the closest cut-off frequency and its coefficients */ - for (int i = 0; i < 21; i++) { - float tmp = cut_off_coef[i][0] < expt_cut_off ? expt_cut_off - cut_off_coef[i][0] : cut_off_coef[i][0] - expt_cut_off; - if (tmp < min) { - min = tmp; - cnt = i; - } - } + uint32_t param0; + uint32_t param5; + s_i2s_hal_get_cut_off_coef(slot_cfg->pdm_tx.hp_cut_off_freq_hz, ¶m0, ¶m5); i2s_ll_tx_enable_pdm_hp_filter(hal->dev, slot_cfg->pdm_tx.hp_en); - i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, cut_off_coef[cnt][1]); - i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, cut_off_coef[cnt][2]); + i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, param0); + i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, param5); i2s_ll_tx_set_pdm_sd_dither(hal->dev, slot_cfg->pdm_tx.sd_dither); i2s_ll_tx_set_pdm_sd_dither2(hal->dev, slot_cfg->pdm_tx.sd_dither2); #endif @@ -233,7 +241,18 @@ void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha uint32_t slot_mask = slot_cfg->slot_mode == I2S_SLOT_MODE_STEREO ? I2S_PDM_SLOT_BOTH : slot_cfg->pdm_rx.slot_mask; #endif // SOC_I2S_SUPPORTS_PDM_RX > 1 i2s_ll_rx_set_active_chan_mask(hal->dev, slot_mask); -#endif // SOC_I2S_SUPPORTS_PDM_RX +#endif // SOC_I2S_HW_VERSION_1 + +#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER // TODO: add this macro to soc_caps + uint32_t param0; + uint32_t param5; + s_i2s_hal_get_cut_off_coef(slot_cfg->pdm_rx.hp_cut_off_freq_hz, ¶m0, ¶m5); + i2s_ll_rx_enable_pdm_hp_filter(hal->dev, slot_cfg->pdm_rx.hp_en); + i2s_ll_rx_set_pdm_hp_filter_param0(hal->dev, param0); + i2s_ll_rx_set_pdm_hp_filter_param5(hal->dev, param5); + /* Set the amplification number, the default and the minimum value is 1. 0 will mute the channel */ + i2s_ll_rx_set_pdm_amplify_num(hal->dev, slot_cfg->pdm_rx.amplify_num ? slot_cfg->pdm_rx.amplify_num : 1); +#endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER } void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal) diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index e1286b876fe9..e2957e5cc440 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -91,7 +91,13 @@ typedef struct { /* PDM TX configurations */ struct { i2s_pdm_slot_mask_t slot_mask; /*!< Choose the slots to activate */ - } pdm_rx; /*!< Specific configurations for PDM TX mode */ +#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER + bool hp_en; /*!< High pass filter enable */ + float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */ + uint32_t amplify_num; /*!< The amplification number of the final conversion result */ +#endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER + + } pdm_rx; /*!< Specific configurations for PDM RX mode */ #endif }; diff --git a/components/soc/esp32c6/include/soc/i2s_struct.h b/components/soc/esp32c6/include/soc/i2s_struct.h index e2e4de298cf8..f7b7f069ad96 100644 --- a/components/soc/esp32c6/include/soc/i2s_struct.h +++ b/components/soc/esp32c6/include/soc/i2s_struct.h @@ -240,34 +240,6 @@ typedef union { uint32_t val; } i2s_rx_conf1_reg_t; -/** Type of rx_clkm_conf register - * I2S RX clock configure register - */ -typedef union { - struct { - /** rx_clkm_div_num : R/W; bitpos: [7:0]; default: 2; - * Integral I2S clock divider value - */ - uint32_t rx_clkm_div_num:8; - uint32_t reserved_8:18; - /** rx_clk_active : R/W; bitpos: [26]; default: 0; - * I2S Rx module clock enable signal. - */ - uint32_t rx_clk_active:1; - /** rx_clk_sel : R/W; bitpos: [28:27]; default: 0; - * Select I2S Rx module source clock. 0: XTAL clock. 1: PLL240M. 2: PLL160M. 3: I2S_MCLK_in. - */ - uint32_t rx_clk_sel:2; - /** mclk_sel : R/W; bitpos: [29]; default: 0; - * 0: UseI2S Tx module clock as I2S_MCLK_OUT. 1: UseI2S Rx module clock as - * I2S_MCLK_OUT. - */ - uint32_t mclk_sel:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} i2s_rx_clkm_conf_reg_t; - /** Type of tx_pcm2pdm_conf register * I2S TX PCM2PDM configuration register */ @@ -609,37 +581,6 @@ typedef union { uint32_t val; } i2s_tx_conf1_reg_t; -/** Type of tx_clkm_conf register - * I2S TX clock configure register - */ -typedef union { - struct { - /** tx_clkm_div_num : R/W; bitpos: [7:0]; default: 2; - * Integral I2S TX clock divider value. f_I2S_CLK = f_I2S_CLK_S/(N+b/a). There will be - * (a-b) * n-div and b * (n+1)-div. So the average combination will be: for b <= - * a/2, z * [x * n-div + (n+1)-div] + y * n-div. For b > a/2, z * [n-div + x * - * (n+1)-div] + y * (n+1)-div. - */ - uint32_t tx_clkm_div_num:8; - uint32_t reserved_8:18; - /** tx_clk_active : R/W; bitpos: [26]; default: 0; - * I2S Tx module clock enable signal. - */ - uint32_t tx_clk_active:1; - /** tx_clk_sel : R/W; bitpos: [28:27]; default: 0; - * Select I2S Tx module source clock. 0: XTAL clock. 1: PLL240M. 2: PLL160M. 3: - * I2S_MCLK_in. - */ - uint32_t tx_clk_sel:2; - /** clk_en : R/W; bitpos: [29]; default: 0; - * Set this bit to enable clk gate - */ - uint32_t clk_en:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} i2s_tx_clkm_conf_reg_t; - /** Type of tx_tdm_ctrl register * I2S TX TDM mode control register */ @@ -742,36 +683,6 @@ typedef union { /** Group: RX clock and timing registers */ -/** Type of rx_clkm_div_conf register - * I2S RX module clock divider configure register - */ -typedef union { - struct { - /** rx_clkm_div_z : R/W; bitpos: [8:0]; default: 0; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_Z is b. For b > a/2, the value of - * I2S_RX_CLKM_DIV_Z is (a-b). - */ - uint32_t rx_clkm_div_z:9; - /** rx_clkm_div_y : R/W; bitpos: [17:9]; default: 1; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of - * I2S_RX_CLKM_DIV_Y is (a%(a-b)). - */ - uint32_t rx_clkm_div_y:9; - /** rx_clkm_div_x : R/W; bitpos: [26:18]; default: 0; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value - * of I2S_RX_CLKM_DIV_X is (a/(a-b)) - 1. - */ - uint32_t rx_clkm_div_x:9; - /** rx_clkm_div_yn1 : R/W; bitpos: [27]; default: 0; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of - * I2S_RX_CLKM_DIV_YN1 is 1. - */ - uint32_t rx_clkm_div_yn1:1; - uint32_t reserved_28:4; - }; - uint32_t val; -} i2s_rx_clkm_div_conf_reg_t; - /** Type of rx_timing register * I2S RX timing control register */ @@ -813,36 +724,6 @@ typedef union { /** Group: TX clock and timing registers */ -/** Type of tx_clkm_div_conf register - * I2S TX module clock divider configure register - */ -typedef union { - struct { - /** tx_clkm_div_z : R/W; bitpos: [8:0]; default: 0; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_Z is b. For b > a/2, the value of - * I2S_TX_CLKM_DIV_Z is (a-b). - */ - uint32_t tx_clkm_div_z:9; - /** tx_clkm_div_y : R/W; bitpos: [17:9]; default: 1; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of - * I2S_TX_CLKM_DIV_Y is (a%(a-b)). - */ - uint32_t tx_clkm_div_y:9; - /** tx_clkm_div_x : R/W; bitpos: [26:18]; default: 0; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value - * of I2S_TX_CLKM_DIV_X is (a/(a-b)) - 1. - */ - uint32_t tx_clkm_div_x:9; - /** tx_clkm_div_yn1 : R/W; bitpos: [27]; default: 0; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of - * I2S_TX_CLKM_DIV_YN1 is 1. - */ - uint32_t tx_clkm_div_yn1:1; - uint32_t reserved_28:4; - }; - uint32_t val; -} i2s_tx_clkm_div_conf_reg_t; - /** Type of tx_timing register * I2S TX timing control register */ @@ -993,10 +874,7 @@ typedef struct i2s_dev_t { volatile i2s_tx_conf_reg_t tx_conf; volatile i2s_rx_conf1_reg_t rx_conf1; volatile i2s_tx_conf1_reg_t tx_conf1; - volatile i2s_rx_clkm_conf_reg_t rx_clkm_conf; - volatile i2s_tx_clkm_conf_reg_t tx_clkm_conf; - volatile i2s_rx_clkm_div_conf_reg_t rx_clkm_div_conf; - volatile i2s_tx_clkm_div_conf_reg_t tx_clkm_div_conf; + uint32_t reserved_030[4]; volatile i2s_tx_pcm2pdm_conf_reg_t tx_pcm2pdm_conf; volatile i2s_tx_pcm2pdm_conf1_reg_t tx_pcm2pdm_conf1; uint32_t reserved_048[2]; diff --git a/components/soc/esp32h2/include/soc/i2s_struct.h b/components/soc/esp32h2/include/soc/i2s_struct.h index f4ac17a3b075..34f876838f86 100644 --- a/components/soc/esp32h2/include/soc/i2s_struct.h +++ b/components/soc/esp32h2/include/soc/i2s_struct.h @@ -240,34 +240,6 @@ typedef union { uint32_t val; } i2s_rx_conf1_reg_t; -/** Type of rx_clkm_conf register - * I2S RX clock configure register - */ -typedef union { - struct { - /** rx_clkm_div_num : R/W; bitpos: [7:0]; default: 2; - * Integral I2S clock divider value - */ - uint32_t rx_clkm_div_num:8; - uint32_t reserved_8:18; - /** rx_clk_active : R/W; bitpos: [26]; default: 0; - * I2S Rx module clock enable signal. - */ - uint32_t rx_clk_active:1; - /** rx_clk_sel : R/W; bitpos: [28:27]; default: 0; - * Select I2S Rx module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: I2S_MCLK_in. - */ - uint32_t rx_clk_sel:2; - /** mclk_sel : R/W; bitpos: [29]; default: 0; - * 0: UseI2S Tx module clock as I2S_MCLK_OUT. 1: UseI2S Rx module clock as - * I2S_MCLK_OUT. - */ - uint32_t mclk_sel:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} i2s_rx_clkm_conf_reg_t; - /** Type of tx_pcm2pdm_conf register * I2S TX PCM2PDM configuration register */ @@ -607,37 +579,6 @@ typedef union { uint32_t val; } i2s_tx_conf1_reg_t; -/** Type of tx_clkm_conf register - * I2S TX clock configure register - */ -typedef union { - struct { - /** tx_clkm_div_num : R/W; bitpos: [7:0]; default: 2; - * Integral I2S TX clock divider value. f_I2S_CLK = f_I2S_CLK_S/(N+b/a). There will be - * (a-b) * n-div and b * (n+1)-div. So the average combination will be: for b <= - * a/2, z * [x * n-div + (n+1)-div] + y * n-div. For b > a/2, z * [n-div + x * - * (n+1)-div] + y * (n+1)-div. - */ - uint32_t tx_clkm_div_num:8; - uint32_t reserved_8:18; - /** tx_clk_active : R/W; bitpos: [26]; default: 0; - * I2S Tx module clock enable signal. - */ - uint32_t tx_clk_active:1; - /** tx_clk_sel : R/W; bitpos: [28:27]; default: 0; - * Select I2S Tx module source clock. 0: XTAL clock. 1: APLL. 2: CLK160. 3: - * I2S_MCLK_in. - */ - uint32_t tx_clk_sel:2; - /** clk_en : R/W; bitpos: [29]; default: 0; - * Set this bit to enable clk gate - */ - uint32_t clk_en:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} i2s_tx_clkm_conf_reg_t; - /** Type of tx_tdm_ctrl register * I2S TX TDM mode control register */ @@ -740,36 +681,6 @@ typedef union { /** Group: RX clock and timing registers */ -/** Type of rx_clkm_div_conf register - * I2S RX module clock divider configure register - */ -typedef union { - struct { - /** rx_clkm_div_z : R/W; bitpos: [8:0]; default: 0; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_Z is b. For b > a/2, the value of - * I2S_RX_CLKM_DIV_Z is (a-b). - */ - uint32_t rx_clkm_div_z:9; - /** rx_clkm_div_y : R/W; bitpos: [17:9]; default: 1; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of - * I2S_RX_CLKM_DIV_Y is (a%(a-b)). - */ - uint32_t rx_clkm_div_y:9; - /** rx_clkm_div_x : R/W; bitpos: [26:18]; default: 0; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value - * of I2S_RX_CLKM_DIV_X is (a/(a-b)) - 1. - */ - uint32_t rx_clkm_div_x:9; - /** rx_clkm_div_yn1 : R/W; bitpos: [27]; default: 0; - * For b <= a/2, the value of I2S_RX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of - * I2S_RX_CLKM_DIV_YN1 is 1. - */ - uint32_t rx_clkm_div_yn1:1; - uint32_t reserved_28:4; - }; - uint32_t val; -} i2s_rx_clkm_div_conf_reg_t; - /** Type of rx_timing register * I2S RX timing control register */ @@ -811,36 +722,6 @@ typedef union { /** Group: TX clock and timing registers */ -/** Type of tx_clkm_div_conf register - * I2S TX module clock divider configure register - */ -typedef union { - struct { - /** tx_clkm_div_z : R/W; bitpos: [8:0]; default: 0; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_Z is b. For b > a/2, the value of - * I2S_TX_CLKM_DIV_Z is (a-b). - */ - uint32_t tx_clkm_div_z:9; - /** tx_clkm_div_y : R/W; bitpos: [17:9]; default: 1; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of - * I2S_TX_CLKM_DIV_Y is (a%(a-b)). - */ - uint32_t tx_clkm_div_y:9; - /** tx_clkm_div_x : R/W; bitpos: [26:18]; default: 0; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value - * of I2S_TX_CLKM_DIV_X is (a/(a-b)) - 1. - */ - uint32_t tx_clkm_div_x:9; - /** tx_clkm_div_yn1 : R/W; bitpos: [27]; default: 0; - * For b <= a/2, the value of I2S_TX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of - * I2S_TX_CLKM_DIV_YN1 is 1. - */ - uint32_t tx_clkm_div_yn1:1; - uint32_t reserved_28:4; - }; - uint32_t val; -} i2s_tx_clkm_div_conf_reg_t; - /** Type of tx_timing register * I2S TX timing control register */ @@ -991,10 +872,7 @@ typedef struct { volatile i2s_tx_conf_reg_t tx_conf; volatile i2s_rx_conf1_reg_t rx_conf1; volatile i2s_tx_conf1_reg_t tx_conf1; - volatile i2s_rx_clkm_conf_reg_t rx_clkm_conf; - volatile i2s_tx_clkm_conf_reg_t tx_clkm_conf; - volatile i2s_rx_clkm_div_conf_reg_t rx_clkm_div_conf; - volatile i2s_tx_clkm_div_conf_reg_t tx_clkm_div_conf; + uint32_t reserved_030[4]; volatile i2s_tx_pcm2pdm_conf_reg_t tx_pcm2pdm_conf; volatile i2s_tx_pcm2pdm_conf1_reg_t tx_pcm2pdm_conf1; uint32_t reserved_048[2]; diff --git a/components/soc/esp32p4/i2s_periph.c b/components/soc/esp32p4/i2s_periph.c index 1e466a34335d..66225f77c1de 100644 --- a/components/soc/esp32p4/i2s_periph.c +++ b/components/soc/esp32p4/i2s_periph.c @@ -11,4 +11,73 @@ Bunch of constants for every I2S peripheral: GPIO signals, irqs, hw addr of registers etc */ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { + [0] = { + .mck_out_sig = I2S0_MCLK_PAD_OUT_IDX, + + .m_tx_bck_sig = I2S0_O_BCK_PAD_OUT_IDX, + .m_rx_bck_sig = I2S0_I_BCK_PAD_OUT_IDX, + .m_tx_ws_sig = I2S0_O_WS_PAD_OUT_IDX, + .m_rx_ws_sig = I2S0_I_WS_PAD_OUT_IDX, + + .s_tx_bck_sig = I2S0_O_BCK_PAD_IN_IDX, + .s_rx_bck_sig = I2S0_I_BCK_PAD_IN_IDX, + .s_tx_ws_sig = I2S0_O_WS_PAD_IN_IDX, + .s_rx_ws_sig = I2S0_I_WS_PAD_IN_IDX, + + .data_out_sigs[0] = I2S0_O_SD_PAD_OUT_IDX, + .data_out_sigs[1] = I2S0_O_SD1_PAD_OUT_IDX, + .data_in_sigs[0] = I2S0_I_SD_PAD_IN_IDX, + .data_in_sigs[1] = I2S0_I_SD1_PAD_IN_IDX, + .data_in_sigs[2] = I2S0_I_SD2_PAD_IN_IDX, + .data_in_sigs[3] = I2S0_I_SD3_PAD_IN_IDX, + + .irq = -1, + .module = PERIPH_I2S0_MODULE, + }, + [1] = { + .mck_out_sig = I2S1_MCLK_PAD_OUT_IDX, + + .m_tx_bck_sig = I2S1_O_BCK_PAD_OUT_IDX, + .m_rx_bck_sig = I2S1_I_BCK_PAD_OUT_IDX, + .m_tx_ws_sig = I2S1_O_WS_PAD_OUT_IDX, + .m_rx_ws_sig = I2S1_I_WS_PAD_OUT_IDX, + + .s_tx_bck_sig = I2S1_O_BCK_PAD_IN_IDX, + .s_rx_bck_sig = I2S1_I_BCK_PAD_IN_IDX, + .s_tx_ws_sig = I2S1_O_WS_PAD_IN_IDX, + .s_rx_ws_sig = I2S1_I_WS_PAD_IN_IDX, + + .data_out_sigs[0] = I2S1_O_SD_PAD_OUT_IDX, + .data_out_sigs[1] = -1, + .data_in_sigs[0] = I2S1_I_SD_PAD_IN_IDX, + .data_in_sigs[1] = -1, + .data_in_sigs[2] = -1, + .data_in_sigs[3] = -1, + + .irq = -1, + .module = PERIPH_I2S1_MODULE, + }, + [2] = { + .mck_out_sig = I2S2_MCLK_PAD_OUT_IDX, + + .m_tx_bck_sig = I2S2_O_BCK_PAD_OUT_IDX, + .m_rx_bck_sig = I2S2_I_BCK_PAD_OUT_IDX, + .m_tx_ws_sig = I2S2_O_WS_PAD_OUT_IDX, + .m_rx_ws_sig = I2S2_I_WS_PAD_OUT_IDX, + + .s_tx_bck_sig = I2S2_O_BCK_PAD_IN_IDX, + .s_rx_bck_sig = I2S2_I_BCK_PAD_IN_IDX, + .s_tx_ws_sig = I2S2_O_WS_PAD_IN_IDX, + .s_rx_ws_sig = I2S2_I_WS_PAD_IN_IDX, + + .data_out_sigs[0] = I2S2_O_SD_PAD_OUT_IDX, + .data_out_sigs[1] = -1, + .data_in_sigs[0] = I2S2_I_SD_PAD_IN_IDX, + .data_in_sigs[1] = -1, + .data_in_sigs[2] = -1, + .data_in_sigs[3] = -1, + + .irq = -1, + .module = PERIPH_I2S2_MODULE, + }, }; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 6e71422bd936..28c867a8765c 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -71,6 +71,10 @@ config SOC_I2C_SUPPORTED bool default y +config SOC_I2S_SUPPORTED + bool + default y + config SOC_SYSTIMER_SUPPORTED bool default y @@ -433,7 +437,7 @@ config SOC_I2C_SUPPORT_RTC config SOC_I2S_NUM int - default 1 + default 3 config SOC_I2S_HW_VERSION_2 bool @@ -443,7 +447,7 @@ config SOC_I2S_SUPPORTS_XTAL bool default y -config SOC_I2S_SUPPORTS_PLL_F160M +config SOC_I2S_SUPPORTS_APLL bool default y @@ -451,10 +455,38 @@ config SOC_I2S_SUPPORTS_PCM bool default y +config SOC_I2S_SUPPORTS_PDM + bool + default y + +config SOC_I2S_SUPPORTS_PDM_TX + bool + default y + +config SOC_I2S_SUPPORTS_PDM_RX + bool + default y + +config SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER + bool + default y + +config SOC_I2S_SUPPORTS_TDM + bool + default y + config SOC_I2S_PDM_MAX_TX_LINES int default 2 +config SOC_I2S_PDM_MAX_RX_LINES + int + default 4 + +config SOC_I2S_TDM_FULL_DATA_WIDTH + bool + default y + config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK bool default y diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 32e27ca898e3..7137ba4a12ca 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -150,6 +150,7 @@ typedef enum { SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 40MHz crystal */ + SOC_MOD_CLK_APLL, /*!< Audio PLL is sourced from PLL, and its frequency is configurable through APLL configuration registers */ SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ } soc_module_clk_t; @@ -334,6 +335,20 @@ typedef enum { ///////////////////////////////////////////////// I2S ////////////////////////////////////////////////////////////// +/** + * @brief Array initializer for all supported clock sources of I2S + */ +#define SOC_I2S_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL} + +/** + * @brief I2S clock source enum + */ +typedef enum { + I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default source clock */ + I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + I2S_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */ +} soc_periph_i2s_clk_src_t; + /////////////////////////////////////////////////I2C//////////////////////////////////////////////////////////////////// /** diff --git a/components/soc/esp32p4/include/soc/i2s_struct.h b/components/soc/esp32p4/include/soc/i2s_struct.h index 87b35a0da70c..6e05f6a2eb86 100644 --- a/components/soc/esp32p4/include/soc/i2s_struct.h +++ b/components/soc/esp32p4/include/soc/i2s_struct.h @@ -277,6 +277,92 @@ typedef union { uint32_t val; } i2s_rx_pdm2pcm_conf_reg_t; +/** Type of tx_pcm2pdm_conf register + * I2S TX PCM2PDM configuration register + */ +typedef union { + struct { + /** tx_pdm_hp_bypass : R/W; bitpos: [0]; default: 0; + * I2S TX PDM bypass hp filter or not. The option has been removed. + */ + uint32_t tx_pdm_hp_bypass:1; + /** tx_pdm_sinc_osr2 : R/W; bitpos: [4:1]; default: 2; + * I2S TX PDM OSR2 value + */ + uint32_t tx_pdm_sinc_osr2:4; + /** tx_pdm_prescale : R/W; bitpos: [12:5]; default: 0; + * I2S TX PDM prescale for sigmadelta + */ + uint32_t tx_pdm_prescale:8; + /** tx_pdm_hp_in_shift : R/W; bitpos: [14:13]; default: 1; + * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + */ + uint32_t tx_pdm_hp_in_shift:2; + /** tx_pdm_lp_in_shift : R/W; bitpos: [16:15]; default: 1; + * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + */ + uint32_t tx_pdm_lp_in_shift:2; + /** tx_pdm_sinc_in_shift : R/W; bitpos: [18:17]; default: 1; + * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + */ + uint32_t tx_pdm_sinc_in_shift:2; + /** tx_pdm_sigmadelta_in_shift : R/W; bitpos: [20:19]; default: 1; + * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + */ + uint32_t tx_pdm_sigmadelta_in_shift:2; + /** tx_pdm_sigmadelta_dither2 : R/W; bitpos: [21]; default: 0; + * I2S TX PDM sigmadelta dither2 value + */ + uint32_t tx_pdm_sigmadelta_dither2:1; + /** tx_pdm_sigmadelta_dither : R/W; bitpos: [22]; default: 1; + * I2S TX PDM sigmadelta dither value + */ + uint32_t tx_pdm_sigmadelta_dither:1; + /** tx_pdm_dac_2out_en : R/W; bitpos: [23]; default: 0; + * I2S TX PDM dac mode enable + */ + uint32_t tx_pdm_dac_2out_en:1; + /** tx_pdm_dac_mode_en : R/W; bitpos: [24]; default: 0; + * I2S TX PDM dac 2channel enable + */ + uint32_t tx_pdm_dac_mode_en:1; + /** pcm2pdm_conv_en : R/W; bitpos: [25]; default: 0; + * I2S TX PDM Converter enable + */ + uint32_t pcm2pdm_conv_en:1; + uint32_t reserved_26:6; + }; + uint32_t val; +} i2s_tx_pcm2pdm_conf_reg_t; + +/** Type of tx_pcm2pdm_conf1 register + * I2S TX PCM2PDM configuration register + */ +typedef union { + struct { + /** tx_pdm_fp : R/W; bitpos: [9:0]; default: 960; + * I2S TX PDM Fp + */ + uint32_t tx_pdm_fp:10; + /** tx_pdm_fs : R/W; bitpos: [19:10]; default: 480; + * I2S TX PDM Fs + */ + uint32_t tx_pdm_fs:10; + /** tx_iir_hp_mult12_5 : R/W; bitpos: [22:20]; default: 7; + * The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + + * I2S_TX_IIR_HP_MULT12_5[2:0]) + */ + uint32_t tx_iir_hp_mult12_5:3; + /** tx_iir_hp_mult12_0 : R/W; bitpos: [25:23]; default: 7; + * The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + + * I2S_TX_IIR_HP_MULT12_0[2:0]) + */ + uint32_t tx_iir_hp_mult12_0:3; + uint32_t reserved_26:6; + }; + uint32_t val; +} i2s_tx_pcm2pdm_conf1_reg_t; + /** Type of rx_tdm_ctrl register * I2S TX TDM mode control register */ @@ -371,7 +457,7 @@ typedef union { uint32_t val; } i2s_rx_tdm_ctrl_reg_t; -/** Type of rxeof_num register +/** Type of rx_eof_num register * I2S RX data number control register. */ typedef union { @@ -384,7 +470,7 @@ typedef union { uint32_t reserved_12:20; }; uint32_t val; -} i2s_rxeof_num_reg_t; +} i2s_rx_eof_num_reg_t; /** Group: TX Control and configuration registers */ @@ -530,89 +616,6 @@ typedef union { uint32_t val; } i2s_tx_conf1_reg_t; -/** Type of tx_pcm2pdm_conf register - * I2S TX PCM2PDM configuration register - */ -typedef union { - struct { - uint32_t reserved_0:1; - /** tx_pdm_sinc_osr2 : R/W; bitpos: [4:1]; default: 2; - * I2S TX PDM OSR2 value - */ - uint32_t tx_pdm_sinc_osr2:4; - /** tx_pdm_prescale : R/W; bitpos: [12:5]; default: 0; - * I2S TX PDM prescale for sigmadelta - */ - uint32_t tx_pdm_prescale:8; - /** tx_pdm_hp_in_shift : R/W; bitpos: [14:13]; default: 1; - * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 - */ - uint32_t tx_pdm_hp_in_shift:2; - /** tx_pdm_lp_in_shift : R/W; bitpos: [16:15]; default: 1; - * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 - */ - uint32_t tx_pdm_lp_in_shift:2; - /** tx_pdm_sinc_in_shift : R/W; bitpos: [18:17]; default: 1; - * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 - */ - uint32_t tx_pdm_sinc_in_shift:2; - /** tx_pdm_sigmadelta_in_shift : R/W; bitpos: [20:19]; default: 1; - * I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 - */ - uint32_t tx_pdm_sigmadelta_in_shift:2; - /** tx_pdm_sigmadelta_dither2 : R/W; bitpos: [21]; default: 0; - * I2S TX PDM sigmadelta dither2 value - */ - uint32_t tx_pdm_sigmadelta_dither2:1; - /** tx_pdm_sigmadelta_dither : R/W; bitpos: [22]; default: 1; - * I2S TX PDM sigmadelta dither value - */ - uint32_t tx_pdm_sigmadelta_dither:1; - /** tx_pdm_dac_2out_en : R/W; bitpos: [23]; default: 0; - * I2S TX PDM dac mode enable - */ - uint32_t tx_pdm_dac_2out_en:1; - /** tx_pdm_dac_mode_en : R/W; bitpos: [24]; default: 0; - * I2S TX PDM dac 2channel enable - */ - uint32_t tx_pdm_dac_mode_en:1; - /** pcm2pdm_conv_en : R/W; bitpos: [25]; default: 0; - * I2S TX PDM Converter enable - */ - uint32_t pcm2pdm_conv_en:1; - uint32_t reserved_26:6; - }; - uint32_t val; -} i2s_tx_pcm2pdm_conf_reg_t; - -/** Type of tx_pcm2pdm_conf1 register - * I2S TX PCM2PDM configuration register - */ -typedef union { - struct { - /** tx_pdm_fp : R/W; bitpos: [9:0]; default: 960; - * I2S TX PDM Fp - */ - uint32_t tx_pdm_fp:10; - /** tx_pdm_fs : R/W; bitpos: [19:10]; default: 480; - * I2S TX PDM Fs - */ - uint32_t tx_pdm_fs:10; - /** tx_iir_hp_mult12_5 : R/W; bitpos: [22:20]; default: 7; - * The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + - * I2S_TX_IIR_HP_MULT12_5[2:0]) - */ - uint32_t tx_iir_hp_mult12_5:3; - /** tx_iir_hp_mult12_0 : R/W; bitpos: [25:23]; default: 7; - * The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + - * I2S_TX_IIR_HP_MULT12_0[2:0]) - */ - uint32_t tx_iir_hp_mult12_0:3; - uint32_t reserved_26:6; - }; - uint32_t val; -} i2s_tx_pcm2pdm_conf1_reg_t; - /** Type of tx_tdm_ctrl register * I2S TX TDM mode control register */ @@ -845,7 +848,7 @@ typedef union { uint32_t val; } i2s_lc_hung_conf_reg_t; -/** Type of conf_sigle_data register +/** Type of conf_single_data register * I2S signal data register */ typedef union { @@ -856,7 +859,7 @@ typedef union { uint32_t single_data:32; }; uint32_t val; -} i2s_conf_sigle_data_reg_t; +} i2s_conf_single_data_reg_t; /** Group: TX status registers */ @@ -986,8 +989,8 @@ typedef struct { volatile i2s_rx_timing_reg_t rx_timing; volatile i2s_tx_timing_reg_t tx_timing; volatile i2s_lc_hung_conf_reg_t lc_hung_conf; - volatile i2s_rxeof_num_reg_t rxeof_num; - volatile i2s_conf_sigle_data_reg_t conf_sigle_data; + volatile i2s_rx_eof_num_reg_t rx_eof_num; + volatile i2s_conf_single_data_reg_t conf_single_data; volatile i2s_state_reg_t state; volatile i2s_etm_conf_reg_t etm_conf; volatile i2s_fifo_cnt_reg_t fifo_cnt; @@ -996,6 +999,9 @@ typedef struct { volatile i2s_date_reg_t date; } i2s_dev_t; +extern i2s_dev_t I2S0; +extern i2s_dev_t I2S1; +extern i2s_dev_t I2S2; #ifndef __cplusplus _Static_assert(sizeof(i2s_dev_t) == 0x84, "Invalid size of i2s_dev_t structure"); diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 2e97a113fc68..a4343f13d9b7 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -50,6 +50,8 @@ #define SOC_RTC_MEM_SUPPORTED 1 // #define SOC_I2S_SUPPORTED 1 //TODO: IDF-6508 #define SOC_RMT_SUPPORTED 1 +#define SOC_I2S_SUPPORTED 1 +// #define SOC_RMT_SUPPORTED 1 //TODO: IDF-7476 // #define SOC_SDM_SUPPORTED 1 //TODO: IDF-7551 // #define SOC_GPSPI_SUPPORTED 1 //TODO: IDF-7502, TODO: IDF-7503 // #define SOC_LEDC_SUPPORTED 1 //TODO: IDF-6510 @@ -240,16 +242,19 @@ #define SOC_I2C_SUPPORT_RTC (1) /*-------------------------- I2S CAPS ----------------------------------------*/ -//TODO: IDF-6508 -#define SOC_I2S_NUM (1U) +#define SOC_I2S_NUM (3U) #define SOC_I2S_HW_VERSION_2 (1) #define SOC_I2S_SUPPORTS_XTAL (1) -#define SOC_I2S_SUPPORTS_PLL_F160M (1) +#define SOC_I2S_SUPPORTS_APLL (1) #define SOC_I2S_SUPPORTS_PCM (1) -// #define SOC_I2S_SUPPORTS_PDM (1) -// #define SOC_I2S_SUPPORTS_PDM_TX (1) -#define SOC_I2S_PDM_MAX_TX_LINES (2) -// #define SOC_I2S_SUPPORTS_TDM (1) +#define SOC_I2S_SUPPORTS_PDM (1) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_SUPPORTS_PDM_RX (1) +#define SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER (1) +#define SOC_I2S_SUPPORTS_TDM (1) +#define SOC_I2S_PDM_MAX_TX_LINES (2) // On I2S0 +#define SOC_I2S_PDM_MAX_RX_LINES (4) // On I2S0 +#define SOC_I2S_TDM_FULL_DATA_WIDTH (1) /*!< No limitation to data bit width when using multiple slots */ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index d0face2c1ada..1622658bec39 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -54,15 +54,15 @@ examples/peripherals/i2c/i2c_tools: examples/peripherals/i2s/i2s_basic/i2s_pdm: disable: - - if: SOC_I2S_SUPPORTS_PDM != 1 + - if: SOC_I2S_SUPPORTS_PDM != 1 or IDF_TARGET == "esp32p4" examples/peripherals/i2s/i2s_basic/i2s_std: disable: - - if: SOC_I2S_SUPPORTED != 1 + - if: SOC_I2S_SUPPORTED != 1 or IDF_TARGET == "esp32p4" examples/peripherals/i2s/i2s_basic/i2s_tdm: disable: - - if: SOC_I2S_SUPPORTS_TDM != 1 + - if: SOC_I2S_SUPPORTS_TDM != 1 or IDF_TARGET == "esp32p4" examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm: disable: @@ -71,10 +71,12 @@ examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm: examples/peripherals/i2s/i2s_codec/i2s_es8311: disable: - - if: SOC_I2S_SUPPORTED != 1 or SOC_I2C_SUPPORTED != 1 + - if: (SOC_I2S_SUPPORTED != 1 or SOC_I2C_SUPPORTED != 1) or IDF_TARGET == "esp32p4" reason: rely on I2S STD mode and I2C to config es7210 examples/peripherals/i2s/i2s_recorder: + disable: + - if: IDF_TARGET == "esp32p4" enable: - if: SOC_I2S_SUPPORTS_PDM_RX > 0 From 0b0f25c30d4309b01692b3fe2c935cc1c64a5793 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 2 Aug 2023 19:21:54 +0800 Subject: [PATCH 106/142] feat(i2s): supported getting the tx sync count and specify interrupt flags --- components/driver/dac/esp32/dac_dma.c | 1 + components/driver/deprecated/i2s_legacy.c | 69 +++-- components/driver/i2s/i2s_common.c | 123 ++++++-- components/driver/i2s/i2s_pdm.c | 20 +- components/driver/i2s/i2s_private.h | 16 +- components/driver/i2s/i2s_std.c | 13 +- components/driver/i2s/i2s_tdm.c | 17 +- .../driver/i2s/include/driver/i2s_common.h | 2 + .../driver/i2s/include/driver/i2s_pdm.h | 40 +-- .../driver/include/esp_private/i2s_sync.h | 71 +++++ .../driver/test_apps/.build-test-rules.yml | 16 + .../test_apps/i2s_test_apps/i2s/README.md | 4 +- .../i2s_test_apps/i2s/main/test_i2s.c | 9 +- .../i2s_test_apps/i2s/main/test_i2s_iram.c | 23 +- .../i2s_test_apps/i2s_multi_dev/README.md | 4 +- .../i2s_test_apps/legacy_i2s_driver/README.md | 4 +- .../i2s_test_apps/test_inc/test_i2s.h | 10 +- components/hal/esp32/include/hal/i2s_ll.h | 23 ++ components/hal/esp32c3/include/hal/i2s_ll.h | 23 ++ components/hal/esp32c6/include/hal/i2s_ll.h | 8 +- components/hal/esp32h2/include/hal/i2s_ll.h | 8 +- .../hal/esp32p4/include/hal/clk_gate_ll.h | 16 - .../hal/esp32p4/include/{ => hal}/i2s_ll.h | 290 ++++++++++++++---- components/hal/esp32s2/include/hal/i2s_ll.h | 24 ++ components/hal/esp32s3/include/hal/i2s_ll.h | 33 ++ components/hal/i2s_hal.c | 2 +- components/soc/esp32c3/i2s_periph.c | 2 +- components/soc/esp32c6/i2s_periph.c | 2 +- components/soc/esp32h2/i2s_periph.c | 2 +- components/soc/esp32p4/i2s_periph.c | 9 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 12 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 3 +- components/soc/esp32p4/include/soc/rtc.h | 38 +++ components/soc/esp32p4/include/soc/soc_caps.h | 2 + components/soc/esp32s3/i2s_periph.c | 4 +- examples/peripherals/.build-test-rules.yml | 24 +- .../i2s/i2s_codec/i2s_es8311/README.md | 4 +- 37 files changed, 749 insertions(+), 222 deletions(-) create mode 100644 components/driver/include/esp_private/i2s_sync.h rename components/hal/esp32p4/include/{ => hal}/i2s_ll.h (76%) diff --git a/components/driver/dac/esp32/dac_dma.c b/components/driver/dac/esp32/dac_dma.c index c5f8223a9092..b5bd20e9b97c 100644 --- a/components/driver/dac/esp32/dac_dma.c +++ b/components/driver/dac/esp32/dac_dma.c @@ -17,6 +17,7 @@ #include "hal/adc_ll.h" #include "hal/i2s_hal.h" #include "hal/i2s_types.h" +#include "hal/clk_tree_ll.h" #include "soc/i2s_periph.h" #include "../dac_priv_dma.h" #include "esp_private/i2s_platform.h" diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c index f687cf917072..939727597974 100644 --- a/components/driver/deprecated/i2s_legacy.c +++ b/components/driver/deprecated/i2s_legacy.c @@ -58,6 +58,14 @@ static const char *TAG = "i2s(legacy)"; #define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) +#if !SOC_RCC_IS_INDEPENDENT +#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#define I2S_RCC_ENV_DECLARE (void)__DECLARE_RCC_ATOMIC_ENV +#else +#define I2S_RCC_ATOMIC() +#define I2S_RCC_ENV_DECLARE +#endif + #define I2S_DMA_BUFFER_MAX_SIZE 4092 #if SOC_I2S_SUPPORTS_ADC_DAC @@ -1021,11 +1029,14 @@ static void i2s_set_clock_legacy(i2s_port_t i2s_num) i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg; i2s_hal_clock_info_t clk_info; i2s_calculate_clock(i2s_num, &clk_info); - if (p_i2s[i2s_num]->dir & I2S_DIR_TX) { - i2s_hal_set_tx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src); - } - if (p_i2s[i2s_num]->dir & I2S_DIR_RX) { - i2s_hal_set_rx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src); + I2S_RCC_ATOMIC() { + I2S_RCC_ENV_DECLARE; + if (p_i2s[i2s_num]->dir & I2S_DIR_TX) { + i2s_hal_set_tx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src); + } + if (p_i2s[i2s_num]->dir & I2S_DIR_RX) { + i2s_hal_set_rx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src); + } } } @@ -1479,17 +1490,6 @@ static esp_err_t i2s_init_legacy(i2s_port_t i2s_num, int intr_alloc_flag) ESP_RETURN_ON_ERROR(i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->rx), TAG, "Allocate I2S dma rx buffer failed"); } - /* Initialize I2S DMA object */ -#if SOC_I2S_HW_VERSION_2 - /* Enable tx/rx submodule clock */ - if (p_i2s[i2s_num]->dir & I2S_DIR_TX) { - i2s_ll_tx_enable_clock(p_i2s[i2s_num]->hal.dev); - } - if (p_i2s[i2s_num]->dir & I2S_DIR_RX) { - i2s_ll_rx_enable_clock(p_i2s[i2s_num]->hal.dev); - } -#endif - return ESP_OK; } @@ -1538,12 +1538,15 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) #if SOC_I2S_SUPPORTS_APLL if (obj->use_apll) { - // switch back to PLL clock source - if (obj->dir & I2S_DIR_TX) { - i2s_ll_tx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT); - } - if (obj->dir & I2S_DIR_RX) { - i2s_ll_rx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT); + I2S_RCC_ATOMIC() { + I2S_RCC_ENV_DECLARE; + // switch back to PLL clock source + if (obj->dir & I2S_DIR_TX) { + i2s_ll_tx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT); + } + if (obj->dir & I2S_DIR_RX) { + i2s_ll_rx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT); + } } periph_rtc_apll_release(); } @@ -1556,11 +1559,13 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) } #endif #if SOC_I2S_HW_VERSION_2 - if (obj->dir & I2S_DIR_TX) { - i2s_ll_tx_disable_clock(obj->hal.dev); - } - if (obj->dir & I2S_DIR_RX) { - i2s_ll_rx_disable_clock(obj->hal.dev); + I2S_RCC_ATOMIC() { + if (obj->dir & I2S_DIR_TX) { + i2s_ll_tx_disable_clock(obj->hal.dev); + } + if (obj->dir & I2S_DIR_RX) { + i2s_ll_rx_disable_clock(obj->hal.dev); + } } #endif /* Disable module clock */ @@ -1904,8 +1909,9 @@ esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name) if (!comp_using_i2s[id]) { ret = ESP_OK; comp_using_i2s[id] = comp_name; - periph_module_enable(i2s_periph_signal[id].module); - i2s_ll_enable_clock(I2S_LL_GET_HW(id)); + I2S_RCC_ATOMIC() { + i2s_ll_enable_clock(I2S_LL_GET_HW(id)); + } } portEXIT_CRITICAL(&i2s_spinlock[id]); return ret; @@ -1920,8 +1926,9 @@ esp_err_t i2s_platform_release_occupation(int id) ret = ESP_OK; comp_using_i2s[id] = NULL; /* Disable module clock */ - periph_module_disable(i2s_periph_signal[id].module); - i2s_ll_disable_clock(I2S_LL_GET_HW(id)); + I2S_RCC_ATOMIC() { + i2s_ll_disable_clock(I2S_LL_GET_HW(id)); + } } portEXIT_CRITICAL(&i2s_spinlock[id]); return ret; diff --git a/components/driver/i2s/i2s_common.c b/components/driver/i2s/i2s_common.c index d1e7f2dbde2c..41dde28b7798 100644 --- a/components/driver/i2s/i2s_common.c +++ b/components/driver/i2s/i2s_common.c @@ -25,6 +25,11 @@ #include "soc/soc_caps.h" #include "hal/gpio_hal.h" #include "hal/i2s_hal.h" +#if CONFIG_IDF_TARGET_ESP32P4 +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" +#include "rom/cache.h" +#endif #if SOC_I2S_SUPPORTS_ADC_DAC #include "hal/adc_ll.h" @@ -35,7 +40,6 @@ #endif #include "esp_private/i2s_platform.h" -#include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" #include "driver/gpio.h" @@ -261,6 +265,7 @@ static esp_err_t i2s_register_channel(i2s_controller_t *i2s_obj, i2s_dir_t dir, new_chan->callbacks.on_send_q_ovf = NULL; new_chan->dma.rw_pos = 0; new_chan->dma.curr_ptr = NULL; + new_chan->dma.curr_desc = NULL; new_chan->start = NULL; new_chan->stop = NULL; @@ -330,6 +335,26 @@ uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uin uint32_t bytes_per_sample = ((data_bit_width + 15) / 16) * 2; uint32_t bytes_per_frame = bytes_per_sample * active_chan; uint32_t bufsize = dma_frame_num * bytes_per_frame; +#if CONFIG_IDF_TARGET_ESP32P4 + /* bufsize need to align with cache line size */ + uint32_t alignment = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); + uint32_t aligned_frame_num = dma_frame_num; + /* To make the buffer aligned with the cache line size, search for the ceil aligned size first, + If the buffer size exceed the max DMA buffer size, toggle the sign to search for the floor aligned size */ + for (int sign = 1; bufsize % alignment != 0; aligned_frame_num += sign) { + bufsize = aligned_frame_num * bytes_per_frame; + /* If the buffer size exceed the max dma size */ + if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) { + sign = -1; // toggle the search sign + aligned_frame_num = dma_frame_num; // Reset the frame num + bufsize = aligned_frame_num * bytes_per_frame; // Reset the bufsize + } + } + if (bufsize / bytes_per_frame != dma_frame_num) { + ESP_LOGW(TAG, "dma frame num is adjusted to %"PRIu32" to algin the dma buffer with %"PRIu32 + ", bufsize = %"PRIu32, bufsize / bytes_per_frame, alignment, bufsize); + } +#endif /* Limit DMA buffer size if it is out of range (DMA buffer limitation is 4092 bytes) */ if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) { uint32_t frame_num = I2S_DMA_BUFFER_MAX_SIZE / bytes_per_frame; @@ -348,18 +373,21 @@ esp_err_t i2s_free_dma_desc(i2s_chan_handle_t handle) for (int i = 0; i < handle->dma.desc_num; i++) { if (handle->dma.bufs[i]) { free(handle->dma.bufs[i]); + handle->dma.bufs[i] = NULL; } if (handle->dma.desc[i]) { free(handle->dma.desc[i]); + handle->dma.desc[i] = NULL; } } if (handle->dma.bufs) { free(handle->dma.bufs); + handle->dma.bufs = NULL; } if (handle->dma.desc) { free(handle->dma.desc); + handle->dma.desc = NULL; } - handle->dma.desc = NULL; return ESP_OK; } @@ -372,13 +400,20 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu handle->dma.desc_num = num; handle->dma.buf_size = bufsize; +#if SOC_GDMA_TRIG_PERIPH_I2S0_BUS == SOC_GDMA_BUS_AHB + uint32_t alignment = 32; + uint32_t desc_size = alignment; +#else + uint32_t alignment = 4; + uint32_t desc_size = sizeof(lldesc_t); +#endif /* Descriptors must be in the internal RAM */ handle->dma.desc = (lldesc_t **)heap_caps_calloc(num, sizeof(lldesc_t *), I2S_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(handle->dma.desc, ESP_ERR_NO_MEM, err, TAG, "create I2S DMA decriptor array failed"); handle->dma.bufs = (uint8_t **)heap_caps_calloc(num, sizeof(uint8_t *), I2S_MEM_ALLOC_CAPS); for (int i = 0; i < num; i++) { /* Allocate DMA descriptor */ - handle->dma.desc[i] = (lldesc_t *) heap_caps_calloc(1, sizeof(lldesc_t), I2S_DMA_ALLOC_CAPS); + handle->dma.desc[i] = (lldesc_t *) heap_caps_aligned_calloc(alignment, 1, desc_size, I2S_DMA_ALLOC_CAPS); ESP_GOTO_ON_FALSE(handle->dma.desc[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA description failed"); handle->dma.desc[i]->owner = 1; handle->dma.desc[i]->eof = 1; @@ -386,15 +421,18 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu handle->dma.desc[i]->length = bufsize; handle->dma.desc[i]->size = bufsize; handle->dma.desc[i]->offset = 0; - handle->dma.bufs[i] = (uint8_t *) heap_caps_calloc(1, bufsize * sizeof(uint8_t), I2S_DMA_ALLOC_CAPS); + handle->dma.bufs[i] = (uint8_t *) heap_caps_aligned_calloc(alignment, 1, bufsize * sizeof(uint8_t), I2S_DMA_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(handle->dma.bufs[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA buffer failed"); handle->dma.desc[i]->buf = handle->dma.bufs[i]; - ESP_GOTO_ON_FALSE(handle->dma.desc[i]->buf, ESP_ERR_NO_MEM, err, TAG, "allocate DMA buffer failed"); ESP_LOGV(TAG, "desc addr: %8p\tbuffer addr:%8p", handle->dma.desc[i], handle->dma.bufs[i]); } /* Connect DMA descriptor as a circle */ for (int i = 0; i < num; i++) { /* Link to the next descriptor */ STAILQ_NEXT(handle->dma.desc[i], qe) = (i < (num - 1)) ? (handle->dma.desc[i + 1]) : handle->dma.desc[0]; +#if CONFIG_IDF_TARGET_ESP32P4 + Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)(handle->dma.desc[i]), desc_size); +#endif } if (handle->dir == I2S_DIR_RX) { i2s_ll_rx_set_eof_num(handle->controller->hal.dev, bufsize); @@ -459,6 +497,9 @@ static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_e uint32_t dummy; finish_desc = (lldesc_t *)event_data->rx_eof_desc_addr; +#if CONFIG_IDF_TARGET_ESP32P4 + Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)finish_desc->buf, handle->dma.buf_size); +#endif i2s_event_data_t evt = { .data = &(finish_desc->buf), .size = handle->dma.buf_size, @@ -487,7 +528,7 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e lldesc_t *finish_desc; uint32_t dummy; - finish_desc = (lldesc_t *)(event_data->tx_eof_desc_addr); + finish_desc = (lldesc_t *)event_data->tx_eof_desc_addr; i2s_event_data_t evt = { .data = &(finish_desc->buf), .size = handle->dma.buf_size, @@ -505,6 +546,9 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e if (handle->dma.auto_clear) { uint8_t *sent_buf = (uint8_t *)finish_desc->buf; memset(sent_buf, 0, handle->dma.buf_size); +#if CONFIG_IDF_TARGET_ESP32P4 + Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)sent_buf, handle->dma.buf_size); +#endif } xQueueSendFromISR(handle->msg_queue, &(finish_desc->buf), &need_yield2); @@ -646,7 +690,7 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle); } #else - intr_flag |= ESP_INTR_FLAG_SHARED; + intr_flag |= handle->intr_flags ? handle->intr_flags : ESP_INTR_FLAG_LOWMED; /* Initialize I2S module interrupt */ if (handle->dir == I2S_DIR_TX) { esp_intr_alloc_intrstatus(i2s_periph_signal[port_id].irq, intr_flag, @@ -771,6 +815,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_TX, chan_cfg->dma_desc_num), err, TAG, "register I2S tx channel failed"); i2s_obj->tx_chan->role = chan_cfg->role; + i2s_obj->tx_chan->intr_flags = chan_cfg->intr_flags; i2s_obj->tx_chan->dma.auto_clear = chan_cfg->auto_clear; i2s_obj->tx_chan->dma.desc_num = chan_cfg->dma_desc_num; i2s_obj->tx_chan->dma.frame_num = chan_cfg->dma_frame_num; @@ -784,6 +829,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_RX, chan_cfg->dma_desc_num), err, TAG, "register I2S rx channel failed"); i2s_obj->rx_chan->role = chan_cfg->role; + i2s_obj->rx_chan->intr_flags = chan_cfg->intr_flags; i2s_obj->rx_chan->dma.desc_num = chan_cfg->dma_desc_num; i2s_obj->rx_chan->dma.frame_num = chan_cfg->dma_frame_num; i2s_obj->rx_chan->start = i2s_rx_channel_start; @@ -821,10 +867,12 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle) bool is_bound = true; #if SOC_I2S_HW_VERSION_2 - if (dir == I2S_DIR_TX) { - i2s_ll_tx_disable_clock(handle->controller->hal.dev); - } else { - i2s_ll_rx_disable_clock(handle->controller->hal.dev); + I2S_RCC_ATOMIC() { + if (dir == I2S_DIR_TX) { + i2s_ll_tx_disable_clock(handle->controller->hal.dev); + } else { + i2s_ll_rx_disable_clock(handle->controller->hal.dev); + } } #endif #if SOC_I2S_SUPPORTS_APLL @@ -978,6 +1026,7 @@ esp_err_t i2s_channel_disable(i2s_chan_handle_t handle) xSemaphoreTake(handle->binary, portMAX_DELAY); /* Reset the descriptor pointer */ handle->dma.curr_ptr = NULL; + handle->dma.curr_desc = NULL; handle->dma.rw_pos = 0; handle->stop(handle); #if CONFIG_PM_ENABLE @@ -1005,11 +1054,11 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src, xSemaphoreTake(tx_handle->mutex, portMAX_DELAY); /* The pre-load data will be loaded from the first descriptor */ - if (tx_handle->dma.curr_ptr == NULL) { - tx_handle->dma.curr_ptr = tx_handle->dma.desc[0]; + if (tx_handle->dma.curr_desc == NULL) { + tx_handle->dma.curr_desc = tx_handle->dma.desc[0]; + tx_handle->dma.curr_ptr = (void *)tx_handle->dma.desc[0]->buf; tx_handle->dma.rw_pos = 0; } - lldesc_t *desc_ptr = (lldesc_t *)tx_handle->dma.curr_ptr; /* Loop until no bytes in source buff remain or the descriptors are full */ while (remain_bytes) { @@ -1020,7 +1069,10 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src, break; } /* Load the data from the last loaded position */ - memcpy((uint8_t *)(desc_ptr->buf + tx_handle->dma.rw_pos), data_ptr, bytes_can_load); + memcpy((uint8_t *)(tx_handle->dma.curr_ptr + tx_handle->dma.rw_pos), data_ptr, bytes_can_load); +#if CONFIG_IDF_TARGET_ESP32P4 + Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)(tx_handle->dma.curr_ptr + tx_handle->dma.rw_pos), (uint32_t)bytes_can_load); +#endif data_ptr += bytes_can_load; // Move forward the data pointer total_loaded_bytes += bytes_can_load; // Add to the total loaded bytes remain_bytes -= bytes_can_load; // Update the remaining bytes to be loaded @@ -1030,9 +1082,9 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src, /* If the next descriptor is not the first descriptor, keep load to the first descriptor * otherwise all descriptor has been loaded, break directly, the dma buffer position * will remain at the end of the last dma buffer */ - if (STAILQ_NEXT(desc_ptr, qe) != tx_handle->dma.desc[0]) { - desc_ptr = STAILQ_NEXT(desc_ptr, qe); - tx_handle->dma.curr_ptr = (void *)desc_ptr; + if (STAILQ_NEXT((lldesc_t *)tx_handle->dma.curr_desc, qe) != tx_handle->dma.desc[0]) { + tx_handle->dma.curr_desc = STAILQ_NEXT((lldesc_t *)tx_handle->dma.curr_desc, qe); + tx_handle->dma.curr_ptr = (void *)(((lldesc_t *)tx_handle->dma.curr_desc)->buf); tx_handle->dma.rw_pos = 0; } else { break; @@ -1077,6 +1129,9 @@ esp_err_t i2s_channel_write(i2s_chan_handle_t handle, const void *src, size_t si bytes_can_write = size; } memcpy(data_ptr, src_byte, bytes_can_write); +#if CONFIG_IDF_TARGET_ESP32P4 + Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)data_ptr, (uint32_t)bytes_can_write); +#endif size -= bytes_can_write; src_byte += bytes_can_write; handle->dma.rw_pos += bytes_can_write; @@ -1146,8 +1201,9 @@ esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name) if ((!g_i2s.controller[id]) && (g_i2s.comp_name[id] == NULL)) { g_i2s.comp_name[id] = comp_name; /* Enable module clock */ - periph_module_enable(i2s_periph_signal[id].module); - i2s_ll_enable_clock(I2S_LL_GET_HW(id)); + I2S_RCC_ATOMIC() { + i2s_ll_enable_clock(I2S_LL_GET_HW(id)); + } } else { occupied_comp = g_i2s.comp_name[id]; ret = ESP_ERR_NOT_FOUND; @@ -1167,8 +1223,9 @@ esp_err_t i2s_platform_release_occupation(int id) if (!g_i2s.controller[id]) { g_i2s.comp_name[id] = NULL; /* Disable module clock */ - periph_module_disable(i2s_periph_signal[id].module); - i2s_ll_disable_clock(I2S_LL_GET_HW(id)); + I2S_RCC_ATOMIC() { + i2s_ll_disable_clock(I2S_LL_GET_HW(id)); + } } else { ret = ESP_ERR_INVALID_STATE; } @@ -1183,3 +1240,25 @@ size_t inline i2s_platform_get_dma_buffer_offset(void) * then find the corresponding field , the address of this field is the offset of this type */ return (size_t)&(((i2s_chan_handle_t)0)->dma.bufs); } + +#if SOC_I2S_SUPPORTS_TX_SYNC_CNT +uint32_t i2s_sync_get_bclk_count(i2s_chan_handle_t tx_handle) +{ + return i2s_ll_tx_get_bclk_sync_count(tx_handle->controller->hal.dev); +} + +uint32_t i2s_sync_get_fifo_count(i2s_chan_handle_t tx_handle) +{ + return i2s_ll_tx_get_fifo_sync_count(tx_handle->controller->hal.dev); +} + +void i2s_sync_reset_bclk_count(i2s_chan_handle_t tx_handle) +{ + i2s_ll_tx_reset_bclk_sync_counter(tx_handle->controller->hal.dev); +} + +void i2s_sync_reset_fifo_count(i2s_chan_handle_t tx_handle) +{ + i2s_ll_tx_reset_fifo_sync_counter(tx_handle->controller->hal.dev); +} +#endif // SOC_I2S_SUPPORTS_TX_SYNC_CNT diff --git a/components/driver/i2s/i2s_pdm.c b/components/driver/i2s/i2s_pdm.c index 7991f6e969ef..2426e896fef0 100644 --- a/components/driver/i2s/i2s_pdm.c +++ b/components/driver/i2s/i2s_pdm.c @@ -70,7 +70,10 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + I2S_RCC_ATOMIC() { + I2S_RCC_ENV_DECLARE; + i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + } #if SOC_I2S_HW_VERSION_2 /* Work around for PDM TX clock, overwrite the raw division directly to reduce the noise * This set of coefficients is a special division to reduce the background noise in PDM TX mode */ @@ -187,10 +190,7 @@ esp_err_t i2s_channel_init_pdm_tx_mode(i2s_chan_handle_t handle, const i2s_pdm_t ESP_GOTO_ON_ERROR(i2s_init_dma_intr(handle, I2S_INTR_ALLOC_FLAGS), err, TAG, "initialize dma interrupt failed"); i2s_ll_tx_enable_pdm(handle->controller->hal.dev); -#if SOC_I2S_HW_VERSION_2 - /* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */ - i2s_ll_tx_enable_clock(handle->controller->hal.dev); -#endif + #ifdef CONFIG_PM_ENABLE esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX; #if SOC_I2S_SUPPORTS_APLL @@ -357,7 +357,10 @@ static esp_err_t i2s_pdm_rx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_rx portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + I2S_RCC_ATOMIC() { + I2S_RCC_ENV_DECLARE; + i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + } portEXIT_CRITICAL(&g_i2s.spinlock); /* Update the mode info: clock configuration */ @@ -467,10 +470,7 @@ esp_err_t i2s_channel_init_pdm_rx_mode(i2s_chan_handle_t handle, const i2s_pdm_r ESP_GOTO_ON_ERROR(i2s_init_dma_intr(handle, I2S_INTR_ALLOC_FLAGS), err, TAG, "initialize dma interrupt failed"); i2s_ll_rx_enable_pdm(handle->controller->hal.dev); -#if SOC_I2S_HW_VERSION_2 - /* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */ - i2s_ll_rx_enable_clock(handle->controller->hal.dev); -#endif + #ifdef CONFIG_PM_ENABLE esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX; #if SOC_I2S_SUPPORTS_APLL diff --git a/components/driver/i2s/i2s_private.h b/components/driver/i2s/i2s_private.h index 23dfe79f5fee..802eb32fbb5f 100644 --- a/components/driver/i2s/i2s_private.h +++ b/components/driver/i2s/i2s_private.h @@ -16,8 +16,10 @@ #if SOC_GDMA_SUPPORTED #include "esp_private/gdma.h" #endif +#include "esp_private/periph_ctrl.h" #include "esp_pm.h" #include "esp_err.h" +#include "sdkconfig.h" #ifdef __cplusplus extern "C" { @@ -26,14 +28,22 @@ extern "C" { // If ISR handler is allowed to run whilst cache is disabled, // Make sure all the code and related variables used by the handler are in the SRAM #if CONFIG_I2S_ISR_IRAM_SAFE -#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED) +#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED) #define I2S_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else -#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED) +#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED) #define I2S_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif //CONFIG_I2S_ISR_IRAM_SAFE #define I2S_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) +#if !SOC_RCC_IS_INDEPENDENT +#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#define I2S_RCC_ENV_DECLARE (void)__DECLARE_RCC_ATOMIC_ENV +#else +#define I2S_RCC_ATOMIC() +#define I2S_RCC_ENV_DECLARE +#endif + #define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL") /** @@ -61,6 +71,7 @@ typedef struct { bool auto_clear; /*!< Set to auto clear DMA TX descriptor, i2s will always send zero automatically if no data to send */ uint32_t rw_pos; /*!< reading/writing pointer position */ void *curr_ptr; /*!< Pointer to current dma buffer */ + void *curr_desc; /*!< Pointer to current dma descriptor used for pre-load */ lldesc_t **desc; /*!< dma descriptor array */ uint8_t **bufs; /*!< dma buffer array */ } i2s_dma_t; @@ -88,6 +99,7 @@ struct i2s_channel_obj_t { i2s_dma_t dma; /*!< i2s dma object */ i2s_state_t state; /*!< i2s driver state. Ensuring the driver working in a correct sequence */ /* Stored configurations */ + int intr_flags; void *mode_info; /*!< Slot, clock and gpio information of each mode */ #if SOC_I2S_SUPPORTS_APLL bool apll_en; /*!< Flag of wether APLL enabled */ diff --git a/components/driver/i2s/i2s_std.c b/components/driver/i2s/i2s_std.c index 2570e3b4b2f1..0b32139c2160 100644 --- a/components/driver/i2s/i2s_std.c +++ b/components/driver/i2s/i2s_std.c @@ -77,10 +77,13 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - if (handle->dir == I2S_DIR_TX) { - i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); - } else { - i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + I2S_RCC_ATOMIC() { + I2S_RCC_ENV_DECLARE; + if (handle->dir == I2S_DIR_TX) { + i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + } else { + i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + } } portEXIT_CRITICAL(&g_i2s.spinlock); @@ -226,10 +229,8 @@ esp_err_t i2s_channel_init_std_mode(i2s_chan_handle_t handle, const i2s_std_conf /* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */ if (handle->dir == I2S_DIR_TX) { i2s_ll_tx_enable_std(handle->controller->hal.dev); - i2s_ll_tx_enable_clock(handle->controller->hal.dev); } else { i2s_ll_rx_enable_std(handle->controller->hal.dev); - i2s_ll_rx_enable_clock(handle->controller->hal.dev); } #endif diff --git a/components/driver/i2s/i2s_tdm.c b/components/driver/i2s/i2s_tdm.c index 5484881dd981..b4353f8c8300 100644 --- a/components/driver/i2s/i2s_tdm.c +++ b/components/driver/i2s/i2s_tdm.c @@ -79,10 +79,13 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - if (handle->dir == I2S_DIR_TX) { - i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); - } else { - i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + I2S_RCC_ATOMIC() { + I2S_RCC_ENV_DECLARE; + if (handle->dir == I2S_DIR_TX) { + i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + } else { + i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); + } } portEXIT_CRITICAL(&g_i2s.spinlock); @@ -232,10 +235,8 @@ esp_err_t i2s_channel_init_tdm_mode(i2s_chan_handle_t handle, const i2s_tdm_conf /* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */ if (handle->dir == I2S_DIR_TX) { i2s_ll_tx_enable_tdm(handle->controller->hal.dev); - i2s_ll_tx_enable_clock(handle->controller->hal.dev); } else { i2s_ll_rx_enable_tdm(handle->controller->hal.dev); - i2s_ll_rx_enable_clock(handle->controller->hal.dev); } #endif #ifdef CONFIG_PM_ENABLE @@ -275,12 +276,12 @@ esp_err_t i2s_channel_reconfig_tdm_clock(i2s_chan_handle_t handle, const i2s_tdm #if SOC_I2S_SUPPORTS_APLL /* Enable APLL and acquire its lock when the clock source is changed to APLL */ - if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && clk_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) { + if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && tdm_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) { periph_rtc_apll_acquire(); handle->apll_en = true; } /* Disable APLL and release its lock when clock source is changed to 160M_PLL */ - if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && clk_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { + if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && tdm_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { periph_rtc_apll_release(); handle->apll_en = false; } diff --git a/components/driver/i2s/include/driver/i2s_common.h b/components/driver/i2s/include/driver/i2s_common.h index 819ab0d23f0e..fb2c99a4f140 100644 --- a/components/driver/i2s/include/driver/i2s_common.h +++ b/components/driver/i2s/include/driver/i2s_common.h @@ -25,6 +25,7 @@ extern "C" { .dma_desc_num = 6, \ .dma_frame_num = 240, \ .auto_clear = false, \ + .intr_flags = 0, \ } #define I2S_GPIO_UNUSED GPIO_NUM_NC /*!< Used in i2s_gpio_config_t for signals which are not used */ @@ -63,6 +64,7 @@ typedef struct { * it should be the multiple of '3' when the data bit width is 24. */ bool auto_clear; /*!< Set to auto clear DMA TX buffer, i2s will always send zero automatically if no data to send */ + int intr_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */ } i2s_chan_config_t; /** diff --git a/components/driver/i2s/include/driver/i2s_pdm.h b/components/driver/i2s/include/driver/i2s_pdm.h index d8bd632c9995..11601166aaf0 100644 --- a/components/driver/i2s/include/driver/i2s_pdm.h +++ b/components/driver/i2s/include/driver/i2s_pdm.h @@ -23,6 +23,7 @@ extern "C" { #if SOC_I2S_SUPPORTS_PDM_RX +#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER /** * @brief PDM format in 2 slots(RX) * @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode @@ -34,21 +35,11 @@ extern "C" { .slot_mode = mono_or_stereo, \ .slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \ + .hpf_en = true, \ + .hpf_cut_off_freq_hz = 35.5, \ + .amplify_num = 1, \ } - -/** - * @brief i2s default pdm rx clock configuration - * @param rate sample rate - */ -#define I2S_PDM_RX_CLK_DEFAULT_CONFIG(rate) { \ - .sample_rate_hz = rate, \ - .clk_src = I2S_CLK_SRC_DEFAULT, \ - .mclk_multiple = I2S_MCLK_MULTIPLE_256, \ - .dn_sample_mode = I2S_PDM_DSR_8S, \ - .bclk_div = 8, \ -} - -#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER +#else /** * @brief PDM format in 2 slots(RX) * @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode @@ -60,12 +51,23 @@ extern "C" { .slot_mode = mono_or_stereo, \ .slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \ - .hp_en = true, \ - .hp_cut_off_freq_hz = 35.5, \ - .amplify_num = 1, \ /* TODO: maybe need an enum */ } #endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER +/** + * @brief i2s default pdm rx clock configuration + * @param rate sample rate + */ +#define I2S_PDM_RX_CLK_DEFAULT_CONFIG(rate) { \ + .sample_rate_hz = rate, \ + .clk_src = I2S_CLK_SRC_DEFAULT, \ + .mclk_multiple = I2S_MCLK_MULTIPLE_256, \ + .dn_sample_mode = I2S_PDM_DSR_8S, \ + .bclk_div = 8, \ +} + + + /** * @brief I2S slot configuration for pdm rx mode */ @@ -329,8 +331,8 @@ typedef struct { i2s_pdm_sig_scale_t sinc_scale; /*!< Sinc filter scaling value */ #if SOC_I2S_HW_VERSION_2 i2s_pdm_tx_line_mode_t line_mode; /*!< PDM TX line mode, one-line codec, one-line dac, two-line dac mode can be selected */ - bool hp_en; /*!< High pass filter enable */ - float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */ + bool hpf_en; /*!< High pass filter enable */ + float hpf_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */ uint32_t sd_dither; /*!< Sigma-delta filter dither */ uint32_t sd_dither2; /*!< Sigma-delta filter dither2 */ #endif // SOC_I2S_HW_VERSION_2 diff --git a/components/driver/include/esp_private/i2s_sync.h b/components/driver/include/esp_private/i2s_sync.h new file mode 100644 index 000000000000..83c419039766 --- /dev/null +++ b/components/driver/include/esp_private/i2s_sync.h @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// DO NOT USE THESE APIS IN YOUR APPLICATIONS +// The following APIs are for internal use, public to other IDF components, but not for users' applications. + +/** + * This file is used for getting the bclk and fifo sending count + * for the synchronization among different I2S ports. + * + * The APIs in this file might be called frequently, so they are made light-weight and flexible to be called + * + * NOTE: These APIs are private for ESP internal usages. + * Please be aware of the risk that APIs might be changed regarding the use case. + */ + +#pragma once + +#include +#include "driver/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_I2S_SUPPORTS_TX_SYNC_CNT + +/** + * @brief Get the counter number of BCLK ticks + * @note The BCLK tick count reflects the real data that have sent on line + * + * @param[in] tx_handle The I2S tx channel handle + * @return + * - BCLK tick count + */ +uint32_t i2s_sync_get_bclk_count(i2s_chan_handle_t tx_handle); + +/** + * @brief Get the counter number of fifo + * @note The FIFO count reflects how many slots have processed + * Normally, fifo_cnt = slot_bit_width * bclk_cnt + * If fifo_cnt < slot_bit_width * bclk_cnt, that means some data are still stuck in the I2S controller + * + * @param[in] tx_handle The I2S tx channel handle + * @return + * - FIFO slot count + */ +uint32_t i2s_sync_get_fifo_count(i2s_chan_handle_t tx_handle); + +/** + * @brief Reset the bclk counter + * + * @param[in] tx_handle The I2S tx channel handle + */ +void i2s_sync_reset_bclk_count(i2s_chan_handle_t tx_handle); + +/** + * @brief Reset the fifo counter + * + * @param[in] tx_handle The I2S tx channel handle + */ +void i2s_sync_reset_fifo_count(i2s_chan_handle_t tx_handle); + +#endif // SOC_I2S_SUPPORTS_TX_SYNC_CNT + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/test_apps/.build-test-rules.yml b/components/driver/test_apps/.build-test-rules.yml index f69afb0d5911..b1fd554b0c10 100644 --- a/components/driver/test_apps/.build-test-rules.yml +++ b/components/driver/test_apps/.build-test-rules.yml @@ -33,15 +33,27 @@ components/driver/test_apps/i2c_test_apps: components/driver/test_apps/i2s_test_apps: disable: - if: SOC_I2S_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners components/driver/test_apps/i2s_test_apps/i2s: disable: - if: SOC_I2S_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners components/driver/test_apps/i2s_test_apps/i2s_multi_dev: disable: - if: SOC_I2S_SUPPORTED != 1 - if: SOC_I2S_HW_VERSION_2 != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac: disable: @@ -50,6 +62,10 @@ components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac: components/driver/test_apps/i2s_test_apps/legacy_i2s_driver: disable: - if: SOC_I2S_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners components/driver/test_apps/ledc: disable: diff --git a/components/driver/test_apps/i2s_test_apps/i2s/README.md b/components/driver/test_apps/i2s_test_apps/i2s/README.md index 19f1d19a5490..a79fcf4c5ea7 100644 --- a/components/driver/test_apps/i2s_test_apps/i2s/README.md +++ b/components/driver/test_apps/i2s_test_apps/i2s/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c b/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c index a419ea6c2e15..0cbe69b6ff6e 100644 --- a/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c +++ b/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s.c @@ -11,6 +11,7 @@ #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" +#include "sdkconfig.h" #include "driver/gpio.h" #include "hal/gpio_hal.h" #include "esp_err.h" @@ -775,7 +776,7 @@ static void i2s_test_common_sample_rate(i2s_chan_handle_t rx_chan, i2s_std_clk_c // pcnt will count the pulse number on WS signal in 100ms TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit)); TEST_ESP_OK(pcnt_unit_start(pcnt_unit)); - vTaskDelay(pdMS_TO_TICKS(TEST_I2S_PERIOD_MS)); + esp_rom_delay_us(100 * 1000); TEST_ESP_OK(pcnt_unit_stop(pcnt_unit)); TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &real_pulse)); printf("[%"PRIu32" Hz] %d pulses, expected %d, err %d\n", test_freq[i], real_pulse, expt_pulse, real_pulse - expt_pulse); @@ -803,9 +804,10 @@ TEST_CASE("I2S_default_PLL_clock_test", "[i2s]") TEST_ESP_OK(i2s_new_channel(&chan_cfg, NULL, &rx_handle)); TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg)); -#if SOC_I2S_SUPPORTS_PLL_F160M || SOC_I2S_SUPPORTS_PLL_F96M +// ESP32-P4 has no PLL except XTAL +#if !CONFIG_IDF_TARGET_ESP32P4 i2s_test_common_sample_rate(rx_handle, &std_cfg.clk_cfg); -#endif // SOC_I2S_SUPPORTS_PLL_F160M || SOC_I2S_SUPPORTS_PLL_F96M +#endif // CONFIG_IDF_TARGET_ESP32P4 #if SOC_I2S_SUPPORTS_XTAL std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_XTAL; i2s_test_common_sample_rate(rx_handle, &std_cfg.clk_cfg); @@ -882,7 +884,6 @@ TEST_CASE("I2S_package_lost_test", "[i2s]") for (i = 0; i < test_num; i++) { printf("Testing %"PRIu32" Hz sample rate\n", test_freq[i]); std_cfg.clk_cfg.sample_rate_hz = test_freq[i]; - std_cfg.clk_cfg.sample_rate_hz = test_freq[i]; TEST_ESP_OK(i2s_channel_reconfig_std_clock(rx_handle, &std_cfg.clk_cfg)); TEST_ESP_OK(i2s_channel_enable(rx_handle)); for (int j = 0; j < 10; j++) { diff --git a/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s_iram.c b/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s_iram.c index 518dcf4b8755..021f4f30eb05 100644 --- a/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s_iram.c +++ b/components/driver/test_apps/i2s_test_apps/i2s/main/test_i2s_iram.c @@ -13,6 +13,9 @@ #include "driver/i2s_std.h" #include "esp_attr.h" #include "soc/soc_caps.h" +#if CONFIG_IDF_TARGET_ESP32P4 +#include "rom/cache.h" +#endif #include "esp_private/i2s_platform.h" #include "esp_private/spi_flash_os.h" #include "../../test_inc/test_i2s.h" @@ -39,9 +42,13 @@ static void IRAM_ATTR test_i2s_iram_write(i2s_chan_handle_t tx_handle) // disable cache and non-iram ISR handlers spi_flash_guard_get()->start(); // write data into dma buffer directly, the data in dma buffer will be sent automatically - for (int i=0; i < 100; i++) { - dma_bufs[0][i] = i + 1; + for (int i = 0; i < 400; i++) { + dma_bufs[0][i] = i % 100 + 1; } +#if CONFIG_IDF_TARGET_ESP32P4 + // TODO: need to consider PSRAM if I2S driver supports EDMA + Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)dma_bufs[0], 400); +#endif // enable cache and non-iram ISR handlers spi_flash_guard_get()->end(); } @@ -52,8 +59,8 @@ TEST_CASE("i2s_iram_interrupt_safe", "[i2s]") i2s_chan_handle_t rx_chan = NULL; i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER); - chan_cfg.dma_desc_num = 6; - chan_cfg.dma_frame_num = 200; + chan_cfg.dma_desc_num = 2; + chan_cfg.dma_frame_num = 100; TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan)); i2s_std_config_t std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000), @@ -73,14 +80,14 @@ TEST_CASE("i2s_iram_interrupt_safe", "[i2s]") }; TEST_ESP_OK(i2s_channel_init_std_mode(tx_chan, &std_cfg)); TEST_ESP_OK(i2s_channel_init_std_mode(rx_chan, &std_cfg)); - int is_triggerred = 0; + int is_triggered = 0; i2s_event_callbacks_t cbs = { .on_recv = NULL, .on_recv_q_ovf = NULL, .on_sent = test_i2s_tx_done_callback, .on_send_q_ovf = NULL, }; - TEST_ESP_OK(i2s_channel_register_event_callback(tx_chan, &cbs, &is_triggerred)); + TEST_ESP_OK(i2s_channel_register_event_callback(tx_chan, &cbs, &is_triggered)); TEST_ESP_OK(i2s_channel_enable(tx_chan)); TEST_ESP_OK(i2s_channel_enable(rx_chan)); @@ -92,7 +99,7 @@ TEST_CASE("i2s_iram_interrupt_safe", "[i2s]") for (int retry = 0; retry < 3; retry++) { i2s_channel_read(rx_chan, recv_buf, 2000, &r_bytes, pdMS_TO_TICKS(1000)); for (i = 0; i < 2000 - 100; i++) { - if (recv_buf[i] != 0) { + if (recv_buf[i] == 1 && recv_buf[i + 1] == 2) { goto finish; } } @@ -107,7 +114,7 @@ TEST_CASE("i2s_iram_interrupt_safe", "[i2s]") for (int j = 1; j <= 100; j++) { TEST_ASSERT_EQUAL_UINT8(recv_buf[i++], j); } - TEST_ASSERT(is_triggerred); + TEST_ASSERT(is_triggered); free(recv_buf); } diff --git a/components/driver/test_apps/i2s_test_apps/i2s_multi_dev/README.md b/components/driver/test_apps/i2s_test_apps/i2s_multi_dev/README.md index 541c8b1e9aca..bb5058d38743 100644 --- a/components/driver/test_apps/i2s_test_apps/i2s_multi_dev/README.md +++ b/components/driver/test_apps/i2s_test_apps/i2s_multi_dev/README.md @@ -1,3 +1,3 @@ -| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md index 19f1d19a5490..a79fcf4c5ea7 100644 --- a/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md +++ b/components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/i2s_test_apps/test_inc/test_i2s.h b/components/driver/test_apps/i2s_test_apps/test_inc/test_i2s.h index 4c1a3763b5f7..1adaf4e1fc15 100644 --- a/components/driver/test_apps/i2s_test_apps/test_inc/test_i2s.h +++ b/components/driver/test_apps/i2s_test_apps/test_inc/test_i2s.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,6 +44,14 @@ extern "C" { #define SLAVE_WS_IO 15 #define DATA_IN_IO 19 #define DATA_OUT_IO 18 +#elif CONFIG_IDF_TARGET_ESP32P4 +#define MASTER_MCK_IO 34 +#define MASTER_BCK_IO 35 +#define MASTER_WS_IO 48 +#define SLAVE_BCK_IO 10 +#define SLAVE_WS_IO 11 +#define DATA_IN_IO 12 +#define DATA_OUT_IO 49 #else #define MASTER_MCK_IO 0 #define MASTER_BCK_IO 4 diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index c03f56ce028a..d718d17a3418 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -18,6 +18,7 @@ #include "hal/misc.h" #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" +#include "soc/dport_reg.h" #include "hal/i2s_types.h" #include "hal/hal_utils.h" @@ -90,12 +91,23 @@ static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en) */ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { + if (hw == &I2S0) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + } else { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); + } if (hw->clkm_conf.clk_en == 0) { hw->clkm_conf.clk_en = 1; hw->conf2.val = 0; } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) + /** * @brief I2S module disable clock. * @@ -106,8 +118,19 @@ static inline void i2s_ll_disable_clock(i2s_dev_t *hw) if (hw->clkm_conf.clk_en == 1) { hw->clkm_conf.clk_en = 0; } + if (hw == &I2S0) { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + } else { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); + } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) + /** * @brief I2S tx msb right enable * diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 1bf9d1ecc40e..e79f5ec9c520 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -17,6 +17,7 @@ #include "hal/assert.h" #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" +#include "soc/system_struct.h" #include "hal/i2s_types.h" #include "hal/hal_utils.h" @@ -43,9 +44,15 @@ extern "C" { */ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { + SYSTEM.perip_clk_en0.reg_i2s1_clk_en = 1; + SYSTEM.perip_rst_en0.reg_i2s1_rst = 0; hw->tx_clkm_conf.clk_en = 1; } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) + /** * @brief I2S module disable I2S clock. * @@ -54,8 +61,14 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) static inline void i2s_ll_disable_clock(i2s_dev_t *hw) { hw->tx_clkm_conf.clk_en = 0; + SYSTEM.perip_clk_en0.reg_i2s1_clk_en = 0; + SYSTEM.perip_rst_en0.reg_i2s1_rst = 1; } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) + /** * @brief Enable I2S tx module clock * @@ -86,6 +99,11 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) hw->tx_clkm_conf.tx_clk_active = 0; } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +// i2s_ll_tx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity +#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__) + /** * @brief Disable I2S rx module clock * @@ -96,6 +114,11 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) hw->rx_clkm_conf.rx_clk_active = 0; } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +// i2s_ll_rx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity +#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__) + /** * @brief I2S mclk use tx module clock * diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index 33da02f677ae..86c5788fbfd7 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -44,8 +44,8 @@ extern "C" { */ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { - // The clock gate enabling is moved to `periph_module_enable` - (void)hw; + PCR.i2s_conf.i2s_clk_en = 1; + PCR.i2s_conf.i2s_rst_en = 0; } /** @@ -55,8 +55,8 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_disable_clock(i2s_dev_t *hw) { - // The clock gate disabling is moved to `periph_module_disable` - (void)hw; + PCR.i2s_conf.i2s_clk_en = 0; + PCR.i2s_conf.i2s_rst_en = 1; } /** diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index c7cd73dd4fc4..9f9e648ce855 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -45,8 +45,8 @@ extern "C" { */ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { - // The clock gate enabling is moved to `periph_module_enable` - (void)hw; + PCR.i2s_conf.i2s_clk_en = 1; + PCR.i2s_conf.i2s_rst_en = 0; } /** @@ -56,8 +56,8 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_disable_clock(i2s_dev_t *hw) { - // The clock gate disabling is moved to `periph_module_disable` - (void)hw; + PCR.i2s_conf.i2s_clk_en = 0; + PCR.i2s_conf.i2s_rst_en = 1; } /** diff --git a/components/hal/esp32p4/include/hal/clk_gate_ll.h b/components/hal/esp32p4/include/hal/clk_gate_ll.h index 48e7a095099f..8b21f7dfbb8b 100644 --- a/components/hal/esp32p4/include/hal/clk_gate_ll.h +++ b/components/hal/esp32p4/include/hal/clk_gate_ll.h @@ -36,12 +36,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return HP_SYS_CLKRST_REG_I2C0_APB_CLK_EN; case PERIPH_I2C1_MODULE: return HP_SYS_CLKRST_REG_I2C1_APB_CLK_EN; - case PERIPH_I2S0_MODULE: - return HP_SYS_CLKRST_REG_I2S0_TX_CLK_EN | HP_SYS_CLKRST_REG_I2S0_RX_CLK_EN; - case PERIPH_I2S1_MODULE: - return HP_SYS_CLKRST_REG_I2S1_RX_CLK_EN | HP_SYS_CLKRST_REG_I2S1_TX_CLK_EN; - case PERIPH_I2S2_MODULE: - return HP_SYS_CLKRST_REG_I2S2_RX_CLK_EN | HP_SYS_CLKRST_REG_I2S2_TX_CLK_EN; case PERIPH_LCD_MODULE: return HP_SYS_CLKRST_REG_LCD_CLK_EN; case PERIPH_UART0_MODULE: @@ -151,12 +145,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return HP_SYS_CLKRST_REG_RST_EN_CAN2; case PERIPH_LEDC_MODULE: return HP_SYS_CLKRST_REG_RST_EN_LEDC; - case PERIPH_I2S0_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_I2S0_APB; - case PERIPH_I2S1_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_I2S1_APB; - case PERIPH_I2S2_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_I2S2_APB; case PERIPH_GPSPI2_MODULE: return HP_SYS_CLKRST_REG_RST_EN_SPI2; case PERIPH_GPSPI3_MODULE: @@ -294,10 +282,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) case PERIPH_TWAI1_MODULE: case PERIPH_TWAI2_MODULE: case PERIPH_LEDC_MODULE: - case PERIPH_I2S0_MODULE: - return HP_SYS_CLKRST_HP_RST_EN1_REG; - case PERIPH_I2S1_MODULE: - case PERIPH_I2S2_MODULE: case PERIPH_GPSPI2_MODULE: case PERIPH_GPSPI3_MODULE: case PERIPH_CAM_MODULE: diff --git a/components/hal/esp32p4/include/i2s_ll.h b/components/hal/esp32p4/include/hal/i2s_ll.h similarity index 76% rename from components/hal/esp32p4/include/i2s_ll.h rename to components/hal/esp32p4/include/hal/i2s_ll.h index c2ce486e048d..3d7027ede326 100644 --- a/components/hal/esp32p4/include/i2s_ll.h +++ b/components/hal/esp32p4/include/hal/i2s_ll.h @@ -17,7 +17,7 @@ #include "hal/assert.h" #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" -#include "soc/pcr_struct.h" +#include "soc/hp_sys_clkrst_struct.h" #include "hal/i2s_types.h" @@ -26,6 +26,7 @@ extern "C" { #endif #define I2S_LL_GET_HW(num) (((num) == 0)? (&I2S0) : ((num) == 1) ? (&I2S1) : (&I2S2)) +#define I2S_LL_GET_ID(hw) (((hw) == &I2S0)? 0 : ((hw) == &I2S1) ? 1 : 2) #define I2S_LL_TDM_CH_MASK (0xffff) #define I2S_LL_PDM_BCK_FACTOR (64) @@ -53,10 +54,30 @@ typedef struct { */ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { - // The clock gate enabling is moved to `periph_module_enable` - (void)hw; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s0_apb_clk_en = 1; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s0_apb = 0; + break; + case 1: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s1_apb_clk_en = 1; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s1_apb = 0; + break; + case 2: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s2_apb_clk_en = 1; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s2_apb = 0; + break; + default: + // Never reach + HAL_ASSERT(false); + } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) + /** * @brief I2S module disable I2S clock. * @@ -64,10 +85,30 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_disable_clock(i2s_dev_t *hw) { - // The clock gate disabling is moved to `periph_module_disable` - (void)hw; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s0_apb_clk_en = 0; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s0_apb = 1; + break; + case 1: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s1_apb_clk_en = 0; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s1_apb = 1; + break; + case 2: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s2_apb_clk_en = 0; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s2_apb = 1; + break; + default: + // Never reach + HAL_ASSERT(false); + } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) + /** * @brief Enable I2S tx module clock * @@ -75,8 +116,18 @@ static inline void i2s_ll_disable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) { - (void)hw; - PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 1; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_clk_en = 1; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_tx_clk_en = 1; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_tx_clk_en = 1; + return; + } } /** @@ -86,8 +137,18 @@ static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) { - (void)hw; - PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 1; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl11.reg_i2s0_rx_clk_en = 1; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s1_rx_clk_en = 1; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_clk_en = 1; + return; + } } /** @@ -97,10 +158,24 @@ static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) { - (void)hw; - PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 0; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_clk_en = 0; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_tx_clk_en = 0; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_tx_clk_en = 0; + return; + } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__) + /** * @brief Disable I2S rx module clock * @@ -108,10 +183,24 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) { - (void)hw; - PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 0; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl11.reg_i2s0_rx_clk_en = 0; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s1_rx_clk_en = 0; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_clk_en = 0; + return; + } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__) + /** * @brief I2S mclk use tx module clock * @@ -119,8 +208,18 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) */ static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw) { - (void)hw; - PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 0; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_mst_clk_sel = 0; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_mst_clk_sel = 0; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_mst_clk_sel = 0; + return; + } } /** @@ -130,8 +229,18 @@ static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw) */ static inline void i2s_ll_mclk_bind_to_rx_clk(i2s_dev_t *hw) { - (void)hw; - PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 1; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_mst_clk_sel = 1; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_mst_clk_sel = 1; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_mst_clk_sel = 1; + return; + } } /** @@ -200,6 +309,22 @@ static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) hw->rx_conf.rx_fifo_reset = 0; } +static inline uint32_t i2s_ll_get_clk_src(i2s_clock_src_t src) +{ + switch (src) + { + case I2S_CLK_SRC_XTAL: + return 0; + case I2S_CLK_SRC_APLL: + return 1; + case I2S_CLK_SRC_EXTERNAL: + return 2; + default: + HAL_ASSERT(false && "unsupported clock source"); + break; + } +} + /** * @brief Set TX source clock * @@ -208,18 +333,18 @@ static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) */ static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - (void)hw; - switch (src) - { - case I2S_CLK_SRC_XTAL: - PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 0; - break; - case I2S_CLK_SRC_APLL: - PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 1; - break; - default: - HAL_ASSERT(false && "unsupported clock source"); - break; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + uint32_t clk_src = i2s_ll_get_clk_src(src); + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_clk_src_sel = clk_src; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_tx_clk_src_sel = clk_src; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_tx_clk_src_sel = clk_src; + return; } } @@ -231,18 +356,18 @@ static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) */ static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - (void)hw; - switch (src) - { - case I2S_CLK_SRC_XTAL: - PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 0; - break; - case I2S_CLK_SRC_APLL: - PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 1; - break; - default: - HAL_ASSERT(false && "unsupported clock source"); - break; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + uint32_t clk_src = i2s_ll_get_clk_src(src); + switch (I2S_LL_GET_ID(hw)) { + case 0: + HP_SYS_CLKRST.peri_clk_ctrl11.reg_i2s0_rx_clk_src_sel = clk_src; + return; + case 1: + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s1_rx_clk_src_sel = clk_src; + return; + case 2: + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_clk_src_sel = clk_src; + return; } } @@ -269,14 +394,30 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - (void)hw; - HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); - typeof(PCR.i2s_tx_clkm_div_conf) div = {}; - div.i2s_tx_clkm_div_x = x; - div.i2s_tx_clkm_div_y = y; - div.i2s_tx_clkm_div_z = z; - div.i2s_tx_clkm_div_yn1 = yn1; - PCR.i2s_tx_clkm_div_conf.val = div.val; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl13, reg_i2s0_tx_div_n, div_int); + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_div_x = x; + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_yn1 = yn1; + return; + case 1: + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl16, reg_i2s1_tx_div_n, div_int); + HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_x = x; + HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_yn1 = yn1; + return; + case 2: + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl18, reg_i2s2_tx_div_n, div_int); + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_x = x; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_yn1 = yn1; + return; + } } /** @@ -291,14 +432,30 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - (void)hw; - HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); - typeof(PCR.i2s_rx_clkm_div_conf) div = {}; - div.i2s_rx_clkm_div_x = x; - div.i2s_rx_clkm_div_y = y; - div.i2s_rx_clkm_div_z = z; - div.i2s_rx_clkm_div_yn1 = yn1; - PCR.i2s_rx_clkm_div_conf.val = div.val; + // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer + switch (I2S_LL_GET_ID(hw)) { + case 0: + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl12, reg_i2s0_rx_div_n, div_int); + HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_x = x; + HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_yn1 = yn1; + return; + case 1: + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl14, reg_i2s1_rx_div_n, div_int); + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_x = x; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_yn1 = yn1; + return; + case 2: + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl17, reg_i2s2_rx_div_n, div_int); + HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_div_x = x; + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_y = y; + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_z = z; + HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_yn1 = yn1; + return; + } } /** @@ -890,13 +1047,12 @@ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) * @brief Enable RX PDM mode. * * @param hw Peripheral I2S hardware instance address. - * @param pdm_enable Set true to RX enable PDM mode */ -static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw) { - hw->rx_conf.rx_pdm_en = pdm_enable; - hw->rx_conf.rx_tdm_en = !pdm_enable; - hw->rx_pdm2pcm_conf.rx_pdm2pcm_en = pdm_enable; + hw->rx_conf.rx_pdm_en = 1; + hw->rx_conf.rx_tdm_en = 0; + hw->rx_pdm2pcm_conf.rx_pdm2pcm_en = 1; } /** @@ -1198,6 +1354,7 @@ static inline void i2s_ll_tx_pdm_line_mode(i2s_dev_t *hw, i2s_pdm_tx_line_mode_t * * @param hw Peripheral I2S hardware instance address. */ +__attribute__((always_inline)) static inline void i2s_ll_tx_reset_fifo_sync_counter(i2s_dev_t *hw) { hw->fifo_cnt.tx_fifo_cnt_rst = 1; @@ -1209,8 +1366,9 @@ static inline void i2s_ll_tx_reset_fifo_sync_counter(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. * @return - * count value + * bclk count value */ +__attribute__((always_inline)) static inline uint32_t i2s_ll_tx_get_fifo_sync_count(i2s_dev_t *hw) { return hw->fifo_cnt.tx_fifo_cnt; @@ -1221,6 +1379,7 @@ static inline uint32_t i2s_ll_tx_get_fifo_sync_count(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ +__attribute__((always_inline)) static inline void i2s_ll_tx_reset_bclk_sync_counter(i2s_dev_t *hw) { hw->bck_cnt.tx_bck_cnt_rst = 1; @@ -1232,9 +1391,10 @@ static inline void i2s_ll_tx_reset_bclk_sync_counter(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. * @return - * count value + * fifo count value */ -static inline void i2s_ll_tx_get_bclk_sync_count(i2s_dev_t *hw) +__attribute__((always_inline)) +static inline uint32_t i2s_ll_tx_get_bclk_sync_count(i2s_dev_t *hw) { return hw->bck_cnt.tx_bck_cnt; } diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 30d481d9c867..f8791f1d19e9 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -18,6 +18,8 @@ #include "hal/misc.h" #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" +#include "soc/system_reg.h" +#include "soc/dport_access.h" #include "hal/i2s_types.h" #include "hal/hal_utils.h" @@ -87,6 +89,13 @@ static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en) */ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { + if (hw == &I2S0) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + } else { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); + } if (hw->clkm_conf.clk_en == 0) { hw->clkm_conf.clk_sel = 2; hw->clkm_conf.clk_en = 1; @@ -94,6 +103,10 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) + /** * @brief I2S module disable clock. * @@ -104,8 +117,19 @@ static inline void i2s_ll_disable_clock(i2s_dev_t *hw) if (hw->clkm_conf.clk_en == 1) { hw->clkm_conf.clk_en = 0; } + if (hw == &I2S0) { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + } else { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); + } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) + /** * @brief I2S tx msb right enable * diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 4880c6850da1..ac4d99f859a1 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -17,6 +17,7 @@ #include "hal/assert.h" #include "soc/i2s_periph.h" #include "soc/i2s_struct.h" +#include "soc/system_struct.h" #include "hal/i2s_types.h" #include "hal/hal_utils.h" @@ -44,9 +45,20 @@ extern "C" { */ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { + if (hw == &I2S0) { + SYSTEM.perip_clk_en0.i2s0_clk_en = 1; + SYSTEM.perip_rst_en0.i2s0_rst = 0; + } else { + SYSTEM.perip_clk_en0.i2s1_clk_en = 1; + SYSTEM.perip_rst_en0.i2s1_rst = 0; + } hw->tx_clkm_conf.clk_en = 1; } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) + /** * @brief I2S module disable I2S clock. * @@ -55,8 +67,19 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) static inline void i2s_ll_disable_clock(i2s_dev_t *hw) { hw->tx_clkm_conf.clk_en = 0; + if (hw == &I2S0) { + SYSTEM.perip_clk_en0.i2s0_clk_en = 0; + SYSTEM.perip_rst_en0.i2s0_rst = 1; + } else { + SYSTEM.perip_clk_en0.i2s1_clk_en = 0; + SYSTEM.perip_rst_en0.i2s1_rst = 1; + } } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) + /** * @brief Enable I2S tx module clock * @@ -87,6 +110,11 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) hw->tx_clkm_conf.tx_clk_active = 0; } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +// i2s_ll_tx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity +#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__) + /** * @brief Disable I2S rx module clock * @@ -97,6 +125,11 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) hw->rx_clkm_conf.rx_clk_active = 0; } +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +// i2s_ll_rx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity +#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__) + /** * @brief I2S mclk use tx module clock * diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 1803bd51f8c9..15653cce8415 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -243,7 +243,7 @@ void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha i2s_ll_rx_set_active_chan_mask(hal->dev, slot_mask); #endif // SOC_I2S_HW_VERSION_1 -#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER // TODO: add this macro to soc_caps +#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER uint32_t param0; uint32_t param5; s_i2s_hal_get_cut_off_coef(slot_cfg->pdm_rx.hp_cut_off_freq_hz, ¶m0, ¶m5); diff --git a/components/soc/esp32c3/i2s_periph.c b/components/soc/esp32c3/i2s_periph.c index 0aad6d6cad52..ec14aa72a26d 100644 --- a/components/soc/esp32c3/i2s_periph.c +++ b/components/soc/esp32c3/i2s_periph.c @@ -29,7 +29,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, - .irq = -1, + .irq = ETS_I2S1_INTR_SOURCE, .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32c6/i2s_periph.c b/components/soc/esp32c6/i2s_periph.c index 3965e936eee5..cb0a6a14ff6e 100644 --- a/components/soc/esp32c6/i2s_periph.c +++ b/components/soc/esp32c6/i2s_periph.c @@ -29,7 +29,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_out_sigs[1] = I2SO_SD1_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, - .irq = -1, + .irq = ETS_I2S1_INTR_SOURCE, .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32h2/i2s_periph.c b/components/soc/esp32h2/i2s_periph.c index 4183de00a680..cf70f2cb946c 100644 --- a/components/soc/esp32h2/i2s_periph.c +++ b/components/soc/esp32h2/i2s_periph.c @@ -28,7 +28,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_out_sig = I2SO_SD_OUT_IDX, .data_in_sig = I2SI_SD_IN_IDX, - .irq = -1, + .irq = ETS_I2S1_INTR_SOURCE, .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32p4/i2s_periph.c b/components/soc/esp32p4/i2s_periph.c index 66225f77c1de..39078caab4ac 100644 --- a/components/soc/esp32p4/i2s_periph.c +++ b/components/soc/esp32p4/i2s_periph.c @@ -13,6 +13,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { [0] = { .mck_out_sig = I2S0_MCLK_PAD_OUT_IDX, + .mck_in_sig = I2S0_MCLK_PAD_IN_IDX, .m_tx_bck_sig = I2S0_O_BCK_PAD_OUT_IDX, .m_rx_bck_sig = I2S0_I_BCK_PAD_OUT_IDX, @@ -31,11 +32,12 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[2] = I2S0_I_SD2_PAD_IN_IDX, .data_in_sigs[3] = I2S0_I_SD3_PAD_IN_IDX, - .irq = -1, + .irq = ETS_I2S0_INTR_SOURCE, .module = PERIPH_I2S0_MODULE, }, [1] = { .mck_out_sig = I2S1_MCLK_PAD_OUT_IDX, + .mck_in_sig = I2S1_MCLK_PAD_IN_IDX, .m_tx_bck_sig = I2S1_O_BCK_PAD_OUT_IDX, .m_rx_bck_sig = I2S1_I_BCK_PAD_OUT_IDX, @@ -54,11 +56,12 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[2] = -1, .data_in_sigs[3] = -1, - .irq = -1, + .irq = ETS_I2S1_INTR_SOURCE, .module = PERIPH_I2S1_MODULE, }, [2] = { .mck_out_sig = I2S2_MCLK_PAD_OUT_IDX, + .mck_in_sig = I2S2_MCLK_PAD_IN_IDX, .m_tx_bck_sig = I2S2_O_BCK_PAD_OUT_IDX, .m_rx_bck_sig = I2S2_I_BCK_PAD_OUT_IDX, @@ -77,7 +80,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[2] = -1, .data_in_sigs[3] = -1, - .irq = -1, + .irq = ETS_I2S2_INTR_SOURCE, .module = PERIPH_I2S2_MODULE, }, }; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 28c867a8765c..fbc3963a49c5 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -67,11 +67,11 @@ config SOC_RMT_SUPPORTED bool default y -config SOC_I2C_SUPPORTED +config SOC_I2S_SUPPORTED bool default y -config SOC_I2S_SUPPORTED +config SOC_I2C_SUPPORTED bool default y @@ -471,6 +471,10 @@ config SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER bool default y +config SOC_I2S_SUPPORTS_TX_SYNC_CNT + bool + default y + config SOC_I2S_SUPPORTS_TDM bool default y @@ -1127,6 +1131,10 @@ config SOC_MODEM_CLOCK_IS_INDEPENDENT bool default n +config SOC_CLK_APLL_SUPPORTED + bool + default y + config SOC_CLK_XTAL32K_SUPPORTED bool default y diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 7137ba4a12ca..664e5d4b7b99 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -338,7 +338,7 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of I2S */ -#define SOC_I2S_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL} +#define SOC_I2S_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL, I2S_CLK_SRC_EXTERNAL} /** * @brief I2S clock source enum @@ -347,6 +347,7 @@ typedef enum { I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default source clock */ I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ I2S_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */ + I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */ } soc_periph_i2s_clk_src_t; /////////////////////////////////////////////////I2C//////////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32p4/include/soc/rtc.h b/components/soc/esp32p4/include/soc/rtc.h index a27bacea551c..f81d22c20564 100644 --- a/components/soc/esp32p4/include/soc/rtc.h +++ b/components/soc/esp32p4/include/soc/rtc.h @@ -486,6 +486,44 @@ bool rtc_dig_8m_enabled(void); */ uint32_t rtc_clk_freq_cal(uint32_t cal_val); +/** + * @brief Enable or disable APLL + * + * Output frequency is given by the formula: + * apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((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. + * + * @param enable true to enable, false to disable + */ +void rtc_clk_apll_enable(bool enable); + +/** + * @brief Calculate APLL clock coeffifcients + * + * @param freq expected APLL frequency + * @param o_div frequency divider, 0..31 + * @param sdm0 frequency adjustment parameter, 0..255 + * @param sdm1 frequency adjustment parameter, 0..255 + * @param sdm2 frequency adjustment parameter, 0..63 + * + * @return + * - 0 Failed + * - else Sucess + */ +uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2); + +/** + * @brief Set APLL clock coeffifcients + * + * @param o_div frequency divider, 0..31 + * @param sdm0 frequency adjustment parameter, 0..255 + * @param sdm1 frequency adjustment parameter, 0..255 + * @param sdm2 frequency adjustment parameter, 0..63 + */ +void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2); // -------------------------- CLOCK TREE DEFS ALIAS ---------------------------- // **WARNING**: The following are only for backwards compatibility. diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index a4343f13d9b7..984d1526f922 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -251,6 +251,7 @@ #define SOC_I2S_SUPPORTS_PDM_TX (1) #define SOC_I2S_SUPPORTS_PDM_RX (1) #define SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER (1) +#define SOC_I2S_SUPPORTS_TX_SYNC_CNT (1) #define SOC_I2S_SUPPORTS_TDM (1) #define SOC_I2S_PDM_MAX_TX_LINES (2) // On I2S0 #define SOC_I2S_PDM_MAX_RX_LINES (4) // On I2S0 @@ -515,6 +516,7 @@ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (0) #define SOC_MODEM_CLOCK_IS_INDEPENDENT (0) +#define SOC_CLK_APLL_SUPPORTED (1) /*!< Support Audio PLL */ #define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ #define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */ #define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */ diff --git a/components/soc/esp32s3/i2s_periph.c b/components/soc/esp32s3/i2s_periph.c index 496626448343..853541bd9eb2 100644 --- a/components/soc/esp32s3/i2s_periph.c +++ b/components/soc/esp32s3/i2s_periph.c @@ -32,7 +32,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[2] = I2S0I_SD2_IN_IDX, .data_in_sigs[3] = I2S0I_SD3_IN_IDX, - .irq = -1, + .irq = ETS_I2S0_INTR_SOURCE, .module = PERIPH_I2S0_MODULE, }, { @@ -56,7 +56,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { .data_in_sigs[2] = -1, .data_in_sigs[3] = -1, - .irq = -1, + .irq = ETS_I2S1_INTR_SOURCE, .module = PERIPH_I2S1_MODULE, } }; diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 1622658bec39..d5bc6686d62b 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -55,28 +55,48 @@ examples/peripherals/i2c/i2c_tools: examples/peripherals/i2s/i2s_basic/i2s_pdm: disable: - if: SOC_I2S_SUPPORTS_PDM != 1 or IDF_TARGET == "esp32p4" + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners examples/peripherals/i2s/i2s_basic/i2s_std: disable: - if: SOC_I2S_SUPPORTED != 1 or IDF_TARGET == "esp32p4" + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners examples/peripherals/i2s/i2s_basic/i2s_tdm: disable: - if: SOC_I2S_SUPPORTS_TDM != 1 or IDF_TARGET == "esp32p4" + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm: disable: - if: SOC_I2S_SUPPORTS_TDM != 1 or (SOC_I2C_SUPPORTED != 1 or SOC_GPSPI_SUPPORTED != 1) reason: rely on I2S TDM mode to receive audio, I2C to config es7210 and SPI to save audio to SD card + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners examples/peripherals/i2s/i2s_codec/i2s_es8311: disable: - - if: (SOC_I2S_SUPPORTED != 1 or SOC_I2C_SUPPORTED != 1) or IDF_TARGET == "esp32p4" + - if: (SOC_I2S_SUPPORTED != 1 or SOC_I2C_SUPPORTED != 1) reason: rely on I2S STD mode and I2C to config es7210 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runners examples/peripherals/i2s/i2s_recorder: disable: - - if: IDF_TARGET == "esp32p4" + - if: SOC_SDMMC_HOST_SUPPORTED != 1 or IDF_TARGET == "esp32p4" enable: - if: SOC_I2S_SUPPORTS_PDM_RX > 0 diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md b/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md index bbfcf8f9f499..7bd46beba262 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md +++ b/examples/peripherals/i2s/i2s_codec/i2s_es8311/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # I2S ES8311 Example From 72a0746e626c8f690cfa2f1ccca2f87beb42f286 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 6 Sep 2023 10:55:47 +0800 Subject: [PATCH 107/142] refactor(apll): move the apll soc caps to clk_tree_ll --- components/driver/dac/esp32/dac_dma.c | 2 +- components/driver/dac/esp32s2/dac_dma.c | 7 +- components/driver/deprecated/i2s_legacy.c | 35 +++++---- components/driver/i2s/i2s_common.c | 16 ++-- components/driver/i2s/i2s_pdm.c | 6 +- components/driver/i2s/i2s_private.h | 10 ++- components/driver/i2s/i2s_std.c | 3 +- components/driver/i2s/i2s_tdm.c | 3 +- .../driver/i2s/include/driver/i2s_pdm.h | 13 ++-- .../esp_hw_support/include/clk_ctrl_os.h | 2 +- .../esp_hw_support/port/esp32/rtc_clk.c | 4 +- .../esp_hw_support/port/esp32s2/rtc_clk.c | 4 +- .../hal/esp32/include/hal/clk_tree_ll.h | 11 ++- components/hal/esp32/include/hal/i2s_ll.h | 67 +++++++++++------ components/hal/esp32c3/include/hal/i2s_ll.h | 51 +++++++------ components/hal/esp32c6/include/hal/i2s_ll.h | 30 ++++++-- components/hal/esp32h2/include/hal/i2s_ll.h | 30 ++++++-- .../hal/esp32p4/include/hal/clk_tree_ll.h | 10 +++ components/hal/esp32p4/include/hal/i2s_ll.h | 73 ++++++++++--------- .../hal/esp32s2/include/hal/clk_tree_ll.h | 11 ++- components/hal/esp32s2/include/hal/i2s_ll.h | 66 +++++++++++------ components/hal/esp32s3/include/hal/i2s_ll.h | 63 ++++++++-------- components/hal/i2s_hal.c | 40 ++++++---- components/hal/include/hal/i2s_hal.h | 23 +++++- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 16 ---- components/soc/esp32/include/soc/soc_caps.h | 7 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32p4/include/soc/soc_caps.h | 2 + .../esp32s2/include/soc/Kconfig.soc_caps.in | 16 ---- components/soc/esp32s2/include/soc/soc_caps.h | 5 -- 30 files changed, 374 insertions(+), 256 deletions(-) diff --git a/components/driver/dac/esp32/dac_dma.c b/components/driver/dac/esp32/dac_dma.c index b5bd20e9b97c..f1e648f16dd7 100644 --- a/components/driver/dac/esp32/dac_dma.c +++ b/components/driver/dac/esp32/dac_dma.c @@ -47,7 +47,7 @@ static const char *TAG = "DAC_DMA"; static uint32_t s_dac_set_apll_freq(uint32_t mclk) { /* Calculate the expected APLL */ - int div = (int)((SOC_APLL_MIN_HZ / mclk) + 1); + int div = (int)((CLK_LL_APLL_MIN_HZ / mclk) + 1); /* apll_freq = mclk * div * when div = 1, hardware will still divide 2 * when div = 0, hardware will divide 255 diff --git a/components/driver/dac/esp32s2/dac_dma.c b/components/driver/dac/esp32s2/dac_dma.c index af9dfb11c699..d13c63f39b93 100644 --- a/components/driver/dac/esp32s2/dac_dma.c +++ b/components/driver/dac/esp32s2/dac_dma.c @@ -19,6 +19,7 @@ #include "hal/dac_ll.h" #include "hal/adc_ll.h" #include "hal/hal_utils.h" +#include "hal/clk_tree_ll.h" #include "soc/lldesc.h" #include "soc/soc.h" #include "soc/soc_caps.h" @@ -75,9 +76,9 @@ static esp_err_t s_dac_dma_periph_set_clock(uint32_t freq_hz, bool is_apll){ uint32_t digi_ctrl_freq; // Digital controller clock if (is_apll) { /* Theoretical frequency range (due to the limitation of DAC, the maximum frequency may not reach): - * SOC_APLL_MAX_HZ: 119.24 Hz ~ 67.5 MHz - * SOC_APLL_MIN_HZ: 5.06 Hz ~ 2.65 MHz */ - digi_ctrl_freq = s_dac_set_apll_freq(freq_hz < 120 ? SOC_APLL_MIN_HZ :SOC_APLL_MAX_HZ); + * CLK_LL_APLL_MAX_HZ: 119.24 Hz ~ 67.5 MHz + * CLK_LL_APLL_MIN_HZ: 5.06 Hz ~ 2.65 MHz */ + digi_ctrl_freq = s_dac_set_apll_freq(freq_hz < 120 ? CLK_LL_APLL_MIN_HZ :CLK_LL_APLL_MAX_HZ); ESP_RETURN_ON_FALSE(digi_ctrl_freq, ESP_ERR_INVALID_ARG, TAG, "set APLL coefficients failed"); } else { digi_ctrl_freq = APB_CLK_FREQ; diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c index 939727597974..9b2ec2a3494b 100644 --- a/components/driver/deprecated/i2s_legacy.c +++ b/components/driver/deprecated/i2s_legacy.c @@ -25,6 +25,10 @@ #include "hal/gpio_hal.h" #include "driver/i2s_types_legacy.h" #include "hal/i2s_hal.h" +#if SOC_I2S_SUPPORTS_APLL +#include "hal/clk_tree_ll.h" +#endif + #if SOC_I2S_SUPPORTS_DAC #include "hal/dac_ll.h" #include "hal/dac_types.h" @@ -58,12 +62,16 @@ static const char *TAG = "i2s(legacy)"; #define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) +#if SOC_SYS_DIGI_CLKRST_REG_SHARED +#define I2S_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2S_CLOCK_SRC_ATOMIC() +#endif + #if !SOC_RCC_IS_INDEPENDENT -#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC() -#define I2S_RCC_ENV_DECLARE (void)__DECLARE_RCC_ATOMIC_ENV +#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC() #else #define I2S_RCC_ATOMIC() -#define I2S_RCC_ENV_DECLARE #endif #define I2S_DMA_BUFFER_MAX_SIZE 4092 @@ -641,7 +649,7 @@ static uint32_t i2s_config_source_clock(i2s_port_t i2s_num, bool use_apll, uint3 #if SOC_I2S_SUPPORTS_APLL if (use_apll) { /* Calculate the expected APLL */ - int div = (int)((SOC_APLL_MIN_HZ / mclk) + 1); + int div = (int)((CLK_LL_APLL_MIN_HZ / mclk) + 1); /* apll_freq = mclk * div * when div = 1, hardware will still divide 2 * when div = 0, the final mclk will be unpredictable @@ -1029,8 +1037,7 @@ static void i2s_set_clock_legacy(i2s_port_t i2s_num) i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg; i2s_hal_clock_info_t clk_info; i2s_calculate_clock(i2s_num, &clk_info); - I2S_RCC_ATOMIC() { - I2S_RCC_ENV_DECLARE; + I2S_CLOCK_SRC_ATOMIC() { if (p_i2s[i2s_num]->dir & I2S_DIR_TX) { i2s_hal_set_tx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src); } @@ -1538,14 +1545,13 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) #if SOC_I2S_SUPPORTS_APLL if (obj->use_apll) { - I2S_RCC_ATOMIC() { - I2S_RCC_ENV_DECLARE; + I2S_CLOCK_SRC_ATOMIC() { // switch back to PLL clock source if (obj->dir & I2S_DIR_TX) { - i2s_ll_tx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT); + i2s_hal_set_tx_clock(&obj->hal, NULL, I2S_CLK_SRC_DEFAULT); } if (obj->dir & I2S_DIR_RX) { - i2s_ll_rx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT); + i2s_hal_set_rx_clock(&obj->hal, NULL, I2S_CLK_SRC_DEFAULT); } } periph_rtc_apll_release(); @@ -1559,7 +1565,7 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) } #endif #if SOC_I2S_HW_VERSION_2 - I2S_RCC_ATOMIC() { + I2S_CLOCK_SRC_ATOMIC() { if (obj->dir & I2S_DIR_TX) { i2s_ll_tx_disable_clock(obj->hal.dev); } @@ -1910,7 +1916,9 @@ esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name) ret = ESP_OK; comp_using_i2s[id] = comp_name; I2S_RCC_ATOMIC() { - i2s_ll_enable_clock(I2S_LL_GET_HW(id)); + i2s_ll_enable_bus_clock(id, true); + i2s_ll_reset_register(id); + i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), true); } } portEXIT_CRITICAL(&i2s_spinlock[id]); @@ -1927,7 +1935,8 @@ esp_err_t i2s_platform_release_occupation(int id) comp_using_i2s[id] = NULL; /* Disable module clock */ I2S_RCC_ATOMIC() { - i2s_ll_disable_clock(I2S_LL_GET_HW(id)); + i2s_ll_enable_bus_clock(id, false); + i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), false); } } portEXIT_CRITICAL(&i2s_spinlock[id]); diff --git a/components/driver/i2s/i2s_common.c b/components/driver/i2s/i2s_common.c index 41dde28b7798..269fe52b5d4f 100644 --- a/components/driver/i2s/i2s_common.c +++ b/components/driver/i2s/i2s_common.c @@ -36,6 +36,7 @@ #include "driver/adc_i2s_legacy.h" #endif #if SOC_I2S_SUPPORTS_APLL +#include "hal/clk_tree_ll.h" #include "clk_ctrl_os.h" #endif @@ -401,7 +402,7 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu handle->dma.buf_size = bufsize; #if SOC_GDMA_TRIG_PERIPH_I2S0_BUS == SOC_GDMA_BUS_AHB - uint32_t alignment = 32; + uint32_t alignment = 64; uint32_t desc_size = alignment; #else uint32_t alignment = 4; @@ -448,14 +449,14 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu static uint32_t i2s_set_get_apll_freq(uint32_t mclk_freq_hz) { /* Calculate the expected APLL */ - int mclk_div = (int)((SOC_APLL_MIN_HZ / mclk_freq_hz) + 1); + int mclk_div = (int)((CLK_LL_APLL_MIN_HZ / mclk_freq_hz) + 1); /* apll_freq = mclk * div * when div = 1, hardware will still divide 2 * when div = 0, the final mclk will be unpredictable * So the div here should be at least 2 */ mclk_div = mclk_div < 2 ? 2 : mclk_div; uint32_t expt_freq = mclk_freq_hz * mclk_div; - if (expt_freq > SOC_APLL_MAX_HZ) { + if (expt_freq > CLK_LL_APLL_MAX_HZ) { ESP_LOGE(TAG, "The required APLL frequency exceed its maximum value"); return 0; } @@ -867,7 +868,7 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle) bool is_bound = true; #if SOC_I2S_HW_VERSION_2 - I2S_RCC_ATOMIC() { + I2S_CLOCK_SRC_ATOMIC() { if (dir == I2S_DIR_TX) { i2s_ll_tx_disable_clock(handle->controller->hal.dev); } else { @@ -1202,7 +1203,9 @@ esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name) g_i2s.comp_name[id] = comp_name; /* Enable module clock */ I2S_RCC_ATOMIC() { - i2s_ll_enable_clock(I2S_LL_GET_HW(id)); + i2s_ll_enable_bus_clock(id, true); + i2s_ll_reset_register(id); + i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), true); } } else { occupied_comp = g_i2s.comp_name[id]; @@ -1224,7 +1227,8 @@ esp_err_t i2s_platform_release_occupation(int id) g_i2s.comp_name[id] = NULL; /* Disable module clock */ I2S_RCC_ATOMIC() { - i2s_ll_disable_clock(I2S_LL_GET_HW(id)); + i2s_ll_enable_bus_clock(id, false); + i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), false); } } else { ret = ESP_ERR_INVALID_STATE; diff --git a/components/driver/i2s/i2s_pdm.c b/components/driver/i2s/i2s_pdm.c index 2426e896fef0..574247c0c82a 100644 --- a/components/driver/i2s/i2s_pdm.c +++ b/components/driver/i2s/i2s_pdm.c @@ -70,8 +70,7 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - I2S_RCC_ATOMIC() { - I2S_RCC_ENV_DECLARE; + I2S_CLOCK_SRC_ATOMIC() { i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); } #if SOC_I2S_HW_VERSION_2 @@ -357,8 +356,7 @@ static esp_err_t i2s_pdm_rx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_rx portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - I2S_RCC_ATOMIC() { - I2S_RCC_ENV_DECLARE; + I2S_CLOCK_SRC_ATOMIC() { i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); } portEXIT_CRITICAL(&g_i2s.spinlock); diff --git a/components/driver/i2s/i2s_private.h b/components/driver/i2s/i2s_private.h index 802eb32fbb5f..90858a04b430 100644 --- a/components/driver/i2s/i2s_private.h +++ b/components/driver/i2s/i2s_private.h @@ -36,12 +36,16 @@ extern "C" { #endif //CONFIG_I2S_ISR_IRAM_SAFE #define I2S_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) +#if SOC_SYS_DIGI_CLKRST_REG_SHARED +#define I2S_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define I2S_CLOCK_SRC_ATOMIC() +#endif + #if !SOC_RCC_IS_INDEPENDENT -#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC() -#define I2S_RCC_ENV_DECLARE (void)__DECLARE_RCC_ATOMIC_ENV +#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC() #else #define I2S_RCC_ATOMIC() -#define I2S_RCC_ENV_DECLARE #endif #define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL") diff --git a/components/driver/i2s/i2s_std.c b/components/driver/i2s/i2s_std.c index 0b32139c2160..715ca04399a6 100644 --- a/components/driver/i2s/i2s_std.c +++ b/components/driver/i2s/i2s_std.c @@ -77,8 +77,7 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - I2S_RCC_ATOMIC() { - I2S_RCC_ENV_DECLARE; + I2S_CLOCK_SRC_ATOMIC() { if (handle->dir == I2S_DIR_TX) { i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); } else { diff --git a/components/driver/i2s/i2s_tdm.c b/components/driver/i2s/i2s_tdm.c index b4353f8c8300..caed5c51a4f4 100644 --- a/components/driver/i2s/i2s_tdm.c +++ b/components/driver/i2s/i2s_tdm.c @@ -79,8 +79,7 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ - I2S_RCC_ATOMIC() { - I2S_RCC_ENV_DECLARE; + I2S_CLOCK_SRC_ATOMIC() { if (handle->dir == I2S_DIR_TX) { i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src); } else { diff --git a/components/driver/i2s/include/driver/i2s_pdm.h b/components/driver/i2s/include/driver/i2s_pdm.h index 11601166aaf0..f697c2371ba6 100644 --- a/components/driver/i2s/include/driver/i2s_pdm.h +++ b/components/driver/i2s/include/driver/i2s_pdm.h @@ -35,8 +35,8 @@ extern "C" { .slot_mode = mono_or_stereo, \ .slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \ I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \ - .hpf_en = true, \ - .hpf_cut_off_freq_hz = 35.5, \ + .hp_en = true, \ + .hp_cut_off_freq_hz = 35.5, \ .amplify_num = 1, \ } #else @@ -81,7 +81,10 @@ typedef struct { #if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER bool hp_en; /*!< High pass filter enable */ float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */ - uint32_t amplify_num; /*!< The amplification number of the final conversion result, range 1~15, default 1 */ + uint32_t amplify_num; /*!< The amplification number of the final conversion result. + * The data that have converted from PDM to PCM module, will time 'amplify_num' additionally to amplify the final result. + * Note that it's only a multiplier of the digital PCM data, not the gain of the analog signal + * range 1~15, default 1 */ #endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER } i2s_pdm_rx_slot_config_t; @@ -331,8 +334,8 @@ typedef struct { i2s_pdm_sig_scale_t sinc_scale; /*!< Sinc filter scaling value */ #if SOC_I2S_HW_VERSION_2 i2s_pdm_tx_line_mode_t line_mode; /*!< PDM TX line mode, one-line codec, one-line dac, two-line dac mode can be selected */ - bool hpf_en; /*!< High pass filter enable */ - float hpf_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */ + bool hp_en; /*!< High pass filter enable */ + float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */ uint32_t sd_dither; /*!< Sigma-delta filter dither */ uint32_t sd_dither2; /*!< Sigma-delta filter dither2 */ #endif // SOC_I2S_HW_VERSION_2 diff --git a/components/esp_hw_support/include/clk_ctrl_os.h b/components/esp_hw_support/include/clk_ctrl_os.h index 519fddee407c..99366497fe93 100644 --- a/components/esp_hw_support/include/clk_ctrl_os.h +++ b/components/esp_hw_support/include/clk_ctrl_os.h @@ -54,7 +54,7 @@ void periph_rtc_apll_release(void); * @brief Calculate and set APLL coefficients by given frequency * @note Have to call 'periph_rtc_apll_acquire' to enable APLL power before setting frequency * @note This calculation is based on the inequality: - * xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= SOC_APLL_MULTIPLIER_OUT_MIN_HZ(350 MHz) + * xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= CLK_LL_APLL_MULTIPLIER_MIN_HZ(350 MHz) * It will always calculate the minimum coefficients that can satisfy the inequality above, instead of loop them one by one. * which means more appropriate coefficients are likely to exist. * But this algorithm can meet almost all the cases and the accuracy can be guaranteed as well. diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index 384964e3d318..1856425f2e9f 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -217,7 +217,7 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz, '+1' in the following code is to get the ceil value. * With this condition, as we know the 'o_div' can't be greater than 31, then we can calculate the APLL minimum support frequency is * 350 MHz / ((31 + 2) * 2) = 5303031 Hz (for ceil) */ - o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MIN_HZ / (float)(freq * 2) + 1) - 2; + o_div = (int)(CLK_LL_APLL_MULTIPLIER_MIN_HZ / (float)(freq * 2) + 1) - 2; if (o_div > 31) { ESP_HW_LOGE(TAG, "Expected frequency is too small"); return 0; @@ -227,7 +227,7 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz, we need to get the floor value in the following code. * With this condition, as we know the 'o_div' can't be smaller than 0, then we can calculate the APLL maximum support frequency is * 500 MHz / ((0 + 2) * 2) = 125000000 Hz */ - o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MAX_HZ / (float)(freq * 2)) - 2; + o_div = (int)(CLK_LL_APLL_MULTIPLIER_MAX_HZ / (float)(freq * 2)) - 2; if (o_div < 0) { ESP_HW_LOGE(TAG, "Expected frequency is too big"); return 0; diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index 8c77c4cd88fa..75558b8f50a5 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -119,7 +119,7 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz, '+1' in the following code is to get the ceil value. * With this condition, as we know the 'o_div' can't be greater than 31, then we can calculate the APLL minimum support frequency is * 350 MHz / ((31 + 2) * 2) = 5303031 Hz (for ceil) */ - o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MIN_HZ / (float)(freq * 2) + 1) - 2; + o_div = (int)(CLK_LL_APLL_MULTIPLIER_MIN_HZ / (float)(freq * 2) + 1) - 2; if (o_div > 31) { ESP_HW_LOGE(TAG, "Expected frequency is too small"); return 0; @@ -129,7 +129,7 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz, we need to get the floor value in the following code. * With this condition, as we know the 'o_div' can't be smaller than 0, then we can calculate the APLL maximum support frequency is * 500 MHz / ((0 + 2) * 2) = 125000000 Hz */ - o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MAX_HZ / (float)(freq * 2)) - 2; + o_div = (int)(CLK_LL_APLL_MULTIPLIER_MAX_HZ / (float)(freq * 2)) - 2; if (o_div < 0) { ESP_HW_LOGE(TAG, "Expected frequency is too big"); return 0; diff --git a/components/hal/esp32/include/hal/clk_tree_ll.h b/components/hal/esp32/include/hal/clk_tree_ll.h index 79ea9fc00306..67ae94a51a3b 100644 --- a/components/hal/esp32/include/hal/clk_tree_ll.h +++ b/components/hal/esp32/include/hal/clk_tree_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -73,6 +73,15 @@ extern "C" { #define CLK_LL_XTAL_32K_BOOTSTRAP_DRES_VAL 3 #define CLK_LL_XTAL_32K_BOOTSTRAP_DBIAS_VAL 0 +/* APLL multiplier output frequency range */ +// apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) +#define CLK_LL_APLL_MULTIPLIER_MIN_HZ (350000000) // 350 MHz +#define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz + +/* APLL output frequency range */ +#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation +#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation + /** * @brief XTAL32K_CLK enable modes */ diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index d718d17a3418..a6a7a1b15fa8 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -85,51 +85,72 @@ static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en) } /** - * @brief I2S module general init, enable I2S clock. + * @brief Enable the bus clock for I2S module * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock + */ +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) +{ + if (enable) { + if (i2s_id == 0) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + } else { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + } + } else if (i2s_id == 1) { + if (i2s_id == 0) { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + } else { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + } + } +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_bus_clock(__VA_ARGS__) + + +/** + * @brief Reset the I2S module + * + * @param i2s_id The port id of I2S */ -static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +static inline void i2s_ll_reset_register(int i2s_id) { - if (hw == &I2S0) { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + if (i2s_id == 0) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); - } else { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + } else if (i2s_id == 1) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); } - if (hw->clkm_conf.clk_en == 0) { - hw->clkm_conf.clk_en = 1; - hw->conf2.val = 0; - } } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) +#define i2s_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_reset_register(__VA_ARGS__) /** - * @brief I2S module disable clock. + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock */ -static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) { - if (hw->clkm_conf.clk_en == 1) { + if (enable && !hw->clkm_conf.clk_en) { + hw->clkm_conf.clk_en = 1; + hw->conf2.val = 0; + } else if (!enable && hw->clkm_conf.clk_en) { hw->clkm_conf.clk_en = 0; } - if (hw == &I2S0) { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); - } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); - } } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) +#define i2s_ll_enable_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_core_clock(__VA_ARGS__) /** * @brief I2S tx msb right enable diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index e79f5ec9c520..1b7e9de0da51 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -37,37 +37,54 @@ extern "C" { #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT + /** - * @brief I2S module general init, enable I2S clock. + * @brief Enable the bus clock for I2S module * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock + */ +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) +{ + (void)i2s_id; + SYSTEM.perip_clk_en0.reg_i2s1_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_bus_clock(__VA_ARGS__) + + +/** + * @brief Reset the I2S module + * + * @param i2s_id The port id of I2S */ -static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +static inline void i2s_ll_reset_register(int i2s_id) { - SYSTEM.perip_clk_en0.reg_i2s1_clk_en = 1; + (void)i2s_id; + SYSTEM.perip_rst_en0.reg_i2s1_rst = 1; SYSTEM.perip_rst_en0.reg_i2s1_rst = 0; - hw->tx_clkm_conf.clk_en = 1; } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) +#define i2s_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_reset_register(__VA_ARGS__) /** - * @brief I2S module disable I2S clock. + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock */ -static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) { - hw->tx_clkm_conf.clk_en = 0; - SYSTEM.perip_clk_en0.reg_i2s1_clk_en = 0; - SYSTEM.perip_rst_en0.reg_i2s1_rst = 1; + hw->tx_clkm_conf.clk_en = enable; } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) +#define i2s_ll_enable_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_core_clock(__VA_ARGS__) /** * @brief Enable I2S tx module clock @@ -99,11 +116,6 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) hw->tx_clkm_conf.tx_clk_active = 0; } -/// use a macro to wrap the function, force the caller to use it in a critical section -/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -// i2s_ll_tx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity -#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__) - /** * @brief Disable I2S rx module clock * @@ -114,11 +126,6 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) hw->rx_clkm_conf.rx_clk_active = 0; } -/// use a macro to wrap the function, force the caller to use it in a critical section -/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -// i2s_ll_rx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity -#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__) - /** * @brief I2S mclk use tx module clock * diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index 86c5788fbfd7..52c15d43f0a2 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -38,25 +38,39 @@ extern "C" { #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** - * @brief I2S module general init, enable I2S clock. * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock + */ +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) +{ + (void)i2s_id; + PCR.i2s_conf.i2s_clk_en = enable; +} + +/** + * @brief Reset the I2S module + * + * @param i2s_id The port id of I2S */ -static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +static inline void i2s_ll_reset_register(int i2s_id) { - PCR.i2s_conf.i2s_clk_en = 1; + (void)i2s_id; + PCR.i2s_conf.i2s_rst_en = 1; PCR.i2s_conf.i2s_rst_en = 0; } /** - * @brief I2S module disable I2S clock. + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock */ -static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) { - PCR.i2s_conf.i2s_clk_en = 0; - PCR.i2s_conf.i2s_rst_en = 1; + (void)hw; + (void)enable; + // No need to do anything } /** diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 9f9e648ce855..0baf7101e55e 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -39,25 +39,39 @@ extern "C" { #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F96M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT /** - * @brief I2S module general init, enable I2S clock. * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock + */ +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) +{ + (void)i2s_id; + PCR.i2s_conf.i2s_clk_en = enable; +} + +/** + * @brief Reset the I2S module + * + * @param i2s_id The port id of I2S */ -static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +static inline void i2s_ll_reset_register(int i2s_id) { - PCR.i2s_conf.i2s_clk_en = 1; + (void)i2s_id; + PCR.i2s_conf.i2s_rst_en = 1; PCR.i2s_conf.i2s_rst_en = 0; } /** - * @brief I2S module disable I2S clock. + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock */ -static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) { - PCR.i2s_conf.i2s_clk_en = 0; - PCR.i2s_conf.i2s_rst_en = 1; + (void)hw; + (void)enable; + // No need to do anything } /** diff --git a/components/hal/esp32p4/include/hal/clk_tree_ll.h b/components/hal/esp32p4/include/hal/clk_tree_ll.h index c3fee0041aa1..29a38bdfc51a 100644 --- a/components/hal/esp32p4/include/hal/clk_tree_ll.h +++ b/components/hal/esp32p4/include/hal/clk_tree_ll.h @@ -30,6 +30,16 @@ extern "C" { #define CLK_LL_PLL_480M_FREQ_MHZ (480) +/* APLL multiplier output frequency range */ +// TODO: IDF-7526 check if the APLL frequency range is same as before +// apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) +#define CLK_LL_APLL_MULTIPLIER_MIN_HZ (350000000) // 350 MHz +#define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz + +/* APLL output frequency range */ +#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation +#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation + #define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ .dac = 3, \ .dres = 3, \ diff --git a/components/hal/esp32p4/include/hal/i2s_ll.h b/components/hal/esp32p4/include/hal/i2s_ll.h index 3d7027ede326..0fd64cad6f17 100644 --- a/components/hal/esp32p4/include/hal/i2s_ll.h +++ b/components/hal/esp32p4/include/hal/i2s_ll.h @@ -48,66 +48,73 @@ typedef struct { } i2s_ll_mclk_div_t; /** - * @brief I2S module general init, enable I2S clock. + * @brief Enable the bus clock for I2S module * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock */ -static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) { - // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer - switch (I2S_LL_GET_ID(hw)) { + switch (i2s_id) { case 0: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s0_apb_clk_en = 1; - HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s0_apb = 0; - break; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s0_apb_clk_en = enable; + return; case 1: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s1_apb_clk_en = 1; - HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s1_apb = 0; - break; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s1_apb_clk_en = enable; + return; case 2: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s2_apb_clk_en = 1; - HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s2_apb = 0; - break; - default: - // Never reach - HAL_ASSERT(false); + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s2_apb_clk_en = enable; + return; } } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) +#define i2s_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_bus_clock(__VA_ARGS__) /** - * @brief I2S module disable I2S clock. + * @brief Reset the I2S module * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S */ -static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +static inline void i2s_ll_reset_register(int i2s_id) { - // Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer - switch (I2S_LL_GET_ID(hw)) { + switch (i2s_id) { case 0: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s0_apb_clk_en = 0; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s0_apb = 1; - break; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s0_apb = 0; + return; case 1: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s1_apb_clk_en = 0; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s1_apb = 1; - break; + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s1_apb = 0; + return; case 2: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s2_apb_clk_en = 0; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s2_apb = 1; - break; - default: - // Never reach - HAL_ASSERT(false); + HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s2_apb = 0; + return; } } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) +#define i2s_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_reset_register(__VA_ARGS__) + +/** + * @brief I2S module general init, enable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock + */ +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) +{ + (void)hw; + (void)enable; + // No need to do anything +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_core_clock(__VA_ARGS__) /** * @brief Enable I2S tx module clock diff --git a/components/hal/esp32s2/include/hal/clk_tree_ll.h b/components/hal/esp32s2/include/hal/clk_tree_ll.h index f7d67937eea1..b0505b1ce28f 100644 --- a/components/hal/esp32s2/include/hal/clk_tree_ll.h +++ b/components/hal/esp32s2/include/hal/clk_tree_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -47,6 +47,15 @@ extern "C" { #define CLK_LL_APLL_CAL_DELAY_2 0x3f #define CLK_LL_APLL_CAL_DELAY_3 0x1f +/* APLL multiplier output frequency range */ +// apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) +#define CLK_LL_APLL_MULTIPLIER_MIN_HZ (350000000) // 350 MHz +#define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz + +/* APLL output frequency range */ +#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation +#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation + #define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ .dac = 3, \ .dres = 3, \ diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index f8791f1d19e9..2c97bf157a54 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -83,52 +83,72 @@ static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en) } /** - * @brief I2S module general init, enable I2S clock. + * @brief Enable the bus clock for I2S module * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock + */ +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) +{ + if (enable) { + if (i2s_id == 0) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + } else { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + } + } else { + if (i2s_id == 0) { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + } else { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + } + } +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the I2S module + * + * @param i2s_id The port id of I2S */ -static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +static inline void i2s_ll_reset_register(int i2s_id) { - if (hw == &I2S0) { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + if (i2s_id == 0) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); } else { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); } - if (hw->clkm_conf.clk_en == 0) { - hw->clkm_conf.clk_sel = 2; - hw->clkm_conf.clk_en = 1; - hw->conf2.val = 0; - } } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) +#define i2s_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_reset_register(__VA_ARGS__) /** - * @brief I2S module disable clock. + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock */ -static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) { - if (hw->clkm_conf.clk_en == 1) { + if (enable && !hw->clkm_conf.clk_en) { + hw->clkm_conf.clk_sel = 2; + hw->clkm_conf.clk_en = 1; + hw->conf2.val = 0; + } else if (!enable && hw->clkm_conf.clk_en) { hw->clkm_conf.clk_en = 0; } - if (hw == &I2S0) { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); - } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); - } } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) +#define i2s_ll_enable_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_core_clock(__VA_ARGS__) /** * @brief I2S tx msb right enable diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index ac4d99f859a1..89b53f8c24f1 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -38,47 +38,60 @@ extern "C" { #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT + /** - * @brief I2S module general init, enable I2S clock. + * @brief Enable the bus clock for I2S module * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S + * @param enable Set true to enable the buf clock */ -static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +static inline void i2s_ll_enable_bus_clock(int i2s_id, bool enable) { - if (hw == &I2S0) { - SYSTEM.perip_clk_en0.i2s0_clk_en = 1; - SYSTEM.perip_rst_en0.i2s0_rst = 0; - } else { - SYSTEM.perip_clk_en0.i2s1_clk_en = 1; - SYSTEM.perip_rst_en0.i2s1_rst = 0; + if (i2s_id == 0) { + SYSTEM.perip_clk_en0.i2s0_clk_en = enable; + } else if (i2s_id == 1) { + SYSTEM.perip_clk_en0.i2s1_clk_en = enable; } - hw->tx_clkm_conf.clk_en = 1; } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__) +#define i2s_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_bus_clock(__VA_ARGS__) /** - * @brief I2S module disable I2S clock. + * @brief Reset the I2S module * - * @param hw Peripheral I2S hardware instance address. + * @param i2s_id The port id of I2S */ -static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +static inline void i2s_ll_reset_register(int i2s_id) { - hw->tx_clkm_conf.clk_en = 0; - if (hw == &I2S0) { - SYSTEM.perip_clk_en0.i2s0_clk_en = 0; + if (i2s_id == 0) { SYSTEM.perip_rst_en0.i2s0_rst = 1; - } else { - SYSTEM.perip_clk_en0.i2s1_clk_en = 0; + SYSTEM.perip_rst_en0.i2s0_rst = 0; + } else if (i2s_id == 1) { SYSTEM.perip_rst_en0.i2s1_rst = 1; + SYSTEM.perip_rst_en0.i2s1_rst = 0; } } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__) +#define i2s_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_reset_register(__VA_ARGS__) + +/** + * @brief I2S module general init, enable I2S clock. + * + * @param hw Peripheral I2S hardware instance address. + * @param enable set true to enable the core clock + */ +static inline void i2s_ll_enable_core_clock(i2s_dev_t *hw, bool enable) +{ + hw->tx_clkm_conf.clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_ll_enable_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_core_clock(__VA_ARGS__) /** * @brief Enable I2S tx module clock @@ -110,11 +123,6 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw) hw->tx_clkm_conf.tx_clk_active = 0; } -/// use a macro to wrap the function, force the caller to use it in a critical section -/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -// i2s_ll_tx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity -#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__) - /** * @brief Disable I2S rx module clock * @@ -125,11 +133,6 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw) hw->rx_clkm_conf.rx_clk_active = 0; } -/// use a macro to wrap the function, force the caller to use it in a critical section -/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -// i2s_ll_rx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity -#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__) - /** * @brief I2S mclk use tx module clock * diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index 15653cce8415..5ea3de62d64a 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -65,30 +65,38 @@ void i2s_hal_init(i2s_hal_context_t *hal, int port_id) hal->dev = I2S_LL_GET_HW(port_id); } -void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src) +void _i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src) { - hal_utils_clk_div_t mclk_div = {}; + if (clk_info) { + hal_utils_clk_div_t mclk_div = {}; #if SOC_I2S_HW_VERSION_2 - i2s_ll_tx_enable_clock(hal->dev); - i2s_ll_mclk_bind_to_tx_clk(hal->dev); + i2s_ll_tx_enable_clock(hal->dev); + i2s_ll_mclk_bind_to_tx_clk(hal->dev); #endif - i2s_ll_tx_clk_set_src(hal->dev, clk_src); - i2s_hal_calc_mclk_precise_division(clk_info->sclk, clk_info->mclk, &mclk_div); - i2s_ll_tx_set_mclk(hal->dev, &mclk_div); - i2s_ll_tx_set_bck_div_num(hal->dev, clk_info->bclk_div); + i2s_ll_tx_clk_set_src(hal->dev, clk_src); + i2s_hal_calc_mclk_precise_division(clk_info->sclk, clk_info->mclk, &mclk_div); + i2s_ll_tx_set_mclk(hal->dev, &mclk_div); + i2s_ll_tx_set_bck_div_num(hal->dev, clk_info->bclk_div); + } else { + i2s_ll_tx_clk_set_src(hal->dev, clk_src); + } } -void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src) +void _i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src) { - hal_utils_clk_div_t mclk_div = {}; + if (clk_info) { + hal_utils_clk_div_t mclk_div = {}; #if SOC_I2S_HW_VERSION_2 - i2s_ll_rx_enable_clock(hal->dev); - i2s_ll_mclk_bind_to_rx_clk(hal->dev); + i2s_ll_rx_enable_clock(hal->dev); + i2s_ll_mclk_bind_to_rx_clk(hal->dev); #endif - i2s_ll_rx_clk_set_src(hal->dev, clk_src); - i2s_hal_calc_mclk_precise_division(clk_info->sclk, clk_info->mclk, &mclk_div); - i2s_ll_rx_set_mclk(hal->dev, &mclk_div); - i2s_ll_rx_set_bck_div_num(hal->dev, clk_info->bclk_div); + i2s_ll_rx_clk_set_src(hal->dev, clk_src); + i2s_hal_calc_mclk_precise_division(clk_info->sclk, clk_info->mclk, &mclk_div); + i2s_ll_rx_set_mclk(hal->dev, &mclk_div); + i2s_ll_rx_set_bck_div_num(hal->dev, clk_info->bclk_div); + } else { + i2s_ll_rx_clk_set_src(hal->dev, clk_src); + } } /*------------------------------------------------------------------------- diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index e2957e5cc440..6e8af9bf8444 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -142,20 +142,35 @@ void i2s_hal_calc_mclk_precise_division(uint32_t sclk, uint32_t mclk, hal_utils_ * @brief Set tx channel clock * * @param hal Context of the HAL layer - * @param clk_info clock information + * @param clk_info clock information, if it is NULL, only set the clock source * @param clk_src clock source */ -void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src); +void _i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src); + +#if SOC_SYS_DIGI_CLKRST_REG_SHARED +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_hal_set_tx_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _i2s_hal_set_tx_clock(__VA_ARGS__) +#else +#define i2s_hal_set_tx_clock(...) _i2s_hal_set_tx_clock(__VA_ARGS__) +#endif /** * @brief Set rx channel clock * * @param hal Context of the HAL layer - * @param clk_info clock information + * @param clk_info clock information, if it is NULL, only set the clock source * @param clk_src clock source */ -void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src); +void _i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src); +#if SOC_SYS_DIGI_CLKRST_REG_SHARED +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define i2s_hal_set_rx_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _i2s_hal_set_rx_clock(__VA_ARGS__) +#else +#define i2s_hal_set_rx_clock(...) _i2s_hal_set_rx_clock(__VA_ARGS__) +#endif /*------------------------------------------------------------------------- | STD configuration | diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index a3348e60225c..0945f539afeb 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -811,22 +811,6 @@ config SOC_CLK_APLL_SUPPORTED bool default y -config SOC_APLL_MULTIPLIER_OUT_MIN_HZ - int - default 350000000 - -config SOC_APLL_MULTIPLIER_OUT_MAX_HZ - int - default 500000000 - -config SOC_APLL_MIN_HZ - int - default 5303031 - -config SOC_APLL_MAX_HZ - int - default 125000000 - config SOC_CLK_RC_FAST_D256_SUPPORTED bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index ab27817b3461..a3ebb1c9b538 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -399,11 +399,6 @@ /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_APLL_SUPPORTED (1) -// apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) -#define SOC_APLL_MULTIPLIER_OUT_MIN_HZ (350000000) // 350 MHz -#define SOC_APLL_MULTIPLIER_OUT_MAX_HZ (500000000) // 500 MHz -#define SOC_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation -#define SOC_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation #define SOC_CLK_RC_FAST_D256_SUPPORTED (1) #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 (1) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index fbc3963a49c5..76a4587ddd52 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1123,6 +1123,10 @@ config SOC_PM_PAU_LINK_NUM int default 4 +config SOC_SYS_DIGI_CLKRST_REG_SHARED + bool + default y + config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default n diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 984d1526f922..d3a1b238703d 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -154,6 +154,7 @@ #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 +// TODO: IDF-5360 (Copy from esp32c3, need check) /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ /** The maximum length of a Digital Signature in bits. */ #define SOC_DS_SIGNATURE_MAX_BIT_LEN (4096) @@ -513,6 +514,7 @@ #define SOC_PM_PAU_LINK_NUM (4) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ +#define SOC_SYS_DIGI_CLKRST_REG_SHARED (1) #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (0) #define SOC_MODEM_CLOCK_IS_INDEPENDENT (0) diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 8643908f4f27..f548a06b7979 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -1035,22 +1035,6 @@ config SOC_CLK_APLL_SUPPORTED bool default y -config SOC_APLL_MULTIPLIER_OUT_MIN_HZ - int - default 350000000 - -config SOC_APLL_MULTIPLIER_OUT_MAX_HZ - int - default 500000000 - -config SOC_APLL_MIN_HZ - int - default 5303031 - -config SOC_APLL_MAX_HZ - int - default 125000000 - config SOC_CLK_RC_FAST_D256_SUPPORTED bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 6a3dff526e94..809fb5ffc565 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -446,11 +446,6 @@ /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_APLL_SUPPORTED (1) -// apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) -#define SOC_APLL_MULTIPLIER_OUT_MIN_HZ (350000000) // 350 MHz -#define SOC_APLL_MULTIPLIER_OUT_MAX_HZ (500000000) // 500 MHz -#define SOC_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation -#define SOC_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation #define SOC_CLK_RC_FAST_D256_SUPPORTED (1) #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 (1) From e1039f9ce28245f8b9ba814bc85e4ac773a0b239 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Thu, 7 Sep 2023 16:47:26 +0800 Subject: [PATCH 108/142] fix(i2s_platform): merge the i2s platform acquire API --- components/driver/CMakeLists.txt | 3 +- components/driver/deprecated/i2s_legacy.c | 47 +----- components/driver/i2s/i2s_common.c | 142 ++++++------------ components/driver/i2s/i2s_platform.c | 78 ++++++++++ components/driver/i2s/i2s_private.h | 38 ++++- .../driver/i2s/include/driver/i2s_common.h | 4 +- components/hal/esp32p4/include/hal/i2s_ll.h | 45 +++--- components/hal/include/hal/i2s_hal.h | 4 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 - components/soc/esp32p4/include/soc/soc_caps.h | 3 - docs/docs_not_updated/esp32h2.txt | 1 - docs/docs_not_updated/esp32p4.txt | 1 - docs/en/api-reference/peripherals/i2s.rst | 1 + 13 files changed, 177 insertions(+), 194 deletions(-) create mode 100644 components/driver/i2s/i2s_platform.c diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 0a168abb5ad9..6af58de63da9 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -111,6 +111,7 @@ endif() # I2S related source files if(CONFIG_SOC_I2S_SUPPORTED) list(APPEND srcs "i2s/i2s_common.c" + "i2s/i2s_platform.c" "i2s/i2s_std.c" "deprecated/i2s_legacy.c") if(CONFIG_SOC_I2S_SUPPORTS_PDM) @@ -236,7 +237,7 @@ else() # Can be removed together with legacy drivers) idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${includes} - PRIV_REQUIRES efuse esp_timer + PRIV_REQUIRES efuse esp_timer esp_mm REQUIRES esp_pm esp_ringbuf freertos soc hal esp_hw_support LDFRAGMENTS ${ldfragments} ) diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c index 9b2ec2a3494b..494aba2e25a7 100644 --- a/components/driver/deprecated/i2s_legacy.c +++ b/components/driver/deprecated/i2s_legacy.c @@ -52,6 +52,7 @@ #include "esp_pm.h" #include "esp_efuse.h" #include "esp_rom_gpio.h" +#include "esp_private/i2s_platform.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" @@ -62,7 +63,7 @@ static const char *TAG = "i2s(legacy)"; #define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) -#if SOC_SYS_DIGI_CLKRST_REG_SHARED +#if SOC_PERIPH_CLK_CTRL_SHARED #define I2S_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() #else #define I2S_CLOCK_SRC_ATOMIC() @@ -150,9 +151,6 @@ typedef struct { uint32_t total_slot; /*!< Total slot number */ } i2s_obj_t; -// Record the component name that using I2S peripheral -static const char *comp_using_i2s[SOC_I2S_NUM] = {[0 ... SOC_I2S_NUM - 1] = NULL}; - // Global I2S object pointer static i2s_obj_t *p_i2s[SOC_I2S_NUM] = { [0 ... SOC_I2S_NUM - 1] = NULL, @@ -163,11 +161,6 @@ static portMUX_TYPE i2s_spinlock[SOC_I2S_NUM] = { [0 ... SOC_I2S_NUM - 1] = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED, }; - -__attribute__((weak)) esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name); - -__attribute__((weak)) esp_err_t i2s_platform_release_occupation(int id); - /*------------------------------------------------------------- I2S DMA operation -------------------------------------------------------------*/ @@ -1907,42 +1900,6 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) return ESP_OK; } -esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name) -{ - esp_err_t ret = ESP_ERR_NOT_FOUND; - ESP_RETURN_ON_FALSE(id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid i2s port id"); - portENTER_CRITICAL(&i2s_spinlock[id]); - if (!comp_using_i2s[id]) { - ret = ESP_OK; - comp_using_i2s[id] = comp_name; - I2S_RCC_ATOMIC() { - i2s_ll_enable_bus_clock(id, true); - i2s_ll_reset_register(id); - i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), true); - } - } - portEXIT_CRITICAL(&i2s_spinlock[id]); - return ret; -} - -esp_err_t i2s_platform_release_occupation(int id) -{ - esp_err_t ret = ESP_ERR_INVALID_STATE; - ESP_RETURN_ON_FALSE(id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid i2s port id"); - portENTER_CRITICAL(&i2s_spinlock[id]); - if (comp_using_i2s[id]) { - ret = ESP_OK; - comp_using_i2s[id] = NULL; - /* Disable module clock */ - I2S_RCC_ATOMIC() { - i2s_ll_enable_bus_clock(id, false); - i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), false); - } - } - portEXIT_CRITICAL(&i2s_spinlock[id]); - return ret; -} - /** * @brief This function will be called during start up, to check that the new i2s driver is not running along with the legacy i2s driver */ diff --git a/components/driver/i2s/i2s_common.c b/components/driver/i2s/i2s_common.c index 269fe52b5d4f..3a80b158053b 100644 --- a/components/driver/i2s/i2s_common.c +++ b/components/driver/i2s/i2s_common.c @@ -25,10 +25,9 @@ #include "soc/soc_caps.h" #include "hal/gpio_hal.h" #include "hal/i2s_hal.h" -#if CONFIG_IDF_TARGET_ESP32P4 +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE #include "hal/cache_hal.h" #include "hal/cache_ll.h" -#include "rom/cache.h" #endif #if SOC_I2S_SUPPORTS_ADC_DAC @@ -52,6 +51,10 @@ #include "esp_intr_alloc.h" #include "esp_check.h" #include "esp_attr.h" +#include "esp_dma_utils.h" +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +#include "esp_cache.h" +#endif #include "esp_rom_gpio.h" #include "esp_memory_utils.h" @@ -60,18 +63,15 @@ * Set 4092 here to align with 4-byte, so that the position of the slot data in the buffer will be relatively fixed */ #define I2S_DMA_BUFFER_MAX_SIZE (4092) -/** - * @brief Global i2s platform object - * @note For saving all the I2S related information - */ -i2s_platform_t g_i2s = { - .spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED, - .controller[0 ... (SOC_I2S_NUM - 1)] = NULL, // groups will be lazy installed - .comp_name[0 ... (SOC_I2S_NUM - 1)] = NULL, -}; - static const char *TAG = "i2s_common"; +__attribute__((always_inline)) +inline void *i2s_dma_calloc(size_t num, size_t size, uint32_t caps, size_t *actual_size) { + void *ptr = NULL; + esp_dma_calloc(num, size, caps, &ptr, actual_size); + return ptr; +} + /*--------------------------------------------------------------------------- I2S Static APIs ---------------------------------------------------------------------------- @@ -298,6 +298,11 @@ static esp_err_t i2s_register_channel(i2s_controller_t *i2s_obj, i2s_dir_t dir, return ret; } +#ifndef __cplusplus +/* To make sure the i2s_event_callbacks_t is same size as i2s_event_callbacks_internal_t */ +_Static_assert(sizeof(i2s_event_callbacks_t) == sizeof(i2s_event_callbacks_internal_t), "Invalid size of i2s_event_callbacks_t structure"); +#endif + esp_err_t i2s_channel_register_event_callback(i2s_chan_handle_t handle, const i2s_event_callbacks_t *callbacks, void *user_data) { I2S_NULL_POINTER_CHECK(TAG, handle); @@ -336,9 +341,9 @@ uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uin uint32_t bytes_per_sample = ((data_bit_width + 15) / 16) * 2; uint32_t bytes_per_frame = bytes_per_sample * active_chan; uint32_t bufsize = dma_frame_num * bytes_per_frame; -#if CONFIG_IDF_TARGET_ESP32P4 +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE /* bufsize need to align with cache line size */ - uint32_t alignment = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); + uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); uint32_t aligned_frame_num = dma_frame_num; /* To make the buffer aligned with the cache line size, search for the ceil aligned size first, If the buffer size exceed the max DMA buffer size, toggle the sign to search for the floor aligned size */ @@ -401,20 +406,14 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu handle->dma.desc_num = num; handle->dma.buf_size = bufsize; -#if SOC_GDMA_TRIG_PERIPH_I2S0_BUS == SOC_GDMA_BUS_AHB - uint32_t alignment = 64; - uint32_t desc_size = alignment; -#else - uint32_t alignment = 4; - uint32_t desc_size = sizeof(lldesc_t); -#endif /* Descriptors must be in the internal RAM */ handle->dma.desc = (lldesc_t **)heap_caps_calloc(num, sizeof(lldesc_t *), I2S_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(handle->dma.desc, ESP_ERR_NO_MEM, err, TAG, "create I2S DMA decriptor array failed"); handle->dma.bufs = (uint8_t **)heap_caps_calloc(num, sizeof(uint8_t *), I2S_MEM_ALLOC_CAPS); + size_t desc_size = 0; for (int i = 0; i < num; i++) { /* Allocate DMA descriptor */ - handle->dma.desc[i] = (lldesc_t *) heap_caps_aligned_calloc(alignment, 1, desc_size, I2S_DMA_ALLOC_CAPS); + handle->dma.desc[i] = (lldesc_t *) i2s_dma_calloc(1, sizeof(lldesc_t), I2S_DMA_ALLOC_CAPS, &desc_size); ESP_GOTO_ON_FALSE(handle->dma.desc[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA description failed"); handle->dma.desc[i]->owner = 1; handle->dma.desc[i]->eof = 1; @@ -422,7 +421,7 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu handle->dma.desc[i]->length = bufsize; handle->dma.desc[i]->size = bufsize; handle->dma.desc[i]->offset = 0; - handle->dma.bufs[i] = (uint8_t *) heap_caps_aligned_calloc(alignment, 1, bufsize * sizeof(uint8_t), I2S_DMA_ALLOC_CAPS); + handle->dma.bufs[i] = (uint8_t *) i2s_dma_calloc(1, bufsize * sizeof(uint8_t), I2S_DMA_ALLOC_CAPS, NULL); ESP_GOTO_ON_FALSE(handle->dma.bufs[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA buffer failed"); handle->dma.desc[i]->buf = handle->dma.bufs[i]; ESP_LOGV(TAG, "desc addr: %8p\tbuffer addr:%8p", handle->dma.desc[i], handle->dma.bufs[i]); @@ -431,8 +430,8 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu for (int i = 0; i < num; i++) { /* Link to the next descriptor */ STAILQ_NEXT(handle->dma.desc[i], qe) = (i < (num - 1)) ? (handle->dma.desc[i + 1]) : handle->dma.desc[0]; -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)(handle->dma.desc[i]), desc_size); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_cache_msync(handle->dma.desc[i], desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); #endif } if (handle->dir == I2S_DIR_RX) { @@ -498,8 +497,8 @@ static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_e uint32_t dummy; finish_desc = (lldesc_t *)event_data->rx_eof_desc_addr; -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)finish_desc->buf, handle->dma.buf_size); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_cache_msync((void *)finish_desc->buf, handle->dma.buf_size, ESP_CACHE_MSYNC_FLAG_INVALIDATE); #endif i2s_event_data_t evt = { .data = &(finish_desc->buf), @@ -547,8 +546,8 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e if (handle->dma.auto_clear) { uint8_t *sent_buf = (uint8_t *)finish_desc->buf; memset(sent_buf, 0, handle->dma.buf_size); -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)sent_buf, handle->dma.buf_size); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_cache_msync(sent_buf, handle->dma.buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); #endif } xQueueSendFromISR(handle->msg_queue, &(finish_desc->buf), &need_yield2); @@ -691,7 +690,7 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle); } #else - intr_flag |= handle->intr_flags ? handle->intr_flags : ESP_INTR_FLAG_LOWMED; + intr_flag |= handle->intr_prio_flags; /* Initialize I2S module interrupt */ if (handle->dir == I2S_DIR_TX) { esp_intr_alloc_intrstatus(i2s_periph_signal[port_id].irq, intr_flag, @@ -708,10 +707,10 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) return ESP_OK; } -void i2s_gpio_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool is_input, bool is_invert) +void i2s_gpio_check_and_set(int gpio, uint32_t signal_idx, bool is_input, bool is_invert) { /* Ignore the pin if pin = I2S_GPIO_UNUSED */ - if (gpio != I2S_GPIO_UNUSED) { + if (gpio != (int)I2S_GPIO_UNUSED) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); if (is_input) { /* Set direction, for some GPIOs, the input function are not enabled as default */ @@ -724,9 +723,9 @@ void i2s_gpio_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool is_input, } } -void i2s_gpio_loopback_set(gpio_num_t gpio, uint32_t out_sig_idx, uint32_t in_sig_idx) +void i2s_gpio_loopback_set(int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx) { - if (gpio != I2S_GPIO_UNUSED) { + if (gpio != (int)I2S_GPIO_UNUSED) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); gpio_set_direction(gpio, GPIO_MODE_INPUT_OUTPUT); esp_rom_gpio_connect_out_signal(gpio, out_sig_idx, 0, 0); @@ -734,9 +733,9 @@ void i2s_gpio_loopback_set(gpio_num_t gpio, uint32_t out_sig_idx, uint32_t in_si } } -esp_err_t i2s_check_set_mclk(i2s_port_t id, gpio_num_t gpio_num, i2s_clock_src_t clk_src, bool is_invert) +esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_src, bool is_invert) { - if (gpio_num == I2S_GPIO_UNUSED) { + if (gpio_num == (int)I2S_GPIO_UNUSED) { return ESP_OK; } #if CONFIG_IDF_TARGET_ESP32 @@ -785,6 +784,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * I2S_NULL_POINTER_CHECK(TAG, tx_handle || rx_handle); ESP_RETURN_ON_FALSE(chan_cfg->id < SOC_I2S_NUM || chan_cfg->id == I2S_NUM_AUTO, ESP_ERR_INVALID_ARG, TAG, "invalid I2S port id"); ESP_RETURN_ON_FALSE(chan_cfg->dma_desc_num >= 2, ESP_ERR_INVALID_ARG, TAG, "there should be at least 2 DMA buffers"); + ESP_RETURN_ON_FALSE(chan_cfg->intr_priority >= 0 && chan_cfg->intr_priority <= 7, ESP_ERR_INVALID_ARG, TAG, "intr_priority should be within 0~7"); esp_err_t ret = ESP_OK; i2s_controller_t *i2s_obj = NULL; @@ -816,7 +816,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_TX, chan_cfg->dma_desc_num), err, TAG, "register I2S tx channel failed"); i2s_obj->tx_chan->role = chan_cfg->role; - i2s_obj->tx_chan->intr_flags = chan_cfg->intr_flags; + i2s_obj->tx_chan->intr_prio_flags = chan_cfg->intr_priority ? BIT(chan_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED; i2s_obj->tx_chan->dma.auto_clear = chan_cfg->auto_clear; i2s_obj->tx_chan->dma.desc_num = chan_cfg->dma_desc_num; i2s_obj->tx_chan->dma.frame_num = chan_cfg->dma_frame_num; @@ -830,7 +830,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_RX, chan_cfg->dma_desc_num), err, TAG, "register I2S rx channel failed"); i2s_obj->rx_chan->role = chan_cfg->role; - i2s_obj->rx_chan->intr_flags = chan_cfg->intr_flags; + i2s_obj->rx_chan->intr_prio_flags = chan_cfg->intr_priority ? BIT(chan_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED; i2s_obj->rx_chan->dma.desc_num = chan_cfg->dma_desc_num; i2s_obj->rx_chan->dma.frame_num = chan_cfg->dma_frame_num; i2s_obj->rx_chan->start = i2s_rx_channel_start; @@ -1071,8 +1071,8 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src, } /* Load the data from the last loaded position */ memcpy((uint8_t *)(tx_handle->dma.curr_ptr + tx_handle->dma.rw_pos), data_ptr, bytes_can_load); -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)(tx_handle->dma.curr_ptr + tx_handle->dma.rw_pos), (uint32_t)bytes_can_load); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_cache_msync(tx_handle->dma.curr_ptr + tx_handle->dma.rw_pos, bytes_can_load, ESP_CACHE_MSYNC_FLAG_DIR_C2M); #endif data_ptr += bytes_can_load; // Move forward the data pointer total_loaded_bytes += bytes_can_load; // Add to the total loaded bytes @@ -1130,8 +1130,8 @@ esp_err_t i2s_channel_write(i2s_chan_handle_t handle, const void *src, size_t si bytes_can_write = size; } memcpy(data_ptr, src_byte, bytes_can_write); -#if CONFIG_IDF_TARGET_ESP32P4 - Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)data_ptr, (uint32_t)bytes_can_write); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_cache_msync(data_ptr, bytes_can_write, ESP_CACHE_MSYNC_FLAG_DIR_C2M); #endif size -= bytes_can_write; src_byte += bytes_can_write; @@ -1187,64 +1187,6 @@ esp_err_t i2s_channel_read(i2s_chan_handle_t handle, void *dest, size_t size, si return ret; } -/*--------------------------------------------------------------------------- - I2S Platform APIs - ---------------------------------------------------------------------------- - Scope: This file and ADC/DAC/LCD driver - ----------------------------------------------------------------------------*/ - -esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name) -{ - esp_err_t ret = ESP_OK; - const char *occupied_comp = NULL; - ESP_RETURN_ON_FALSE(id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid i2s port id"); - portENTER_CRITICAL(&g_i2s.spinlock); - if ((!g_i2s.controller[id]) && (g_i2s.comp_name[id] == NULL)) { - g_i2s.comp_name[id] = comp_name; - /* Enable module clock */ - I2S_RCC_ATOMIC() { - i2s_ll_enable_bus_clock(id, true); - i2s_ll_reset_register(id); - i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), true); - } - } else { - occupied_comp = g_i2s.comp_name[id]; - ret = ESP_ERR_NOT_FOUND; - } - portEXIT_CRITICAL(&g_i2s.spinlock); - if (occupied_comp != NULL) { - ESP_LOGW(TAG, "i2s controller %d has been occupied by %s", id, occupied_comp); - } - return ret; -} - -esp_err_t i2s_platform_release_occupation(int id) -{ - esp_err_t ret = ESP_OK; - ESP_RETURN_ON_FALSE(id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid i2s port id"); - portENTER_CRITICAL(&g_i2s.spinlock); - if (!g_i2s.controller[id]) { - g_i2s.comp_name[id] = NULL; - /* Disable module clock */ - I2S_RCC_ATOMIC() { - i2s_ll_enable_bus_clock(id, false); - i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), false); - } - } else { - ret = ESP_ERR_INVALID_STATE; - } - portEXIT_CRITICAL(&g_i2s.spinlock); - return ret; -} - -// Only used in `test_i2s_iram.c` to write DMA buffer directly -size_t inline i2s_platform_get_dma_buffer_offset(void) -{ - /* Force to transfer address '0' into 'i2s_chan_handle_t' type, - * then find the corresponding field , the address of this field is the offset of this type */ - return (size_t)&(((i2s_chan_handle_t)0)->dma.bufs); -} - #if SOC_I2S_SUPPORTS_TX_SYNC_CNT uint32_t i2s_sync_get_bclk_count(i2s_chan_handle_t tx_handle) { diff --git a/components/driver/i2s/i2s_platform.c b/components/driver/i2s/i2s_platform.c new file mode 100644 index 000000000000..39d9e87cc292 --- /dev/null +++ b/components/driver/i2s/i2s_platform.c @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_check.h" +#include "i2s_private.h" + +static const char *TAG = "i2s_platform"; + +/** + * @brief Global i2s platform object + * @note For saving all the I2S related information + */ +i2s_platform_t g_i2s = { + .spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED, + .controller[0 ... (SOC_I2S_NUM - 1)] = NULL, // groups will be lazy installed + .comp_name[0 ... (SOC_I2S_NUM - 1)] = NULL, +}; + +/*--------------------------------------------------------------------------- + I2S Platform APIs + ---------------------------------------------------------------------------- + Scope: This file and ADC/DAC/LCD driver + ----------------------------------------------------------------------------*/ + +esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name) +{ + esp_err_t ret = ESP_OK; + const char *occupied_comp = NULL; + ESP_RETURN_ON_FALSE(id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid i2s port id"); + portENTER_CRITICAL(&g_i2s.spinlock); + if ((!g_i2s.controller[id]) && (g_i2s.comp_name[id] == NULL)) { + g_i2s.comp_name[id] = comp_name; + /* Enable module clock */ + I2S_RCC_ATOMIC() { + i2s_ll_enable_bus_clock(id, true); + i2s_ll_reset_register(id); + i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), true); + } + } else { + occupied_comp = g_i2s.comp_name[id]; + ret = ESP_ERR_NOT_FOUND; + } + portEXIT_CRITICAL(&g_i2s.spinlock); + if (occupied_comp != NULL) { + ESP_LOGW(TAG, "i2s controller %d has been occupied by %s", id, occupied_comp); + } + return ret; +} + +esp_err_t i2s_platform_release_occupation(int id) +{ + esp_err_t ret = ESP_OK; + ESP_RETURN_ON_FALSE(id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid i2s port id"); + portENTER_CRITICAL(&g_i2s.spinlock); + if (!g_i2s.controller[id]) { + g_i2s.comp_name[id] = NULL; + /* Disable module clock */ + I2S_RCC_ATOMIC() { + i2s_ll_enable_bus_clock(id, false); + i2s_ll_enable_core_clock(I2S_LL_GET_HW(id), false); + } + } else { + ret = ESP_ERR_INVALID_STATE; + } + portEXIT_CRITICAL(&g_i2s.spinlock); + return ret; +} + +// Only used in `test_i2s_iram.c` to write DMA buffer directly +size_t i2s_platform_get_dma_buffer_offset(void) +{ + /* Force to transfer address '0' into 'i2s_chan_handle_t' type, + * then find the corresponding field , the address of this field is the offset of this type */ + return (size_t)&(((i2s_chan_handle_t)0)->dma.bufs); +} diff --git a/components/driver/i2s/i2s_private.h b/components/driver/i2s/i2s_private.h index 90858a04b430..9405062ca5d5 100644 --- a/components/driver/i2s/i2s_private.h +++ b/components/driver/i2s/i2s_private.h @@ -9,7 +9,7 @@ #include "freertos/FreeRTOS.h" #include "soc/lldesc.h" #include "soc/soc_caps.h" -#include "hal/i2s_types.h" +#include "hal/i2s_hal.h" #include "driver/i2s_types.h" #include "freertos/semphr.h" #include "freertos/queue.h" @@ -36,7 +36,7 @@ extern "C" { #endif //CONFIG_I2S_ISR_IRAM_SAFE #define I2S_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) -#if SOC_SYS_DIGI_CLKRST_REG_SHARED +#if SOC_PERIPH_CLK_CTRL_SHARED #define I2S_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() #else #define I2S_CLOCK_SRC_ATOMIC() @@ -59,6 +59,28 @@ typedef enum { I2S_CHAN_STATE_RUNNING, /*!< i2s channel is idling (initialized and enabled) */ } i2s_state_t; +/** + * @brief Group of I2S callbacks + * @note The callbacks are all running under ISR environment + * @note When CONFIG_I2S_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM. + * The variables used in the function should be in the SRAM as well. + * @note Declare the internal type to remove the dependency of `i2s_common.h` + */ +typedef struct { + i2s_isr_callback_t on_recv; /**< Callback of data received event, only for rx channel + * The event data includes DMA buffer address and size that just finished receiving data + */ + i2s_isr_callback_t on_recv_q_ovf; /**< Callback of receiving queue overflowed event, only for rx channel + * The event data includes buffer size that has been overwritten + */ + i2s_isr_callback_t on_sent; /**< Callback of data sent event, only for tx channel + * The event data includes DMA buffer address and size that just finished sending data + */ + i2s_isr_callback_t on_send_q_ovf; /**< Callback of sending queue overflowed event, only for tx channel + * The event data includes buffer size that has been overwritten + */ +} i2s_event_callbacks_internal_t; + /** * @brief i2s channel level configurations * @note It performs as channel handle @@ -103,7 +125,7 @@ struct i2s_channel_obj_t { i2s_dma_t dma; /*!< i2s dma object */ i2s_state_t state; /*!< i2s driver state. Ensuring the driver working in a correct sequence */ /* Stored configurations */ - int intr_flags; + int intr_prio_flags;/*!< i2s interrupt priority flags */ void *mode_info; /*!< Slot, clock and gpio information of each mode */ #if SOC_I2S_SUPPORTS_APLL bool apll_en; /*!< Flag of wether APLL enabled */ @@ -117,7 +139,7 @@ struct i2s_channel_obj_t { esp_pm_lock_handle_t pm_lock; /*!< Power management lock, to avoid apb clock frequency changes while i2s is working */ #endif QueueHandle_t msg_queue; /*!< Message queue handler, used for transporting data between interrupt and read/write task */ - i2s_event_callbacks_t callbacks; /*!< Callback functions */ + i2s_event_callbacks_internal_t callbacks; /*!< Callback functions */ void *user_data; /*!< User data for callback functions */ void (*start)(i2s_chan_handle_t); /*!< start tx/rx channel */ void (*stop)(i2s_chan_handle_t); /*!< stop tx/rx channel */ @@ -133,7 +155,7 @@ typedef struct { const char *comp_name[SOC_I2S_NUM]; /*!< The component name that occupied i2s controller */ } i2s_platform_t; -extern i2s_platform_t g_i2s; +extern i2s_platform_t g_i2s; /*!< Global i2s instance for driver internal use */ /** * @brief Initialize I2S DMA interrupt @@ -200,7 +222,7 @@ uint32_t i2s_get_source_clk_freq(i2s_clock_src_t clk_src, uint32_t mclk_freq_hz) * @param is_input Is input gpio * @param is_invert Is invert gpio */ -void i2s_gpio_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool is_input, bool is_invert); +void i2s_gpio_check_and_set(int gpio, uint32_t signal_idx, bool is_input, bool is_invert); /** * @brief Check gpio validity and output mclk signal @@ -213,7 +235,7 @@ void i2s_gpio_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool is_input, * - ESP_OK Set mclk output gpio success * - ESP_ERR_INVALID_ARG Invalid GPIO number */ -esp_err_t i2s_check_set_mclk(i2s_port_t id, gpio_num_t gpio_num, i2s_clock_src_t clk_src, bool is_invert); +esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_src, bool is_invert); /** * @brief Attach data out signal and data in signal to a same gpio @@ -222,7 +244,7 @@ esp_err_t i2s_check_set_mclk(i2s_port_t id, gpio_num_t gpio_num, i2s_clock_src_t * @param out_sig_idx Data out signal index * @param in_sig_idx Data in signal index */ -void i2s_gpio_loopback_set(gpio_num_t gpio, uint32_t out_sig_idx, uint32_t in_sig_idx); +void i2s_gpio_loopback_set(int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx); #ifdef __cplusplus } diff --git a/components/driver/i2s/include/driver/i2s_common.h b/components/driver/i2s/include/driver/i2s_common.h index fb2c99a4f140..0b6dc30331de 100644 --- a/components/driver/i2s/include/driver/i2s_common.h +++ b/components/driver/i2s/include/driver/i2s_common.h @@ -25,7 +25,7 @@ extern "C" { .dma_desc_num = 6, \ .dma_frame_num = 240, \ .auto_clear = false, \ - .intr_flags = 0, \ + .intr_priority = 0, \ } #define I2S_GPIO_UNUSED GPIO_NUM_NC /*!< Used in i2s_gpio_config_t for signals which are not used */ @@ -64,7 +64,7 @@ typedef struct { * it should be the multiple of '3' when the data bit width is 24. */ bool auto_clear; /*!< Set to auto clear DMA TX buffer, i2s will always send zero automatically if no data to send */ - int intr_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */ + int intr_priority; /*!< I2S interrupt priority, range [0, 7], if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */ } i2s_chan_config_t; /** diff --git a/components/hal/esp32p4/include/hal/i2s_ll.h b/components/hal/esp32p4/include/hal/i2s_ll.h index 0fd64cad6f17..c3b69cf98d78 100644 --- a/components/hal/esp32p4/include/hal/i2s_ll.h +++ b/components/hal/esp32p4/include/hal/i2s_ll.h @@ -19,6 +19,7 @@ #include "soc/i2s_struct.h" #include "soc/hp_sys_clkrst_struct.h" #include "hal/i2s_types.h" +#include "hal/hal_utils.h" #ifdef __cplusplus @@ -31,22 +32,12 @@ extern "C" { #define I2S_LL_TDM_CH_MASK (0xffff) #define I2S_LL_PDM_BCK_FACTOR (64) -#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) -#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) +#define I2S_LL_CLK_FRAC_DIV_N_MAX 256 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the N register is 8 bit-width +#define I2S_LL_CLK_FRAC_DIV_AB_MAX 512 // I2S_MCLK = I2S_SRC_CLK / (N + b/a), the a/b register is 9 bit-width #define I2S_LL_XTAL_CLK_FREQ (40 * 1000000) // XTAL_CLK: 40MHz #define I2S_LL_DEFAULT_CLK_FREQ I2S_LL_XTAL_CLK_FREQ // No PLL clock source on P4, use XTAL as default -/** - * @brief I2S clock configuration structure - * @note Fmclk = Fsclk /(integ+numer/denom) - */ -typedef struct { - uint16_t integ; // Integer part of I2S module clock divider - uint16_t denom; // Denominator part of I2S module clock divider - uint16_t numer; // Numerator part of I2S module clock divider -} i2s_ll_mclk_div_t; - /** * @brief Enable the bus clock for I2S module * @@ -328,7 +319,7 @@ static inline uint32_t i2s_ll_get_clk_src(i2s_clock_src_t src) return 2; default: HAL_ASSERT(false && "unsupported clock source"); - break; + return -1; } } @@ -471,7 +462,7 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui * @param hw Peripheral I2S hardware instance address. * @param mclk_div The mclk division coefficients */ -static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) +static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate * Set to particular coefficients first then update to the target coefficients, @@ -484,13 +475,13 @@ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mc uint32_t div_z = 0; uint32_t div_yn1 = 0; /* If any of denominator and numerator is 0, set all the coefficients to 0 */ - if (mclk_div->denom && mclk_div->numer) { - div_yn1 = mclk_div->numer * 2 > mclk_div->denom; - div_z = div_yn1 ? mclk_div->denom - mclk_div->numer : mclk_div->numer; - div_x = mclk_div->denom / div_z - 1; - div_y = mclk_div->denom % div_z; + if (mclk_div->denominator && mclk_div->numerator) { + div_yn1 = mclk_div->numerator * 2 > mclk_div->denominator; + div_z = div_yn1 ? mclk_div->denominator - mclk_div->numerator : mclk_div->numerator; + div_x = mclk_div->denominator / div_z - 1; + div_y = mclk_div->denominator % div_z; } - i2s_ll_tx_set_raw_clk_div(hw, mclk_div->integ, div_x, div_y, div_z, div_yn1); + i2s_ll_tx_set_raw_clk_div(hw, mclk_div->integer, div_x, div_y, div_z, div_yn1); } /** @@ -511,7 +502,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 mclk_div The mclk division coefficients */ -static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) +static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const hal_utils_clk_div_t *mclk_div) { /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate * Set to particular coefficients first then update to the target coefficients, @@ -524,13 +515,13 @@ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mc uint32_t div_z = 0; uint32_t div_yn1 = 0; /* If any of denominator and numerator is 0, set all the coefficients to 0 */ - if (mclk_div->denom && mclk_div->numer) { - div_yn1 = mclk_div->numer * 2 > mclk_div->denom; - div_z = div_yn1 ? mclk_div->denom - mclk_div->numer : mclk_div->numer; - div_x = mclk_div->denom / div_z - 1; - div_y = mclk_div->denom % div_z; + if (mclk_div->denominator && mclk_div->numerator) { + div_yn1 = mclk_div->numerator * 2 > mclk_div->denominator; + div_z = div_yn1 ? mclk_div->denominator - mclk_div->numerator : mclk_div->numerator; + div_x = mclk_div->denominator / div_z - 1; + div_y = mclk_div->denominator % div_z; } - i2s_ll_rx_set_raw_clk_div(hw, mclk_div->integ, div_x, div_y, div_z, div_yn1); + i2s_ll_rx_set_raw_clk_div(hw, mclk_div->integer, div_x, div_y, div_z, div_yn1); } /** diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index 6e8af9bf8444..bfa5dfe1c208 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -147,7 +147,7 @@ void i2s_hal_calc_mclk_precise_division(uint32_t sclk, uint32_t mclk, hal_utils_ */ void _i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src); -#if SOC_SYS_DIGI_CLKRST_REG_SHARED +#if SOC_PERIPH_CLK_CTRL_SHARED /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define i2s_hal_set_tx_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _i2s_hal_set_tx_clock(__VA_ARGS__) @@ -164,7 +164,7 @@ void _i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *c */ void _i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src); -#if SOC_SYS_DIGI_CLKRST_REG_SHARED +#if SOC_PERIPH_CLK_CTRL_SHARED /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define i2s_hal_set_rx_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _i2s_hal_set_rx_clock(__VA_ARGS__) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 76a4587ddd52..fbc3963a49c5 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1123,10 +1123,6 @@ config SOC_PM_PAU_LINK_NUM int default 4 -config SOC_SYS_DIGI_CLKRST_REG_SHARED - bool - default y - config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default n diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index d3a1b238703d..abc8d3f8b9bd 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -48,7 +48,6 @@ // #define SOC_EFUSE_SUPPORTED 1 //TODO: IDF-7512 #define SOC_RTC_FAST_MEM_SUPPORTED 1 #define SOC_RTC_MEM_SUPPORTED 1 -// #define SOC_I2S_SUPPORTED 1 //TODO: IDF-6508 #define SOC_RMT_SUPPORTED 1 #define SOC_I2S_SUPPORTED 1 // #define SOC_RMT_SUPPORTED 1 //TODO: IDF-7476 @@ -154,7 +153,6 @@ #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 -// TODO: IDF-5360 (Copy from esp32c3, need check) /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ /** The maximum length of a Digital Signature in bits. */ #define SOC_DS_SIGNATURE_MAX_BIT_LEN (4096) @@ -514,7 +512,6 @@ #define SOC_PM_PAU_LINK_NUM (4) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ -#define SOC_SYS_DIGI_CLKRST_REG_SHARED (1) #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (0) #define SOC_MODEM_CLOCK_IS_INDEPENDENT (0) diff --git a/docs/docs_not_updated/esp32h2.txt b/docs/docs_not_updated/esp32h2.txt index a0fd1f872faa..fb3d48388c9d 100644 --- a/docs/docs_not_updated/esp32h2.txt +++ b/docs/docs_not_updated/esp32h2.txt @@ -3,7 +3,6 @@ api-guides/coexist api-guides/cplusplus api-guides/dfu api-guides/index -api-reference/peripherals/i2s api-reference/peripherals/spi_features api-reference/peripherals/sdio_slave api-reference/peripherals/adc_calibration diff --git a/docs/docs_not_updated/esp32p4.txt b/docs/docs_not_updated/esp32p4.txt index 839e965ed4f4..c4061400c68c 100644 --- a/docs/docs_not_updated/esp32p4.txt +++ b/docs/docs_not_updated/esp32p4.txt @@ -111,7 +111,6 @@ api-reference/peripherals/gpio.rst api-reference/peripherals/sdspi_host.rst api-reference/peripherals/dac.rst api-reference/peripherals/spi_slave.rst -api-reference/peripherals/i2s.rst api-reference/peripherals/touch_element.rst api-reference/peripherals/lcd.rst api-reference/peripherals/ana_cmpr.rst diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index c379114a3a0b..071352c3f634 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -116,6 +116,7 @@ ESP32-C3 I2S 0 I2S 0 none I2S 0 none none ESP32-C6 I2S 0 I2S 0 none I2S 0 none none ESP32-S3 I2S 0/1 I2S 0 I2S 0 I2S 0/1 none none ESP32-H2 I2S 0 I2S 0 none I2S 0 none none +ESP32-P4 I2S 0~2 I2S 0 I2S 0 I2S 0~2 none none ========= ======== ======== ======== ======== ======== ========== Standard Mode From 4215adcdb4fe78ffdbdf708ea000c19a17c09e35 Mon Sep 17 00:00:00 2001 From: Armando Date: Wed, 27 Sep 2023 13:08:28 +0800 Subject: [PATCH 109/142] feat(cache): added cache msync doc --- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32p4/include/soc/soc_caps.h | 1 + .../diagrams/mmu/cache_align_issue.png | Bin 0 -> 40154 bytes docs/conf_common.py | 4 + docs/doxygen/Doxyfile | 1 + docs/en/api-reference/system/index.rst | 1 + docs/en/api-reference/system/mm.rst | 11 +- docs/en/api-reference/system/mm_sync.rst | 146 ++++++++++++++++++ docs/zh_CN/api-reference/system/index.rst | 1 + docs/zh_CN/api-reference/system/mm_sync.rst | 1 + 10 files changed, 160 insertions(+), 10 deletions(-) create mode 100644 docs/_static/diagrams/mmu/cache_align_issue.png create mode 100644 docs/en/api-reference/system/mm_sync.rst create mode 100644 docs/zh_CN/api-reference/system/mm_sync.rst diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 6e71422bd936..f46468c5577b 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -115,6 +115,10 @@ config SOC_SPIRAM_SUPPORTED bool default y +config SOC_PSRAM_DMA_CAPABLE + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 2e97a113fc68..04d5dba19e07 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -74,6 +74,7 @@ #define SOC_LP_GPIO_MATRIX_SUPPORTED 1 #define SOC_LP_PERIPHERALS_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 +#define SOC_PSRAM_DMA_CAPABLE 1 // #define SOC_ULP_SUPPORTED 1 //TODO: IDF-7534 // #define SOC_SDMMC_HOST_SUPPORTED 1 //TODO: IDF-6502 // #define SOC_CLK_TREE_SUPPORTED 1 //TODO: IDF-7526 diff --git a/docs/_static/diagrams/mmu/cache_align_issue.png b/docs/_static/diagrams/mmu/cache_align_issue.png new file mode 100644 index 0000000000000000000000000000000000000000..8b3c8f1430caccf0e05b303a7214f4f67579f60b GIT binary patch literal 40154 zcmbSz1yq#L+U^WFqQD>_2+|=XDIEiXlp@mINJvQ|HI#G_#_nk1U}k3PXkq8H zhu$Oxflx!_q$E_`Qn%AwJ&8Ily4JMc)+*59%EA~h&}6YK{fN-zV`#B3rKP11FW+9# zKJ*KvMq^7qB6w9OE8=(d?(y$a&!{VDb*X~Nyb z<-|p-0FL2nrd6q3q{mUx2{ z*@Ek(6hxx3e12S2Jdz!q`FA)w)pYgaL!Z3i{K*Niz!M`r$RHW^qc#lh_9;rBMvv6( z(+b?aO@!!3j6--LkfxsHbZn4d!wp}Dt{~THBFJ0h_lE|a-FOw!NcQsu0$Q?`Ydnl9 zT45}RL^=A-GpNqn`H7zr2uPnq*K+0+8nS48qg&!}*PCN}f$lI^_j~_J`Om4QaEIHv zV$gjHYD^*=On3mtXU}?tS40yyB6FoGkPt|F7pWr!6Enh^b;C#w+N^GfoOlRM-i8g{H?PIh#3B+L;b%|BON7H6s#bkGW{x?&=b=-wJi1ta$( zo<2i8L}CieyJ8OB9A6eg+L_ELPRqnNA#lk%Z4hPzH;y8-dyZI@g_!f*e+^s3Nwp|W zpyWrTblUX_nU6{jiJ1HpJ&3@eH~&8ehLe(#MEcRg{&fF#^8is4{*>-OA}{>3T^)O0 z1_9%`)5iJi%%!>s*RJCsq(qg)Xo{u=97DiDjy_%;EYL_{n3|bE8L90( zBbOl9@Ws1mIsv42-i3$Xp%$C}WfTVKCV~r}V;;9?reL+V3w)M}qZ&acS?z3}q2Axsq`yw32GgQmbQR&nH>p?*lAZ&=HHosG3;|nr_yIqv} zWf=uV;h`c%+VR8x#{+p>oiLhkt}_`eHq7=aZO9kjrMCJhTF67gFo>J09Ms;Ee&p%J z(bQm2ECGfDgyc#!*jt#cIpxQUZ!9JYy%^kgmHKZ4QNx;B1$1beQ_>SCR2?W}ND9hn z?J0t|u®1f~HcCHEFjVBfc5>4sBF*1>A&@&D7h__`D!9JC5AIx1Z=u&EJ-`ei^ zv+C#RU%QUq=`qFBaH;Ej)2v;D-6#D1Cyrn9pJ(0Tl+Sn)3-jJwJ$+u+&~*4La^zI{ z{Ob#L_kt%4R^BwY^%43W4M=OA-0Q2e=C!Rr4C$(MQRgwQAs-)WHP&BEPlskzTty9K zv6BmNN>!n}aFgCYp804w1+uHz_|X%ZN`~cw4cQ}p)E~Y|k&izT;^q8w=7U@DSt;8W zbwx+E>O2Cxb?sDr`PggtwlAM-ZKxE@-ln>Acr?|E%&18V8FdM0fuX8=lX8T?fCz__c%#uMyuX|v&%GO?~h=f5#b~Y#8 zWHEVU|0K%dWY$jOHj;wAnHh12&K%t?Pn8+VZ1_{?Y~11=hOfy`$NlkQeOV>bFtH&Q zad(_j)PU}i=wxZTIpr>Nh*~QOo~n6neTPsrZT9J3%{5*yCJ1 zT9f(iYfZ)o1`9-*kiIjGR1=8gNqT0iBS-zt2#F@rZw})3zz7<9(D&-=g!Mbj<<-^e z6Y<_0L3U4a?|m7`!JP&|9m_0n(O5eykRUr##M?3XujZtA`u~WeoIY`F`raa*;p4Wq z|E*YJWNtF1c2jk;x+i8$Ud30B_o~bg<#5i|X+{GqdZBo%MsM`xcm4 z1Dc3|5GLiM}_iIMLixfu3NPZ zyATGcnv6w@q7?NL`qd(+xk~zARAD*ux;M4TTQ7m}&9``>@uZdyeeZ6ozpasy_VHv( zMq}$q?(5C!%fWUD8EBmUKGQzbb4^Zjb`xGi{>$k6S|{K2B=Ys@oXa(FmMk7gTx@J? zMh3@dGxu6_Idk;);Hc;>6(q;Ql%LGZ-OS|JVSGv~n9msFjws9@^;s@V&HMLh?9Gky zl$pK6H@ACm_wMBDfsp0x3P*AL(0w0wGj66>f9dyvw?raMahjjJUpssMp2)C(&Jljg z4gEOT371|NOJ{P(w!= z<;7CMeX8Ni zyu9cJpHXthV{`3(iQD=4`GJ9f#<&&JkwiBw@;D-#Q#nmCIO zVBPP1B>*Pce}sZb^qY{s3F*^^<1dGI);{weKB(zNa&>+<`_mAeoP{5{Vo0#us!-@l zYLYbo3x{{pgmNi9e~wut#EqSH5TDRmka%~i!fLeu0i!wj%ua5q*Kq!Dbb>Vm(=y)c~z-2wXC`vna(ugJXtAugPuc zKzw#ZUSl|0t*ww%gYwoW{jL1Ol4U-tkzrz*03z=`?WeP~P9yCzjZV)8D$LLyOTzML zwRy)Fbf0l1TrK60v$~!m5d~98MHcKwg5eQjXt*NG0e>QR>U^D^y zS!o%H->zHdJFN<46tw$t^qOMHU#p;NZ6z1$u?_9GK39+I&{HHk_)+2hBy8Dm)U=gS zpYk*L*pDyeZ`o3PyP{tD7Zzynj0-E&2UVx|#7o20c72*`8)AG`qYdPL-=v9J`3$w} zgk9nlWjC*Q=q`-(n0W{^nM&J6e6(HL)vdCuFnDG-!7B5jzG{!6;3)z4Xr!mQR7)@Ie$L!SjdO^Pj z2GPy0-c{4Ji}QOs5voGsCEvCw94EwIt?cKp{yrLFb|`l&yk2HmHeJbc_MXkY8~D?p z%iMhJ&xBU3n0Fnmqh{dGetr(&ps&BXbX!8dux+VL3_daY@@s9mhBvMBaOb_&(kN4o zO^N{BoAq*L_Gto1$se6%L&|d(-l|?2fo>F!Ynblv;y;?H>Cj{^nqyxd2Mz61*5;mq>Ttqoo3x}3uJW(S=7R)sRIaDj*Rb-l#Wvs z-FnEcUSR)P%yNVLgz;pXON_>QVwq$YMk97mjsJ>VT>o70{iO2r+k%X2-%*B%=^g2t zAA%=C^)@L@K1VqQW1gBCM;KkLx8NJN&S^1oK7Ngxb7u`#4@i6@7#qUVGQ#Uc+$P#T z+cGFj2~B3?P1#WH6n2|7)}Cn22k7xr>g(}Szm{mizxm#dCkqWc?hu@7-1njSHttF( z9Qo|+sB-hQQ`MvHRogW?b`Qti9LfTY&!(UCXG8?desBHZC^!C+3TH|^ey{B#Zf5K9 zNN`>=BQDJ8S_o6}N9lEz0heCi-nF*@_r?{E*Rc3ZQ_4W6{~9LL$af7hoY(t$*1f}n zPK-Ynu~p(&b}XZ|5&D~*SZiSU-h9{EDv{pXh3Qn?%Aa#GEB7+{s--$=1>aKnq)q;y zs+2GIA~hF~u=$Z&%`L7+?qrp2uE_P`RePyxN-bSLfUtO@xPhqUK=fuX__W(-9I(-P zjhv(EO5f3-?46ln1dQwvJNd7|tuaA#etm)R{S|v+=p9$y{AW zDuGX5)qUZLH%m)$A$IH!^bFK!u?s10$B&j+Kl4e`lvbCT5SnzBj|d7{_z2 z^38=F?Jd^cB=j4lXP5inQ1Y{j}V#wxZ}e1 z5psN-nn7~Al7YwNoh#mikja4>360pBJ2PGrubk0KXgiGp#?;QhBann~GfK^)T1-LfAud?D%~CT<;|dTuFh~ zd%c1A{nZUON8x%&q%_ByWlQ|mq}n}w9c}dk%PQy3(M3fsO1g6D6DzbI=r(;k{_-5R z;<``3*}pT&)g$g%H?~$epmm{ZiX*K|hb-)r4YKl8nyUQF!q#xo33YY#c>m^EQwGfY(y!r?t!w?GnG1gFdmyD&N@t92p$ZQuX*(9ba4$o936@>O?FW9nW)un>+ZtoMRPQhxVZmDe3nOF@0VEiQ0vwW zrm0qy;Z%xme++n0#-U?><_CNi2J%0I>ff|Q7iUD1UVS~gevxxi!(SpLJ+?b1z@2MS zInJD0Sm|%3mC$!{GITyt=i|ZE|Ka+i{gv+nlG$ZW5{D{$+!Ddlv8{n8PP}#Wani5nL}$8P}H74zG{Ix*U^)=Za_Mm!7yM)xR4H zee3$d<$z$xJ)KMUs=U%};I(y>v)%T4l{)}bi2M$Tz^(8buvn(lwxkv$p>q}M?fYhW zX7aPs7m6!>)wEn;Jopu7d^r1wnVOb;6~AB)MHXrd{GxrFjF+_StmXQ}`MCHB_crOn zs3Vu2<%=I3GTJ$4%lWb;m_1J{JhTr9#k(%?{|B1lnV6Et-@cpWwGyFwmG(S=pq0UM zq*%M)h3m}EZjXJRn=K;Jv+H!W7z(!4TXV~7DQNhbkxP3w=kgJJ83w!}niIl>-R}wC zEe`q_^66i2V3rbs_?xfXpi&Z8RM3q;#;@Lk3?SQ`R>v)KlM|GrmI`( z$%{>iO_{98r=IEfv~r=K`GTsQgV0Jv5SOFl&iA#~o1Xqz!VMQg(hU>3_GdjVAN3mR zyN$x1uZh1Vn_j8c=`fiuv&1*qT__IGdwp?%F=|VA(>K62Yt83Kq4GPbD|8J*Ii}== z(#)~lmFL9UQR1A`>+M0B=TE#U7s^D%W}R~Lo&@%`861Y(Iy@*i)16DYP&vD~9;g1^ zRq|@6k>@1W-fzNs)%~j)Gyr5}%96##mi8Pwp91w6{OcdYoFs$%4f+l1b2Zx)8g(9W z1u7~kwbMLRe5H4uX1#=KzQ$dq+)X|;w(-e8<}HesuYG>Z<`q+7E3##*Y-OdTMv`hf z$?6rZuG`C>(sxd`L_R`VBPQKUx^+WFsOL5RZc$@{D&_dcX9!uFy2tqMuDYFfp*fHN zj(xJfeJv&7;W&(IZiaieLrBQAWd2;QtGG59f0=sWR&GO=%DivPLa(cjJHxk$aGs~( zT&}KKC-bj(`lF3rzM58KA;@4gN_&3~m zRBAm>%e8Y`N@TLBwZU+R#(4AD@!Ck7t#{&VXJj_Nn6`u z^#V*6jeOPSwN2mCY#F#DOFRxdIwNCmXGc#A3Yeb*u1=AD)_8fYF{%Kiw{PpJtE+>8 zu;B*zs-d^$1@MCHvLI=SYm1A@k*6@41TzL1m=Y53qcHf^lLRw07Gi49Nri>T@ZEVy zo2gxCWvsJ+C67Z*$y$o+?d?S(Aq6S)!qF(&B-x+%gTGZ6KdDmk^ve*N4pPDa1V(u% z<@f`I+6FlscynUx_C3I{DZhG4GDo-D8X84H#qRly#rcZHAaZY!sjA7;QwO7z?e=mw z`*}yzr$q_Cw4k-0M{gG^J&cZSJo#hUH0LhzUU_O`sN~(~J@Ne3C#vO0cH9acO!~O> zq<)E5w7mKC>LqnuHp1?lGi-&Ym2hE8HA6gg<;&0>iR+)8`5Ai(KDwbS-%fgOj`AM~ zv8!p~g?3e&2Plx(o8qy2ZyL6$92a?kQ&U$L+Og=a565sz?(6Oz0PN_2dph>2yD<|T zUw_;dTL9cMzu>>fRtHX`f}TSTmhR@~oSd`M(_lTz*wf~m;t6YYFflogy58)^YinyK zE9Mdk2eb9Go|C;Bu;6Wm(cF8B_?exPgNcO|ss`nU)0lE6>FVkEdJwn;--Wicw4est zIGpU=8%M{lb;NSGFD0KoeTrgaJ(K-WESnG;cG|HXABrv%pmUnc0%Tz*p+xRq{!oD6 z|9(K;Fyae4yyV^mo$RCdB5OnFanIMLMC5Z~XQJ(Jr3p+HOV`@XA_SBddnep(4G?=f z(=#ncUqbrspOt7z^*E@OfhW%2sU>26KZB8 z+Zs_A629n8Srv`Mhbuwkj*!{jgPw-@Y_a7qs1*}j98os8K%h8@*Hyg&L(#{wj!K2c zIK3@5pG7n4W4x+F^J=;}T!QE{iO|pt14|)2P*wwcO+_KZj+8jOs9Ly#N03w(X0X@mMszbeDyhe^9IstBBQf@xDC1AHm)!i`*lq#Xv^H zfO*%1w(yzIm(7&ffWr`MQo4LqmWZcxjEF(fTPD`IT(R;wXm24j7+XwNCQ)2>H=vof zO1bWmLBM|^Xd#fYB71Z>p%!K&oTVCKogzqvS`fV0Q1|bv6xk&eU}kVSLNbRaQOs^C zOlarj|L*~%wdLh~5&S7aI5u_}y!`-^&*C8)TYxJzM)LvtJ6>cHMDn`@Z>u*F@cyNF zkVPFfABg`uo2jaiyq8(eQ}_VA4tbLaxxDR`j{Oflm@DL=jHfcfApnBec=@~ME>rpxsX6ll@sWinph09n*xIe-Kbjr1`^WvIah+q-<3PYAPeO zbB893!5(qm7P|R($&_~XwFz=p~n69!2v;-!9=I5&()De3ZKp5 z;v(|2Ir?!*pUZtZt~*OhOLQ)9t%SfMo;&Ezv|~GE4ZP1*N{!kow2S^tyCCL!iuUfI zrQbMAO8Gye3j#@gyII{@hm~+Lp7urYKZ0(@+Y=QP6*N!YLC#qpW6R;Vxw%0Oz$2fV ztCJ5OJ|wW~XwPU*2+Gn5IO5R;2t?AMW#;=SzdYQY;9+5rw?;u5Rjh!)G4O*Q13M6}+`--{mwl z$A$O4(N*IJZVczg>6awx1g5rkb)laK5y?mzSfVt6zsp?4ervP{kYC_6oeOP2S_$#s z#O1ZM3}IJATVjXU4?JSWg5@|}Q+ zf+FYTi6x$sgldzdCIk|}r{wvdm~0aCOX#eUhS25rIJZl4e3209#+(x*F^@t5+rjZM z7H#xtv$m>Rf$2>g+P;JotOX4@U)p+kd3ku~aXE@o}*%|k0rYTOQ{Lhw|de_&L+O-b9t{FvkP|=iJ$g|>3xsIp0ZA@J?Qm(Id zr<{@``ZkQ38M=q3`kXq9tcM9vjy;c-S96AZeka6aEg1XUmtMpZ?n{a2kZDPu0p-t= zVgcQ>A11}{3a_jPCej#-X$XydAnOQ<+$TZJH-dTU1tXO~q$bUo5`#2;;aJV{hm8ouNK!~Q{60g56w zZ&?(XdK!P$5QA0`MH4~zTYjFxK6ZrNs-{|rh_r#WM)fTx%)a+c;gYdKc@0RBz6i_t?OfMr<6%QohhHenIB=NWaEzxsOU;?i||o z6A082A7#tMfi(+OOMv!E6;>-NX+7u6p>#TX2iDD7gp2}b=#Q+VpBLrj6FZOiiY;gV z*E%RQ?@tFe0790p@qCk&$)`C!HT9cu2M#LsTl}$a&bK&F55cnAo2~^53rEsv((z8c z>z>Q1<=$3F)6d@C_h9YNGca5o4!r=^ODMEcq*s4@yffuckV!42t4*KSrEs5jy!@JK zUxr$zBSBYIND6*};ejEmtqM7?;q8DX8%}6ELuNk-=rBQhWRfc#xD11;kBl4tqOKy2 z*NnPzJ31V4`=J32bv{j~HKk;~J)Zn$B)WsrU=F6*D?D0zxVj5oYb71i_m)_+P!Yie zEIMJV3Tc(vph8nmU4l`iQiy=qqo;)kkVqvZCASG67g%y6$h4%=_bF6t_;M@HKxUkt znduQ-v>`xllR}QW5-C3E>+6G@U%8fTk_(}C#ZxcQpJ{7*(n(R#L0+ir$jQeCg84_h z|93GvP92QQFKPY^m=7@|47JpY)X}T>*?Q{g>d=%iBz{@&BD_EiFt+28o7{~4Q~6hT z9tQ=pL7(IJQBH@O9JqC^yIpUPZwMqG{giMcMo%q}+#G%{cdHj^cZ1~isxSGmQ7ZFcYD6?F-T zU?8<(BSe7&DL>+?=Dja1aRR#x^mka9)4lyVgxm{)zW9r+R;r}NUo z!-L;uQWad^rIW%Xfj=5T0TXlB*rIvQIPcGaXZgt&wOgD+mV(X3#(L?(V1L5|rh zN`1DK$o@ccmlC-&rH?3gxuApiROg<>v%Dw=B6zaDz30?z*-=GDxK?lX_M5b_4&tYS zG@qtBWo3WV1Vb+F8twZZk~#%9^Nq7^Pgb(Buzc~lI5sAr$FIuve<%8gJ@$OzG*-rb zqTI}8vI6?Znc=7n9pMm6ThGq2O%x4Qm&=ZJnFbky@IKl1mM1}YX6EK6J5%?9qgZ&b z8T7PSgt5m8wT2ozPR@_E!nzBFDWn{75%G63rTBWI<3rObr`+O=%!yq(gPNL^XrAZ& zz<#qanA6?ey)rv<%pD(a^_w0%5s#k{QQszk_dv*Lz8UKArL-w*UWG-s8I|sww?@@A z?~zj2qq%=^ETsqiQ3My3wexqiyN1H1TqI~;UIJ?arZw+VG|v!guBT`iviIo-wz-}v zgL;*ttW0BHWRuHvHwK#*Itm0n5lPNY1U5^&Jiuo_%Krk#fRZ%7p@17W1mDHoC&jui z+e!LOcmrC7mTif+0T{u8488RFM~?(I#I#oe1F!YRPYHz`#T2l9erae^NX*nZx3#u{ zI3Q=&sX9D9P5^OmdVbFLdi2>pr+Q<985DTS;k=lPjErfPhp++5ey;Eb!lOxZ%a=!E z25Fbif3B}vm{)B`z;Ma=db{VAQ~B*Ez2d%xA`%N!{wI7CL}RM{H^G(RsH*OGY5Q^5yro3{q$6?H8{ip%N5{pX zr#fjSU?waYhifG`zj;G2HIqq;hP>Eb~e`nM#IUeiqG>d>!pp1&&=b@5cTuY5D^Om4-1)#544IFlYCNovhFC8t zDVj>d=Oi-znU0kaE1}3Q0ct|llP;b?+g?0q}(nUS0EC#^&W~q@j!D6Tn=kj6K2Ostue}sbXxhVt z?ourSk$4Iv9+5`;lzo*Zie|lGBmtkFxc%z|Xy1KTGj#=nLyyo2wl}DB4yPO}(fEI* zUvrR26e;I(b|N|OlBA7<#WEohfW;xE=HZ-=GJInXCo~LG2m@^&E24M+0*%EZ0P>zB z^jlUFm`gCWWiW84)E}KJtn>-Sgx)hq2=Mv%zP6!m?9h_8K0(LEJ3TuKv2?@&G!MwG z?5N6^tC%)8I0#al047DWe|zYCIHGrig&F(hft+UHEfkl*z)mk1$$G+u47D*fyx=!< z4Vy}2M+==sg67~d0B2ktPf$dm?STFL6C^vPJjvH{*H2B;Xz+1_>Zb^M&u-XCm|YlT zydO?t80L+GIY9BAMJZqKAv0uRpzWB7n*26I$A$y(?@dps#lWYXscID1V|<>xylm&d zNKgOmpp*P>KrpTW5UH3U#{Msm2YS0_ii#l8taTebYhw%ZYE|Oyw<`*&aH+63+Kp|G zO^xCmI-TGZ&%FJ$J#$j%E!|=7seRKeBi&@8MsjJ^ zO2z{doMtF1KNSlBmy+_v_oEc5jM8ko>e^hJWTH3cRRn1U1|<}SGuJ)UkFIJx^QJm! z8q6u!9}@mKkKGv4zdzIYpp5C2>qgTy$zki^P>4cY%+-+i#kmM;H5@0$;a{Nl^wdqO zFpn!P$&G2ou*W9sY!yl&6hHc$3?`H6YCu@J&EmWCA!zH-Wv{`bUkAi_}k>4 zq+sNOyY#O@ypPL?ig8YAUdCHVM__(zwe2T@Heku@Xr7xlI=xK!_+JG=W*#69e{B5X zX3H1fFI`*aNeHgJ7oO{qowrrE@f^JGkx zb5!V*+^x~LG4N`$iH)V^^iS|3TuCnxrVg|CqPpT;?8J z{lfmLn9Amx9A%6{KKAMz3(AePqA*YI@z}W9oRhoC$Nif_^txLc~mRsS)UC zQ@u@cwj2>Y4F+FlPnWE(CmSWMnluls*r_yJ=kD9g&DjS%fi0vCDZCRk5LVJ*ue(YK zQ(QIrGhIQX@;g>i0Cz)!V*Hn-vDW=>mzH?w*9b>%yuNO!y+sz2HMf)1+U3u4JZ zJG&#TY#*DEGaYm9jl}ZflX?+J7}-f5X`?>>nW3`&Xywrx{8!I)5-CY4eRi(IuDpj~?4%^4{{fAQ=*B6v^Px+7b+X~yg z?6~G4^*p<`I>dJD_NKiIfZP~mJ-anxXXuD4nP=D))wSe8Pwx1$4`=pZLnEkHa&vNl zgJW^-V(Gk%bqi~?H!8z9fMEAVWI3K{IID`Des1l9dJr2Uas3KyJvzxPDF~;etY_H_AZuJ}@NKZow`c4* ztqv!mgoc$q-fwG6t}(ih41haWil2;gWdvKLdrEu^OU&iwVA4SNCd{ag1Qj)LiU{cD zzA7iC)PLkYQJXXAhY6k7zo5(bP2JaI^vh(%TCB?G_RZvE{tWF5{Oy}T^Me9|i>uRW zy}G(fjrQy>L)kG3L7Ufk=UWDS)9U7q^nRppG@Zy~<@w&ZNy)bX0YnJe(?{AHUL$jw`aH*G0Rl z;zQ>wMJ|kzvSdVy8Qu(mGBEAy3k-TjMzObtvYiz4PgH?l)xjP#MSxZ*F=%T1@J+r? zLK(BC-1s?lj1d&!Id}&0J=*+GP1+C~e!~Stb?uodI*=8v~_^Gi!Bst`_$W%P(@M^x<=LwmVoh=bqnIzm)Yp`JNmj zA;)h^CV$;`xR;v##xXMC{6G<2m^%J!!}4t5<>Rndg3qN?k1h|LRPt%VY3HXuGe~`P z-KiUK;4U9u#+FO+`KBVyjru8fDarVHrS|!5)04M{sW)Axr8gH9j;09BuVRG!y8MQL zJ||*DkM^chwC$IpysodXcxhE)Sp?WVSSUXPwi7XS=Dx~TQUlwC#Usw+J-E}cRP^N6 zWOEhjrl_AHzCX4aj%I(j3tbsQvWeUp7xkN-KYQkRx^EO1=z*hEZ94;M6RMMh(Eu;^ zI~!-Q{ob7vT8dfz;Rod2TjbWWzz=Z*SNpevP)2RY60PcX6LmhkW=<_%70GqC zHqO7Vd)VsnFAPob1BTd&62c(^-?i6gm@~UuXbfXVBb%LJ;3vzmWcUWm{ z)4)=9m0m^P8%tN#UTC0_i4>bUYTnT6^Neq8+p80CEqBs z=(=Z$F@pQ@0uw`>s_J}m%;qtSM)!2y7)^t$VX+ze?qN*XyyE2Ag9n#W%|Ns z7DcfRqo`rPer@eaZ>ESIS|W2Ebbx{a+$JJpTH9WNJ#S zd#mJzYj13bF{|v5^~3H1ChyUe-vP6G-c5U+i&=*{K?x1~zcnt;b4xThl4v&TY?4>> z>P)o;-$h{2J$=-VzZo&spX&3lwv=<_m)}M~?JW9K-Fuvp)jd-8odZ>`(GlDw^Svli z-pr34VNfr%tFhF}Z#&l7#s+bKY^cwjoYm zd(Id)uI`Xz!k6NUM!K}UZB5-cVO=GXTz&tq*K*nSvHL6B=)^?q_8`D;VoGqP^igy{ zD|0`8CLtkdJ%B=i3;rMkG7q~8ZI*aHY{#86PteMFCzHygaKy@PrVf*+^uhJO0tfcv zlKi9nkZnGjmGFD_Ux@V?|A~0KS5dsMMx|W6lQL(0UgcBcx)X)ZJy9>yVbSmfcSbwf z*=#b{!Inv!078Cg~uLIR8$&c{WHS6 zRb%h<@MY_W^tB#uc3>Gbrq?AGE#9N-W0~=Nry!2+)0ohdTmM4Vf7fJ8pJ6Ge=|+!< ze~j<8E%5`6tK`{6j;mN^BDLWe*Jeh-PTlj5?*7SR!|oea75B?er6Q4Bd~;JmWn+$y zozokQo}XXa`EYYgCXtfgT$gsgCg=W0cOKB2D(KiAOkk`7^gwECAc_03pjtklT>Z3=G)T@oBC>=JB-h$QvAx@1Lywdv(RRA((R8&+@P|!$G?CxHB%5*w5o28}YUtX_u z_cx5@oe}SSTuw=W$RV&M+0ztrg}u%Xc}i_VM0tw-jNw)ndGr~iGn@)IK5zPvA(Vc( zmi7IIhjLug#Z2P0_fmn)jWsKI>S2;O3>;{d~o9fB_c;8!q9@E^6CZu$ACFljP8LT>f=Rf7>KWHDVlxU_qjT$7-Mas%n8b<`u+N&lBxgf&P$dw9NlIF(0N=w zb&_T+s_m*PXyOFh1l|@=e`ZZs>JbP-(lysB;2;da#vGHbNZebun5!WI-rXAU^D_%D zq=bJqMDyl7vx>|1I8D_ES#U^*R=o>~SO?7!cYZG<;XOqvo4&xZedlNz)zmVoK-}Ks)@n(!eTG=ZC!c0{b|TDoT%aS zEG$2!rpWDIp;^f=6hPBf1YRDtRVw=D`AU6i*qREjdoKx z{j+(YXc;dv>7bBE^L-(9X8JQ#5cS6E>+2&08YuZMnb$HlA%PK4IZ6C>=^r?_I$C}O zr2;PeKerrZD!6~?M-*N3lH~!DPX?e>RhfrDqA<;&|8_~K zZ_ZMy2tb5||&`~=GH?CdPqV%Lt1+Iv^2jT;U>h0z8) z4JU0WXR|(lY~$T4{ooY5qnHfwbf5TnS_L!IA|Y)n6{n)0x>tYrgB2n-Gg@so=RIC( zq|Ogm5+Xw%yjNysmX+FNjKDLqWlq}J(Sa#zWSCqE+dnzEH-*CwH?anlxuiOd5>CDl zFg>kXq#g!W_Hc6p=es_u7g(*BF~X(el&ttbyixPXYfcTZ?&{1mk}= zS>F2xJw(Yt>;eLs)~s!uh`&Nka2i+4Fq{Fv>EM}d<8VO2qNF8`U&4&oM{h;@B*+}2 z4}EGK!QRBlB>!dzLK&A{L)vB4(8!2}0O2$BUp5z+f1`qcCSPScBZT6tBqdw1sXVDc z*lGb$A7A_u^)Ly=*UFuEG|KaBfI7fEYB(}WdmpT#F8x*l(9pXo;lDBLg_xbdPHUdvGL{0m#CJzYzL$SEdlB2AgdL28*Tu zlqDe{ArCjVlhA`{3{411<@mH1_#ENsp^PX;cza(@d^I=lJdid#F&D<(n`_EQNtvp7 zV^VgS7wZ_!3m3bkYK5o&&8^I+?cK;1H9|tb*ae4rG+R2BW+QX2ZTq3#QKi1Y>}=W< z7GQ{DE5}u&)n0Xk5;t8Pr=&^DUzdG7VRuE~=gU*6S>4 zG63%Ffl&A20_|O{5Vpc6V52H!kEVu|GBC2}OX3qj?!ed*()XQl0PhLNLnMR*@dbhs zcw(|KX`36R+U4-a(@15Ycm$@dnvl$lQz#l1jy-nlXDFI1I`pa??TK{(`xBz7W+b@< z*cpfs`+c9lv&!)oH�XT&bCn&8py!@)z^{J3VG44~>|)1;7}l() z8v}peLN1AubZyRYS;(#fzLmgw!m7WcaCsL2b&yBH$x~%hHeL(4BwVB1z#3#KaQ)hV$GE?^y66C6s&)wDJPH!)mat z0ML6UU?LsYBL7oecLfrsjKp7YDBgE==dX&i`|INqAYPzCb2v2lA553OpAl)f62U`^ zd!=k67_>k!I6FU2uyfS`ayBvfKP8>1nQJt#4H&39AU&+0wnn|}Hk2y6MeSnejgIf5hh$WMC0ea0( zO>f@vuU$J_Pig6}f}33TX7lp$Kn-p^@J&q=vHYUSV)#9l2W?vcV;yV+rKGXPrWAJB z9xc*&^6m~)QK%HcjpoaPCL+a7(EfLubQ?-`O=cAobO*~Nj_C!-)Jal5@Fn1b4Bl|Q zSzwF_^itwX(R4t-0OgRQ;ZXV6v+$9k_%swGOFyGvV@5U(F2VpJ*y-JSL?!HEJ=f@k zD%RQA^h^e=Z-D8e>H1s&NF3z=a!pm+{nK6a5D)neiv`}{bH#t}e!={vdUnJDT=4Z( zA8Muv2nf>C(@}5vG~zyVkM||TEnrSU;e)h^(6`M%Ee0TE97e?$f-4gTk4`0MUihODO%sJKiOaW4m+- zNycT-AOy9$VDZL%^qCp>|0OqI(t znMv@%4U{3@y1lQCvytpLtZHCoNeG~Q^9WqdOfwn(NfAINK#jfd#F}}(aMiF|z$$Vn zxD5?uV+32}Q7*>*KM0Tt$&^bW0ZO%)(Qmmro8_NTH%6F?3S%~-qwONfZ;?Qv+&)o} z()bCHl}7x_3qWm8fvv+D!!Tm36Qhcab|AL~Iglf6h5?u<(#kGMt&X%{b;S`u7nCjb z06L0tJrIiUW6kNX88CsSmnVgj2TZn|r25_*8wvqA30-X@G_pTvTD_r2Q7DW4tbuJ1 zEPc%g-7iY~T0lU6G#H_)YG^<^ZYT+SiII@o)OdKMJcPe|0a6T!h`_{yZol+{(_-Q7 zGk1HN&}aGrH(V+59WMDJovLSpOG{)wTR_rYSy}1+;2%4x3jz#y<;;LrVdV!3kj4ti zDnousRNmLV4_V7JMc?TKW|UzPIsv)Ytke{qd*Rtw7zy0;?TeIIrUluOnUF_~C-(>u zF7KxwzyY_ShfAcLg55kYnh6ZIxVvZAU4o6z+uGVjtRAy9ClJ6cmJ>W6@OjF2 zu8C~(TU%2VmMQ|*U(@_6twsj7jzDi9@(v&Z5TJt_P7W)XrWoA>!OhnaF5r6br;`35 zu>WgA_+J9DD@jxkD4EqJU3jSa3p^g7#H@d_SDYg-X1MN7$NaMdV}W=T^SQpPvYGm4 zc2o5D-z4(44nim`9S;|`NTVeEKhxzu%}AiPXl%3ffIUGHi3HF9N+?8wyGBx-46djXb+00uirD87K0us+m zYqX<7nvJCYPiz%0FivcDv4s~zaSB~NXD}%x3jX8A4+m#w=T*vITSvg?XDq%)z^^b* zVa%8E_&%t(P1N&xXGfywTCjfI_ucp|!Yz#`B$Pq_`gPXoYJ%aJc5MLO00%*_AHy`be2IHOJYD?5QM>_5IDfkFbn zUZ9VI9*;Z-?*Vs8A1cKL1O)KUx;+7b3K}_Z4-8;|bYESZq+Lq5qWn#f)Z*ge{QMd~ z%8yA(y5;FSN%p;`NBGTR0Eqi`Q*KnE0O%Hg)wJo{&;PKJpqH3`0`OEuQdIDPgr=sZ zloUAGl#Y=ROJDzYFCitR*sESr@HwE@FVb(Q18+pn$;rvf3u*>Y09^Sin}T{e^fpbm zvQ!y7785Q>(G@~mx((!Z-=#Qgi~U@iZ6dHspaar>0BmknqlLG=dsKx)M!NjA%j3Ou` zi3YMYCR=4&6@9GvOSf8~Z^F8eNJC5NQsILS7#Nz#CF(5krpmtcPppp`JLoZw?;&wv zvL5qLD2)21R0e5^4>@3;!ENvF?{{6D`}6hd*R;#{1YmImEqS%|gt9G7xrBiw7wH`= zf2cr2^j8YQ7+6Nud>m;kw_jOmKnF(iZ!pK%%ny}>1tZ!%=eJi7j_VEHpX820P})`@ z9=+H;bK&!h@TYJt0M)VTyMnB&{p#M%195NN-r#Au8h`_$X`ZB>T^#{ean`^?5L9x{ zo_%|>grx)#!=3b7-aWpTmp$`9m%}SAPI;sG1trQ-6!YuPz)-mR-qgnjjn517)`H$$ z?FHr!kBFa6sY*b@^1fX-?+#~Um8tx+C%zkATmAZY%jPxq+d2>IF$;JCbgA3yurs{zVSxj6hi}b9C^2Cw zUaIACberQakndf?r$@sYXU&Ye{QKsH+e+RQ`>!nJUbn`&X#tBtZu;wG8J^K!{3CNV zlFw%9>gu=>(T49a5))v)abKd;hHc3@y{tqN?xA+FtYB6)0_0ekq+0lXvDs_)} z1;?kye{->}ebKVmV!HoH+U%P+hpWx{DdouxUHs$2w1xjk&*=s9+1>ZI813IHd4klH zJMCV+5dN0(3;SPmK6jx;uKdiu`{Tjp!QRs^T!MwQ4$?uC8q1u~yC!1{?gKuHQVF-* zD@%gIE#ev5<;D(m3Wl33zA>GzSi1+CE2=}LwEjRBeemvLC-n_(W~W{ib-}R zMaiCtdgR&r$NPwmxv5h-r!&;>oy(ocyKF0%x)*bfIZi|zd0k#N%ZoP9#1~8UG#)=p z`Kt_dO=^a?;k~}tr2R6BE^!~r931yjSF%3Y!q9%>f9t$WHuv&zMawhsurmk0VDT%_ z>cK0mmOXKNt7!2otz93kXFtVnUG~V*h^yDvzc}Ft_d(S?e)^m7d3?aXO1+cKiL9^@ z)JwYI>@5m8DY-J6#P>=b)SctZd&CXVDcV@uJ=DxRxWhlRMkGzPbL}nNGD9#e5UugD z8wt`1MaL|cWhA;jeclkqWyf=wI76ZA*`cgOFCvU@V@13vBua;JaN2ct+BJob)djY zwU2jPLk*kTUg;m8{>eZxP^3cq-Z~vt{{+ozXM-5$YU0;j;%{TGpor1Dy(iEmh-lf8 z(PVE4>LsrDGG`v&Y?Yk+V~bjk?$U6<%J~_lAEKS=R<$|X1`18rJzu#|#c;9pYux*# z0C|{$oP(C6A3v_A3d4P($kEp0r$2ps{GAfg$5*-Y3nB6M)>NbR5}nZ~(kmmTK?}U; z(;q1{w&%aQTlTd1?2mKADZBLA!Z`~>U*0{0FD7`{e7^FY-q{*VG`oFXdAErg@s4BP zt3+%dOVOxMcdT3c)jN~UY^_P_yRBx@&qu_1*D(_w1rtQ&r^4T%BQu>%!e(K72CJ{U z+-cr!9#qA%T;SoVq7`i|IqYcbWU;>M(rU-Gcq7A2IYC;j2x@A;0$2U`cCGAWgg;DR z+L?=CZK(O{fxTqSqS?9dZC|`YSl3~Lu3leDi?RKOmMM;{cwR9D8j`Gs>7sRNDeRv; zr1+SWGG?+Oa&muFbv-Dnl}`!u0oYZ+*1_B=f$}B!=TBs%Hf9w1RueYZ6Utm9GRQPC zryM#QFu&MGm3`$e9zhi4^$&jeS!Miwun51TI;rvaVDlGr<)DlHx-{qwslV3jFrTCO zj+ujpa^v#q#_xgtUWN;6u?g$>MOL##tNjuTxT@TEDkh$*vH;F+2%JaCm+n<5JPL4^ z&e;x|Lq*hdhn`H-)VUdx2P>gX_^4uGI@j_6Z=h|`0Uqop@TWH#K}2%O#MRLDO9=}< zZH$uRV_TQTXQd=0_&N04_T&}>YI^}IVn3?cVo!AJ#=%VCb|7`Epn8(0_M)fm2>!8dBXFff8w>F>)gH7- z$IUiXUX?cg3uM7 zf4j~VkSaS7e}|t}>)^J(6P9Fm=gwiJ*I^1%RWEzzZsLzjn)SE2{Jech*S=)s*K%1v zO#>Ho?)aF+4%YQiP1F4R{`x0;H(lZxyW5lCyVxWRc~!#kb+MP1_M}e!`kL>$@|>k> zUK`LdE*)lhXFHN|B{@_V+qi|^2dk-xMbr46V# zuxRh7RunH~mfw|KT@58S-Y-8}*A!L;K~_691Kmbui9AmMJ3dt z6>)%X?xp!J8DlsV3wn{!O94te;oBAXwU!yTv2E-(*g;{}?~>?i{$*dt{diPS{RvGu z+ubthtNuFtIQ7C;uM?p?CN+*2Dm<8>@G~%P_Xc598ZmaC*Dz4*ha{WZRIw%lHA9HB zXJky>QOd2Cy4KwNTq4SA7o3Y&@!=b<(6o!2+!TQZzf5k_+wHR%t3S6+M`OD`Ub-m; zh~AeCw=5Nl8K^2-t1*vc$xf3flN&mQv6xGejuR5QbUDs0wcBy*p5M2u4;ksXUq+O9!J)>)e z7Xt0Xu7F%5I1b{ONx@$ARxudBFdwu@)?lc&Oqmw|3OT`I(2(580DQ|3K}Uqi$Bq-5 zvM9nvet>3_zI@5(I0&PXtDJycRjy&8cRAAFQv1OhmXwr_rZW^nA61IDT&wQ*IM!!E zJL;zOt|~WXF@&dP`C#U2CaN}p`tUQGEn_zP>*;>vZwQamA!{{TC9a*IIPuTQ*3N91 zb+z>jxWr~T5)~7JUE2zh``@V{ar-bUixK4FX$P*$=fy_Nk}E4t+NnJ1+=V$i{Y+nV zA6z{2TQD$017`j|9thWdOxtInnVm#fWIC6;1z5jEg+o3A`7Ao&K(~a1eeBoU-z8Ur zE0SK`N8UFaAEtz+*OQvIc(?9$sOUb_7d{jq4 zz2!0%PgS*P)dyWzYB%=9ZDf7D#U%GD@CXLPXM8@BVjE{^*r<&6nUcbMtvSMzf5zmG z4)|Gs*JNz<=4vwhO;Y&%B9~kk3cl{khpKUzXc{@3Zwf*F$jR5wo;?Hoh)zrxj?Y4f zW%P6|anFGg5?CbywmDBk8U2fdEE0ck3rBWFkNJywPpj1WM8m=fExRm=!H8P2;WSj2 zs}V5yz_uR7v0R!LDZxZH%;}P_u~q83J1aZ5UX^%VhsaK94U7wLH|XE5{_uq*1qyjn zG-9-uMhfBXR|m!RnNe-P4@mlXrZ>9LVBzTCoT6V{p0fd1#5=*5#0yF zQ*k=XNRIkp@1BQ>Tyu$@cX)>&tVm8JBD@fNTK&*?CJIiAxl;XNW%T@ybf(g0Fc0q4 zL&?<#M&bN7$5V=)b>FZNkwO#gPEH*ak-od#ZF+h|zQc}yWVQuTDtfmjy#!WO;MWZv zr{kc`b-e5yu0E~#Cbh2K+bb@(Smp`(?n6m@nF>c_!DV#~1@DxTv^<1uI)-rP>}=f@ z&k$Uu@7S}!H!Fv~oAf_4Ej(o0F;!ZajgD(n%BpLYAer*ojK^rVwC`Y zkHHZUcIHJshrJnTTIJf_AHK_qW=7~f#VXaQ z|SQvhQwJU7?4vvJh--Q)Ig{1Y|A^;*O+soJ*dMHqFOQJDxDmH}b%Sb=9GW2uq( zyuU+%fQJk|`qkJ&cUR;88_^|}4fWNpnt-;B}yo9EKDAJy$vD|b#K|8(7{l>Pe2!Qfdw)|!k)YQ~eR8Kt~B7XPn zz$*^|-<%n0#RpD?mU9CfDudaI8q2mUS+0|ZQSva|J=F@#SMexC(Bix{Crgxoqfv?C}Lq~WuPUTU1{xYfW6hu9wCX3p|@>{sIz5QkoE z?nv996}!^WX1rNo^}T+fbm=Z+VqyY1LnE{(+RUE91x zG_KRRi5>RON4&Y-=AUkv3JMAWp>=jZlMf;)>gAR$ae;!|%o#jT>~Jo*SAbW_1c-s- zT?;+dL`YUv78?I`s|mIkCO-aLhUkk-<<}Aqw-@-Fmgbenu-?2}NWLV9Exupenl?tI zmmWnX_4IuS4tMSPCr{qMa1_gnewkJpHNQqrmXqFYH4IB=888CFW5QLL{OLv8~-Rk)c{s#3GZQ9w^@Yd$$o1*rQ z;lu*X0AN~da*LnqyL`UfUr&PgaYP^E7`4Z=MBZDWfZFpLPhN3GtlIbY1rxz@qs&E; zIZWnR6cX*)pRKK!<*_g{-^gP{U6<3do|PguWR?w*1#-D zSh!MQzoZ|(>oZ-t(pY1E%@^;tkQeP^Jky;$zIKH(*-58`w7{jD1espEp%&VP=srJ@ z8mR~t{(TW2uTm$ePElq5*RGZtwyAgL1@M5>sIj!DMD8#Fn2?~Lw`&58U7?W159(Wh9e`%r5q9;-TaSUvqG4Ny2@$p;3G!O{T zK@axyFl)fW2pSG^Ue{r>$2RqqWi&^T(wUY6Nr&7Fc_V7mnk2f&gil{8)3F`hE>NKg zcx7iR6y{l(Y{%j}eb?XT&vlo#RK@|w@7e6*Q<&Eq{Id|ity)G#ITR8-9AedcL}etO z@6K!@FatW;&Ui6(b0KnbuLjQ=qXlrrA`n~G+>#H`VSGsn)ynky;}`;kOMDw}ZXf|2 zKuHw}q<@)kulZp;8J|>l#(6w^hcQpBpWWG<224=hs&KNXO#7yr@E(A1L(6goCKWxY}m7ziezC2>c!0{mo)WiAq zNKyhUhU)H(hpVjopo0w99Xpt6eWXMP*P#YAkhF4vhjYaS#{;lRF{|Xbh!FGORoG)B zU`rF>-kamDMd>=V@#Vet1x0t}dVMr~Re8u{6h zqTB6WTM?S(IPqc7Jq0AdFLun7l-YnywNah_^T!FVRh5P^0|f>Q5Uu}~&-_06x?YPh zq|su5I0H|UBma451jFyW@G43y$0R~`@KmOYV`XRF{3w9 zRIi|)0Xu|J0lT=N^DUDpib2;Jp%Ogv%j*ok7kYRhf1dmwtQrogdw)=a!`eqn21$!D zmlr!Efq>-z)-1Gq4W%(3&iAD109?a&F|JskQgmwCw<53;pO}b;k6$ppdl2(US{mqC zx52l>tnRs-!?7=Eh*?@%8W?0LxGU>wr9`BHA8rEe+YqMa!0oHuOk*P>BQ>?xr_1m< zLv0)uvw$bUX+B*#ucE?^@vy(&LmP(w;=|6HJbUC%G_{aF$x;`+vcvG@1&SAZT|Caa zF}f`#g4fUEeux#2Ao@bm%f+uD6*E!-Vjs~(uzkQWg9n@MY|APBi7PfNz>WX`BsSpa zDOSK74L&5;Yp+3=sy3g=IHzP?`LaDmB!mvPA`VUoqA$rkBCT7q9)Nd&_?$)K+h+q~ zV>CkUad6sffo((Cm+q$!H(97&VLCwzLUix>&e+xAg4xpnhgNUl%cO7{F3VVS*wksY z+@FSw(1ub72zWh0AD-SE#7J_@*asib1p}TZuZw&kkYz1K+&TMxx z5N{GhNy6!szz;2AFxL&fu5hJ2AKk0fV=c55f=PnO7$HH!9A{)Fd~*)5+=#x*jtw>; z2)z8Z?-jRg>msF9_fcsN@<(iauC3lLv%>vFf@I$n(-P=91hbsRD}!Db~}FXIRNVN&%KZyd`*H7fJRJ&hxb(p)pr(A>5hP&PVi{ylD2=LiuRF0Q+e_^)aC^uoL2%wSsj1= zeNB2WTIO&%CznUt&RFilO+YNX(D9k71^}1P2;PI3P0r;7ZH%V;oo2n>69wpMnab!8 zkV$l`c7}k&$^-=Uw{PFpUM;$XseGpB1_W$YqfoG841i<>h&tIczC{5Ggo7zvFZO>z zd&Du!{+(<21_fdUt)OAVG50KvY^~+~CP@ zLe>pV2;HAp$PmZ~e2>ZBr*6#{$z~Jn%d!CfrX%m#S%~-Cfl6??YpobeZCMyfS)0Ls zxd5IpwN6;+Zu*PPYhfT%qT#V*wVxygJsSllWK!nhbY5tt?G7368CnE$@V=k-3M!;Z05Atp~%@h?>9%=(=4+#&C z8#rCAaNE5?aj-p>CKK1(cGkP&zsbeJ8xN}IXmfP?v6R_Oz_@^(?+?2veunVY97)pX zaN%p{bNDrL78Nrw`av0ayCGkyG!7iy>ZHxx1jxMWZq$oZ_+YgdxuWCg=?*0}GRG8^;Fi9jet6nAQzj@Wb=mFY5fFDGp{T z0=~*&dhczy=yv0oVEV#0qYLmb(87)YU_L*&Z zJ})0^0yG%u_Fr-LIB6chx44@$uV_t#O1d!a&CMW7i0igA1p z$m$&rex{^=B!(Q1-`yE7T0&KXARtG5Nkc;eZS-l=FOy2;ok{E00frL5Z7CG&Q|$)F zi?f#~1HrQ<*l>`hUI}zKp=)fgt=j-&@$#QgNbYh_HFX?cn9m9Lu}6((;ZK{oJDhOI z>#^zSOK|uB=(lQls0QEZ-?s>`evm4Bd5W)n zL@TU4AnOavhcu0@z5rxiK(l$uwd&TwdG2pwpAvCEgm?3RaXSJdUO8jqLn!^ zDPaP{eMb3WvK@XIe7SD@SMTuKi@z+e*DD~DrqjKVLp3eNtM$g`Mo^}nei`GJJZNOs zut3mFGc#HmBIF)B%^Cw_{C{x8u|(yuV$H31YmhmqKZIH&oM5i*b%;ssz#6LKz`<}{ zDX@#dLjEN7fl_p3a+--!)@ReC2IqVasK zO@BO72|b_J+V@&`kcom}4~rqXof6X0(lRoa3di{Ruuo0`AT(g}Yk8r%Vl&Kw5*Dm_ zjzBn3{^{#mOi&jb!w=YxfZZvCu5^i*rpJ+V0s;=$rO#(umtO##yjp{!#nasl*braz z^}(io4I-{)nf^Dh<<_Ibi9prJ3W9IrX&)UR;j;akSF>5pPp1{-!H{rq;XRt!T~LAk z7_g#wy4d~w;RI?jEN99o)#X(&wm-={z;|?^X&%DLi@A0V07>a@#a#aT z4V8AH|rqH-v0+etGY>4_NA%NXx_5 zH%E-hG}~7Hy%UFV3ApWhOpyGe0Ak1p*zP9S{!uY8G5bp`OHTnVmhWjTOF)wOw1Y67 z;v85|^Gdk(k8e24)d1rU-0EVOSXkrL7MlOL;6WCN*dlB-Q$W8LmT$g7+Hb2ICyp+1 z(K@$>QuGC7Xv4O*eBZGlN+z1(gg3%o4~PX2YUaX3TG5PaB$Xj^l{)WWAj`IO)-c!b zr1zPj$k|SK?}m2`A)z%F>R5&R39^Po29< zqlEkJN3Z`MV+S|^f+KIQTLlKP^g86fk_Ru)skz&U14Bb8tY`(gO{*q@p!L;>%o3VKadqwt`s=%<5f4BmCot2w^Q-l{%l zpV>0A!&3F!diuMI>u|1@p3bXLoU-~%Co1sCGSpBUE%q)gr`El#jG^YM>&VVKTBdYW4AHW@yqX3121|;>Q52yu=N#iS zAygI^K2L0Mgzm>;R;^X~$FbD3aBciLaEG zBv1N_{l{VI?F8k>%~BbXgyLms{NcA}6`Eaqrw)tFiJa5|P3t?C?6A*#zx=$?Ev1uv z4tdL8?WlE?q)%>2QQdO%jhN+8q58UnD0HWJ|DMUNp6|k9rFf?1O2b|XZmW(d_oA*& zN5mv7XCY0?tq=~9br#Yd4J`L3~`tudzZ)MnXxNJ$jcYup;iL!GtFc>tC~(?SK29*&mcWq z#7p>ND-((?d(S5uk2WZ;I8Z7OzIQJ{|J+u$+OY{Jbsgme0t(+N@-h<}H!dEcJLV+twc@WYV@=JDyueRPQKdBgo^ z1+h+Cy58QHhq2Cn&FykFYZCSIA`k1)u0}6jA3MU-C8*KS-*6^qxr2fo)QeT2i?H@f zFB2}~k?zRG^t#WO6V@|G;8%e|tJ+g@8_Qj|Ljga8=B4W*a#bdCg2;+w zySkn{xl6Jt8WwJafnJ)%&qTKcZ*4ab*2Et{uOB+Fub6hu&12U0v)|!%eoTK@b!npq zVmmZB44tw+ZVID^i0VEVJN2o44WEBz_oe0M{j4k_x-0`B%X-E1%u-5St(8me7e!*1 zwQT`@k0kx?EiE>}6|QJr?)IVrci)`E&viS)?p8%+69-@UO)Wky=L=9k&^;el?5~(c zKe5!H)UlKteGpi<=uI@sg^of0hFH08U29f4UWK`vueWl@2bYY!@+V8~E`EMhB&4DK zBmW>w0ih0y@1*KFfE4!l+8IHX4s+#uX@=vLHgwHaNdF9BDy2!ceER*Ccf+Z%yT|@F z%_QR4(%&S8@>6>6pXV&cNL18!!$a&p?kJr#>}%CIFCplD=f8dUL8#9a=&`&pae63t zk1xLUIO*9QcJFFBP zDy}`(1r-n0Y9F(^Fz>`6r#&PgPK6=&*vC5`{jr`ak;sa9@>lz!UjC%+8=h?}Z-U~o zXNP-!CIzr+JOj}62^Xe;y(xPWo0PfdVIH5M)2JgU2BoOa9 zv6NXyN0hm1nvJaNvlFMziVTDBJ+^!PdnH?F_NO{8^EczynWI*3q=X)lSs)PH*Cy}~ z=ET9cFEo%K!aXzKB)a&C|lWz^NatJ^y_siCO&SzWlGS&OB_~4-QOc5E4R>4 zFyu~*qkEV#M_Y<+hCf@nVKH5)*!udqFmq&Iw}*Oa!fabgLqfW9SmGPxA_XXm!R;ZiF+FyO|eqV1`<6I z5yCh|BaZ_<;Jlb_nUZTN5mRZAz z=<^nOP6KL+i~97cG-6dqL7G%TI`H#_dUoPBit=%50$g&u!8K>HXmX)5XEr05$cCEbr1|!53;4Dz5}h zYGAa7o7r888XhB2gU7hC?w&Q3G@k9}KTIWedbx95?R-NZ_=TKE%_B*`0_V^qK>6in z+)yAF_iU!6$i48cbi(*?Leb~o65}esz07)J1=e`-QWf`c)bvkej`IEB_k1f+hHQ^} zFDF#5gDsRrOadZ(b{oee_}0-Zua?=Rq2z{wgGi`D%p`L0P5K>XvzrSrI0;UkQoxl> zyqz#iYPXL{p+rTZmqtLbEIs&^sGHp55T|wRsPfpbxt|B+aR*no!*0xfuI}bveMeJB z_{XF9o;ytT#rQC418MtO(HLlWrw zfljQ4#yPbc{yhOIMYCz59&Dt_JuIb!?R$cr73V}fFm15ROV109oHhi1H25b|qwVfP zw(i91dk?dpl-zai__)4BH-@HIHG1q0)zMVS3v&Kb62cGS&IhWD7pLV^6GK0YQO8AC zs86&A7v9cC8p`rM4mH)ZL{FJP1Fl3ACdOWZ@{=%cA7kT7gInjf0L=H#c|9qp=A^Wy5eX-g(Y*%3zVpr{tmv_ldU_<5UqqDL=y5(-TQi>? zgE#<5HzlG%gdK%ZfA-5hRuS8~k}RZA3?|=FB|nXijdmS~g>mdy{+x@3aN%{^NMg8u zk@=2z?8BuF`dsLsp2-D}L{wB1KoLU!Sk_QeQqmL&H@~9>v-DgCdLys*JL2*=Uyu51 zxn!Y~<$sSSRkmXZ>1^lzOULm4>!;@J-}nN*P&@`7=4b$P00}cR3@L*fv?a=c1nhq) z34Qzi3pAX;pHtd5=u;7h7;bZx91y#m9QC(~?pSH+yv33JhFj+ZQnnlFa7z~5}72%BgM9kf&AhWV5 z4d8UcXV^SiUIC!W4kH%uym!9E#%&Rsa0|*?1SRj`?!>9r;3q86ikVQ&kl&82xGMnJ z1lA{iP+mkZA;JRGZN40!ZckuVzwrqJP6!c9zG2VVb}z7B{}95JxL~OooZXpB4@4Ke z$-SJL2B4P!y7GaZB|m>uSuWg`brZRr_EJY(_b_yO_$5F z-}By(8yXslii@jGKaJK*8vOp6930HY6M8zj0^n-U* z3m>k;x52KqU`Fihfg=UN2}>K?TW$V4?R5Hn-eCkdIFdHy!Cr_rQhHkA1w3dCnSr*H zl9Ezg5&uW7_Y-ziY;h2$jZp5V5Vp9?|7ZFB}#Si zyV?>MFK6cVZvaRD=Nao;MyTD9z%nueyWVVn>U$r6{sY@ba7dY>f#^Jv z&;{E^=PT*IaMZuMZ5THcpEJC9?bKL7QSrx*A0YC*mXMU}1I@4hbZ!5EuaH6I_SEff z>n%rtl+#yu-M^AW$W}q?`FebPy`lj}LRg8|il&O~-HqT~v*=1kPhZ#$5?~EWm_;9U ziD>_Q!N08D8gM2--ki$L5M`e22q4V78y_D>mL=^Idf-x{VU-(Zm~M2j1NdGU*INn9 z@=xNQ;2M9^Zt2auPbNVeFz`QUln>r;Y&a48h=8N@`x%c`Z%3ywY~+dlTBd8iI%hWc zcWq;|=FpP~qQg;qPJkG6RfH*WuhCTr?+meKE9P|>6GmQNqnscLq8e+C(c%E?3YHt3 z@l!ceTEb7@BXGS%gjGVicOcl11Nt?f(qI%Wu|s z^p<61+6Nn_mFN{Z%r&BkL|yi$_-fM$Q=mxu=nh&JQtDbQ`H-gvvY1cX%F3UAYx6B1 zR*CS%NyiE5b;fg38gHlfHmiRshWYPijMHccWw^Ev2>uwSquDi}N|{sT`TV_W*4R%8jlfc_^IK!TD9bpF7t z6m&yAQvfj13V8PZn>mnDQhqDUdq}LUt(DId!+YA0z=;0`wga|L^E$r)3RY3T%rY#F{&W zBk5(?acgd#_`fZ7@-u|-oVO7B{pok??8-E-{l-rlg(MZ0zo!krDI6>;(YA8GC+4`+ zR6siXA1LtO8wC!8qEdt2Xwc1mTJg|V)G|-L%}I2{1-R>oBQv5q%QyJKV9snw)gBXAfNa?@kfjdLh^7TJ?(jGths5NgNf?kV~|A&W{lg$D5CE5Oh(D8k;sN^idxqK}(-} zPsf`c6?M4^M4_P}bkQ<>R&>c+^ifg<#WU$s?gATtO+d&9S_5c);C-%d18962~ zQikhIzIuRDBt=jn`7&4L?&g-VfM80%9v(3RjdwS&tsMn(Fjx)yu2B9g%PtNGME$F3&yu(~|`$Ghy6c!c3ZNes|z^yfD6zUIhn0J_F z%9!bY-fj`e+Ud{er9{V?(A$>fEf78D_i(mJvHHhpg3w(TnRpJAFl&k*kGWFSOgIvA>l&y zC)~^p^jJag8eo75z_3+;s(WI!8(9aSppJ+0T*gBLX+ac?ePE&s5LV9sjVj=9$e$FH zKT-9-Ng!a>gWPe_IRloGjI8X|d&`jw(JoVR+NiH%IW`2UT3U@@Rm(d|0F{qUrBKg9 zt!;0i;R>+dq^T6ag!`#t?Jz89B_c490$?2Pk_JKWGXs>PKAaX+9hYq2QU5)ky!ZqD zYj>fwt}tM+4!9+(z^XiT3kWP{yh>C{h#>c1gaZV?SW!*&MiqE7Jv1QO8^eKsR~P>9 z0sP00|GB+V8a3d6`SjZqVP)_B4dLp(^1=3NnF(NmW-t}A3lEy`NrO4|@9n(6Rd>{M zwFu!SYP~n?ivc4kD!+~y0i<@A?~35ANIuuXD?1(nA>fk`5mFjMf)I4` z9k)IME6|D{cLCdvESK?LQWYa4;>f03kb~!$AlMpUA_pchMk@z7xn_~5{GVJo85tRC z>(T{F@l{nxR8)fZ$78Yr4s}|P)?i)0ssgJr1*ikFt#YEwz;?eNhrrHS4*3`51^^!X z{QROiKz8*H_9aKtOyA!Vsw&O3Ipde51^kh~MFgl>W95${mNjR*5hhfYa`ZU;ON}s! z3JPFy58#;XgS}7=m3Z8jPUk!TDM)!2m1R#j#hA- zNp0Dlu`$BR#DsQ(&jH>3O}o6rcOwxEI1FbHhW}QW4I1(N-|Qm|x&Ey&)ehu?htC=n z=vX^JE2q}`{@$H}A3PH#iRk_fOgI>>yN09Y1|U%f!e?-@s`pb06m!F=`N_PuTqyWo zdCv=}#{v7A$fUgdr5*cKR{t#*5rJ3U$spFN#}T3;U_Q}zU_JsYHJXBp0CoMiT+tpF zC#4R5<47tJ4Z#7loEG<+(@#uIF-b{0fNckWKv~=82nYZGOR@cnz?BdcC9kCw+FcSu zFyHLaU(%r0C2_cW86bg=l+2cb#|fNWHH#+8;fGD+|1A9i zcq{a)=wR>?(6`}pm;=SIMy5YTY|qWv7L!h6EjVjlIE`K!@@~OPz~VKYUVT;Zm;aPn zqw@*)XnhRM|J+`H&f^n}?Eua#2nQ|zUt9V_Mhoh+Kma?(&1D&g5@KMy1C|Sb&%^YI z-2D%THZlB*QU6SEIlz+zl-;m6K_yshD0fIRLIKC$qDIpH1w4eY6a@&HHJxcYG0BtP z^43hSyd$oKx*EvQC;jb@;pD?2%vHPLd&&puNntCsNXQ^TM|gY&nUwtPL=QbWN{z}6 z_v#4uRIm_62vV^j+_{!-D!vj2?5I#byh^QK9F537S)(GPG1<>M9I`>;SqlX`Chsqn zuo-X3I$*M8C?$&kAaC?4nt~K#dd0bKC4fBFC@@3qGfY0Yx0Cniipp;5p+9{;w=pjZ zD*ehyQeY?~W)Yq*pkN67o`03|<1mUpOYDc=*yD#xi#`j@$Poe?=}-cLcq={B)evxv z*F2?3;cM@W+%gS5b!06s>P7#g3+>dG-)+qzfdv`Ts#{lmJ8S|wWOa`m5f*dlM{yv} zEMR?r=!dRLmV=(CU{s+_)4U6Th45%e0CJL1vq(>Vz%aUzZa`MD49M0wL~V?zK*c)z zc^y_Afse-e?w|&^aFSuXeY!r)VF8~DxYh-QhGr4a*YqNAAsQMjU-SdGQqq=>Fh*mB z9MiTc|0MC3VdwuO{qhy%pD2^Z%o%Vb&BUX*!Y!v})I!2;qcrz-(#5@1FZ?u+NeGq5 zO;iIB(+RS`@9_k`bIBL~atF`g!6c{|FmMPYwjEDtJh;=IDzqnp;Ea_F#`g~(Utj*e z=Ii^auaP=_{g@xpxd>ggrK0AB_OCIL&Q{o{8u;zeLw`qWi8|2oVGQie*i zDR5_Npfh@~Ry;CXWSFw;AGa1XluvMe@!7Vmm%L)_o$}PM_Ok7GBY$G?ocGRRR=4JF zkNVMN@axk$U1+NNf4M!skm~dvgT;9`i}2JNM2C^~WX)=|%UjQccOGq0)vm_12hGGM zOlLRBlo3LpvtvzrJ5&~_0{dwK)B<2?g6m}w8K6)?Md~YWPXeX_!k667TM_(habG6Y zQxY?|+fL?mNB@*v+<6X(wBz9CGnW{7M*QHoUhwV`jp)tU=lWo?Z^D1+i20&7KPj34!go=h;jg8L^s@`_+W-`W8+C?nw9HmYv5+p0JG5e^=g*}<; zEOp`)|LlW%gUqDBFqxlLYG}(=x?GISC7LyKM&1jx{Ms4Wo73(Xl!*))m3hhqIN&i* zi8*{H!Jn$k0_DW~H7F9i)oC3%USS_gz0Xz|zCk~}&WDY>R`{KpcLle6qKt+sdJ@LD zI9+Q)PDG5GF5VKT(@fn=Q5R0gi!oL$ZJ~}OIx^p=ZMHJ~i*@K+_B(r%Lszk|1XhTG z@zShyPkq0oJeKHG-Nf2v{5c`ImC>zsE*c?cmF3(xU_2pS%vJ}zx7l_wR);C4=aFd? zsQ1tkF-X~TlGXCc_*h%*`Ej4HBo)&DT+10pU2L^GiBoC&C-Tk<6djuM9 zdx;n@O(%lQ7OcABw+J%c)-ze9@RUls+p8%pXg(i!JPG!em1iJ_7!DNl@!>?2{DcLE zjF8m`#nV~2N9bzfgZP=o{A}IT0UCvT=|#8m%$P7V;gA$HC@v9ZnE{f@T&>GdaHg2sc5aK@$QQ z6*3ObLq2u{Y{OPSXsnq79(?+4YflXFBn2eH6;N3!7;%Lw2B(`AbokQ}GMcf93Bv_u zcYTtC1$76UkYH#?`Z&%<&@*`lav4DKkUTMDH>1OuH?5*Y(rXsM36V=s#TqF!@*XsT zfdu}>P>57DD7b1}bM1_7Hr4G|sWY6&Q#`9OS;;UmbABqdOT)ar>07f`P zIlhherElK(a3o4QoFJ%$S#{8Hjr}V__?@wi>a*2ucl_D0&J-UEJEkhOZUk>|FB{@D$$cuGgn` z6o^HXiE-94}mE7*yga+UpAerf*Ww*$vf;(`|c>F9DmwY{s` zT>elS^%Ni1IW))yVXE5QYCg2$p_#9_2)@OmZ-G4Z(RJDQ3cg_dp9a8FtvByGN}x0z zAuBHt4O$JLOw8qrgO$u}WkQDla>`SJ={xdoZ{Yfs`u7$YQ;BGpfhq(hcm9~8lPxja)L;TC-RRa{NQ=J%)8 zYQr!!Y1c+(KjA1J@9yW0h5W2;>~`YpY6@?tKDV1aPBp8Ti2Q&u4K&`h=ak4wKv>c| zRw6>9msMVIg9seJwpokTQJqqkx&Z4&qGvK6TV^c4Cnd-|ViMg(TQ~dy!=v zj-tucWU;&y4(&&|-oipW;Bjk<++;Un+kSUY^;mGWwk7cWYA5Zyf9i2Cej~XE-;tfz z-O7(8B>H$xoHz%~d8Ly-2;)~-@0U#hqPqoLo=*mlGUl_05H8!47)~@}PhN`o7axR_ zbf0?thW&91h*X4=dE0;QlNx9E&3=7pGoJF7JS?3;&R;QU(+!=$xJ)f_|;-)Z?vkvOC-jR60|UE$4!&a(ER?~q4ML>A0bc_#zSX;newo^*NGz!W6H6$ z@}ec)#Cd64FZ#z1;F%q!@+=9G?7X+7rXpIGQ*-Hr!yn+-rin^~rRz8p_!XB)caC{Crz;F7*5+&Fmz?Y}7-X7v6wMYT>TW0hCVequ z+qse48!H0H8Op-2Q^Yi5W)A=N0C*cdm^Zi`IeG|JLv@; zGq0QZ(Jz*fFD@VN=gMmCCM#{V^tz{Hwbe$*%b`D(B*H8$83|{dgdvbfM&fIRT=l&q z=w(ro^T~YY-Y2D#x(ZdZt_hAL)64qY!L|~BMw^=rx*>2f-SrLh-m)>sm=U^VHV~veoV84~!59*Z-*O zyrY`P_b5IIgg|g3C|xjM=+dN04@h5>7Nm%R3ZjUVMCl1l1px(=A}B?CNKp}K;({PG zQj|rBsPwi-lTbqoyk9Kmy>oW|+2o%&nMqEP$xM=a@8^4WhU@hAoOr>`8ZkQXtge>+ zSIMGwdGDzd=&DNntX?I_HXe7Y{A1W`Un3^Ri))balrvJ^=h)%$`Hd>X_Hf;pnsa6G zO0R@T?IPvc=**5z_$u6?=2(K-bJw8|{Yx8*@m=8;NIMbL^~)Nj)Yu~W8>s@&1Oz7I zO%YAQHx?gGZko90<^+DIuGF?V`HHaIbo!lrlP770)-cRPWs?oPiX>*iuv#J~>W2F+ zdv>?c`NO^n(A?-;5PjiAwhN!m7~|%=?%7jY<7Io#+@#c9DGP+$d%v|E-P6i&^t-S= zP*qxEy4(@Gle*#=FT$_!s&?9vj@+bd&+UdaCa0JBWD?g zbN;)W^`lu0(RVEBRd_`tjww-RN#PV0PN}Dixy+`Fm&69fKu-T%kM_*~FS-G->ZG(f z;#v&y?oss``<5$Ne|qSrYI`$h-%@>u|7v;xVM&p({AE1ViFAF4 z7nLT-*lhI)4Hzt`ir(y%IhpKkdgBP&#hL~ddCc3)9mYBw{A`yR3tc6R<%){9F5nU= zJ4B_vOPn0LM=jNBZk~e{e1YCK8T@?tfVJwwK#PAh0A@k-te|$_YD0FFUpsJ z!NVhaJU*}Y)vi7t7}8-Bq|JCdi=C7(zny<^Co~whlzG}_rEk~$a`}e|d4LTG+$bJg zna@y`$T!EkozF@md6J0>8&9~qZa?b8y#AT;YYr(NCd%=OpwUyRG&d&;~!^RitSQ3aL!=VzH-D5eZns+uDxsv41gU1 z1FX%qWK*KAA=47i+ezu<`E;DJ3J>@w(Q&QjQAGk~s{v6U*MaDxNKyBd=`p%qIy~BJ<=RpZu&{na{YCEMvMk@d5H_V3%-I@~ztGn%dK-(bL0ynxD zjQ-=8;xeE$9J-v@OERw7fRH%e~P5cggFIC$##;Qqu4uPG=$bT;`BibAg#g;yBSvLnFB zLDl;c*Nx%zD{e;7)6nrCR@&MZ?ZRwE4r%=UZvb&7ss>MoVn^+-<0v9Md8M`r)zJ*=xKiQY>m?2iW>LW1EpZ>FhTYJIch(*AhR|r>Ve+<-x$l{hZzk zn46GDxe1I&+k+*T#AhK$SO&yR55K%lw&8hu&Yb5tFYIM~u^rD|Yatj0mjwsWZ%|9x zjVi!ZzH49`tIAKbQDN`NiQd1PC!c-rT>~ihHUWiuEy6uq7@sYmbiCdrB>NwS?%;r% zR)Shq5A^lO+6!o{u}ugQt3iX4M4t)u>$Nv{`R#obg3`s8=m4R@DUJJt$ZE<}$ME3J zS4kfn0pfrbdfUe3t0e!Idn^Qe|LgmSWk4C0l#~QB2N4djIu~bDP0lPP{r-9-J}9u2Kl%Bff;Rwoc@_)bWqxmX zq3rT0G1ul~^;1&Q0jfoHb z6qcCujlmtsqd@5dPOyLpfX@4>E-~+C4tUMHyga5q3?&7>QoO5l+R)MQE>oj0v#@Xm z{c&Is>s0Dy0Nh-#2yIk+&$)v~1YRGzeiR5h3uyQVlPD8i0Qi=alKSpZgM2&?F@aa~ zf6w6i_Khj&>69u8)+Y%3;g;WAijRu}RCCf=wSH8wF#=EvAlBt~7!>2Cj;bUkpeUZl zgJKPuz>5SN24Hq%`EoR^hqn=LAUF;Xq)cu>V06I=NfpeK71hyknc@LPtzXT+@tL9U z(uyYlE=xjNLW}#e074_8fJY2#+T!t`Sv3-jLC40}p+nS=L?SUdDrz<$v}JUrs{v?u zk`fXv&CPgGJ!|yzI|B$1cy7KuM37jR4U3(-2|&0^1#2(4tFEQeaTdO`i@;L(>^)KC z1!`9z30QHf8K99DDh04=zJoe)a&pqr>^BlSK`J2sgFq3OUCacBC4tiJqTjW2{4sBa zn0G7It_rLG=rNe9^aGCRn|qU&U}Yl-eLfQ9`YUuGEpp4s24d&rEO<0e5$LB)lAe zF5^*BLV|s{Pf*ZYvk<_x!tMob@c#iOzo3MlJL^}zs@pHrLMcv z>THJ$e}LS3n1u!#kpHy79r@Woe(9U+8f#}V7IcaBkZ*>DH(hgQ5F3v<9@nu z0X9_O6EQ=AiQ3FE`=82v(&TiiNmv<1B4u+jJ9b5`&-?%ZiE7$kXz@~ zkDAoYp^R-5C$tQI(5W^Gq(i)19UrVZM@#`%L#7_;k;y$1b8$YRVtPJT1-arPI*~h~ z`9{kcy&;L5O6B`W2>q)aXu$Q!M86*wd1(^Q^hAwp@YAo=oy!I?gODx|As`Fx*R-$e zI?0HoucJsj!f9JH6ywoDe}jcSFE_DD&*42{uzVbrkn$17F!v9;W^ylc$SE^vVz!~V zfX65tx;F!E7A6muM#>;bNzpzp?h&|tn!FBv!jzFJt>QY$xDga;VZ5y3dcb~0&K&|bY{6j> z>-)vVu;#a^UiMnTJqgKvlT!9)#pPA3srM5INrXT9G(k_33^G!0?pNaJU%Xun&yQ}# zHbfRg+a4So@f}FXOlmr44DE;MyVygy{On%6j!rCvrqDO82eP<_WU3zTMXF{*vB+ic zI~ARJJ6cOIiNFQofxS7=*3%V+nvNsj`_s?+VPTtl@!f+7Y3SUyX^#K|yNJ?ODH_~G zUGs*LMZL9^Mmw+G7io9Ih>38yV(ek5yskyOs`u`UfEb{z3YV%&t{3VnD1&(q1bXn0 z8X@T7=>p*=&BEiB9=OJlQ$%Gi6D0G)Oy|b|fo;NepRO+45$O(w!0%s(g=$&i6B8rS znhwfAiMydZX;AFz9!8THPj)yB%MFO8$)LPIxF#~lsd!73X(zCDx4MqSEPv68;ymW-a5usj;2Qd<_FFXeC4ZP0isJZ zda~<96vJuY4(com66Rg3uNAEoDzgnov37X-2+ua=QH$5QPbl3(O!`}3>Bnhj8}pYW Ui3|W>9SB^^jgJ|X7`jFM7gNa&UH||9 literal 0 HcmV?d00001 diff --git a/docs/conf_common.py b/docs/conf_common.py index 62ee1a348c17..d6e684fb8beb 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -73,6 +73,8 @@ COEXISTENCE_DOCS = ['api-guides/coexist.rst'] +MM_SYNC_DOCS = ['api-reference/system/mm_sync.rst'] + SDMMC_DOCS = ['api-reference/peripherals/sdmmc_host.rst'] SDIO_SLAVE_DOCS = ['api-reference/peripherals/sdio_slave.rst', @@ -186,6 +188,8 @@ 'SOC_WIFI_SUPPORTED':WIFI_DOCS, 'SOC_BT_CLASSIC_SUPPORTED':CLASSIC_BT_DOCS, 'SOC_SUPPORT_COEXISTENCE':COEXISTENCE_DOCS, + 'SOC_PSRAM_DMA_CAPABLE':MM_SYNC_DOCS, + 'SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE':MM_SYNC_DOCS, 'SOC_SDMMC_HOST_SUPPORTED':SDMMC_DOCS, 'SOC_SDIO_SLAVE_SUPPORTED':SDIO_SLAVE_DOCS, 'SOC_MCPWM_SUPPORTED':MCPWM_DOCS, diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 60441c822fdf..8d464a9e4c06 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -157,6 +157,7 @@ INPUT = \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_cpu.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_etm.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/esp_dma_utils.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_ds.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_hmac.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \ diff --git a/docs/en/api-reference/system/index.rst b/docs/en/api-reference/system/index.rst index 24e2bf0ad208..3f284fcf092f 100644 --- a/docs/en/api-reference/system/index.rst +++ b/docs/en/api-reference/system/index.rst @@ -21,6 +21,7 @@ System API freertos_additions mem_alloc mm + :SOC_PSRAM_DMA_CAPABLE or SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE: mm_sync heap_debug esp_timer internal-unstable diff --git a/docs/en/api-reference/system/mm.rst b/docs/en/api-reference/system/mm.rst index 3926c9a2b312..6af737ad30ef 100644 --- a/docs/en/api-reference/system/mm.rst +++ b/docs/en/api-reference/system/mm.rst @@ -153,10 +153,7 @@ SPI Flash can be accessed by SPI1 (ESP-IDF ``esp_flash`` driver APIs), or by poi PSRAM can also be accessed by EDMA. Data desynchronisation may happen because hardware does not guarantee the data consistency under such condition. You should call :cpp:func:`esp_cache_msync` to synchronise the Cache and the PSRAM. - :cpp:func:`esp_cache_msync` has two synchronization directions, - - * :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M`: from cache to memory. By default (if you do not specify a direction), the synchronization is in this direction. Content in the address you specified is written back to the memory. - * :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_M2C`: from memory to cache. By default, content in the address you specified is invalidated from the cache. + See :doc:`Memory Synchronization ` for more details. Thread Safety @@ -174,9 +171,3 @@ API Reference - ESP MMAP Driver ------------------------------- .. include-build-file:: inc/esp_mmu_map.inc - - -API Reference - ESP MSYNC Driver --------------------------------- - -.. include-build-file:: inc/esp_cache.inc diff --git a/docs/en/api-reference/system/mm_sync.rst b/docs/en/api-reference/system/mm_sync.rst new file mode 100644 index 000000000000..6aa0ec3819ad --- /dev/null +++ b/docs/en/api-reference/system/mm_sync.rst @@ -0,0 +1,146 @@ +Memory Synchronization +********************** + +.. toctree:: + :maxdepth: 1 + + +Introduction +============ + +.. only:: SOC_PSRAM_DMA_CAPABLE + + {IDF_TARGET_NAME} can access its connected PSRAM via these ways: + + - CPU + - DMA + +.. only:: SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + + {IDF_TARGET_NAME} can access its internal memory via these ways: + + - CPU + - DMA + +By default, CPU accesses the above mentioned memory via cache. Whereas DMA accesses the memory directly, without going through cache. + +This leads to potential cache data coherence issue: + +- When a DMA transaction changes the content of a piece of memory, and the content has been cached already. Under this condition: + + - CPU may read stale data. + - the stale data in the cache may be written back to the memory. The new data updated by the previous DMA transaction will be overwritten. + +- CPU changes the content of an address. The content is in the cache, but not in the memory yet (cache will write back the content to the memory according to its own strategy). Under this condition: + + - The next DMA transactions to read this content from the memory will get stale data. + +There are three common methods to address such cache data coherence issue: + +.. list:: + + 1. Hardware based cache Coherent Interconnect, {IDF_TARGET_NAME} does not have such ability. + 2. Use the DMA buffer from non-cacheable memory. Memory that CPU access it without going through cache is called non-cacheable memory. + 3. Explicitly call a memory synchronization API to writeback the content in the cache back to the memory, or invalidate the content in the cache. + + +Memory Synchronisation Driver +============================= + +The suggested way to deal with such cache data coherence issue is by using the memory synchronization API :cpp:func:`esp_cache_msync` provided by ESP-IDF `esp_mm` component. + + +Driver Concept +-------------- + +Direction of the cache memory synchronization: + +- :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M`, for synchronization from cache to memory. +- :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_M2C`, for synchronization from memory to cache. + +Type of the cache memory synchronization: + +- :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_DATA`, for synchronization to a data address region. +- :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_INST`, for synchronization to an instruction address region. + + +Driver Behaviour +---------------- + +Calling :cpp:func:`esp_cache_msync` will do a synchronization between cache and memory. The first parameter `addr` and the second parameter `size` together describe the memory region that is to be synchronized. About the third parameter `flags`: + +.. list:: + + - :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M`. With this flag, content in the specified address region is written back to the memory. This direction is usually used **after** the content of an address is updated by the CPU, e.g. a memset to the address. Operation in this direction should happen **before** a DMA operation to the same address. + - :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_M2C`. With this flag, content in the specified address region is invalidated from the cache. This direction is usually used **after** the content of an address is updated by the DMA. Operation in this direction should happen **before** a CPU read operation to the same address. + +The above two flags help select the synchronization direction. Specially, if neither of these two flags are used, :cpp:func:`esp_cache_msync` will by default select the :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M` direction. Users are not allowed to set both of the two flags at the same time. + +.. list:: + + - :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_DATA`. + - :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_INST`. + +The above two flags help select the type of the synchronization address. Specially, if neither of these two flags are used, :cpp:func:`esp_cache_msync` will by default select the :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_DATA` direction. Users are not allowed to set both of the two flags at the same time. + + +.. list:: + + - :c:macro:`ESP_CACHE_MSYNC_FLAG_INVALIDATE`. This flag is used to trigger a cache invalidation to the specified address region, after the region is written back to the memory. This flag is mainly used for :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M` direction. For :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_M2C` direction, behaviour is the same as if the :c:macro:`ESP_CACHE_MSYNC_FLAG_INVALIDATE` flag is not set. + - :c:macro:`ESP_CACHE_MSYNC_FLAG_UNALIGNED`. This flag force the :cpp:func:`esp_cache_msync` API to do synchronization without checking the address and size alignment. For more details, see chapter `Address Alignment Requirement` following. + + +Address Alignment Requirement +============================= + +There is address and size alignment requirement (in bytes) for using :cpp:func:`esp_cache_msync`. The alignment requirement comes from cache. + +- An address region whose start address and size both meet the cache memory synchronization alignment requirement is defined as an **aligned address region**. +- An address region whose start address or size does not meet the cache memory synchronization alignment requirement is defined as an **unaligned address region**. + +By default, if you specify an unaligned address region, :cpp:func:`esp_cache_msync` will return an :c:macro:`ESP_ERR_INVALID_ARG` error, together with the required alignment. + + +Memory Allocation Helper +------------------------ + +cache memory synchronization is usually considered when DMA is involved. ESP-IDF provides an API to do memory allocation that can meet the alignment requirement from both the cache and the DMA. + +- :cpp:func:`esp_dma_malloc`, this API allocates a chunk of memory that meets the alignment requirement from both the cache and the DMA. +- :cpp:func:`esp_dma_calloc`, this API allocates a chunk of memory that meets the alignment requirement from both the cache and the DMA. The initialized value in the memory is set to zero. + +You can also use :c:macro:`ESP_DMA_MALLOC_FLAG_PSRAM` to allocate from the PSRAM. + + +Warning for Address Alignment Requirement +----------------------------------------- + +You can set the :c:macro:`ESP_CACHE_MSYNC_FLAG_UNALIGNED` flag to bypass such check. Note you should be very careful about using this flag. cache memory synchronization to an unaligned address region may silently corrupt the memory. + +For example, assume: + +- alignment requirement is 0x40 bytes. +- a call to :cpp:func:`esp_cache_msync`, with `ESP_CACHE_MSYNC_FLAG_DIR_M2C | ESP_CACHE_MSYNC_FLAG_UNALIGNED` flags, the specified address region is 0x4000_0020 ~ 0x4000_0060 (see **data C** in below graph). + +Above settings will trigger a cache invalidation to the address region 0x4000_0000 ~ 0x4000_0080, see **sync item0** and **sync item1** in the below graph. + +If the content in 0x4000_0000 ~ 0x4000_0020 (**data A** in the below graph) or 0x4000_0060 ~ 0x4000_0080 (**data B** in the below graph) are not written back to the memory yet, then these **data A** and **data B** will be discarded. + +.. image:: /../_static/diagrams/mmu/cache_align_issue.png + :scale: 80 % + :align: center + + +API Reference +============= + +API Reference - ESP Msync Driver +-------------------------------- + +.. include-build-file:: inc/esp_cache.inc + + +API Reference - ESP DMA Utils +----------------------------- + +.. include-build-file:: inc/esp_dma_utils.inc diff --git a/docs/zh_CN/api-reference/system/index.rst b/docs/zh_CN/api-reference/system/index.rst index 6d0216bf22a1..e617a7a9c793 100644 --- a/docs/zh_CN/api-reference/system/index.rst +++ b/docs/zh_CN/api-reference/system/index.rst @@ -21,6 +21,7 @@ System API freertos_additions mem_alloc mm + :SOC_PSRAM_DMA_CAPABLE or SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE: mm_sync heap_debug esp_timer internal-unstable diff --git a/docs/zh_CN/api-reference/system/mm_sync.rst b/docs/zh_CN/api-reference/system/mm_sync.rst new file mode 100644 index 000000000000..9527c4df231f --- /dev/null +++ b/docs/zh_CN/api-reference/system/mm_sync.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/system/mm_sync.rst From f465bc131ab3d3f1df26697394ffab7438235e8e Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 25 Sep 2023 14:00:03 +0800 Subject: [PATCH 110/142] change(mspi): remove s3 120mhz sdr warning --- components/esp_hw_support/mspi_timing_by_mspi_delay.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/esp_hw_support/mspi_timing_by_mspi_delay.c b/components/esp_hw_support/mspi_timing_by_mspi_delay.c index efa5dbbd1ba9..8f6a98aa9954 100644 --- a/components/esp_hw_support/mspi_timing_by_mspi_delay.c +++ b/components/esp_hw_support/mspi_timing_by_mspi_delay.c @@ -469,8 +469,6 @@ static uint32_t s_select_best_tuning_config_dtr(const mspi_timing_config_t *conf static uint32_t s_select_best_tuning_config_str(const mspi_timing_config_t *configs, uint32_t consecutive_length, uint32_t end) { #if (MSPI_TIMING_CORE_CLOCK_MHZ == 120 || MSPI_TIMING_CORE_CLOCK_MHZ == 240) - ESP_EARLY_LOGW("FLASH/PSRAM", "DO NOT USE FOR MASS PRODUCTION! Timing parameters may be updated in future IDF version."); - //STR best point scheme uint32_t best_point; From d57c4cde44397c24f1d5f4d4d318828be8dbc3f3 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Wed, 27 Sep 2023 11:27:55 +0800 Subject: [PATCH 111/142] ci(adc): increase adc performance test threshold on c6 --- .../include/esp32c6/idf_performance_target.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/idf_test/include/esp32c6/idf_performance_target.h b/components/idf_test/include/esp32c6/idf_performance_target.h index 08c145126bfb..ee92a631f715 100644 --- a/components/idf_test/include/esp32c6/idf_performance_target.h +++ b/components/idf_test/include/esp32c6/idf_performance_target.h @@ -23,10 +23,10 @@ #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 32 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 -#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 7 -#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 7 -#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_4 7 -#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_8 7 -#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 7 -#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 7 -#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 7 +#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 10 +#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 10 +#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_4 10 +#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_8 10 +#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 10 +#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 10 +#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 10 From 817036f46f490c2ecea1bf1f8ef716a751d539a4 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Wed, 20 Sep 2023 11:05:02 +0800 Subject: [PATCH 112/142] fix(adc): power settings not taking into effect on C6 --- .../include/esp_private/esp_modem_clock.h | 7 +++++ components/esp_hw_support/modem_clock.c | 27 +++++++++++++++++++ .../port/esp32c6/sar_periph_ctrl.c | 3 +++ components/hal/esp32c6/modem_clock_hal.c | 8 ++++-- components/hal/esp32h2/modem_clock_hal.c | 6 ++++- components/hal/include/hal/modem_clock_hal.h | 1 + 6 files changed, 49 insertions(+), 3 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_modem_clock.h b/components/esp_hw_support/include/esp_private/esp_modem_clock.h index bd822ebfbd6c..1aae8638e84e 100644 --- a/components/esp_hw_support/include/esp_private/esp_modem_clock.h +++ b/components/esp_hw_support/include/esp_private/esp_modem_clock.h @@ -124,6 +124,13 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module); */ void modem_clock_wifi_mac_reset(void); +/** + * @brief Enable clock registers which shared by both modem and ADC. Need a ref count to enable/disable them + * + * @param enable true: enable; false: disable + */ +void modem_clock_shared_enable(bool enable); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 3ad811bdd6e4..16d08189b1e0 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -53,6 +53,9 @@ typedef struct modem_clock_context { modem_clock_lpclk_src_t lpclk_src[PERIPH_MODEM_MODULE_NUM]; } modem_clock_context_t; +extern portMUX_TYPE rtc_spinlock; + +static int modem_clock_apb_80m_cnt; #if SOC_WIFI_SUPPORTED static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable) @@ -102,7 +105,31 @@ static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, boo static void IRAM_ATTR modem_clock_fe_configure(modem_clock_context_t *ctx, bool enable) { modem_clock_hal_enable_fe_clock(ctx->hal, enable); + modem_clock_shared_enable(enable); +} + +#if SOC_MODEM_CLOCK_IS_INDEPENDENT +void modem_clock_shared_enable(bool enable) +{ + if(enable) { + portENTER_CRITICAL_SAFE(&rtc_spinlock); + modem_clock_apb_80m_cnt++; + if (modem_clock_apb_80m_cnt == 1) { + modem_clock_hal_enable_shared_clock(true); + } + portEXIT_CRITICAL_SAFE(&rtc_spinlock); + } else { + portENTER_CRITICAL_SAFE(&rtc_spinlock); + modem_clock_apb_80m_cnt--; + if (modem_clock_apb_80m_cnt == 0) { + modem_clock_hal_enable_shared_clock(false); + } else if (modem_clock_apb_80m_cnt < 0) { + abort(); + } + portEXIT_CRITICAL_SAFE(&rtc_spinlock); + } } +#endif // SOC_MODEM_CLOCK_IS_INDEPENDENT static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) { diff --git a/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c b/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c index c0b853124afd..e4b4328d0e21 100644 --- a/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c +++ b/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c @@ -18,6 +18,7 @@ #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "esp_private/sar_periph_ctrl.h" +#include "esp_private/esp_modem_clock.h" #include "hal/sar_ctrl_ll.h" static const char *TAG = "sar_periph_ctrl"; @@ -55,6 +56,7 @@ static int s_pwdet_power_on_cnt; static void s_sar_power_acquire(void) { + modem_clock_shared_enable(true); portENTER_CRITICAL_SAFE(&rtc_spinlock); s_pwdet_power_on_cnt++; if (s_pwdet_power_on_cnt == 1) { @@ -75,6 +77,7 @@ static void s_sar_power_release(void) sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_FSM); } portEXIT_CRITICAL_SAFE(&rtc_spinlock); + modem_clock_shared_enable(false); } diff --git a/components/hal/esp32c6/modem_clock_hal.c b/components/hal/esp32c6/modem_clock_hal.c index e89e19c7fe53..9290362f6a7d 100644 --- a/components/hal/esp32c6/modem_clock_hal.c +++ b/components/hal/esp32c6/modem_clock_hal.c @@ -104,13 +104,17 @@ uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t * void IRAM_ATTR modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { - modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_cal_160m_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_160m_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_80m_clock(hal->syscon_dev, enable); } } +void IRAM_ATTR modem_clock_hal_enable_shared_clock(bool enable) +{ + modem_syscon_ll_enable_fe_apb_clock(&MODEM_SYSCON, enable); + modem_syscon_ll_enable_fe_80m_clock(&MODEM_SYSCON, enable); +} + void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider) { modem_lpcon_ll_set_ble_rtc_timer_divisor_value(hal->lpcon_dev, divider); diff --git a/components/hal/esp32h2/modem_clock_hal.c b/components/hal/esp32h2/modem_clock_hal.c index 8534cd4a860d..3dc090650468 100644 --- a/components/hal/esp32h2/modem_clock_hal.c +++ b/components/hal/esp32h2/modem_clock_hal.c @@ -24,11 +24,15 @@ void IRAM_ATTR modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, b modem_lpcon_ll_enable_fe_mem_clock(hal->lpcon_dev, enable); modem_syscon_ll_enable_fe_sdm_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_adc_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_32m_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_16m_clock(hal->syscon_dev, enable); } +void IRAM_ATTR modem_clock_hal_enable_shared_clock(bool enable) +{ + modem_syscon_ll_enable_fe_apb_clock(&MODEM_SYSCON, enable); +} + void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider) { lp_clkrst_ll_set_ble_rtc_timer_divisor_value(&LP_CLKRST, divider); diff --git a/components/hal/include/hal/modem_clock_hal.h b/components/hal/include/hal/modem_clock_hal.h index 04ba96575b43..d00031d884bf 100644 --- a/components/hal/include/hal/modem_clock_hal.h +++ b/components/hal/include/hal/modem_clock_hal.h @@ -29,6 +29,7 @@ uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t * #endif void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable); +void modem_clock_hal_enable_shared_clock(bool enable); #if SOC_BT_SUPPORTED void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider); From c8083b07bf1a53dad4fec01144b01c59d64ba399 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 25 Sep 2023 11:29:15 +0800 Subject: [PATCH 113/142] feat(modem_clock): separate management of modem_adc_common_fe clock and modem_private_fe --- components/esp_hw_support/modem_clock.c | 92 ++++++++----------- .../port/esp32c6/sar_periph_ctrl.c | 4 +- components/hal/esp32c6/modem_clock_hal.c | 18 ++-- components/hal/esp32h2/modem_clock_hal.c | 12 +-- components/hal/include/hal/modem_clock_hal.h | 4 +- .../hal/include/hal/modem_clock_types.h | 4 +- .../soc/esp32c6/include/soc/periph_defs.h | 3 +- .../soc/esp32h2/include/soc/periph_defs.h | 3 +- 8 files changed, 63 insertions(+), 77 deletions(-) diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 16d08189b1e0..f48a281bc94e 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -21,7 +21,8 @@ // Please define the frequently called modules in the low bit, // which will improve the execution efficiency typedef enum { - MODEM_CLOCK_FE, + MODEM_CLOCK_MODEM_ADC_COMMON_FE, + MODEM_CLOCK_MODEM_PRIVATE_FE, MODEM_CLOCK_COEXIST, MODEM_CLOCK_I2C_MASTER, #if SOC_WIFI_SUPPORTED @@ -53,9 +54,6 @@ typedef struct modem_clock_context { modem_clock_lpclk_src_t lpclk_src[PERIPH_MODEM_MODULE_NUM]; } modem_clock_context_t; -extern portMUX_TYPE rtc_spinlock; - -static int modem_clock_apb_80m_cnt; #if SOC_WIFI_SUPPORTED static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable) @@ -102,34 +100,15 @@ static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, boo modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); } -static void IRAM_ATTR modem_clock_fe_configure(modem_clock_context_t *ctx, bool enable) +static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) { - modem_clock_hal_enable_fe_clock(ctx->hal, enable); - modem_clock_shared_enable(enable); + modem_clock_hal_enable_modem_adc_common_fe_clock(ctx->hal, enable); } -#if SOC_MODEM_CLOCK_IS_INDEPENDENT -void modem_clock_shared_enable(bool enable) +static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) { - if(enable) { - portENTER_CRITICAL_SAFE(&rtc_spinlock); - modem_clock_apb_80m_cnt++; - if (modem_clock_apb_80m_cnt == 1) { - modem_clock_hal_enable_shared_clock(true); - } - portEXIT_CRITICAL_SAFE(&rtc_spinlock); - } else { - portENTER_CRITICAL_SAFE(&rtc_spinlock); - modem_clock_apb_80m_cnt--; - if (modem_clock_apb_80m_cnt == 0) { - modem_clock_hal_enable_shared_clock(false); - } else if (modem_clock_apb_80m_cnt < 0) { - abort(); - } - portEXIT_CRITICAL_SAFE(&rtc_spinlock); - } + modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); } -#endif // SOC_MODEM_CLOCK_IS_INDEPENDENT static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) { @@ -154,22 +133,23 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi static DRAM_ATTR modem_clock_context_t modem_clock_context = { .hal = &modem_clock_hal, .lock = portMUX_INITIALIZER_UNLOCKED, .dev = { - [MODEM_CLOCK_FE] = { .refs = 0, .configure = modem_clock_fe_configure }, - [MODEM_CLOCK_COEXIST] = { .refs = 0, .configure = modem_clock_coex_configure }, - [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .configure = modem_clock_i2c_master_configure }, + [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .configure = modem_clock_modem_adc_common_fe_configure }, + [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .configure = modem_clock_modem_private_fe_configure }, + [MODEM_CLOCK_COEXIST] = { .refs = 0, .configure = modem_clock_coex_configure }, + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .configure = modem_clock_i2c_master_configure }, #if SOC_WIFI_SUPPORTED - [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .configure = modem_clock_wifi_mac_configure }, - [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .configure = modem_clock_wifi_bb_configure }, + [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .configure = modem_clock_wifi_mac_configure }, + [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .configure = modem_clock_wifi_bb_configure }, #endif - [MODEM_CLOCK_ETM] = { .refs = 0, .configure = modem_clock_etm_configure }, + [MODEM_CLOCK_ETM] = { .refs = 0, .configure = modem_clock_etm_configure }, #if SOC_BT_SUPPORTED - [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .configure = modem_clock_ble_mac_configure }, - [MODEM_CLOCK_BLE_BB] = { .refs = 0, .configure = modem_clock_ble_bb_configure }, + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .configure = modem_clock_ble_mac_configure }, + [MODEM_CLOCK_BLE_BB] = { .refs = 0, .configure = modem_clock_ble_bb_configure }, #endif #if SOC_IEEE802154_SUPPORTED - [MODEM_CLOCK_802154_MAC] = { .refs = 0, .configure = modem_clock_ieee802154_mac_configure }, + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .configure = modem_clock_ieee802154_mac_configure }, #endif - [MODEM_CLOCK_DATADUMP] = { .refs = 0, .configure = modem_clock_data_dump_configure } + [MODEM_CLOCK_DATADUMP] = { .refs = 0, .configure = modem_clock_data_dump_configure } }, .lpclk_src = { [0 ... PERIPH_MODEM_MODULE_NUM - 1] = MODEM_CLOCK_LPCLK_SRC_INVALID } }; @@ -186,16 +166,16 @@ static void IRAM_ATTR modem_clock_domain_power_state_icg_map_init(modem_clock_co /* the ICG code's bit 0, 1 and 2 indicates the ICG state * of pmu SLEEP, MODEM and ACTIVE mode respectively */ const uint32_t code[MODEM_CLOCK_DOMAIN_MAX] = { - [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, - [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_PRIVATE_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, }; for (modem_clock_domain_t domain = MODEM_CLOCK_DOMAIN_MODEM_APB; domain < MODEM_CLOCK_DOMAIN_MAX; domain++) { modem_clock_hal_set_clock_domain_icg_bitmap(ctx->hal, domain, code[domain]); @@ -306,30 +286,32 @@ void IRAM_ATTR modem_clock_module_mac_reset(periph_module_t module) #define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BLE_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) #define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BLE_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) #define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) -#define PHY_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER) | BIT(MODEM_CLOCK_FE)) +#define PHY_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER) | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) #define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) #define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) +#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) static IRAM_ATTR uint32_t modem_clock_get_module_deps(periph_module_t module) { uint32_t deps = 0; switch (module) { - case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; - case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; + case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; #if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED - case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; + case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; #endif #if SOC_WIFI_SUPPORTED - case PERIPH_WIFI_MODULE: deps = WIFI_CLOCK_DEPS; break; + case PERIPH_WIFI_MODULE: deps = WIFI_CLOCK_DEPS; break; #endif #if SOC_BT_SUPPORTED - case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; #endif #if SOC_IEEE802154_SUPPORTED - case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; + case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; #endif #if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED - case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; + case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; #endif default: assert(0); diff --git a/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c b/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c index e4b4328d0e21..c541f2b57016 100644 --- a/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c +++ b/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c @@ -56,7 +56,7 @@ static int s_pwdet_power_on_cnt; static void s_sar_power_acquire(void) { - modem_clock_shared_enable(true); + modem_clock_module_enable(PERIPH_MODEM_ADC_COMMON_FE_MODULE); portENTER_CRITICAL_SAFE(&rtc_spinlock); s_pwdet_power_on_cnt++; if (s_pwdet_power_on_cnt == 1) { @@ -77,7 +77,7 @@ static void s_sar_power_release(void) sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_FSM); } portEXIT_CRITICAL_SAFE(&rtc_spinlock); - modem_clock_shared_enable(false); + modem_clock_module_disable(PERIPH_MODEM_ADC_COMMON_FE_MODULE); } diff --git a/components/hal/esp32c6/modem_clock_hal.c b/components/hal/esp32c6/modem_clock_hal.c index 9290362f6a7d..6707c9b01236 100644 --- a/components/hal/esp32c6/modem_clock_hal.c +++ b/components/hal/esp32c6/modem_clock_hal.c @@ -36,7 +36,7 @@ void IRAM_ATTR modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_conte case MODEM_CLOCK_DOMAIN_BT: modem_syscon_ll_set_bt_icg_bitmap(hal->syscon_dev, bitmap); break; - case MODEM_CLOCK_DOMAIN_FE: + case MODEM_CLOCK_DOMAIN_MODEM_PRIVATE_FE: modem_syscon_ll_set_fe_icg_bitmap(hal->syscon_dev, bitmap); break; case MODEM_CLOCK_DOMAIN_IEEE802154: @@ -77,7 +77,7 @@ uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t * case MODEM_CLOCK_DOMAIN_BT: bitmap = modem_syscon_ll_get_bt_icg_bitmap(hal->syscon_dev); break; - case MODEM_CLOCK_DOMAIN_FE: + case MODEM_CLOCK_DOMAIN_MODEM_PRIVATE_FE: bitmap = modem_syscon_ll_get_fe_icg_bitmap(hal->syscon_dev); break; case MODEM_CLOCK_DOMAIN_IEEE802154: @@ -101,18 +101,20 @@ uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t * return bitmap; } -void IRAM_ATTR modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable) +void IRAM_ATTR modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { - modem_syscon_ll_enable_fe_cal_160m_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_160m_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_80m_clock(hal->syscon_dev, enable); } } -void IRAM_ATTR modem_clock_hal_enable_shared_clock(bool enable) +void IRAM_ATTR modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_context_t *hal, bool enable) { - modem_syscon_ll_enable_fe_apb_clock(&MODEM_SYSCON, enable); - modem_syscon_ll_enable_fe_80m_clock(&MODEM_SYSCON, enable); + if (enable) { + modem_syscon_ll_enable_fe_cal_160m_clock(hal->syscon_dev, enable); + modem_syscon_ll_enable_fe_160m_clock(hal->syscon_dev, enable); + } } void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider) diff --git a/components/hal/esp32h2/modem_clock_hal.c b/components/hal/esp32h2/modem_clock_hal.c index 3dc090650468..b120b52a369c 100644 --- a/components/hal/esp32h2/modem_clock_hal.c +++ b/components/hal/esp32h2/modem_clock_hal.c @@ -19,7 +19,12 @@ typedef enum { MODEM_CLOCK_EXT32K_CODE = 2 } modem_clock_32k_clk_src_code_t; -void IRAM_ATTR modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable) +void IRAM_ATTR modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable) +{ + modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); +} + +void IRAM_ATTR modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_context_t *hal, bool enable) { modem_lpcon_ll_enable_fe_mem_clock(hal->lpcon_dev, enable); modem_syscon_ll_enable_fe_sdm_clock(hal->syscon_dev, enable); @@ -28,11 +33,6 @@ void IRAM_ATTR modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, b modem_syscon_ll_enable_fe_16m_clock(hal->syscon_dev, enable); } -void IRAM_ATTR modem_clock_hal_enable_shared_clock(bool enable) -{ - modem_syscon_ll_enable_fe_apb_clock(&MODEM_SYSCON, enable); -} - void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider) { lp_clkrst_ll_set_ble_rtc_timer_divisor_value(&LP_CLKRST, divider); diff --git a/components/hal/include/hal/modem_clock_hal.h b/components/hal/include/hal/modem_clock_hal.h index d00031d884bf..27b95cafdd37 100644 --- a/components/hal/include/hal/modem_clock_hal.h +++ b/components/hal/include/hal/modem_clock_hal.h @@ -28,8 +28,8 @@ void modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain); #endif -void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable); -void modem_clock_hal_enable_shared_clock(bool enable); +void modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable); +void modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_context_t *hal, bool enable); #if SOC_BT_SUPPORTED void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider); diff --git a/components/hal/include/hal/modem_clock_types.h b/components/hal/include/hal/modem_clock_types.h index ed435be22621..e430a0610ff5 100644 --- a/components/hal/include/hal/modem_clock_types.h +++ b/components/hal/include/hal/modem_clock_types.h @@ -15,13 +15,13 @@ typedef enum { MODEM_CLOCK_DOMAIN_MODEM_PERIPH, MODEM_CLOCK_DOMAIN_WIFI, MODEM_CLOCK_DOMAIN_BT, - MODEM_CLOCK_DOMAIN_FE, + MODEM_CLOCK_DOMAIN_MODEM_ADC_COMMON_FE, + MODEM_CLOCK_DOMAIN_MODEM_PRIVATE_FE, MODEM_CLOCK_DOMAIN_IEEE802154, MODEM_CLOCK_DOMAIN_LP_APB, MODEM_CLOCK_DOMAIN_I2C_MASTER, MODEM_CLOCK_DOMAIN_COEX, MODEM_CLOCK_DOMAIN_WIFIPWR, - MODEM_CLOCK_DOMAIN_MAX } modem_clock_domain_t; diff --git a/components/soc/esp32c6/include/soc/periph_defs.h b/components/soc/esp32c6/include/soc/periph_defs.h index 06c180f45855..40f2aaa8fa4a 100644 --- a/components/soc/esp32c6/include/soc/periph_defs.h +++ b/components/soc/esp32c6/include/soc/periph_defs.h @@ -57,12 +57,13 @@ typedef enum { PERIPH_PHY_MODULE, PERIPH_ANA_I2C_MASTER_MODULE, PERIPH_MODEM_ETM_MODULE, + PERIPH_MODEM_ADC_COMMON_FE_MODULE, PERIPH_MODULE_MAX /* !!! Don't append soc modules here !!! */ } periph_module_t; #define PERIPH_MODEM_MODULE_MIN PERIPH_WIFI_MODULE -#define PERIPH_MODEM_MODULE_MAX PERIPH_MODEM_ETM_MODULE +#define PERIPH_MODEM_MODULE_MAX PERIPH_MODEM_ADC_COMMON_FE_MODULE #define PERIPH_MODEM_MODULE_NUM (PERIPH_MODEM_MODULE_MAX - PERIPH_MODEM_MODULE_MIN + 1) #define IS_MODEM_MODULE(periph) ((periph>=PERIPH_MODEM_MODULE_MIN) && (periph<=PERIPH_MODEM_MODULE_MAX)) diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index 0d48b639a824..8f53ce666f7e 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -52,12 +52,13 @@ typedef enum { PERIPH_PHY_MODULE, PERIPH_ANA_I2C_MASTER_MODULE, PERIPH_MODEM_ETM_MODULE, + PERIPH_MODEM_ADC_COMMON_FE_MODULE, PERIPH_MODULE_MAX /* !!! Don't append soc modules here !!! */ } periph_module_t; #define PERIPH_MODEM_MODULE_MIN PERIPH_BT_MODULE -#define PERIPH_MODEM_MODULE_MAX PERIPH_MODEM_ETM_MODULE +#define PERIPH_MODEM_MODULE_MAX PERIPH_MODEM_ADC_COMMON_FE_MODULE #define PERIPH_MODEM_MODULE_NUM (PERIPH_MODEM_MODULE_MAX - PERIPH_MODEM_MODULE_MIN + 1) #define IS_MODEM_MODULE(periph) ((periph>=PERIPH_MODEM_MODULE_MIN) && (periph<=PERIPH_MODEM_MODULE_MAX)) From 8e9a151dbc20e49aedc237983c236e890ced6caa Mon Sep 17 00:00:00 2001 From: gaoxu Date: Wed, 27 Sep 2023 10:00:52 +0800 Subject: [PATCH 114/142] ci(adc): add a test about adc1 work with wifi on c6 --- .../esp_adc/test_apps/adc/main/CMakeLists.txt | 2 +- .../{test_adc2_wifi.c => test_adc_wifi.c} | 140 ++++++++++-------- 2 files changed, 83 insertions(+), 59 deletions(-) rename components/esp_adc/test_apps/adc/main/{test_adc2_wifi.c => test_adc_wifi.c} (55%) diff --git a/components/esp_adc/test_apps/adc/main/CMakeLists.txt b/components/esp_adc/test_apps/adc/main/CMakeLists.txt index b6cac22db4c2..437361620dc0 100644 --- a/components/esp_adc/test_apps/adc/main/CMakeLists.txt +++ b/components/esp_adc/test_apps/adc/main/CMakeLists.txt @@ -3,7 +3,7 @@ set(srcs "test_app_main.c" "test_adc_performance.c" "test_adc_driver.c" "test_adc_driver_iram.c" - "test_adc2_wifi.c" + "test_adc_wifi.c" "test_common_adc.c") # In order for the cases defined by `TEST_CASE` to be linked into the final elf, diff --git a/components/esp_adc/test_apps/adc/main/test_adc2_wifi.c b/components/esp_adc/test_apps/adc/main/test_adc_wifi.c similarity index 55% rename from components/esp_adc/test_apps/adc/main/test_adc2_wifi.c rename to components/esp_adc/test_apps/adc/main/test_adc_wifi.c index eb3f7278c853..d0ef8d3f0f77 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc2_wifi.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_wifi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,32 +18,32 @@ #include "test_common_adc.h" #include "test_utils.h" -/** - * On ESP32C3, ADC2 is no longer supported, due to its HW limitation. - */ -#if (SOC_ADC_PERIPH_NUM > 1) && !CONFIG_IDF_TARGET_ESP32C3 +#if SOC_WIFI_SUPPORTED && SOC_ADC_SUPPORTED -static const char* TAG = "test_adc2"; +static const char* TAG = "test_adc_wifi"; #define DEFAULT_SSID "TEST_SSID" #define DEFAULT_PWD "TEST_PASS" +//ADC Channels #if CONFIG_IDF_TARGET_ESP32 -#define TEST_ADC2_CHAN0 ADC_CHANNEL_9 -#elif CONFIG_IDF_TARGET_ESP32S2 -#define TEST_ADC2_CHAN0 ADC_CHANNEL_0 -#elif CONFIG_IDF_TARGET_ESP32C3 -#define TEST_ADC2_CHAN0 ADC_CHANNEL_0 -#elif CONFIG_IDF_TARGET_ESP32S3 -#define TEST_ADC2_CHAN0 ADC_CHANNEL_0 +#define ADC1_WIFI_TEST_CHAN0 ADC_CHANNEL_4 +#define ADC2_WIFI_TEST_CHAN0 ADC_CHANNEL_9 +#else +#define ADC1_WIFI_TEST_CHAN0 ADC_CHANNEL_0 +#define ADC2_WIFI_TEST_CHAN0 ADC_CHANNEL_0 #endif -#define ADC_ERROR_THRES 100 +#define ADC_ERROR_THRES 200 #define TEST_NUM 8 #define MINUS_UNTIL_ZERO(a, b) ( ((a) > (b)) ? ((a)-(b)): 0) #define TIME_REMAIN(start, now, timeout) ((now) >= (start) ? MINUS_UNTIL_ZERO((timeout), (now)-(start)) : -1) +static int read_raw; +static int target_value; +static int test_adc_io; +static bool test_list[TEST_NUM] = {1, 1, 0, 0, 1, 0, 1, 0}; static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) @@ -98,7 +98,30 @@ static int event_deinit(void) return ESP_OK; } -TEST_CASE("adc2 work with wifi","[adc]") +static void s_test_adc_work_when_wifi_on(adc_oneshot_unit_handle_t adc_handle, adc_channel_t channel) +{ + esp_err_t ret = ESP_FAIL; + int32_t start = xTaskGetTickCount(); + int32_t now; + int32_t remain_wait_ms = 0; + int32_t timeout = pdMS_TO_TICKS(10); + do { + now = xTaskGetTickCount(); + remain_wait_ms = pdTICKS_TO_MS(TIME_REMAIN(start, now, timeout)); + ret = adc_oneshot_read(adc_handle, channel, &read_raw); + if (ret == ESP_OK) { + printf("When WiFi is ON, ADC read: %d (target_value: %d)\n", read_raw, target_value); + TEST_ASSERT_INT_WITHIN(ADC_ERROR_THRES, target_value, read_raw); + break; + } else if (ret == ESP_ERR_TIMEOUT) { + continue; + } else { + TEST_ESP_OK(ret); + } + } while (remain_wait_ms); +} + +__attribute__((unused)) static void adc_work_with_wifi(adc_unit_t unit_id, adc_channel_t channel) { test_case_uses_tcpip(); @@ -132,82 +155,83 @@ TEST_CASE("adc2 work with wifi","[adc]") TEST_ESP_OK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); //---------------------------------ADC init-----------------------------------// - int read_raw; - int target_value; - int test_adc_io; - bool test_list[TEST_NUM] = {1, 1, 0, 0, 1, 0, 1, 0}; - TEST_ESP_OK(adc_oneshot_channel_to_io(ADC_UNIT_2, TEST_ADC2_CHAN0, &test_adc_io)); + TEST_ESP_OK(adc_oneshot_channel_to_io(unit_id, channel, &test_adc_io)); printf("test_adc_io is %d\n", test_adc_io); - //-------------ADC2 Init---------------// - adc_oneshot_unit_handle_t adc2_handle; - adc_oneshot_unit_init_cfg_t init_config2 = { - .unit_id = ADC_UNIT_2, + //-------------ADC Init---------------// + adc_oneshot_unit_handle_t adc_handle; + adc_oneshot_unit_init_cfg_t init_config = { + .unit_id = unit_id, .ulp_mode = ADC_ULP_MODE_DISABLE, }; - TEST_ESP_OK(adc_oneshot_new_unit(&init_config2, &adc2_handle)); + TEST_ESP_OK(adc_oneshot_new_unit(&init_config, &adc_handle)); - //-------------ADC2 TEST Channel 0 Config---------------// + //-------------ADC TEST Channel Config---------------// adc_oneshot_chan_cfg_t config = { .bitwidth = ADC_BITWIDTH_DEFAULT, .atten = ADC_ATTEN_DB_11, }; - TEST_ESP_OK(adc_oneshot_config_channel(adc2_handle, TEST_ADC2_CHAN0, &config)); + TEST_ESP_OK(adc_oneshot_config_channel(adc_handle, channel, &config)); for (int i = 0; i < TEST_NUM; i++) { /* Tune test ADC channel level */ - test_adc_set_io_level(ADC_UNIT_2, TEST_ADC2_CHAN0, test_list[i]); + test_adc_set_io_level(unit_id, channel, test_list[i]); target_value = test_list[i] ? ADC_TEST_HIGH_VAL : ADC_TEST_LOW_VAL; - /* ADC2 single read before WIFI start */ - TEST_ESP_OK(adc_oneshot_read(adc2_handle, TEST_ADC2_CHAN0, &read_raw)); + /* ADC single read before WIFI start */ + TEST_ESP_OK(adc_oneshot_read(adc_handle, channel, &read_raw)); printf("Before WiFi starts, ADC read: %d (target_value: %d)\n", read_raw, target_value); TEST_ASSERT_INT_WITHIN(ADC_ERROR_THRES, target_value, read_raw); - /* ADC2 single read when WIFI is on */ + /* ADC single read when WIFI is on */ TEST_ESP_OK(esp_wifi_start()); #if CONFIG_IDF_TARGET_ESP32 - TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, adc_oneshot_read(adc2_handle, TEST_ADC2_CHAN0, &read_raw)); + if (unit_id == 1) { + // On ESP32 ADC2, PWDET/PKDET controller is for Wi-Fi internal use only. + // If Wi-Fi module is using the SAR ADC2, users can not measure the analog signal from the pins using SAR ADC2. + // After SAR ADC2 is released by Wi-Fi, users can use SAR ADC2 normally. + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, adc_oneshot_read(adc_handle, channel, &read_raw)); + } else { + s_test_adc_work_when_wifi_on(adc_handle, channel); + } #else - esp_err_t ret = ESP_FAIL; - int32_t start = xTaskGetTickCount(); - int32_t now; - int32_t remain_wait_ms = 0; - int32_t timeout = pdMS_TO_TICKS(10); - - do { - now = xTaskGetTickCount(); - remain_wait_ms = pdTICKS_TO_MS(TIME_REMAIN(start, now, timeout)); - ret = adc_oneshot_read(adc2_handle, TEST_ADC2_CHAN0, &read_raw); - if (ret == ESP_OK) { - printf("When WiFi is ON, ADC read: %d (target_value: %d)\n", read_raw, target_value); - TEST_ASSERT_INT_WITHIN(ADC_ERROR_THRES, target_value, read_raw); - break; - } else if (ret == ESP_ERR_TIMEOUT) { - continue; - } else { - TEST_ESP_OK(ret); - } - } while (remain_wait_ms); + s_test_adc_work_when_wifi_on(adc_handle, channel); #endif - - - /* ADC2 single read after WIFI is off */ + /* ADC single read after WIFI is off */ TEST_ESP_OK(esp_wifi_stop()); - TEST_ESP_OK(adc_oneshot_read(adc2_handle, TEST_ADC2_CHAN0, &read_raw)); + TEST_ESP_OK(adc_oneshot_read(adc_handle, channel, &read_raw)); printf("After WiFi is OFF, ADC read: %d (target_value: %d)\n\n", read_raw, target_value); TEST_ASSERT_INT_WITHIN(ADC_ERROR_THRES, target_value, read_raw); } + TEST_ESP_OK(adc_oneshot_del_unit(adc_handle)); + ESP_LOGI(TAG, "ADC%d with WiFi test is success", unit_id + 1); + TEST_ESP_OK(esp_wifi_deinit()); event_deinit(); nvs_flash_deinit(); - TEST_ESP_OK(adc_oneshot_del_unit(adc2_handle)); TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of esp_netif and event_loop."); } -#endif //#if (SOC_ADC_PERIPH_NUM > 1) +#if CONFIG_IDF_TARGET_ESP32C6 +// On ESP32C6, ADC need to call two modem clocks: modem_syscon_ll_enable_fe_80m_clock and modem_syscon_ll_enable_fe_apb_clock. +// Without calling these two clocks, PWDET mode will not take into effect, so ADC readings will be wrong. +TEST_CASE("ADC1 work with WiFi","[adc]") +{ + adc_work_with_wifi(ADC_UNIT_1, ADC1_WIFI_TEST_CHAN0); +} +#endif // CONFIG_IDF_TARGET_ESP32C6 + +#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3 +// On ESP32C3, ADC2 is no longer supported, due to its HW limitation. +TEST_CASE("ADC2 work with WiFi","[adc]") +{ + adc_work_with_wifi(ADC_UNIT_2, ADC2_WIFI_TEST_CHAN0); +} +#endif // (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3 + +#endif //SOC_WIFI_SUPPORTED && SOC_ADC_SUPPORTED From 8efe9500770f7f0bde39b874f655de3d4113ed03 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Wed, 27 Sep 2023 10:01:10 +0800 Subject: [PATCH 115/142] fix(adc): power settings not taking into effect on H2 --- components/esp_hw_support/port/esp32h2/sar_periph_ctrl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/esp_hw_support/port/esp32h2/sar_periph_ctrl.c b/components/esp_hw_support/port/esp32h2/sar_periph_ctrl.c index 79598ee0eb8a..115f4077bd2f 100644 --- a/components/esp_hw_support/port/esp32h2/sar_periph_ctrl.c +++ b/components/esp_hw_support/port/esp32h2/sar_periph_ctrl.c @@ -17,6 +17,7 @@ #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "esp_private/sar_periph_ctrl.h" +#include "esp_private/esp_modem_clock.h" #include "hal/sar_ctrl_ll.h" static const char *TAG = "sar_periph_ctrl"; @@ -54,6 +55,7 @@ static int s_pwdet_power_on_cnt; static void s_sar_power_acquire(void) { + modem_clock_module_enable(PERIPH_MODEM_ADC_COMMON_FE_MODULE); portENTER_CRITICAL_SAFE(&rtc_spinlock); s_pwdet_power_on_cnt++; if (s_pwdet_power_on_cnt == 1) { @@ -74,6 +76,7 @@ static void s_sar_power_release(void) sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_FSM); } portEXIT_CRITICAL_SAFE(&rtc_spinlock); + modem_clock_module_disable(PERIPH_MODEM_ADC_COMMON_FE_MODULE); } From be2c59112941e59fee52bed92a4e385c4755d35f Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Thu, 28 Sep 2023 09:16:03 +0530 Subject: [PATCH 116/142] fix(startup): flip the security configuration check order For cases where the bootloader is not enabled with the security features ends up receiving an incorrect application with flash encryption enabled should not really program any security efuses. In the startup sequence, we first used to program the ROM DL mode configuration but now we check for the flash encryption related checks first. If the flash encryption related checks finds that flash encryption is not enabled on the device then it aborts the boot process. This is the case with `CONFIG_SECURE_FLASH_CHECK_ENC_EN_IN_APP` enabled. This would at-least ensure that accidental program of security enabled application does not really program any ROM DL mode efuses and there is chance to recover the device. --- components/esp_system/startup.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 639095442168..3d98a6e2fd4b 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -355,6 +355,15 @@ static void do_core_init(void) #endif #endif +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + esp_flash_encryption_init_checks(); +#endif + +#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT) + // Note: in some configs this may read flash, so placed after flash init + esp_secure_boot_init_checks(); +#endif + #if CONFIG_SECURE_DISABLE_ROM_DL_MODE err = esp_efuse_disable_rom_download_mode(); assert(err == ESP_OK && "Failed to disable ROM download mode"); @@ -369,15 +378,6 @@ static void do_core_init(void) esp_efuse_disable_basic_rom_console(); #endif -#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED - esp_flash_encryption_init_checks(); -#endif - -#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT) - // Note: in some configs this may read flash, so placed after flash init - esp_secure_boot_init_checks(); -#endif - #ifdef ROM_LOG_MODE esp_efuse_set_rom_log_scheme(ROM_LOG_MODE); #endif From d56647b2519c6ed1cd2925a73179c074469bb843 Mon Sep 17 00:00:00 2001 From: "sonika.rathi" Date: Tue, 26 Sep 2023 13:56:39 +0200 Subject: [PATCH 117/142] fix(vfs/uart): Add support for multi-task call to uart select --- .../vfs/test_apps/main/test_vfs_select.c | 465 +++++++++++------- components/vfs/vfs_uart.c | 16 +- 2 files changed, 288 insertions(+), 193 deletions(-) diff --git a/components/vfs/test_apps/main/test_vfs_select.c b/components/vfs/test_apps/main/test_vfs_select.c index 7f46a88615ef..3e8c04596d18 100644 --- a/components/vfs/test_apps/main/test_vfs_select.c +++ b/components/vfs/test_apps/main/test_vfs_select.c @@ -101,6 +101,23 @@ static void uart1_init(void) uart_param_config(UART_NUM_1, &uart_config); } +static void read_task(void *param) +{ + char recv_message[sizeof(message)]; + const test_task_param_t *test_task_param = param; + vTaskDelay(test_task_param->delay_ms / portTICK_PERIOD_MS); + read(test_task_param->fd, recv_message, sizeof(message)); + if (test_task_param->sem) { + xSemaphoreGive(test_task_param->sem); + } + vTaskDelete(NULL); +} + +static inline void start_read_task(const test_task_param_t *test_task_param) +{ + xTaskCreate(read_task, "read_task", 8*1024, (void *) test_task_param, 5, NULL); +} + static void send_task(void *param) { const test_task_param_t *test_task_param = param; @@ -112,7 +129,7 @@ static void send_task(void *param) vTaskDelete(NULL); } -static inline void start_task(const test_task_param_t *test_task_param) +static inline void start_write_task(const test_task_param_t *test_task_param) { xTaskCreate(send_task, "send_task", 8*1024, (void *) test_task_param, 5, NULL); } @@ -164,7 +181,7 @@ TEST_CASE("UART can do select()", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_task(&test_task_param); + start_write_task(&test_task_param); int s = select(uart_fd + 1, &rfds, NULL, NULL, &tv); TEST_ASSERT_EQUAL(s, 1); @@ -181,7 +198,7 @@ TEST_CASE("UART can do select()", "[vfs]") FD_SET(uart_fd, &rfds); FD_SET(socket_fd, &rfds); - start_task(&test_task_param); + start_write_task(&test_task_param); s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); TEST_ASSERT_EQUAL(s, 1); @@ -198,6 +215,256 @@ TEST_CASE("UART can do select()", "[vfs]") deinit(uart_fd, socket_fd); } +static void select_task(void *task_param) +{ + const test_select_task_param_t *param = task_param; + + int s = select(param->maxfds, param->rdfds, param->wrfds, param->errfds, param->tv); + TEST_ASSERT_EQUAL(param->select_ret, s); + + if (param->sem) { + xSemaphoreGive(param->sem); + } + vTaskDelete(NULL); +} + +static void inline start_select_task(test_select_task_param_t *param) +{ + xTaskCreate(select_task, "select_task", 4*1024, (void *) param, 5, NULL); +} + +TEST_CASE("concurrent selects work for UART", "[vfs]") +{ + // This test case initiates two select tasks on the same UART FD, + // One task will wait for a write operation, while the other will wait for a read operation to occur. + // The first task will complete its operation before the second task proceeds with its operation on the same FD + // In this scenario, the write operation will be performed initially, + // followed by the subsequent continuation of the read operation. + + int uart_fd, socket_fd; + init(&uart_fd, &socket_fd); + + const test_task_param_t send_param = { + .fd = uart_fd, + .delay_ms = 0, + .sem = NULL, + }; + + fd_set wrfds1; + FD_ZERO(&wrfds1); + FD_SET(uart_fd, &wrfds1); + + test_select_task_param_t param_write = { + .rdfds = NULL, + .wrfds = &wrfds1, + .errfds = NULL, + .maxfds = uart_fd + 1, + .tv = NULL, + .select_ret = 1, + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(param_write.sem); + //Start first task which will wait on select call for write operation on the UART FD + start_select_task(¶m_write); + + fd_set rdfds2; + FD_ZERO(&rdfds2); + FD_SET(uart_fd, &rdfds2); + + test_select_task_param_t param_read = { + .rdfds = &rdfds2, + .wrfds = NULL, + .errfds = NULL, + .maxfds = uart_fd + 1, + .tv = NULL, + .select_ret = 1, + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(param_read.sem); + //Start second task which will wait on another select call for read operation on the same UART FD + start_select_task(¶m_read); + + //Start writing operation on the UART port + start_write_task(&send_param); + //Confirm the completion of the write operation + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param_write.sem, 1000 / portTICK_PERIOD_MS)); + vSemaphoreDelete(param_write.sem); + TEST_ASSERT(FD_ISSET(uart_fd, &wrfds1)); + + //Start reading operation on the same UART port + start_read_task(&send_param); + //Confirm the completion of the read operation + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param_read.sem, 1000 / portTICK_PERIOD_MS)); + vSemaphoreDelete(param_read.sem); + TEST_ASSERT(FD_ISSET(uart_fd, &rdfds2)); + + deinit(uart_fd, socket_fd); +} + +TEST_CASE("concurrent selects work", "[vfs]") +{ + int uart_fd, socket_fd; + init(&uart_fd, &socket_fd); + const int dummy_socket_fd = open_dummy_socket(); + + { + // Two tasks will wait for the same UART FD for reading and they will time-out + + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 100000, + }; + + fd_set rdfds1; + FD_ZERO(&rdfds1); + FD_SET(uart_fd, &rdfds1); + + test_select_task_param_t param = { + .rdfds = &rdfds1, + .wrfds = NULL, + .errfds = NULL, + .maxfds = uart_fd + 1, + .tv = &tv, + .select_ret = 0, // expected timeout + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(param.sem); + + fd_set rdfds2; + FD_ZERO(&rdfds2); + FD_SET(uart_fd, &rdfds2); + FD_SET(socket_fd, &rdfds2); + FD_SET(dummy_socket_fd, &rdfds2); + + start_select_task(¶m); + vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() + + int s = select(MAX(MAX(uart_fd, dummy_socket_fd), socket_fd) + 1, &rdfds2, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(0, s); // timeout here as well + + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1000 / portTICK_PERIOD_MS)); + vSemaphoreDelete(param.sem); + } + + { + // One tasks waits for UART reading and one for writing. The former will be successful and latter will + // time-out. + + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 100000, + }; + + fd_set wrfds1; + FD_ZERO(&wrfds1); + FD_SET(uart_fd, &wrfds1); + + test_select_task_param_t param = { + .rdfds = NULL, + .wrfds = &wrfds1, + .errfds = NULL, + .maxfds = uart_fd + 1, + .tv = &tv, + .select_ret = 1, + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(param.sem); + + const test_task_param_t send_param = { + .fd = uart_fd, + .delay_ms = 50, + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(send_param.sem); + start_write_task(&send_param); // This task will write to UART which will be detected by select() + start_select_task(¶m); + vTaskDelay(100 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() + + fd_set rdfds2; + FD_ZERO(&rdfds2); + FD_SET(uart_fd, &rdfds2); + FD_SET(socket_fd, &rdfds2); + FD_SET(dummy_socket_fd, &rdfds2); + + int s = select(MAX(MAX(uart_fd, dummy_socket_fd), socket_fd) + 1, &rdfds2, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(1, s); + TEST_ASSERT(FD_ISSET(uart_fd, &rdfds2)); + TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rdfds2)); + TEST_ASSERT_UNLESS(FD_ISSET(dummy_socket_fd, &rdfds2)); + + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1000 / portTICK_PERIOD_MS)); + vSemaphoreDelete(param.sem); + + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(send_param.sem, 1000 / portTICK_PERIOD_MS)); + vSemaphoreDelete(send_param.sem); + } + + deinit(uart_fd, socket_fd); + close(dummy_socket_fd); +} + +TEST_CASE("select() works with concurrent mount", "[vfs][fatfs]") +{ + wl_handle_t test_wl_handle; + int uart_fd, socket_fd; + + init(&uart_fd, &socket_fd); + const int dummy_socket_fd = open_dummy_socket(); + + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 2 + }; + + // select() will be waiting for a socket & UART and FATFS mount will occur in parallel + + struct timeval tv = { + .tv_sec = 1, + .tv_usec = 0, + }; + + fd_set rdfds; + FD_ZERO(&rdfds); + FD_SET(uart_fd, &rdfds); + FD_SET(dummy_socket_fd, &rdfds); + + test_select_task_param_t param = { + .rdfds = &rdfds, + .wrfds = NULL, + .errfds = NULL, + .maxfds = MAX(uart_fd, dummy_socket_fd) + 1, + .tv = &tv, + .select_ret = 0, // expected timeout + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(param.sem); + + start_select_task(¶m); + vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() + + TEST_ESP_OK(esp_vfs_fat_spiflash_mount_rw_wl("/spiflash", NULL, &mount_config, &test_wl_handle)); + + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1500 / portTICK_PERIOD_MS)); + + // select() will be waiting for a socket & UART and FATFS unmount will occur in parallel + + FD_ZERO(&rdfds); + FD_SET(uart_fd, &rdfds); + FD_SET(dummy_socket_fd, &rdfds); + + start_select_task(¶m); + vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() + + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", test_wl_handle)); + + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1500 / portTICK_PERIOD_MS)); + + vSemaphoreDelete(param.sem); + + deinit(uart_fd, socket_fd); + close(dummy_socket_fd); +} + TEST_CASE("UART can do poll() with POLLIN event", "[vfs]") { int uart_fd; @@ -222,7 +489,7 @@ TEST_CASE("UART can do poll() with POLLIN event", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_task(&test_task_param); + start_write_task(&test_task_param); int s = poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(s, 1); @@ -240,7 +507,7 @@ TEST_CASE("UART can do poll() with POLLIN event", "[vfs]") poll_fds[1].fd = socket_fd; poll_fds[1].events = POLLIN; - start_task(&test_task_param); + start_write_task(&test_task_param); s = poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(s, 1); @@ -283,7 +550,7 @@ TEST_CASE("UART can do poll() with POLLOUT event", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_task(&test_task_param); + start_write_task(&test_task_param); poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(uart_fd, poll_fds[0].fd); @@ -327,7 +594,7 @@ TEST_CASE("socket can do select()", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_task(&test_task_param); + start_write_task(&test_task_param); const int s = select(MAX(MAX(uart_fd, socket_fd), dummy_socket_fd) + 1, &rfds, NULL, NULL, &tv); TEST_ASSERT_EQUAL(1, s); @@ -376,7 +643,7 @@ TEST_CASE("socket can do poll()", "[vfs]") .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); - start_task(&test_task_param); + start_write_task(&test_task_param); int s = poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100); TEST_ASSERT_EQUAL(s, 1); @@ -466,185 +733,3 @@ TEST_CASE("poll() timeout", "[vfs]") deinit(uart_fd, socket_fd); } - -static void select_task(void *task_param) -{ - const test_select_task_param_t *param = task_param; - - int s = select(param->maxfds, param->rdfds, param->wrfds, param->errfds, param->tv); - TEST_ASSERT_EQUAL(param->select_ret, s); - - if (param->sem) { - xSemaphoreGive(param->sem); - } - vTaskDelete(NULL); -} - -static void inline start_select_task(test_select_task_param_t *param) -{ - xTaskCreate(select_task, "select_task", 4*1024, (void *) param, 5, NULL); -} - -TEST_CASE("concurrent selects work", "[vfs]") -{ - int uart_fd, socket_fd; - init(&uart_fd, &socket_fd); - const int dummy_socket_fd = open_dummy_socket(); - - { - // Two tasks will wait for the same UART FD for reading and they will time-out - - struct timeval tv = { - .tv_sec = 0, - .tv_usec = 100000, - }; - - fd_set rdfds1; - FD_ZERO(&rdfds1); - FD_SET(uart_fd, &rdfds1); - - test_select_task_param_t param = { - .rdfds = &rdfds1, - .wrfds = NULL, - .errfds = NULL, - .maxfds = uart_fd + 1, - .tv = &tv, - .select_ret = 0, // expected timeout - .sem = xSemaphoreCreateBinary(), - }; - TEST_ASSERT_NOT_NULL(param.sem); - - fd_set rdfds2; - FD_ZERO(&rdfds2); - FD_SET(uart_fd, &rdfds2); - FD_SET(socket_fd, &rdfds2); - FD_SET(dummy_socket_fd, &rdfds2); - - start_select_task(¶m); - vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() - - int s = select(MAX(MAX(uart_fd, dummy_socket_fd), socket_fd) + 1, &rdfds2, NULL, NULL, &tv); - TEST_ASSERT_EQUAL(0, s); // timeout here as well - - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1000 / portTICK_PERIOD_MS)); - vSemaphoreDelete(param.sem); - } - - { - // One tasks waits for UART reading and one for writing. The former will be successful and latter will - // time-out. - - struct timeval tv = { - .tv_sec = 0, - .tv_usec = 100000, - }; - - fd_set wrfds1; - FD_ZERO(&wrfds1); - FD_SET(uart_fd, &wrfds1); - - test_select_task_param_t param = { - .rdfds = NULL, - .wrfds = &wrfds1, - .errfds = NULL, - .maxfds = uart_fd + 1, - .tv = &tv, - .select_ret = 1, - .sem = xSemaphoreCreateBinary(), - }; - TEST_ASSERT_NOT_NULL(param.sem); - - const test_task_param_t send_param = { - .fd = uart_fd, - .delay_ms = 50, - .sem = xSemaphoreCreateBinary(), - }; - TEST_ASSERT_NOT_NULL(send_param.sem); - start_task(&send_param); // This task will write to UART which will be detected by select() - start_select_task(¶m); - vTaskDelay(100 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() - - fd_set rdfds2; - FD_ZERO(&rdfds2); - FD_SET(uart_fd, &rdfds2); - FD_SET(socket_fd, &rdfds2); - FD_SET(dummy_socket_fd, &rdfds2); - - int s = select(MAX(MAX(uart_fd, dummy_socket_fd), socket_fd) + 1, &rdfds2, NULL, NULL, &tv); - TEST_ASSERT_EQUAL(1, s); - TEST_ASSERT(FD_ISSET(uart_fd, &rdfds2)); - TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rdfds2)); - TEST_ASSERT_UNLESS(FD_ISSET(dummy_socket_fd, &rdfds2)); - - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1000 / portTICK_PERIOD_MS)); - vSemaphoreDelete(param.sem); - - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(send_param.sem, 1000 / portTICK_PERIOD_MS)); - vSemaphoreDelete(send_param.sem); - } - - deinit(uart_fd, socket_fd); - close(dummy_socket_fd); -} - -TEST_CASE("select() works with concurrent mount", "[vfs][fatfs]") -{ - wl_handle_t test_wl_handle; - int uart_fd, socket_fd; - - init(&uart_fd, &socket_fd); - const int dummy_socket_fd = open_dummy_socket(); - - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = true, - .max_files = 2 - }; - - // select() will be waiting for a socket & UART and FATFS mount will occur in parallel - - struct timeval tv = { - .tv_sec = 1, - .tv_usec = 0, - }; - - fd_set rdfds; - FD_ZERO(&rdfds); - FD_SET(uart_fd, &rdfds); - FD_SET(dummy_socket_fd, &rdfds); - - test_select_task_param_t param = { - .rdfds = &rdfds, - .wrfds = NULL, - .errfds = NULL, - .maxfds = MAX(uart_fd, dummy_socket_fd) + 1, - .tv = &tv, - .select_ret = 0, // expected timeout - .sem = xSemaphoreCreateBinary(), - }; - TEST_ASSERT_NOT_NULL(param.sem); - - start_select_task(¶m); - vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() - - TEST_ESP_OK(esp_vfs_fat_spiflash_mount_rw_wl("/spiflash", NULL, &mount_config, &test_wl_handle)); - - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1500 / portTICK_PERIOD_MS)); - - // select() will be waiting for a socket & UART and FATFS unmount will occur in parallel - - FD_ZERO(&rdfds); - FD_SET(uart_fd, &rdfds); - FD_SET(dummy_socket_fd, &rdfds); - - start_select_task(¶m); - vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() - - TEST_ESP_OK(esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", test_wl_handle)); - - TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(param.sem, 1500 / portTICK_PERIOD_MS)); - - vSemaphoreDelete(param.sem); - - deinit(uart_fd, socket_fd); - close(dummy_socket_fd); -} diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index 3e1fcf4a74b7..fd6fb42de91f 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -128,6 +128,7 @@ typedef struct { static uart_select_args_t **s_registered_selects = NULL; static int s_registered_select_num = 0; static portMUX_TYPE s_registered_select_lock = portMUX_INITIALIZER_UNLOCKED; +static int s_uart_select_count[UART_NUM] = {0}; static esp_err_t uart_end_select(void *end_select_args); @@ -469,7 +470,10 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, //uart_set_select_notif_callback sets the callbacks in UART ISR for (int i = 0; i < max_fds; ++i) { if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) { - uart_set_select_notif_callback(i, select_notif_callback_isr); + if (s_uart_select_count[i] == 0) { + uart_set_select_notif_callback(i, select_notif_callback_isr); + } + s_uart_select_count[i]++; } } @@ -504,7 +508,13 @@ static esp_err_t uart_end_select(void *end_select_args) portENTER_CRITICAL(uart_get_selectlock()); esp_err_t ret = unregister_select(args); for (int i = 0; i < UART_NUM; ++i) { - uart_set_select_notif_callback(i, NULL); + if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) { + s_uart_select_count[i]--; + if (s_uart_select_count[i] == 0) { + uart_set_select_notif_callback(i, NULL); + } + break; + } } portEXIT_CRITICAL(uart_get_selectlock()); From 821f7b04988d0721ff7dbb64af43d165e3124718 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 20 Sep 2023 12:47:21 +0800 Subject: [PATCH 118/142] fix(ledc): fix ledc driver 100% duty cycle configuration Update ledc duty cycle value range in doxygen. Fix duty configuration error at 100% duty cycle for ESP32. Improve LEDC API doxygen. Closes https://github.com/espressif/esp-idf/pull/11516 Closes https://github.com/espressif/esp-idf/issues/12083 --- components/driver/ledc/include/driver/ledc.h | 118 ++++++++++++------ components/driver/ledc/ledc.c | 15 ++- docs/en/api-reference/peripherals/ledc.rst | 8 +- docs/zh_CN/api-reference/peripherals/ledc.rst | 8 +- .../peripherals/ledc/ledc_basic/README.md | 8 +- .../ledc_basic/main/ledc_basic_example_main.c | 8 +- 6 files changed, 114 insertions(+), 51 deletions(-) diff --git a/components/driver/ledc/include/driver/ledc.h b/components/driver/ledc/include/driver/ledc.h index bce4e0de4e30..0e5fcbb65e47 100644 --- a/components/driver/ledc/include/driver/ledc.h +++ b/components/driver/ledc/include/driver/ledc.h @@ -38,12 +38,12 @@ extern "C" { */ typedef struct { int gpio_num; /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16 */ - ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */ + ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode (only exists on esp32) or low-speed mode */ ledc_channel_t channel; /*!< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */ ledc_intr_type_t intr_type; /*!< configure interrupt, Fade interrupt enable or Fade interrupt disable */ ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - LEDC_TIMER_MAX-1) */ uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */ - int hpoint; /*!< LEDC channel hpoint value, the max value is 0xfffff */ + int hpoint; /*!< LEDC channel hpoint value, the range is [0, (2**duty_resolution)-1] */ struct { unsigned int output_invert: 1;/*!< Enable (1) or disable (0) gpio output invert */ } flags; /*!< LEDC flags */ @@ -54,7 +54,7 @@ typedef struct { * @brief Configuration parameters of LEDC timer for ledc_timer_config function */ typedef struct { - ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */ + ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode (only exists on esp32) or low-speed mode */ ledc_timer_bit_t duty_resolution; /*!< LEDC channel duty resolution */ ledc_timer_t timer_num; /*!< The timer source of channel (0 - LEDC_TIMER_MAX-1) */ uint32_t freq_hz; /*!< LEDC timer frequency (Hz) */ @@ -88,7 +88,7 @@ typedef struct { ledc_cb_event_t event; /**< Event name */ uint32_t speed_mode; /**< Speed mode of the LEDC channel group */ uint32_t channel; /**< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */ - uint32_t duty; /**< LEDC current duty of the channel, the range of duty is [0, (2**duty_resolution) - 1] */ + uint32_t duty; /**< LEDC current duty of the channel, the range of duty is [0, (2**duty_resolution)] */ } ledc_cb_param_t; /** @@ -135,6 +135,7 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf); /** * @brief LEDC update channel parameters + * * @note Call this function to activate the LEDC updated parameters. * After ledc_set_duty, we need to call this function to update the settings. * And the new LEDC parameters don't take effect until the next PWM cycle. @@ -144,13 +145,13 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf); * @note If `CONFIG_LEDC_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, * makes it possible to execute even when the Cache is disabled. * @note This function is allowed to run within ISR context. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error - * */ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel); @@ -177,6 +178,7 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc * @note If `CONFIG_LEDC_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, * makes it possible to execute even when the Cache is disabled. * @note This function is allowed to run within ISR context. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param idle_level Set output idle level after LEDC stops. @@ -216,15 +218,17 @@ uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num); /** * @brief LEDC set duty and hpoint value * Only after calling ledc_update_duty will the duty update. + * * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to * control one LEDC channel in different tasks at the same time. * A thread-safe version of API is ledc_set_duty_and_update * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1] - * @param hpoint Set the LEDC hpoint value(max: 0xfffff) + * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)] + * @param hpoint Set the LEDC hpoint value, the range is [0, (2**duty_resolution)-1] * * @return * - ESP_OK Success @@ -237,6 +241,7 @@ esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t chann * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t + * * @return * - LEDC_ERR_VAL if parameter error * - Others Current hpoint value of LEDC channel @@ -247,14 +252,16 @@ int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel); * @brief LEDC set duty * This function do not change the hpoint value of this channel. if needed, please call ledc_set_duty_with_hpoint. * only after calling ledc_update_duty will the duty update. + * * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to * control one LEDC channel in different tasks at the same time. * A thread-safe version of API is ledc_set_duty_and_update. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1] + * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)] * * @return * - ESP_OK Success @@ -280,11 +287,13 @@ uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel); /** * @brief LEDC set gradient * Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect. + * * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution) - 1] + * @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution)] * @param fade_direction Set the direction of the gradient * @param step_num Set the number of the gradient * @param duty_cycle_num Set how many LEDC tick each time the gradient lasts @@ -310,7 +319,8 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Function pointer error. + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Failed to find available interrupt source */ esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle); @@ -320,7 +330,7 @@ esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param timer_sel Timer index (0-3), there are 4 timers in LEDC module * @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source - * @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution)] + * @param duty_resolution Resolution of duty setting in number of bits. The range is [1, SOC_LEDC_TIMER_BIT_WIDTH] * @param clk_src Select LEDC source clock. * * @return @@ -350,7 +360,6 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, ledc_timer_t timer_sel); * @return * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success - * */ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, ledc_timer_t timer_sel); @@ -381,6 +390,7 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel /** * @brief Set LEDC fade function. + * * @note Call ledc_fade_func_install() once before calling this function. * Call ledc_fade_start() after this to start fading. * @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to @@ -388,22 +398,24 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel * A thread-safe version of API is ledc_set_fade_step_and_start * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. - * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. , + * + * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] + * @param target_duty Target duty of fading [0, (2**duty_resolution)] * @param scale Controls the increase or decrease step scale. * @param cycle_num increase or decrease the duty every cycle_num cycles * * @return - * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num); /** * @brief Set LEDC fade function, with a limited time. + * * @note Call ledc_fade_func_install() once before calling this function. * Call ledc_fade_start() after this to start fading. * @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to @@ -411,43 +423,48 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel * A thread-safe version of API is ledc_set_fade_step_and_start * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. - * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. , + * + * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] + * @param target_duty Target duty of fading [0, (2**duty_resolution)] * @param max_fade_time_ms The maximum time of the fading ( ms ). * * @return - * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms); /** * @brief Install LEDC fade function. This function will occupy interrupt of LEDC module. + * * @param 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. * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function already installed. + * - ESP_ERR_INVALID_ARG Intr flag error + * - ESP_ERR_NOT_FOUND Failed to find available interrupt source + * - ESP_ERR_INVALID_STATE Fade function already installed */ esp_err_t ledc_fade_func_install(int intr_alloc_flags); /** * @brief Uninstall LEDC fade function. - * */ void ledc_fade_func_uninstall(void); /** * @brief Start LEDC fading. + * * @note Call ledc_fade_func_install() once before calling this function. * Call this API right after ledc_set_fade_with_time or ledc_set_fade_with_step before to start fading. * @note Starting fade operation with this API is not thread-safe, use with care. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel number * @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info. @@ -455,7 +472,7 @@ void ledc_fade_func_uninstall(void); * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_ERR_INVALID_STATE Channel not initialized or fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error. */ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode); @@ -463,81 +480,99 @@ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_f #if SOC_LEDC_SUPPORT_FADE_STOP /** * @brief Stop LEDC fading. The duty of the channel is garanteed to be fixed at most one PWM cycle after the function returns. + * * @note This API can be called if a new fixed duty or a new fade want to be set while the last fade operation is still running in progress. * @note Call this API will abort the fading operation only if it was started by calling ledc_fade_start with LEDC_FADE_NO_WAIT mode. * @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards has no use in stopping the fade. Fade will continue until it reachs the target duty. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel number * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function not installed. - * - ESP_ERR_INVALID_ARG Parameter error. + * - ESP_ERR_INVALID_STATE Channel not initialized + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL Fade function init error */ esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel); #endif //SOC_LEDC_SUPPORT_FADE_STOP /** * @brief A thread-safe API to set duty for LEDC channel and return when duty updated. + * * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1] - * @param hpoint Set the LEDC hpoint value(max: 0xfffff) + * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)] + * @param hpoint Set the LEDC hpoint value, the range is [0, (2**duty_resolution)-1] * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE Channel not initialized + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint); /** * @brief A thread-safe API to set and start LEDC fade function, with a limited time. + * * @note Call ledc_fade_func_install() once, before calling this function. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] + * @param target_duty Target duty of fading [0, (2**duty_resolution)] * @param max_fade_time_ms The maximum time of the fading ( ms ). * @param fade_mode choose blocking or non-blocking mode + * * @return - * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode); /** * @brief A thread-safe API to set and start LEDC fade function. + * * @note Call ledc_fade_func_install() once before calling this function. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * Other duty operations will have to wait until the fade operation has finished. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t - * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] + * @param target_duty Target duty of fading [0, (2**duty_resolution)] * @param scale Controls the increase or decrease step scale. * @param cycle_num increase or decrease the duty every cycle_num cycles * @param fade_mode choose blocking or non-blocking mode + * * @return - * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode); /** * @brief LEDC callback registration function + * * @note The callback is called from an ISR, it must never attempt to block, and any FreeRTOS API called must be ISR capable. + * * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param cbs Group of LEDC callback functions * @param user_arg user registered data for the callback function + * * @return - * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success - * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Fade function init error */ esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg); @@ -608,10 +643,11 @@ typedef struct { * @param start_duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution)] * @param fade_params_list Pointer to the array of fade parameters for a multi-fade * @param list_len Length of the fade_params_list, i.e. number of fade ranges for a multi-fade (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX) + * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_ERR_INVALID_STATE Fade function not installed + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_multi_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t start_duty, const ledc_fade_param_config_t *fade_params_list, uint32_t list_len); @@ -631,10 +667,11 @@ esp_err_t ledc_set_multi_fade(ledc_mode_t speed_mode, ledc_channel_t channel, ui * @param fade_params_list Pointer to the array of fade parameters for a multi-fade * @param list_len Length of the fade_params_list, i.e. number of fade ranges for a multi-fade (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX) * @param fade_mode Choose blocking or non-blocking mode + * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_ERR_INVALID_STATE Fade function not installed + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_multi_fade_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t start_duty, const ledc_fade_param_config_t *fade_params_list, uint32_t list_len, ledc_fade_mode_t fade_mode); @@ -658,11 +695,11 @@ esp_err_t ledc_set_multi_fade_and_start(ledc_mode_t speed_mode, ledc_channel_t c * @param[in] fade_params_list_size The size of the fade_params_list user allocated (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX) * @param[out] fade_params_list Pointer to the array of ledc_fade_param_config_t structure * @param[out] hw_fade_range_num Number of fade ranges for this multi-fade + * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_ERR_INVALID_STATE LEDC not initialized - * - ESP_ERR_NO_MEM Out of memory + * - ESP_ERR_INVALID_STATE Channel not initialized * - ESP_FAIL Required number of hardware ranges exceeds the size of the ledc_fade_param_config_t array user allocated */ esp_err_t ledc_fill_multi_fade_param_list(ledc_mode_t speed_mode, ledc_channel_t channel, @@ -685,10 +722,11 @@ esp_err_t ledc_fill_multi_fade_param_list(ledc_mode_t speed_mode, ledc_channel_t * @param[out] cycle Pointer to accept fade cycle value * @param[out] scale Pointer to accept fade scale value * @param[out] step Pointer to accept fade step value + * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_ERR_INVALID_STATE LEDC not initialized + * - ESP_ERR_INVALID_STATE Channel not initialized */ esp_err_t ledc_read_fade_param(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t range, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step); #endif // SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED diff --git a/components/driver/ledc/ledc.c b/components/driver/ledc/ledc.c index 753c2dd3a15d..67145ba39a24 100644 --- a/components/driver/ledc/ledc.c +++ b/components/driver/ledc/ledc.c @@ -672,8 +672,13 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf) #endif /*set channel parameters*/ - /* channel parameters decide how the waveform looks like in one period*/ - /* set channel duty and hpoint value, duty range is (0 ~ ((2 ** duty_resolution) - 1)), max hpoint value is 0xfffff*/ + /* channel parameters decide how the waveform looks like in one period */ + /* set channel duty and hpoint value, duty range is [0, (2**duty_res)], hpoint range is [0, (2**duty_res)-1] */ + /* Note: On ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2, ESP32C6, ESP32H2, ESP32P4, due to a hardware bug, + * 100% duty cycle (i.e. 2**duty_res) is not reachable when the binded timer selects the maximum duty + * resolution. For example, the max duty resolution on ESP32C3 is 14-bit width, then set duty to (2**14) + * will mess up the duty calculation in hardware. + */ ledc_set_duty_with_hpoint(speed_mode, ledc_channel, duty, hpoint); /*update duty settings*/ ledc_update_duty(speed_mode, ledc_channel); @@ -859,7 +864,7 @@ static inline void IRAM_ATTR ledc_calc_fade_end_channel(uint32_t *fade_end_statu *channel = i; } -void IRAM_ATTR ledc_fade_isr(void *arg) +static void IRAM_ATTR ledc_fade_isr(void *arg) { bool cb_yield = false; BaseType_t HPTaskAwoken = pdFALSE; @@ -1070,8 +1075,9 @@ static esp_err_t _ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t ESP_LOGD(LEDC_TAG, "cur duty: %"PRIu32"; target: %"PRIu32", step: %d, cycle: %d; scale: %d; dir: %d", duty_cur, target_duty, step_num, cycle_num, scale, dir); } else { + // Directly set duty to the target, does not care on the dir portENTER_CRITICAL(&ledc_spinlock); - ledc_duty_config(speed_mode, channel, LEDC_VAL_NO_CHANGE, target_duty, dir, 1, 1, 0); + ledc_duty_config(speed_mode, channel, LEDC_VAL_NO_CHANGE, target_duty, 1, 1, 1, 0); portEXIT_CRITICAL(&ledc_spinlock); ESP_LOGD(LEDC_TAG, "Set to target duty: %"PRIu32, target_duty); } @@ -1231,6 +1237,7 @@ esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel) esp_err_t ledc_fade_func_install(int intr_alloc_flags) { + LEDC_CHECK(s_ledc_fade_isr_handle == NULL, "fade function already installed", ESP_ERR_INVALID_STATE); //OR intr_alloc_flags with ESP_INTR_FLAG_IRAM because the fade isr is in IRAM return ledc_isr_register(ledc_fade_isr, NULL, intr_alloc_flags | ESP_INTR_FLAG_IRAM, &s_ledc_fade_isr_handle); } diff --git a/docs/en/api-reference/peripherals/ledc.rst b/docs/en/api-reference/peripherals/ledc.rst index 7a29b7fd9a6c..475a2d27d9b4 100644 --- a/docs/en/api-reference/peripherals/ledc.rst +++ b/docs/en/api-reference/peripherals/ledc.rst @@ -246,7 +246,13 @@ To set the duty cycle, use the dedicated function :cpp:func:`ledc_set_duty`. Aft Another way to set the duty cycle, as well as some other channel parameters, is by calling :cpp:func:`ledc_channel_config` covered in Section :ref:`ledc-api-configure-channel`. -The range of the duty cycle values passed to functions depends on selected ``duty_resolution`` and should be from ``0`` to ``(2 ** duty_resolution) - 1``. For example, if the selected duty resolution is 10, then the duty cycle values can range from 0 to 1023. This provides the resolution of ~ 0.1%. +The range of the duty cycle values passed to functions depends on selected ``duty_resolution`` and should be from ``0`` to ``(2 ** duty_resolution)``. For example, if the selected duty resolution is 10, then the duty cycle values can range from 0 to 1024. This provides the resolution of ~ 0.1%. + +.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c2 or esp32c6 or esp32h2 or esp32p4 + + .. warning:: + + On {IDF_TARGET_NAME}, when channel's binded timer selects its maximum duty resolution, the duty cycle value cannot be set to ``(2 ** duty_resolution)``. Otherwise, the internal duty counter in the hardware will overflow and be messed up. Change PWM Duty Cycle Using Hardware diff --git a/docs/zh_CN/api-reference/peripherals/ledc.rst b/docs/zh_CN/api-reference/peripherals/ledc.rst index 55ff9bdce098..98554736fc36 100644 --- a/docs/zh_CN/api-reference/peripherals/ledc.rst +++ b/docs/zh_CN/api-reference/peripherals/ledc.rst @@ -246,7 +246,13 @@ LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实 另外一种设置占空比和其他通道参数的方式是调用 :ref:`ledc-api-configure-channel` 一节提到的函数 :cpp:func:`ledc_channel_config`。 -传递给函数的占空比数值范围取决于选定的 ``duty_resolution``,应为 ``0`` 至 ``(2 ** duty_resolution) - 1``。例如,如选定的占空比分辨率为 10,则占空比的数值范围为 0 至 1023。此时分辨率为 ~ 0.1%。 +传递给函数的占空比数值范围取决于选定的 ``duty_resolution``,应为 ``0`` 至 ``(2 ** duty_resolution)``。例如,如选定的占空比分辨率为 10,则占空比的数值范围为 0 至 1024。此时分辨率为 ~ 0.1%。 + +.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c2 or esp32c6 or esp32h2 or esp32p4 + + .. warning:: + + 在 {IDF_TARGET_NAME} 上,当通道绑定的定时器配置了其最大 PWM 占空比分辨率( ``MAX_DUTY_RES`` ),通道的占空比不能被设置到 ``(2 ** MAX_DUTY_RES)`` 。否则,硬件内部占空比计数器会溢出,并导致占空比计算错误。 使用硬件改变 PWM 占空比 diff --git a/examples/peripherals/ledc/ledc_basic/README.md b/examples/peripherals/ledc/ledc_basic/README.md index efab05a92b52..36827f21f899 100644 --- a/examples/peripherals/ledc/ledc_basic/README.md +++ b/examples/peripherals/ledc/ledc_basic/README.md @@ -27,7 +27,7 @@ The example uses fixed PWM frequency of 5 kHz, duty cycle in 50%, and output GPI Depending on the selected `LEDC_FREQUENCY`, you will need to change the `LEDC_DUTY_RES`. -To dinamicaly set the duty and frequency, you can use the following functions: +To dynamically set the duty and frequency, you can use the following functions: To set the frequency to 2.5 kHZ i.e: @@ -35,10 +35,10 @@ To set the frequency to 2.5 kHZ i.e: ledc_set_freq(LEDC_MODE, LEDC_TIMER, 2500); ``` -Now the duty to 100% i.e: +Now set the duty to 100% i.e: ```c -ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 8191); +ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 8192); ledc_update_duty(LEDC_MODE, LEDC_CHANNEL); ``` @@ -46,7 +46,7 @@ To change the duty cycle you need to calculate the duty range according to the d If duty resolution is 13 bits: -Duty range: `0 to (2 ** 13) - 1 = 8191` where 0 is 0% and 8191 is 100%. +Duty range: `0 to (2 ** 13) = 8191` where 0 is 0% and 8192 is 100%. ### Build and Flash diff --git a/examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c b/examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c index f4f97b7200df..b0ce4474dc80 100644 --- a/examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c +++ b/examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c @@ -15,9 +15,15 @@ #define LEDC_OUTPUT_IO (5) // Define the output GPIO #define LEDC_CHANNEL LEDC_CHANNEL_0 #define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits -#define LEDC_DUTY (4095) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095 +#define LEDC_DUTY (4096) // Set duty to 50%. (2 ** 13) * 50% = 4096 #define LEDC_FREQUENCY (5000) // Frequency in Hertz. Set frequency at 5 kHz +/* Warning: + * For ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2, ESP32C6, ESP32H2, ESP32P4 targets, + * when LEDC_DUTY_RES selects the maximum duty resolution (i.e. value equal to SOC_LEDC_TIMER_BIT_WIDTH), + * 100% duty cycle is not reachable (duty cannot be set to (2 ** SOC_LEDC_TIMER_BIT_WIDTH)). + */ + static void example_ledc_init(void) { // Prepare and then apply the LEDC PWM timer configuration From f5f44e2ce5fd3136d4c38019bb529d027f99c26e Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 21 Sep 2023 19:04:31 +0800 Subject: [PATCH 119/142] fix(ledc): always allocate memory from internal ram --- components/driver/ledc/ledc.c | 20 ++++--------------- .../driver/test_apps/ledc/main/CMakeLists.txt | 2 +- .../driver/test_apps/ledc/pytest_ledc.py | 17 +++++++++++++++- .../test_apps/ledc/sdkconfig.defaults.esp32s3 | 4 ++++ 4 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 components/driver/test_apps/ledc/sdkconfig.defaults.esp32s3 diff --git a/components/driver/ledc/ledc.c b/components/driver/ledc/ledc.c index 67145ba39a24..79826e72c999 100644 --- a/components/driver/ledc/ledc.c +++ b/components/driver/ledc/ledc.c @@ -7,6 +7,7 @@ #include "esp_types.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +#include "freertos/idf_additions.h" #include "esp_log.h" #include "esp_check.h" #include "soc/gpio_periph.h" @@ -58,9 +59,6 @@ typedef struct { ledc_fade_mode_t mode; SemaphoreHandle_t ledc_fade_sem; SemaphoreHandle_t ledc_fade_mux; -#if CONFIG_SPIRAM_USE_MALLOC - StaticQueue_t ledc_fade_sem_storage; -#endif ledc_cb_t ledc_fade_callback; void *cb_user_arg; volatile ledc_fade_fsm_t fsm; @@ -992,7 +990,7 @@ static esp_err_t ledc_fade_channel_deinit(ledc_mode_t speed_mode, ledc_channel_t s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = NULL; } if (s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem) { - vSemaphoreDelete(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem); + vSemaphoreDeleteWithCaps(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem); s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = NULL; } free(s_ledc_fade_rec[speed_mode][channel]); @@ -1008,23 +1006,13 @@ static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_chann return ESP_FAIL; } if (s_ledc_fade_rec[speed_mode][channel] == NULL) { -#if CONFIG_SPIRAM_USE_MALLOC + // Always malloc internally since LEDC ISR is always placed in IRAM s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) heap_caps_calloc(1, sizeof(ledc_fade_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (s_ledc_fade_rec[speed_mode][channel] == NULL) { ledc_fade_channel_deinit(speed_mode, channel); return ESP_ERR_NO_MEM; } - - memset(&s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem_storage, 0, sizeof(StaticQueue_t)); - s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinaryStatic(&s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem_storage); -#else - s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) calloc(1, sizeof(ledc_fade_t)); - if (s_ledc_fade_rec[speed_mode][channel] == NULL) { - ledc_fade_channel_deinit(speed_mode, channel); - return ESP_ERR_NO_MEM; - } - s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinary(); -#endif + s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinaryWithCaps(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = xSemaphoreCreateMutex(); xSemaphoreGive(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem); s_ledc_fade_rec[speed_mode][channel]->fsm = LEDC_FSM_IDLE; diff --git a/components/driver/test_apps/ledc/main/CMakeLists.txt b/components/driver/test_apps/ledc/main/CMakeLists.txt index 88d1d6cfbb4a..146642e5d3ee 100644 --- a/components/driver/test_apps/ledc/main/CMakeLists.txt +++ b/components/driver/test_apps/ledc/main/CMakeLists.txt @@ -4,5 +4,5 @@ set(srcs "test_app_main.c" # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity driver esp_timer + PRIV_REQUIRES unity driver esp_timer esp_psram WHOLE_ARCHIVE) diff --git a/components/driver/test_apps/ledc/pytest_ledc.py b/components/driver/test_apps/ledc/pytest_ledc.py index 4e9f75f0cef5..5d4daa5beb40 100644 --- a/components/driver/test_apps/ledc/pytest_ledc.py +++ b/components/driver/test_apps/ledc/pytest_ledc.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest @@ -6,6 +6,7 @@ @pytest.mark.supported_targets +@pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_ledc_psram') @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -17,3 +18,17 @@ ) def test_ledc(dut: IdfDut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.esp32s3 +@pytest.mark.octal_psram +@pytest.mark.parametrize( + 'config', + [ + 'iram_safe', + 'release', + ], + indirect=True, +) +def test_ledc_psram(dut: IdfDut) -> None: + dut.run_all_single_board_cases() diff --git a/components/driver/test_apps/ledc/sdkconfig.defaults.esp32s3 b/components/driver/test_apps/ledc/sdkconfig.defaults.esp32s3 new file mode 100644 index 000000000000..24336a0742ef --- /dev/null +++ b/components/driver/test_apps/ledc/sdkconfig.defaults.esp32s3 @@ -0,0 +1,4 @@ +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 From 66821f699ce1579b661818b141a9172f8e32262e Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 21 Sep 2023 19:27:43 +0800 Subject: [PATCH 120/142] refactor(ledc): move related kconfig and linker.lf to its own folder --- components/driver/CMakeLists.txt | 2 ++ components/driver/Kconfig | 10 +--------- components/driver/ledc/Kconfig.ledc | 11 +++++++++++ components/driver/ledc/linker.lf | 12 ++++++++++++ components/driver/linker.lf | 4 ---- components/driver/test_apps/ledc/sdkconfig.defaults | 2 +- components/hal/linker.lf | 2 -- 7 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 components/driver/ledc/Kconfig.ledc create mode 100644 components/driver/ledc/linker.lf diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 6af58de63da9..c3d8a35c4e27 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -125,6 +125,8 @@ endif() # LEDC related source files if(CONFIG_SOC_LEDC_SUPPORTED) list(APPEND srcs "ledc/ledc.c") + + list(APPEND ldfragments "ledc/linker.lf") endif() # MCPWM related source files diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 65f29bd8e7e3..174904903c6a 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -409,15 +409,7 @@ menu "Driver Configurations" endmenu # Parallel IO Configuration - menu "LEDC Configuration" - config LEDC_CTRL_FUNC_IN_IRAM - bool "Place LEDC control functions into IRAM" - default n - help - Place LEDC control functions (ledc_update_duty and ledc_stop) into IRAM, - so that these functions can be IRAM-safe and able to be called in an IRAM context. - Enabling this option can improve driver performance as well. - endmenu # LEDC Configuration + orsource "./ledc/Kconfig.ledc" menu "I2C Configuration" config I2C_ISR_IRAM_SAFE diff --git a/components/driver/ledc/Kconfig.ledc b/components/driver/ledc/Kconfig.ledc new file mode 100644 index 000000000000..74f8b7a37b5b --- /dev/null +++ b/components/driver/ledc/Kconfig.ledc @@ -0,0 +1,11 @@ +menu "LEDC Configuration" + + config LEDC_CTRL_FUNC_IN_IRAM + bool "Place LEDC control functions into IRAM" + default n + help + Place LEDC control functions (ledc_update_duty and ledc_stop) into IRAM, + so that these functions can be IRAM-safe and able to be called in an IRAM context. + Enabling this option can improve driver performance as well. + +endmenu # LEDC Configuration diff --git a/components/driver/ledc/linker.lf b/components/driver/ledc/linker.lf new file mode 100644 index 000000000000..4119b65081de --- /dev/null +++ b/components/driver/ledc/linker.lf @@ -0,0 +1,12 @@ +[mapping:ledc_driver] +archive: libdriver.a +entries: + if LEDC_CTRL_FUNC_IN_IRAM = y: + ledc: ledc_stop (noflash) + ledc: ledc_update_duty (noflash) + ledc: _ledc_update_duty (noflash) + +[mapping:ledc_hal] +archive: libhal.a +entries: + ledc_hal_iram (noflash) diff --git a/components/driver/linker.lf b/components/driver/linker.lf index 9c69a76c5cdd..ae09bf19a9c3 100644 --- a/components/driver/linker.lf +++ b/components/driver/linker.lf @@ -15,7 +15,3 @@ entries: if DAC_CTRL_FUNC_IN_IRAM = y: dac_oneshot: dac_oneshot_output_voltage (noflash) dac_continuous: dac_continuous_write_asynchronously (noflash) - if LEDC_CTRL_FUNC_IN_IRAM = y: - ledc: ledc_stop (noflash) - ledc: ledc_update_duty (noflash) - ledc: _ledc_update_duty (noflash) diff --git a/components/driver/test_apps/ledc/sdkconfig.defaults b/components/driver/test_apps/ledc/sdkconfig.defaults index 8b3c17e0e008..568a2ae79fc7 100644 --- a/components/driver/test_apps/ledc/sdkconfig.defaults +++ b/components/driver/test_apps/ledc/sdkconfig.defaults @@ -1,4 +1,4 @@ CONFIG_FREERTOS_HZ=1000 -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_INIT=n # Disable memory protection, because "LEDC continue work after software reset" test case requires a cpu reset CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n diff --git a/components/hal/linker.lf b/components/hal/linker.lf index c36d4a2d5e87..b2d5f76a76cc 100644 --- a/components/hal/linker.lf +++ b/components/hal/linker.lf @@ -14,8 +14,6 @@ entries: spi_hal_iram (noflash) if HAL_SPI_SLAVE_FUNC_IN_IRAM = y: spi_slave_hal_iram (noflash) - if SOC_LEDC_SUPPORTED = y: - ledc_hal_iram (noflash) if SOC_I2C_SUPPORTED = y: i2c_hal_iram (noflash) if HAL_WDT_USE_ROM_IMPL = n: From c75fab3fa407ec461a02154bc0b8fa2599a48202 Mon Sep 17 00:00:00 2001 From: Bogdan Kolendovskyy Date: Mon, 25 Sep 2023 11:29:51 +0200 Subject: [PATCH 121/142] esp_eth: change rtl8201 reset timing to match datasheet In esp_eth_phy_rtl8201.c: Add 150ms delay after hardware reset, chage reset assertion time to 10ms In esp_eth_phy_802_3.c: Change reset function to use vTaskDelay for long (>=10ms) reset assertion time Change esp_eth_phy_802_3_detect_phy_addr to check range 0-31 instead of 0-15. --- components/esp_eth/src/esp_eth_phy_802_3.c | 10 +++++++--- components/esp_eth/src/esp_eth_phy_rtl8201.c | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/components/esp_eth/src/esp_eth_phy_802_3.c b/components/esp_eth/src/esp_eth_phy_802_3.c index 4157f02011d9..51a10fd55182 100644 --- a/components/esp_eth/src/esp_eth_phy_802_3.c +++ b/components/esp_eth/src/esp_eth_phy_802_3.c @@ -366,7 +366,11 @@ esp_err_t esp_eth_phy_802_3_reset_hw(phy_802_3_t *phy_802_3, uint32_t reset_asse esp_rom_gpio_pad_select_gpio(phy_802_3->reset_gpio_num); gpio_set_direction(phy_802_3->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(phy_802_3->reset_gpio_num, 0); - esp_rom_delay_us(reset_assert_us); + if (reset_assert_us < 10000) { + esp_rom_delay_us(reset_assert_us); + } else { + vTaskDelay(pdMS_TO_TICKS(reset_assert_us/1000)); + } gpio_set_level(phy_802_3->reset_gpio_num, 1); } return ESP_OK; @@ -380,14 +384,14 @@ esp_err_t esp_eth_phy_802_3_detect_phy_addr(esp_eth_mediator_t *eth, int *detect } int addr_try = 0; uint32_t reg_value = 0; - for (; addr_try < 16; addr_try++) { + for (; addr_try < 32; addr_try++) { eth->phy_reg_read(eth, addr_try, ETH_PHY_IDR1_REG_ADDR, ®_value); if (reg_value != 0xFFFF && reg_value != 0x00) { *detected_addr = addr_try; break; } } - if (addr_try < 16) { + if (addr_try < 32) { ESP_LOGD(TAG, "Found PHY address: %d", addr_try); 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 1464fc6acfe6..4f3a9337b4fa 100644 --- a/components/esp_eth/src/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/esp_eth_phy_rtl8201.c @@ -9,8 +9,13 @@ #include #include "esp_log.h" #include "esp_check.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_eth_phy_802_3.h" +#define RTL8201_PHY_RESET_ASSERTION_TIME_US 10000 +#define RTL8201_PHY_POST_RESET_INIT_TIME_MS 150 + static const char *TAG = "rtl8201"; /***************Vendor Specific Register***************/ @@ -144,6 +149,15 @@ static esp_err_t rtl8201_loopback(esp_eth_phy_t *phy, bool enable) return ret; } +static esp_err_t rtl8201_reset_hw(esp_eth_phy_t *phy) +{ + phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); + esp_err_t ret = esp_eth_phy_802_3_reset_hw(phy_802_3, RTL8201_PHY_RESET_ASSERTION_TIME_US); + vTaskDelay(pdMS_TO_TICKS(RTL8201_PHY_POST_RESET_INIT_TIME_MS)); + return ret; +} + + static esp_err_t rtl8201_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -177,6 +191,7 @@ esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config) rtl8201->phy_802_3.parent.get_link = rtl8201_get_link; rtl8201->phy_802_3.parent.autonego_ctrl = rtl8201_autonego_ctrl; rtl8201->phy_802_3.parent.loopback = rtl8201_loopback; + rtl8201->phy_802_3.parent.reset_hw = rtl8201_reset_hw; return &rtl8201->phy_802_3.parent; err: From 28b8a5d9b4343c5f34de633ec8bab01f93eadd8b Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Fri, 15 Sep 2023 23:10:41 +0800 Subject: [PATCH 122/142] fix(esp_system): Fix mixing logs, remove early info logs for 2nd CPU Fixes mixing logs when two cores use esp_rom_printf --- components/esp_system/port/cpu_start.c | 7 +++---- components/freertos/app_startup.c | 4 ++-- .../system/ram_loadable_app/pytest_ram_loadable_app.py | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 484609959616..b5c0fb417ec0 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -233,7 +233,7 @@ void IRAM_ATTR call_start_cpu1(void) #endif s_cpu_up[1] = true; - ESP_EARLY_LOGI(TAG, "App cpu up."); + ESP_EARLY_LOGD(TAG, "App cpu up"); // Clear interrupt matrix for APP CPU core core_intr_matrix_clear(); @@ -271,7 +271,7 @@ static void start_other_core(void) abort(); } - ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1); + ESP_EARLY_LOGD(TAG, "Starting app cpu, entry point is %p", call_start_cpu1); #if CONFIG_IDF_TARGET_ESP32 && !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP Cache_Flush(1); @@ -315,7 +315,6 @@ static void start_other_core(void) for (int i = 0; i < SOC_CPU_CORES_NUM; i++) { cpus_up &= s_cpu_up[i]; } - //TODO: IDF-7891, check mixing logs esp_rom_delay_us(100); } } @@ -571,7 +570,7 @@ void IRAM_ATTR call_start_cpu0(void) s_cpu_up[0] = true; #endif - ESP_EARLY_LOGI(TAG, "Pro cpu up."); + ESP_EARLY_LOGD(TAG, "Pro cpu up"); #if SOC_CPU_CORES_NUM > 1 // there is no 'single-core mode' for natively single-core processors #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE diff --git a/components/freertos/app_startup.c b/components/freertos/app_startup.c index e716eed7c614..b9b60ff47b1b 100644 --- a/components/freertos/app_startup.c +++ b/components/freertos/app_startup.c @@ -96,7 +96,7 @@ void esp_startup_start_app(void) port_start_app_hook(); } - ESP_EARLY_LOGI(APP_START_TAG, "Starting scheduler on CPU0"); + ESP_EARLY_LOGD(APP_START_TAG, "Starting scheduler on CPU0"); vTaskStartScheduler(); } @@ -130,7 +130,7 @@ void esp_startup_start_app_other_cores(void) // Initialize the cross-core interrupt on CPU1 esp_crosscore_int_init(); - ESP_EARLY_LOGI(APP_START_TAG, "Starting scheduler on CPU%d", xPortGetCoreID()); + ESP_EARLY_LOGD(APP_START_TAG, "Starting scheduler on CPU%d", xPortGetCoreID()); xPortStartScheduler(); abort(); // Only get to here if FreeRTOS somehow very broken } diff --git a/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py index 2d3eb0e22397..71953f16f266 100644 --- a/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py +++ b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py @@ -14,7 +14,7 @@ @pytest.mark.generic @pytest.mark.parametrize('config', ['pure_ram',], indirect=True,) def test_pure_ram_loadable_app(dut: IdfDut) -> None: - dut.expect('app_start: Starting scheduler', timeout=10) + dut.expect('main_task: Calling app_main()', timeout=10) dut.expect('Time since boot: 3 seconds...', timeout=10) From 37c7c5b58d6621fdb5177e91963a8274440efbc2 Mon Sep 17 00:00:00 2001 From: Marek Fiala Date: Tue, 5 Sep 2023 11:09:52 +0200 Subject: [PATCH 123/142] feat(tools): Add shellcheck for shell scripts to CI - shellcheck fixes in shell scripts --- .pre-commit-config.yaml | 11 +++++++++++ .shellcheckrc | 5 +++++ export.sh | 7 ++++--- install.sh | 10 ++++++---- 4 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 .shellcheckrc diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a1964a9c9766..773f183388b2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -208,3 +208,14 @@ repos: - id: astyle_py # If you are modifying astyle version, update tools/format.sh as well args: ['--astyle-version=3.4.7', '--rules=tools/ci/astyle-rules.yml'] + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.9.0.5 + hooks: + - id: shellcheck + name: shellcheck bash + args: ['--shell', 'bash', '-x'] + files: 'install.sh|export.sh' + - id: shellcheck + name: shellcheck dash (export.sh) + args: ['--shell', 'dash', '-x'] + files: 'export.sh' diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 000000000000..4b9f5f36b864 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,5 @@ +# This is shellcheck config file +# Files that are checked: install.sh, export.sh + +# Do not complain about variables determined at runtime (IDF_PATH) +disable=SC1090 diff --git a/export.sh b/export.sh index 4ef6ff84d963..d658b22eaa34 100644 --- a/export.sh +++ b/export.sh @@ -65,6 +65,7 @@ __main() { self_path="${BASH_SOURCE}" elif [ -n "${ZSH_VERSION-}" ] then + # shellcheck disable=SC2296 # ignore parameter starts with '{' because it's zsh self_path="${(%):-%x}" fi @@ -138,7 +139,7 @@ __main() { if [ -n "$BASH" ] then - path_prefix=${PATH%%${old_path}} + path_prefix="${PATH%%"${old_path}"}" # shellcheck disable=SC2169,SC2039 # unreachable with 'dash' if [ -n "${path_prefix}" ]; then __verbose "Added the following directories to PATH:" @@ -201,7 +202,7 @@ __cleanup() { # Not unsetting IDF_PYTHON_ENV_PATH, it can be used by IDF build system # to check whether we are using a private Python environment - return $1 + return "$1" } @@ -222,7 +223,7 @@ __enable_autocomplete() { elif [ -n "${BASH_SOURCE-}" ] then WARNING_MSG="WARNING: Failed to load shell autocompletion for bash version: $BASH_VERSION!" - # shellcheck disable=SC3028,SC3054,SC2086 # code block for 'bash' only + # shellcheck disable=SC3028,SC3054,SC2086,SC2169 # code block for 'bash' only [ ${BASH_VERSINFO[0]} -lt 4 ] && { echo "$WARNING_MSG"; return; } eval "$(env LANG=en _IDF.PY_COMPLETE=$SOURCE_BASH idf.py)" || echo "$WARNING_MSG" fi diff --git a/install.sh b/install.sh index 2206eeff34c0..868665c527d5 100755 --- a/install.sh +++ b/install.sh @@ -18,18 +18,20 @@ while getopts ":h" option; do h) "${ESP_PYTHON}" "${IDF_PATH}/tools/install_util.py" print_help sh exit;; + \?) + ;; esac done -TARGETS=`"${ESP_PYTHON}" "${IDF_PATH}/tools/install_util.py" extract targets "$@"` +TARGETS=$("${ESP_PYTHON}" "${IDF_PATH}/tools/install_util.py" extract targets "$@") echo "Installing ESP-IDF tools" -"${ESP_PYTHON}" "${IDF_PATH}/tools/idf_tools.py" install --targets=${TARGETS} +"${ESP_PYTHON}" "${IDF_PATH}/tools/idf_tools.py" install --targets="${TARGETS}" -FEATURES=`"${ESP_PYTHON}" "${IDF_PATH}/tools/install_util.py" extract features "$@"` +FEATURES=$("${ESP_PYTHON}" "${IDF_PATH}/tools/install_util.py" extract features "$@") echo "Installing Python environment and packages" -"${ESP_PYTHON}" "${IDF_PATH}/tools/idf_tools.py" install-python-env --features=${FEATURES} +"${ESP_PYTHON}" "${IDF_PATH}/tools/idf_tools.py" install-python-env --features="${FEATURES}" echo "All done! You can now run:" echo "" From addbc79ee771faa43e962444c961bf4cc289fba1 Mon Sep 17 00:00:00 2001 From: Marek Fiala Date: Tue, 3 Oct 2023 13:35:06 +0200 Subject: [PATCH 124/142] refactor(tools): shellcheck pass modification Closes https://github.com/espressif/esp-idf/pull/12247 --- export.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/export.sh b/export.sh index e9c83866f567..4db5e1b76d15 100644 --- a/export.sh +++ b/export.sh @@ -19,7 +19,7 @@ __verbose() { __script_dir(){ # shellcheck disable=SC2169,SC2169,SC2039,SC3010,SC3028 # unreachable with 'dash' - if [ `uname -s` = "Darwin" ]; then + if [ "$(uname -s)" = "Darwin" ]; then # convert possibly relative path to absolute script_dir="$(__realpath "${self_path}")" # resolve any ../ references to make the path shorter From ff87a0061cdfcfe72cb9e8e95b40282952454f10 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 27 Sep 2023 20:18:51 +0200 Subject: [PATCH 125/142] feat(wpa_supplicant): migrate the tests from unit-test-app --- components/wpa_supplicant/test/CMakeLists.txt | 14 ------ .../test_apps/.build-test-rules.yml | 11 +++++ .../wpa_supplicant/test_apps/CMakeLists.txt | 9 ++++ components/wpa_supplicant/test_apps/README.md | 19 ++++++++ .../test_apps/main/CMakeLists.txt | 25 ++++++++++ .../test_apps/main/idf_component.yml | 3 ++ .../{test => test_apps/main}/test_crypto.c | 0 .../{test => test_apps/main}/test_dpp.c | 2 +- .../{test => test_apps/main}/test_eloop.c | 0 .../main}/test_fast_pbkdf2.c | 0 .../main}/test_offchannel.c | 2 +- .../{test => test_apps/main}/test_sae.c | 2 +- .../main/test_wpa_supplicant_common.h | 21 ++++++++ .../test_apps/main/test_wpa_supplicant_main.c | 48 +++++++++++++++++++ .../test_apps/pytest_wpa_supplicant_ut.py | 25 ++++++++++ .../test_apps/sdkconfig.defaults | 5 ++ 16 files changed, 169 insertions(+), 17 deletions(-) delete mode 100644 components/wpa_supplicant/test/CMakeLists.txt create mode 100644 components/wpa_supplicant/test_apps/.build-test-rules.yml create mode 100644 components/wpa_supplicant/test_apps/CMakeLists.txt create mode 100644 components/wpa_supplicant/test_apps/README.md create mode 100644 components/wpa_supplicant/test_apps/main/CMakeLists.txt create mode 100644 components/wpa_supplicant/test_apps/main/idf_component.yml rename components/wpa_supplicant/{test => test_apps/main}/test_crypto.c (100%) rename components/wpa_supplicant/{test => test_apps/main}/test_dpp.c (98%) rename components/wpa_supplicant/{test => test_apps/main}/test_eloop.c (100%) rename components/wpa_supplicant/{test => test_apps/main}/test_fast_pbkdf2.c (100%) rename components/wpa_supplicant/{test => test_apps/main}/test_offchannel.c (99%) rename components/wpa_supplicant/{test => test_apps/main}/test_sae.c (99%) create mode 100644 components/wpa_supplicant/test_apps/main/test_wpa_supplicant_common.h create mode 100644 components/wpa_supplicant/test_apps/main/test_wpa_supplicant_main.c create mode 100644 components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py create mode 100644 components/wpa_supplicant/test_apps/sdkconfig.defaults diff --git a/components/wpa_supplicant/test/CMakeLists.txt b/components/wpa_supplicant/test/CMakeLists.txt deleted file mode 100644 index 99377e598e8c..000000000000 --- a/components/wpa_supplicant/test/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -idf_component_register(SRC_DIRS "." - PRIV_INCLUDE_DIRS "." "${CMAKE_CURRENT_BINARY_DIR}" - PRIV_INCLUDE_DIRS "../src" "../esp_supplicant/src" - PRIV_REQUIRES cmock esp_common test_utils wpa_supplicant mbedtls esp_wifi esp_event) - -idf_component_get_property(esp_supplicant_dir wpa_supplicant COMPONENT_DIR) - -# Calculate MD5 value of header file esp_wifi_driver.h -file(MD5 ${esp_supplicant_dir}/esp_supplicant/src/esp_wifi_driver.h WIFI_SUPPLICANT_MD5) -string(SUBSTRING "${WIFI_SUPPLICANT_MD5}" 0 7 WIFI_SUPPLICANT_MD5) - -add_definitions(-DWIFI_SUPPLICANT_MD5=\"${WIFI_SUPPLICANT_MD5}\") -add_definitions(-DCONFIG_WPA3_SAE) -add_definitions(-DCONFIG_DPP) diff --git a/components/wpa_supplicant/test_apps/.build-test-rules.yml b/components/wpa_supplicant/test_apps/.build-test-rules.yml new file mode 100644 index 000000000000..6013a2343cba --- /dev/null +++ b/components/wpa_supplicant/test_apps/.build-test-rules.yml @@ -0,0 +1,11 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/wpa_supplicant/test_apps: + disable: + - if: SOC_WIFI_SUPPORTED != 1 + depends_components: + - esp_wifi + - wpa_supplicant + - mbedtls + - esp_timer + - esp_event diff --git a/components/wpa_supplicant/test_apps/CMakeLists.txt b/components/wpa_supplicant/test_apps/CMakeLists.txt new file mode 100644 index 000000000000..bbfb3f8b9fd6 --- /dev/null +++ b/components/wpa_supplicant/test_apps/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) +list(PREPEND SDKCONFIG_DEFAULTS + "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers" + "sdkconfig.defaults") + +project(wpa_supplicant_test) diff --git a/components/wpa_supplicant/test_apps/README.md b/components/wpa_supplicant/test_apps/README.md new file mode 100644 index 000000000000..3fa2378f0005 --- /dev/null +++ b/components/wpa_supplicant/test_apps/README.md @@ -0,0 +1,19 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | + +# wpa_supplicant unit test + +To build and run this test app, using esp32s3 target for example: + +```bash +idf.py set-target esp32s3 +idf.py build flash monitor +``` + +To run tests using pytest: + +```bash +idf.py set-target esp32s3 +idf.py build +pytest --target=esp32s3 +``` diff --git a/components/wpa_supplicant/test_apps/main/CMakeLists.txt b/components/wpa_supplicant/test_apps/main/CMakeLists.txt new file mode 100644 index 000000000000..5dcdf7b250ea --- /dev/null +++ b/components/wpa_supplicant/test_apps/main/CMakeLists.txt @@ -0,0 +1,25 @@ +idf_component_register(SRCS + "test_crypto.c" + "test_dpp.c" + "test_eloop.c" + "test_fast_pbkdf2.c" + "test_offchannel.c" + "test_sae.c" + "test_wpa_supplicant_main.c" + PRIV_INCLUDE_DIRS "." + PRIV_REQUIRES wpa_supplicant mbedtls esp_wifi esp_event unity + WHOLE_ARCHIVE) + +idf_component_get_property(esp_supplicant_dir wpa_supplicant COMPONENT_DIR) + +# Calculate MD5 value of header file esp_wifi_driver.h +file(MD5 ${esp_supplicant_dir}/esp_supplicant/src/esp_wifi_driver.h WIFI_SUPPLICANT_MD5) +string(SUBSTRING "${WIFI_SUPPLICANT_MD5}" 0 7 WIFI_SUPPLICANT_MD5) + +# Steal some private include directories from wpa_supplicant +target_include_directories(${COMPONENT_LIB} PRIVATE ${esp_supplicant_dir}/esp_supplicant/src) +target_include_directories(${COMPONENT_LIB} PRIVATE ${esp_supplicant_dir}/src) + +add_definitions(-DWIFI_SUPPLICANT_MD5=\"${WIFI_SUPPLICANT_MD5}\") +add_definitions(-DCONFIG_WPA3_SAE) +add_definitions(-DCONFIG_DPP) diff --git a/components/wpa_supplicant/test_apps/main/idf_component.yml b/components/wpa_supplicant/test_apps/main/idf_component.yml new file mode 100644 index 000000000000..f5001494e215 --- /dev/null +++ b/components/wpa_supplicant/test_apps/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + test_utils: + path: ${IDF_PATH}/tools/unit-test-app/components/test_utils diff --git a/components/wpa_supplicant/test/test_crypto.c b/components/wpa_supplicant/test_apps/main/test_crypto.c similarity index 100% rename from components/wpa_supplicant/test/test_crypto.c rename to components/wpa_supplicant/test_apps/main/test_crypto.c diff --git a/components/wpa_supplicant/test/test_dpp.c b/components/wpa_supplicant/test_apps/main/test_dpp.c similarity index 98% rename from components/wpa_supplicant/test/test_dpp.c rename to components/wpa_supplicant/test_apps/main/test_dpp.c index d9eb32732bcf..af8d2460ad50 100644 --- a/components/wpa_supplicant/test/test_dpp.c +++ b/components/wpa_supplicant/test_apps/main/test_dpp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/wpa_supplicant/test/test_eloop.c b/components/wpa_supplicant/test_apps/main/test_eloop.c similarity index 100% rename from components/wpa_supplicant/test/test_eloop.c rename to components/wpa_supplicant/test_apps/main/test_eloop.c diff --git a/components/wpa_supplicant/test/test_fast_pbkdf2.c b/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c similarity index 100% rename from components/wpa_supplicant/test/test_fast_pbkdf2.c rename to components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c diff --git a/components/wpa_supplicant/test/test_offchannel.c b/components/wpa_supplicant/test_apps/main/test_offchannel.c similarity index 99% rename from components/wpa_supplicant/test/test_offchannel.c rename to components/wpa_supplicant/test_apps/main/test_offchannel.c index 126b2844fef2..5ddc0f082fc5 100644 --- a/components/wpa_supplicant/test/test_offchannel.c +++ b/components/wpa_supplicant/test_apps/main/test_offchannel.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 * diff --git a/components/wpa_supplicant/test/test_sae.c b/components/wpa_supplicant/test_apps/main/test_sae.c similarity index 99% rename from components/wpa_supplicant/test/test_sae.c rename to components/wpa_supplicant/test_apps/main/test_sae.c index 3c14d14c4b2e..ec13d144fc82 100644 --- a/components/wpa_supplicant/test/test_sae.c +++ b/components/wpa_supplicant/test_apps/main/test_sae.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/wpa_supplicant/test_apps/main/test_wpa_supplicant_common.h b/components/wpa_supplicant/test_apps/main/test_wpa_supplicant_common.h new file mode 100644 index 000000000000..a13ab4c2554b --- /dev/null +++ b/components/wpa_supplicant/test_apps/main/test_wpa_supplicant_common.h @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set the leak threshold value for the specific test case + * + * @param threshold Maximum allowed memory leak in bytes + */ +void set_leak_threshold(int threshold); + +#ifdef __cplusplus +} +#endif diff --git a/components/wpa_supplicant/test_apps/main/test_wpa_supplicant_main.c b/components/wpa_supplicant/test_apps/main/test_wpa_supplicant_main.c new file mode 100644 index 000000000000..833d9ba3f003 --- /dev/null +++ b/components/wpa_supplicant/test_apps/main/test_wpa_supplicant_main.c @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "esp_heap_caps.h" + +#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT 0 +static int leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT; +void set_leak_threshold(int threshold) +{ + leak_threshold = -threshold; +} + +static size_t before_free_8bit; +static size_t before_free_32bit; + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d, threshold %d)\n", type, before_free, after_free, delta, leak_threshold); + TEST_ASSERT_MESSAGE(delta > leak_threshold, "memory leak"); +} + +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); + + leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT; +} + +void app_main(void) +{ + printf("Running wpa_supplicant component tests\n"); + unity_run_menu(); +} diff --git a/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py b/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py new file mode 100644 index 000000000000..f2d647ed70eb --- /dev/null +++ b/components/wpa_supplicant/test_apps/pytest_wpa_supplicant_ut.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from idf_unity_tester import CaseTester +from pytest_embedded import Dut + + +@pytest.mark.generic +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c3 +@pytest.mark.esp32c2 +@pytest.mark.esp32c6 +def test_wpa_supplicant_ut(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32 +@pytest.mark.wifi_two_dut +def test_wpa_supplicant_ut_offchan(case_tester: CaseTester) -> None: + for case in case_tester.test_menu: + if case.attributes.get('test_env') == 'wifi_two_dut': + case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/wpa_supplicant/test_apps/sdkconfig.defaults b/components/wpa_supplicant/test_apps/sdkconfig.defaults new file mode 100644 index 000000000000..94128e903475 --- /dev/null +++ b/components/wpa_supplicant/test_apps/sdkconfig.defaults @@ -0,0 +1,5 @@ +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n +CONFIG_ESP_WIFI_TESTING_OPTIONS=y +CONFIG_ESP_WIFI_DPP_SUPPORT=y +CONFIG_WPA3_SAE=y From 6e22dc2fe2f40ce25990d523d5ce1e1a95c4ce57 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:43:15 +0200 Subject: [PATCH 126/142] ci(wpa_supplicant): set leak thresholds in test_crypto --- components/wpa_supplicant/test_apps/main/test_crypto.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/wpa_supplicant/test_apps/main/test_crypto.c b/components/wpa_supplicant/test_apps/main/test_crypto.c index d0460d5293ec..e7b5a2159b24 100644 --- a/components/wpa_supplicant/test_apps/main/test_crypto.c +++ b/components/wpa_supplicant/test_apps/main/test_crypto.c @@ -16,11 +16,13 @@ #include "mbedtls/ecp.h" #include "test_utils.h" +#include "test_wpa_supplicant_common.h" typedef struct crypto_bignum crypto_bignum; TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]") { + set_leak_threshold(250); { uint8_t buf[32], buf2[32]; @@ -331,6 +333,7 @@ static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]") { + set_leak_threshold(600); static const mbedtls_mpi_uint secp256r1_gx[] = { BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), From b9952370b45500acbca23de8559c5b2f7bd6a8bd Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:45:24 +0200 Subject: [PATCH 127/142] change(wpa_supplicant): reformat test_dpp with astyle --- .../wpa_supplicant/test_apps/main/test_dpp.c | 279 +++++++++--------- 1 file changed, 142 insertions(+), 137 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_dpp.c b/components/wpa_supplicant/test_apps/main/test_dpp.c index af8d2460ad50..72e16c4a649d 100644 --- a/components/wpa_supplicant/test_apps/main/test_dpp.c +++ b/components/wpa_supplicant/test_apps/main/test_dpp.c @@ -19,9 +19,9 @@ #ifdef CONFIG_ESP_WIFI_TESTING_OPTIONS struct dpp_global { - void *msg_ctx; - struct dl_list bootstrap; /* struct dpp_bootstrap_info */ - struct dl_list configurator; /* struct dpp_configurator */ + void *msg_ctx; + struct dl_list bootstrap; /* struct dpp_bootstrap_info */ + struct dl_list configurator; /* struct dpp_configurator */ }; extern u8 dpp_protocol_key_override[600]; @@ -32,139 +32,144 @@ extern size_t dpp_nonce_override_len; TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]") { - /* Global variables */ - char command[1200] = {0}; - const u8 *frame; - int len = 0; - struct dpp_authentication *auth_instance = NULL; - u8 auth[MAX_FRAME_SIZE] = {0}; - char prefix[] = "30310201010420"; - char postfix[] = "a00a06082a8648ce3d030107"; - size_t hex_len; - int ret = 0; - int id; - - /* DPP global config initialization */ - struct dpp_global_config dpp_conf; - memset(&dpp_conf, 0, sizeof(dpp_conf)); - struct dpp_global *dpp = dpp_global_init(&dpp_conf); - - /* bootstrap generation test */ - ESP_LOGI("DPP Test", "bootstrap generation test"); - { - char key[1000] = {0}; - const char *uri; - - char private_bootstrap_key[] = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0"; - char bootstrap_info[] = "DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgACCcWFqRtN+f0loEUgGIXDnMXPrjl92u2pV97Ff6DjUD8=;;"; - - sprintf(key, "%s%s%s", prefix, private_bootstrap_key, postfix); - - sprintf(command, "type=qrcode key=%s", key); - id = dpp_bootstrap_gen(dpp, command); - uri = dpp_bootstrap_get_uri(dpp, id); - printf("uri is =%s\n", uri); - printf("is be =%s\n", bootstrap_info); - TEST_ASSERT((strcmp(uri, bootstrap_info) == 0)); - } - ESP_LOGI("DPP Test", "bootstap generation passed"); - ESP_LOGI("DPP Test", "Overwrite Protocol key, responder nounce"); - { - char protocol_key[] = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5"; - char nounce[] = "3d0cfb011ca916d796f7029ff0b43393"; - - /* Overwrite protocol key */ - memset(command, 0, 1200); - sprintf(command, "%s%s%s", prefix, protocol_key, postfix); - - hex_len = os_strlen(command); - ret = 0; - - if (hex_len > 2 * sizeof(dpp_protocol_key_override)) - ret = -1; - else if (hexstr2bin(command, dpp_protocol_key_override, - hex_len / 2)) - ret = -1; - else - dpp_protocol_key_override_len = hex_len / 2; - - TEST_ASSERT(ret == 0); - - /* Overwrite nounce */ - hex_len = os_strlen(nounce); - - if (hex_len > 2 * sizeof(dpp_nonce_override)) - ret = -1; - else if (hexstr2bin(nounce, dpp_nonce_override, hex_len / 2)) - ret = -1; - else - dpp_nonce_override_len = hex_len / 2; - - TEST_ASSERT(ret == 0); - - } - ESP_LOGI("DPP Test", "Overwritten Protocol key, responder nounce.. "); - ESP_LOGI("DPP Test", "Enqueue Auth request"); - { - char auth_req[] = "d00012001ac459c40d649f8664c1b8771ac459c40d6400120409506f9a1a010002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d011020005d467a09760292fc15d31792b0a5b050db8bf6ad807d71b2d93f4d1c2e65d8810310400050a532ae2a07207276418d2fa630295d45569be425aa634f02014d00a7d1f61ae14f35a5a858bccad90d126c46594c49ef82655e78888e15a32d916ac217249118100200510104102900868f478fc599ac3fa8152b975eff8be4e71b189dbefbc3185b1d7f3864e896f913cba3d9601326f278"; - - char auth_resp[] = "d00012349f8664c1b8771ac459c40d649f8664c1b87712340409506f9a1a0101001001000002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d091040005e3fb3576884887f17c3203d8a3a6c2fac722ef0e2201b61ac73bc655c709a902d4b030669fb9eff8b0a79fa7c1a172ac2a92c626256963f9274dc90682c81e504107500da553cdf80da3e27054c5e1f809ac303c63948b9bb5690ad12f357d75dfbc362cbae89e472dd6851925534024310aff5ae403831e98a7efc7deb9516164329c227039ae73c509147d156ae085f56c242bf7decc1f3b68d81697c6197453cb6faff7b062f7861073148052db539895bc6583d08b4aa"; - u8 *tmp; - - hex_len = os_strlen(auth_req); - if (hex_len > 2 * MAX_FRAME_SIZE) - ret = -1; - else if (hexstr2bin(auth_req, auth, hex_len / 2)) - ret = -1; - else - len = hex_len / 2; - frame = auth; - frame += 26; - len -= 26; - auth_instance = dpp_auth_req_rx(NULL, 1, 0 , NULL, - dpp_bootstrap_get_id(dpp, id), 2412, frame, frame+6, len-6); - - /* auth response u8 */ - hex_len = os_strlen(auth_resp); - if (hex_len > 2 * MAX_FRAME_SIZE) - ret = -1; - else if (hexstr2bin(auth_resp, auth, hex_len / 2)) - ret = -1; - else - len = hex_len / 2; - tmp = auth; - tmp += 26; - len -= 26; - - frame = wpabuf_head_u8(auth_instance->resp_msg); - len = wpabuf_len(auth_instance->resp_msg); - - TEST_ASSERT(memcmp(frame + 28, tmp + 26, len - 26) == 0); - } - ESP_LOGI("DPP Test", "Auth request parsing passed"); - ESP_LOGI("DPP Test", "Enqueue Auth confirm parsing passed"); - { - char auth_confirm[] = "d00012341ac459c40d649f8664c1b8771ac459c40d6412340409506f9a1a0102001001000002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d0410340054e07e62c74526dfd97e029dc781e0771e573ebc73c94227b5de8350fc6a1974b40f54c9fe1a1c9288a91fce4ee6c1f2ff069741"; - hex_len = os_strlen(auth_confirm); - os_memset(auth, 0, 1200); - if (hex_len > 2 * MAX_FRAME_SIZE) - ret = -1; - else if (hexstr2bin(auth_confirm, auth, hex_len / 2)) - ret = -1; - else - len = hex_len / 2; - frame = auth; - frame = auth + 26; - len = len - 26; - dpp_auth_conf_rx(auth_instance, frame, frame+6, len-6); - TEST_ASSERT(auth_instance->auth_success == 1); - } - ESP_LOGI("DPP Test", "Auth confirm parsing passed"); - /* deinit for memory passing */ - { - dpp_auth_deinit(auth_instance); - dpp_global_deinit(dpp); - } - ESP_LOGI("DPP Test", "Test case passed"); + /* Global variables */ + char command[1200] = {0}; + const u8 *frame; + int len = 0; + struct dpp_authentication *auth_instance = NULL; + u8 auth[MAX_FRAME_SIZE] = {0}; + char prefix[] = "30310201010420"; + char postfix[] = "a00a06082a8648ce3d030107"; + size_t hex_len; + int ret = 0; + int id; + + /* DPP global config initialization */ + struct dpp_global_config dpp_conf; + memset(&dpp_conf, 0, sizeof(dpp_conf)); + struct dpp_global *dpp = dpp_global_init(&dpp_conf); + + /* bootstrap generation test */ + ESP_LOGI("DPP Test", "bootstrap generation test"); + { + char key[1000] = {0}; + const char *uri; + + char private_bootstrap_key[] = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0"; + char bootstrap_info[] = "DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgACCcWFqRtN+f0loEUgGIXDnMXPrjl92u2pV97Ff6DjUD8=;;"; + + sprintf(key, "%s%s%s", prefix, private_bootstrap_key, postfix); + + sprintf(command, "type=qrcode key=%s", key); + id = dpp_bootstrap_gen(dpp, command); + uri = dpp_bootstrap_get_uri(dpp, id); + printf("uri is =%s\n", uri); + printf("is be =%s\n", bootstrap_info); + TEST_ASSERT((strcmp(uri, bootstrap_info) == 0)); + } + ESP_LOGI("DPP Test", "bootstap generation passed"); + ESP_LOGI("DPP Test", "Overwrite Protocol key, responder nounce"); + { + char protocol_key[] = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5"; + char nounce[] = "3d0cfb011ca916d796f7029ff0b43393"; + + /* Overwrite protocol key */ + memset(command, 0, 1200); + sprintf(command, "%s%s%s", prefix, protocol_key, postfix); + + hex_len = os_strlen(command); + ret = 0; + + if (hex_len > 2 * sizeof(dpp_protocol_key_override)) { + ret = -1; + } else if (hexstr2bin(command, dpp_protocol_key_override, + hex_len / 2)) { + ret = -1; + } else { + dpp_protocol_key_override_len = hex_len / 2; + } + + TEST_ASSERT(ret == 0); + + /* Overwrite nounce */ + hex_len = os_strlen(nounce); + + if (hex_len > 2 * sizeof(dpp_nonce_override)) { + ret = -1; + } else if (hexstr2bin(nounce, dpp_nonce_override, hex_len / 2)) { + ret = -1; + } else { + dpp_nonce_override_len = hex_len / 2; + } + + TEST_ASSERT(ret == 0); + + } + ESP_LOGI("DPP Test", "Overwritten Protocol key, responder nounce.. "); + ESP_LOGI("DPP Test", "Enqueue Auth request"); + { + char auth_req[] = "d00012001ac459c40d649f8664c1b8771ac459c40d6400120409506f9a1a010002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d011020005d467a09760292fc15d31792b0a5b050db8bf6ad807d71b2d93f4d1c2e65d8810310400050a532ae2a07207276418d2fa630295d45569be425aa634f02014d00a7d1f61ae14f35a5a858bccad90d126c46594c49ef82655e78888e15a32d916ac217249118100200510104102900868f478fc599ac3fa8152b975eff8be4e71b189dbefbc3185b1d7f3864e896f913cba3d9601326f278"; + + char auth_resp[] = "d00012349f8664c1b8771ac459c40d649f8664c1b87712340409506f9a1a0101001001000002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d091040005e3fb3576884887f17c3203d8a3a6c2fac722ef0e2201b61ac73bc655c709a902d4b030669fb9eff8b0a79fa7c1a172ac2a92c626256963f9274dc90682c81e504107500da553cdf80da3e27054c5e1f809ac303c63948b9bb5690ad12f357d75dfbc362cbae89e472dd6851925534024310aff5ae403831e98a7efc7deb9516164329c227039ae73c509147d156ae085f56c242bf7decc1f3b68d81697c6197453cb6faff7b062f7861073148052db539895bc6583d08b4aa"; + u8 *tmp; + + hex_len = os_strlen(auth_req); + if (hex_len > 2 * MAX_FRAME_SIZE) { + ret = -1; + } else if (hexstr2bin(auth_req, auth, hex_len / 2)) { + ret = -1; + } else { + len = hex_len / 2; + } + frame = auth; + frame += 26; + len -= 26; + auth_instance = dpp_auth_req_rx(NULL, 1, 0, NULL, + dpp_bootstrap_get_id(dpp, id), 2412, frame, frame + 6, len - 6); + + /* auth response u8 */ + hex_len = os_strlen(auth_resp); + if (hex_len > 2 * MAX_FRAME_SIZE) { + ret = -1; + } else if (hexstr2bin(auth_resp, auth, hex_len / 2)) { + ret = -1; + } else { + len = hex_len / 2; + } + tmp = auth; + tmp += 26; + len -= 26; + + frame = wpabuf_head_u8(auth_instance->resp_msg); + len = wpabuf_len(auth_instance->resp_msg); + + TEST_ASSERT(memcmp(frame + 28, tmp + 26, len - 26) == 0); + } + ESP_LOGI("DPP Test", "Auth request parsing passed"); + ESP_LOGI("DPP Test", "Enqueue Auth confirm parsing passed"); + { + char auth_confirm[] = "d00012341ac459c40d649f8664c1b8771ac459c40d6412340409506f9a1a0102001001000002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d0410340054e07e62c74526dfd97e029dc781e0771e573ebc73c94227b5de8350fc6a1974b40f54c9fe1a1c9288a91fce4ee6c1f2ff069741"; + hex_len = os_strlen(auth_confirm); + os_memset(auth, 0, 1200); + if (hex_len > 2 * MAX_FRAME_SIZE) { + ret = -1; + } else if (hexstr2bin(auth_confirm, auth, hex_len / 2)) { + ret = -1; + } else { + len = hex_len / 2; + } + frame = auth; + frame = auth + 26; + len = len - 26; + dpp_auth_conf_rx(auth_instance, frame, frame + 6, len - 6); + TEST_ASSERT(auth_instance->auth_success == 1); + } + ESP_LOGI("DPP Test", "Auth confirm parsing passed"); + /* deinit for memory passing */ + { + dpp_auth_deinit(auth_instance); + dpp_global_deinit(dpp); + } + ESP_LOGI("DPP Test", "Test case passed"); } #endif From 955e2076b6ce8dc8d2a5f0e2ce2cb06e0dfdd7a8 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:46:37 +0200 Subject: [PATCH 128/142] change(wpa_supplicant): clean up test_dpp, set leak threshold --- components/wpa_supplicant/test_apps/main/test_dpp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_dpp.c b/components/wpa_supplicant/test_apps/main/test_dpp.c index 72e16c4a649d..b75cbbd91534 100644 --- a/components/wpa_supplicant/test_apps/main/test_dpp.c +++ b/components/wpa_supplicant/test_apps/main/test_dpp.c @@ -14,8 +14,10 @@ #include "utils/common.h" #include "utils/includes.h" #include "crypto/crypto.h" -#include "../src/common/defs.h" -#include "../src/common/dpp.h" +#include "common/defs.h" +#include "common/dpp.h" +#include "sdkconfig.h" +#include "test_wpa_supplicant_common.h" #ifdef CONFIG_ESP_WIFI_TESTING_OPTIONS struct dpp_global { @@ -32,6 +34,7 @@ extern size_t dpp_nonce_override_len; TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]") { + set_leak_threshold(120); /* Global variables */ char command[1200] = {0}; const u8 *frame; From 6eec370532cd34dd87064482dfd2f9f288494ebd Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:47:16 +0200 Subject: [PATCH 129/142] change(wpa_supplicant): reformat test_eloop with astyle --- .../test_apps/main/test_eloop.c | 79 +++++++++---------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_eloop.c b/components/wpa_supplicant/test_apps/main/test_eloop.c index 7cf73bb5e489..0f9d23b4b8ac 100644 --- a/components/wpa_supplicant/test_apps/main/test_eloop.c +++ b/components/wpa_supplicant/test_apps/main/test_eloop.c @@ -26,29 +26,28 @@ int executed_order[6]; int t; struct os_reltime ts; - /* there is only single instance of esp_timer so no need of protection */ void callback(void *a, void *b) { - int *i = a; - struct os_time age, now; + int *i = a; + struct os_time age, now; - os_get_reltime(&now); - os_time_sub(&now, &ts, &age); + os_get_reltime(&now); + os_time_sub(&now, &ts, &age); - int32_t ms_diff = (age.sec - timeouts_sec[*i]) * 1000 + - (age.usec - timeouts_usec[*i]) / 1000; + int32_t ms_diff = (age.sec - timeouts_sec[*i]) * 1000 + + (age.usec - timeouts_usec[*i]) / 1000; - /* let's give 50 ms offset for this small block */ - if (ms_diff > 50) { - executed_order[t] = -1; - } else { - executed_order[t] = *i; - } - t++; + /* let's give 50 ms offset for this small block */ + if (ms_diff > 50) { + executed_order[t] = -1; + } else { + executed_order[t] = *i; + } + t++; - ESP_LOGI("Eloop Test", "timer[%d] ran after %" PRId32 " msec of scheduled time", - *i, ms_diff); + ESP_LOGI("Eloop Test", "timer[%d] ran after %" PRId32 " msec of scheduled time", + *i, ms_diff); } @@ -56,32 +55,32 @@ extern const wifi_osi_funcs_t *wifi_funcs; /* Check if eloop runs its timers correctly & in correct order */ TEST_CASE("Test eloop timers run", "[eloop]") { - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - cfg.nvs_enable = false; - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - TEST_ESP_OK(esp_wifi_stop()); - TEST_ESP_OK(esp_wifi_deinit()); - /* Reset memory stats since some is leaked during the first initialization */ - test_utils_record_free_mem(); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + cfg.nvs_enable = false; + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + TEST_ESP_OK(esp_wifi_stop()); + TEST_ESP_OK(esp_wifi_deinit()); + /* Reset memory stats since some is leaked during the first initialization */ + test_utils_record_free_mem(); - int execution_order[6] = {1, 5, 3, 0, 2, 4}; - int index[6] = {0,1,2,3,4,5}; - t = 0; + int execution_order[6] = {1, 5, 3, 0, 2, 4}; + int index[6] = {0, 1, 2, 3, 4, 5}; + t = 0; - /* We need pptask to run eloop, wifi init will do that */ - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - os_get_reltime(&ts); - for (int i = 0; i < 6; i++) { - eloop_register_timeout(timeouts_sec[i], timeouts_usec[i], - callback, &index[i], NULL); - } + /* We need pptask to run eloop, wifi init will do that */ + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + os_get_reltime(&ts); + for (int i = 0; i < 6; i++) { + eloop_register_timeout(timeouts_sec[i], timeouts_usec[i], + callback, &index[i], NULL); + } - /* wait for all timers to run */ - os_sleep(20, 0); - /* check the execution order, this will also check whether they were fired at correct time */ - TEST_ASSERT(memcmp(execution_order, executed_order, 6*sizeof(int)) == 0); - TEST_ESP_OK(esp_wifi_stop()); - TEST_ESP_OK(esp_wifi_deinit()); - os_sleep(3, 0); + /* wait for all timers to run */ + os_sleep(20, 0); + /* check the execution order, this will also check whether they were fired at correct time */ + TEST_ASSERT(memcmp(execution_order, executed_order, 6 * sizeof(int)) == 0); + TEST_ESP_OK(esp_wifi_stop()); + TEST_ESP_OK(esp_wifi_deinit()); + os_sleep(3, 0); } #endif //SOC_WIFI_SUPPORTED From 191a9021c26b44afe024661d16434f9c7f49ae71 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:48:57 +0200 Subject: [PATCH 130/142] change(wpa_supplicant): clean up test_eloop, set leak threshold - sort includes, fix relative includes - make all globals static - remove ifdef SOC_WIFI_SUPPORTED since the whole test app is only built when SOC_WIFI_SUPPORTED is set --- .../test_apps/main/test_eloop.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_eloop.c b/components/wpa_supplicant/test_apps/main/test_eloop.c index 0f9d23b4b8ac..9553c50bb665 100644 --- a/components/wpa_supplicant/test_apps/main/test_eloop.c +++ b/components/wpa_supplicant/test_apps/main/test_eloop.c @@ -3,31 +3,31 @@ * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ -#include "string.h" +#include +#include #include #include "esp_system.h" -#include "unity.h" +#include "esp_log.h" #include "esp_system.h" #include "esp_event.h" #include "esp_wifi_types.h" +#include "unity.h" #include "utils/common.h" #include "utils/eloop.h" #include "common/ieee802_11_defs.h" -#include "../esp_supplicant/src/esp_wifi_driver.h" -#include "esp_log.h" -#include "test_utils.h" +#include "esp_wifi_driver.h" #include "memory_checks.h" -#include +#include "test_wpa_supplicant_common.h" + +static uint32_t timeouts_usec[6] = { 10000, 1000, 10000, 5000, 15000, 1000 }; +static uint32_t timeouts_sec[6] = { 10, 1, 10, 5, 15, 1 }; +static int executed_order[6]; +static int t; +static struct os_reltime ts; -#if SOC_WIFI_SUPPORTED -uint32_t timeouts_usec[6] = { 10000, 1000, 10000, 5000, 15000, 1000 }; -uint32_t timeouts_sec[6] = { 10, 1, 10, 5, 15, 1 }; -int executed_order[6]; -int t; -struct os_reltime ts; /* there is only single instance of esp_timer so no need of protection */ -void callback(void *a, void *b) +static void callback(void *a, void *b) { int *i = a; struct os_time age, now; @@ -55,6 +55,7 @@ extern const wifi_osi_funcs_t *wifi_funcs; /* Check if eloop runs its timers correctly & in correct order */ TEST_CASE("Test eloop timers run", "[eloop]") { + set_leak_threshold(800); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); cfg.nvs_enable = false; ESP_ERROR_CHECK(esp_wifi_init(&cfg)); @@ -83,4 +84,3 @@ TEST_CASE("Test eloop timers run", "[eloop]") TEST_ESP_OK(esp_wifi_deinit()); os_sleep(3, 0); } -#endif //SOC_WIFI_SUPPORTED From 6c27208ade4ceeb9dc5872d99d0a8a7c8d2c9e8d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:49:38 +0200 Subject: [PATCH 131/142] change(wpa_supplicant): reformat test_fast_pbkdf2 with astyle --- .../test_apps/main/test_fast_pbkdf2.c | 79 ++++++++++--------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c b/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c index 02055c045e8b..9bb0eadb8f25 100644 --- a/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c +++ b/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c @@ -16,53 +16,54 @@ TEST_CASE("Test pbkdf2", "[crypto-pbkdf2]") { - uint8_t PMK[PMK_LEN]; - uint8_t ssid_len; - uint8_t passphrase_len; - uint8_t ssid[MAX_SSID_LEN]; - uint8_t passphrase[MAX_PASSPHRASE_LEN]; - uint8_t expected_pmk1[PMK_LEN] = - {0xe7, 0x90, 0xd0, 0x65, 0x67, 0xf0, 0xbf, 0xca, 0xca, 0x10, 0x88, 0x0b, 0x85, 0xb2, 0x33, 0xe5, - 0xe1, 0xd5, 0xe5, 0xb8, 0xd0, 0xfd, 0x94, 0x60, 0x56, 0x95, 0x5e, 0x41, 0x5a, 0x7f, 0xfa, 0xfa}; + uint8_t PMK[PMK_LEN]; + uint8_t ssid_len; + uint8_t passphrase_len; + uint8_t ssid[MAX_SSID_LEN]; + uint8_t passphrase[MAX_PASSPHRASE_LEN]; + uint8_t expected_pmk1[PMK_LEN] = { + 0xe7, 0x90, 0xd0, 0x65, 0x67, 0xf0, 0xbf, 0xca, 0xca, 0x10, 0x88, 0x0b, 0x85, 0xb2, 0x33, 0xe5, + 0xe1, 0xd5, 0xe5, 0xb8, 0xd0, 0xfd, 0x94, 0x60, 0x56, 0x95, 0x5e, 0x41, 0x5a, 0x7f, 0xfa, 0xfa + }; - uint8_t expected_pmk[PMK_LEN]; + uint8_t expected_pmk[PMK_LEN]; - /* Compare Fast PBKDF output with expected output*/ - pbkdf2_sha1("espressif", (uint8_t *)"espressif", strlen("espressif"), 4096, PMK, PMK_LEN); - TEST_ASSERT(memcmp(PMK, expected_pmk1, PMK_LEN) == 0); + /* Compare Fast PBKDF output with expected output*/ + pbkdf2_sha1("espressif", (uint8_t *)"espressif", strlen("espressif"), 4096, PMK, PMK_LEN); + TEST_ASSERT(memcmp(PMK, expected_pmk1, PMK_LEN) == 0); - /* Compare fast PBKDF output with mbedtls pbkdf2 function's output */ - pbkdf2_sha1("espressif2", (uint8_t *)"espressif2", strlen("espressif2"), 4096, PMK, PMK_LEN); - mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const unsigned char *) "espressif2", - strlen("espressif2") , (const unsigned char *)"espressif2", - strlen("espressif2"), 4096, PMK_LEN, expected_pmk); - TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0); + /* Compare fast PBKDF output with mbedtls pbkdf2 function's output */ + pbkdf2_sha1("espressif2", (uint8_t *)"espressif2", strlen("espressif2"), 4096, PMK, PMK_LEN); + mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const unsigned char *) "espressif2", + strlen("espressif2"), (const unsigned char *)"espressif2", + strlen("espressif2"), 4096, PMK_LEN, expected_pmk); + TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0); - /* Calculate PMK using random ssid and passphrase and compare */ - os_memset(ssid, 0, MAX_SSID_LEN); - os_memset(passphrase, 0, MAX_PASSPHRASE_LEN); - ssid_len = os_random(); - ssid_len %= MAX_SSID_LEN; + /* Calculate PMK using random ssid and passphrase and compare */ + os_memset(ssid, 0, MAX_SSID_LEN); + os_memset(passphrase, 0, MAX_PASSPHRASE_LEN); + ssid_len = os_random(); + ssid_len %= MAX_SSID_LEN; - os_get_random(ssid, ssid_len); + os_get_random(ssid, ssid_len); - passphrase_len = os_random(); - passphrase_len %= MAX_PASSPHRASE_LEN; + passphrase_len = os_random(); + passphrase_len %= MAX_PASSPHRASE_LEN; - os_get_random(passphrase, passphrase_len); - pbkdf2_sha1((char *)passphrase, ssid, ssid_len, 4096, PMK, PMK_LEN); - mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const unsigned char *) passphrase, - strlen((char *)passphrase) , (const unsigned char *)ssid, - ssid_len, 4096, PMK_LEN, expected_pmk); + os_get_random(passphrase, passphrase_len); + pbkdf2_sha1((char *)passphrase, ssid, ssid_len, 4096, PMK, PMK_LEN); + mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const unsigned char *) passphrase, + strlen((char *)passphrase), (const unsigned char *)ssid, + ssid_len, 4096, PMK_LEN, expected_pmk); - /* Dump values if fails */ - if (memcmp(PMK, expected_pmk, PMK_LEN) != 0) { - ESP_LOG_BUFFER_HEXDUMP("passphrase", passphrase, passphrase_len, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEXDUMP("ssid", ssid, ssid_len, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEXDUMP("PMK", PMK, PMK_LEN, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEXDUMP("expected_pmk", expected_pmk, PMK_LEN, ESP_LOG_INFO); - } - TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0); + /* Dump values if fails */ + if (memcmp(PMK, expected_pmk, PMK_LEN) != 0) { + ESP_LOG_BUFFER_HEXDUMP("passphrase", passphrase, passphrase_len, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("ssid", ssid, ssid_len, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("PMK", PMK, PMK_LEN, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("expected_pmk", expected_pmk, PMK_LEN, ESP_LOG_INFO); + } + TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0); } #endif /* SOC_WIFI_SUPPORTED */ From 098d28276e584f8ee8e2a02fe84c9cb7cfde260d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:50:55 +0200 Subject: [PATCH 132/142] change(wpa_supplicant): set leak threshold in test_fast_pbkdf2 --- .../wpa_supplicant/test_apps/main/test_fast_pbkdf2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c b/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c index 9bb0eadb8f25..6e94c3e403d9 100644 --- a/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c +++ b/components/wpa_supplicant/test_apps/main/test_fast_pbkdf2.c @@ -9,13 +9,14 @@ #include "utils/common.h" #include "mbedtls/pkcs5.h" #include "crypto/sha1.h" - -#if SOC_WIFI_SUPPORTED +#include "test_wpa_supplicant_common.h" #define PMK_LEN 32 TEST_CASE("Test pbkdf2", "[crypto-pbkdf2]") { + set_leak_threshold(120); + uint8_t PMK[PMK_LEN]; uint8_t ssid_len; uint8_t passphrase_len; @@ -65,5 +66,3 @@ TEST_CASE("Test pbkdf2", "[crypto-pbkdf2]") } TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0); } - -#endif /* SOC_WIFI_SUPPORTED */ From c07ee2d56b562585a5a6e0834e8f48a78211aebf Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:54:10 +0200 Subject: [PATCH 133/142] change(wpa_supplicant): test_offchannel: cleanups and leak thresholds - sort includes - fix relative includes - replace TEMPORARY_DISABLED_FOR_TARGETS with just IDF_TARGET_ESP32, to avoid having to change this file when bringing up new chips - astyle formatting - set leak threshold in test cases - use the new 'wifi_two_dut' environment marker instead of UT_T2_1 --- .../test_apps/main/test_offchannel.c | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_offchannel.c b/components/wpa_supplicant/test_apps/main/test_offchannel.c index 5ddc0f082fc5..9e5ef6f5bce1 100644 --- a/components/wpa_supplicant/test_apps/main/test_offchannel.c +++ b/components/wpa_supplicant/test_apps/main/test_offchannel.c @@ -10,20 +10,23 @@ * CONDITIONS OF ANY KIND, either express or implied. */ -#include "string.h" +#include #include #include "esp_system.h" -#include "unity.h" +#include "esp_log.h" #include "esp_system.h" #include "esp_event.h" -#include "esp_wifi_types.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "unity.h" #include "utils/common.h" +#include "esp_wifi_types.h" +#include "esp_wifi_driver.h" +#include "memory_checks.h" #include "common/ieee802_11_defs.h" -#include "../esp_supplicant/src/esp_wifi_driver.h" -#include "esp_log.h" #include "test_utils.h" -#include "memory_checks.h" -#include "freertos/event_groups.h" +#include "test_wpa_supplicant_common.h" +#include "sdkconfig.h" #define WIFI_START_EVENT 0x00000001 #define WIFI_ROC_DONE_EVENT 0x00000002 @@ -32,9 +35,9 @@ #define TEST_LISTEN_CHANNEL 6 -/* No runners */ -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3, ESP32C2, ESP32C6, ESP32H2) -//IDF-5046 +/* No runners; IDF-5046 */ +#if CONFIG_IDF_TARGET_ESP32 + static const char *TAG = "test_offchan"; esp_netif_t *wifi_netif; static EventGroupHandle_t wifi_event; @@ -127,7 +130,7 @@ void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len, uint8_t channel, uint32_t wait_time_ms) { wifi_action_tx_req_t *req = os_zalloc(sizeof(*req) + len);; - TEST_ASSERT( req != NULL); + TEST_ASSERT(req != NULL); req->ifx = WIFI_IF_STA; memcpy(req->dest_mac, dest_mac, ETH_ALEN); @@ -144,14 +147,13 @@ void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len, os_free(req); } - /* Test that foreground Scan doesn't pre-empt ROC & vice versa */ TEST_CASE("Test scan and ROC simultaneously", "[Offchan]") { wifi_action_rx_cb_t rx_cb = dummy_rx_action; EventBits_t bits; - test_case_uses_tcpip(); + set_leak_threshold(6000); start_wifi_as_sta(); xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_PERIOD_MS); @@ -180,7 +182,7 @@ static void test_wifi_offchan_tx(void) char mac_str[19]; uint8_t mac[6]; - test_case_uses_tcpip(); + set_leak_threshold(6000); start_wifi_as_sta(); xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_PERIOD_MS); @@ -218,7 +220,7 @@ static void test_wifi_roc(void) EventBits_t bits; uint8_t mac[6]; - test_case_uses_tcpip(); + set_leak_threshold(6000); start_wifi_as_sta(); xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_PERIOD_MS); @@ -241,6 +243,6 @@ static void test_wifi_roc(void) } } -TEST_CASE_MULTIPLE_DEVICES("test ROC and Offchannel Action Frame Tx", "[Offchan][test_env=UT_T2_1][timeout=90]", test_wifi_roc, test_wifi_offchan_tx); +TEST_CASE_MULTIPLE_DEVICES("test ROC and Offchannel Action Frame Tx", "[Offchan][test_env=wifi_two_dut][timeout=90]", test_wifi_roc, test_wifi_offchan_tx); -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(...) +#endif //CONFIG_IDF_TARGET_ESP32 From 1745baffae58fd197f395dd978886cc600ad3246 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:54:44 +0200 Subject: [PATCH 134/142] change(wpa_supplicant): reformat test_sae with astyle --- .../wpa_supplicant/test_apps/main/test_sae.c | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_sae.c b/components/wpa_supplicant/test_apps/main/test_sae.c index ec13d144fc82..f4520473d393 100644 --- a/components/wpa_supplicant/test_apps/main/test_sae.c +++ b/components/wpa_supplicant/test_apps/main/test_sae.c @@ -22,14 +22,14 @@ #if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6781 typedef struct crypto_bignum crypto_bignum; - static struct wpabuf *wpabuf_alloc2(size_t len) { struct wpabuf *buf = (struct wpabuf *)os_zalloc(sizeof(struct wpabuf) + len); - if (buf == NULL) + if (buf == NULL) { return NULL; + } buf->size = len; - buf->buf = (u8 *) (buf + 1); + buf->buf = (u8 *)(buf + 1); return buf; } @@ -39,8 +39,9 @@ static struct wpabuf *wpabuf_alloc2(size_t len) * */ void wpabuf_free2(struct wpabuf *buf) { - if (buf == NULL) + if (buf == NULL) { return; + } os_free(buf); } @@ -188,10 +189,9 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") ESP_LOG_BUFFER_HEXDUMP("SAE: Predefined PMKID ", pmkid, SAE_PMKID_LEN, ESP_LOG_INFO); TEST_ASSERT(os_memcmp(pmkid, sae.pmkid, SAE_PMKID_LEN) == 0); - pt_info = sae_derive_pt(pt_groups, - (const u8 *) ssid, os_strlen(ssid), - (const u8 *) pw, os_strlen(pw), pwid); + (const u8 *) ssid, os_strlen(ssid), + (const u8 *) pw, os_strlen(pw), pwid); TEST_ASSERT(pt_info != NULL); @@ -240,13 +240,13 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") buf = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf != NULL); + TEST_ASSERT(buf != NULL); sae_write_commit(&sae, buf, NULL, NULL);// No anti-clogging token /* Parsing commit created by self will be detected as reflection attack*/ TEST_ASSERT(sae_parse_commit(&sae, - wpabuf_mhead(buf), buf->used, NULL, 0, default_groups, 0) == SAE_SILENTLY_DISCARD); + wpabuf_mhead(buf), buf->used, NULL, 0, default_groups, 0) == SAE_SILENTLY_DISCARD); wpabuf_free2(buf); sae_clear_temp_data(&sae); @@ -281,14 +281,13 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") /* STA1 creates commit msg buffer*/ buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf1 != NULL); + TEST_ASSERT(buf1 != NULL); sae_write_commit(&sae1, buf1, NULL, NULL);// No anti-clogging token - ESP_LOG_BUFFER_HEXDUMP("SAE: Commit1", wpabuf_mhead_u8(buf1), wpabuf_len(buf1), ESP_LOG_INFO); - + ESP_LOG_BUFFER_HEXDUMP("SAE: Commit1", wpabuf_mhead_u8(buf1), wpabuf_len(buf1), ESP_LOG_INFO); /* STA2 creates commit msg buffer*/ buf2 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf2 != NULL); + TEST_ASSERT(buf2 != NULL); sae_write_commit(&sae2, buf2, NULL, NULL);// No anti-clogging token ESP_LOG_BUFFER_HEXDUMP("SAE: Commit2", wpabuf_mhead_u8(buf2), wpabuf_len(buf2), ESP_LOG_INFO); @@ -297,11 +296,11 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") /* STA1 parses STA2 commit*/ TEST_ASSERT(sae_parse_commit(&sae1, - wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0); + wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0); /* STA2 parses STA1 commit*/ TEST_ASSERT(sae_parse_commit(&sae2, - wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0); + wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0); /* STA1 processes commit*/ TEST_ASSERT(sae_process_commit(&sae1) == 0); @@ -311,13 +310,13 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") /* STA1 creates confirm msg buffer*/ buf3 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf3 != NULL); + TEST_ASSERT(buf3 != NULL); sae_write_confirm(&sae1, buf3); ESP_LOG_BUFFER_HEXDUMP("SAE: Confirm1", wpabuf_mhead_u8(buf3), wpabuf_len(buf3), ESP_LOG_INFO); /* STA2 creates confirm msg buffer*/ buf4 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf3 != NULL); + TEST_ASSERT(buf3 != NULL); sae_write_confirm(&sae2, buf4); ESP_LOG_BUFFER_HEXDUMP("SAE: Confirm2", wpabuf_mhead_u8(buf4), wpabuf_len(buf4), ESP_LOG_INFO); @@ -369,12 +368,12 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") /* STA1 creates commit msg buffer*/ buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf1 != NULL); + TEST_ASSERT(buf1 != NULL); sae_write_commit(&sae1, buf1, NULL, NULL);// No anti-clogging token /* STA2 creates commit msg buffer*/ buf2 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf2 != NULL); + TEST_ASSERT(buf2 != NULL); sae_write_commit(&sae2, buf2, NULL, NULL);// No anti-clogging token sae1.state = SAE_COMMITTED; @@ -382,11 +381,11 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") /* STA1 parses STA2 commit*/ TEST_ASSERT(sae_parse_commit(&sae1, - wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0); + wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0); /* STA2 parses STA1 commit*/ TEST_ASSERT(sae_parse_commit(&sae2, - wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0); + wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0); /* STA1 processes commit*/ TEST_ASSERT(sae_process_commit(&sae1) == 0); @@ -396,12 +395,12 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") /* STA1 creates confirm msg buffer*/ buf3 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf3 != NULL); + TEST_ASSERT(buf3 != NULL); sae_write_confirm(&sae1, buf3); /* STA2 creates confirm msg buffer*/ buf4 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); - TEST_ASSERT( buf3 != NULL); + TEST_ASSERT(buf3 != NULL); sae_write_confirm(&sae2, buf4); /* STA1 checks confirm from STA2 and the check fails*/ From 2b1e9af12f304918cae338e624f91c27cf4dd45c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Oct 2023 12:57:05 +0200 Subject: [PATCH 135/142] change(wpa_supplicant): clean up test_sae, set leak thresholds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix relative includes - remove ESP32-H2-related TODO — an ifdef is not needed now since the whole app is built only for SOC_WIFI_SUPPORTED=y - set leak threshold in test case --- components/wpa_supplicant/test_apps/main/test_sae.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_sae.c b/components/wpa_supplicant/test_apps/main/test_sae.c index f4520473d393..d2cef1572ee3 100644 --- a/components/wpa_supplicant/test_apps/main/test_sae.c +++ b/components/wpa_supplicant/test_apps/main/test_sae.c @@ -16,10 +16,11 @@ #include "utils/common.h" #include "utils/includes.h" #include "crypto/crypto.h" -#include "../src/common/sae.h" +#include "common/sae.h" #include "utils/wpabuf.h" #include "test_utils.h" -#if !CONFIG_IDF_TARGET_ESP32H2 // IDF-6781 +#include "test_wpa_supplicant_common.h" + typedef struct crypto_bignum crypto_bignum; static struct wpabuf *wpabuf_alloc2(size_t len) @@ -47,6 +48,7 @@ void wpabuf_free2(struct wpabuf *buf) TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") { + set_leak_threshold(120); ESP_LOGI("SAE Test", "### Beginning SAE init and deinit ###"); { /* Test init and deinit*/ @@ -422,5 +424,5 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") ESP_LOGI("SAE Test", "=========== Complete ============"); } -#endif + #endif /* CONFIG_WPA3_SAE */ From 24b2e0a56d6ccdd15d3a75b0ea91f91389131746 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Mon, 18 Sep 2023 10:59:05 +0200 Subject: [PATCH 136/142] ci: different test case name with different params --- conftest.py | 13 ++++++++++++- tools/ci/idf_pytest/utils.py | 5 ++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/conftest.py b/conftest.py index 6e97d8d57837..06ed3a81a15a 100644 --- a/conftest.py +++ b/conftest.py @@ -19,6 +19,7 @@ import os import re import sys +from copy import deepcopy from datetime import datetime from typing import Callable, Optional @@ -87,7 +88,17 @@ def test_func_name(request: FixtureRequest) -> str: @pytest.fixture def test_case_name(request: FixtureRequest, target: str, config: str) -> str: is_qemu = request._pyfuncitem.get_closest_marker('qemu') is not None - return format_case_id(target, config, request.node.originalname, is_qemu=is_qemu) # type: ignore + if hasattr(request._pyfuncitem, 'callspec'): + params = deepcopy(request._pyfuncitem.callspec.params) # type: ignore + else: + params = {} + + filtered_params = {} + for k, v in params.items(): + if k not in request.session._fixturemanager._arg2fixturedefs: # type: ignore + filtered_params[k] = v # not fixture ones + + return format_case_id(target, config, request.node.originalname, is_qemu=is_qemu, params=filtered_params) # type: ignore @pytest.fixture diff --git a/tools/ci/idf_pytest/utils.py b/tools/ci/idf_pytest/utils.py index e71c1ce6f984..aef1a776c54b 100644 --- a/tools/ci/idf_pytest/utils.py +++ b/tools/ci/idf_pytest/utils.py @@ -9,7 +9,7 @@ from .constants import TARGET_MARKERS -def format_case_id(target: t.Optional[str], config: t.Optional[str], case: str, is_qemu: bool = False) -> str: +def format_case_id(target: t.Optional[str], config: t.Optional[str], case: str, is_qemu: bool = False, params: t.Optional[dict] = None) -> str: parts = [] if target: parts.append((str(target) + '_qemu') if is_qemu else str(target)) @@ -17,6 +17,9 @@ def format_case_id(target: t.Optional[str], config: t.Optional[str], case: str, parts.append(str(config)) parts.append(case) + if params: + parts.append(str(params)) + return '.'.join(parts) From d64116866326d0eb8fcdeb60a6716320e4c504f5 Mon Sep 17 00:00:00 2001 From: Jakub Kocka Date: Thu, 5 Oct 2023 11:01:58 +0200 Subject: [PATCH 137/142] fix(tools): adjusted esptool @flash_args command print to prevent issues --- tools/idf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/idf.py b/tools/idf.py index 7dafb5b39c71..9ab0d90f57c4 100755 --- a/tools/idf.py +++ b/tools/idf.py @@ -501,7 +501,7 @@ def flasher_path(f: Union[str, 'os.PathLike[str]']) -> str: if os.path.exists(os.path.join(args.build_dir, 'flash_args')): print(f'or from the "{args.build_dir}" directory') - print(' {}'.format(' '.join(esptool_cmd + ['@flash_args']))) + print(' {}'.format(' '.join(esptool_cmd + ['"@flash_args"']))) if 'all' in actions or 'build' in actions: print_flashing_message('Project', 'project') From 499e8addc954bafb7818f06b9adf6c7a43efba41 Mon Sep 17 00:00:00 2001 From: mofeifei Date: Sat, 7 Oct 2023 11:53:50 +0800 Subject: [PATCH 138/142] docs: update cn trans for tips and quirks --- docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst b/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst index c3142edc4ff5..a15dad603ba2 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst +++ b/docs/zh_CN/api-guides/jtag-debugging/tips-and-quirks.rst @@ -49,7 +49,7 @@ flash 映射 vs 软件 flash 断点 “next” 命令无法跳过子程序的原因 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -当使用 ``next`` 命令单步执行代码时,GDB 会在子程序的前面设置一个断点(两个中可用的一个),这样就可以跳过进入子程序内部的细节。如果这两个断点已经用在代码的其它位置,那么 ``next`` 命令将不起作用。在这种情况下,请删掉一个断点以使其中一个变得可用。当两个断点都已经被使用时,``next`` 命令会像 ``step`` 命令一样工作,调试器就会进入子程序内部。 +当使用 ``next`` 命令单步执行代码时,GDB 会在子程序的前面设置一个断点,这样就可以跳过进入子程序内部的细节。如果 {IDF_TARGET_SOC_CPU_BREAKPOINTS_NUM} 个断点都已经设置好,那么 ``next`` 命令将不起作用。在这种情况下,请删掉其他断点以使其中一个变得可用。当所有断点都已经被使用时,``next`` 命令会像 ``step`` 命令一样工作,调试器就会进入子程序内部。 .. _jtag-debugging-tip-code-options: @@ -111,7 +111,7 @@ GDB 具有 FreeRTOS 支持的 Python 扩展模块。在系统要求满足的情 在启动时,调试器发出一系列命令来复位芯片并使其在特定的代码行停止运行。这个命令序列(如下所示)支持自定义,用户可以选择在最方便合适的代码行开始调试工作。 -* ``set remote hardware-watchpoint-limit 2`` — 限制 GDB 仅使用 {IDF_TARGET_NAME} 支持的两个硬件观察点。更多详细信息,请查阅 `GDB 配置远程目标 `_ 。 +* ``set remote hardware-watchpoint-limit {IDF_TARGET_SOC_CPU_WATCHPOINTS_NUM}`` — 限制 GDB 使用芯片支持的硬件观察点数量,{IDF_TARGET_NAME} 支持 {IDF_TARGET_SOC_CPU_WATCHPOINTS_NUM} 个观察点。更多详细信息,请查阅 `GDB 配置远程目标 `_ 。 * ``mon reset halt`` — 复位芯片并使 CPU 停止运行。 * ``maintenance flush register-cache`` — monitor (``mon``) 命令无法通知 GDB 目标状态已经更改,GDB 会假设在 ``mon reset halt`` 之前所有的任务堆栈仍然有效。实际上,复位后目标状态将发生变化。执行 ``maintenance flush register-cache`` 是一种强制 GDB 从目标获取最新状态的方法。 * ``thb app_main`` — 在 ``app_main`` 处插入一个临时的硬件断点,如果有需要,可以将其替换为其他函数名。 From 4ee7fac7da29023e951b7222e8bfe88a75e7d6fd Mon Sep 17 00:00:00 2001 From: renpeiying Date: Tue, 29 Aug 2023 16:56:15 +0800 Subject: [PATCH 139/142] docs: Provide Chinese translation for system/intr_alloc.rst --- docs/en/api-reference/system/intr_alloc.rst | 102 ++++++------ .../zh_CN/api-reference/system/intr_alloc.rst | 157 +++++++++++++++++- 2 files changed, 208 insertions(+), 51 deletions(-) diff --git a/docs/en/api-reference/system/intr_alloc.rst b/docs/en/api-reference/system/intr_alloc.rst index fb4a4caf94a0..06b7bc456dff 100644 --- a/docs/en/api-reference/system/intr_alloc.rst +++ b/docs/en/api-reference/system/intr_alloc.rst @@ -1,78 +1,77 @@ Interrupt Allocation ==================== +:link_to_translation:`zh_CN:[中文]` + Overview -------- -.. only:: esp32 +.. only:: esp32 or esp32s3 - The {IDF_TARGET_NAME} has two cores, with 32 interrupts each. Each interrupt has a certain priority level, most (but not all) interrupts are connected to the interrupt mux. + The {IDF_TARGET_NAME} has two cores, with 32 interrupts each. Each interrupt has a fixed priority, most (but not all) interrupts are connected to the interrupt matrix. .. only:: esp32s2 - The {IDF_TARGET_NAME} has one core, with 32 interrupts. Each interrupt has a certain priority level, most (but not all) interrupts are connected to the interrupt mux. - -.. only:: esp32s3 - - The {IDF_TARGET_NAME} has two cores, with 32 interrupts. Each interrupt has a certain priority level, most (but not all) interrupts are connected to the interrupt mux. + The {IDF_TARGET_NAME} has one core, with 32 interrupts. Each interrupt has a fixed priority, most (but not all) interrupts are connected to the interrupt matrix. .. only:: esp32c2 or esp32c3 - The {IDF_TARGET_NAME} has one core, with 31 interrupts. Each interrupt has a programmable priority level. + The {IDF_TARGET_NAME} has one core, with 31 interrupts. Each interrupt's priority is independently programmable. .. only:: esp32c6 or esp32h2 - The {IDF_TARGET_NAME} has one core, with 28 external asynchronous interrupts. Each interrupt has a programmable priority level. In addition, there are also 4 core local interrupt sources (CLINT). See **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#riscvcpu>`__] for more details. + The {IDF_TARGET_NAME} has one core, with 28 external asynchronous interrupts. Each interrupt's priority is independently programmable. In addition, there are also 4 core local interrupt sources (CLINT). See **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#riscvcpu>`__] for more details. Because there are more interrupt sources than interrupts, sometimes it makes sense to share an interrupt in multiple drivers. The :cpp:func:`esp_intr_alloc` abstraction exists to hide all these implementation details. -A driver can allocate an interrupt for a certain peripheral by calling :cpp:func:`esp_intr_alloc` (or :cpp:func:`esp_intr_alloc_intrstatus`). It can use the flags passed to this function to set the type of interrupt allocated, specifying a particular level or trigger method. The interrupt allocation code will then find an applicable interrupt, use the interrupt mux to hook it up to the peripheral, and install the given interrupt handler and ISR to it. +A driver can allocate an interrupt for a certain peripheral by calling :cpp:func:`esp_intr_alloc` (or :cpp:func:`esp_intr_alloc_intrstatus`). It can use the flags passed to this function to specify the type, priority, and trigger method of the interrupt to allocate. The interrupt allocation code will then find an applicable interrupt, use the interrupt matrix to hook it up to the peripheral, and install the given interrupt handler and ISR to it. -This code presents two different types of interrupts, handled differently: shared interrupts and non-shared interrupts. The simplest ones are non-shared interrupts: a separate interrupt is allocated per :cpp:func:`esp_intr_alloc` call and this interrupt is solely used for the peripheral attached to it, with only one ISR that will get called. On the other hand, shared interrupts can have multiple peripherals triggering them, with multiple ISRs being called when one of the peripherals attached signals an interrupt. Thus, ISRs that are intended for shared interrupts should check the interrupt status of the peripheral they service in order to check if any action is required. +The interrupt allocator presents two different types of interrupts, namely shared interrupts and non-shared interrupts, both of which require different handling. Non-shared interrupts will allocate a separate interrupt for every :cpp:func:`esp_intr_alloc` call, and this interrupt is use solely for the peripheral attached to it, with only one ISR that will get called. Shared interrupts can have multiple peripherals triggering them, with multiple ISRs being called when one of the peripherals attached signals an interrupt. Thus, ISRs that are intended for shared interrupts should check the interrupt status of the peripheral they service in order to check if any action is required. Non-shared interrupts can be either level- or edge-triggered. Shared interrupts can only be level interrupts due to the chance of missed interrupts when edge interrupts are used. -For example, let us say DevA and DevB share an interrupt. DevB signals an interrupt, so INT line goes high. The ISR handler calls code for DevA but does nothing. Then, ISR handler calls code for DevB, but while doing that, DevA signals an interrupt. DevB's ISR is done, it clears interrupt status for DevB and exits interrupt code. Now, an interrupt for DevA is still pending, but because the INT line never went low, as DevA kept it high even when the interrupt for DevB was cleared, the interrupt is never serviced. +To illustrate why shard interrupts can only be level-triggered, take the scenario where peripheral A and peripheral B share the same edge-triggered interrupt. Peripheral B triggers an interrupt and sets its interrupt signal high, causing a low-to-high edge, which in turn latches the CPU's interrupt bit and triggers the ISR. The ISR executes, checks that peripheral A did not trigger an interrupt, and proceeds to handle and clear peripheral B's interrupt signal. Before the ISR returns, the CPU clears its interrupt bit latch. Thus, during the entire interrupt handling process, if peripheral A triggers an interrupt, it will be missed due the CPU clearing the interrupt bit latch. .. only:: esp32 or esp32s3 - Multicore Issues - ---------------- + Multicore Issues + ---------------- - Peripherals that can generate interrupts can be divided in two types: + Peripherals that can generate interrupts can be divided in two types: - - External peripherals, within the {IDF_TARGET_NAME} but outside the Xtensa cores themselves. Most {IDF_TARGET_NAME} peripherals are of this type. - - Internal peripherals, part of the Xtensa CPU cores themselves. + - External peripherals, within the {IDF_TARGET_NAME} but outside the Xtensa cores themselves. Most {IDF_TARGET_NAME} peripherals are of this type. + - Internal peripherals, part of the Xtensa CPU cores themselves. - Interrupt handling differs slightly between these two types of peripherals. + Interrupt handling differs slightly between these two types of peripherals. - Internal Peripheral Interrupts - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Internal Peripheral Interrupts + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Each Xtensa CPU core has its own set of six internal peripherals: + Each Xtensa CPU core has its own set of six internal peripherals: - - Three timer comparators - - A performance monitor - - Two software interrupts. + - Three timer comparators + - A performance monitor + - Two software interrupts - Internal interrupt sources are defined in ``esp_intr_alloc.h`` as ``ETS_INTERNAL_*_INTR_SOURCE``. + Internal interrupt sources are defined in ``esp_intr_alloc.h`` as ``ETS_INTERNAL_*_INTR_SOURCE``. - These peripherals can only be configured from the core they are associated with. When generating an interrupt, the interrupt they generate is hard-wired to their associated core; it is not possible to have, for example, an internal timer comparator of one core generate an interrupt on another core. That is why these sources can only be managed using a task running on that specific core. Internal interrupt sources are still allocatable using :cpp:func:`esp_intr_alloc` as normal, but they cannot be shared and will always have a fixed interrupt level (namely, the one associated in hardware with the peripheral). + These peripherals can only be configured from the core they are associated with. When generating an interrupt, the interrupt they generate is hard-wired to their associated core; it is not possible to have, for example, an internal timer comparator of one core generate an interrupt on another core. That is why these sources can only be managed using a task running on that specific core. Internal interrupt sources are still allocatable using :cpp:func:`esp_intr_alloc` as normal, but they cannot be shared and will always have a fixed interrupt level (namely, the one associated in hardware with the peripheral). - External Peripheral Interrupts - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + External Peripheral Interrupts + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - The remaining interrupt sources are from external peripherals. These are defined in ``soc/soc.h`` as ``ETS_*_INTR_SOURCE``. + The remaining interrupt sources are from external peripherals. These are defined in ``soc/soc.h`` as ``ETS_*_INTR_SOURCE``. - Non-internal interrupt slots in both CPU cores are wired to an interrupt multiplexer, which can be used to route any external interrupt source to any of these interrupt slots. + Non-internal interrupt slots in both CPU cores are wired to an interrupt matrix, which can be used to route any external interrupt source to any of these interrupt slots. - - Allocating an external interrupt will always allocate it on the core that does the allocation. - - Freeing an external interrupt must always happen on the same core it was allocated on. - - Disabling and enabling external interrupts from another core is allowed. - - Multiple external interrupt sources can share an interrupt slot by passing ``ESP_INTR_FLAG_SHARED`` as a flag to :cpp:func:`esp_intr_alloc`. + - Allocating an external interrupt will always allocate it on the core that does the allocation. + - Freeing an external interrupt must always happen on the same core it was allocated on. + - Disabling and enabling external interrupts from another core is allowed. + - Multiple external interrupt sources can share an interrupt slot by passing ``ESP_INTR_FLAG_SHARED`` as a flag to :cpp:func:`esp_intr_alloc`. + + Care should be taken when calling :cpp:func:`esp_intr_alloc` from a task which is not pinned to a core. During task switching, these tasks can migrate between cores. Therefore it is impossible to tell which CPU the interrupt is allocated on, which makes it difficult to free the interrupt handle and may also cause debugging difficulties. It is advised to use :cpp:func:`xTaskCreatePinnedToCore` with a specific CoreID argument to create tasks that allocate interrupts. In the case of internal interrupt sources, this is required. - Care should be taken when calling :cpp:func:`esp_intr_alloc` from a task which is not pinned to a core. During task switching, these tasks can migrate between cores. Therefore it is impossible to tell which CPU the interrupt is allocated on, which makes it difficult to free the interrupt handle and may also cause debugging difficulties. It is advised to use :cpp:func:`xTaskCreatePinnedToCore` with a specific CoreID argument to create tasks that allocate interrupts. In the case of internal interrupt sources, this is required. IRAM-Safe Interrupt Handlers ---------------------------- @@ -96,29 +95,32 @@ Sources attached to non-shared interrupt do not support this feature. .. only:: not SOC_CPU_HAS_FLEXIBLE_INTC - By default, when ``ESP_INTR_FLAG_SHARED`` flag is specified, the interrupt allocator will allocate only Level 1 interrupts. Use ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` to also allow allocating shared interrupts at Level 2 and Level 3. + By default, when ``ESP_INTR_FLAG_SHARED`` flag is specified, the interrupt allocator will allocate only priority level 1 interrupts. Use ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` to also allow allocating shared interrupts at priority levels 2 and 3. Though the framework supports this feature, you have to use it **very carefully**. There usually exist two ways to stop an interrupt from being triggered: **disable the source** or **mask peripheral interrupt status**. ESP-IDF only handles enabling and disabling of the source itself, leaving status and mask bits to be handled by users. -**Status bits shall either be masked before the handler responsible for it is disabled, either be masked and then properly handled in another enabled interrupt**. +**Status bits shall either be masked before the handler responsible for it is disabled, or be masked and then properly handled in another enabled interrupt**. .. note:: - Leaving some status bits unhandled without masking them, while disabling the handlers for them, will cause the interrupt(s) to be triggered indefinitely, resulting therefore in a system crash. + Leaving some status bits unhandled without masking them, while disabling the handlers for them, will cause the interrupt(s) to be triggered indefinitely, resulting therefore in a system crash. + Troubleshooting Interrupt Allocation ------------------------------------ -On most Espressif SoCs, CPU interrupts are a limited resource. Therefore it is possible to run a program which runs out of CPU interrupts, for example by initializing several peripheral drivers. Typically, this will result in the driver initialization function returning ``ESP_ERR_NOT_FOUND`` error code. +On most Espressif SoCs, CPU interrupts are a limited resource. Therefore it is possible for a program to run out of CPU interrupts, for example by initializing several peripheral drivers. Typically, this will result in the driver initialization function returning ``ESP_ERR_NOT_FOUND`` error code. + +If this happens, you can use :cpp:func:`esp_intr_dump` function to print the list of interrupts along with their status. The output of this function typically looks like this: -If this happens, you can use :cpp:func:`esp_intr_dump` function to print the list of interrupts along with their status. The output of this function typically looks like this:: +.. code-block:: CPU 0 interrupt status: - Int Level Type Status - 0 1 Level Reserved - 1 1 Level Reserved - 2 1 Level Used: RTC_CORE - 3 1 Level Used: TG0_LACT_LEVEL + Int Level Type Status + 0 1 Level Reserved + 1 1 Level Reserved + 2 1 Level Used: RTC_CORE + 3 1 Level Used: TG0_LACT_LEVEL ... The columns of the output have the following meaning: @@ -126,8 +128,8 @@ The columns of the output have the following meaning: .. list:: - ``Int``: CPU interrupt input number. This is typically not used in software directly, and is provided for reference only. - :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``: Interrupt level (1-7) of the CPU interrupt. This level is fixed in hardware, and cannot be changed. - :SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``: For interrupts which have been allocated, the level (priority) of the interrupt. For free interrupts ``*`` is printed. + :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``: Interrupt priority (1-7) of the CPU interrupt. This priority is fixed in hardware, and cannot be changed. + :SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``: For interrupts which have been allocated, the priority of the interrupt. For free interrupts ``*`` is printed. :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Type``: Interrupt type (Level or Edge) of the CPU interrupt. This type is fixed in hardware, and cannot be changed. :SOC_CPU_HAS_FLEXIBLE_INTC: - ``Type``: For interrupts which have been allocated, the type (Level or Edge) of the interrupt. For free interrupts ``*`` is printed. - ``Status``: One of the possible statuses of the interrupt: @@ -135,7 +137,7 @@ The columns of the output have the following meaning: - ``Used: ``: The interrupt is allocated and connected to a single peripheral. - ``Shared: ...``: The interrupt is allocated and connected to multiple peripherals. See :ref:`intr-alloc-shared-interrupts` above. - ``Free``: The interrupt is not allocated and can be used by :cpp:func:`esp_intr_alloc`. - :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Free (not general-use)``: The interrupt is not allocated, but is either a high-level interrupt (level 4-7) or and edge-triggered interrupt. High-level interrupts can be allocated using :cpp:func:`esp_intr_alloc` but require the handlers to be written in Assembly, see :doc:`../../api-guides/hlinterrupts`. Edge-triggered low- and medium- level interrupts can also be allocated using :cpp:func:`esp_intr_alloc`, but are not used often since most peripheral interrupts are level-triggered. + :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Free (not general-use)``: The interrupt is not allocated, but is either a high-priority interrupt (priority 4-7) or an edge-triggered interrupt. High-priority interrupts can be allocated using :cpp:func:`esp_intr_alloc` but requires the handlers to be written in Assembly, see :doc:`../../api-guides/hlinterrupts`. Edge-triggered low- and medium-priority interrupts can also be allocated using :cpp:func:`esp_intr_alloc`, but are not used often since most peripheral interrupts are level-triggered. If you have confirmed that the application is indeed running out of interrupts, a combination of the following suggestions can help resolve the issue: @@ -143,8 +145,8 @@ If you have confirmed that the application is indeed running out of interrupts, :not CONFIG_FREERTOS_UNICORE: - On multi-core SoCs, try initializing some of the peripheral drivers from a task pinned to the second core. Interrupts are typically allocated on the same core where the peripheral driver initialization function runs. Therefore by running the initialization function on the second core, more interrupt inputs can be used. - Determine the interrupts which can tolerate higher latency, and allocate them using ``ESP_INTR_FLAG_SHARED`` flag (optionally ORed with ``ESP_INTR_FLAG_LOWMED``). Using this flag for two or more peripherals will let them use a single interrupt input, and therefore save interrupt inputs for other peripherals. See :ref:`intr-alloc-shared-interrupts` above. - :not SOC_CPU_HAS_FLEXIBLE_INTC: - Some peripheral driver may default to allocating interrupts with ``ESP_INTR_FLAG_LEVEL1`` flag, so level 2 and 3 interrupts do not get used by default. If :cpp:func:`esp_intr_dump` shows that some level 2 or 3 interrupts are available, try changing the interrupt allocation flags when initializing the driver to ``ESP_INTR_FLAG_LEVEL2`` or ``ESP_INTR_FLAG_LEVEL3``. - - Check if some of the peripheral drivers do not need to be used all the time, and initialize/deinitialize them on demand. This can reduce the number of simultaneously allocated interrupts. + :not SOC_CPU_HAS_FLEXIBLE_INTC: - Some peripheral driver may default to allocating interrupts with ``ESP_INTR_FLAG_LEVEL1`` flag, so priority 2 and 3 interrupts do not get used by default. If :cpp:func:`esp_intr_dump` shows that some priority 2 or 3 interrupts are available, try changing the interrupt allocation flags when initializing the driver to ``ESP_INTR_FLAG_LEVEL2`` or ``ESP_INTR_FLAG_LEVEL3``. + - Check if some of the peripheral drivers do not need to be used all the time, and initialize or deinitialize them on demand. This can reduce the number of simultaneously allocated interrupts. API Reference diff --git a/docs/zh_CN/api-reference/system/intr_alloc.rst b/docs/zh_CN/api-reference/system/intr_alloc.rst index 7e5576cd45af..f795107ac73f 100644 --- a/docs/zh_CN/api-reference/system/intr_alloc.rst +++ b/docs/zh_CN/api-reference/system/intr_alloc.rst @@ -1 +1,156 @@ -.. include:: ../../../en/api-reference/system/intr_alloc.rst \ No newline at end of file +中断分配 +======== + +:link_to_translation:`en:[English]` + +概述 +---- + +.. only:: esp32 or esp32s3 + + {IDF_TARGET_NAME} 有两个核,每个核有 32 个中断。每个中断都有一个确定的优先级别,大多数中断(但不是全部)都连接到中断矩阵。 + +.. only:: esp32s2 + + {IDF_TARGET_NAME} 有一个核,32 个中断。每个中断都有一个确定的优先级别,大多数中断(但不是全部)都连接到中断矩阵。 + +.. only:: esp32c2 or esp32c3 + + {IDF_TARGET_NAME} 有一个核,31 个中断。每个中断的优先级别都可独立地通过编程设置。 + +.. only:: esp32c6 or esp32h2 + + {IDF_TARGET_NAME} 有一个核,28 个外部异步中断。每个中断的优先级别都可独立地通过编程设置。此外,还有 4 个核心本地中断源 (CLINT)。详细信息请参见 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#riscvcpu>`__]。 + +由于中断源数量多于中断,有时多个驱动程序可以共用一个中断。:cpp:func:`esp_intr_alloc` 抽象隐藏了这些实现细节。 + +驱动程序可以通过调用 :cpp:func:`esp_intr_alloc`,或 :cpp:func:`esp_intr_alloc_intrstatus` 为某个外设分配中断。通过向此函数传递 flag,可以指定中断类型、优先级和触发方式。然后,中断分配代码会找到适用的中断,使用中断矩阵将其连接到外设,并为其安装给定的中断处理程序和 ISR。 + +中断分配器提供两种不同的中断类型:共享中断和非共享中断,这两种中断需要不同处理方式。非共享中断在每次调用 :cpp:func:`esp_intr_alloc` 时,都会分配一个单独的中断,该中断仅用于与其相连的外设,只调用一个 ISR。共享中断则可以由多个外设触发,当其中一个外设发出中断信号时,会调用多个 ISR。因此,针对共享中断的 ISR 应检查对应外设的中断状态,以确定是否需要采取任何操作。 + +非共享中断可由电平或边缘触发。共享中断只能由电平触发,因为使用边缘触发可能会错过中断。 + +要解释为什么共享中断只能由电平触发,以外设 A 和外设 B 共用一个边缘触发中断为例进行说明:当外设 B 触发中断时,会将其中断信号设置为高电平,产生一个从低到高的边缘,进而锁存 CPU 中断位,并触发 ISR。接着,ISR 开始执行,检查到此时外设 A 没有触发中断,于是继续处理外设 B 的中断信号,最后将外设 B 的中断状态清除。最后,CPU 会在 ISR 返回之前清除中断位锁存器。因此在整个中断处理过程中,如果外设 A 触发了中断,该中断会因 CPU 清除中断位锁存器而丢失。 + + +.. only:: esp32 or esp32s3 + + 多核问题 + -------- + + 可以生成中断的外设包括以下两种类型: + + - 外部外设,属于 {IDF_TARGET_NAME},但不属于 Xtensa 核。大多数 {IDF_TARGET_NAME} 外设都属于此类型。 + - 内部外设,是 Xtensa CPU 的一部分。 + + 这两种外设的中断处理略有不同。 + + 内部外设中断 + ^^^^^^^^^^^^^^^^^^^^ + + 每个 Xtensa CPU 核都有六个内部外设: + + - 三个定时器比较器 + - 一个性能监视器 + - 两个软件中断 + + 内部中断源在 ``esp_intr_alloc.h`` 中定义为 ``ETS_INTERNAL_*_INTR_SOURCE``。 + + 这些外设只能通过关联的内核进行配置。在生成中断时,它们生成的中断被硬连线到关联的内核上,例如,一个内核的内部定时器比较器不能生成另一个内核上的中断。因此,这些中断源只能通过在特定内核上运行任务来进行管理。内部中断源仍然可用 :cpp:func:`esp_intr_alloc` 正常分配,但不能共用,而且始终具有固定的中断级别(即与外设关联的硬件级别)。 + + 外部外设中断 + ^^^^^^^^^^^^^^^^^^^^ + + 剩余的中断源来自外部外设,在 ``soc/soc.h`` 中定义为 ``ETS_*_INTR_SOURCE``。 + + 两个 CPU 的非内部中断源槽都与中断矩阵相连,可以将任何外部中断源发送到这些中断槽中。 + + - 外部中断会始终被分配到执行该分配的内核上。 + - 释放外部中断必须在分配该中断的内核上进行。 + - 允许从另一个内核禁用和启用外部中断。 + - 多个外部中断源可以通过向 :cpp:func:`esp_intr_alloc` 发送 ``ESP_INTR_FLAG_SHARED`` flag 来共享一个中断槽。 + + 须注意从未关联到内核的任务中调用 :cpp:func:`esp_intr_alloc` 的情况。在任务切换期间,这些任务可能在不同内核之间进行迁移,因此无法确定中断分配到了哪个 CPU,给释放中断句柄造成困难,也可能引起调试问题。建议使用特定 CoreID 参数的 :cpp:func:`xTaskCreatePinnedToCore` 来创建中断分配任务,这对于内部中断源而言是必要的。 + + +IRAM-safe 中断处理程序 +---------------------- + +``ESP_INTR_FLAG_IRAM`` flag 注册的中断处理程序始终在 IRAM(并从 DRAM 读取其所有数据)中运行,因此在擦除和写入 flash 时无需禁用。 + +这对于需要保证最小执行延迟的中断来说非常有用,因为 flash 写入和擦除操作可能很慢(擦除可能需要数十毫秒或数百毫秒才能完成)。 + +如果中断被频繁调用,可以将中断处理程序保留在 IRAM 中,避免 flash cache 丢失。 + +有关更多详细信息,请参阅 :ref:`SPI flash API 相关文档 `。 + +.. _intr-alloc-shared-interrupts: + +多个处理程序共用一个中断源 +-------------------------- + +如果用 ``ESP_INTR_FLAG_SHARED`` flag 分配所有处理程序,可能将多个处理程序分配给同一个源。这些程序会被分配给与源关联的中断,并在源可用时按顺序调用。处理程序可以单独禁用和释放。如果启用了一个或多个处理程序,则会将源关联到中断(启用),否则会取消关联。禁用的处理程序永远不会被调用,但是只要启用了源的任何一个处理程序,这个源仍然能被触发。 + +关联到非共享中断的源不支持此功能。 + +.. only:: not SOC_CPU_HAS_FLEXIBLE_INTC + + 默认情况下,指定 ``ESP_INTR_FLAG_SHARED`` flag 时,中断分配器仅分配优先级为 1 的中断。可以使用 ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` 允许分配优先级为 2 和 3 的共享中断。 + +尽管支持此功能,使用时也必须 **非常小心**。通常存在两种办法可以阻止中断触发: **禁用源** 或 **屏蔽外设中断状态**。ESP-IDF 仅处理源本身的启用和禁用,中断源的状态位和屏蔽位须由用户操作。 + +**状态位须在负责该位的处理程序禁用前屏蔽,也可以在另一个启用的中断中屏蔽和处理该状态位。** + +.. note:: + + 如果不屏蔽状态位而让其处于未处理状态,同时禁用这些状态位的处理程序,就会导致无限次触发中断,引起系统崩溃。 + + +排除中断分配故障 +------------------ + +CPU 中断在大多数 Espressif SoC 上都是有限的资源。因此,一个运行的程序有可能耗尽 CPU 中断,例如初始化多个外设驱动程序的情况。这通常导致驱动程序的初始化函数返回 ``ESP_ERR_NOT_FOUND`` 错误。 + +这种情况下,可使用 :cpp:func:`esp_intr_dump` 函数打印中断列表及其状态。此函数输出通常如下: + +.. code-block:: + + CPU 0 interrupt status: + Int Level Type Status + 0 1 Level Reserved + 1 1 Level Reserved + 2 1 Level Used: RTC_CORE + 3 1 Level Used: TG0_LACT_LEVEL + ... + +输出列含义如下: + +.. list:: + + - ``Int``:CPU 中断输入编号。通常不直接在软件中使用,仅作为参考。 + :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``:CPU 中断的优先级(1-7)。此优先级固定在硬件上,无法更改。 + :SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``:已分配中断的优先级级别。空闲的中断具有标记 ``*``。 + :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Type``:CPU 中断的中断类型(电平或边缘中断)。此类型在硬件上固定,无法更改。 + :SOC_CPU_HAS_FLEXIBLE_INTC: - ``Type``:已分配中断的类型(电平或边缘中断)。空闲的中断具有标记 ``*``。 + - ``Status``:中断的可能状态: + - ``Reserved``:中断在硬件层面保留,或由 ESP-IDF 的某些部分保留。不能使用 :cpp:func:`esp_intr_alloc` 分配。 + - ``Used: ``:中断已分配并连接到单个外设。 + - ``Shared: ...``:中断已分配并连接到多个外设。参见本文档 :ref:`intr-alloc-shared-interrupts` 章节。 + - ``Free``:中断未分配,可以由 :cpp:func:`esp_intr_alloc` 使用。 + :not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Free (not general-use)``:中断未分配,但它是高优先级中断(级别 4-7)或边缘触发中断。高优先级中断可以使用 :cpp:func:`esp_intr_alloc` 分配,但要求处理程序必须用汇编语言编写,参见 :doc:`../../api-guides/hlinterrupts`。低优先级和中优先级的边缘触发中断也可以用 :cpp:func:`esp_intr_alloc` 分配,但很少使用,因为大多数外设中断是电平触发的。 + +如果已确认应用程序的确用完了中断,可组合采用下列建议解决问题: + +.. list:: + + :not CONFIG_FREERTOS_UNICORE: - 在多核 SoC 上,尝试通过固定在第二个核的任务来初始化某些外设驱动程序。中断通常分配在运行外设驱动程序初始化函数的同一个内核上,因此,通过在第二个内核上运行初始化函数,就可以使用更多的中断输入。 + - 找到可接受更高延迟的中断,并用 ``ESP_INTR_FLAG_SHARED`` flag (或与 ``ESP_INTR_FLAG_LOWMED`` 进行 OR 运算)分配这些中断。对两个或更多外设使用此 flag 能让它们使用单个中断输入,从而为其他外设节约中断输入。参见 :ref:`intr-alloc-shared-interrupts`。 + :not SOC_CPU_HAS_FLEXIBLE_INTC: - 一些外设驱动程序可能默认使用 ``ESP_INTR_FLAG_LEVEL1`` flag 来分配中断,因此默认情况下不会使用优先级为 2 或 3 的中断。如果 :cpp:func:`esp_intr_dump` 显示某些优先级为 2 或 3 的中断可用,尝试在初始化驱动程序时将中断分配 flag 改为 ``ESP_INTR_FLAG_LEVEL2`` 或 ``ESP_INTR_FLAG_LEVEL3``。 + - 检查是否有些外设驱动程序不需要一直启用,并按需将其初始化或取消初始化。这样可以减少同时分配的中断数量。 + + +API 参考 +-------- + +.. include-build-file:: inc/esp_intr_types.inc +.. include-build-file:: inc/esp_intr_alloc.inc From b774bd1457bb15544c4c3e9f018ffd76767928d5 Mon Sep 17 00:00:00 2001 From: Armando Date: Sun, 8 Oct 2023 10:35:52 +0800 Subject: [PATCH 140/142] refactor(esp_adc): reformat code with astyle_py --- components/esp_adc/adc_cali.c | 1 - components/esp_adc/adc_cali_curve_fitting.c | 1 - components/esp_adc/adc_common.c | 1 - components/esp_adc/adc_continuous.c | 4 +- components/esp_adc/adc_continuous_internal.h | 1 - components/esp_adc/adc_filter.c | 8 +-- components/esp_adc/adc_monitor.c | 1 - components/esp_adc/adc_oneshot.c | 12 +--- .../esp_adc/curve_fitting_coefficients.h | 2 +- .../deprecated/esp32/esp_adc_cal_legacy.c | 14 +++-- .../deprecated/esp32c3/esp_adc_cal_legacy.c | 31 +++++------ .../deprecated/esp32s2/esp_adc_cal_legacy.c | 20 +++---- .../deprecated/esp32s3/esp_adc_cal_legacy.c | 55 +++++++++---------- .../deprecated/esp_adc_cal_common_legacy.c | 3 +- .../deprecated/esp_adc_cal_internal_legacy.h | 3 +- .../include/esp_adc_cal_types_legacy.h | 1 - .../esp_adc/esp32/adc_cali_line_fitting.c | 22 +++----- .../esp_adc/esp32c2/adc_cali_line_fitting.c | 4 -- .../esp32c3/curve_fitting_coefficients.c | 20 +++---- .../esp32c6/curve_fitting_coefficients.c | 3 +- .../esp_adc/esp32s2/adc_cali_line_fitting.c | 31 ++++------- .../esp32s3/curve_fitting_coefficients.c | 40 +++++++------- components/esp_adc/include/esp_adc/adc_cali.h | 1 - .../esp_adc/include/esp_adc/adc_cali_scheme.h | 2 - .../esp_adc/include/esp_adc/adc_continuous.h | 2 - .../esp_adc/include/esp_adc/adc_filter.h | 1 - .../esp_adc/include/esp_adc/adc_monitor.h | 2 - .../esp_adc/include/esp_private/adc_private.h | 4 -- .../esp_adc/interface/adc_cali_interface.h | 1 - .../esp_adc/test_apps/adc/main/test_adc.c | 25 ++++----- .../test_apps/adc/main/test_adc_driver.c | 15 ++--- .../test_apps/adc/main/test_adc_driver_iram.c | 5 +- .../test_apps/adc/main/test_adc_performance.c | 23 ++++---- .../test_apps/adc/main/test_common_adc.c | 7 +-- .../test_apps/adc/main/test_common_adc.h | 2 - tools/ci/astyle-rules.yml | 1 - 36 files changed, 152 insertions(+), 217 deletions(-) diff --git a/components/esp_adc/adc_cali.c b/components/esp_adc/adc_cali.c index 4b5b4e26aac2..89558f28d771 100644 --- a/components/esp_adc/adc_cali.c +++ b/components/esp_adc/adc_cali.c @@ -18,7 +18,6 @@ const __attribute__((unused)) static char *TAG = "adc_cali"; - esp_err_t adc_cali_check_scheme(adc_cali_scheme_ver_t *scheme_mask) { ESP_RETURN_ON_FALSE(scheme_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); diff --git a/components/esp_adc/adc_cali_curve_fitting.c b/components/esp_adc/adc_cali_curve_fitting.c index dbdfab4783fb..919614a5fca5 100644 --- a/components/esp_adc/adc_cali_curve_fitting.c +++ b/components/esp_adc/adc_cali_curve_fitting.c @@ -178,7 +178,6 @@ static void calc_first_step_coefficients(const adc_calib_info_t *parsed_data, ca ESP_LOGV(TAG, "Calib V1, Cal Voltage = %" PRId32 ", Digi out = %" PRId32 ", Coef_a = %" PRId32, parsed_data->ref_data.ver1.voltage, parsed_data->ref_data.ver1.digi, ctx->chars_first_step.coeff_a); } - static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param) { if (v_cali_1 == 0 || param->term_num == 0) { diff --git a/components/esp_adc/adc_common.c b/components/esp_adc/adc_common.c index c7f4e100296a..4a2da9625b00 100644 --- a/components/esp_adc/adc_common.c +++ b/components/esp_adc/adc_common.c @@ -17,7 +17,6 @@ #include "hal/adc_hal_common.h" #include "soc/adc_periph.h" - static const char *TAG = "adc_common"; static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED; extern portMUX_TYPE rtc_spinlock; diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index ebaf348003fb..a52799210d25 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -197,7 +197,7 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi } ret = esp_intr_alloc(spicommon_irqdma_source_for_host(adc_ctx->spi_host), ESP_INTR_FLAG_IRAM, adc_dma_intr_handler, - (void *)adc_ctx, &adc_ctx->dma_intr_hdl); + (void *)adc_ctx, &adc_ctx->dma_intr_hdl); if (ret != ESP_OK) { goto cleanup; } @@ -213,7 +213,7 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi adc_ctx->i2s_host = I2S_NUM_0; ret = esp_intr_alloc(i2s_periph_signal[adc_ctx->i2s_host].irq, ESP_INTR_FLAG_IRAM, adc_dma_intr_handler, - (void *)adc_ctx, &adc_ctx->dma_intr_hdl); + (void *)adc_ctx, &adc_ctx->dma_intr_hdl); if (ret != ESP_OK) { goto cleanup; } diff --git a/components/esp_adc/adc_continuous_internal.h b/components/esp_adc/adc_continuous_internal.h index 3673cf6833d3..e78787ba975c 100644 --- a/components/esp_adc/adc_continuous_internal.h +++ b/components/esp_adc/adc_continuous_internal.h @@ -106,7 +106,6 @@ struct adc_continuous_ctx_t { #endif }; - #ifdef __cplusplus } #endif diff --git a/components/esp_adc/adc_filter.c b/components/esp_adc/adc_filter.c index 672b5acd5ab0..da8ead99ea5b 100644 --- a/components/esp_adc/adc_filter.c +++ b/components/esp_adc/adc_filter.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,13 +20,12 @@ static const char *TAG = "adc_filter"; static portMUX_TYPE s_filter_spinlock = portMUX_INITIALIZER_UNLOCKED; - #if SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED static atomic_bool s_adc_filter_claimed[SOC_ADC_DIGI_IIR_FILTER_NUM] = {ATOMIC_VAR_INIT(false), #if (SOC_ADC_DIGI_IIR_FILTER_NUM >= 2) -ATOMIC_VAR_INIT(false) + ATOMIC_VAR_INIT(false) #endif -}; + }; static esp_err_t s_adc_filter_claim(adc_continuous_handle_t handle, adc_iir_filter_t *filter_ctx, adc_unit_t unit) { @@ -87,7 +86,6 @@ static esp_err_t s_adc_filter_free(adc_iir_filter_t *filter_ctx) } #endif - esp_err_t adc_new_continuous_iir_filter(adc_continuous_handle_t handle, const adc_continuous_iir_filter_config_t *config, adc_iir_filter_handle_t *ret_hdl) { esp_err_t ret = ESP_FAIL; diff --git a/components/esp_adc/adc_monitor.c b/components/esp_adc/adc_monitor.c index 75ceaf4674cf..8bdeeddd85a1 100644 --- a/components/esp_adc/adc_monitor.c +++ b/components/esp_adc/adc_monitor.c @@ -28,7 +28,6 @@ typedef struct adc_monitor_platform_t { // Global context of adc monitor, other member will be lazy loaded static adc_monitor_platform_t s_adc_monitor_platform = {.monitor_spinlock = portMUX_INITIALIZER_UNLOCKED}; - #if CONFIG_IDF_TARGET_ESP32S2 // Monitor unit index need equal to ADC unit index on ESP32S2 static atomic_bool s_adc_monitor_claimed[SOC_ADC_DIGI_MONITOR_NUM] = {}; diff --git a/components/esp_adc/adc_oneshot.c b/components/esp_adc/adc_oneshot.c index 84b3cd33238b..dba3fd6b1ca5 100644 --- a/components/esp_adc/adc_oneshot.c +++ b/components/esp_adc/adc_oneshot.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,18 +25,15 @@ #include "hal/adc_ll.h" #include "soc/adc_periph.h" - #if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM #define ADC_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else #define ADC_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif - extern portMUX_TYPE rtc_spinlock; static const char *TAG = "adc_oneshot"; - typedef struct adc_oneshot_unit_ctx_t { adc_oneshot_hal_ctx_t hal; uint32_t unit_id; @@ -49,20 +46,17 @@ typedef struct adc_oneshot_ctx_t { int apb_periph_ref_cnts; //For the chips that ADC oneshot mode using APB_SARADC periph } adc_oneshot_ctx_t; - static adc_oneshot_ctx_t s_ctx; //ADC oneshot mode context static atomic_bool s_adc_unit_claimed[SOC_ADC_PERIPH_NUM] = {ATOMIC_VAR_INIT(false), #if (SOC_ADC_PERIPH_NUM >= 2) -ATOMIC_VAR_INIT(false) + ATOMIC_VAR_INIT(false) #endif -}; - + }; static bool s_adc_unit_claim(adc_unit_t unit); static bool s_adc_unit_free(adc_unit_t unit); static esp_err_t s_adc_io_init(adc_unit_t unit, adc_channel_t channel); - esp_err_t adc_oneshot_io_to_channel(int io_num, adc_unit_t * const unit_id, adc_channel_t * const channel) { return adc_io_to_channel(io_num, unit_id, channel); diff --git a/components/esp_adc/curve_fitting_coefficients.h b/components/esp_adc/curve_fitting_coefficients.h index 9c35d724b5b1..a4620237ad26 100644 --- a/components/esp_adc/curve_fitting_coefficients.h +++ b/components/esp_adc/curve_fitting_coefficients.h @@ -15,7 +15,7 @@ extern "C" { typedef struct { uint8_t term_num; ///< Term number of the algorithm formula const uint64_t (*coeff)[2]; ///< Coeff of each term. See `adc_error_coef_atten` for details (and the magic number 2) - const int32_t (*sign); ///< Sign of each term + const int32_t (*sign); ///< Sign of each term } cali_chars_second_step_t; /** diff --git a/components/esp_adc/deprecated/esp32/esp_adc_cal_legacy.c b/components/esp_adc/deprecated/esp32/esp_adc_cal_legacy.c index 58cd8476cb1d..08603733d124 100644 --- a/components/esp_adc/deprecated/esp32/esp_adc_cal_legacy.c +++ b/components/esp_adc/deprecated/esp32/esp_adc_cal_legacy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,13 +85,17 @@ static const uint32_t adc2_vref_atten_offset[4] = {63, 66, 89, 128}; //20 Point lookup tables, covering ADC readings from 2880 to 4096, step size of 64 static const uint32_t lut_adc1_low[LUT_POINTS] = {2240, 2297, 2352, 2405, 2457, 2512, 2564, 2616, 2664, 2709, - 2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060}; + 2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060 + }; static const uint32_t lut_adc1_high[LUT_POINTS] = {2667, 2706, 2745, 2780, 2813, 2844, 2873, 2901, 2928, 2956, - 2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209}; + 2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209 + }; static const uint32_t lut_adc2_low[LUT_POINTS] = {2238, 2293, 2347, 2399, 2451, 2507, 2561, 2613, 2662, 2710, - 2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059}; + 2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059 + }; static const uint32_t lut_adc2_high[LUT_POINTS] = {2657, 2698, 2738, 2774, 2807, 2838, 2867, 2894, 2921, 2946, - 2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185}; + 2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185 + }; /* ----------------------- EFuse Access Functions --------------------------- */ static bool check_efuse_vref(void) diff --git a/components/esp_adc/deprecated/esp32c3/esp_adc_cal_legacy.c b/components/esp_adc/deprecated/esp32c3/esp_adc_cal_legacy.c index 1755344799bf..74213defc962 100644 --- a/components/esp_adc/deprecated/esp32c3/esp_adc_cal_legacy.c +++ b/components/esp_adc/deprecated/esp32c3/esp_adc_cal_legacy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,7 +20,6 @@ const static char LOG_TAG[] = "ADC_CALI"; - /* ------------------------ Characterization Constants ---------------------- */ // coeff_a is actually a float number @@ -41,21 +40,21 @@ static const int coeff_a_scaling = 65536; * @note ADC1 and ADC2 use same coeffients */ const static uint64_t adc_error_coef_atten[4][5][2] = { - {{225966470500043, 1e15}, {7265418501948, 1e16}, {109410402681, 1e16}, {0, 0}, {0, 0}}, //atten0 - {{4229623392600516, 1e16}, {731527490903, 1e16}, {88166562521, 1e16}, {0, 0}, {0, 0}}, //atten1 - {{1017859239236435, 1e15}, {97159265299153, 1e16}, {149794028038, 1e16}, {0, 0}, {0, 0}}, //atten2 - {{14912262772850453, 1e16}, {228549975564099, 1e16}, {356391935717, 1e16}, {179964582, 1e16}, {42046, 1e16}} //atten3 - }; + {{225966470500043, 1e15}, {7265418501948, 1e16}, {109410402681, 1e16}, {0, 0}, {0, 0}}, //atten0 + {{4229623392600516, 1e16}, {731527490903, 1e16}, {88166562521, 1e16}, {0, 0}, {0, 0}}, //atten1 + {{1017859239236435, 1e15}, {97159265299153, 1e16}, {149794028038, 1e16}, {0, 0}, {0, 0}}, //atten2 + {{14912262772850453, 1e16}, {228549975564099, 1e16}, {356391935717, 1e16}, {179964582, 1e16}, {42046, 1e16}} //atten3 +}; /** * Term sign * @note ADC1 and ADC2 use same coeffients */ const static int32_t adc_error_sign[4][5] = { - {-1, -1, 1, 0, 0}, //atten0 - { 1, -1, 1, 0, 0}, //atten1 - {-1, -1, 1, 0, 0}, //atten2 - {-1, -1, 1, -1, 1} //atten3 - }; + {-1, -1, 1, 0, 0}, //atten0 + { 1, -1, 1, 0, 0}, //atten1 + {-1, -1, 1, 0, 0}, //atten2 + {-1, -1, 1, -1, 1} //atten3 +}; /* -------------------- Characterization Helper Data Types ------------------ */ typedef struct { @@ -122,10 +121,10 @@ esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source) } esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, - adc_atten_t atten, - adc_bits_width_t bit_width, - uint32_t default_vref, - esp_adc_cal_characteristics_t *chars) + adc_atten_t atten, + adc_bits_width_t bit_width, + uint32_t default_vref, + esp_adc_cal_characteristics_t *chars) { esp_err_t ret; adc_calib_parsed_info_t efuse_parsed_data = {0}; diff --git a/components/esp_adc/deprecated/esp32s2/esp_adc_cal_legacy.c b/components/esp_adc/deprecated/esp32s2/esp_adc_cal_legacy.c index e995541c96f0..6e92f8f37e89 100644 --- a/components/esp_adc/deprecated/esp32s2/esp_adc_cal_legacy.c +++ b/components/esp_adc/deprecated/esp32s2/esp_adc_cal_legacy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -105,11 +105,11 @@ static bool prepare_calib_data_for(adc_unit_t adc_num, adc_atten_t atten, adc_ca * */ static void characterize_using_two_point(adc_unit_t adc_num, - adc_atten_t atten, - uint32_t high, - uint32_t low, - uint32_t *coeff_a, - uint32_t *coeff_b) + adc_atten_t atten, + uint32_t high, + uint32_t low, + uint32_t *coeff_a, + uint32_t *coeff_b) { // once we have recovered the reference high(Dhigh) and low(Dlow) readings, we can calculate a and b from // the measured high and low readings @@ -161,10 +161,10 @@ esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source) } esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, - adc_atten_t atten, - adc_bits_width_t bit_width, - uint32_t default_vref, - esp_adc_cal_characteristics_t *chars) + adc_atten_t atten, + adc_bits_width_t bit_width, + uint32_t default_vref, + esp_adc_cal_characteristics_t *chars) { bool res __attribute__((unused)); adc_calib_parsed_info efuse_parsed_data = {0}; diff --git a/components/esp_adc/deprecated/esp32s3/esp_adc_cal_legacy.c b/components/esp_adc/deprecated/esp32s3/esp_adc_cal_legacy.c index 0c6945d81344..a37cf01655e6 100644 --- a/components/esp_adc/deprecated/esp32s3/esp_adc_cal_legacy.c +++ b/components/esp_adc/deprecated/esp32s3/esp_adc_cal_legacy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,32 +39,32 @@ static const int coeff_a_scaling = 1000000; * @note Above formula is rewritten from the original documentation, please note that the coefficients are re-ordered. */ const static uint64_t adc1_error_coef_atten[4][5][2] = { - {{27856531419538344, 1e16}, {50871540569528, 1e16}, {9798249589, 1e15}, {0, 0}, {0, 0}}, //ADC1 atten0 - {{29831022915028695, 1e16}, {49393185868806, 1e16}, {101379430548, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten1 - {{23285545746296417, 1e16}, {147640181047414, 1e16}, {208385525314, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten2 - {{644403418269478, 1e15}, {644334888647536, 1e16}, {1297891447611, 1e16}, {70769718, 1e15}, {13515, 1e15}} //ADC1 atten3 - }; + {{27856531419538344, 1e16}, {50871540569528, 1e16}, {9798249589, 1e15}, {0, 0}, {0, 0}}, //ADC1 atten0 + {{29831022915028695, 1e16}, {49393185868806, 1e16}, {101379430548, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten1 + {{23285545746296417, 1e16}, {147640181047414, 1e16}, {208385525314, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten2 + {{644403418269478, 1e15}, {644334888647536, 1e16}, {1297891447611, 1e16}, {70769718, 1e15}, {13515, 1e15}} //ADC1 atten3 +}; const static uint64_t adc2_error_coef_atten[4][5][2] = { - {{25668651654328927, 1e16}, {1353548869615, 1e16}, {36615265189, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten0 - {{23690184690298404, 1e16}, {66319894226185, 1e16}, {118964995959, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten1 - {{9452499397020617, 1e16}, {200996773954387, 1e16}, {259011467956, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten2 - {{12247719764336924,1e16}, {755717904943462, 1e16}, {1478791187119, 1e16}, {79672528, 1e15}, {15038, 1e15}} //ADC2 atten3 - }; + {{25668651654328927, 1e16}, {1353548869615, 1e16}, {36615265189, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten0 + {{23690184690298404, 1e16}, {66319894226185, 1e16}, {118964995959, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten1 + {{9452499397020617, 1e16}, {200996773954387, 1e16}, {259011467956, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten2 + {{12247719764336924, 1e16}, {755717904943462, 1e16}, {1478791187119, 1e16}, {79672528, 1e15}, {15038, 1e15}} //ADC2 atten3 +}; /** * Term sign */ const static int32_t adc1_error_sign[4][5] = { - {-1, -1, 1, 0, 0}, //ADC1 atten0 - {-1, -1, 1, 0, 0}, //ADC1 atten1 - {-1, -1, 1, 0, 0}, //ADC1 atten2 - {-1, -1, 1, -1, 1} //ADC1 atten3 - }; + {-1, -1, 1, 0, 0}, //ADC1 atten0 + {-1, -1, 1, 0, 0}, //ADC1 atten1 + {-1, -1, 1, 0, 0}, //ADC1 atten2 + {-1, -1, 1, -1, 1} //ADC1 atten3 +}; const static int32_t adc2_error_sign[4][5] = { - {-1, 1, 1, 0, 0}, //ADC2 atten0 - {-1, -1, 1, 0, 0}, //ADC2 atten1 - {-1, -1, 1, 0, 0}, //ADC2 atten2 - { 1, -1, 1, -1, 1} //ADC2 atten3 - }; + {-1, 1, 1, 0, 0}, //ADC2 atten0 + {-1, -1, 1, 0, 0}, //ADC2 atten1 + {-1, -1, 1, 0, 0}, //ADC2 atten2 + { 1, -1, 1, -1, 1} //ADC2 atten3 +}; /* -------------------- Characterization Helper Data Types ------------------ */ typedef struct { @@ -81,7 +81,6 @@ typedef struct { } ref_data; } adc_calib_info_t; - //To get the reference point (Dout, Vin) static esp_err_t get_reference_point(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_info_t *calib_info) { @@ -125,10 +124,10 @@ static void calculate_characterization_coefficients(const adc_calib_info_t *pars } esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, - adc_atten_t atten, - adc_bits_width_t bit_width, - uint32_t default_vref, - esp_adc_cal_characteristics_t *chars) + adc_atten_t atten, + adc_bits_width_t bit_width, + uint32_t default_vref, + esp_adc_cal_characteristics_t *chars) { (void) default_vref; @@ -176,8 +175,8 @@ uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_char esp_adc_error_calc_param_t param = { .v_cali_input = v_cali_1, .term_num = (chars->atten == 3) ? 5 : 3, - .coeff = (chars->adc_num == ADC_UNIT_1) ? &adc1_error_coef_atten : &adc2_error_coef_atten, - .sign = (chars->adc_num == ADC_UNIT_1) ? &adc1_error_sign : &adc2_error_sign, + .coeff = (chars->adc_num == ADC_UNIT_1) ? &adc1_error_coef_atten :&adc2_error_coef_atten, + .sign = (chars->adc_num == ADC_UNIT_1) ? &adc1_error_sign :&adc2_error_sign, }; error = esp_adc_cal_get_reading_error(¶m, chars->atten); diff --git a/components/esp_adc/deprecated/esp_adc_cal_common_legacy.c b/components/esp_adc/deprecated/esp_adc_cal_common_legacy.c index a990466394cd..982f7c9f7c47 100644 --- a/components/esp_adc/deprecated/esp_adc_cal_common_legacy.c +++ b/components/esp_adc/deprecated/esp_adc_cal_common_legacy.c @@ -46,7 +46,6 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, return ret; } - #if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED /*------------------------------------------------------------------------------ * Private API @@ -79,7 +78,7 @@ int32_t esp_adc_cal_get_reading_error(const esp_adc_error_calc_param_t *param, u error = (int32_t)term[0] * (*param->sign)[atten][0]; for (int i = 1; i < term_num; i++) { - variable[i] = variable[i-1] * v_cali_1; + variable[i] = variable[i - 1] * v_cali_1; coeff = (*param->coeff)[atten][i][0]; term[i] = variable[i] * coeff; ESP_LOGV(TAG, "big coef is %llu, big term%d is %llu, coef_id is %d", coeff, i, term[i], i); diff --git a/components/esp_adc/deprecated/esp_adc_cal_internal_legacy.h b/components/esp_adc/deprecated/esp_adc_cal_internal_legacy.h index 518c397f5b40..3f2218e8ba1b 100644 --- a/components/esp_adc/deprecated/esp_adc_cal_internal_legacy.h +++ b/components/esp_adc/deprecated/esp_adc_cal_internal_legacy.h @@ -31,7 +31,7 @@ typedef struct { uint64_t v_cali_input; //Input to calculate the error uint8_t term_num; //Term number of the algorithm formula const uint64_t (*coeff)[COEFF_GROUP_NUM][TERM_MAX][2]; //Coeff of each term. See `adc_error_coef_atten` for details (and the magic number 2) - const int32_t (*sign)[COEFF_GROUP_NUM][TERM_MAX]; //Sign of each term + const int32_t (*sign)[COEFF_GROUP_NUM][TERM_MAX]; //Sign of each term } esp_adc_error_calc_param_t; /** @@ -44,7 +44,6 @@ int32_t esp_adc_cal_get_reading_error(const esp_adc_error_calc_param_t *param, u #endif //#if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED - #ifdef __cplusplus } #endif diff --git a/components/esp_adc/deprecated/include/esp_adc_cal_types_legacy.h b/components/esp_adc/deprecated/include/esp_adc_cal_types_legacy.h index 7c366afabe3e..613f09a4c641 100644 --- a/components/esp_adc/deprecated/include/esp_adc_cal_types_legacy.h +++ b/components/esp_adc/deprecated/include/esp_adc_cal_types_legacy.h @@ -44,7 +44,6 @@ typedef struct { } esp_adc_cal_characteristics_t; #endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - #ifdef __cplusplus } #endif diff --git a/components/esp_adc/esp32/adc_cali_line_fitting.c b/components/esp_adc/esp32/adc_cali_line_fitting.c index 0421b27fd406..adf79c4c3fbc 100644 --- a/components/esp_adc/esp32/adc_cali_line_fitting.c +++ b/components/esp_adc/esp32/adc_cali_line_fitting.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -88,17 +88,20 @@ static const uint32_t adc2_vref_atten_offset[4] = {63, 66, 89, 128}; //20 Point lookup tables, covering ADC readings from 2880 to 4096, step size of 64 static const uint32_t lut_adc1_low[LUT_POINTS] = {2240, 2297, 2352, 2405, 2457, 2512, 2564, 2616, 2664, 2709, - 2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060}; + 2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060 + }; static const uint32_t lut_adc1_high[LUT_POINTS] = {2667, 2706, 2745, 2780, 2813, 2844, 2873, 2901, 2928, 2956, - 2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209}; + 2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209 + }; static const uint32_t lut_adc2_low[LUT_POINTS] = {2238, 2293, 2347, 2399, 2451, 2507, 2561, 2613, 2662, 2710, - 2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059}; + 2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059 + }; static const uint32_t lut_adc2_high[LUT_POINTS] = {2657, 2698, 2738, 2774, 2807, 2838, 2867, 2894, 2921, 2946, - 2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185}; + 2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185 + }; const __attribute__((unused)) static char *TAG = "adc_cali"; - /* ----------------------- EFuse Access Functions --------------------------- */ static bool check_efuse_vref(void); static bool check_efuse_tp(void); @@ -107,7 +110,6 @@ static uint32_t read_efuse_vref(void); static uint32_t read_efuse_tp_low(adc_unit_t unit_id); static uint32_t read_efuse_tp_high(adc_unit_t unit_id); - /* ----------------------- Characterization Functions ----------------------- */ static void characterize_using_two_point(adc_unit_t unit_id, adc_atten_t atten, @@ -121,7 +123,6 @@ static void characterize_using_vref(adc_unit_t unit_id, uint32_t *coeff_a, uint32_t *coeff_b); - /* ------------------------ Conversion Functions --------------------------- */ static uint32_t calculate_voltage_linear(uint32_t adc_reading, uint32_t coeff_a, uint32_t coeff_b); //Only call when ADC reading is above threshold @@ -133,11 +134,9 @@ static inline uint32_t interpolate_two_points(uint32_t y1, uint32_t y2, uint32_t return ((y1 * x_step) + (y2 * x) - (y1 * x) + (x_step / 2)) / x_step; } - /* ------------------------ Interface Functions --------------------------- */ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage); - /* ------------------------ Context Structure--------------------------- */ typedef struct { adc_unit_t unit_id; ///< ADC unit @@ -151,7 +150,6 @@ typedef struct { adc_cali_line_fitting_efuse_val_t efuse_val; ///< Type of calibration value used in characterization } cali_chars_line_fitting_t; - /* ------------------------- Public API ------------------------------------- */ esp_err_t adc_cali_create_scheme_line_fitting(const adc_cali_line_fitting_config_t *config, adc_cali_handle_t *ret_handle) { @@ -350,7 +348,6 @@ static uint32_t read_efuse_tp_high(adc_unit_t unit_id) return ret; //Reading of ADC at 850mV } - /* ----------------------- Characterization Functions ----------------------- */ static void characterize_using_two_point(adc_unit_t unit_id, adc_atten_t atten, @@ -400,7 +397,6 @@ static void characterize_using_vref(adc_unit_t unit_id, *coeff_b = atten_offsets[atten]; } - /* ------------------------ Conversion Functions --------------------------- */ static uint32_t calculate_voltage_linear(uint32_t adc_reading, uint32_t coeff_a, uint32_t coeff_b) { diff --git a/components/esp_adc/esp32c2/adc_cali_line_fitting.c b/components/esp_adc/esp32c2/adc_cali_line_fitting.c index 295616c05f5d..3ccf36eba435 100644 --- a/components/esp_adc/esp32c2/adc_cali_line_fitting.c +++ b/components/esp_adc/esp32c2/adc_cali_line_fitting.c @@ -17,7 +17,6 @@ #include "esp_adc/adc_cali_scheme.h" #include "adc_cali_interface.h" - /** * This file contains Line Fitting Calibration Scheme for ESP32C2. * @@ -30,7 +29,6 @@ * 5. Only build this file, when `ADC_CALI_SCHEME_LINE_FITTING_V2_SUPPORTED == true` */ - // coeff_a is actually a float number // it is scaled to put them into uint32_t so that the headers do not have to be changed static const int coeff_a_scaling = 65536; @@ -43,7 +41,6 @@ typedef struct { uint32_t coeff_b; ///< Offset of ADC-Voltage characteristics } cali_chars_line_fitting_t; - /* ------------------------ Interface Functions --------------------------- */ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage); static esp_err_t check_valid(const adc_cali_line_fitting_config_t *config); @@ -107,7 +104,6 @@ esp_err_t adc_cali_delete_scheme_line_fitting(adc_cali_handle_t handle) return ESP_OK; } - /* ------------------------ Interface Functions --------------------------- */ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage) { diff --git a/components/esp_adc/esp32c3/curve_fitting_coefficients.c b/components/esp_adc/esp32c3/curve_fitting_coefficients.c index 9d8bda65edf2..4ef3a058d1f6 100644 --- a/components/esp_adc/esp32c3/curve_fitting_coefficients.c +++ b/components/esp_adc/esp32c3/curve_fitting_coefficients.c @@ -24,20 +24,20 @@ * @note ADC1 and ADC2 use same coefficients */ const static uint64_t adc1_error_coef_atten[COEFF_GROUP_NUM][TERM_MAX][2] = { - {{225966470500043, 1e15}, {7265418501948, 1e16}, {109410402681, 1e16}, {0, 0}, {0, 0}}, //atten0 - {{4229623392600516, 1e16}, {731527490903, 1e16}, {88166562521, 1e16}, {0, 0}, {0, 0}}, //atten1 - {{1017859239236435, 1e15}, {97159265299153, 1e16}, {149794028038, 1e16}, {0, 0}, {0, 0}}, //atten2 - {{14912262772850453, 1e16}, {228549975564099, 1e16}, {356391935717, 1e16}, {179964582, 1e16}, {42046, 1e16}} //atten3 - }; + {{225966470500043, 1e15}, {7265418501948, 1e16}, {109410402681, 1e16}, {0, 0}, {0, 0}}, //atten0 + {{4229623392600516, 1e16}, {731527490903, 1e16}, {88166562521, 1e16}, {0, 0}, {0, 0}}, //atten1 + {{1017859239236435, 1e15}, {97159265299153, 1e16}, {149794028038, 1e16}, {0, 0}, {0, 0}}, //atten2 + {{14912262772850453, 1e16}, {228549975564099, 1e16}, {356391935717, 1e16}, {179964582, 1e16}, {42046, 1e16}} //atten3 +}; /** * Term sign */ const static int32_t adc1_error_sign[COEFF_GROUP_NUM][TERM_MAX] = { - {-1, -1, 1, 0, 0}, //atten0 - { 1, -1, 1, 0, 0}, //atten1 - {-1, -1, 1, 0, 0}, //atten2 - {-1, -1, 1, -1, 1} //atten3 - }; + {-1, -1, 1, 0, 0}, //atten0 + { 1, -1, 1, 0, 0}, //atten1 + {-1, -1, 1, 0, 0}, //atten2 + {-1, -1, 1, -1, 1} //atten3 +}; void curve_fitting_get_second_step_coeff(const adc_cali_curve_fitting_config_t *config, cali_chars_second_step_t *ctx) { diff --git a/components/esp_adc/esp32c6/curve_fitting_coefficients.c b/components/esp_adc/esp32c6/curve_fitting_coefficients.c index 588c318b9694..b0be52b64359 100644 --- a/components/esp_adc/esp32c6/curve_fitting_coefficients.c +++ b/components/esp_adc/esp32c6/curve_fitting_coefficients.c @@ -38,7 +38,7 @@ const static uint64_t adc1_error_coef_atten[COEFF_VERSION_NUM][COEFF_GROUP_NUM][ {{0, 0}, {0, 0}, {0, 0}}, //atten0 {{0, 0}, {0, 0}, {0, 0}}, //atten1 {{12217864764388775, 1e16}, {1954123107752, 1e16}, {6409679727, 1e16}}, //atten2 - {{3915910437042445 , 1e16}, {31536470857564, 1e16}, {12493873014, 1e16}}, //atten3 + {{3915910437042445, 1e16}, {31536470857564, 1e16}, {12493873014, 1e16}}, //atten3 }, }; @@ -62,7 +62,6 @@ const static int32_t adc1_error_sign[COEFF_VERSION_NUM][COEFF_GROUP_NUM][TERM_MA }, }; - void curve_fitting_get_second_step_coeff(const adc_cali_curve_fitting_config_t *config, cali_chars_second_step_t *ctx) { uint32_t adc_calib_ver = esp_efuse_rtc_calib_get_ver(); diff --git a/components/esp_adc/esp32s2/adc_cali_line_fitting.c b/components/esp_adc/esp32s2/adc_cali_line_fitting.c index a14e91235386..87ec4e7e3ed2 100644 --- a/components/esp_adc/esp32s2/adc_cali_line_fitting.c +++ b/components/esp_adc/esp32s2/adc_cali_line_fitting.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,6 @@ const __attribute__((unused)) static char *TAG = "adc_cali"; static const int coeff_a_scaling = 65536; static const int coeff_b_scaling = 1024; - /* -------------------- Characterization Helper Data Types ------------------ */ typedef struct { int adc_calib_high; @@ -49,7 +48,6 @@ typedef struct { } efuse_data; } adc_calib_parsed_info_t; - /* ------------------------ Context Structure--------------------------- */ typedef struct { adc_unit_t unit_id; ///< ADC unit @@ -58,7 +56,6 @@ typedef struct { uint32_t coeff_b; ///< Offset of ADC-Voltage curve } cali_chars_line_fitting_t; - /* ----------------------- Characterization Functions ----------------------- */ static bool prepare_calib_data_for(adc_unit_t unit_id, adc_atten_t atten, adc_calib_parsed_info_t *parsed_data_storage); /** @@ -71,22 +68,20 @@ static bool prepare_calib_data_for(adc_unit_t unit_id, adc_atten_t atten, adc_ca * */ static void characterize_using_two_point(adc_unit_t unit_id, - adc_atten_t atten, - uint32_t high, - uint32_t low, - uint32_t *coeff_a, - uint32_t *coeff_b); + adc_atten_t atten, + uint32_t high, + uint32_t low, + uint32_t *coeff_a, + uint32_t *coeff_b); /* * Estimate the (assumed) linear relationship btwn the measured raw value and the voltage * with the previously done measurement when the chip was manufactured. * */ static bool calculate_characterization_coefficients(const adc_calib_parsed_info_t *parsed_data, cali_chars_line_fitting_t *ctx); - /* ------------------------ Interface Functions --------------------------- */ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage); - /* ------------------------- Public API ------------------------------------- */ esp_err_t adc_cali_create_scheme_line_fitting(const adc_cali_line_fitting_config_t *config, adc_cali_handle_t *ret_handle) { @@ -142,7 +137,6 @@ esp_err_t adc_cali_delete_scheme_line_fitting(adc_cali_handle_t handle) return ESP_OK; } - /* ------------------------ Interface Functions --------------------------- */ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage) { @@ -154,7 +148,6 @@ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage) return ESP_OK; } - /* ----------------------- Characterization Functions ----------------------- */ static bool prepare_calib_data_for(adc_unit_t unit_id, adc_atten_t atten, adc_calib_parsed_info_t *parsed_data_storage) { @@ -213,11 +206,11 @@ static bool prepare_calib_data_for(adc_unit_t unit_id, adc_atten_t atten, adc_ca * */ static void characterize_using_two_point(adc_unit_t unit_id, - adc_atten_t atten, - uint32_t high, - uint32_t low, - uint32_t *coeff_a, - uint32_t *coeff_b) + adc_atten_t atten, + uint32_t high, + uint32_t low, + uint32_t *coeff_a, + uint32_t *coeff_b) { // once we have recovered the reference high(Dhigh) and low(Dlow) readings, we can calculate a and b from // the measured high and low readings @@ -244,7 +237,7 @@ static bool calculate_characterization_coefficients(const adc_calib_parsed_info_ case 2: ESP_LOGD(TAG, "Calib V2, volt%dmV", parsed_data->efuse_data.ver2.adc_calib_high); ctx->coeff_a = coeff_a_scaling * parsed_data->efuse_data.ver2.adc_calib_high_voltage / - parsed_data->efuse_data.ver2.adc_calib_high; + parsed_data->efuse_data.ver2.adc_calib_high; ctx->coeff_b = 0; break; default: diff --git a/components/esp_adc/esp32s3/curve_fitting_coefficients.c b/components/esp_adc/esp32s3/curve_fitting_coefficients.c index 74a500da31f1..ea10cfeb66e4 100644 --- a/components/esp_adc/esp32s3/curve_fitting_coefficients.c +++ b/components/esp_adc/esp32s3/curve_fitting_coefficients.c @@ -24,32 +24,32 @@ * @note Above formula is rewritten from the original documentation, please note that the coefficients are re-ordered. */ const static uint64_t adc1_error_coef_atten[COEFF_GROUP_NUM][TERM_MAX][2] = { - {{27856531419538344, 1e16}, {50871540569528, 1e16}, {9798249589, 1e15}, {0, 0}, {0, 0}}, //ADC1 atten0 - {{29831022915028695, 1e16}, {49393185868806, 1e16}, {101379430548, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten1 - {{23285545746296417, 1e16}, {147640181047414, 1e16}, {208385525314, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten2 - {{644403418269478, 1e15}, {644334888647536, 1e16}, {1297891447611, 1e16}, {70769718, 1e15}, {13515, 1e15}} //ADC1 atten3 - }; + {{27856531419538344, 1e16}, {50871540569528, 1e16}, {9798249589, 1e15}, {0, 0}, {0, 0}}, //ADC1 atten0 + {{29831022915028695, 1e16}, {49393185868806, 1e16}, {101379430548, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten1 + {{23285545746296417, 1e16}, {147640181047414, 1e16}, {208385525314, 1e16}, {0, 0}, {0, 0}}, //ADC1 atten2 + {{644403418269478, 1e15}, {644334888647536, 1e16}, {1297891447611, 1e16}, {70769718, 1e15}, {13515, 1e15}} //ADC1 atten3 +}; const static uint64_t adc2_error_coef_atten[COEFF_GROUP_NUM][TERM_MAX][2] = { - {{25668651654328927, 1e16}, {1353548869615, 1e16}, {36615265189, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten0 - {{23690184690298404, 1e16}, {66319894226185, 1e16}, {118964995959, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten1 - {{9452499397020617, 1e16}, {200996773954387, 1e16}, {259011467956, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten2 - {{12247719764336924,1e16}, {755717904943462, 1e16}, {1478791187119, 1e16}, {79672528, 1e15}, {15038, 1e15}} //ADC2 atten3 - }; + {{25668651654328927, 1e16}, {1353548869615, 1e16}, {36615265189, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten0 + {{23690184690298404, 1e16}, {66319894226185, 1e16}, {118964995959, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten1 + {{9452499397020617, 1e16}, {200996773954387, 1e16}, {259011467956, 1e16}, {0, 0}, {0, 0}}, //ADC2 atten2 + {{12247719764336924, 1e16}, {755717904943462, 1e16}, {1478791187119, 1e16}, {79672528, 1e15}, {15038, 1e15}} //ADC2 atten3 +}; /** * Term sign */ const static int32_t adc1_error_sign[COEFF_GROUP_NUM][TERM_MAX] = { - {-1, -1, 1, 0, 0}, //ADC1 atten0 - {-1, -1, 1, 0, 0}, //ADC1 atten1 - {-1, -1, 1, 0, 0}, //ADC1 atten2 - {-1, -1, 1, -1, 1} //ADC1 atten3 - }; + {-1, -1, 1, 0, 0}, //ADC1 atten0 + {-1, -1, 1, 0, 0}, //ADC1 atten1 + {-1, -1, 1, 0, 0}, //ADC1 atten2 + {-1, -1, 1, -1, 1} //ADC1 atten3 +}; const static int32_t adc2_error_sign[COEFF_GROUP_NUM][TERM_MAX] = { - {-1, 1, 1, 0, 0}, //ADC2 atten0 - {-1, -1, 1, 0, 0}, //ADC2 atten1 - {-1, -1, 1, 0, 0}, //ADC2 atten2 - { 1, -1, 1, -1, 1} //ADC2 atten3 - }; + {-1, 1, 1, 0, 0}, //ADC2 atten0 + {-1, -1, 1, 0, 0}, //ADC2 atten1 + {-1, -1, 1, 0, 0}, //ADC2 atten2 + { 1, -1, 1, -1, 1} //ADC2 atten3 +}; void curve_fitting_get_second_step_coeff(const adc_cali_curve_fitting_config_t *config, cali_chars_second_step_t *ctx) { diff --git a/components/esp_adc/include/esp_adc/adc_cali.h b/components/esp_adc/include/esp_adc/adc_cali.h index b9b949b19f09..205760151044 100644 --- a/components/esp_adc/include/esp_adc/adc_cali.h +++ b/components/esp_adc/include/esp_adc/adc_cali.h @@ -53,7 +53,6 @@ esp_err_t adc_cali_check_scheme(adc_cali_scheme_ver_t *scheme_mask); */ esp_err_t adc_cali_raw_to_voltage(adc_cali_handle_t handle, int raw, int *voltage); - #ifdef __cplusplus } #endif diff --git a/components/esp_adc/include/esp_adc/adc_cali_scheme.h b/components/esp_adc/include/esp_adc/adc_cali_scheme.h index 8894c66c1f00..80889096acf3 100644 --- a/components/esp_adc/include/esp_adc/adc_cali_scheme.h +++ b/components/esp_adc/include/esp_adc/adc_cali_scheme.h @@ -15,7 +15,6 @@ extern "C" { #endif - #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED /*--------------------------------------------------------------- Curve Fitting Calibration Scheme @@ -56,7 +55,6 @@ esp_err_t adc_cali_create_scheme_curve_fitting(const adc_cali_curve_fitting_conf esp_err_t adc_cali_delete_scheme_curve_fitting(adc_cali_handle_t handle); #endif // #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED - #if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED /*--------------------------------------------------------------- Line Fitting Calibration Scheme diff --git a/components/esp_adc/include/esp_adc/adc_continuous.h b/components/esp_adc/include/esp_adc/adc_continuous.h index 7f8aec4a89bd..99b2b269d573 100644 --- a/components/esp_adc/include/esp_adc/adc_continuous.h +++ b/components/esp_adc/include/esp_adc/adc_continuous.h @@ -16,7 +16,6 @@ extern "C" { #endif - /* * Driver Backgrounds * @@ -239,7 +238,6 @@ esp_err_t adc_continuous_io_to_channel(int io_num, adc_unit_t * const unit_id, a */ esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int * const io_num); - #ifdef __cplusplus } #endif diff --git a/components/esp_adc/include/esp_adc/adc_filter.h b/components/esp_adc/include/esp_adc/adc_filter.h index 973ccf0d26ed..bc34dcfc8d23 100644 --- a/components/esp_adc/include/esp_adc/adc_filter.h +++ b/components/esp_adc/include/esp_adc/adc_filter.h @@ -31,7 +31,6 @@ typedef struct { adc_digi_iir_filter_coeff_t coeff; ///< ADC filter coefficient } adc_continuous_iir_filter_config_t; - /** * @brief New an ADC continuous mode IIR filter * diff --git a/components/esp_adc/include/esp_adc/adc_monitor.h b/components/esp_adc/include/esp_adc/adc_monitor.h index c6a37695c79e..8066771a2e79 100644 --- a/components/esp_adc/include/esp_adc/adc_monitor.h +++ b/components/esp_adc/include/esp_adc/adc_monitor.h @@ -6,7 +6,6 @@ #pragma once - #include "adc_continuous.h" #ifdef __cplusplus @@ -48,7 +47,6 @@ typedef struct { adc_monitor_evt_cb_t on_below_low_thresh; /*!< adc_monitor low value interrupt callback */ } adc_monitor_evt_cbs_t; - /** * @brief Allocate an ADC continuous mode monitor (and configure it into an initial state) * diff --git a/components/esp_adc/include/esp_private/adc_private.h b/components/esp_adc/include/esp_private/adc_private.h index ae599e97c665..805614a976ac 100644 --- a/components/esp_adc/include/esp_private/adc_private.h +++ b/components/esp_adc/include/esp_private/adc_private.h @@ -11,7 +11,6 @@ #include "hal/adc_types.h" #include "soc/soc_caps.h" - #ifdef __cplusplus extern "C" { #endif @@ -33,7 +32,6 @@ void adc_apb_periph_claim(void); */ void adc_apb_periph_free(void); - /*--------------------------------------------------------------- ADC IOs ---------------------------------------------------------------*/ @@ -64,7 +62,6 @@ esp_err_t adc_io_to_channel(int io_num, adc_unit_t * const unit_id, adc_channel_ */ esp_err_t adc_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int * const io_num); - /*--------------------------------------------------------------- ADC Oneshot Read API ISR Version ---------------------------------------------------------------*/ @@ -89,7 +86,6 @@ typedef struct adc_oneshot_unit_ctx_t *adc_oneshot_unit_handle_t; */ esp_err_t adc_oneshot_read_isr(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw); - #ifdef __cplusplus } #endif diff --git a/components/esp_adc/interface/adc_cali_interface.h b/components/esp_adc/interface/adc_cali_interface.h index 751fef5276df..34edc85eb607 100644 --- a/components/esp_adc/interface/adc_cali_interface.h +++ b/components/esp_adc/interface/adc_cali_interface.h @@ -11,7 +11,6 @@ extern "C" { #endif - typedef struct adc_cali_scheme_t adc_cali_scheme_t; /** diff --git a/components/esp_adc/test_apps/adc/main/test_adc.c b/components/esp_adc/test_apps/adc/main/test_adc.c index 2fedff2b0899..30230fa4c29a 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc.c +++ b/components/esp_adc/test_apps/adc/main/test_adc.c @@ -34,7 +34,6 @@ static const char *TAG_CH[2][10] = {{"ADC1_CH4", "ADC1_CH5"}, {"ADC2_CH0"}}; static const char *TAG_CH[2][10] = {{"ADC1_CH2", "ADC1_CH3"}, {"ADC2_CH0"}}; #endif - /*--------------------------------------------------------------- ADC Oneshot High / Low test ---------------------------------------------------------------*/ @@ -95,7 +94,6 @@ TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw[1][0]); #endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 - test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 1); TEST_ESP_OK(adc_oneshot_read(adc1_handle, ADC1_TEST_CHAN0, &adc_raw[0][0])); ESP_LOGI(TAG_CH[0][0], "raw data: %d", adc_raw[0][0]); @@ -113,15 +111,12 @@ TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw[1][0]); #endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 - TEST_ESP_OK(adc_oneshot_del_unit(adc1_handle)); #if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 TEST_ESP_OK(adc_oneshot_del_unit(adc2_handle)); #endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 } - - #if SOC_ADC_CALIBRATION_V1_SUPPORTED /*--------------------------------------------------------------- ADC Oneshot with Light Sleep @@ -224,8 +219,8 @@ static void s_adc_oneshot_with_sleep(adc_unit_t unit_id, adc_channel_t channel) ESP_LOGI(TAG, "ADC%d Chan%d: raw difference: %"PRId32, unit_id + 1, channel, raw_diff); if (do_calibration) { - int32_t cali_diff = cali_expected - cali_after_sleep; - ESP_LOGI(TAG, "ADC%d Chan%d: cali difference: %"PRId32, unit_id + 1, channel, cali_diff); + int32_t cali_diff = cali_expected - cali_after_sleep; + ESP_LOGI(TAG, "ADC%d Chan%d: cali difference: %"PRId32, unit_id + 1, channel, cali_diff); } //Test Calibration registers @@ -267,14 +262,14 @@ TEST_CASE("test ADC2 Single Read with Light Sleep", "[adc][manul][ignore]") #endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED - #if SOC_ADC_MONITOR_SUPPORTED && CONFIG_SOC_ADC_DMA_SUPPORTED #if CONFIG_IDF_TARGET_ESP32S2 #define TEST_ADC_FORMATE_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1 #else #define TEST_ADC_FORMATE_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 #endif -bool IRAM_ATTR test_high_cb(adc_monitor_handle_t monitor_handle, const adc_monitor_evt_data_t *event_data, void *user_data){ +bool IRAM_ATTR test_high_cb(adc_monitor_handle_t monitor_handle, const adc_monitor_evt_data_t *event_data, void *user_data) +{ return false; } TEST_CASE("ADC continuous monitor init_deinit", "[adc]") @@ -366,7 +361,6 @@ TEST_CASE("ADC continuous monitor init_deinit", "[adc]") TEST_ESP_OK(adc_continuous_deinit(handle)); } - /** * NOTE: To run this special feature test case, you need wire ADC channel pin you want to monit * to a wave output pin defined below. @@ -386,11 +380,13 @@ TEST_CASE("ADC continuous monitor init_deinit", "[adc]") #define TEST_WAVE_OUT_PIN GPIO_NUM_2 //GPIO_2 static uint32_t m1h_cnt, m1l_cnt; -bool IRAM_ATTR m1h_cb(adc_monitor_handle_t monitor_handle, const adc_monitor_evt_data_t *event_data, void *user_data){ +bool IRAM_ATTR m1h_cb(adc_monitor_handle_t monitor_handle, const adc_monitor_evt_data_t *event_data, void *user_data) +{ m1h_cnt ++; return false; } -bool IRAM_ATTR m1l_cb(adc_monitor_handle_t monitor_handle, const adc_monitor_evt_data_t *event_data, void *user_data){ +bool IRAM_ATTR m1l_cb(adc_monitor_handle_t monitor_handle, const adc_monitor_evt_data_t *event_data, void *user_data) +{ m1l_cnt ++; return false; } @@ -451,8 +447,7 @@ TEST_CASE("ADC continuous monitor functionary", "[adc][manual][ignore]") TEST_ESP_OK(adc_continuous_monitor_enable(monitor_handle)); TEST_ESP_OK(adc_continuous_start(handle)); - for (uint8_t i=0; i<8; i++) - { + for (uint8_t i = 0; i < 8; i++) { vTaskDelay(1000); // check monitor cb @@ -465,7 +460,7 @@ TEST_CASE("ADC continuous monitor functionary", "[adc][manual][ignore]") m1h_cnt = 0; gpio_set_level(TEST_WAVE_OUT_PIN, 0); } else { - TEST_ASSERT_UINT32_WITHIN(SOC_ADC_SAMPLE_FREQ_THRES_LOW*0.1, SOC_ADC_SAMPLE_FREQ_THRES_LOW, m1l_cnt); + TEST_ASSERT_UINT32_WITHIN(SOC_ADC_SAMPLE_FREQ_THRES_LOW * 0.1, SOC_ADC_SAMPLE_FREQ_THRES_LOW, m1l_cnt); TEST_ASSERT_LESS_THAN_UINT32(5, m1h_cnt); //Actually, it will still encountered 1~2 times because hardware run very quickly m1l_cnt = 0; gpio_set_level(TEST_WAVE_OUT_PIN, 1); diff --git a/components/esp_adc/test_apps/adc/main/test_adc_driver.c b/components/esp_adc/test_apps/adc/main/test_adc_driver.c index 04d5fb397b53..a38f4270fe86 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_driver.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_driver.c @@ -59,13 +59,11 @@ static bool IRAM_ATTR s_alarm_callback(gptimer_handle_t timer, const gptimer_ala TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw); } - // check the count value at alarm event vTaskNotifyGiveFromISR(test_ctx->task_handle, &high_task_wakeup); return high_task_wakeup == pdTRUE; } - TEST_CASE("ADC oneshot fast work with ISR", "[adc_oneshot]") { static test_adc_isr_ctx_t isr_test_ctx = {}; @@ -114,7 +112,6 @@ TEST_CASE("ADC oneshot fast work with ISR", "[adc_oneshot]") TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000))); TEST_ESP_OK(gptimer_stop(timer)); - //ADC IO tile high test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 1); isr_test_ctx.level = 1; @@ -144,7 +141,6 @@ TEST_CASE("ADC oneshot fast work with ISR", "[adc_oneshot]") #define ADC_FRAME_TEST_SIZE 8192 - static bool IRAM_ATTR NOINLINE_ATTR s_conv_done_cb_frame_size_test(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data) { test_adc_isr_ctx_t *test_ctx = (test_adc_isr_ctx_t *)user_data; @@ -206,8 +202,8 @@ TEST_CASE("ADC continuous big conv_frame_size test", "[adc_continuous]") sum += ADC_DRIVER_TEST_GET_DATA(p); cnt++; } - esp_rom_printf("avg: %d\n", sum/cnt); - TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, sum/cnt); + esp_rom_printf("avg: %d\n", sum / cnt); + TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, sum / cnt); } TEST_ESP_OK(adc_continuous_stop(handle)); @@ -215,7 +211,6 @@ TEST_CASE("ADC continuous big conv_frame_size test", "[adc_continuous]") free(result); } - #define ADC_FLUSH_TEST_SIZE 64 TEST_CASE("ADC continuous flush internal pool", "[adc_continuous][mannual][ignore]") @@ -253,11 +248,11 @@ TEST_CASE("ADC continuous flush internal pool", "[adc_continuous][mannual][ignor for (int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES) { adc_digi_output_data_t *p = (void*)&result[i]; - #if (SOC_ADC_DIGI_RESULT_BYTES == 2) +#if (SOC_ADC_DIGI_RESULT_BYTES == 2) printf("ADC1, Channel: %d, Value: %d\n", p->type1.channel, p->type1.data); - #else +#else printf("ADC1, Channel: %d, Value: %d\n", p->type2.channel, p->type2.data); - #endif +#endif } /** * With this delay, check the read out data to be the newest data diff --git a/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c b/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c index cfe4f32131f7..a69d4fcf76b6 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c @@ -43,7 +43,6 @@ extern void spi_flash_enable_interrupts_caches_and_other_cpu(void); __attribute__((unused)) static void s_test_cache_disable_period_us(test_adc_iram_ctx_t *ctx, uint32_t period_us); - #if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM && CONFIG_GPTIMER_ISR_IRAM_SAFE /*--------------------------------------------------------------- ADC oneshot work with cache safe ISR @@ -143,7 +142,6 @@ TEST_CASE("ADC oneshot fast work with ISR and Flash", "[adc_oneshot]") } #endif //#if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM && CONFIG_GPTIMER_ISR_IRAM_SAFE - #if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE || CONFIG_GDMA_ISR_IRAM_SAFE #include "esp_adc/adc_continuous.h" /*--------------------------------------------------------------- @@ -165,7 +163,7 @@ static bool IRAM_ATTR NOINLINE_ATTR s_conv_done_cb(adc_continuous_handle_t handl int raw = 0; for (int i = 0; i < edata->size; i += SOC_ADC_DIGI_RESULT_BYTES) { - adc_digi_output_data_t *p = (void*)&(edata->conv_frame_buffer[i]); + adc_digi_output_data_t *p = (void*) & (edata->conv_frame_buffer[i]); #if (SOC_ADC_DIGI_RESULT_BYTES == 2) raw += p->type1.data; #else @@ -181,7 +179,6 @@ static bool IRAM_ATTR NOINLINE_ATTR s_conv_done_cb(adc_continuous_handle_t handl } } - return false; } diff --git a/components/esp_adc/test_apps/adc/main/test_adc_performance.c b/components/esp_adc/test_apps/adc/main/test_adc_performance.c index d255bb70619f..e0da5d9aef5e 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_performance.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_performance.c @@ -41,7 +41,7 @@ static int s_insert_point(uint32_t value) TEST_ASSERT_GREATER_OR_EQUAL(4096, s_adc_count_size); s_adc_offset = 0; //Fixed to 0 because the array can hold all the data in 12 bits } else { - s_adc_offset = MAX((int)value - s_adc_count_size/2, 0); + s_adc_offset = MAX((int)value - s_adc_count_size / 2, 0); } } @@ -75,15 +75,15 @@ static uint32_t s_get_average(void) uint32_t sum = 0; int count = 0; for (int i = 0; i < s_adc_count_size; i++) { - sum += s_p_adc_count[i] * (s_adc_offset+i); + sum += s_p_adc_count[i] * (s_adc_offset + i); count += s_p_adc_count[i]; } - return sum/count; + return sum / count; } static float s_print_summary(bool figure) { - const int MAX_WIDTH=20; + const int MAX_WIDTH = 20; int max_count = 0; int start = -1; int end = -1; @@ -100,12 +100,12 @@ static float s_print_summary(bool figure) end = i; } count += s_p_adc_count[i]; - sum += s_p_adc_count[i] * (s_adc_offset+i); + sum += s_p_adc_count[i] * (s_adc_offset + i); } if (figure) { for (int i = start; i <= end; i++) { - printf("%4d ", i+s_adc_offset); + printf("%4d ", i + s_adc_offset); int count = s_p_adc_count[i] * MAX_WIDTH / max_count; for (int j = 0; j < count; j++) { putchar('|'); @@ -113,7 +113,7 @@ static float s_print_summary(bool figure) printf(" %d\n", s_p_adc_count[i]); } } - float average = (float)sum/count; + float average = (float)sum / count; float variation_square = 0; for (int i = start; i <= end; i ++) { @@ -125,10 +125,10 @@ static float s_print_summary(bool figure) } printf("%d points.\n", count); - printf("average: %.1f\n", (float)sum/count); - printf("std: %.2f\n", sqrt(variation_square/count)); + printf("average: %.1f\n", (float)sum / count); + printf("std: %.2f\n", sqrt(variation_square / count)); - return sqrt(variation_square/count); + return sqrt(variation_square / count); } #if SOC_ADC_DMA_SUPPORTED @@ -148,7 +148,6 @@ static float s_print_summary(bool figure) #define ADC_TEST_PKG_SIZE 512 #define ADC_TEST_CNT 4096 - static bool IRAM_ATTR s_conv_done_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data) { BaseType_t mustYield = pdFALSE; @@ -389,7 +388,6 @@ TEST_CASE("ADC1 oneshot std_deviation performance", "[adc_oneshot][performance]" #define RECORD_TIME_END(p_time) do{__t2 = esp_cpu_get_cycle_count(); *p_time = (__t2-__t1);}while(0) #define GET_US_BY_CCOUNT(t) ((double)t/CPU_FREQ_MHZ) - //ADC Channels #if CONFIG_IDF_TARGET_ESP32 #define ADC1_CALI_SPEED_TEST_CHAN0 ADC_CHANNEL_6 @@ -401,7 +399,6 @@ TEST_CASE("ADC1 oneshot std_deviation performance", "[adc_oneshot][performance]" #define TIMES_PER_ATTEN 10 - static IRAM_ATTR NOINLINE_ATTR uint32_t get_cali_time_in_ccount(adc_cali_handle_t cali_handle, int adc_raw) { uint32_t time; diff --git a/components/esp_adc/test_apps/adc/main/test_common_adc.c b/components/esp_adc/test_apps/adc/main/test_common_adc.c index 9bb4a3b79f8c..7212d849c96c 100644 --- a/components/esp_adc/test_apps/adc/main/test_common_adc.c +++ b/components/esp_adc/test_apps/adc/main/test_common_adc.c @@ -35,7 +35,6 @@ adc_digi_iir_filter_coeff_t g_test_filter_coeff[TEST_FILTER_COEFF_NUMS] = { }; #endif - /*--------------------------------------------------------------- ADC Calibration ---------------------------------------------------------------*/ @@ -90,7 +89,6 @@ void test_adc_calibration_deinit(adc_cali_handle_t handle) #endif } - /*--------------------------------------------------------------- ADC GPIO ---------------------------------------------------------------*/ @@ -102,7 +100,7 @@ void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level) #if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED uint32_t io_num = ADC_GET_IO_NUM(unit, channel); - TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY: GPIO_PULLDOWN_ONLY))); + TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY : GPIO_PULLDOWN_ONLY))); #else gpio_num_t io_num = ADC_GET_IO_NUM(unit, channel); if (level) { @@ -112,11 +110,10 @@ void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level) TEST_ESP_OK(rtc_gpio_pullup_dis(io_num)); TEST_ESP_OK(rtc_gpio_pulldown_en(io_num)); } - TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY: GPIO_PULLDOWN_ONLY))); + TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY : GPIO_PULLDOWN_ONLY))); #endif } - void test_adc_set_io_middle(adc_unit_t unit, adc_channel_t channel) { TEST_ASSERT(channel < SOC_ADC_CHANNEL_NUM(unit) && "invalid channel"); diff --git a/components/esp_adc/test_apps/adc/main/test_common_adc.h b/components/esp_adc/test_apps/adc/main/test_common_adc.h index f77200add221..742b536aa958 100644 --- a/components/esp_adc/test_apps/adc/main/test_common_adc.h +++ b/components/esp_adc/test_apps/adc/main/test_common_adc.h @@ -88,7 +88,6 @@ extern "C" { #define ADC_TEST_HIGH_THRESH 200 #endif - /*--------------------------------------------------------------- ADC Attenuation ---------------------------------------------------------------*/ @@ -133,7 +132,6 @@ bool test_adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten */ void test_adc_calibration_deinit(adc_cali_handle_t handle); - /*--------------------------------------------------------------- ADC GPIO ---------------------------------------------------------------*/ diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index b09def62d560..92e8c8a73a0e 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -52,7 +52,6 @@ components_not_formatted_temporary: - "/components/cxx/" - "/components/driver/" - "/components/efuse/" - - "/components/esp_adc/" - "/components/esp_app_format/" - "/components/esp_bootloader_format/" - "/components/esp_coex/" From 2144eedb66d392f3662062eb5e2c339309d5c4b2 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 28 Sep 2023 15:25:42 +0800 Subject: [PATCH 141/142] refactor(esp_psram): reformat code with astyle_py --- components/esp_psram/esp_psram.c | 16 +++++----------- components/esp_psram/mmu_psram_flash.c | 6 +----- tools/ci/astyle-rules.yml | 1 - 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/components/esp_psram/esp_psram.c b/components/esp_psram/esp_psram.c index f354d5098689..10abd43b8911 100644 --- a/components/esp_psram/esp_psram.c +++ b/components/esp_psram/esp_psram.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ - /*---------------------------------------------------------------------------------------------------- * Abstraction layer for PSRAM. PSRAM device related registers and MMU/Cache related code shouls be * abstracted to lower layers. @@ -35,7 +34,6 @@ #include "esp_private/esp_cache_esp32_private.h" #endif - /** * Two types of PSRAM memory regions for now: * - 8bit aligned @@ -84,12 +82,12 @@ typedef struct { static psram_ctx_t s_psram_ctx; static const char* TAG = "esp_psram"; - #if CONFIG_IDF_TARGET_ESP32 //If no function in esp_himem.c is used, this function will be linked into the //binary instead of the one in esp_himem.c, automatically making sure no memory //is reserved if no himem function is used. -size_t __attribute__((weak)) esp_himem_reserved_area_size(void) { +size_t __attribute__((weak)) esp_himem_reserved_area_size(void) +{ return 0; } @@ -105,7 +103,6 @@ static void IRAM_ATTR s_mapping(int v_start, int size) } #endif //CONFIG_IDF_TARGET_ESP32 - esp_err_t esp_psram_init(void) { if (s_psram_ctx.is_initialised) { @@ -301,12 +298,11 @@ esp_err_t esp_psram_init(void) return ESP_OK; } - esp_err_t esp_psram_extram_add_to_heap_allocator(void) { esp_err_t ret = ESP_FAIL; - uint32_t byte_aligned_caps[] = {MALLOC_CAP_SPIRAM|MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}; + uint32_t byte_aligned_caps[] = {MALLOC_CAP_SPIRAM | MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT}; ret = heap_caps_add_region_with_caps(byte_aligned_caps, s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].vaddr_start, s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].vaddr_end); @@ -316,7 +312,7 @@ esp_err_t esp_psram_extram_add_to_heap_allocator(void) if (s_psram_ctx.regions_to_heap[PSRAM_MEM_32BIT_ALIGNED].size) { assert(s_psram_ctx.regions_to_heap[PSRAM_MEM_32BIT_ALIGNED].vaddr_start); - uint32_t word_aligned_caps[] = {MALLOC_CAP_SPIRAM|MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_32BIT}; + uint32_t word_aligned_caps[] = {MALLOC_CAP_SPIRAM | MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_32BIT}; ret = heap_caps_add_region_with_caps(word_aligned_caps, s_psram_ctx.regions_to_heap[PSRAM_MEM_32BIT_ALIGNED].vaddr_start, s_psram_ctx.regions_to_heap[PSRAM_MEM_32BIT_ALIGNED].vaddr_end); @@ -331,7 +327,6 @@ esp_err_t esp_psram_extram_add_to_heap_allocator(void) return ESP_OK; } - bool IRAM_ATTR esp_psram_check_ptr_addr(const void *p) { if (!s_psram_ctx.is_initialised) { @@ -342,7 +337,6 @@ bool IRAM_ATTR esp_psram_check_ptr_addr(const void *p) ((intptr_t)p >= s_psram_ctx.mapped_regions[PSRAM_MEM_32BIT_ALIGNED].vaddr_start && (intptr_t)p < s_psram_ctx.mapped_regions[PSRAM_MEM_32BIT_ALIGNED].vaddr_end); } - esp_err_t esp_psram_extram_reserve_dma_pool(size_t size) { if (size == 0) { @@ -423,7 +417,7 @@ static bool s_test_psram(intptr_t v_start, size_t size, intptr_t reserved_start, } } if (errct) { - ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, size/32, initial_err + v_start); + ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, size / 32, initial_err + v_start); return false; } else { ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK"); diff --git a/components/esp_psram/mmu_psram_flash.c b/components/esp_psram/mmu_psram_flash.c index 026500c49718..e6e4d36fabdf 100644 --- a/components/esp_psram/mmu_psram_flash.c +++ b/components/esp_psram/mmu_psram_flash.c @@ -43,7 +43,6 @@ static uint32_t page0_mapped = 0; static uint32_t page0_page = INVALID_PHY_PAGE; #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA - #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page) { @@ -87,7 +86,6 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size } #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS - #if CONFIG_SPIRAM_RODATA esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page) { @@ -135,7 +133,6 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si } #endif //#if CONFIG_SPIRAM_RODATA - /*---------------------------------------------------------------------------- Part 2 APIs (See @Backgrounds on top of this file) -------------------------------------------------------------------------------*/ @@ -196,7 +193,6 @@ uint32_t instruction_flash_end_page_get(void) } #endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS - #if CONFIG_SPIRAM_RODATA //------------------------------------Copy Flash .rodata to PSRAM-------------------------------------// static uint32_t rodata_in_spiram; @@ -218,7 +214,7 @@ void rodata_flash_page_info_init(uint32_t psram_start_physical_page) uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & SOC_MMU_VADDR_MASK) / MMU_PAGE_SIZE; rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset]; #elif CONFIG_IDF_TARGET_ESP32S3 - uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; + uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START); #endif rodata_start_page &= SOC_MMU_VALID_VAL_MASK; diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index 92e8c8a73a0e..5d3af55afe21 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -71,7 +71,6 @@ components_not_formatted_temporary: - "/components/esp_partition/" - "/components/esp_phy/" - "/components/esp_pm/" - - "/components/esp_psram/" - "/components/esp_ringbuf/" - "/components/esp_rom/" - "/components/esp_system/" From 3d4b60afc0cb7700a6c472a835a0aa4b6eb563d7 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 28 Sep 2023 15:27:51 +0800 Subject: [PATCH 142/142] refactor(esp_mm): reformat code with astyle_py --- components/esp_mm/cache_esp32.c | 3 --- components/esp_mm/esp_cache.c | 3 --- components/esp_mm/esp_mmu_map.c | 19 ++----------------- components/esp_mm/ext_mem_layout.h | 1 - tools/ci/astyle-rules.yml | 1 - 5 files changed, 2 insertions(+), 25 deletions(-) diff --git a/components/esp_mm/cache_esp32.c b/components/esp_mm/cache_esp32.c index 665023a82bd5..c907a057cde8 100644 --- a/components/esp_mm/cache_esp32.c +++ b/components/esp_mm/cache_esp32.c @@ -10,19 +10,16 @@ #include "rom/cache.h" #include "esp_private/esp_cache_esp32_private.h" - static cache_driver_t s_cache_drv = { Cache_Flush, NULL, }; - void cache_register_writeback(cache_driver_t *func) { s_cache_drv.cache_writeback_psram = func->cache_writeback_psram; } - void cache_sync(void) { if (s_cache_drv.cache_writeback_psram) { diff --git a/components/esp_mm/esp_cache.c b/components/esp_mm/esp_cache.c index 38ee4ca687fb..350d81ee0458 100644 --- a/components/esp_mm/esp_cache.c +++ b/components/esp_mm/esp_cache.c @@ -26,7 +26,6 @@ static const char *TAG = "cache"; DEFINE_CRIT_SECTION_LOCK_STATIC(s_spinlock); - esp_err_t esp_cache_msync(void *addr, size_t size, int flags) { ESP_RETURN_ON_FALSE_ISR(addr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); @@ -90,7 +89,6 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags) return ESP_OK; } - esp_err_t esp_cache_aligned_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size) { ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); @@ -132,7 +130,6 @@ esp_err_t esp_cache_aligned_malloc(size_t size, uint32_t flags, void **out_ptr, return ESP_OK; } - esp_err_t esp_cache_aligned_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size) { ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); diff --git a/components/esp_mm/esp_mmu_map.c b/components/esp_mm/esp_mmu_map.c index ecf0ad56a605..3ac6879917c6 100644 --- a/components/esp_mm/esp_mmu_map.c +++ b/components/esp_mm/esp_mmu_map.c @@ -29,7 +29,6 @@ #include "ext_mem_layout.h" #include "esp_mmu_map.h" - //This is for size align #define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) //This is for vaddr align @@ -108,7 +107,6 @@ typedef struct { mem_region_t mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM]; } mmu_ctx_t; - static mmu_ctx_t s_mmu_ctx; #if ENABLE_PADDR_CHECK @@ -116,7 +114,6 @@ static bool s_is_enclosed(uint32_t block_start, uint32_t block_end, uint32_t new static bool s_is_overlapped(uint32_t block_start, uint32_t block_end, uint32_t new_block_start, uint32_t new_block_size); #endif //#if ENABLE_PADDR_CHECK - #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS static cache_bus_mask_t s_get_bus_mask(uint32_t vaddr_start, uint32_t len) @@ -232,7 +229,7 @@ void esp_mmu_map_init(void) //Count the mem regions left after coalescing uint32_t region_num = 0; for (int i = 0; i < SOC_MMU_LINEAR_ADDRESS_REGION_NUM; i++) { - if(hw_mem_regions[i].caps != MEM_REGION_MERGED) { + if (hw_mem_regions[i].caps != MEM_REGION_MERGED) { region_num++; } } @@ -257,7 +254,6 @@ void esp_mmu_map_init(void) assert(available_region_idx == region_num); } - static esp_err_t s_mem_caps_check(mmu_mem_caps_t caps) { if (caps & MMU_MEM_CAP_EXEC) { @@ -291,7 +287,6 @@ esp_err_t esp_mmu_map_get_max_consecutive_free_block_size(mmu_mem_caps_t caps, m return ESP_OK; } - static int32_t s_find_available_region(mem_region_t *mem_regions, uint32_t region_nums, size_t size, mmu_mem_caps_t caps, mmu_target_t target) { int32_t found_region_id = -1; @@ -372,7 +367,6 @@ IRAM_ATTR esp_err_t esp_mmu_paddr_find_caps(const esp_paddr_t paddr, mmu_mem_cap return ESP_OK; } - static void IRAM_ATTR NOINLINE_ATTR s_do_cache_invalidate(uint32_t vaddr_start, uint32_t size) { #if CONFIG_IDF_TARGET_ESP32 @@ -387,7 +381,6 @@ static void IRAM_ATTR NOINLINE_ATTR s_do_cache_invalidate(uint32_t vaddr_start, #endif // CONFIG_IDF_TARGET_ESP32 } - #if MMU_LL_MMU_PER_TARGET FORCE_INLINE_ATTR uint32_t s_mapping_operation(mmu_target_t target, uint32_t vaddr_start, esp_paddr_t paddr_start, uint32_t size) { @@ -418,7 +411,6 @@ FORCE_INLINE_ATTR uint32_t s_mapping_operation(mmu_target_t target, uint32_t vad } #endif - static void IRAM_ATTR NOINLINE_ATTR s_do_mapping(mmu_target_t target, uint32_t vaddr_start, esp_paddr_t paddr_start, uint32_t size) { /** @@ -592,7 +584,6 @@ esp_err_t esp_mmu_map(esp_paddr_t paddr_start, size_t size, mmu_target_t target, return ret; } - #if MMU_LL_MMU_PER_TARGET FORCE_INLINE_ATTR void s_unmapping_operation(uint32_t vaddr_start, uint32_t size) { @@ -618,7 +609,6 @@ FORCE_INLINE_ATTR void s_unmapping_operation(uint32_t vaddr_start, uint32_t size } #endif - static void IRAM_ATTR NOINLINE_ATTR s_do_unmapping(uint32_t vaddr_start, uint32_t size) { /** @@ -680,7 +670,6 @@ esp_err_t esp_mmu_unmap(void *ptr) return ESP_OK; } - esp_err_t esp_mmu_map_dump_mapped_blocks(FILE* stream) { char line[100]; @@ -725,7 +714,6 @@ esp_err_t esp_mmu_map_dump_mapped_blocks(FILE* stream) return ESP_OK; } - /*--------------------------------------------------------------- Private dump functions, IRAM Safe ---------------------------------------------------------------*/ @@ -753,7 +741,6 @@ esp_err_t IRAM_ATTR esp_mmu_map_dump_mapped_blocks_private(void) return ESP_OK; } - /*--------------------------------------------------------------- Helper APIs for conversion between vaddr and paddr ---------------------------------------------------------------*/ @@ -785,7 +772,6 @@ esp_err_t esp_mmu_vaddr_to_paddr(void *vaddr, esp_paddr_t *out_paddr, mmu_target return ESP_OK; } - static bool NOINLINE_ATTR IRAM_ATTR s_paddr_to_vaddr(esp_paddr_t paddr, mmu_target_t target, mmu_vaddr_t type, uint32_t *out_vaddr) { //we call this for now, but this will be refactored to move out of `spi_flash` @@ -812,7 +798,6 @@ esp_err_t esp_mmu_paddr_to_vaddr(esp_paddr_t paddr, mmu_target_t target, mmu_vad return ESP_OK; } - #if ENABLE_PADDR_CHECK /*--------------------------------------------------------------- Helper functions to check block @@ -875,7 +860,7 @@ static bool s_is_overlapped(uint32_t block_start, uint32_t block_end, uint32_t n uint32_t new_block_end = new_block_start + new_block_size; if (((new_block_start < block_start) && (new_block_end > block_start)) || - ((new_block_start < block_end) && (new_block_end > block_end))) { + ((new_block_start < block_end) && (new_block_end > block_end))) { is_overlapped = true; } else { is_overlapped = false; diff --git a/components/esp_mm/ext_mem_layout.h b/components/esp_mm/ext_mem_layout.h index 9f72753306ce..fc5b49ae8b54 100644 --- a/components/esp_mm/ext_mem_layout.h +++ b/components/esp_mm/ext_mem_layout.h @@ -16,7 +16,6 @@ extern "C" { #endif - typedef struct { uint32_t start; //laddr start uint32_t end; //laddr end diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index 5d3af55afe21..98ff84a0f648 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -66,7 +66,6 @@ components_not_formatted_temporary: - "/components/esp_https_server/" - "/components/esp_hw_support/" - "/components/esp_local_ctrl/" - - "/components/esp_mm/" - "/components/esp_netif/" - "/components/esp_partition/" - "/components/esp_phy/"