Skip to content

Commit

Permalink
feat(bitscrambler): add driver support on esp32c5
Browse files Browse the repository at this point in the history
  • Loading branch information
suda-morris committed Jan 23, 2025
1 parent 706b5e4 commit 21a8c22
Show file tree
Hide file tree
Showing 18 changed files with 684 additions and 46 deletions.
6 changes: 4 additions & 2 deletions components/esp_driver_bitscrambler/src/bitscrambler.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ static void enable_clocks(bitscrambler_t *bs)
if (ref_count == 0) { //we're the first to enable the BitScrambler module
bitscrambler_ll_set_bus_clock_sys_enable(1);
bitscrambler_ll_reset_sys();
bitscrambler_ll_mem_power_by_pmu();
}
if (bs->cfg.dir == BITSCRAMBLER_DIR_RX || bs->loopback) {
bitscrambler_ll_set_bus_clock_rx_enable(1);
Expand All @@ -123,6 +124,7 @@ static void disable_clocks(bitscrambler_t *bs)
}
if (ref_count == 0) { //we're the last to disable the BitScrambler module
bitscrambler_ll_set_bus_clock_sys_enable(0);
bitscrambler_ll_mem_force_power_off();
}
}
}
Expand Down Expand Up @@ -221,7 +223,7 @@ esp_err_t bitscrambler_load_program(bitscrambler_handle_t bs, const void *progra

//Set options from header
bitscrambler_ll_set_lut_width(bs->hw, bs->cfg.dir, hdr.lut_width);
bitscrambler_ll_set_prefetch_mode(bs->hw, bs->cfg.dir, hdr.prefetch ? BITSCRAMBLER_PREFETCH_ENABLED : BITSCRAMBLER_PREFETCH_DISABLED);
bitscrambler_ll_enable_prefetch_on_reset(bs->hw, bs->cfg.dir, hdr.prefetch);
bitscrambler_ll_set_eof_mode(bs->hw, bs->cfg.dir, hdr.eof_on);
bitscrambler_ll_set_tailing_bits(bs->hw, bs->cfg.dir, hdr.trailing_bits);
//fixed options
Expand Down Expand Up @@ -298,7 +300,7 @@ esp_err_t bitscrambler_reset(bitscrambler_handle_t handle)
//If the halt bit is set, the Bitscrambler should (eventually) go to idle state. If it
//does not, something got stuck.
int timeout = BITSCRAMBLER_RESET_ITERATIONS;
while ((bitscrambler_ll_current_state(handle->hw, handle->cfg.dir) != BITSCRAMBLER_STATE_IDLE) && timeout != 0) {
while ((bitscrambler_ll_get_current_state(handle->hw, handle->cfg.dir) != BITSCRAMBLER_STATE_IDLE) && timeout != 0) {
timeout--;
}
if (timeout == 0) {
Expand Down
21 changes: 21 additions & 0 deletions components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/gdma_channel.h"
#include "bitscrambler_soc_specific.h"

// Note: these are indexed by the values of the SOC_BITSCRAMBLER_ATTACH_ defines
// in soc/bitscrambler_peri_select.h
// This map is used by the bitscrambler loopback driver only.

const bitscrambler_periph_desc_t g_bitscrambler_periph_desc[] = {
[SOC_BITSCRAMBLER_ATTACH_GPSPI2] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2), SOC_GDMA_TRIG_PERIPH_SPI2_BUS},
[SOC_BITSCRAMBLER_ATTACH_UHCI] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0), SOC_GDMA_TRIG_PERIPH_UHCI0_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S0] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S, 0), SOC_GDMA_TRIG_PERIPH_I2S0_BUS},
[SOC_BITSCRAMBLER_ATTACH_AES] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0), SOC_GDMA_TRIG_PERIPH_AES0_BUS},
[SOC_BITSCRAMBLER_ATTACH_SHA] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA, 0), SOC_GDMA_TRIG_PERIPH_SHA0_BUS},
[SOC_BITSCRAMBLER_ATTACH_ADC] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0), SOC_GDMA_TRIG_PERIPH_ADC0_BUS},
[SOC_BITSCRAMBLER_ATTACH_PARL_IO] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0), SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS},
};
26 changes: 21 additions & 5 deletions components/esp_driver_bitscrambler/src/bitscrambler_loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
#include "esp_private/gdma_link.h"
#include "esp_private/bitscrambler.h"
#include "hal/dma_types.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "bitscrambler_private.h"
#include "bitscrambler_soc_specific.h"
#include "esp_err.h"
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "esp_cache.h"
#include "esp_dma_utils.h"
#include "esp_memory_utils.h"

const static char *TAG = "bs_loop";

Expand Down Expand Up @@ -97,7 +100,11 @@ esp_err_t bitscrambler_loopback_create(bitscrambler_handle_t *handle, int attach
bs->max_transfer_sz_bytes = max_transfer_sz_bytes;
int desc_ct = (max_transfer_sz_bytes + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
int bus = g_bitscrambler_periph_desc[attach_to].bus;
#ifdef SOC_GDMA_BUS_AXI
size_t align = (bus == SOC_GDMA_BUS_AXI) ? 8 : 4;
#else
size_t align = 4;
#endif

// create DMA link list for TX and RX
gdma_link_list_config_t dma_link_cfg = {
Expand Down Expand Up @@ -239,10 +246,16 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s
};
gdma_link_mount_buffers(bsl->rx_link_list, 0, &out_buf_mount_config, 1, NULL);

//Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about
//the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to
//be improved, but potentially needs a fix in esp_cache_msync not to check the size.
esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
int int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
int ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);

bool need_cache_sync = esp_ptr_internal(buffer_in) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0);
if (need_cache_sync) {
//Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about
//the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to
//be improved, but potentially needs a fix in esp_cache_msync not to check the size.
esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
}

gdma_start(bsl->rx_channel, gdma_link_get_head_addr(bsl->rx_link_list));
gdma_start(bsl->tx_channel, gdma_link_get_head_addr(bsl->tx_link_list));
Expand All @@ -258,7 +271,10 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s
ret = ESP_ERR_TIMEOUT;
}

esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
need_cache_sync = esp_ptr_internal(buffer_out) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0);
if (need_cache_sync) {
esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
}

if (bytes_written) {
*bytes_written = gdma_link_count_buffer_size_till_eof(bsl->rx_link_list, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ set(COMPONENTS main)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(test_bitscrambler)

message(STATUS "Checking bitscrambler registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "bitscrambler" "pcr" "hp_sys_clkrst"
HAL_MODULES "bitscrambler")
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| Supported Targets | ESP32-P4 |
| ----------------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-P4 |
| ----------------- | -------- | -------- |
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut


@pytest.mark.esp32p4
@pytest.mark.esp32c5
@pytest.mark.generic
def test_bitscrambler(dut: Dut) -> None:
dut.run_all_single_board_cases()
Loading

0 comments on commit 21a8c22

Please sign in to comment.