Merge branch 'feat/bitscrambler_esp32s31' into 'master'

feat(bitscrambler): add esp32s31 support

Closes IDF-14714

See merge request espressif/esp-idf!47338
This commit is contained in:
morris
2026-04-08 14:07:56 +08:00
22 changed files with 746 additions and 43 deletions
@@ -0,0 +1,6 @@
{
"chipname": "esp32s31",
"extra_instruction_groups": [
"addcti"
]
}
@@ -70,6 +70,7 @@ static bool claim_channel(bitscrambler_direction_t dir)
bitscrambler_ll_reset_sys();
// also power on the memory
bitscrambler_ll_mem_power_by_pmu();
bitscrambler_ll_mem_set_low_power_mode(BITSCRAMBLER_LL_MEM_LP_MODE_SHUT_DOWN);
}
}
if (dir == BITSCRAMBLER_DIR_TX) {
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/gdma_channel.h"
#include "bitscrambler_soc_specific.h"
// Note: these are indexed by the values of the SOC_BITSCRAMBLER_ATTACH_ defines in 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_LCD_CAM] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0), SOC_GDMA_TRIG_PERIPH_LCD0_BUS},
[SOC_BITSCRAMBLER_ATTACH_GPSPI2] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2), SOC_GDMA_TRIG_PERIPH_SPI2_BUS},
[SOC_BITSCRAMBLER_ATTACH_GPSPI3] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 3), SOC_GDMA_TRIG_PERIPH_SPI3_BUS},
[SOC_BITSCRAMBLER_ATTACH_PARL_IO] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0), SOC_GDMA_TRIG_PERIPH_PARLIO0_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_I2S0CH0] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S0CH, 0), SOC_GDMA_TRIG_PERIPH_I2S0CH0_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S0CH1] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S0CH, 1), SOC_GDMA_TRIG_PERIPH_I2S0CH1_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S0CH2] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S0CH, 2), SOC_GDMA_TRIG_PERIPH_I2S0CH2_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S0CH3] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S0CH, 3), SOC_GDMA_TRIG_PERIPH_I2S0CH3_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S1CH0] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S1CH, 0), SOC_GDMA_TRIG_PERIPH_I2S1CH0_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S1CH1] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S1CH, 1), SOC_GDMA_TRIG_PERIPH_I2S1CH1_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S1CH2] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S1CH, 2), SOC_GDMA_TRIG_PERIPH_I2S1CH2_BUS},
[SOC_BITSCRAMBLER_ATTACH_I2S1CH3] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S1CH, 3), SOC_GDMA_TRIG_PERIPH_I2S1CH3_BUS},
[SOC_BITSCRAMBLER_ATTACH_UHCI] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0), SOC_GDMA_TRIG_PERIPH_UHCI0_BUS},
[SOC_BITSCRAMBLER_ATTACH_RMT] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_RMT, 0), SOC_GDMA_TRIG_PERIPH_RMT0_BUS},
};
@@ -1,2 +1,2 @@
| Supported Targets | ESP32-C5 | ESP32-P4 |
| ----------------- | -------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-P4 | ESP32-S31 |
| ----------------- | -------- | -------- | --------- |
@@ -30,7 +30,7 @@ TEST_CASE("Basic BitScrambler I/O", "[bs]")
data_out[i] = 0xFF;
}
bitscrambler_handle_t bs;
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len));
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_GPSPI2, len));
TEST_ESP_OK(bitscrambler_load_program(bs, bitscrambler_program_trivial));
size_t res_len;
TEST_ESP_OK(bitscrambler_loopback_run(bs, data_in, len, data_out, len, &res_len));
@@ -50,7 +50,7 @@ TEST_CASE("Timeout on stuck program", "[bs]")
uint8_t *data_out = heap_caps_aligned_calloc(8, 1, len, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
bitscrambler_handle_t bs;
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len));
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_GPSPI2, len));
TEST_ESP_OK(bitscrambler_load_program(bs, bitscrambler_program_timeout));
esp_err_t err = bitscrambler_loopback_run(bs, data_in, len, data_out, len, NULL);
TEST_ASSERT(err == ESP_ERR_TIMEOUT);
@@ -68,7 +68,7 @@ TEST_CASE("BitScrambler with EOF counted on upstream", "[bs]")
TEST_ASSERT_NOT_NULL(data_out);
bitscrambler_handle_t bs;
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len * 4));
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_GPSPI2, len * 4));
TEST_ESP_OK(bitscrambler_load_program(bs, bitscrambler_program_eof_upstream));
size_t res_len = 0;
TEST_ESP_OK(bitscrambler_loopback_run(bs, data_in, len, data_out, len * 4, &res_len));
@@ -97,7 +97,7 @@ TEST_CASE("BitScrambler with EOF counted on downstream", "[bs]")
TEST_ASSERT_NOT_NULL(data_out);
bitscrambler_handle_t bs;
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len * 4));
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_GPSPI2, len * 4));
TEST_ESP_OK(bitscrambler_load_program(bs, bitscrambler_program_eof_downstream));
size_t res_len = 0;
TEST_ESP_OK(bitscrambler_loopback_run(bs, data_in, len, data_out, len * 4, &res_len));
@@ -126,7 +126,7 @@ TEST_CASE("BitScrambler with LUT32", "[bs]")
TEST_ASSERT_NOT_NULL(data_out);
bitscrambler_handle_t bs;
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len * 4));
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_GPSPI2, len * 4));
TEST_ESP_OK(bitscrambler_load_program(bs, bitscrambler_program_lut32));
size_t res_len = 0;
TEST_ESP_OK(bitscrambler_loopback_run(bs, data_in, len, data_out, len * 4, &res_len));
@@ -165,7 +165,7 @@ TEST_CASE("BitScrambler with loop instruction", "[bs]")
TEST_ASSERT_NOT_NULL(data_out);
bitscrambler_handle_t bs;
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len));
TEST_ESP_OK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_GPSPI2, len));
TEST_ESP_OK(bitscrambler_load_program(bs, bitscrambler_program_loop));
size_t res_len = 0;
TEST_ESP_OK(bitscrambler_loopback_run(bs, data_in, sizeof(data_in) / sizeof(data_in[0]), data_out, len, &res_len));
@@ -3,9 +3,10 @@
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic
@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target'])
@idf_parametrize('target', soc_filtered_targets('SOC_BITSCRAMBLER_SUPPORTED == 1'), indirect=['target'])
def test_bitscrambler(dut: Dut) -> None:
dut.run_all_single_board_cases()
+4 -3
View File
@@ -6,11 +6,12 @@ if(CONFIG_SOC_PARLIO_SUPPORTED)
list(APPEND srcs "src/parlio_common.c"
"src/parlio_tx.c"
"src/parlio_rx.c")
if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED)
list(APPEND srcs "src/parlio_bitscrambler.c")
endif()
endif()
if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED)
list(APPEND srcs "src/parlio_bitscrambler.c")
endif()
if(${target} STREQUAL "linux")
set(priv_requires "")
+3 -3
View File
@@ -10,11 +10,11 @@ if(CONFIG_SOC_RMT_SUPPORTED)
"src/rmt_encoder_simple.c"
"src/rmt_rx.c"
"src/rmt_tx.c")
if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED AND CONFIG_SOC_RMT_SUPPORT_DMA)
list(APPEND srcs "src/rmt_encoder_bs.c")
endif()
endif()
if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED AND CONFIG_SOC_RMT_SUPPORT_DMA)
list(APPEND srcs "src/rmt_encoder_bs.c")
endif()
if(${target} STREQUAL "linux")
set(requires "")
@@ -14,6 +14,7 @@
#include "soc/pcr_struct.h"
#include "soc/hp_system_struct.h"
#include "hal/misc.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -23,6 +24,10 @@ extern "C" {
#define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW
typedef enum {
BITSCRAMBLER_LL_MEM_LP_MODE_SHUT_DOWN, // memory will be powered down during low power stage
} bitscrambler_ll_mem_lp_mode_t;
/**
* @brief Select peripheral BitScrambler is attached to
*
@@ -344,6 +349,16 @@ static inline void bitscrambler_ll_mem_power_by_pmu(void)
PCR.bs_pd_ctrl.bs_mem_force_pu = 0;
}
/**
* @brief Set low power mode for BitScrambler memory (LUT) block
*
* @param mode BitScrambler memory low power mode in low power stage
*/
static inline void bitscrambler_ll_mem_set_low_power_mode(bitscrambler_ll_mem_lp_mode_t mode)
{
HAL_ASSERT(mode == BITSCRAMBLER_LL_MEM_LP_MODE_SHUT_DOWN);
}
/**
* @brief Reset the BitScrambler module
*/
@@ -14,6 +14,7 @@
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/hp_system_struct.h"
#include "hal/misc.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -23,6 +24,10 @@ extern "C" {
#define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW
typedef enum {
BITSCRAMBLER_LL_MEM_LP_MODE_SHUT_DOWN, // memory will be powered down during low power stage
} bitscrambler_ll_mem_lp_mode_t;
/**
* @brief Select peripheral BitScrambler is attached to
*
@@ -362,6 +367,16 @@ static inline void bitscrambler_ll_mem_power_by_pmu(void)
// empty
}
/**
* @brief Set low power mode for BitScrambler memory (LUT) block
*
* @param mode BitScrambler memory low power mode in low power stage
*/
static inline void bitscrambler_ll_mem_set_low_power_mode(bitscrambler_ll_mem_lp_mode_t mode)
{
HAL_ASSERT(mode == BITSCRAMBLER_LL_MEM_LP_MODE_SHUT_DOWN);
}
/**
* @brief Reset the BitScrambler module
*/
@@ -0,0 +1,393 @@
/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <limits.h>
#include <stdlib.h>
#include <stdbool.h>
#include "soc/bitscrambler_struct.h"
#include "hal/bitscrambler_types.h"
#include "soc/hp_system_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "hal/misc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BITSCRAMBLER_LL_GET_HW(num) (((num) == 0) ? (&BITSCRAMBLER) : NULL)
#define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW
typedef enum {
BITSCRAMBLER_LL_MEM_LP_MODE_DEEP_SLEEP, // memory will enter deep sleep during low power stage, keep memory data
BITSCRAMBLER_LL_MEM_LP_MODE_LIGHT_SLEEP, // memory will enter light sleep during low power stage, keep memory data
BITSCRAMBLER_LL_MEM_LP_MODE_SHUT_DOWN, // memory will be powered down during low power stage
BITSCRAMBLER_LL_MEM_LP_MODE_DISABLE, // disable the low power stage
} bitscrambler_ll_mem_lp_mode_t;
/**
* @brief Select peripheral BitScrambler is attached to
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param peri Peripheral to select, should pick the value from bitscrambler_peri_select.h
*/
static inline void bitscrambler_ll_select_peripheral(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int peri)
{
if (dir == BITSCRAMBLER_DIR_TX) {
HP_SYSTEM.bitscrambler_peri_sel.bitscrambler_peri_tx_sel = peri;
} else { // RX
HP_SYSTEM.bitscrambler_peri_sel.bitscrambler_peri_rx_sel = peri;
}
}
/**
* @brief Enable the BitScrambler
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
*/
static inline void bitscrambler_ll_enable(bitscrambler_dev_t *hw, bitscrambler_direction_t dir)
{
hw->ctrl[dir].ena = 1;
}
/**
* @brief Disable the BitScrambler
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
*/
static inline void bitscrambler_ll_disable(bitscrambler_dev_t *hw, bitscrambler_direction_t dir)
{
hw->ctrl[dir].ena = 0;
}
/**
* @brief Write a word to the instruction memory
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param inst_idx Instruction to write to
* @param word_idx Word within the instruction to write to
* @param data Data to write
*/
static inline void bitscrambler_ll_instmem_write(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int inst_idx, int word_idx, uint32_t data)
{
hw->inst_cfg[dir].cfg0.inst_idx = inst_idx;
hw->inst_cfg[dir].cfg0.inst_pos = word_idx;
hw->inst_cfg[dir].cfg1.inst = data;
}
/**
* @brief Read a word from the instruction memory
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param inst_idx Instruction to write to
* @param word_idx Word within the instruction to write to
*
* @returns Word read from instruction memory
*/
static inline uint32_t bitscrambler_ll_instmem_read(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int inst_idx, int word_idx)
{
hw->inst_cfg[dir].cfg0.inst_idx = inst_idx;
hw->inst_cfg[dir].cfg0.inst_pos = word_idx;
return hw->inst_cfg[dir].cfg1.inst;
}
/**
* @brief Write a word to LUT memory
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param word_idx Word within the LUT to write to
* @param data Data to write
*/
static inline void bitscrambler_ll_lutmem_write(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int word_idx, uint32_t data)
{
hw->lut_cfg[dir].cfg0.lut_idx = word_idx;
hw->lut_cfg[dir].cfg1.lut = data;
}
/**
* @brief Set width of LUT memory (as seen by Bitscrambler, not by host)
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param width Width selection
*/
static inline void bitscrambler_ll_set_lut_width(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_lut_width_t width)
{
hw->lut_cfg[dir].cfg0.lut_mode = width;
}
/**
* @brief Get width of LUT memory
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
*/
static inline int bitscrambler_ll_get_lut_width(bitscrambler_dev_t *hw, bitscrambler_direction_t dir)
{
return hw->lut_cfg[dir].cfg0.lut_mode;
}
/**
* @brief Enable loopback mode, where the RX BitScrambler is disabled and the TX BitScrambler loops
* back to the receive DMA path to memory.
*
* @param hw BitScrambler hardware instance address.
* @param en True if loopback mode is enabled; false otherwise
*/
static inline void bitscrambler_ll_enable_loopback(bitscrambler_dev_t *hw, bool en)
{
hw->sys.loop_mode = en ? 1 : 0;
}
/**
* @brief Set condition-checking mode
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param mode Mode to set
*/
static inline void bitscrambler_ll_set_cond_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_cond_mode_t mode)
{
hw->ctrl[dir].cond_mode = mode;
}
/**
* @brief Enable prefetch mode
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param en True to enable prefetch mode; false to disable
*/
static inline void bitscrambler_ll_enable_prefetch_on_reset(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bool en)
{
// 0: means do data prefetch on reset, 1: means no reset prefetch, user has to load the data manually in the assembly code
hw->ctrl[dir].fetch_mode = en ? 0 : 1;
}
/**
* @brief Set EOF mode
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param mode Mode to set
*/
static inline void bitscrambler_ll_set_eof_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_eof_mode_t mode)
{
hw->ctrl[dir].eof_mode = mode;
}
/**
* @brief Set mode of dummy-reading after EOF
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param mode Mode to set
*/
static inline void bitscrambler_ll_set_dummy_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_dummy_mode_t mode)
{
hw->ctrl[dir].rd_dummy = mode;
}
/**
* @brief Set halting mode
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param mode Mode to set
*/
static inline void bitscrambler_ll_set_halt_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_halt_mode_t mode)
{
hw->ctrl[dir].halt_mode = mode;
}
/**
* @brief Set amount of bits to ignore after EOF
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param bitcount Number of bits to ignore
*/
static inline void bitscrambler_ll_set_tailing_bits(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int bitcount)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tail_bits[dir], tailing_bits, bitcount);
}
/**
* @brief Reset BitScrambler FIFO
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
*/
static inline void bitscrambler_ll_reset_fifo(bitscrambler_dev_t *hw, bitscrambler_direction_t dir)
{
hw->ctrl[dir].fifo_rst = 1;
hw->ctrl[dir].fifo_rst = 0;
}
/**
* @brief Clear trace of EOF counts
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
*/
static inline void bitscrambler_ll_clear_eof_trace(bitscrambler_dev_t *hw, bitscrambler_direction_t dir)
{
hw->state[dir].eof_trace_clr = 1;
hw->state[dir].eof_trace_clr = 0;
}
/**
* @brief Set state of BitScrambler
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @param state One of BITSCRAMBLER_SET_STATE_[RUN|HALT|PAUSE]. Note the WAIT state cannot be set externally.
*/
static inline void bitscrambler_ll_set_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_set_state_t state)
{
hw->ctrl[dir].pause = (state == BITSCRAMBLER_SET_STATE_PAUSE) ? 1 : 0;
hw->ctrl[dir].halt = (state == BITSCRAMBLER_SET_STATE_HALT) ? 1 : 0;
}
/**
* @brief Return current BitScrambler state
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
*
* @returns one of BITSCRAMBLER_STATE_* values
*/
static inline bitscrambler_state_t bitscrambler_ll_get_current_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir)
{
if (hw->state[dir].in_idle) {
return BITSCRAMBLER_STATE_IDLE;
}
if (hw->state[dir].in_run) {
return BITSCRAMBLER_STATE_RUN;
}
if (hw->state[dir].in_wait) {
return BITSCRAMBLER_STATE_WAIT;
}
if (hw->state[dir].in_pause) {
return BITSCRAMBLER_STATE_PAUSED;
}
return BITSCRAMBLER_STATE_UNKNOWN;
}
/**
* @brief Return if the bitscrambler FIFO is ready
*
* @note For TX, means the outfifo is not empty, then we can start the peripheral to transmit the data
* For RX, means the infifo is not full, then we can start the peripheral to receive the data
*
* @param hw BitScrambler hardware instance address.
* @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX
* @return true if FIFO is ready, false otherwise
*/
static inline bool bitscrambler_ll_is_fifo_ready(bitscrambler_dev_t *hw, bitscrambler_direction_t dir)
{
return hw->state[dir].fifo_empty;
}
/**
* @brief Enable the bus clock for BitScrambler module
*/
static inline void bitscrambler_ll_set_bus_clock_sys_enable(bool enable)
{
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_sys_clk_en = enable;
}
/**
* @brief Enable the bus clock for RX BitScrambler module
*/
static inline void bitscrambler_ll_set_bus_clock_rx_enable(bool enable)
{
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_rx_sys_clk_en = enable;
}
/**
* @brief Enable the bus clock for TX BitScrambler module
*/
static inline void bitscrambler_ll_set_bus_clock_tx_enable(bool enable)
{
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_tx_sys_clk_en = enable;
}
/**
* @brief Force power on the bitscrambler memory block, regardless of the outside PMU logic
*/
static inline void bitscrambler_ll_mem_force_power_on(void)
{
HP_SYSTEM.sys_bitscram_mem_lp_ctrl.sys_bitscram_mem_lp_force_ctrl = 1;
HP_SYSTEM.sys_bitscram_mem_lp_ctrl.sys_bitscram_mem_lp_en = 0;
}
/**
* @brief Force power off the bitscrambler memory block, regardless of the outside PMU logic
*/
static inline void bitscrambler_ll_mem_force_power_off(void)
{
HP_SYSTEM.sys_bitscram_mem_lp_ctrl.sys_bitscram_mem_lp_force_ctrl = 1;
HP_SYSTEM.sys_bitscram_mem_lp_ctrl.sys_bitscram_mem_lp_en = 1;
}
/**
* @brief Power control the bitscrambler memory block by the outside PMU logic
*/
static inline void bitscrambler_ll_mem_power_by_pmu(void)
{
HP_SYSTEM.sys_bitscram_mem_lp_ctrl.sys_bitscram_mem_lp_force_ctrl = 0;
HP_SYSTEM.sys_bitscram_mem_lp_ctrl.sys_bitscram_mem_lp_en = 0;
}
/**
* @brief Set low power mode for BitScrambler memory (LUT) block
*
* @param mode BitScrambler memory low power mode in low power stage
*/
static inline void bitscrambler_ll_mem_set_low_power_mode(bitscrambler_ll_mem_lp_mode_t mode)
{
HP_SYSTEM.sys_bitscram_mem_lp_ctrl.sys_bitscram_mem_lp_mode = mode;
}
/**
* @brief Reset the BitScrambler module
*/
static inline void bitscrambler_ll_reset_sys(void)
{
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_rst_en = 1;
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_rst_en = 0;
}
/**
* @brief Reset the BitScrambler RX module
*/
static inline void bitscrambler_ll_reset_rx(void)
{
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_rx_rst_en = 1;
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_rx_rst_en = 0;
}
/**
* @brief Reset the BitScrambler TX module
*/
static inline void bitscrambler_ll_reset_tx(void)
{
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_tx_rst_en = 1;
HP_SYS_CLKRST.bitscrambler_ctrl0.reg_bitscrambler_tx_rst_en = 0;
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
/*
* @brief BitScrambler attachment targets
* Note that these are the values written to HP_SYSTEM_BITSCRAMBLER_PERI_SEL_REG.
*/
#define SOC_BITSCRAMBLER_ATTACH_NONE -1
#define SOC_BITSCRAMBLER_ATTACH_LCD_CAM 1
#define SOC_BITSCRAMBLER_ATTACH_GPSPI2 2
#define SOC_BITSCRAMBLER_ATTACH_GPSPI3 3
#define SOC_BITSCRAMBLER_ATTACH_PARL_IO 4
#define SOC_BITSCRAMBLER_ATTACH_AES 5
#define SOC_BITSCRAMBLER_ATTACH_SHA 6
#define SOC_BITSCRAMBLER_ATTACH_ADC 7
#define SOC_BITSCRAMBLER_ATTACH_I2S0CH0 8
#define SOC_BITSCRAMBLER_ATTACH_I2S0CH1 9
#define SOC_BITSCRAMBLER_ATTACH_I2S0CH2 10
#define SOC_BITSCRAMBLER_ATTACH_I2S0CH3 11
#define SOC_BITSCRAMBLER_ATTACH_I2S1CH0 12
#define SOC_BITSCRAMBLER_ATTACH_I2S1CH1 13
#define SOC_BITSCRAMBLER_ATTACH_I2S1CH2 14
#define SOC_BITSCRAMBLER_ATTACH_I2S1CH3 15
#define SOC_BITSCRAMBLER_ATTACH_UHCI 16
#define SOC_BITSCRAMBLER_ATTACH_RMT 17
#define SOC_BITSCRAMBLER_ATTACH_MAX 17
@@ -115,6 +115,10 @@ config SOC_MODEM_CLOCK_SUPPORTED
bool
default y
config SOC_BITSCRAMBLER_SUPPORTED
bool
default y
config SOC_CORDIC_SUPPORTED
bool
default y
@@ -97,7 +97,7 @@
// #define SOC_DEEP_SLEEP_SUPPORTED 1 // TODO: [ESP32S31] IDF-14643
#define SOC_MODEM_CLOCK_SUPPORTED 1
// #define SOC_PM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14648
// #define SOC_BITSCRAMBLER_SUPPORTED 1 // TODO: [ESP32S31] IDF-14714
#define SOC_BITSCRAMBLER_SUPPORTED 1
// #define SOC_SIMD_INSTRUCTION_SUPPORTED 1 // TODO: [ESP32S31] IDF-14661
#define SOC_CORDIC_SUPPORTED 1
#define SOC_REGI2C_SUPPORTED 1
@@ -491,35 +491,240 @@ typedef union {
} bitscrambler_version_reg_t;
///////////////////// TX and RX registers are exactly the same //////////////////////////////////
// The following registers are used for both TX and RX, so we can use the same struct for both //
///////////////////////////////////////////////////////////////////////////////////////////////
/** Type of inst_cfg0 register
* Control and configuration registers
*/
typedef union {
struct {
/** inst_idx : R/W; bitpos: [2:0]; default: 0;
* write this bits to specify the one of 8 instruction
*/
uint32_t inst_idx:3;
/** inst_pos : R/W; bitpos: [6:3]; default: 0;
* write this bits to specify the bit position of 257 bit instruction which in units
* of 32 bits
*/
uint32_t inst_pos:4;
uint32_t reserved_7:25;
};
uint32_t val;
} bitscrambler_inst_cfg0_reg_t;
/** Type of inst_cfg1 register
* Control and configuration registers
*/
typedef union {
struct {
/** inst : R/W; bitpos: [31:0]; default: 4;
* write this bits to update instruction, Read this bits to get instruction.
*/
uint32_t inst:32;
};
uint32_t val;
} bitscrambler_inst_cfg1_reg_t;
/** Type of lut_cfg0 register
* Control and configuration registers
*/
typedef union {
struct {
/** lut_idx : R/W; bitpos: [10:0]; default: 0;
* write this bits to specify the bytes position of LUT RAM based on lut_mode
*/
uint32_t lut_idx:11;
/** lut_mode : R/W; bitpos: [12:11]; default: 0;
* write this bits to specify the bytes mode of LUT RAM, 0: 1 byte,1: 2bytes, 2: 4
* bytes
*/
uint32_t lut_mode:2;
uint32_t reserved_13:19;
};
uint32_t val;
} bitscrambler_lut_cfg0_reg_t;
/** Type of lut_cfg1 register
* Control and configuration registers
*/
typedef union {
struct {
/** lut : R/W; bitpos: [31:0]; default: 20;
* write this bits to update LUT, Read this bits to get LUT
*/
uint32_t lut:32;
};
uint32_t val;
} bitscrambler_lut_cfg1_reg_t;
/** Type of tailing_bits register
* Control and configuration registers
*/
typedef union {
struct {
/** tailing_bits : R/W; bitpos: [15:0]; default: 0;
* write this bits to specify the extra data bit length after getting EOF
*/
uint32_t tailing_bits:16;
uint32_t reserved_16:16;
};
uint32_t val;
} bitscrambler_tailing_bits_reg_t;
/** Type of ctrl register
* Control and configuration registers
*/
typedef union {
struct {
/** ena : R/W; bitpos: [0]; default: 0;
* write this bit to enable the bitscrambler
*/
uint32_t ena:1;
/** pause : R/W; bitpos: [1]; default: 0;
* write this bit to pause the bitscrambler core
*/
uint32_t pause:1;
/** halt : R/W; bitpos: [2]; default: 1;
* write this bit to halt the bitscrambler core
*/
uint32_t halt:1;
/** eof_mode : R/W; bitpos: [3]; default: 0;
* write this bit to set the bitscrambler core EOF signal generating mode
*/
uint32_t eof_mode:1;
/** cond_mode : R/W; bitpos: [4]; default: 0;
* write this bit to specify the LOOP instruction condition mode
*/
uint32_t cond_mode:1;
/** fetch_mode : R/W; bitpos: [5]; default: 0;
* write this bit to set the bitscrambler core fetch instruction mode
*/
uint32_t fetch_mode:1;
/** halt_mode : R/W; bitpos: [6]; default: 0;
* write this bit to set the bitscrambler core halt mode
*/
uint32_t halt_mode:1;
/** rd_dummy : R/W; bitpos: [7]; default: 0;
* write this bit to set the bitscrambler core read data mode when EOF received
*/
uint32_t rd_dummy:1;
/** fifo_rst : WT; bitpos: [8]; default: 0;
* write this bit to reset the bitscrambler fifo
*/
uint32_t fifo_rst:1;
uint32_t reserved_9:23;
};
uint32_t val;
} bitscrambler_ctrl_reg_t;
/** Type of state register
* Status registers
*/
typedef union {
struct {
/** in_idle : RO; bitpos: [0]; default: 1;
* represents the bitscrambler core in halt mode
*/
uint32_t in_idle:1;
/** in_run : RO; bitpos: [1]; default: 0;
* represents the bitscrambler core in run mode
*/
uint32_t in_run:1;
/** in_wait : RO; bitpos: [2]; default: 0;
* represents the bitscrambler core in wait mode to wait write back done
*/
uint32_t in_wait:1;
/** in_pause : RO; bitpos: [3]; default: 0;
* represents the bitscrambler core in pause mode
*/
uint32_t in_pause:1;
/** fifo_empty : RO; bitpos: [4]; default: 0;
* represents the bitscrambler fifo state (tx: empty, rx: full)
*/
uint32_t fifo_empty:1;
/** crc_rdy : RO; bitpos: [5]; default: 0;
* represents the crc calculate result is ready
*/
uint32_t crc_rdy:1;
uint32_t reserved_6:10;
/** eof_get_cnt : RO; bitpos: [29:16]; default: 0;
* represents the bytes numbers when get EOF
*/
uint32_t eof_get_cnt:14;
/** eof_overload : RO; bitpos: [30]; default: 0;
* represents the some EOFs will be lost
*/
uint32_t eof_overload:1;
/** eof_trace_clr : WT; bitpos: [31]; default: 0;
* write this bit to clear eof_overload and eof_get_cnt registers
*/
uint32_t eof_trace_clr:1;
};
uint32_t val;
} bitscrambler_state_reg_t;
/** Type of cnt_cfg register
* Counter cfg registers
*/
typedef union {
struct {
/** cnt_a_cfg_value : R/W; bitpos: [15:0]; default: 0;
* config the counter a value
*/
uint32_t cnt_a_cfg_value:16;
/** cnt_b_cfg_value : R/W; bitpos: [31:16]; default: 0;
* config the counter b value
*/
uint32_t cnt_b_cfg_value:16;
};
uint32_t val;
} bitscrambler_cnt_cfg_reg_t;
/** Type of cnt_state register
* Counter state registers
*/
typedef union {
struct {
/** cnt_a_value : RO; bitpos: [15:0]; default: 0;
* read the counter a value
*/
uint32_t cnt_a_value:16;
/** cnt_b_value : RO; bitpos: [31:16]; default: 0;
* read the counter b value
*/
uint32_t cnt_b_value:16;
};
uint32_t val;
} bitscrambler_cnt_state_reg_t;
typedef struct {
volatile bitscrambler_tx_inst_cfg0_reg_t tx_inst_cfg0;
volatile bitscrambler_tx_inst_cfg1_reg_t tx_inst_cfg1;
volatile bitscrambler_rx_inst_cfg0_reg_t rx_inst_cfg0;
volatile bitscrambler_rx_inst_cfg1_reg_t rx_inst_cfg1;
volatile bitscrambler_tx_lut_cfg0_reg_t tx_lut_cfg0;
volatile bitscrambler_tx_lut_cfg1_reg_t tx_lut_cfg1;
volatile bitscrambler_rx_lut_cfg0_reg_t rx_lut_cfg0;
volatile bitscrambler_rx_lut_cfg1_reg_t rx_lut_cfg1;
volatile bitscrambler_tx_tailing_bits_reg_t tx_tailing_bits;
volatile bitscrambler_rx_tailing_bits_reg_t rx_tailing_bits;
volatile bitscrambler_tx_ctrl_reg_t tx_ctrl;
volatile bitscrambler_rx_ctrl_reg_t rx_ctrl;
volatile bitscrambler_tx_state_reg_t tx_state;
volatile bitscrambler_rx_state_reg_t rx_state;
volatile bitscrambler_tx_cnt_cfg_reg_t tx_cnt_cfg;
volatile bitscrambler_rx_cnt_cfg_reg_t rx_cnt_cfg;
volatile bitscrambler_tx_cnt_state_reg_t tx_cnt_state;
volatile bitscrambler_rx_cnt_state_reg_t rx_cnt_state;
volatile struct {
bitscrambler_inst_cfg0_reg_t cfg0;
bitscrambler_inst_cfg1_reg_t cfg1;
} inst_cfg[2];
volatile struct {
bitscrambler_lut_cfg0_reg_t cfg0;
bitscrambler_lut_cfg1_reg_t cfg1;
} lut_cfg[2];
volatile bitscrambler_tailing_bits_reg_t tail_bits[2];
volatile bitscrambler_ctrl_reg_t ctrl[2];
volatile bitscrambler_state_reg_t state[2];
volatile bitscrambler_cnt_cfg_reg_t cnt_cfg[2];
volatile bitscrambler_cnt_state_reg_t cnt_state[2];
uint32_t reserved_048[44];
volatile bitscrambler_sys_reg_t sys;
volatile bitscrambler_version_reg_t version;
} bitscrambler_dev_t;
#ifndef __cplusplus
_Static_assert(sizeof(bitscrambler_dev_t) == 0x100, "Invalid size of bitscrambler_dev_t structure");
#endif
extern bitscrambler_dev_t BITSCRAMBLER;
#ifdef __cplusplus
}
#endif
+2
View File
@@ -93,6 +93,8 @@ INPUT = \
$(PROJECT_PATH)/components/esp_driver_ana_cmpr/include/driver/ana_cmpr.h \
$(PROJECT_PATH)/components/esp_driver_ana_cmpr/include/driver/ana_cmpr_etm.h \
$(PROJECT_PATH)/components/esp_driver_ana_cmpr/include/driver/ana_cmpr_types.h \
$(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler.h \
$(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler_loopback.h \
$(PROJECT_PATH)/components/esp_driver_cordic/include/driver/cordic.h \
$(PROJECT_PATH)/components/esp_driver_cordic/include/driver/cordic_types.h \
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_continuous.h \
-2
View File
@@ -1,6 +1,4 @@
INPUT += \
$(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler.h \
$(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler_loopback.h \
$(PROJECT_PATH)/components/esp_hal_dma/esp32c5/include/hal/bitscrambler_peri_select.h \
$(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_i2c.h \
$(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_uart.h \
-2
View File
@@ -1,6 +1,4 @@
INPUT += \
$(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler.h \
$(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler_loopback.h \
$(PROJECT_PATH)/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h \
$(PROJECT_PATH)/components/esp_driver_cam/include/esp_cam_ctlr.h \
$(PROJECT_PATH)/components/esp_driver_cam/include/esp_cam_ctlr_types.h \
+1
View File
@@ -1 +1,2 @@
INPUT += \
$(PROJECT_PATH)/components/esp_hal_dma/esp32s31/include/hal/bitscrambler_peri_select.h
+2 -2
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C5 | ESP32-P4 |
| ----------------- | -------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-P4 | ESP32-S31 |
| ----------------- | -------- | -------- | --------- |
# BitScrambler Loopback Example
@@ -40,7 +40,7 @@ void app_main(void)
assert(result_buf_size >= output_data_len);
bitscrambler_handle_t bs;
ESP_ERROR_CHECK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, result_buf_size));
ESP_ERROR_CHECK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_GPSPI2, result_buf_size));
ESP_ERROR_CHECK(bitscrambler_load_program(bs, bitscrambler_program_example));
size_t result_len;
@@ -3,10 +3,11 @@
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic
@idf_parametrize('target', ['esp32p4', 'esp32c5'], indirect=['target'])
@idf_parametrize('target', soc_filtered_targets('SOC_BITSCRAMBLER_SUPPORTED == 1'), indirect=['target'])
def test_bitscrambler_loopback_example(dut: Dut) -> None:
dut.expect_exact('BitScrambler example main', timeout=5)
dut.expect_exact('BitScrambler program complete. Input 40, output 40 bytes')