diff --git a/components/esp32s2/CMakeLists.txt b/components/esp32s2/CMakeLists.txt index 024b08b95b..3879c14e7e 100644 --- a/components/esp32s2/CMakeLists.txt +++ b/components/esp32s2/CMakeLists.txt @@ -14,6 +14,7 @@ else() set(srcs "cache_err_int.c" "memprot.c" "clk.c" + "cp_dma.c" "crosscore_int.c" "dport_access.c" "hw_random.c" diff --git a/components/esp32s2/cp_dma.c b/components/esp32s2/cp_dma.c new file mode 100644 index 0000000000..57e0891cf3 --- /dev/null +++ b/components/esp32s2/cp_dma.c @@ -0,0 +1,235 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "esp_compiler.h" +#include "esp_intr_alloc.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "soc/soc_caps.h" +#include "soc/cp_dma_caps.h" +#include "hal/cp_dma_hal.h" +#include "hal/cp_dma_ll.h" +#include "cp_dma.h" +#include "soc/periph_defs.h" + +static const char *TAG = "cp_dma"; + +#define CP_DMA_CHECK(a, msg, tag, ret, ...) \ + do { \ + if (unlikely(!(a))) { \ + ESP_LOGE(TAG, "%s(%d): " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret_code = ret; \ + goto tag; \ + } \ + } while (0) + +/** + * @brief Stream is high level abstraction over descriptor. + * It combines the descriptor used by DMA and the callback function registered by user. + * The benifit is, we can converter the descriptor address into stream handle. + */ +typedef struct { + cp_dma_descriptor_t tx_desc; + cp_dma_isr_cb_t cb; + void *cb_args; +} cp_dma_out_stream_t; + +typedef struct { + cp_dma_descriptor_t rx_desc; + cp_dma_isr_cb_t cb; + void *cb_args; +} cp_dma_in_stream_t; + +typedef struct cp_dma_driver_context_s { + uint32_t max_out_stream; + uint32_t max_in_stream; + uint32_t flags; + cp_dma_hal_context_t hal; // HAL context + intr_handle_t intr_hdl; // interrupt handle + portMUX_TYPE spin_lock; + cp_dma_out_stream_t *out_streams; // pointer to the first out stream + cp_dma_in_stream_t *in_streams; // pointer to the first in stream + uint8_t streams[0]; // stream buffer (out streams + in streams), the size if configured by user +} cp_dma_driver_context_t; + +static void cp_dma_isr_default_handler(void *arg) IRAM_ATTR; + +esp_err_t cp_dma_driver_install(const cp_dma_config_t *config, cp_dma_driver_t *drv_hdl) +{ + esp_err_t ret_code = ESP_OK; + cp_dma_driver_context_t *cp_dma_driver = NULL; + + CP_DMA_CHECK(config, "configuration can't be null", err, ESP_ERR_INVALID_ARG); + CP_DMA_CHECK(drv_hdl, "driver handle can't be null", err, ESP_ERR_INVALID_ARG); + + size_t total_malloc_size = sizeof(cp_dma_driver_context_t) + sizeof(cp_dma_out_stream_t) * config->max_out_stream + sizeof(cp_dma_in_stream_t) * config->max_in_stream; + if (config->flags & CP_DMA_FLAGS_WORK_WITH_CACHE_DISABLED) { + // to work when cache is disabled, make sure to put driver handle in DRAM + cp_dma_driver = heap_caps_calloc(1, total_malloc_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + } else { + cp_dma_driver = calloc(1, total_malloc_size); + } + CP_DMA_CHECK(cp_dma_driver, "allocate driver memory failed", err, ESP_ERR_NO_MEM); + + int int_flags = 0; + if (config->flags & CP_DMA_FLAGS_WORK_WITH_CACHE_DISABLED) { + int_flags |= ESP_INTR_FLAG_IRAM; // make sure interrupt can still work when cache is disabled + } + ret_code = esp_intr_alloc(ETS_DMA_COPY_INTR_SOURCE, int_flags, cp_dma_isr_default_handler, cp_dma_driver, &cp_dma_driver->intr_hdl); + CP_DMA_CHECK(ret_code == ESP_OK, "allocate intr failed", err, ret_code); + + cp_dma_driver->out_streams = (cp_dma_out_stream_t *)cp_dma_driver->streams; + cp_dma_driver->in_streams = (cp_dma_in_stream_t *)(cp_dma_driver->streams + config->max_out_stream * sizeof(cp_dma_out_stream_t)); + // HAL layer has no idea about "data stream" but TX/RX descriptors + // We put all descritprs' addresses into an array, HAL driver will make it a loop during initialization + { + cp_dma_descriptor_t *tx_descriptors[config->max_out_stream]; + cp_dma_descriptor_t *rx_descriptors[config->max_in_stream]; + for (int i = 0; i < config->max_out_stream; i++) { + tx_descriptors[i] = &cp_dma_driver->out_streams[i].tx_desc; + } + for (int i = 0; i < config->max_in_stream; i++) { + rx_descriptors[i] = &cp_dma_driver->in_streams[i].rx_desc; + } + cp_dma_hal_init(&cp_dma_driver->hal, tx_descriptors, config->max_out_stream, rx_descriptors, config->max_in_stream); + } // limit the scope of tx_descriptors and rx_descriptors so that goto can jump after this code block + + cp_dma_driver->spin_lock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; + cp_dma_driver->max_in_stream = config->max_in_stream; + cp_dma_driver->max_out_stream = config->max_out_stream; + *drv_hdl = cp_dma_driver; + + cp_dma_hal_start(&cp_dma_driver->hal); // enable DMA and interrupt + + return ESP_OK; +err: + if (cp_dma_driver) { + if (cp_dma_driver->intr_hdl) { + esp_intr_free(cp_dma_driver->intr_hdl); + } + free(cp_dma_driver); + } + if (drv_hdl) { + *drv_hdl = NULL; + } + return ret_code; +} + +esp_err_t cp_dma_driver_uninstall(cp_dma_driver_t drv_hdl) +{ + esp_err_t ret_code = ESP_OK; + CP_DMA_CHECK(drv_hdl, "driver handle can't be null", err, ESP_ERR_INVALID_ARG); + + esp_intr_free(drv_hdl->intr_hdl); + cp_dma_hal_stop(&drv_hdl->hal); + cp_dma_hal_deinit(&drv_hdl->hal); + free(drv_hdl); + return ESP_OK; +err: + return ret_code; +} + +esp_err_t cp_dma_memcpy(cp_dma_driver_t drv_hdl, void *dst, void *src, size_t n, cp_dma_isr_cb_t cb_isr, void *cb_args) +{ + esp_err_t ret_code = ESP_OK; + cp_dma_descriptor_t *rx_start_desc = NULL; + cp_dma_descriptor_t *rx_end_desc = NULL; + cp_dma_descriptor_t *tx_start_desc = NULL; + cp_dma_descriptor_t *tx_end_desc = NULL; + int rx_prepared_size = 0; + int tx_prepared_size = 0; + CP_DMA_CHECK(drv_hdl, "driver handle can't be null", err, ESP_ERR_INVALID_ARG); + // CP_DMA can only access SRAM + CP_DMA_CHECK(esp_ptr_internal(src) && esp_ptr_internal(dst), "address not in SRAM", err, ESP_ERR_INVALID_ARG); + CP_DMA_CHECK(n <= SOC_CP_DMA_MAX_BUFFER_SIZE * drv_hdl->max_out_stream, "exceed max num of tx stream", err, ESP_ERR_INVALID_ARG); + CP_DMA_CHECK(n <= SOC_CP_DMA_MAX_BUFFER_SIZE * drv_hdl->max_in_stream, "exceed max num of rx stream", err, ESP_ERR_INVALID_ARG); + if (cb_isr && (drv_hdl->flags & CP_DMA_FLAGS_WORK_WITH_CACHE_DISABLED)) { + CP_DMA_CHECK(esp_ptr_in_iram(cb_isr), "callback(%p) not in IRAM", err, ESP_ERR_INVALID_ARG, cb_isr); + } + + // Prepare TX and RX descriptor + portENTER_CRITICAL_SAFE(&drv_hdl->spin_lock); + // prepare functions will not change internal status of HAL until cp_dma_hal_restart_* are called + rx_prepared_size = cp_dma_hal_prepare_receive(&drv_hdl->hal, dst, n, &rx_start_desc, &rx_end_desc); + tx_prepared_size = cp_dma_hal_prepare_transmit(&drv_hdl->hal, src, n, &tx_start_desc, &tx_end_desc); + if ((rx_prepared_size == n) && (tx_prepared_size == n)) { + // register user callback to the end-of-frame descriptor (must before we restart RX) + cp_dma_in_stream_t *data_stream_rx = __containerof(rx_end_desc, cp_dma_in_stream_t, rx_desc); + data_stream_rx->cb = cb_isr; + data_stream_rx->cb_args = cb_args; + // The restart should be called with the exact returned start and end desc from previous successful prepare calls + cp_dma_hal_restart_rx(&drv_hdl->hal, rx_start_desc, rx_end_desc); + cp_dma_hal_restart_tx(&drv_hdl->hal, tx_start_desc, tx_end_desc); + } + portEXIT_CRITICAL_SAFE(&drv_hdl->spin_lock); + + CP_DMA_CHECK(rx_prepared_size == n, "out of rx descriptor", err, ESP_FAIL); + // It's unlikely that we have space for rx descriptor but no space for tx descriptor + // Because in CP_DMA, both tx and rx descriptor should move in the same pace + CP_DMA_CHECK(tx_prepared_size == n, "out of tx descriptor", err, ESP_FAIL); + + return ESP_OK; +err: + return ret_code; +} + +/** + * @brief Default ISR handler provided by ESP-IDF + */ +static void cp_dma_isr_default_handler(void *args) +{ + cp_dma_driver_context_t *cp_dma_driver = (cp_dma_driver_context_t *)args; + cp_dma_in_stream_t *in_stream = NULL; + cp_dma_descriptor_t *next_desc = NULL; + bool need_yield = false; + bool to_continue = false; + + portENTER_CRITICAL_ISR(&cp_dma_driver->spin_lock); + uint32_t status = cp_dma_hal_get_intr_status(&cp_dma_driver->hal); + cp_dma_hal_clear_intr_status(&cp_dma_driver->hal, status); + portEXIT_CRITICAL_ISR(&cp_dma_driver->spin_lock); + ESP_EARLY_LOGD(TAG, "intr status=0x%x", status); + + // End-Of-Frame on RX side + if (status & CP_DMA_LL_EVENT_RX_EOF) { + cp_dma_descriptor_t *eof = (cp_dma_descriptor_t *)cp_dma_ll_get_rx_eof_descriptor_address(cp_dma_driver->hal.dev); + // traversal all unchecked descriptors + do { + portENTER_CRITICAL_ISR(&cp_dma_driver->spin_lock); + // There is an assumption that the usage of rx descriptors are in the same pace as tx descriptors (this is determined by CP DMA working mechanism) + // And once the rx descriptor is recycled, the corresponding tx desc is guaranteed to be returned by DMA + to_continue = cp_dma_hal_get_next_rx_descriptor(&cp_dma_driver->hal, eof, &next_desc); + portEXIT_CRITICAL_ISR(&cp_dma_driver->spin_lock); + if (next_desc) { + in_stream = __containerof(next_desc, cp_dma_in_stream_t, rx_desc); + // invoke user registered callback if available + if (in_stream->cb) { + cp_dma_event_t e = {.id = CP_DMA_EVENT_M2M_DONE}; + if (in_stream->cb(cp_dma_driver, &e, in_stream->cb_args)) { + need_yield = true; + } + in_stream->cb = NULL; + in_stream->cb_args = NULL; + } + } + } while (to_continue); + } + + if (need_yield) { + portYIELD_FROM_ISR(); + } +} diff --git a/components/esp32s2/include/cp_dma.h b/components/esp32s2/include/cp_dma.h new file mode 100644 index 0000000000..e95959ec7b --- /dev/null +++ b/components/esp32s2/include/cp_dma.h @@ -0,0 +1,126 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" + +/** + * @brief Handle of CP_DMA driver + * + */ +typedef struct cp_dma_driver_context_s *cp_dma_driver_t; + +/** + * @brief CP_DMA event ID + * + */ +typedef enum { + CP_DMA_EVENT_M2M_DONE, /*!< One or more memory copy transactions are done */ +} cp_dma_event_id_t; + +/** + * @brief Type defined for CP_DMA event object (including event ID, event data) + * + */ +typedef struct { + cp_dma_event_id_t id; /*!< Event ID */ + void *data; /*!< Event data */ +} cp_dma_event_t; + +/** + * @brief Type defined for cp_dma ISR callback function + * + * @param drv_hdl Handle of CP_DMA driver + * @param event Event object, which contains the event ID, event data, and so on + * @param cb_args User defined arguments for the callback function. It's passed in cp_dma_memcpy function + * @return Whether a high priority task is woken up by the callback function + * + */ +typedef bool (*cp_dma_isr_cb_t)(cp_dma_driver_t drv_hdl, cp_dma_event_t *event, void *cb_args); + +/** + * @brief Type defined for configuration of CP_DMA driver + * + */ +typedef struct { + uint32_t max_out_stream; /*!< maximum number of out link streams that can work simultaneously */ + uint32_t max_in_stream; /*!< maximum number of in link streams that can work simultaneously */ + uint32_t flags; /*!< Extra flags to control some special behaviour of CP_DMA, OR'ed of CP_DMA_FLAGS_xxx macros */ +} cp_dma_config_t; + +#define CP_DMA_FLAGS_WORK_WITH_CACHE_DISABLED (1 << 0) /*!< CP_DMA can work even when cache is diabled */ + +/** + * @brief Default configuration for CP_DMA driver + * + */ +#define CP_DMA_DEFAULT_CONFIG() \ + { \ + .max_out_stream = 8, \ + .max_in_stream = 8, \ + .flags = 0, \ + } + +/** + * @brief Install CP_DMA driver + * + * @param[in] config Configuration of CP_DMA driver + * @param[out] drv_hdl Returned handle of CP_DMA driver or NULL if driver installation failed + * @return + * - ESP_OK: Install CP_DMA driver successfully + * - ESP_ERR_INVALID_ARG: Install CP_DMA driver failed because of some invalid argument + * - ESP_ERR_NO_MEM: Install CP_DMA driver failed because there's no enough capable memory + * - ESP_FAIL: Install CP_DMA driver failed because of other error + */ +esp_err_t cp_dma_driver_install(const cp_dma_config_t *config, cp_dma_driver_t *drv_hdl); + +/** + * @brief Uninstall CP_DMA driver + * + * @param[in] drv_hdl Handle of CP_DMA driver that returned from cp_dma_driver_install + * @return + * - ESP_OK: Uninstall CP_DMA driver successfully + * - ESP_ERR_INVALID_ARG: Uninstall CP_DMA driver failed because of some invalid argument + * - ESP_FAIL: Uninstall CP_DMA driver failed because of other error + */ +esp_err_t cp_dma_driver_uninstall(cp_dma_driver_t drv_hdl); + +/** + * @brief Send an asynchronous memory copy request + * + * @param[in] drv_hdl Handle of CP_DMA driver that returned from cp_dma_driver_install + * @param[in] dst Destination address (copy to) + * @param[in] src Source address (copy from) + * @param[in] n Number of bytes to copy + * @param[in] cb_isr Callback function, which got invoked in ISR context. A NULL pointer here can bypass the callback. + * @param[in] cb_args User defined argument to be passed to the callback function + * @return + * - ESP_OK: Send memcopy request successfully + * - ESP_ERR_INVALID_ARG: Send memcopy request failed because of some invalid argument + * - ESP_FAIL: Send memcopy request failed because of other error + * + * @note The callback function is invoked in ISR context, please never handle heavy load in the callback. + * The default ISR handler is placed in IRAM, please place callback function in IRAM as well by applying IRAM_ATTR to it. + */ +esp_err_t cp_dma_memcpy(cp_dma_driver_t drv_hdl, void *dst, void *src, size_t n, cp_dma_isr_cb_t cb_isr, void *cb_args); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp32s2/ld/esp32s2.peripherals.ld b/components/esp32s2/ld/esp32s2.peripherals.ld index 5bcfbd58ea..a35558a977 100644 --- a/components/esp32s2/ld/esp32s2.peripherals.ld +++ b/components/esp32s2/ld/esp32s2.peripherals.ld @@ -17,7 +17,7 @@ PROVIDE ( RMTMEM = 0x3f416400 ); PROVIDE ( PCNT = 0x3f417000 ); PROVIDE ( SLC = 0x3f418000 ); PROVIDE ( LEDC = 0x3f419000 ); -PROVIDE ( MCP = 0x3f4c3000 ); +PROVIDE ( CP_DMA = 0x3f4c3000 ); PROVIDE ( TIMERG0 = 0x3f41F000 ); PROVIDE ( TIMERG1 = 0x3f420000 ); PROVIDE ( GPSPI2 = 0x3f424000 ); diff --git a/components/esp32s2/test/test_cp_dma.c b/components/esp32s2/test/test_cp_dma.c new file mode 100644 index 0000000000..8dcfbdc153 --- /dev/null +++ b/components/esp32s2/test/test_cp_dma.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include "esp_heap_caps.h" +#include "esp_rom_sys.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "test_utils.h" +#include "ccomp_timer.h" +#include "soc/cp_dma_caps.h" +#include "cp_dma.h" + +#define ALIGN_UP(addr, align) (((addr) + (align)-1) & ~((align)-1)) + +static void cp_dma_setup_testbench(uint32_t seed, uint32_t *buffer_size, uint8_t **src_buf, uint8_t **dst_buf, uint8_t **from_addr, uint8_t **to_addr, uint32_t align) +{ + srand(seed); + printf("allocating memory buffer...\r\n"); + // memory copy from/to PSRAM is not allowed + *src_buf = heap_caps_malloc(*buffer_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + *dst_buf = heap_caps_calloc(1, *buffer_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + + TEST_ASSERT_NOT_NULL_MESSAGE(*src_buf, "allocate source buffer failed"); + TEST_ASSERT_NOT_NULL_MESSAGE(*dst_buf, "allocate destination buffer failed"); + + *from_addr = (uint8_t *)ALIGN_UP((uint32_t)(*src_buf), 4); + *to_addr = (uint8_t *)ALIGN_UP((uint32_t)(*dst_buf), 4); + uint8_t gap = MAX(*from_addr - *src_buf, *to_addr - *dst_buf); + *buffer_size -= gap; + + *from_addr += align; + *to_addr += align; + *buffer_size -= align; + + printf("...size %d Bytes, src@%p, dst@%p\r\n", *buffer_size, *from_addr, *to_addr); + + printf("fill src buffer with random data\r\n"); + for (int i = 0; i < *buffer_size; i++) { + (*from_addr)[i] = rand() % 256; + } +} + +static void cp_dma_verify_and_clear_testbench(uint32_t seed, uint32_t buffer_size, uint8_t *src_buf, uint8_t *dst_buf, uint8_t *from_addr, uint8_t *to_addr) +{ + srand(seed); + for (int i = 0; i < buffer_size; i++) { + // check if source date has been copied to destination and source data not broken + TEST_ASSERT_EQUAL_MESSAGE(rand() % 256, to_addr[i], "destination data doesn't match generator data"); + } + srand(seed); + for (int i = 0; i < buffer_size; i++) { + // check if source data has been copied to destination + TEST_ASSERT_EQUAL_MESSAGE(rand() % 256, to_addr[i], "destination data doesn't match source data"); + } + free(src_buf); + free(dst_buf); +} + +TEST_CASE("memory copy by DMA one by one", "[CP_DMA]") +{ + cp_dma_config_t config = CP_DMA_DEFAULT_CONFIG(); + config.max_in_stream = 4; + config.max_out_stream = 4; + cp_dma_driver_t driver = NULL; + TEST_ESP_OK(cp_dma_driver_install(&config, &driver)); + + uint32_t test_buffer_len[] = {256, 512, 1024, 2048, 4096, 5011}; + uint8_t *sbuf = NULL; + uint8_t *dbuf = NULL; + uint8_t *from = NULL; + uint8_t *to = NULL; + + for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) { + // Test different align edge + for (int align = 0; align < 4; align++) { + cp_dma_setup_testbench(i, &test_buffer_len[i], &sbuf, &dbuf, &from, &to, align); + TEST_ESP_OK(cp_dma_memcpy(driver, to, from, test_buffer_len[i], NULL, NULL)); + cp_dma_verify_and_clear_testbench(i, test_buffer_len[i], sbuf, dbuf, from, to); + + vTaskDelay(pdMS_TO_TICKS(100)); + } + } + + TEST_ESP_OK(cp_dma_driver_uninstall(driver)); +} + +TEST_CASE("memory copy by DMA on the fly", "[CP_DMA]") +{ + cp_dma_config_t config = CP_DMA_DEFAULT_CONFIG(); + config.max_in_stream = 4; + config.max_out_stream = 4; + cp_dma_driver_t driver = NULL; + TEST_ESP_OK(cp_dma_driver_install(&config, &driver)); + + uint32_t test_buffer_len[] = {512, 1024, 2048, 4096, 5011}; + uint8_t *sbufs[] = {0, 0, 0, 0, 0}; + uint8_t *dbufs[] = {0, 0, 0, 0, 0}; + uint8_t *froms[] = {0, 0, 0, 0, 0}; + uint8_t *tos[] = {0, 0, 0, 0, 0}; + + // Aligned case + for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) { + cp_dma_setup_testbench(i, &test_buffer_len[i], &sbufs[i], &dbufs[i], &froms[i], &tos[i], 0); + } + for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) { + TEST_ESP_OK(cp_dma_memcpy(driver, tos[i], froms[i], test_buffer_len[i], NULL, NULL)); + } + for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) { + cp_dma_verify_and_clear_testbench(i, test_buffer_len[i], sbufs[i], dbufs[i], froms[i], tos[i]); + } + + // Non-aligned case + for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) { + cp_dma_setup_testbench(i, &test_buffer_len[i], &sbufs[i], &dbufs[i], &froms[i], &tos[i], 3); + } + for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) { + TEST_ESP_OK(cp_dma_memcpy(driver, tos[i], froms[i], test_buffer_len[i], NULL, NULL)); + } + for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) { + cp_dma_verify_and_clear_testbench(i, test_buffer_len[i], sbufs[i], dbufs[i], froms[i], tos[i]); + } + + TEST_ESP_OK(cp_dma_driver_uninstall(driver)); +} + +#define TEST_CP_DMA_MECP_DMAY_BENCH_COUNTS (16) +static uint32_t test_cp_dma_memcpy_bench_len = 4096; +static int count = 0; + +static IRAM_ATTR bool test_cp_dma_memcpy_cb(cp_dma_driver_t drv_hdl, cp_dma_event_t *event, void *cb_args) +{ + SemaphoreHandle_t sem = (SemaphoreHandle_t)cb_args; + BaseType_t high_task_wakeup = pdFALSE; + switch (event->id) { + case CP_DMA_EVENT_M2M_DONE: + count++; + if (count == TEST_CP_DMA_MECP_DMAY_BENCH_COUNTS) { + xSemaphoreGiveFromISR(sem, &high_task_wakeup); + } + break; + default: + break; + } + return high_task_wakeup == pdTRUE; +} + +TEST_CASE("memory copy by DMA with callback", "[CP_DMA][performance]") +{ + SemaphoreHandle_t sem = xSemaphoreCreateBinary(); + + cp_dma_config_t config = CP_DMA_DEFAULT_CONFIG(); + cp_dma_driver_t driver = NULL; + TEST_ESP_OK(cp_dma_driver_install(&config, &driver)); + + uint8_t *sbuf = NULL; + uint8_t *dbuf = NULL; + uint8_t *from = NULL; + uint8_t *to = NULL; + + cp_dma_setup_testbench(0, &test_cp_dma_memcpy_bench_len, &sbuf, &dbuf, &from, &to, 0); + count = 0; + ccomp_timer_start(); + for (int i = 0; i < TEST_CP_DMA_MECP_DMAY_BENCH_COUNTS; i++) { + TEST_ESP_OK(cp_dma_memcpy(driver, to, from, test_cp_dma_memcpy_bench_len, test_cp_dma_memcpy_cb, sem)); + } + + // wait for done semaphore + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(sem, pdMS_TO_TICKS(1000))); + esp_rom_printf("memcpy %d Bytes data by HW costs %lldus\r\n", test_cp_dma_memcpy_bench_len, ccomp_timer_stop() / TEST_CP_DMA_MECP_DMAY_BENCH_COUNTS); + + ccomp_timer_start(); + for (int i = 0; i < TEST_CP_DMA_MECP_DMAY_BENCH_COUNTS; i++) { + memcpy(to, from, test_cp_dma_memcpy_bench_len); + } + esp_rom_printf("memcpy %d Bytes data by SW costs %lldus\r\n", test_cp_dma_memcpy_bench_len, ccomp_timer_stop() / TEST_CP_DMA_MECP_DMAY_BENCH_COUNTS); + + cp_dma_verify_and_clear_testbench(0, test_cp_dma_memcpy_bench_len, sbuf, dbuf, from, to); + + TEST_ESP_OK(cp_dma_driver_uninstall(driver)); + vSemaphoreDelete(sem); +} diff --git a/components/soc/soc/esp32s2/include/soc/cp_dma_caps.h b/components/soc/soc/esp32s2/include/soc/cp_dma_caps.h new file mode 100644 index 0000000000..e3a7b1a1e4 --- /dev/null +++ b/components/soc/soc/esp32s2/include/soc/cp_dma_caps.h @@ -0,0 +1,25 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define SOC_CP_DMA_MAX_BUFFER_SIZE (4095) /*!< Maximum size of the buffer that can be attached to descriptor */ + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/soc/esp32s2/include/soc/cp_dma_reg.h b/components/soc/soc/esp32s2/include/soc/cp_dma_reg.h new file mode 100644 index 0000000000..ee785b4766 --- /dev/null +++ b/components/soc/soc/esp32s2/include/soc/cp_dma_reg.h @@ -0,0 +1,698 @@ +/** Copyright 2020 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include "soc/soc.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** CP_DMA_INT_RAW_REG register + * Raw interrupt status + */ +#define CP_DMA_INT_RAW_REG (DR_REG_CP_BASE + 0x0) +/** CP_DMA_IN_DONE_INT_RAW : RO; bitpos: [0]; default: 0; + * This is the interrupt raw bit. Triggered when the last data of frame is received or + * the receive buffer is full indicated by inlink descriptor. + */ +#define CP_DMA_IN_DONE_INT_RAW (BIT(0)) +#define CP_DMA_IN_DONE_INT_RAW_M (CP_DMA_IN_DONE_INT_RAW_V << CP_DMA_IN_DONE_INT_RAW_S) +#define CP_DMA_IN_DONE_INT_RAW_V 0x00000001 +#define CP_DMA_IN_DONE_INT_RAW_S 0 +/** CP_DMA_IN_SUC_EOF_INT_RAW : RO; bitpos: [1]; default: 0; + * This is the interrupt raw bit. Triggered when the last data of one frame is + * received. + */ +#define CP_DMA_IN_SUC_EOF_INT_RAW (BIT(1)) +#define CP_DMA_IN_SUC_EOF_INT_RAW_M (CP_DMA_IN_SUC_EOF_INT_RAW_V << CP_DMA_IN_SUC_EOF_INT_RAW_S) +#define CP_DMA_IN_SUC_EOF_INT_RAW_V 0x00000001 +#define CP_DMA_IN_SUC_EOF_INT_RAW_S 1 +/** CP_DMA_OUT_DONE_INT_RAW : RO; bitpos: [2]; default: 0; + * This is the interrupt raw bit. Triggered when all data indicated by one outlink + * descriptor has been pushed into Tx FIFO. + */ +#define CP_DMA_OUT_DONE_INT_RAW (BIT(2)) +#define CP_DMA_OUT_DONE_INT_RAW_M (CP_DMA_OUT_DONE_INT_RAW_V << CP_DMA_OUT_DONE_INT_RAW_S) +#define CP_DMA_OUT_DONE_INT_RAW_V 0x00000001 +#define CP_DMA_OUT_DONE_INT_RAW_S 2 +/** CP_DMA_OUT_EOF_INT_RAW : RO; bitpos: [3]; default: 0; + * This is the interrupt raw bit. Triggered when the last data with EOF flag has been + * pushed into Tx FIFO. + */ +#define CP_DMA_OUT_EOF_INT_RAW (BIT(3)) +#define CP_DMA_OUT_EOF_INT_RAW_M (CP_DMA_OUT_EOF_INT_RAW_V << CP_DMA_OUT_EOF_INT_RAW_S) +#define CP_DMA_OUT_EOF_INT_RAW_V 0x00000001 +#define CP_DMA_OUT_EOF_INT_RAW_S 3 +/** CP_DMA_IN_DSCR_ERR_INT_RAW : RO; bitpos: [4]; default: 0; + * This is the interrupt raw bit. Triggered when detecting inlink descriptor error, + * including owner error, the second and third word error of inlink descriptor. + */ +#define CP_DMA_IN_DSCR_ERR_INT_RAW (BIT(4)) +#define CP_DMA_IN_DSCR_ERR_INT_RAW_M (CP_DMA_IN_DSCR_ERR_INT_RAW_V << CP_DMA_IN_DSCR_ERR_INT_RAW_S) +#define CP_DMA_IN_DSCR_ERR_INT_RAW_V 0x00000001 +#define CP_DMA_IN_DSCR_ERR_INT_RAW_S 4 +/** CP_DMA_OUT_DSCR_ERR_INT_RAW : RO; bitpos: [5]; default: 0; + * This is the interrupt raw bit. Triggered when detecting outlink descriptor error, + * including owner error, the second and third word error of outlink descriptor. + */ +#define CP_DMA_OUT_DSCR_ERR_INT_RAW (BIT(5)) +#define CP_DMA_OUT_DSCR_ERR_INT_RAW_M (CP_DMA_OUT_DSCR_ERR_INT_RAW_V << CP_DMA_OUT_DSCR_ERR_INT_RAW_S) +#define CP_DMA_OUT_DSCR_ERR_INT_RAW_V 0x00000001 +#define CP_DMA_OUT_DSCR_ERR_INT_RAW_S 5 +/** CP_DMA_IN_DSCR_EMPTY_INT_RAW : RO; bitpos: [6]; default: 0; + * This is the interrupt raw bit. Triggered when receiving data is completed and no + * more inlink descriptor. + */ +#define CP_DMA_IN_DSCR_EMPTY_INT_RAW (BIT(6)) +#define CP_DMA_IN_DSCR_EMPTY_INT_RAW_M (CP_DMA_IN_DSCR_EMPTY_INT_RAW_V << CP_DMA_IN_DSCR_EMPTY_INT_RAW_S) +#define CP_DMA_IN_DSCR_EMPTY_INT_RAW_V 0x00000001 +#define CP_DMA_IN_DSCR_EMPTY_INT_RAW_S 6 +/** CP_DMA_OUT_TOTAL_EOF_INT_RAW : RO; bitpos: [7]; default: 0; + * This is the interrupt raw bit. Triggered when data corresponding to all outlink + * descriptor and the last descriptor with valid EOF is transmitted out. + */ +#define CP_DMA_OUT_TOTAL_EOF_INT_RAW (BIT(7)) +#define CP_DMA_OUT_TOTAL_EOF_INT_RAW_M (CP_DMA_OUT_TOTAL_EOF_INT_RAW_V << CP_DMA_OUT_TOTAL_EOF_INT_RAW_S) +#define CP_DMA_OUT_TOTAL_EOF_INT_RAW_V 0x00000001 +#define CP_DMA_OUT_TOTAL_EOF_INT_RAW_S 7 +/** CP_DMA_CRC_DONE_INT_RAW : RO; bitpos: [8]; default: 0; + * This is the interrupt raw bit. Triggered when crc calculation is done. + */ +#define CP_DMA_CRC_DONE_INT_RAW (BIT(8)) +#define CP_DMA_CRC_DONE_INT_RAW_M (CP_DMA_CRC_DONE_INT_RAW_V << CP_DMA_CRC_DONE_INT_RAW_S) +#define CP_DMA_CRC_DONE_INT_RAW_V 0x00000001 +#define CP_DMA_CRC_DONE_INT_RAW_S 8 + +/** CP_DMA_INT_ST_REG register + * Masked interrupt status + */ +#define CP_DMA_INT_ST_REG (DR_REG_CP_BASE + 0x4) +/** CP_DMA_IN_DONE_INT_ST : RO; bitpos: [0]; default: 0; + * This is the masked interrupt bit for cp_in_done_int interrupt when + * cp_in_done_int_ena is set to 1. + */ +#define CP_DMA_IN_DONE_INT_ST (BIT(0)) +#define CP_DMA_IN_DONE_INT_ST_M (CP_DMA_IN_DONE_INT_ST_V << CP_DMA_IN_DONE_INT_ST_S) +#define CP_DMA_IN_DONE_INT_ST_V 0x00000001 +#define CP_DMA_IN_DONE_INT_ST_S 0 +/** CP_DMA_IN_SUC_EOF_INT_ST : RO; bitpos: [1]; default: 0; + * This is the masked interrupt bit for cp_in_suc_eof_int interrupt when + * cp_in_suc_eof_int_ena is set to 1. + */ +#define CP_DMA_IN_SUC_EOF_INT_ST (BIT(1)) +#define CP_DMA_IN_SUC_EOF_INT_ST_M (CP_DMA_IN_SUC_EOF_INT_ST_V << CP_DMA_IN_SUC_EOF_INT_ST_S) +#define CP_DMA_IN_SUC_EOF_INT_ST_V 0x00000001 +#define CP_DMA_IN_SUC_EOF_INT_ST_S 1 +/** CP_DMA_OUT_DONE_INT_ST : RO; bitpos: [2]; default: 0; + * This is the masked interrupt bit for cp_out_done_int interrupt when + * cp_out_done_int_ena is set to 1. + */ +#define CP_DMA_OUT_DONE_INT_ST (BIT(2)) +#define CP_DMA_OUT_DONE_INT_ST_M (CP_DMA_OUT_DONE_INT_ST_V << CP_DMA_OUT_DONE_INT_ST_S) +#define CP_DMA_OUT_DONE_INT_ST_V 0x00000001 +#define CP_DMA_OUT_DONE_INT_ST_S 2 +/** CP_DMA_OUT_EOF_INT_ST : RO; bitpos: [3]; default: 0; + * This is the masked interrupt bit for cp_out_eof_int interrupt when + * cp_out_eof_int_ena is set to 1. + */ +#define CP_DMA_OUT_EOF_INT_ST (BIT(3)) +#define CP_DMA_OUT_EOF_INT_ST_M (CP_DMA_OUT_EOF_INT_ST_V << CP_DMA_OUT_EOF_INT_ST_S) +#define CP_DMA_OUT_EOF_INT_ST_V 0x00000001 +#define CP_DMA_OUT_EOF_INT_ST_S 3 +/** CP_DMA_IN_DSCR_ERR_INT_ST : RO; bitpos: [4]; default: 0; + * This is the masked interrupt bit for cp_in_dscr_err_int interrupt when + * cp_in_dscr_err_int_ena is set to 1. + */ +#define CP_DMA_IN_DSCR_ERR_INT_ST (BIT(4)) +#define CP_DMA_IN_DSCR_ERR_INT_ST_M (CP_DMA_IN_DSCR_ERR_INT_ST_V << CP_DMA_IN_DSCR_ERR_INT_ST_S) +#define CP_DMA_IN_DSCR_ERR_INT_ST_V 0x00000001 +#define CP_DMA_IN_DSCR_ERR_INT_ST_S 4 +/** CP_DMA_OUT_DSCR_ERR_INT_ST : RO; bitpos: [5]; default: 0; + * This is the masked interrupt bit for cp_out_dscr_err_int interrupt when + * cp_out_dscr_err_int_ena is set to 1. + */ +#define CP_DMA_OUT_DSCR_ERR_INT_ST (BIT(5)) +#define CP_DMA_OUT_DSCR_ERR_INT_ST_M (CP_DMA_OUT_DSCR_ERR_INT_ST_V << CP_DMA_OUT_DSCR_ERR_INT_ST_S) +#define CP_DMA_OUT_DSCR_ERR_INT_ST_V 0x00000001 +#define CP_DMA_OUT_DSCR_ERR_INT_ST_S 5 +/** CP_DMA_IN_DSCR_EMPTY_INT_ST : RO; bitpos: [6]; default: 0; + * This is the masked interrupt bit for cp_in_dscr_empty_int interrupt when + * cp_in_dscr_empty_int_ena is set to 1. + */ +#define CP_DMA_IN_DSCR_EMPTY_INT_ST (BIT(6)) +#define CP_DMA_IN_DSCR_EMPTY_INT_ST_M (CP_DMA_IN_DSCR_EMPTY_INT_ST_V << CP_DMA_IN_DSCR_EMPTY_INT_ST_S) +#define CP_DMA_IN_DSCR_EMPTY_INT_ST_V 0x00000001 +#define CP_DMA_IN_DSCR_EMPTY_INT_ST_S 6 +/** CP_DMA_OUT_TOTAL_EOF_INT_ST : RO; bitpos: [7]; default: 0; + * This is the masked interrupt bit for cp_out_total_eof_int interrupt when + * cp_out_total_eof_int_ena is set to 1. + */ +#define CP_DMA_OUT_TOTAL_EOF_INT_ST (BIT(7)) +#define CP_DMA_OUT_TOTAL_EOF_INT_ST_M (CP_DMA_OUT_TOTAL_EOF_INT_ST_V << CP_DMA_OUT_TOTAL_EOF_INT_ST_S) +#define CP_DMA_OUT_TOTAL_EOF_INT_ST_V 0x00000001 +#define CP_DMA_OUT_TOTAL_EOF_INT_ST_S 7 +/** CP_DMA_CRC_DONE_INT_ST : RO; bitpos: [8]; default: 0; + * This is the masked interrupt bit for cp_crc_done_int interrupt when + * cp_crc_done_int_ena is set to 1. + */ +#define CP_DMA_CRC_DONE_INT_ST (BIT(8)) +#define CP_DMA_CRC_DONE_INT_ST_M (CP_DMA_CRC_DONE_INT_ST_V << CP_DMA_CRC_DONE_INT_ST_S) +#define CP_DMA_CRC_DONE_INT_ST_V 0x00000001 +#define CP_DMA_CRC_DONE_INT_ST_S 8 + +/** CP_DMA_INT_ENA_REG register + * Interrupt enable bits + */ +#define CP_DMA_INT_ENA_REG (DR_REG_CP_BASE + 0x8) +/** CP_DMA_IN_DONE_INT_ENA : R/W; bitpos: [0]; default: 0; + * This is the interrupt enable bit for cp_in_done_int interrupt. + */ +#define CP_DMA_IN_DONE_INT_ENA (BIT(0)) +#define CP_DMA_IN_DONE_INT_ENA_M (CP_DMA_IN_DONE_INT_ENA_V << CP_DMA_IN_DONE_INT_ENA_S) +#define CP_DMA_IN_DONE_INT_ENA_V 0x00000001 +#define CP_DMA_IN_DONE_INT_ENA_S 0 +/** CP_DMA_IN_SUC_EOF_INT_ENA : R/W; bitpos: [1]; default: 0; + * This is the interrupt enable bit for cp_in_suc_eof_int interrupt. + */ +#define CP_DMA_IN_SUC_EOF_INT_ENA (BIT(1)) +#define CP_DMA_IN_SUC_EOF_INT_ENA_M (CP_DMA_IN_SUC_EOF_INT_ENA_V << CP_DMA_IN_SUC_EOF_INT_ENA_S) +#define CP_DMA_IN_SUC_EOF_INT_ENA_V 0x00000001 +#define CP_DMA_IN_SUC_EOF_INT_ENA_S 1 +/** CP_DMA_OUT_DONE_INT_ENA : R/W; bitpos: [2]; default: 0; + * This is the interrupt enable bit for cp_out_done_int interrupt. + */ +#define CP_DMA_OUT_DONE_INT_ENA (BIT(2)) +#define CP_DMA_OUT_DONE_INT_ENA_M (CP_DMA_OUT_DONE_INT_ENA_V << CP_DMA_OUT_DONE_INT_ENA_S) +#define CP_DMA_OUT_DONE_INT_ENA_V 0x00000001 +#define CP_DMA_OUT_DONE_INT_ENA_S 2 +/** CP_DMA_OUT_EOF_INT_ENA : R/W; bitpos: [3]; default: 0; + * This is the interrupt enable bit for cp_out_eof_int interrupt. + */ +#define CP_DMA_OUT_EOF_INT_ENA (BIT(3)) +#define CP_DMA_OUT_EOF_INT_ENA_M (CP_DMA_OUT_EOF_INT_ENA_V << CP_DMA_OUT_EOF_INT_ENA_S) +#define CP_DMA_OUT_EOF_INT_ENA_V 0x00000001 +#define CP_DMA_OUT_EOF_INT_ENA_S 3 +/** CP_DMA_IN_DSCR_ERR_INT_ENA : R/W; bitpos: [4]; default: 0; + * This is the interrupt enable bit for cp_in_dscr_err_int interrupt. + */ +#define CP_DMA_IN_DSCR_ERR_INT_ENA (BIT(4)) +#define CP_DMA_IN_DSCR_ERR_INT_ENA_M (CP_DMA_IN_DSCR_ERR_INT_ENA_V << CP_DMA_IN_DSCR_ERR_INT_ENA_S) +#define CP_DMA_IN_DSCR_ERR_INT_ENA_V 0x00000001 +#define CP_DMA_IN_DSCR_ERR_INT_ENA_S 4 +/** CP_DMA_OUT_DSCR_ERR_INT_ENA : R/W; bitpos: [5]; default: 0; + * This is the interrupt enable bit for cp_out_dscr_err_int interrupt. + */ +#define CP_DMA_OUT_DSCR_ERR_INT_ENA (BIT(5)) +#define CP_DMA_OUT_DSCR_ERR_INT_ENA_M (CP_DMA_OUT_DSCR_ERR_INT_ENA_V << CP_DMA_OUT_DSCR_ERR_INT_ENA_S) +#define CP_DMA_OUT_DSCR_ERR_INT_ENA_V 0x00000001 +#define CP_DMA_OUT_DSCR_ERR_INT_ENA_S 5 +/** CP_DMA_IN_DSCR_EMPTY_INT_ENA : R/W; bitpos: [6]; default: 0; + * This is the interrupt enable bit for cp_in_dscr_empty_int interrupt. + */ +#define CP_DMA_IN_DSCR_EMPTY_INT_ENA (BIT(6)) +#define CP_DMA_IN_DSCR_EMPTY_INT_ENA_M (CP_DMA_IN_DSCR_EMPTY_INT_ENA_V << CP_DMA_IN_DSCR_EMPTY_INT_ENA_S) +#define CP_DMA_IN_DSCR_EMPTY_INT_ENA_V 0x00000001 +#define CP_DMA_IN_DSCR_EMPTY_INT_ENA_S 6 +/** CP_DMA_OUT_TOTAL_EOF_INT_ENA : R/W; bitpos: [7]; default: 0; + * This is the interrupt enable bit for cp_out_total_eof_int interrupt. + */ +#define CP_DMA_OUT_TOTAL_EOF_INT_ENA (BIT(7)) +#define CP_DMA_OUT_TOTAL_EOF_INT_ENA_M (CP_DMA_OUT_TOTAL_EOF_INT_ENA_V << CP_DMA_OUT_TOTAL_EOF_INT_ENA_S) +#define CP_DMA_OUT_TOTAL_EOF_INT_ENA_V 0x00000001 +#define CP_DMA_OUT_TOTAL_EOF_INT_ENA_S 7 +/** CP_DMA_CRC_DONE_INT_ENA : R/W; bitpos: [8]; default: 0; + * This is the interrupt enable bit for cp_crc_done_int interrupt. + */ +#define CP_DMA_CRC_DONE_INT_ENA (BIT(8)) +#define CP_DMA_CRC_DONE_INT_ENA_M (CP_DMA_CRC_DONE_INT_ENA_V << CP_DMA_CRC_DONE_INT_ENA_S) +#define CP_DMA_CRC_DONE_INT_ENA_V 0x00000001 +#define CP_DMA_CRC_DONE_INT_ENA_S 8 + +/** CP_DMA_INT_CLR_REG register + * Interrupt clear bits + */ +#define CP_DMA_INT_CLR_REG (DR_REG_CP_BASE + 0xc) +/** CP_DMA_IN_DONE_INT_CLR : WO; bitpos: [0]; default: 0; + * Set this bit to clear cp_in_done_int interrupt. + */ +#define CP_DMA_IN_DONE_INT_CLR (BIT(0)) +#define CP_DMA_IN_DONE_INT_CLR_M (CP_DMA_IN_DONE_INT_CLR_V << CP_DMA_IN_DONE_INT_CLR_S) +#define CP_DMA_IN_DONE_INT_CLR_V 0x00000001 +#define CP_DMA_IN_DONE_INT_CLR_S 0 +/** CP_DMA_IN_SUC_EOF_INT_CLR : WO; bitpos: [1]; default: 0; + * Set this bit to clear cp_in_suc_eof_int interrupt. + */ +#define CP_DMA_IN_SUC_EOF_INT_CLR (BIT(1)) +#define CP_DMA_IN_SUC_EOF_INT_CLR_M (CP_DMA_IN_SUC_EOF_INT_CLR_V << CP_DMA_IN_SUC_EOF_INT_CLR_S) +#define CP_DMA_IN_SUC_EOF_INT_CLR_V 0x00000001 +#define CP_DMA_IN_SUC_EOF_INT_CLR_S 1 +/** CP_DMA_OUT_DONE_INT_CLR : WO; bitpos: [2]; default: 0; + * Set this bit to clear cp_out_done_int interrupt. + */ +#define CP_DMA_OUT_DONE_INT_CLR (BIT(2)) +#define CP_DMA_OUT_DONE_INT_CLR_M (CP_DMA_OUT_DONE_INT_CLR_V << CP_DMA_OUT_DONE_INT_CLR_S) +#define CP_DMA_OUT_DONE_INT_CLR_V 0x00000001 +#define CP_DMA_OUT_DONE_INT_CLR_S 2 +/** CP_DMA_OUT_EOF_INT_CLR : WO; bitpos: [3]; default: 0; + * Set this bit to clear cp_out_eof_int interrupt. + */ +#define CP_DMA_OUT_EOF_INT_CLR (BIT(3)) +#define CP_DMA_OUT_EOF_INT_CLR_M (CP_DMA_OUT_EOF_INT_CLR_V << CP_DMA_OUT_EOF_INT_CLR_S) +#define CP_DMA_OUT_EOF_INT_CLR_V 0x00000001 +#define CP_DMA_OUT_EOF_INT_CLR_S 3 +/** CP_DMA_IN_DSCR_ERR_INT_CLR : WO; bitpos: [4]; default: 0; + * Set this bit to clear cp_in_dscr_err_int interrupt. + */ +#define CP_DMA_IN_DSCR_ERR_INT_CLR (BIT(4)) +#define CP_DMA_IN_DSCR_ERR_INT_CLR_M (CP_DMA_IN_DSCR_ERR_INT_CLR_V << CP_DMA_IN_DSCR_ERR_INT_CLR_S) +#define CP_DMA_IN_DSCR_ERR_INT_CLR_V 0x00000001 +#define CP_DMA_IN_DSCR_ERR_INT_CLR_S 4 +/** CP_DMA_OUT_DSCR_ERR_INT_CLR : WO; bitpos: [5]; default: 0; + * Set this bit to clear cp_out_dscr_err_int interrupt. + */ +#define CP_DMA_OUT_DSCR_ERR_INT_CLR (BIT(5)) +#define CP_DMA_OUT_DSCR_ERR_INT_CLR_M (CP_DMA_OUT_DSCR_ERR_INT_CLR_V << CP_DMA_OUT_DSCR_ERR_INT_CLR_S) +#define CP_DMA_OUT_DSCR_ERR_INT_CLR_V 0x00000001 +#define CP_DMA_OUT_DSCR_ERR_INT_CLR_S 5 +/** CP_DMA_IN_DSCR_EMPTY_INT_CLR : WO; bitpos: [6]; default: 0; + * Set this bit to clear cp_in_dscr_empty_int interrupt. + */ +#define CP_DMA_IN_DSCR_EMPTY_INT_CLR (BIT(6)) +#define CP_DMA_IN_DSCR_EMPTY_INT_CLR_M (CP_DMA_IN_DSCR_EMPTY_INT_CLR_V << CP_DMA_IN_DSCR_EMPTY_INT_CLR_S) +#define CP_DMA_IN_DSCR_EMPTY_INT_CLR_V 0x00000001 +#define CP_DMA_IN_DSCR_EMPTY_INT_CLR_S 6 +/** CP_DMA_OUT_TOTAL_EOF_INT_CLR : WO; bitpos: [7]; default: 0; + * Set this bit to clear cp_out_total_eof_int interrupt. + */ +#define CP_DMA_OUT_TOTAL_EOF_INT_CLR (BIT(7)) +#define CP_DMA_OUT_TOTAL_EOF_INT_CLR_M (CP_DMA_OUT_TOTAL_EOF_INT_CLR_V << CP_DMA_OUT_TOTAL_EOF_INT_CLR_S) +#define CP_DMA_OUT_TOTAL_EOF_INT_CLR_V 0x00000001 +#define CP_DMA_OUT_TOTAL_EOF_INT_CLR_S 7 +/** CP_DMA_CRC_DONE_INT_CLR : WO; bitpos: [8]; default: 0; + * Set this bit to clear cp_crc_done_int interrupt. + */ +#define CP_DMA_CRC_DONE_INT_CLR (BIT(8)) +#define CP_DMA_CRC_DONE_INT_CLR_M (CP_DMA_CRC_DONE_INT_CLR_V << CP_DMA_CRC_DONE_INT_CLR_S) +#define CP_DMA_CRC_DONE_INT_CLR_V 0x00000001 +#define CP_DMA_CRC_DONE_INT_CLR_S 8 + +/** CP_DMA_OUT_LINK_REG register + * Link descriptor address and control + */ +#define CP_DMA_OUT_LINK_REG (DR_REG_CP_BASE + 0x10) +/** CP_DMA_OUTLINK_ADDR : R/W; bitpos: [19:0]; default: 0; + * This register is used to specify the least significant 20 bits of the first outlink + * descriptor's address. + */ +#define CP_DMA_OUTLINK_ADDR 0x000FFFFF +#define CP_DMA_OUTLINK_ADDR_M (CP_DMA_OUTLINK_ADDR_V << CP_DMA_OUTLINK_ADDR_S) +#define CP_DMA_OUTLINK_ADDR_V 0x000FFFFF +#define CP_DMA_OUTLINK_ADDR_S 0 +/** CP_DMA_OUTLINK_STOP : R/W; bitpos: [28]; default: 0; + * Set this bit to stop dealing with the outlink descriptor. + */ +#define CP_DMA_OUTLINK_STOP (BIT(28)) +#define CP_DMA_OUTLINK_STOP_M (CP_DMA_OUTLINK_STOP_V << CP_DMA_OUTLINK_STOP_S) +#define CP_DMA_OUTLINK_STOP_V 0x00000001 +#define CP_DMA_OUTLINK_STOP_S 28 +/** CP_DMA_OUTLINK_START : R/W; bitpos: [29]; default: 0; + * Set this bit to start a new outlink descriptor. + */ +#define CP_DMA_OUTLINK_START (BIT(29)) +#define CP_DMA_OUTLINK_START_M (CP_DMA_OUTLINK_START_V << CP_DMA_OUTLINK_START_S) +#define CP_DMA_OUTLINK_START_V 0x00000001 +#define CP_DMA_OUTLINK_START_S 29 +/** CP_DMA_OUTLINK_RESTART : R/W; bitpos: [30]; default: 0; + * Set this bit to restart the outlink descriptpr from the last address. + */ +#define CP_DMA_OUTLINK_RESTART (BIT(30)) +#define CP_DMA_OUTLINK_RESTART_M (CP_DMA_OUTLINK_RESTART_V << CP_DMA_OUTLINK_RESTART_S) +#define CP_DMA_OUTLINK_RESTART_V 0x00000001 +#define CP_DMA_OUTLINK_RESTART_S 30 +/** CP_DMA_OUTLINK_PARK : RO; bitpos: [31]; default: 0; + * 1: the outlink descriptor's FSM is in idle state. + * 0: the outlink descriptor's FSM is working. + */ +#define CP_DMA_OUTLINK_PARK (BIT(31)) +#define CP_DMA_OUTLINK_PARK_M (CP_DMA_OUTLINK_PARK_V << CP_DMA_OUTLINK_PARK_S) +#define CP_DMA_OUTLINK_PARK_V 0x00000001 +#define CP_DMA_OUTLINK_PARK_S 31 + +/** CP_DMA_IN_LINK_REG register + * Link descriptor address and control + */ +#define CP_DMA_IN_LINK_REG (DR_REG_CP_BASE + 0x14) +/** CP_DMA_INLINK_ADDR : R/W; bitpos: [19:0]; default: 0; + * This register is used to specify the least significant 20 bits of the first inlink + * descriptor's address. + */ +#define CP_DMA_INLINK_ADDR 0x000FFFFF +#define CP_DMA_INLINK_ADDR_M (CP_DMA_INLINK_ADDR_V << CP_DMA_INLINK_ADDR_S) +#define CP_DMA_INLINK_ADDR_V 0x000FFFFF +#define CP_DMA_INLINK_ADDR_S 0 +/** CP_DMA_INLINK_STOP : R/W; bitpos: [28]; default: 0; + * Set this bit to stop dealing with the inlink descriptors. + */ +#define CP_DMA_INLINK_STOP (BIT(28)) +#define CP_DMA_INLINK_STOP_M (CP_DMA_INLINK_STOP_V << CP_DMA_INLINK_STOP_S) +#define CP_DMA_INLINK_STOP_V 0x00000001 +#define CP_DMA_INLINK_STOP_S 28 +/** CP_DMA_INLINK_START : R/W; bitpos: [29]; default: 0; + * Set this bit to start dealing with the inlink descriptors. + */ +#define CP_DMA_INLINK_START (BIT(29)) +#define CP_DMA_INLINK_START_M (CP_DMA_INLINK_START_V << CP_DMA_INLINK_START_S) +#define CP_DMA_INLINK_START_V 0x00000001 +#define CP_DMA_INLINK_START_S 29 +/** CP_DMA_INLINK_RESTART : R/W; bitpos: [30]; default: 0; + * Set this bit to restart new inlink descriptors. + */ +#define CP_DMA_INLINK_RESTART (BIT(30)) +#define CP_DMA_INLINK_RESTART_M (CP_DMA_INLINK_RESTART_V << CP_DMA_INLINK_RESTART_S) +#define CP_DMA_INLINK_RESTART_V 0x00000001 +#define CP_DMA_INLINK_RESTART_S 30 +/** CP_DMA_INLINK_PARK : RO; bitpos: [31]; default: 0; + * 1: the inlink descriptor's FSM is in idle state. + * 0: the inlink descriptor's FSM is working. + */ +#define CP_DMA_INLINK_PARK (BIT(31)) +#define CP_DMA_INLINK_PARK_M (CP_DMA_INLINK_PARK_V << CP_DMA_INLINK_PARK_S) +#define CP_DMA_INLINK_PARK_V 0x00000001 +#define CP_DMA_INLINK_PARK_S 31 + +/** CP_DMA_OUT_EOF_DES_ADDR_REG register + * Outlink descriptor address when EOF occurs + */ +#define CP_DMA_OUT_EOF_DES_ADDR_REG (DR_REG_CP_BASE + 0x18) +/** CP_DMA_OUT_EOF_DES_ADDR : RO; bitpos: [31:0]; default: 0; + * This register stores the address of the outlink descriptor when the EOF bit in this + * descriptor is 1. + */ +#define CP_DMA_OUT_EOF_DES_ADDR 0xFFFFFFFF +#define CP_DMA_OUT_EOF_DES_ADDR_M (CP_DMA_OUT_EOF_DES_ADDR_V << CP_DMA_OUT_EOF_DES_ADDR_S) +#define CP_DMA_OUT_EOF_DES_ADDR_V 0xFFFFFFFF +#define CP_DMA_OUT_EOF_DES_ADDR_S 0 + +/** CP_DMA_IN_EOF_DES_ADDR_REG register + * Inlink descriptor address when EOF occurs + */ +#define CP_DMA_IN_EOF_DES_ADDR_REG (DR_REG_CP_BASE + 0x1c) +/** CP_DMA_IN_SUC_EOF_DES_ADDR : RO; bitpos: [31:0]; default: 0; + * This register stores the address of the inlink descriptor when received successful + * EOF. + */ +#define CP_DMA_IN_SUC_EOF_DES_ADDR 0xFFFFFFFF +#define CP_DMA_IN_SUC_EOF_DES_ADDR_M (CP_DMA_IN_SUC_EOF_DES_ADDR_V << CP_DMA_IN_SUC_EOF_DES_ADDR_S) +#define CP_DMA_IN_SUC_EOF_DES_ADDR_V 0xFFFFFFFF +#define CP_DMA_IN_SUC_EOF_DES_ADDR_S 0 + +/** CP_DMA_OUT_EOF_BFR_DES_ADDR_REG register + * Outlink descriptor address before the last outlink descriptor + */ +#define CP_DMA_OUT_EOF_BFR_DES_ADDR_REG (DR_REG_CP_BASE + 0x20) +/** CP_DMA_OUT_EOF_BFR_DES_ADDR : RO; bitpos: [31:0]; default: 0; + * This register stores the address of the outlink descriptor before the last outlink + * descriptor. + */ +#define CP_DMA_OUT_EOF_BFR_DES_ADDR 0xFFFFFFFF +#define CP_DMA_OUT_EOF_BFR_DES_ADDR_M (CP_DMA_OUT_EOF_BFR_DES_ADDR_V << CP_DMA_OUT_EOF_BFR_DES_ADDR_S) +#define CP_DMA_OUT_EOF_BFR_DES_ADDR_V 0xFFFFFFFF +#define CP_DMA_OUT_EOF_BFR_DES_ADDR_S 0 + +/** CP_DMA_INLINK_DSCR_REG register + * Address of current inlink descriptor + */ +#define CP_DMA_INLINK_DSCR_REG (DR_REG_CP_BASE + 0x24) +/** CP_DMA_INLINK_DSCR : RO; bitpos: [31:0]; default: 0; + * The address of the current inlink descriptor x. + */ +#define CP_DMA_INLINK_DSCR 0xFFFFFFFF +#define CP_DMA_INLINK_DSCR_M (CP_DMA_INLINK_DSCR_V << CP_DMA_INLINK_DSCR_S) +#define CP_DMA_INLINK_DSCR_V 0xFFFFFFFF +#define CP_DMA_INLINK_DSCR_S 0 + +/** CP_DMA_INLINK_DSCR_BF0_REG register + * Address of last inlink descriptor + */ +#define CP_DMA_INLINK_DSCR_BF0_REG (DR_REG_CP_BASE + 0x28) +/** CP_DMA_INLINK_DSCR_BF0 : RO; bitpos: [31:0]; default: 0; + * The address of the last inlink descriptor x-1. + */ +#define CP_DMA_INLINK_DSCR_BF0 0xFFFFFFFF +#define CP_DMA_INLINK_DSCR_BF0_M (CP_DMA_INLINK_DSCR_BF0_V << CP_DMA_INLINK_DSCR_BF0_S) +#define CP_DMA_INLINK_DSCR_BF0_V 0xFFFFFFFF +#define CP_DMA_INLINK_DSCR_BF0_S 0 + +/** CP_DMA_INLINK_DSCR_BF1_REG register + * Address of the second-to-last inlink descriptor + */ +#define CP_DMA_INLINK_DSCR_BF1_REG (DR_REG_CP_BASE + 0x2c) +/** CP_DMA_INLINK_DSCR_BF1 : RO; bitpos: [31:0]; default: 0; + * The address of the second-to-last inlink descriptor x-2. + */ +#define CP_DMA_INLINK_DSCR_BF1 0xFFFFFFFF +#define CP_DMA_INLINK_DSCR_BF1_M (CP_DMA_INLINK_DSCR_BF1_V << CP_DMA_INLINK_DSCR_BF1_S) +#define CP_DMA_INLINK_DSCR_BF1_V 0xFFFFFFFF +#define CP_DMA_INLINK_DSCR_BF1_S 0 + +/** CP_DMA_OUTLINK_DSCR_REG register + * Address of current outlink descriptor + */ +#define CP_DMA_OUTLINK_DSCR_REG (DR_REG_CP_BASE + 0x30) +/** CP_DMA_OUTLINK_DSCR : RO; bitpos: [31:0]; default: 0; + * The address of the current outlink descriptor y. + */ +#define CP_DMA_OUTLINK_DSCR 0xFFFFFFFF +#define CP_DMA_OUTLINK_DSCR_M (CP_DMA_OUTLINK_DSCR_V << CP_DMA_OUTLINK_DSCR_S) +#define CP_DMA_OUTLINK_DSCR_V 0xFFFFFFFF +#define CP_DMA_OUTLINK_DSCR_S 0 + +/** CP_DMA_OUTLINK_DSCR_BF0_REG register + * Address of last outlink descriptor + */ +#define CP_DMA_OUTLINK_DSCR_BF0_REG (DR_REG_CP_BASE + 0x34) +/** CP_DMA_OUTLINK_DSCR_BF0 : RO; bitpos: [31:0]; default: 0; + * The address of the last outlink descriptor y-1. + */ +#define CP_DMA_OUTLINK_DSCR_BF0 0xFFFFFFFF +#define CP_DMA_OUTLINK_DSCR_BF0_M (CP_DMA_OUTLINK_DSCR_BF0_V << CP_DMA_OUTLINK_DSCR_BF0_S) +#define CP_DMA_OUTLINK_DSCR_BF0_V 0xFFFFFFFF +#define CP_DMA_OUTLINK_DSCR_BF0_S 0 + +/** CP_DMA_OUTLINK_DSCR_BF1_REG register + * Address of the second-to-last outlink descriptor + */ +#define CP_DMA_OUTLINK_DSCR_BF1_REG (DR_REG_CP_BASE + 0x38) +/** CP_DMA_OUTLINK_DSCR_BF1 : RO; bitpos: [31:0]; default: 0; + * The address of the second-to-last outlink descriptor y-2. + */ +#define CP_DMA_OUTLINK_DSCR_BF1 0xFFFFFFFF +#define CP_DMA_OUTLINK_DSCR_BF1_M (CP_DMA_OUTLINK_DSCR_BF1_V << CP_DMA_OUTLINK_DSCR_BF1_S) +#define CP_DMA_OUTLINK_DSCR_BF1_V 0xFFFFFFFF +#define CP_DMA_OUTLINK_DSCR_BF1_S 0 + +/** CP_DMA_CONF_REG register + * Copy DMA configuration register + */ +#define CP_DMA_CONF_REG (DR_REG_CP_BASE + 0x3c) +/** CP_DMA_IN_RST : R/W; bitpos: [0]; default: 0; + * Set this bit to reset in_inf state machine. + */ +#define CP_DMA_IN_RST (BIT(0)) +#define CP_DMA_IN_RST_M (CP_DMA_IN_RST_V << CP_DMA_IN_RST_S) +#define CP_DMA_IN_RST_V 0x00000001 +#define CP_DMA_IN_RST_S 0 +/** CP_DMA_OUT_RST : R/W; bitpos: [1]; default: 0; + * Set this bit to reset out_inf state machine. + */ +#define CP_DMA_OUT_RST (BIT(1)) +#define CP_DMA_OUT_RST_M (CP_DMA_OUT_RST_V << CP_DMA_OUT_RST_S) +#define CP_DMA_OUT_RST_V 0x00000001 +#define CP_DMA_OUT_RST_S 1 +/** CP_DMA_CMDFIFO_RST : R/W; bitpos: [2]; default: 0; + * Set this bit to reset in_cmd fifo and out_cmd fifo. + */ +#define CP_DMA_CMDFIFO_RST (BIT(2)) +#define CP_DMA_CMDFIFO_RST_M (CP_DMA_CMDFIFO_RST_V << CP_DMA_CMDFIFO_RST_S) +#define CP_DMA_CMDFIFO_RST_V 0x00000001 +#define CP_DMA_CMDFIFO_RST_S 2 +/** CP_DMA_FIFO_RST : R/W; bitpos: [3]; default: 0; + * Set this bit to reset data in receive FIFO. + */ +#define CP_DMA_FIFO_RST (BIT(3)) +#define CP_DMA_FIFO_RST_M (CP_DMA_FIFO_RST_V << CP_DMA_FIFO_RST_S) +#define CP_DMA_FIFO_RST_V 0x00000001 +#define CP_DMA_FIFO_RST_S 3 +/** CP_DMA_OUT_OWNER : R/W; bitpos: [4]; default: 0; + * This is used to configure the owner bit in OUT descriptor. This is effective only + * when you set reg_out_auto_wrback. + */ +#define CP_DMA_OUT_OWNER (BIT(4)) +#define CP_DMA_OUT_OWNER_M (CP_DMA_OUT_OWNER_V << CP_DMA_OUT_OWNER_S) +#define CP_DMA_OUT_OWNER_V 0x00000001 +#define CP_DMA_OUT_OWNER_S 4 +/** CP_DMA_IN_OWNER : R/W; bitpos: [5]; default: 0; + * This is used to configure the owner bit in IN descriptor. + */ +#define CP_DMA_IN_OWNER (BIT(5)) +#define CP_DMA_IN_OWNER_M (CP_DMA_IN_OWNER_V << CP_DMA_IN_OWNER_S) +#define CP_DMA_IN_OWNER_V 0x00000001 +#define CP_DMA_IN_OWNER_S 5 +/** CP_DMA_OUT_AUTO_WRBACK : R/W; bitpos: [6]; default: 0; + * This bit is used to write back out descriptor when hardware has already used this + * descriptor. + */ +#define CP_DMA_OUT_AUTO_WRBACK (BIT(6)) +#define CP_DMA_OUT_AUTO_WRBACK_M (CP_DMA_OUT_AUTO_WRBACK_V << CP_DMA_OUT_AUTO_WRBACK_S) +#define CP_DMA_OUT_AUTO_WRBACK_V 0x00000001 +#define CP_DMA_OUT_AUTO_WRBACK_S 6 +/** CP_DMA_CHECK_OWNER : R/W; bitpos: [7]; default: 0; + * Set this bit to enable owner bit check in descriptor. + */ +#define CP_DMA_CHECK_OWNER (BIT(7)) +#define CP_DMA_CHECK_OWNER_M (CP_DMA_CHECK_OWNER_V << CP_DMA_CHECK_OWNER_S) +#define CP_DMA_CHECK_OWNER_V 0x00000001 +#define CP_DMA_CHECK_OWNER_S 7 +/** CP_DMA_CRC_CAL_RESET : R/W; bitpos: [8]; default: 0; + * Set this bit to reset crc calculation. + */ +#define CP_DMA_CRC_CAL_RESET (BIT(8)) +#define CP_DMA_CRC_CAL_RESET_M (CP_DMA_CRC_CAL_RESET_V << CP_DMA_CRC_CAL_RESET_S) +#define CP_DMA_CRC_CAL_RESET_V 0x00000001 +#define CP_DMA_CRC_CAL_RESET_S 8 +/** CP_DMA_CRC_CAL_EN : R/W; bitpos: [9]; default: 0; + * Set this bit enable crc calculation function. + */ +#define CP_DMA_CRC_CAL_EN (BIT(9)) +#define CP_DMA_CRC_CAL_EN_M (CP_DMA_CRC_CAL_EN_V << CP_DMA_CRC_CAL_EN_S) +#define CP_DMA_CRC_CAL_EN_V 0x00000001 +#define CP_DMA_CRC_CAL_EN_S 9 +/** CP_DMA_CRC_BIG_ENDIAN_EN : R/W; bitpos: [10]; default: 0; + * Set this bit to reorder the bit of data which will be send to excute crc. + */ +#define CP_DMA_CRC_BIG_ENDIAN_EN (BIT(10)) +#define CP_DMA_CRC_BIG_ENDIAN_EN_M (CP_DMA_CRC_BIG_ENDIAN_EN_V << CP_DMA_CRC_BIG_ENDIAN_EN_S) +#define CP_DMA_CRC_BIG_ENDIAN_EN_V 0x00000001 +#define CP_DMA_CRC_BIG_ENDIAN_EN_S 10 +/** CP_DMA_CRC_OUT_REVERSE_EN : R/W; bitpos: [11]; default: 0; + * Set this bit to reverse the crc calculation result. + */ +#define CP_DMA_CRC_OUT_REVERSE_EN (BIT(11)) +#define CP_DMA_CRC_OUT_REVERSE_EN_M (CP_DMA_CRC_OUT_REVERSE_EN_V << CP_DMA_CRC_OUT_REVERSE_EN_S) +#define CP_DMA_CRC_OUT_REVERSE_EN_V 0x00000001 +#define CP_DMA_CRC_OUT_REVERSE_EN_S 11 +/** CP_DMA_CLK_EN : R/W; bitpos: [31]; default: 0; + * 1'b1: Force clock on for register. 1'b0: Support clock only when application writes + * registers. + */ +#define CP_DMA_CLK_EN (BIT(31)) +#define CP_DMA_CLK_EN_M (CP_DMA_CLK_EN_V << CP_DMA_CLK_EN_S) +#define CP_DMA_CLK_EN_V 0x00000001 +#define CP_DMA_CLK_EN_S 31 + +/** CP_DMA_IN_ST_REG register + * Status register of receiving data + */ +#define CP_DMA_IN_ST_REG (DR_REG_CP_BASE + 0x40) +/** CP_DMA_INLINK_DSCR_ADDR : RO; bitpos: [17:0]; default: 0; + * This register stores the current inlink descriptor's address. + */ +#define CP_DMA_INLINK_DSCR_ADDR 0x0003FFFF +#define CP_DMA_INLINK_DSCR_ADDR_M (CP_DMA_INLINK_DSCR_ADDR_V << CP_DMA_INLINK_DSCR_ADDR_S) +#define CP_DMA_INLINK_DSCR_ADDR_V 0x0003FFFF +#define CP_DMA_INLINK_DSCR_ADDR_S 0 +/** CP_DMA_IN_DSCR_STATE : RO; bitpos: [19:18]; default: 0; + * Reserved. + */ +#define CP_DMA_IN_DSCR_STATE 0x00000003 +#define CP_DMA_IN_DSCR_STATE_M (CP_DMA_IN_DSCR_STATE_V << CP_DMA_IN_DSCR_STATE_S) +#define CP_DMA_IN_DSCR_STATE_V 0x00000003 +#define CP_DMA_IN_DSCR_STATE_S 18 +/** CP_DMA_IN_STATE : RO; bitpos: [22:20]; default: 0; + * Reserved. + */ +#define CP_DMA_IN_STATE 0x00000007 +#define CP_DMA_IN_STATE_M (CP_DMA_IN_STATE_V << CP_DMA_IN_STATE_S) +#define CP_DMA_IN_STATE_V 0x00000007 +#define CP_DMA_IN_STATE_S 20 +/** CP_DMA_FIFO_EMPTY : RO; bitpos: [23]; default: 0; + * Copy DMA FIFO empty signal. + */ +#define CP_DMA_FIFO_EMPTY (BIT(23)) +#define CP_DMA_FIFO_EMPTY_M (CP_DMA_FIFO_EMPTY_V << CP_DMA_FIFO_EMPTY_S) +#define CP_DMA_FIFO_EMPTY_V 0x00000001 +#define CP_DMA_FIFO_EMPTY_S 23 + +/** CP_DMA_OUT_ST_REG register + * Status register of trasmitting data + */ +#define CP_DMA_OUT_ST_REG (DR_REG_CP_BASE + 0x44) +/** CP_DMA_OUTLINK_DSCR_ADDR : RO; bitpos: [17:0]; default: 0; + * This register stores the current outlink descriptor's address. + */ +#define CP_DMA_OUTLINK_DSCR_ADDR 0x0003FFFF +#define CP_DMA_OUTLINK_DSCR_ADDR_M (CP_DMA_OUTLINK_DSCR_ADDR_V << CP_DMA_OUTLINK_DSCR_ADDR_S) +#define CP_DMA_OUTLINK_DSCR_ADDR_V 0x0003FFFF +#define CP_DMA_OUTLINK_DSCR_ADDR_S 0 +/** CP_DMA_OUT_DSCR_STATE : RO; bitpos: [19:18]; default: 0; + * Reserved. + */ +#define CP_DMA_OUT_DSCR_STATE 0x00000003 +#define CP_DMA_OUT_DSCR_STATE_M (CP_DMA_OUT_DSCR_STATE_V << CP_DMA_OUT_DSCR_STATE_S) +#define CP_DMA_OUT_DSCR_STATE_V 0x00000003 +#define CP_DMA_OUT_DSCR_STATE_S 18 +/** CP_DMA_OUT_STATE : RO; bitpos: [22:20]; default: 0; + * Reserved. + */ +#define CP_DMA_OUT_STATE 0x00000007 +#define CP_DMA_OUT_STATE_M (CP_DMA_OUT_STATE_V << CP_DMA_OUT_STATE_S) +#define CP_DMA_OUT_STATE_V 0x00000007 +#define CP_DMA_OUT_STATE_S 20 +/** CP_DMA_FIFO_FULL : RO; bitpos: [23]; default: 0; + * Copy DMA FIFO full signal. + */ +#define CP_DMA_FIFO_FULL (BIT(23)) +#define CP_DMA_FIFO_FULL_M (CP_DMA_FIFO_FULL_V << CP_DMA_FIFO_FULL_S) +#define CP_DMA_FIFO_FULL_V 0x00000001 +#define CP_DMA_FIFO_FULL_S 23 + +/** CP_DMA_CRC_OUT_REG register + * CRC result register + */ +#define CP_DMA_CRC_OUT_REG (DR_REG_CP_BASE + 0x48) +/** CP_DMA_CRC_RESULT : RO; bitpos: [31:0]; default: 0; + * This register stores the result of CRC. + */ +#define CP_DMA_CRC_RESULT 0xFFFFFFFF +#define CP_DMA_CRC_RESULT_M (CP_DMA_CRC_RESULT_V << CP_DMA_CRC_RESULT_S) +#define CP_DMA_CRC_RESULT_V 0xFFFFFFFF +#define CP_DMA_CRC_RESULT_S 0 + +/** CP_DMA_DATE_REG register + * Copy DMA version register + */ +#define CP_DMA_DATE_REG (DR_REG_CP_BASE + 0xfc) +/** CP_DMA_DMA_DATE : R/W; bitpos: [31:0]; default: 403185664; + * This is the version register. + */ +#define CP_DMA_DMA_DATE 0xFFFFFFFF +#define CP_DMA_DMA_DATE_M (CP_DMA_DMA_DATE_V << CP_DMA_DMA_DATE_S) +#define CP_DMA_DMA_DATE_V 0xFFFFFFFF +#define CP_DMA_DMA_DATE_S 0 + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/soc/esp32s2/include/soc/cp_dma_struct.h b/components/soc/soc/esp32s2/include/soc/cp_dma_struct.h new file mode 100644 index 0000000000..208c82939c --- /dev/null +++ b/components/soc/soc/esp32s2/include/soc/cp_dma_struct.h @@ -0,0 +1,623 @@ +/** Copyright 2020 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** Interrupt Registers */ +/** Type of dma_int_raw register + * Raw interrupt status + */ +typedef union { + struct { + /** dma_in_done_int_raw : RO; bitpos: [0]; default: 0; + * This is the interrupt raw bit. Triggered when the last data of frame is received or + * the receive buffer is full indicated by inlink descriptor. + */ + uint32_t dma_in_done_int_raw: 1; + /** dma_in_suc_eof_int_raw : RO; bitpos: [1]; default: 0; + * This is the interrupt raw bit. Triggered when the last data of one frame is + * received. + */ + uint32_t dma_in_suc_eof_int_raw: 1; + /** dma_out_done_int_raw : RO; bitpos: [2]; default: 0; + * This is the interrupt raw bit. Triggered when all data indicated by one outlink + * descriptor has been pushed into Tx FIFO. + */ + uint32_t dma_out_done_int_raw: 1; + /** dma_out_eof_int_raw : RO; bitpos: [3]; default: 0; + * This is the interrupt raw bit. Triggered when the last data with EOF flag has been + * pushed into Tx FIFO. + */ + uint32_t dma_out_eof_int_raw: 1; + /** dma_in_dscr_err_int_raw : RO; bitpos: [4]; default: 0; + * This is the interrupt raw bit. Triggered when detecting inlink descriptor error, + * including owner error, the second and third word error of inlink descriptor. + */ + uint32_t dma_in_dscr_err_int_raw: 1; + /** dma_out_dscr_err_int_raw : RO; bitpos: [5]; default: 0; + * This is the interrupt raw bit. Triggered when detecting outlink descriptor error, + * including owner error, the second and third word error of outlink descriptor. + */ + uint32_t dma_out_dscr_err_int_raw: 1; + /** dma_in_dscr_empty_int_raw : RO; bitpos: [6]; default: 0; + * This is the interrupt raw bit. Triggered when receiving data is completed and no + * more inlink descriptor. + */ + uint32_t dma_in_dscr_empty_int_raw: 1; + /** dma_out_total_eof_int_raw : RO; bitpos: [7]; default: 0; + * This is the interrupt raw bit. Triggered when data corresponding to all outlink + * descriptor and the last descriptor with valid EOF is transmitted out. + */ + uint32_t dma_out_total_eof_int_raw: 1; + /** dma_crc_done_int_raw : RO; bitpos: [8]; default: 0; + * This is the interrupt raw bit. Triggered when crc calculation is done. + */ + uint32_t dma_crc_done_int_raw: 1; + }; + uint32_t val; +} cp_dma_int_raw_reg_t; + +/** Type of dma_int_st register + * Masked interrupt status + */ +typedef union { + struct { + /** dma_in_done_int_st : RO; bitpos: [0]; default: 0; + * This is the masked interrupt bit for cp_in_done_int interrupt when + * cp_in_done_int_ena is set to 1. + */ + uint32_t dma_in_done_int_st: 1; + /** dma_in_suc_eof_int_st : RO; bitpos: [1]; default: 0; + * This is the masked interrupt bit for cp_in_suc_eof_int interrupt when + * cp_in_suc_eof_int_ena is set to 1. + */ + uint32_t dma_in_suc_eof_int_st: 1; + /** dma_out_done_int_st : RO; bitpos: [2]; default: 0; + * This is the masked interrupt bit for cp_out_done_int interrupt when + * cp_out_done_int_ena is set to 1. + */ + uint32_t dma_out_done_int_st: 1; + /** dma_out_eof_int_st : RO; bitpos: [3]; default: 0; + * This is the masked interrupt bit for cp_out_eof_int interrupt when + * cp_out_eof_int_ena is set to 1. + */ + uint32_t dma_out_eof_int_st: 1; + /** dma_in_dscr_err_int_st : RO; bitpos: [4]; default: 0; + * This is the masked interrupt bit for cp_in_dscr_err_int interrupt when + * cp_in_dscr_err_int_ena is set to 1. + */ + uint32_t dma_in_dscr_err_int_st: 1; + /** dma_out_dscr_err_int_st : RO; bitpos: [5]; default: 0; + * This is the masked interrupt bit for cp_out_dscr_err_int interrupt when + * cp_out_dscr_err_int_ena is set to 1. + */ + uint32_t dma_out_dscr_err_int_st: 1; + /** dma_in_dscr_empty_int_st : RO; bitpos: [6]; default: 0; + * This is the masked interrupt bit for cp_in_dscr_empty_int interrupt when + * cp_in_dscr_empty_int_ena is set to 1. + */ + uint32_t dma_in_dscr_empty_int_st: 1; + /** dma_out_total_eof_int_st : RO; bitpos: [7]; default: 0; + * This is the masked interrupt bit for cp_out_total_eof_int interrupt when + * cp_out_total_eof_int_ena is set to 1. + */ + uint32_t dma_out_total_eof_int_st: 1; + /** dma_crc_done_int_st : RO; bitpos: [8]; default: 0; + * This is the masked interrupt bit for cp_crc_done_int interrupt when + * cp_crc_done_int_ena is set to 1. + */ + uint32_t dma_crc_done_int_st: 1; + }; + uint32_t val; +} cp_dma_int_st_reg_t; + +/** Type of dma_int_ena register + * Interrupt enable bits + */ +typedef union { + struct { + /** dma_in_done_int_ena : R/W; bitpos: [0]; default: 0; + * This is the interrupt enable bit for cp_in_done_int interrupt. + */ + uint32_t dma_in_done_int_ena: 1; + /** dma_in_suc_eof_int_ena : R/W; bitpos: [1]; default: 0; + * This is the interrupt enable bit for cp_in_suc_eof_int interrupt. + */ + uint32_t dma_in_suc_eof_int_ena: 1; + /** dma_out_done_int_ena : R/W; bitpos: [2]; default: 0; + * This is the interrupt enable bit for cp_out_done_int interrupt. + */ + uint32_t dma_out_done_int_ena: 1; + /** dma_out_eof_int_ena : R/W; bitpos: [3]; default: 0; + * This is the interrupt enable bit for cp_out_eof_int interrupt. + */ + uint32_t dma_out_eof_int_ena: 1; + /** dma_in_dscr_err_int_ena : R/W; bitpos: [4]; default: 0; + * This is the interrupt enable bit for cp_in_dscr_err_int interrupt. + */ + uint32_t dma_in_dscr_err_int_ena: 1; + /** dma_out_dscr_err_int_ena : R/W; bitpos: [5]; default: 0; + * This is the interrupt enable bit for cp_out_dscr_err_int interrupt. + */ + uint32_t dma_out_dscr_err_int_ena: 1; + /** dma_in_dscr_empty_int_ena : R/W; bitpos: [6]; default: 0; + * This is the interrupt enable bit for cp_in_dscr_empty_int interrupt. + */ + uint32_t dma_in_dscr_empty_int_ena: 1; + /** dma_out_total_eof_int_ena : R/W; bitpos: [7]; default: 0; + * This is the interrupt enable bit for cp_out_total_eof_int interrupt. + */ + uint32_t dma_out_total_eof_int_ena: 1; + /** dma_crc_done_int_ena : R/W; bitpos: [8]; default: 0; + * This is the interrupt enable bit for cp_crc_done_int interrupt. + */ + uint32_t dma_crc_done_int_ena: 1; + }; + uint32_t val; +} cp_dma_int_ena_reg_t; + +/** Type of dma_int_clr register + * Interrupt clear bits + */ +typedef union { + struct { + /** dma_in_done_int_clr : WO; bitpos: [0]; default: 0; + * Set this bit to clear cp_in_done_int interrupt. + */ + uint32_t dma_in_done_int_clr: 1; + /** dma_in_suc_eof_int_clr : WO; bitpos: [1]; default: 0; + * Set this bit to clear cp_in_suc_eof_int interrupt. + */ + uint32_t dma_in_suc_eof_int_clr: 1; + /** dma_out_done_int_clr : WO; bitpos: [2]; default: 0; + * Set this bit to clear cp_out_done_int interrupt. + */ + uint32_t dma_out_done_int_clr: 1; + /** dma_out_eof_int_clr : WO; bitpos: [3]; default: 0; + * Set this bit to clear cp_out_eof_int interrupt. + */ + uint32_t dma_out_eof_int_clr: 1; + /** dma_in_dscr_err_int_clr : WO; bitpos: [4]; default: 0; + * Set this bit to clear cp_in_dscr_err_int interrupt. + */ + uint32_t dma_in_dscr_err_int_clr: 1; + /** dma_out_dscr_err_int_clr : WO; bitpos: [5]; default: 0; + * Set this bit to clear cp_out_dscr_err_int interrupt. + */ + uint32_t dma_out_dscr_err_int_clr: 1; + /** dma_in_dscr_empty_int_clr : WO; bitpos: [6]; default: 0; + * Set this bit to clear cp_in_dscr_empty_int interrupt. + */ + uint32_t dma_in_dscr_empty_int_clr: 1; + /** dma_out_total_eof_int_clr : WO; bitpos: [7]; default: 0; + * Set this bit to clear cp_out_total_eof_int interrupt. + */ + uint32_t dma_out_total_eof_int_clr: 1; + /** dma_crc_done_int_clr : WO; bitpos: [8]; default: 0; + * Set this bit to clear cp_crc_done_int interrupt. + */ + uint32_t dma_crc_done_int_clr: 1; + }; + uint32_t val; +} cp_dma_int_clr_reg_t; + + +/** Configuration Registers */ +/** Type of dma_out_link register + * Link descriptor address and control + */ +typedef union { + struct { + /** dma_outlink_addr : R/W; bitpos: [19:0]; default: 0; + * This register is used to specify the least significant 20 bits of the first outlink + * descriptor's address. + */ + uint32_t dma_outlink_addr: 20; + uint32_t reserved_20: 8; + /** dma_outlink_stop : R/W; bitpos: [28]; default: 0; + * Set this bit to stop dealing with the outlink descriptor. + */ + uint32_t dma_outlink_stop: 1; + /** dma_outlink_start : R/W; bitpos: [29]; default: 0; + * Set this bit to start a new outlink descriptor. + */ + uint32_t dma_outlink_start: 1; + /** dma_outlink_restart : R/W; bitpos: [30]; default: 0; + * Set this bit to restart the outlink descriptpr from the last address. + */ + uint32_t dma_outlink_restart: 1; + /** dma_outlink_park : RO; bitpos: [31]; default: 0; + * 1: the outlink descriptor's FSM is in idle state. + * 0: the outlink descriptor's FSM is working. + */ + uint32_t dma_outlink_park: 1; + }; + uint32_t val; +} cp_dma_out_link_reg_t; + +/** Type of dma_in_link register + * Link descriptor address and control + */ +typedef union { + struct { + /** dma_inlink_addr : R/W; bitpos: [19:0]; default: 0; + * This register is used to specify the least significant 20 bits of the first inlink + * descriptor's address. + */ + uint32_t dma_inlink_addr: 20; + uint32_t reserved_20: 8; + /** dma_inlink_stop : R/W; bitpos: [28]; default: 0; + * Set this bit to stop dealing with the inlink descriptors. + */ + uint32_t dma_inlink_stop: 1; + /** dma_inlink_start : R/W; bitpos: [29]; default: 0; + * Set this bit to start dealing with the inlink descriptors. + */ + uint32_t dma_inlink_start: 1; + /** dma_inlink_restart : R/W; bitpos: [30]; default: 0; + * Set this bit to restart new inlink descriptors. + */ + uint32_t dma_inlink_restart: 1; + /** dma_inlink_park : RO; bitpos: [31]; default: 0; + * 1: the inlink descriptor's FSM is in idle state. + * 0: the inlink descriptor's FSM is working. + */ + uint32_t dma_inlink_park: 1; + }; + uint32_t val; +} cp_dma_in_link_reg_t; + +/** Type of dma_conf register + * Copy DMA configuration register + */ +typedef union { + struct { + /** dma_in_rst : R/W; bitpos: [0]; default: 0; + * Set this bit to reset in_inf state machine. + */ + uint32_t dma_in_rst: 1; + /** dma_out_rst : R/W; bitpos: [1]; default: 0; + * Set this bit to reset out_inf state machine. + */ + uint32_t dma_out_rst: 1; + /** dma_cmdfifo_rst : R/W; bitpos: [2]; default: 0; + * Set this bit to reset in_cmd fifo and out_cmd fifo. + */ + uint32_t dma_cmdfifo_rst: 1; + /** dma_fifo_rst : R/W; bitpos: [3]; default: 0; + * Set this bit to reset data in receive FIFO. + */ + uint32_t dma_fifo_rst: 1; + /** dma_out_owner : R/W; bitpos: [4]; default: 0; + * This is used to configure the owner bit in OUT descriptor. This is effective only + * when you set reg_out_auto_wrback. + */ + uint32_t dma_out_owner: 1; + /** dma_in_owner : R/W; bitpos: [5]; default: 0; + * This is used to configure the owner bit in IN descriptor. + */ + uint32_t dma_in_owner: 1; + /** dma_out_auto_wrback : R/W; bitpos: [6]; default: 0; + * This bit is used to write back out descriptor when hardware has already used this + * descriptor. + */ + uint32_t dma_out_auto_wrback: 1; + /** dma_check_owner : R/W; bitpos: [7]; default: 0; + * Set this bit to enable owner bit check in descriptor. + */ + uint32_t dma_check_owner: 1; + /** dma_crc_cal_reset : R/W; bitpos: [8]; default: 0; + * Set this bit to reset crc calculation. + */ + uint32_t dma_crc_cal_reset: 1; + /** dma_crc_cal_en : R/W; bitpos: [9]; default: 0; + * Set this bit enable crc calculation function. + */ + uint32_t dma_crc_cal_en: 1; + /** dma_crc_big_endian_en : R/W; bitpos: [10]; default: 0; + * Set this bit to reorder the bit of data which will be send to excute crc. + */ + uint32_t dma_crc_big_endian_en: 1; + /** dma_crc_out_reverse_en : R/W; bitpos: [11]; default: 0; + * Set this bit to reverse the crc calculation result. + */ + uint32_t dma_crc_out_reverse_en: 1; + uint32_t reserved_12: 19; + /** dma_clk_en : R/W; bitpos: [31]; default: 0; + * 1'b1: Force clock on for register. 1'b0: Support clock only when application writes + * registers. + */ + uint32_t dma_clk_en: 1; + }; + uint32_t val; +} cp_dma_conf_reg_t; + + +/** Status Registers */ +/** Type of dma_out_eof_des_addr register + * Outlink descriptor address when EOF occurs + */ +typedef union { + struct { + /** dma_out_eof_des_addr : RO; bitpos: [31:0]; default: 0; + * This register stores the address of the outlink descriptor when the EOF bit in this + * descriptor is 1. + */ + uint32_t dma_out_eof_des_addr: 32; + }; + uint32_t val; +} cp_dma_out_eof_des_addr_reg_t; + +/** Type of dma_in_eof_des_addr register + * Inlink descriptor address when EOF occurs + */ +typedef union { + struct { + /** dma_in_suc_eof_des_addr : RO; bitpos: [31:0]; default: 0; + * This register stores the address of the inlink descriptor when received successful + * EOF. + */ + uint32_t dma_in_suc_eof_des_addr: 32; + }; + uint32_t val; +} cp_dma_in_eof_des_addr_reg_t; + +/** Type of dma_out_eof_bfr_des_addr register + * Outlink descriptor address before the last outlink descriptor + */ +typedef union { + struct { + /** dma_out_eof_bfr_des_addr : RO; bitpos: [31:0]; default: 0; + * This register stores the address of the outlink descriptor before the last outlink + * descriptor. + */ + uint32_t dma_out_eof_bfr_des_addr: 32; + }; + uint32_t val; +} cp_dma_out_eof_bfr_des_addr_reg_t; + +/** Type of dma_inlink_dscr register + * Address of current inlink descriptor + */ +typedef union { + struct { + /** dma_inlink_dscr : RO; bitpos: [31:0]; default: 0; + * The address of the current inlink descriptor x. + */ + uint32_t dma_inlink_dscr: 32; + }; + uint32_t val; +} cp_dma_inlink_dscr_reg_t; + +/** Type of dma_inlink_dscr_bf0 register + * Address of last inlink descriptor + */ +typedef union { + struct { + /** dma_inlink_dscr_bf0 : RO; bitpos: [31:0]; default: 0; + * The address of the last inlink descriptor x-1. + */ + uint32_t dma_inlink_dscr_bf0: 32; + }; + uint32_t val; +} cp_dma_inlink_dscr_bf0_reg_t; + +/** Type of dma_inlink_dscr_bf1 register + * Address of the second-to-last inlink descriptor + */ +typedef union { + struct { + /** dma_inlink_dscr_bf1 : RO; bitpos: [31:0]; default: 0; + * The address of the second-to-last inlink descriptor x-2. + */ + uint32_t dma_inlink_dscr_bf1: 32; + }; + uint32_t val; +} cp_dma_inlink_dscr_bf1_reg_t; + +/** Type of dma_outlink_dscr register + * Address of current outlink descriptor + */ +typedef union { + struct { + /** dma_outlink_dscr : RO; bitpos: [31:0]; default: 0; + * The address of the current outlink descriptor y. + */ + uint32_t dma_outlink_dscr: 32; + }; + uint32_t val; +} cp_dma_outlink_dscr_reg_t; + +/** Type of dma_outlink_dscr_bf0 register + * Address of last outlink descriptor + */ +typedef union { + struct { + /** dma_outlink_dscr_bf0 : RO; bitpos: [31:0]; default: 0; + * The address of the last outlink descriptor y-1. + */ + uint32_t dma_outlink_dscr_bf0: 32; + }; + uint32_t val; +} cp_dma_outlink_dscr_bf0_reg_t; + +/** Type of dma_outlink_dscr_bf1 register + * Address of the second-to-last outlink descriptor + */ +typedef union { + struct { + /** dma_outlink_dscr_bf1 : RO; bitpos: [31:0]; default: 0; + * The address of the second-to-last outlink descriptor y-2. + */ + uint32_t dma_outlink_dscr_bf1: 32; + }; + uint32_t val; +} cp_dma_outlink_dscr_bf1_reg_t; + +/** Type of dma_in_st register + * Status register of receiving data + */ +typedef union { + struct { + /** dma_inlink_dscr_addr : RO; bitpos: [17:0]; default: 0; + * This register stores the current inlink descriptor's address. + */ + uint32_t dma_inlink_dscr_addr: 18; + /** dma_in_dscr_state : RO; bitpos: [19:18]; default: 0; + * Reserved. + */ + uint32_t dma_in_dscr_state: 2; + /** dma_in_state : RO; bitpos: [22:20]; default: 0; + * Reserved. + */ + uint32_t dma_in_state: 3; + /** dma_fifo_empty : RO; bitpos: [23]; default: 0; + * Copy DMA FIFO empty signal. + */ + uint32_t dma_fifo_empty: 1; + }; + uint32_t val; +} cp_dma_in_st_reg_t; + +/** Type of dma_out_st register + * Status register of transmitting data + */ +typedef union { + struct { + /** dma_outlink_dscr_addr : RO; bitpos: [17:0]; default: 0; + * This register stores the current outlink descriptor's address. + */ + uint32_t dma_outlink_dscr_addr: 18; + /** dma_out_dscr_state : RO; bitpos: [19:18]; default: 0; + * Reserved. + */ + uint32_t dma_out_dscr_state: 2; + /** dma_out_state : RO; bitpos: [22:20]; default: 0; + * Reserved. + */ + uint32_t dma_out_state: 3; + /** dma_fifo_full : RO; bitpos: [23]; default: 0; + * Copy DMA FIFO full signal. + */ + uint32_t dma_fifo_full: 1; + }; + uint32_t val; +} cp_dma_out_st_reg_t; + +/** Type of dma_crc_out register + * CRC result register + */ +typedef union { + struct { + /** dma_crc_result : RO; bitpos: [31:0]; default: 0; + * This register stores the result of CRC. + */ + uint32_t dma_crc_result: 32; + }; + uint32_t val; +} cp_dma_crc_out_reg_t; + +/** Type of dma_date register + * Copy DMA version register + */ +typedef union { + struct { + /** dma_dma_date : R/W; bitpos: [31:0]; default: 403185664; + * This is the version register. + */ + uint32_t dma_dma_date: 32; + }; + uint32_t val; +} cp_dma_date_reg_t; + + +typedef struct { + volatile cp_dma_int_raw_reg_t dma_int_raw; + volatile cp_dma_int_st_reg_t dma_int_st; + volatile cp_dma_int_ena_reg_t dma_int_ena; + volatile cp_dma_int_clr_reg_t dma_int_clr; + volatile cp_dma_out_link_reg_t dma_out_link; + volatile cp_dma_in_link_reg_t dma_in_link; + volatile cp_dma_out_eof_des_addr_reg_t dma_out_eof_des_addr; + volatile cp_dma_in_eof_des_addr_reg_t dma_in_eof_des_addr; + volatile cp_dma_out_eof_bfr_des_addr_reg_t dma_out_eof_bfr_des_addr; + volatile cp_dma_inlink_dscr_reg_t dma_inlink_dscr; + volatile cp_dma_inlink_dscr_bf0_reg_t dma_inlink_dscr_bf0; + volatile cp_dma_inlink_dscr_bf1_reg_t dma_inlink_dscr_bf1; + volatile cp_dma_outlink_dscr_reg_t dma_outlink_dscr; + volatile cp_dma_outlink_dscr_bf0_reg_t dma_outlink_dscr_bf0; + volatile cp_dma_outlink_dscr_bf1_reg_t dma_outlink_dscr_bf1; + volatile cp_dma_conf_reg_t dma_conf; + volatile cp_dma_in_st_reg_t dma_in_st; + volatile cp_dma_out_st_reg_t dma_out_st; + volatile cp_dma_crc_out_reg_t dma_crc_out; + uint32_t reserved_04c; + uint32_t reserved_050; + uint32_t reserved_054; + uint32_t reserved_058; + uint32_t reserved_05c; + uint32_t reserved_060; + uint32_t reserved_064; + uint32_t reserved_068; + uint32_t reserved_06c; + uint32_t reserved_070; + uint32_t reserved_074; + uint32_t reserved_078; + uint32_t reserved_07c; + uint32_t reserved_080; + uint32_t reserved_084; + uint32_t reserved_088; + uint32_t reserved_08c; + uint32_t reserved_090; + uint32_t reserved_094; + uint32_t reserved_098; + uint32_t reserved_09c; + uint32_t reserved_0a0; + uint32_t reserved_0a4; + uint32_t reserved_0a8; + uint32_t reserved_0ac; + uint32_t reserved_0b0; + uint32_t reserved_0b4; + uint32_t reserved_0b8; + uint32_t reserved_0bc; + uint32_t reserved_0c0; + uint32_t reserved_0c4; + uint32_t reserved_0c8; + uint32_t reserved_0cc; + uint32_t reserved_0d0; + uint32_t reserved_0d4; + uint32_t reserved_0d8; + uint32_t reserved_0dc; + uint32_t reserved_0e0; + uint32_t reserved_0e4; + uint32_t reserved_0e8; + uint32_t reserved_0ec; + uint32_t reserved_0f0; + uint32_t reserved_0f4; + uint32_t reserved_0f8; + volatile cp_dma_date_reg_t dma_date; +} cp_dma_dev_t; + +_Static_assert(sizeof(cp_dma_dev_t) == 0x100, "cp_dma_dev_t should occupy 0x100 bytes in memory"); + +extern cp_dma_dev_t CP_DMA; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/soc/esp32s2/include/soc/mcp_reg.h b/components/soc/soc/esp32s2/include/soc/mcp_reg.h deleted file mode 100644 index 907cf4bfe9..0000000000 --- a/components/soc/soc/esp32s2/include/soc/mcp_reg.h +++ /dev/null @@ -1,540 +0,0 @@ -// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _SOC_MCP_REG_H_ -#define _SOC_MCP_REG_H_ - - -#ifdef __cplusplus -extern "C" { -#endif -#include "soc.h" -#define MCP_INT_RAW_REG (DR_REG_MCP_BASE + 0x0000) -/* MCP_CRC_DONE_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: */ -#define MCP_CRC_DONE_INT_RAW (BIT(8)) -#define MCP_CRC_DONE_INT_RAW_M (BIT(8)) -#define MCP_CRC_DONE_INT_RAW_V 0x1 -#define MCP_CRC_DONE_INT_RAW_S 8 -/* MCP_OUT_TOTAL_EOF_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_TOTAL_EOF_INT_RAW (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_RAW_M (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_RAW_V 0x1 -#define MCP_OUT_TOTAL_EOF_INT_RAW_S 7 -/* MCP_IN_DSCR_EMPTY_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_EMPTY_INT_RAW (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_RAW_M (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_RAW_V 0x1 -#define MCP_IN_DSCR_EMPTY_INT_RAW_S 6 -/* MCP_OUT_DSCR_ERR_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DSCR_ERR_INT_RAW (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_RAW_M (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_RAW_V 0x1 -#define MCP_OUT_DSCR_ERR_INT_RAW_S 5 -/* MCP_IN_DSCR_ERR_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_ERR_INT_RAW (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_RAW_M (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_RAW_V 0x1 -#define MCP_IN_DSCR_ERR_INT_RAW_S 4 -/* MCP_OUT_EOF_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_EOF_INT_RAW (BIT(3)) -#define MCP_OUT_EOF_INT_RAW_M (BIT(3)) -#define MCP_OUT_EOF_INT_RAW_V 0x1 -#define MCP_OUT_EOF_INT_RAW_S 3 -/* MCP_OUT_DONE_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DONE_INT_RAW (BIT(2)) -#define MCP_OUT_DONE_INT_RAW_M (BIT(2)) -#define MCP_OUT_DONE_INT_RAW_V 0x1 -#define MCP_OUT_DONE_INT_RAW_S 2 -/* MCP_IN_SUC_EOF_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_SUC_EOF_INT_RAW (BIT(1)) -#define MCP_IN_SUC_EOF_INT_RAW_M (BIT(1)) -#define MCP_IN_SUC_EOF_INT_RAW_V 0x1 -#define MCP_IN_SUC_EOF_INT_RAW_S 1 -/* MCP_IN_DONE_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DONE_INT_RAW (BIT(0)) -#define MCP_IN_DONE_INT_RAW_M (BIT(0)) -#define MCP_IN_DONE_INT_RAW_V 0x1 -#define MCP_IN_DONE_INT_RAW_S 0 - -#define MCP_INT_ST_REG (DR_REG_MCP_BASE + 0x0004) -/* MCP_CRC_DONE_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: */ -#define MCP_CRC_DONE_INT_ST (BIT(8)) -#define MCP_CRC_DONE_INT_ST_M (BIT(8)) -#define MCP_CRC_DONE_INT_ST_V 0x1 -#define MCP_CRC_DONE_INT_ST_S 8 -/* MCP_OUT_TOTAL_EOF_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_TOTAL_EOF_INT_ST (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_ST_M (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_ST_V 0x1 -#define MCP_OUT_TOTAL_EOF_INT_ST_S 7 -/* MCP_IN_DSCR_EMPTY_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_EMPTY_INT_ST (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_ST_M (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_ST_V 0x1 -#define MCP_IN_DSCR_EMPTY_INT_ST_S 6 -/* MCP_OUT_DSCR_ERR_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DSCR_ERR_INT_ST (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_ST_M (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_ST_V 0x1 -#define MCP_OUT_DSCR_ERR_INT_ST_S 5 -/* MCP_IN_DSCR_ERR_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_ERR_INT_ST (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_ST_M (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_ST_V 0x1 -#define MCP_IN_DSCR_ERR_INT_ST_S 4 -/* MCP_OUT_EOF_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_EOF_INT_ST (BIT(3)) -#define MCP_OUT_EOF_INT_ST_M (BIT(3)) -#define MCP_OUT_EOF_INT_ST_V 0x1 -#define MCP_OUT_EOF_INT_ST_S 3 -/* MCP_OUT_DONE_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DONE_INT_ST (BIT(2)) -#define MCP_OUT_DONE_INT_ST_M (BIT(2)) -#define MCP_OUT_DONE_INT_ST_V 0x1 -#define MCP_OUT_DONE_INT_ST_S 2 -/* MCP_IN_SUC_EOF_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_SUC_EOF_INT_ST (BIT(1)) -#define MCP_IN_SUC_EOF_INT_ST_M (BIT(1)) -#define MCP_IN_SUC_EOF_INT_ST_V 0x1 -#define MCP_IN_SUC_EOF_INT_ST_S 1 -/* MCP_IN_DONE_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DONE_INT_ST (BIT(0)) -#define MCP_IN_DONE_INT_ST_M (BIT(0)) -#define MCP_IN_DONE_INT_ST_V 0x1 -#define MCP_IN_DONE_INT_ST_S 0 - -#define MCP_INT_ENA_REG (DR_REG_MCP_BASE + 0x008) -/* MCP_CRC_DONE_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: */ -#define MCP_CRC_DONE_INT_ENA (BIT(8)) -#define MCP_CRC_DONE_INT_ENA_M (BIT(8)) -#define MCP_CRC_DONE_INT_ENA_V 0x1 -#define MCP_CRC_DONE_INT_ENA_S 8 -/* MCP_OUT_TOTAL_EOF_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_TOTAL_EOF_INT_ENA (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_ENA_M (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_ENA_V 0x1 -#define MCP_OUT_TOTAL_EOF_INT_ENA_S 7 -/* MCP_IN_DSCR_EMPTY_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_EMPTY_INT_ENA (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_ENA_M (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_ENA_V 0x1 -#define MCP_IN_DSCR_EMPTY_INT_ENA_S 6 -/* MCP_OUT_DSCR_ERR_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DSCR_ERR_INT_ENA (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_ENA_M (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_ENA_V 0x1 -#define MCP_OUT_DSCR_ERR_INT_ENA_S 5 -/* MCP_IN_DSCR_ERR_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_ERR_INT_ENA (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_ENA_M (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_ENA_V 0x1 -#define MCP_IN_DSCR_ERR_INT_ENA_S 4 -/* MCP_OUT_EOF_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_EOF_INT_ENA (BIT(3)) -#define MCP_OUT_EOF_INT_ENA_M (BIT(3)) -#define MCP_OUT_EOF_INT_ENA_V 0x1 -#define MCP_OUT_EOF_INT_ENA_S 3 -/* MCP_OUT_DONE_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DONE_INT_ENA (BIT(2)) -#define MCP_OUT_DONE_INT_ENA_M (BIT(2)) -#define MCP_OUT_DONE_INT_ENA_V 0x1 -#define MCP_OUT_DONE_INT_ENA_S 2 -/* MCP_IN_SUC_EOF_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_SUC_EOF_INT_ENA (BIT(1)) -#define MCP_IN_SUC_EOF_INT_ENA_M (BIT(1)) -#define MCP_IN_SUC_EOF_INT_ENA_V 0x1 -#define MCP_IN_SUC_EOF_INT_ENA_S 1 -/* MCP_IN_DONE_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DONE_INT_ENA (BIT(0)) -#define MCP_IN_DONE_INT_ENA_M (BIT(0)) -#define MCP_IN_DONE_INT_ENA_V 0x1 -#define MCP_IN_DONE_INT_ENA_S 0 - -#define MCP_INT_CLR_REG (DR_REG_MCP_BASE + 0x000c) -/* MCP_CRC_DONE_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: */ -#define MCP_CRC_DONE_INT_CLR (BIT(8)) -#define MCP_CRC_DONE_INT_CLR_M (BIT(8)) -#define MCP_CRC_DONE_INT_CLR_V 0x1 -#define MCP_CRC_DONE_INT_CLR_S 8 -/* MCP_OUT_TOTAL_EOF_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_TOTAL_EOF_INT_CLR (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_CLR_M (BIT(7)) -#define MCP_OUT_TOTAL_EOF_INT_CLR_V 0x1 -#define MCP_OUT_TOTAL_EOF_INT_CLR_S 7 -/* MCP_IN_DSCR_EMPTY_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_EMPTY_INT_CLR (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_CLR_M (BIT(6)) -#define MCP_IN_DSCR_EMPTY_INT_CLR_V 0x1 -#define MCP_IN_DSCR_EMPTY_INT_CLR_S 6 -/* MCP_OUT_DSCR_ERR_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DSCR_ERR_INT_CLR (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_CLR_M (BIT(5)) -#define MCP_OUT_DSCR_ERR_INT_CLR_V 0x1 -#define MCP_OUT_DSCR_ERR_INT_CLR_S 5 -/* MCP_IN_DSCR_ERR_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_ERR_INT_CLR (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_CLR_M (BIT(4)) -#define MCP_IN_DSCR_ERR_INT_CLR_V 0x1 -#define MCP_IN_DSCR_ERR_INT_CLR_S 4 -/* MCP_OUT_EOF_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_EOF_INT_CLR (BIT(3)) -#define MCP_OUT_EOF_INT_CLR_M (BIT(3)) -#define MCP_OUT_EOF_INT_CLR_V 0x1 -#define MCP_OUT_EOF_INT_CLR_S 3 -/* MCP_OUT_DONE_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUT_DONE_INT_CLR (BIT(2)) -#define MCP_OUT_DONE_INT_CLR_M (BIT(2)) -#define MCP_OUT_DONE_INT_CLR_V 0x1 -#define MCP_OUT_DONE_INT_CLR_S 2 -/* MCP_IN_SUC_EOF_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_SUC_EOF_INT_CLR (BIT(1)) -#define MCP_IN_SUC_EOF_INT_CLR_M (BIT(1)) -#define MCP_IN_SUC_EOF_INT_CLR_V 0x1 -#define MCP_IN_SUC_EOF_INT_CLR_S 1 -/* MCP_IN_DONE_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define MCP_IN_DONE_INT_CLR (BIT(0)) -#define MCP_IN_DONE_INT_CLR_M (BIT(0)) -#define MCP_IN_DONE_INT_CLR_V 0x1 -#define MCP_IN_DONE_INT_CLR_S 0 - -#define MCP_OUT_LINK_REG (DR_REG_MCP_BASE + 0x0010) -/* MCP_OUTLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define MCP_OUTLINK_PARK (BIT(31)) -#define MCP_OUTLINK_PARK_M (BIT(31)) -#define MCP_OUTLINK_PARK_V 0x1 -#define MCP_OUTLINK_PARK_S 31 -/* MCP_OUTLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUTLINK_RESTART (BIT(30)) -#define MCP_OUTLINK_RESTART_M (BIT(30)) -#define MCP_OUTLINK_RESTART_V 0x1 -#define MCP_OUTLINK_RESTART_S 30 -/* MCP_OUTLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUTLINK_START (BIT(29)) -#define MCP_OUTLINK_START_M (BIT(29)) -#define MCP_OUTLINK_START_V 0x1 -#define MCP_OUTLINK_START_S 29 -/* MCP_OUTLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ -/*description: */ -#define MCP_OUTLINK_STOP (BIT(28)) -#define MCP_OUTLINK_STOP_M (BIT(28)) -#define MCP_OUTLINK_STOP_V 0x1 -#define MCP_OUTLINK_STOP_S 28 -/* MCP_OUTLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: */ -#define MCP_OUTLINK_ADDR 0x000FFFFF -#define MCP_OUTLINK_ADDR_M ((MCP_OUTLINK_ADDR_V)<<(MCP_OUTLINK_ADDR_S)) -#define MCP_OUTLINK_ADDR_V 0xFFFFF -#define MCP_OUTLINK_ADDR_S 0 - -#define MCP_IN_LINK_REG (DR_REG_MCP_BASE + 0x0014) -/* MCP_INLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define MCP_INLINK_PARK (BIT(31)) -#define MCP_INLINK_PARK_M (BIT(31)) -#define MCP_INLINK_PARK_V 0x1 -#define MCP_INLINK_PARK_S 31 -/* MCP_INLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: */ -#define MCP_INLINK_RESTART (BIT(30)) -#define MCP_INLINK_RESTART_M (BIT(30)) -#define MCP_INLINK_RESTART_V 0x1 -#define MCP_INLINK_RESTART_S 30 -/* MCP_INLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ -/*description: */ -#define MCP_INLINK_START (BIT(29)) -#define MCP_INLINK_START_M (BIT(29)) -#define MCP_INLINK_START_V 0x1 -#define MCP_INLINK_START_S 29 -/* MCP_INLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ -/*description: */ -#define MCP_INLINK_STOP (BIT(28)) -#define MCP_INLINK_STOP_M (BIT(28)) -#define MCP_INLINK_STOP_V 0x1 -#define MCP_INLINK_STOP_S 28 -/* MCP_INLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: */ -#define MCP_INLINK_ADDR 0x000FFFFF -#define MCP_INLINK_ADDR_M ((MCP_INLINK_ADDR_V)<<(MCP_INLINK_ADDR_S)) -#define MCP_INLINK_ADDR_V 0xFFFFF -#define MCP_INLINK_ADDR_S 0 - -#define MCP_OUT_EOF_DES_ADDR_REG (DR_REG_MCP_BASE + 0x0018) -/* MCP_OUT_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define MCP_OUT_EOF_DES_ADDR 0xFFFFFFFF -#define MCP_OUT_EOF_DES_ADDR_M ((MCP_OUT_EOF_DES_ADDR_V)<<(MCP_OUT_EOF_DES_ADDR_S)) -#define MCP_OUT_EOF_DES_ADDR_V 0xFFFFFFFF -#define MCP_OUT_EOF_DES_ADDR_S 0 - -#define MCP_IN_EOF_DES_ADDR_REG (DR_REG_MCP_BASE + 0x001c) -/* MCP_IN_SUC_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define MCP_IN_SUC_EOF_DES_ADDR 0xFFFFFFFF -#define MCP_IN_SUC_EOF_DES_ADDR_M ((MCP_IN_SUC_EOF_DES_ADDR_V)<<(MCP_IN_SUC_EOF_DES_ADDR_S)) -#define MCP_IN_SUC_EOF_DES_ADDR_V 0xFFFFFFFF -#define MCP_IN_SUC_EOF_DES_ADDR_S 0 - -#define MCP_OUT_EOF_BFR_DES_ADDR_REG (DR_REG_MCP_BASE + 0x0020) -/* MCP_OUT_EOF_BFR_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define MCP_OUT_EOF_BFR_DES_ADDR 0xFFFFFFFF -#define MCP_OUT_EOF_BFR_DES_ADDR_M ((MCP_OUT_EOF_BFR_DES_ADDR_V)<<(MCP_OUT_EOF_BFR_DES_ADDR_S)) -#define MCP_OUT_EOF_BFR_DES_ADDR_V 0xFFFFFFFF -#define MCP_OUT_EOF_BFR_DES_ADDR_S 0 - -#define MCP_INLINK_DSCR_REG (DR_REG_MCP_BASE + 0x0024) -/* MCP_INLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: */ -#define MCP_INLINK_DSCR 0xFFFFFFFF -#define MCP_INLINK_DSCR_M ((MCP_INLINK_DSCR_V)<<(MCP_INLINK_DSCR_S)) -#define MCP_INLINK_DSCR_V 0xFFFFFFFF -#define MCP_INLINK_DSCR_S 0 - -#define MCP_INLINK_DSCR_BF0_REG (DR_REG_MCP_BASE + 0x0028) -/* MCP_INLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: */ -#define MCP_INLINK_DSCR_BF0 0xFFFFFFFF -#define MCP_INLINK_DSCR_BF0_M ((MCP_INLINK_DSCR_BF0_V)<<(MCP_INLINK_DSCR_BF0_S)) -#define MCP_INLINK_DSCR_BF0_V 0xFFFFFFFF -#define MCP_INLINK_DSCR_BF0_S 0 - -#define MCP_INLINK_DSCR_BF1_REG (DR_REG_MCP_BASE + 0x002c) -/* MCP_INLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: */ -#define MCP_INLINK_DSCR_BF1 0xFFFFFFFF -#define MCP_INLINK_DSCR_BF1_M ((MCP_INLINK_DSCR_BF1_V)<<(MCP_INLINK_DSCR_BF1_S)) -#define MCP_INLINK_DSCR_BF1_V 0xFFFFFFFF -#define MCP_INLINK_DSCR_BF1_S 0 - -#define MCP_OUTLINK_DSCR_REG (DR_REG_MCP_BASE + 0x0030) -/* MCP_OUTLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: */ -#define MCP_OUTLINK_DSCR 0xFFFFFFFF -#define MCP_OUTLINK_DSCR_M ((MCP_OUTLINK_DSCR_V)<<(MCP_OUTLINK_DSCR_S)) -#define MCP_OUTLINK_DSCR_V 0xFFFFFFFF -#define MCP_OUTLINK_DSCR_S 0 - -#define MCP_OUTLINK_DSCR_BF0_REG (DR_REG_MCP_BASE + 0x0034) -/* MCP_OUTLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: */ -#define MCP_OUTLINK_DSCR_BF0 0xFFFFFFFF -#define MCP_OUTLINK_DSCR_BF0_M ((MCP_OUTLINK_DSCR_BF0_V)<<(MCP_OUTLINK_DSCR_BF0_S)) -#define MCP_OUTLINK_DSCR_BF0_V 0xFFFFFFFF -#define MCP_OUTLINK_DSCR_BF0_S 0 - -#define MCP_OUTLINK_DSCR_BF1_REG (DR_REG_MCP_BASE + 0x0038) -/* MCP_OUTLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: */ -#define MCP_OUTLINK_DSCR_BF1 0xFFFFFFFF -#define MCP_OUTLINK_DSCR_BF1_M ((MCP_OUTLINK_DSCR_BF1_V)<<(MCP_OUTLINK_DSCR_BF1_S)) -#define MCP_OUTLINK_DSCR_BF1_V 0xFFFFFFFF -#define MCP_OUTLINK_DSCR_BF1_S 0 - -#define MCP_CONF_REG (DR_REG_MCP_BASE + 0x003c) -/* MCP_CLK_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define MCP_CLK_EN (BIT(31)) -#define MCP_CLK_EN_M (BIT(31)) -#define MCP_CLK_EN_V 0x1 -#define MCP_CLK_EN_S 31 -/* MCP_CRC_OUT_REVERSE_EN : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: */ -#define MCP_CRC_OUT_REVERSE_EN (BIT(11)) -#define MCP_CRC_OUT_REVERSE_EN_M (BIT(11)) -#define MCP_CRC_OUT_REVERSE_EN_V 0x1 -#define MCP_CRC_OUT_REVERSE_EN_S 11 -/* MCP_CRC_BIG_ENDIAN_EN : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: Set this bit to reorder the bit of data which will be send to excute crc.*/ -#define MCP_CRC_BIG_ENDIAN_EN (BIT(10)) -#define MCP_CRC_BIG_ENDIAN_EN_M (BIT(10)) -#define MCP_CRC_BIG_ENDIAN_EN_V 0x1 -#define MCP_CRC_BIG_ENDIAN_EN_S 10 -/* MCP_CRC_CAL_EN : R/W ;bitpos:[9] ;default: 1'b0 ; */ -/*description: Set this bit enable crc calculation function.*/ -#define MCP_CRC_CAL_EN (BIT(9)) -#define MCP_CRC_CAL_EN_M (BIT(9)) -#define MCP_CRC_CAL_EN_V 0x1 -#define MCP_CRC_CAL_EN_S 9 -/* MCP_CRC_CAL_RESET : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: Set this bit to reset crc calculation.*/ -#define MCP_CRC_CAL_RESET (BIT(8)) -#define MCP_CRC_CAL_RESET_M (BIT(8)) -#define MCP_CRC_CAL_RESET_V 0x1 -#define MCP_CRC_CAL_RESET_S 8 -/* MCP_CHECK_OWNER : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: Set this bit to enable owner bit check in descriptor.*/ -#define MCP_CHECK_OWNER (BIT(7)) -#define MCP_CHECK_OWNER_M (BIT(7)) -#define MCP_CHECK_OWNER_V 0x1 -#define MCP_CHECK_OWNER_S 7 -/* MCP_OUT_AUTO_WRBACK : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: this bit is used to write back out descriptor when hardware has - already used this descriptor.*/ -#define MCP_OUT_AUTO_WRBACK (BIT(6)) -#define MCP_OUT_AUTO_WRBACK_M (BIT(6)) -#define MCP_OUT_AUTO_WRBACK_V 0x1 -#define MCP_OUT_AUTO_WRBACK_S 6 -/* MCP_IN_OWNER : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: This is used to configure the owner bit in IN descriptor.*/ -#define MCP_IN_OWNER (BIT(5)) -#define MCP_IN_OWNER_M (BIT(5)) -#define MCP_IN_OWNER_V 0x1 -#define MCP_IN_OWNER_S 5 -/* MCP_OUT_OWNER : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: This is used to configure the owner bit in OUT descriptor. This - is effective only when you set reg_out_auto_wrback.*/ -#define MCP_OUT_OWNER (BIT(4)) -#define MCP_OUT_OWNER_M (BIT(4)) -#define MCP_OUT_OWNER_V 0x1 -#define MCP_OUT_OWNER_S 4 -/* MCP_FIFO_RST : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define MCP_FIFO_RST (BIT(3)) -#define MCP_FIFO_RST_M (BIT(3)) -#define MCP_FIFO_RST_V 0x1 -#define MCP_FIFO_RST_S 3 -/* MCP_CMDFIFO_RST : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: set this bit to reset in_cmdfifo and out_cmdfifo.*/ -#define MCP_CMDFIFO_RST (BIT(2)) -#define MCP_CMDFIFO_RST_M (BIT(2)) -#define MCP_CMDFIFO_RST_V 0x1 -#define MCP_CMDFIFO_RST_S 2 -/* MCP_OUT_RST : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: set this bit to reset out_inf state machine.*/ -#define MCP_OUT_RST (BIT(1)) -#define MCP_OUT_RST_M (BIT(1)) -#define MCP_OUT_RST_V 0x1 -#define MCP_OUT_RST_S 1 -/* MCP_IN_RST : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: set this bit to reset in_inf state machine.*/ -#define MCP_IN_RST (BIT(0)) -#define MCP_IN_RST_M (BIT(0)) -#define MCP_IN_RST_V 0x1 -#define MCP_IN_RST_S 0 - -#define MCP_IN_ST_REG (DR_REG_MCP_BASE + 0x0040) -/* MCP_FIFO_EMPTY : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: */ -#define MCP_FIFO_EMPTY (BIT(23)) -#define MCP_FIFO_EMPTY_M (BIT(23)) -#define MCP_FIFO_EMPTY_V 0x1 -#define MCP_FIFO_EMPTY_S 23 -/* MCP_IN_STATE : RO ;bitpos:[22:20] ;default: 3'b0 ; */ -/*description: */ -#define MCP_IN_STATE 0x00000007 -#define MCP_IN_STATE_M ((MCP_IN_STATE_V)<<(MCP_IN_STATE_S)) -#define MCP_IN_STATE_V 0x7 -#define MCP_IN_STATE_S 20 -/* MCP_IN_DSCR_STATE : RO ;bitpos:[19:18] ;default: 2'b0 ; */ -/*description: */ -#define MCP_IN_DSCR_STATE 0x00000003 -#define MCP_IN_DSCR_STATE_M ((MCP_IN_DSCR_STATE_V)<<(MCP_IN_DSCR_STATE_S)) -#define MCP_IN_DSCR_STATE_V 0x3 -#define MCP_IN_DSCR_STATE_S 18 -/* MCP_INLINK_DSCR_ADDR : RO ;bitpos:[17:0] ;default: 18'b0 ; */ -/*description: */ -#define MCP_INLINK_DSCR_ADDR 0x0003FFFF -#define MCP_INLINK_DSCR_ADDR_M ((MCP_INLINK_DSCR_ADDR_V)<<(MCP_INLINK_DSCR_ADDR_S)) -#define MCP_INLINK_DSCR_ADDR_V 0x3FFFF -#define MCP_INLINK_DSCR_ADDR_S 0 - -#define MCP_OUT_ST_REG (DR_REG_MCP_BASE + 0x0044) -/* MCP_FIFO_FULL : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: */ -#define MCP_FIFO_FULL (BIT(23)) -#define MCP_FIFO_FULL_M (BIT(23)) -#define MCP_FIFO_FULL_V 0x1 -#define MCP_FIFO_FULL_S 23 -/* MCP_OUT_STATE : RO ;bitpos:[22:20] ;default: 3'b0 ; */ -/*description: */ -#define MCP_OUT_STATE 0x00000007 -#define MCP_OUT_STATE_M ((MCP_OUT_STATE_V)<<(MCP_OUT_STATE_S)) -#define MCP_OUT_STATE_V 0x7 -#define MCP_OUT_STATE_S 20 -/* MCP_OUT_DSCR_STATE : RO ;bitpos:[19:18] ;default: 2'b0 ; */ -/*description: */ -#define MCP_OUT_DSCR_STATE 0x00000003 -#define MCP_OUT_DSCR_STATE_M ((MCP_OUT_DSCR_STATE_V)<<(MCP_OUT_DSCR_STATE_S)) -#define MCP_OUT_DSCR_STATE_V 0x3 -#define MCP_OUT_DSCR_STATE_S 18 -/* MCP_OUTLINK_DSCR_ADDR : RO ;bitpos:[17:0] ;default: 18'b0 ; */ -/*description: */ -#define MCP_OUTLINK_DSCR_ADDR 0x0003FFFF -#define MCP_OUTLINK_DSCR_ADDR_M ((MCP_OUTLINK_DSCR_ADDR_V)<<(MCP_OUTLINK_DSCR_ADDR_S)) -#define MCP_OUTLINK_DSCR_ADDR_V 0x3FFFF -#define MCP_OUTLINK_DSCR_ADDR_S 0 - -#define MCP_CRC_OUT_REG (DR_REG_MCP_BASE + 0x0048) -/* MCP_CRC_RESULT : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define MCP_CRC_RESULT 0xFFFFFFFF -#define MCP_CRC_RESULT_M ((MCP_CRC_RESULT_V)<<(MCP_CRC_RESULT_S)) -#define MCP_CRC_RESULT_V 0xFFFFFFFF -#define MCP_CRC_RESULT_S 0 - -#define MCP_DATE_REG (DR_REG_MCP_BASE + 0x00fc) -/* MCP_DMA_DATE : R/W ;bitpos:[31:0] ;default: 32'h18082000 ; */ -/*description: */ -#define MCP_DMA_DATE 0xFFFFFFFF -#define MCP_DMA_DATE_M ((MCP_DMA_DATE_V)<<(MCP_DMA_DATE_S)) -#define MCP_DMA_DATE_V 0xFFFFFFFF -#define MCP_DMA_DATE_S 0 - -#ifdef __cplusplus -} -#endif - - - -#endif /*_SOC_MCP_REG_H_ */ - - diff --git a/components/soc/soc/esp32s2/include/soc/mcp_struct.h b/components/soc/soc/esp32s2/include/soc/mcp_struct.h deleted file mode 100644 index 6648a48c79..0000000000 --- a/components/soc/soc/esp32s2/include/soc/mcp_struct.h +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _SOC_MCP_STRUCT_H_ -#define _SOC_MCP_STRUCT_H_ -#ifdef __cplusplus -extern "C" { -#endif - -typedef volatile struct { - union { - struct { - uint32_t in_done: 1; - uint32_t in_suc_eof: 1; - uint32_t out_done: 1; - uint32_t out_eof: 1; - uint32_t in_dscr_err: 1; - uint32_t out_dscr_err: 1; - uint32_t in_dscr_empty: 1; - uint32_t out_total_eof: 1; - uint32_t crc_done: 1; - uint32_t reserved9: 23; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t in_done: 1; - uint32_t in_suc_eof: 1; - uint32_t out_done: 1; - uint32_t out_eof: 1; - uint32_t in_dscr_err: 1; - uint32_t out_dscr_err: 1; - uint32_t in_dscr_empty: 1; - uint32_t out_total_eof: 1; - uint32_t crc_done: 1; - uint32_t reserved9: 23; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t in_done: 1; - uint32_t in_suc_eof: 1; - uint32_t out_done: 1; - uint32_t out_eof: 1; - uint32_t in_dscr_err: 1; - uint32_t out_dscr_err: 1; - uint32_t in_dscr_empty: 1; - uint32_t out_total_eof: 1; - uint32_t crc_done: 1; - uint32_t reserved9: 23; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t in_done: 1; - uint32_t in_suc_eof: 1; - uint32_t out_done: 1; - uint32_t out_eof: 1; - uint32_t in_dscr_err: 1; - uint32_t out_dscr_err: 1; - uint32_t in_dscr_empty: 1; - uint32_t out_total_eof: 1; - uint32_t crc_done: 1; - uint32_t reserved9: 23; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t addr: 20; - uint32_t reserved20: 8; - uint32_t stop: 1; - uint32_t start: 1; - uint32_t restart: 1; - uint32_t park: 1; - }; - uint32_t val; - } out_link; - union { - struct { - uint32_t addr: 20; - uint32_t reserved20: 8; - uint32_t stop: 1; - uint32_t start: 1; - uint32_t restart: 1; - uint32_t park: 1; - }; - uint32_t val; - } in_link; - uint32_t out_eof_des_addr; /**/ - uint32_t in_eof_des_addr; /**/ - uint32_t out_eof_bfr_des_addr; /**/ - uint32_t inlink_dscr; /**/ - uint32_t inlink_dscr_bf0; /**/ - uint32_t inlink_dscr_bf1; /**/ - uint32_t outlink_dscr; /**/ - uint32_t outlink_dscr_bf0; /**/ - uint32_t outlink_dscr_bf1; /**/ - union { - struct { - uint32_t in_rst: 1; /*set this bit to reset in_inf state machine.*/ - uint32_t out_rst: 1; /*set this bit to reset out_inf state machine.*/ - uint32_t cmdfifo_rst: 1; /*set this bit to reset in_cmdfifo and out_cmdfifo.*/ - uint32_t fifo_rst: 1; - uint32_t out_owner: 1; /*This is used to configure the owner bit in OUT descriptor. This is effective only when you set reg_out_auto_wrback.*/ - uint32_t in_owner: 1; /*This is used to configure the owner bit in IN descriptor.*/ - uint32_t out_auto_wrback: 1; /*this bit is used to write back out descriptor when hardware has already used this descriptor.*/ - uint32_t check_owner: 1; /*Set this bit to enable owner bit check in descriptor.*/ - uint32_t crc_cal_reset: 1; /*Set this bit to reset crc calculation.*/ - uint32_t crc_cal_en: 1; /*Set this bit enable crc calculation function.*/ - uint32_t crc_big_endian_en: 1; /*Set this bit to reorder the bit of data which will be send to excute crc.*/ - uint32_t crc_out_reverse_en: 1; - uint32_t reserved12: 19; - uint32_t clk_en: 1; - }; - uint32_t val; - } conf; - union { - struct { - uint32_t dscr_addr: 18; - uint32_t dscr_state: 2; - uint32_t state: 3; - uint32_t fifo_empty: 1; - uint32_t reserved24: 8; - }; - uint32_t val; - } in_st; - union { - struct { - uint32_t dscr_addr: 18; - uint32_t dscr_state: 2; - uint32_t state: 3; - uint32_t fifo_full: 1; - uint32_t reserved24: 8; - }; - uint32_t val; - } out_st; - uint32_t crc_out; /**/ - uint32_t reserved_4c; - uint32_t reserved_50; - uint32_t reserved_54; - uint32_t reserved_58; - uint32_t reserved_5c; - uint32_t reserved_60; - uint32_t reserved_64; - uint32_t reserved_68; - uint32_t reserved_6c; - uint32_t reserved_70; - uint32_t reserved_74; - uint32_t reserved_78; - uint32_t reserved_7c; - uint32_t reserved_80; - uint32_t reserved_84; - uint32_t reserved_88; - uint32_t reserved_8c; - uint32_t reserved_90; - uint32_t reserved_94; - uint32_t reserved_98; - uint32_t reserved_9c; - uint32_t reserved_a0; - uint32_t reserved_a4; - uint32_t reserved_a8; - uint32_t reserved_ac; - uint32_t reserved_b0; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t reserved_cc; - uint32_t reserved_d0; - uint32_t reserved_d4; - uint32_t reserved_d8; - uint32_t reserved_dc; - uint32_t reserved_e0; - uint32_t reserved_e4; - uint32_t reserved_e8; - uint32_t reserved_ec; - uint32_t reserved_f0; - uint32_t reserved_f4; - uint32_t reserved_f8; - uint32_t date; /**/ -} mcp_dev_t; -extern mcp_dev_t MCP; -#ifdef __cplusplus -} -#endif - -#endif /* _SOC_MCP_STRUCT_H_ */ diff --git a/components/soc/src/esp32s2/CMakeLists.txt b/components/soc/src/esp32s2/CMakeLists.txt index 55965da50b..62ccea6019 100644 --- a/components/soc/src/esp32s2/CMakeLists.txt +++ b/components/soc/src/esp32s2/CMakeLists.txt @@ -1,5 +1,6 @@ set(srcs "adc_hal.c" "brownout_hal.c" + "cp_dma_hal.c" "rtc_clk.c" "rtc_clk_init.c" "rtc_init.c" diff --git a/components/soc/src/esp32s2/cp_dma_hal.c b/components/soc/src/esp32s2/cp_dma_hal.c new file mode 100644 index 0000000000..8d825fecf0 --- /dev/null +++ b/components/soc/src/esp32s2/cp_dma_hal.c @@ -0,0 +1,218 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "hal/cp_dma_hal.h" +#include "hal/cp_dma_ll.h" +#include "soc/cp_dma_caps.h" + +#define MCP_DESCRIPTOR_BUFFER_OWNER_DMA (1) +#define MCP_DESCRIPTOR_BUFFER_OWNER_CPU (0) + +void cp_dma_hal_init(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *tx_descriptors[], uint32_t tx_desc_num, cp_dma_descriptor_t *rx_descriptors[], uint32_t rx_desc_num) +{ + hal->dev = &CP_DMA; + cp_dma_ll_enable_clock(hal->dev, true); + cp_dma_ll_reset_in_link(hal->dev); + cp_dma_ll_reset_out_link(hal->dev); + cp_dma_ll_reset_cmd_fifo(hal->dev); + cp_dma_ll_reset_fifo(hal->dev); + cp_dma_ll_enable_intr(hal->dev, UINT32_MAX, false); + cp_dma_ll_clear_intr_status(hal->dev, UINT32_MAX); + cp_dma_ll_enable_owner_check(hal->dev, true); + + // circle TX descriptors + for (int i = 0; i < tx_desc_num; i++) { + tx_descriptors[i]->dw0.owner = MCP_DESCRIPTOR_BUFFER_OWNER_CPU; + tx_descriptors[i]->next = tx_descriptors[i + 1]; + } + tx_descriptors[tx_desc_num - 1]->next = tx_descriptors[0]; + + // circle RX descriptors + for (int i = 0; i < rx_desc_num; i++) { + rx_descriptors[i]->dw0.owner = MCP_DESCRIPTOR_BUFFER_OWNER_CPU; + rx_descriptors[i]->next = rx_descriptors[i + 1]; + } + rx_descriptors[rx_desc_num - 1]->next = rx_descriptors[0]; + + // set the start of each descriptor chain + hal->tx_desc = tx_descriptors[0]; + hal->rx_desc = rx_descriptors[0]; + + /* set base address of the first descriptor */ + cp_dma_ll_tx_set_descriptor_base_addr(hal->dev, (uint32_t)hal->tx_desc); + cp_dma_ll_rx_set_descriptor_base_addr(hal->dev, (uint32_t)hal->rx_desc); + + hal->next_rx_desc_to_check = rx_descriptors[0]; +} + +void cp_dma_hal_deinit(cp_dma_hal_context_t *hal) +{ + cp_dma_ll_enable_clock(hal->dev, false); + hal->dev = NULL; + hal->tx_desc = NULL; + hal->rx_desc = NULL; +} + +void cp_dma_hal_start(cp_dma_hal_context_t *hal) +{ + // enable DMA engine + cp_dma_ll_start_rx(hal->dev, true); + cp_dma_ll_start_tx(hal->dev, true); + // enable RX EOF interrupt + cp_dma_ll_enable_intr(hal->dev, CP_DMA_LL_EVENT_RX_EOF, true); +} + +void cp_dma_hal_stop(cp_dma_hal_context_t *hal) +{ + // disable interrupt + cp_dma_ll_enable_intr(hal->dev, CP_DMA_LL_EVENT_RX_EOF, false); + cp_dma_ll_enable_intr(hal->dev, CP_DMA_LL_EVENT_TX_EOF, false); + + // disable DMA + cp_dma_ll_start_rx(hal->dev, false); + cp_dma_ll_start_tx(hal->dev, false); +} + +uint32_t cp_dma_hal_get_intr_status(cp_dma_hal_context_t *hal) +{ + return cp_dma_ll_get_intr_status(hal->dev); +} + +void cp_dma_hal_clear_intr_status(cp_dma_hal_context_t *hal, uint32_t mask) +{ + cp_dma_ll_clear_intr_status(hal->dev, mask); +} + +int cp_dma_hal_prepare_transmit(cp_dma_hal_context_t *hal, void *buffer, size_t len, cp_dma_descriptor_t **start_desc, cp_dma_descriptor_t **end_desc) +{ + uint32_t prepared_length = 0; + uint8_t *buf = (uint8_t *)buffer; + cp_dma_descriptor_t *desc = hal->tx_desc; // descriptor iterator + cp_dma_descriptor_t *start = desc; + cp_dma_descriptor_t *end = desc; + + while (len > SOC_CP_DMA_MAX_BUFFER_SIZE) { + if (desc->dw0.owner != MCP_DESCRIPTOR_BUFFER_OWNER_DMA) { + desc->dw0.eof = 0; // not the end of the transaction + desc->dw0.size = SOC_CP_DMA_MAX_BUFFER_SIZE; + desc->dw0.length = SOC_CP_DMA_MAX_BUFFER_SIZE; + desc->buffer = &buf[prepared_length]; + desc = desc->next; // move to next descriptor + prepared_length += SOC_CP_DMA_MAX_BUFFER_SIZE; + len -= SOC_CP_DMA_MAX_BUFFER_SIZE; + } else { + // out of TX descriptors + goto _exit; + } + } + if (len) { + if (desc->dw0.owner != MCP_DESCRIPTOR_BUFFER_OWNER_DMA) { + end = desc; // the last descriptor used + desc->dw0.eof = 1; // end of the transaction + desc->dw0.size = len; + desc->dw0.length = len; + desc->buffer = &buf[prepared_length]; + desc = desc->next; // move to next descriptor + prepared_length += len; + } else { + // out of TX descriptors + goto _exit; + } + } + + *start_desc = start; + *end_desc = end; +_exit: + return prepared_length; +} + +int cp_dma_hal_prepare_receive(cp_dma_hal_context_t *hal, void *buffer, size_t size, cp_dma_descriptor_t **start_desc, cp_dma_descriptor_t **end_desc) +{ + uint32_t prepared_length = 0; + uint8_t *buf = (uint8_t *)buffer; + cp_dma_descriptor_t *desc = hal->rx_desc; // descriptor iterator + cp_dma_descriptor_t *start = desc; + cp_dma_descriptor_t *end = desc; + + while (size > SOC_CP_DMA_MAX_BUFFER_SIZE) { + if (desc->dw0.owner != MCP_DESCRIPTOR_BUFFER_OWNER_DMA) { + desc->dw0.size = SOC_CP_DMA_MAX_BUFFER_SIZE; + desc->buffer = &buf[prepared_length]; + desc = desc->next; // move to next descriptor + prepared_length += SOC_CP_DMA_MAX_BUFFER_SIZE; + size -= SOC_CP_DMA_MAX_BUFFER_SIZE; + } else { + // out of TX descriptors + goto _exit; + } + } + if (size) { + if (desc->dw0.owner != MCP_DESCRIPTOR_BUFFER_OWNER_DMA) { + end = desc; // the last descriptor used + desc->dw0.size = size; + desc->buffer = &buf[prepared_length]; + desc = desc->next; // move to next descriptor + prepared_length += size; + } else { + // out of TX descriptors + goto _exit; + } + } + + *start_desc = start; + *end_desc = end; +_exit: + return prepared_length; +} + +void cp_dma_hal_restart_tx(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *start_desc, cp_dma_descriptor_t *end_desc) +{ + // Give descriptor owner to DMA + cp_dma_descriptor_t *desc = start_desc; + while (desc != end_desc) { + desc->dw0.owner = MCP_DESCRIPTOR_BUFFER_OWNER_DMA; + desc = desc->next; + } + desc->dw0.owner = MCP_DESCRIPTOR_BUFFER_OWNER_DMA; + hal->tx_desc = end_desc->next; // update the next available descriptor in HAL + cp_dma_ll_restart_tx(hal->dev); +} + +void cp_dma_hal_restart_rx(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *start_desc, cp_dma_descriptor_t *end_desc) +{ + // Give descriptor owner to DMA + cp_dma_descriptor_t *desc = start_desc; + while (desc != end_desc) { + desc->dw0.owner = MCP_DESCRIPTOR_BUFFER_OWNER_DMA; + desc = desc->next; + } + desc->dw0.owner = MCP_DESCRIPTOR_BUFFER_OWNER_DMA; + hal->rx_desc = end_desc->next; // update the next available descriptor in HAL + cp_dma_ll_restart_rx(hal->dev); +} + +bool cp_dma_hal_get_next_rx_descriptor(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *eof_desc, cp_dma_descriptor_t **next_desc) +{ + cp_dma_descriptor_t *next = hal->next_rx_desc_to_check; + // additional check, to avoid potential interrupt got triggered by mistake + if (next->dw0.owner == MCP_DESCRIPTOR_BUFFER_OWNER_CPU) { + hal->next_rx_desc_to_check = hal->next_rx_desc_to_check->next; + *next_desc = next; + // return if we need to continue + return eof_desc == next ? false : true; + } else { + *next_desc = NULL; + return false; + } +} diff --git a/components/soc/src/esp32s2/include/hal/cp_dma_hal.h b/components/soc/src/esp32s2/include/hal/cp_dma_hal.h new file mode 100644 index 0000000000..bec3dcfcb4 --- /dev/null +++ b/components/soc/src/esp32s2/include/hal/cp_dma_hal.h @@ -0,0 +1,155 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/******************************************************************************* + * NOTICE + * The HAL is not public api, don't use in application code. + * See readme.md in soc/README.md + ******************************************************************************/ + +// CP DMA HAL usages: +// 1. Initialize HAL layer by cp_dma_hal_init, pass in the allocated descriptors for TX and RX +// 2. Enable DMA and interrupt by cp_dma_hal_start +// 3. Prepare descriptors used for TX and RX +// 4. Restart the DMA engine in case it's not in working + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "esp_attr.h" +#include "soc/cp_dma_struct.h" + +typedef struct cp_dma_descriptor { + struct { + uint32_t size : 12; /*!< buffer size */ + uint32_t length : 12; /*!< specify number of valid bytes in the buffer */ + uint32_t reversed24_27 : 4; /*!< reserved */ + uint32_t err : 1; /*!< specify whether a received buffer contains error */ + uint32_t reserved29 : 1; /*!< reserved */ + uint32_t eof : 1; /*!< if this dma link is the last one, you shoule set this bit 1 */ + uint32_t owner : 1; /*!< specify the owner of buffer that this descriptor points to, 1=DMA, 0=CPU. DMA will clear it after use. */ + } dw0; /*!< descriptor word 0 */ + void *buffer; /*!< pointer to the buffer */ + struct cp_dma_descriptor *next; /*!< pointer to the next descriptor or NULL if this descriptor is the last one */ +} cp_dma_descriptor_t; + +_Static_assert(sizeof(cp_dma_descriptor_t) == 12, "cp_dma_descriptor_t should occupy 12 bytes in memory"); + +/** + * @brief HAL context + * + * @note `tx_desc` and `rx_desc` are internal state of the HAL, will be modified during the operations. + * Upper layer of HAL should keep the buffer address themselves and make sure the buffers are freed when the HAL is no longer used. + * + */ +typedef struct { + cp_dma_dev_t *dev; + cp_dma_descriptor_t *tx_desc; + cp_dma_descriptor_t *rx_desc; + cp_dma_descriptor_t *next_rx_desc_to_check; +} cp_dma_hal_context_t; + +/** + * @brief Initialize HAL layer context + * + * @param hal HAL layer context, memroy should be allocated at driver layer + * @param tx_descriptors out link descriptor pool + * @param tx_desc_num number of out link descriptors + * @param rx_descriptors in line descriptor pool + * @param rx_desc_num number of in link descriptors + */ +void cp_dma_hal_init(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *tx_descriptors[], uint32_t tx_desc_num, cp_dma_descriptor_t *rx_descriptors[], uint32_t rx_desc_num); + +/** + * @brief Deinitialize HAL layer context + */ +void cp_dma_hal_deinit(cp_dma_hal_context_t *hal); + +/** + * @brief Start mem2mem DMA state machine + */ +void cp_dma_hal_start(cp_dma_hal_context_t *hal); + +/** + * @brief Stop mem2mem DMA state machine + */ +void cp_dma_hal_stop(cp_dma_hal_context_t *hal); + +/** + * @brief Get interrupt status word + * + * @return uint32_t Interrupt status + */ +uint32_t cp_dma_hal_get_intr_status(cp_dma_hal_context_t *hal) IRAM_ATTR; + +/** + * @brief Clear interrupt mask + * + * @param mask interrupt mask + */ +void cp_dma_hal_clear_intr_status(cp_dma_hal_context_t *hal, uint32_t mask) IRAM_ATTR; + +/** + * @brief Get next RX descriptor that needs recycling + * + * @param eof_desc EOF descriptor for this iteration + * @param[out] next_desc Next descriptor needs to check + * @return Whether to continue + */ +bool cp_dma_hal_get_next_rx_descriptor(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *eof_desc, cp_dma_descriptor_t **next_desc); + +/** + * @brief Prepare buffer to be transmitted + * + * @param hal HAL layer context + * @param buffer buffer address + * @param len buffer size + * @param[out] start_desc The first descriptor that carry the TX transaction + * @param[out] end_desc The last descriptor that carry the TX transaction + * @return Number of bytes has been parepared to transmit + */ +int cp_dma_hal_prepare_transmit(cp_dma_hal_context_t *hal, void *buffer, size_t len, cp_dma_descriptor_t **start_desc, cp_dma_descriptor_t **end_desc); + +/** + * @brief Prepare buffer to receive + * + * @param hal HAL layer context + * @param buffer buffer address + * @param size buffer size + * @param[out] start_desc The first descriptor that carries the RX transaction + * @param[out] end_desc The last descriptor that carries the RX transaction + * @return Number of bytes has been parepared to receive + */ +int cp_dma_hal_prepare_receive(cp_dma_hal_context_t *hal, void *buffer, size_t size, cp_dma_descriptor_t **start_desc, cp_dma_descriptor_t **end_desc); + +/**@{*/ +/** + * @brief Give the owner of descriptors between [start_desc, end_desc] to DMA, and restart DMA HW engine + * + * @param hal HAL layer context + * @param start_desc The first descriptor that carries one transaction + * @param end_desc The last descriptor that carries one transaction + */ +void cp_dma_hal_restart_tx(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *start_desc, cp_dma_descriptor_t *end_desc); +void cp_dma_hal_restart_rx(cp_dma_hal_context_t *hal, cp_dma_descriptor_t *start_desc, cp_dma_descriptor_t *end_desc); +/**@}*/ + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/src/esp32s2/include/hal/cp_dma_ll.h b/components/soc/src/esp32s2/include/hal/cp_dma_ll.h new file mode 100644 index 0000000000..1c04315e5b --- /dev/null +++ b/components/soc/src/esp32s2/include/hal/cp_dma_ll.h @@ -0,0 +1,159 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "soc/cp_dma_struct.h" + +#define CP_DMA_LL_EVENT_RX_DONE (1 << 0) +#define CP_DMA_LL_EVENT_RX_EOF (1 << 1) +#define CP_DMA_LL_EVENT_TX_DONE (1 << 2) +#define CP_DMA_LL_EVENT_TX_EOF (1 << 3) +#define CP_DMA_LL_EVENT_RX_DESC_ERR (1 << 4) +#define CP_DMA_LL_EVENT_TX_DESC_ERR (1 << 5) +#define CP_DMA_LL_EVENT_RX_DESC_EMPTY (1 << 6) +#define CP_DMA_LL_EVENT_TX_TOTAL_EOF (1 << 7) +#define CP_DMA_LL_EVENT_ALL (0xFF) + +/** + * Copy DMA firstly reads data to be transferred from internal RAM, + * stores the data into DMA FIFO via an outlink, + * and then writes the data to the destination internal RAM via an inlink. + */ + +static inline void cp_dma_ll_reset_in_link(cp_dma_dev_t *dev) +{ + dev->dma_conf.dma_in_rst = 1; + dev->dma_conf.dma_in_rst = 0; +} + +static inline void cp_dma_ll_reset_out_link(cp_dma_dev_t *dev) +{ + dev->dma_conf.dma_out_rst = 1; + dev->dma_conf.dma_out_rst = 0; +} + +static inline void cp_dma_ll_reset_fifo(cp_dma_dev_t *dev) +{ + dev->dma_conf.dma_fifo_rst = 1; + dev->dma_conf.dma_fifo_rst = 0; +} + +static inline void cp_dma_ll_reset_cmd_fifo(cp_dma_dev_t *dev) +{ + dev->dma_conf.dma_cmdfifo_rst = 1; + dev->dma_conf.dma_cmdfifo_rst = 0; +} + +static inline void cp_dma_ll_enable_owner_check(cp_dma_dev_t *dev, bool enable) +{ + dev->dma_conf.dma_check_owner = enable; + dev->dma_conf.dma_out_auto_wrback = 1; + dev->dma_conf.dma_out_owner = 0; + dev->dma_conf.dma_in_owner = 0; +} + +static inline void cp_dma_ll_enable_clock(cp_dma_dev_t *dev, bool enable) +{ + dev->dma_conf.dma_clk_en = enable; +} + +static inline void cp_dma_ll_enable_intr(cp_dma_dev_t *dev, uint32_t mask, bool enable) +{ + if (enable) { + dev->dma_int_ena.val |= mask; + } else { + dev->dma_int_ena.val &= ~mask; + } +} + +static inline __attribute__((always_inline)) uint32_t cp_dma_ll_get_intr_status(cp_dma_dev_t *dev) +{ + return dev->dma_int_st.val; +} + +static inline __attribute__((always_inline)) void cp_dma_ll_clear_intr_status(cp_dma_dev_t *dev, uint32_t mask) +{ + dev->dma_int_clr.val = mask; +} + +static inline void cp_dma_ll_tx_set_descriptor_base_addr(cp_dma_dev_t *dev, uint32_t address) +{ + dev->dma_out_link.dma_outlink_addr = address; +} + +static inline void cp_dma_ll_rx_set_descriptor_base_addr(cp_dma_dev_t *dev, uint32_t address) +{ + dev->dma_in_link.dma_inlink_addr = address; +} + +static inline void cp_dma_ll_start_tx(cp_dma_dev_t *dev, bool enable) +{ + if (enable) { + dev->dma_out_link.dma_outlink_start = 1; // cleared automatically by HW + } else { + dev->dma_out_link.dma_outlink_stop = 1; // cleared automatically by HW + } +} + +static inline void cp_dma_ll_start_rx(cp_dma_dev_t *dev, bool enable) +{ + if (enable) { + dev->dma_in_link.dma_inlink_start = 1; // cleared automatically by HW + } else { + dev->dma_in_link.dma_inlink_stop = 1; // cleared automatically by HW + } +} + +static inline void cp_dma_ll_restart_tx(cp_dma_dev_t *dev) +{ + dev->dma_out_link.dma_outlink_restart = 1; // cleared automatically by HW +} + +static inline void cp_dma_ll_restart_rx(cp_dma_dev_t *dev) +{ + dev->dma_in_link.dma_inlink_restart = 1; // cleared automatically by HW +} + +// get the address of last rx descriptor +static inline uint32_t cp_dma_ll_get_rx_eof_descriptor_address(cp_dma_dev_t *dev) +{ + return dev->dma_in_eof_des_addr.dma_in_suc_eof_des_addr; +} + +// get the address of last tx descriptor +static inline uint32_t cp_dma_ll_get_tx_eof_descriptor_address(cp_dma_dev_t *dev) +{ + return dev->dma_out_eof_des_addr.dma_out_eof_des_addr; +} + +static inline uint32_t cp_dma_ll_get_tx_status(cp_dma_dev_t *dev) +{ + return dev->dma_out_st.val; +} + +static inline uint32_t cp_dma_ll_get_rx_status(cp_dma_dev_t *dev) +{ + return dev->dma_in_st.val; +} + +#ifdef __cplusplus +} +#endif diff --git a/docs/Doxyfile b/docs/Doxyfile index 97cf26f1cd..4b6388c150 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -110,6 +110,7 @@ INPUT = \ $(IDF_PATH)/components/driver/include/driver/adc_common.h \ $(IDF_PATH)/components/driver/include/driver/uart.h \ $(IDF_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \ + $(IDF_PATH)/components/esp32s2/include/cp_dma.h \ $(IDF_PATH)/components/esp32s2/include/esp_hmac.h \ $(IDF_PATH)/components/esp32s2/include/esp_ds.h \ $(IDF_PATH)/components/soc/include/hal/rmt_types.h \ diff --git a/docs/conf_common.py b/docs/conf_common.py index 96bc3b352b..358959124e 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -166,8 +166,8 @@ ESP32S2_DOCS = ['esp32s2.rst', 'api-reference/peripherals/hmac.rst', 'api-reference/peripherals/ds.rst', 'api-reference/peripherals/spi_slave_hd.rst', - 'api-reference/peripherals/temp_sensor.rst' - ''] + 'api-reference/peripherals/temp_sensor.rst', + 'api-reference/system/async_memcpy.rst'] # format: {tag needed to include: documents to included}, tags are parsed from sdkconfig and peripheral_caps.h headers conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS, diff --git a/docs/en/api-reference/system/async_memcpy.rst b/docs/en/api-reference/system/async_memcpy.rst new file mode 100644 index 0000000000..1b209473b9 --- /dev/null +++ b/docs/en/api-reference/system/async_memcpy.rst @@ -0,0 +1,80 @@ +The Async memcpy API +==================== + +Overview +-------- + +ESP32-S2 features a dedicated DMA (a.k.a `CP_DMA`) which aims to offload internal memory copy operations from the CPU. When using 160MHz CPU, copying 4KB of data via memcpy() takes 14us, copying via cp_dma_memcpy can complete in 7us. + +The async memcpy API wraps all DMA configurations and operations, the signature of :cpp:func:`cp_dma_memcpy` is almost the same to the standard libc one. + +Thanks to the benefit of the DMA, we don't have to wait for each memory copy to be done before we issue another memcpy request. By providing a user defined callback, it's still possible to know when memcpy has finished. + +.. note:: + Memory copy with external PSRAM is not supported on ESP32-S2, :cpp:func:`cp_dma_memcpy` will abort returning an error if memory address does not reside in SRAM. + +Configure and Install driver +---------------------------- + +:cpp:func:`cp_dma_driver_install` is used to install `CP_DMA` driver with user's configuration. Please note that async memcpy has to be called with the handle returned by :cpp:func:`cp_dma_driver_install`. + +Driver configuration is described in :cpp:type:`cp_dma_config_t`: +:cpp:member:`max_out_stream` and :cpp:member:`max_in_stream`: You can increase/decrease the number if you want to support more/less memcpy operations to be pending in background. +:cpp:member:`flags`: Control special behavior of `CP_DMA`. If `CP_DMA_FLAGS_WORK_WITH_CACHE_DISABLE` is set in the flags, then `CP_DMA` driver can work even when cache is disabled. Please note, it would increase the consumption of SRAM. + +:c:macro:`CP_DMA_DEFAULT_CONFIG` provides a default configuration, which specifies the maximum data streams used by underlay DMA engine to 8. + +.. highlight:: c + +:: + + cp_dma_config_t config = CP_DMA_DEFAULT_CONFIG(); + config.max_in_stream = 4; // update the maximum data stream supported by DMA + config.max_out_stream = 4; + config.flags = CP_DMA_FLAGS_WORK_WITH_CACHE_DISABLE; // the driver can work even when cache is disabled + cp_dma_driver_t driver = NULL; + ESP_ERROR_CHECK(cp_dma_driver_install(&config, &driver)); // install driver, return driver handle + +Send memory copy request +------------------------ + +:cpp:func:`cp_dma_memcpy` is the API to send memory copy request to DMA engine. It must be called after `CP_DMA` driver is installed successfully. This API is thread safe, so it can be called from different tasks. + +Different from the libc version of `memcpy`, user can pass a callback to :cpp:func:`cp_dma_memcpy` when it's necessary. The callback is executed in the ISR context, make sure you won't violate the the restriction applied to ISR handler. + +Besides that, the callback function should reside in IRAM space by applying `IRAM_ATTR` attribute. The prototype of the callback function is :cpp:type:`cp_dma_isr_cb_t`, please note that, the callback function should return true if there's a high priority task woken up due to any operations done in the callback. + +.. highlight:: c + +:: + + Semphr_Handle_t semphr; //already initialized in somewhere + + // Callback implementation, running in ISR context + static IRAM_ATTR bool memcpy_cb(cp_dma_driver_t drv_hdl, cp_dma_event_t *event, void *cb_args) + { + BaseType_t high_task_wakeup = pdFALSE; + switch (event->id) { + case CP_DMA_EVENT_M2M_DONE: + SemphrGiveInISR(semphr, &high_task_wakeup); // high_task_wakeup set to pdTRUE if some high priority task unblocked + break; + default: + break; + } + return high_task_wakeup == pdTRUE; + } + + // Called from user's context + ESP_ERROR_CHECK(cp_dma_memcpy(driver, to, from, copy_len, memcpy_cb, cb_args)); + //Do something else here + SemphrTake(semphr, ...); //wait until the buffer copy is done + +Uninstall driver (optional) +--------------------------- + +:cpp:func:`cp_dma_driver_uninstall` is used to uninstall `CP_DMA` driver. It's not necessary to uninstall the driver after each memcpy operation. If your application won't use `CP_DMA` anymore, then this API can recycle the memory used by driver. + +API Reference +------------- + +.. include-build-file:: inc/cp_dma.inc diff --git a/docs/en/api-reference/system/index.rst b/docs/en/api-reference/system/index.rst index 7fd3ea5f16..98c234b4a0 100644 --- a/docs/en/api-reference/system/index.rst +++ b/docs/en/api-reference/system/index.rst @@ -6,6 +6,7 @@ System API App image format Application Level Tracing + :esp32s2: Async Memory Copy Console Component eFuse Manager Error Codes and Helper Functions diff --git a/docs/zh_CN/api-reference/system/async_memcpy.rst b/docs/zh_CN/api-reference/system/async_memcpy.rst new file mode 100644 index 0000000000..874bf78c2c --- /dev/null +++ b/docs/zh_CN/api-reference/system/async_memcpy.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/system/async_memcpy.rst \ No newline at end of file