Skip to content

Commit d3dba75

Browse files
Kainarxsuda-morris
authored andcommitted
feat(parlio_tx): support to mount bitscrambler
1 parent 39f6aeb commit d3dba75

File tree

15 files changed

+486
-68
lines changed

15 files changed

+486
-68
lines changed

components/esp_driver_parlio/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ if(CONFIG_SOC_PARLIO_SUPPORTED)
88
"src/parlio_rx.c")
99
endif()
1010

11+
if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED)
12+
list(APPEND srcs "src/parlio_bitscrambler.c")
13+
endif()
14+
1115
if(${target} STREQUAL "linux")
1216
set(priv_requires "")
1317
else()
14-
set(priv_requires esp_pm esp_driver_gpio esp_mm)
18+
set(priv_requires esp_pm esp_driver_gpio esp_mm esp_driver_bitscrambler)
1519
endif()
1620

1721
idf_component_register(SRCS ${srcs}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <stdbool.h>
10+
#include <stdint.h>
11+
#include "esp_err.h"
12+
#include "driver/parlio_types.h"
13+
14+
#ifdef __cplusplus
15+
extern "C" {
16+
#endif
17+
18+
/**
19+
* @brief Decorate Parlio TX units with BitScrambler
20+
*
21+
* @note This function creates a BitScrambler instance and associates it with the Parlio TX unit.
22+
* The decorated TX unit will be able to do some pre-process to the user data with the help of BitScrambler
23+
* Only can be called before enable the TX unit
24+
*
25+
* @param[in] tx_unit Parlio TX unit handle
26+
* @return
27+
* - ESP_OK: Decorate Parlio TX units with BitScrambler success
28+
* - ESP_ERR_INVALID_ARG: Failed because of invalid argument
29+
* - ESP_ERR_INVALID_STATE: Failed because the TX unit is already decorated with BitScrambler
30+
* - ESP_FAIL: Failed because of other error
31+
*/
32+
esp_err_t parlio_tx_unit_decorate_bitscrambler(parlio_tx_unit_handle_t tx_unit);
33+
34+
/**
35+
* @brief Remove the BitScrambler decoration from the Parlio TX unit
36+
*
37+
* @note This function removes the BitScrambler decoration from the Parlio TX unit, restoring the original functionality.
38+
* Only can be called before enable the TX unit
39+
*
40+
* @param[in] tx_unit Parlio TX unit handle
41+
* @return
42+
* - ESP_OK: Remove the BitScrambler decoration from the Parlio TX unit success
43+
* - ESP_ERR_INVALID_ARG: Failed because of invalid argument
44+
* - ESP_ERR_INVALID_STATE: Failed because the TX unit is not decorated with BitScrambler
45+
* - ESP_FAIL: Failed because of other error
46+
*/
47+
esp_err_t parlio_tx_unit_undecorate_bitscrambler(parlio_tx_unit_handle_t tx_unit);
48+
49+
#ifdef __cplusplus
50+
}
51+
#endif

components/esp_driver_parlio/include/driver/parlio_tx.h

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -108,23 +108,6 @@ esp_err_t parlio_tx_unit_enable(parlio_tx_unit_handle_t unit);
108108
*/
109109
esp_err_t parlio_tx_unit_disable(parlio_tx_unit_handle_t unit);
110110

111-
/**
112-
* @brief Type of Parallel IO TX done event data
113-
*/
114-
typedef struct {
115-
} parlio_tx_done_event_data_t;
116-
117-
/**
118-
* @brief Prototype of parlio tx event callback
119-
* @param[in] tx_unit Parallel IO TX unit that created by `parlio_new_tx_unit`
120-
* @param[in] edata Point to Parallel IO TX event data. The lifecycle of this pointer memory is inside this function,
121-
* user should copy it into static memory if used outside this function.
122-
* @param[in] user_ctx User registered context, passed from `parlio_tx_unit_register_event_callbacks`
123-
*
124-
* @return Whether a high priority task has been waken up by this callback function
125-
*/
126-
typedef bool (*parlio_tx_done_callback_t)(parlio_tx_unit_handle_t tx_unit, const parlio_tx_done_event_data_t *edata, void *user_ctx);
127-
128111
/**
129112
* @brief Group of Parallel IO TX callbacks
130113
* @note The callbacks are all running under ISR environment
@@ -157,6 +140,7 @@ esp_err_t parlio_tx_unit_register_event_callbacks(parlio_tx_unit_handle_t tx_uni
157140
*/
158141
typedef struct {
159142
uint32_t idle_value; /*!< The value on the data line when the parallel IO is in idle state */
143+
const void *bitscrambler_program; /*!< BitScrambler program binary, NULL if not use BitScrambler */
160144
struct {
161145
uint32_t queue_nonblocking : 1; /*!< If set, when the transaction queue is full, driver will not block the thread but return directly */
162146
uint32_t loop_transmission : 1; /*!< If set, the transmission will be repeated continuously, until the tx_unit is disabled by `parlio_tx_unit_disable` */

components/esp_driver_parlio/include/driver/parlio_types.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -31,6 +31,23 @@ typedef struct parlio_rx_unit_t *parlio_rx_unit_handle_t;
3131
*/
3232
typedef struct parlio_rx_delimiter_t *parlio_rx_delimiter_handle_t;
3333

34+
/**
35+
* @brief Type of Parallel IO TX done event data
36+
*/
37+
typedef struct {
38+
} parlio_tx_done_event_data_t;
39+
40+
/**
41+
* @brief Prototype of parlio tx event callback
42+
* @param[in] tx_unit Parallel IO TX unit that created by `parlio_new_tx_unit`
43+
* @param[in] edata Point to Parallel IO TX event data. The lifecycle of this pointer memory is inside this function,
44+
* user should copy it into static memory if used outside this function.
45+
* @param[in] user_ctx User registered context, passed from `parlio_tx_unit_register_event_callbacks`
46+
*
47+
* @return Whether a high priority task has been waken up by this callback function
48+
*/
49+
typedef bool (*parlio_tx_done_callback_t)(parlio_tx_unit_handle_t tx_unit, const parlio_tx_done_event_data_t *edata, void *user_ctx);
50+
3451
#ifdef __cplusplus
3552
}
3653
#endif
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <string.h>
8+
#include "esp_log.h"
9+
#include "esp_check.h"
10+
#include "driver/parlio_tx.h"
11+
#include "driver/bitscrambler.h"
12+
#include "parlio_priv.h"
13+
14+
static esp_err_t parlio_tx_unit_bs_enable(parlio_tx_unit_handle_t tx_unit, parlio_tx_trans_desc_t *t)
15+
{
16+
if (t->bitscrambler_program) {
17+
ESP_RETURN_ON_ERROR(bitscrambler_enable(tx_unit->bs_handle), TAG, "enable bitscrambler failed");
18+
ESP_RETURN_ON_ERROR(bitscrambler_load_program(tx_unit->bs_handle, t->bitscrambler_program), TAG, "load bitscrambler program failed");
19+
ESP_RETURN_ON_ERROR(bitscrambler_reset(tx_unit->bs_handle), TAG, "reset bitscrambler failed");
20+
ESP_RETURN_ON_ERROR(bitscrambler_start(tx_unit->bs_handle), TAG, "start bitscrambler failed");
21+
}
22+
return ESP_OK;
23+
}
24+
25+
static esp_err_t parlio_tx_unit_bs_disable(parlio_tx_unit_handle_t tx_unit)
26+
{
27+
ESP_RETURN_ON_ERROR(bitscrambler_disable(tx_unit->bs_handle), TAG, "disable bitscrambler failed");
28+
return ESP_OK;
29+
}
30+
31+
esp_err_t parlio_tx_unit_decorate_bitscrambler(parlio_tx_unit_handle_t tx_unit)
32+
{
33+
ESP_RETURN_ON_FALSE(tx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid TX unit");
34+
35+
// bitscrambler function is used under Parlio TX ISR context
36+
// if the cache is disabled, all functions called by ISR must be in IRAM
37+
#if CONFIG_PARLIO_TX_ISR_CACHE_SAFE && !CONFIG_BITSCRAMBLER_CTRL_FUNC_IN_IRAM
38+
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_STATE, TAG, "CONFIG_BITSCRAMBLER_CTRL_FUNC_IN_IRAM must be enabled");
39+
#endif
40+
41+
// check if already decorated
42+
if (tx_unit->bs_handle) {
43+
ESP_RETURN_ON_ERROR(ESP_ERR_INVALID_STATE, TAG, "TX unit already decorated with BitScrambler");
44+
}
45+
46+
// create BitScrambler instance
47+
bitscrambler_config_t bs_config = {
48+
.dir = BITSCRAMBLER_DIR_TX,
49+
.attach_to = SOC_BITSCRAMBLER_ATTACH_PARL_IO,
50+
};
51+
52+
parlio_tx_fsm_t expected_fsm = PARLIO_TX_FSM_INIT;
53+
if (atomic_compare_exchange_strong(&tx_unit->fsm, &expected_fsm, PARLIO_TX_FSM_WAIT)) {
54+
ESP_RETURN_ON_ERROR(bitscrambler_new(&bs_config, &tx_unit->bs_handle), TAG, "create bitscrambler failed");
55+
tx_unit->bs_enable_fn = parlio_tx_unit_bs_enable;
56+
tx_unit->bs_disable_fn = parlio_tx_unit_bs_disable;
57+
atomic_store(&tx_unit->fsm, PARLIO_TX_FSM_INIT);
58+
} else {
59+
ESP_RETURN_ON_ERROR(ESP_ERR_INVALID_STATE, TAG, "TX unit is not in init state");
60+
}
61+
return ESP_OK;
62+
}
63+
64+
esp_err_t parlio_tx_unit_undecorate_bitscrambler(parlio_tx_unit_handle_t tx_unit)
65+
{
66+
ESP_RETURN_ON_FALSE(tx_unit != NULL, ESP_ERR_INVALID_ARG, TAG, "invalid TX unit");
67+
68+
// check if already decorated
69+
if (!tx_unit->bs_handle) {
70+
ESP_RETURN_ON_ERROR(ESP_ERR_INVALID_STATE, TAG, "TX unit not decorated with BitScrambler yet");
71+
}
72+
parlio_tx_fsm_t expected_fsm = PARLIO_TX_FSM_INIT;
73+
if (atomic_compare_exchange_strong(&tx_unit->fsm, &expected_fsm, PARLIO_TX_FSM_WAIT)) {
74+
bitscrambler_free(tx_unit->bs_handle);
75+
tx_unit->bs_handle = NULL;
76+
tx_unit->bs_enable_fn = NULL;
77+
tx_unit->bs_disable_fn = NULL;
78+
atomic_store(&tx_unit->fsm, PARLIO_TX_FSM_INIT);
79+
} else {
80+
ESP_RETURN_ON_ERROR(ESP_ERR_INVALID_STATE, TAG, "TX unit is not in init state");
81+
}
82+
return ESP_OK;
83+
}

components/esp_driver_parlio/src/parlio_priv.h

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "rom/cache.h"
3939
#include "esp_heap_caps.h"
4040
#include "driver/parlio_types.h"
41+
#include "driver/bitscrambler.h"
4142
#include "esp_cache.h"
4243
#include "esp_clk_tree.h"
4344
#include "esp_pm.h"
@@ -122,12 +123,10 @@ typedef enum {
122123
} parlio_dir_t;
123124

124125
typedef enum {
125-
PARLIO_TX_FSM_INIT_WAIT,
126126
PARLIO_TX_FSM_INIT,
127-
PARLIO_TX_FSM_ENABLE_WAIT,
128127
PARLIO_TX_FSM_ENABLE,
129-
PARLIO_TX_FSM_RUN_WAIT,
130128
PARLIO_TX_FSM_RUN,
129+
PARLIO_TX_FSM_WAIT,
131130
} parlio_tx_fsm_t;
132131

133132
typedef struct parlio_unit_t *parlio_unit_base_handle_t;
@@ -150,6 +149,52 @@ struct parlio_unit_t {
150149
parlio_group_t *group; // group handle
151150
};
152151

152+
typedef struct {
153+
uint32_t idle_value; // Parallel IO bus idle value
154+
const void *payload; // payload to be transmitted
155+
size_t payload_bits; // payload size in bits
156+
int dma_link_idx; // index of DMA link list
157+
const void *bitscrambler_program; // bitscrambler program binary
158+
struct {
159+
uint32_t loop_transmission : 1; // whether the transmission is in loop mode
160+
} flags; // Extra configuration flags
161+
} parlio_tx_trans_desc_t;
162+
163+
// original function pointer type definition
164+
165+
typedef esp_err_t (*parlio_tx_bs_enable_fn_t)(parlio_tx_unit_handle_t tx_unit, parlio_tx_trans_desc_t *t);
166+
typedef esp_err_t (*parlio_tx_bs_disable_fn_t)(parlio_tx_unit_handle_t tx_unit);
167+
168+
typedef struct parlio_tx_unit_t {
169+
struct parlio_unit_t base; // base unit
170+
size_t data_width; // data width
171+
intr_handle_t intr; // allocated interrupt handle
172+
esp_pm_lock_handle_t pm_lock; // power management lock
173+
gdma_channel_handle_t dma_chan; // DMA channel
174+
gdma_link_list_handle_t dma_link[PARLIO_DMA_LINK_NUM]; // DMA link list handle
175+
size_t int_mem_align; // Alignment for internal memory
176+
size_t ext_mem_align; // Alignment for external memory
177+
#if CONFIG_PM_ENABLE
178+
char pm_lock_name[PARLIO_PM_LOCK_NAME_LEN_MAX]; // pm lock name
179+
#endif
180+
portMUX_TYPE spinlock; // prevent resource accessing by user and interrupt concurrently
181+
uint32_t out_clk_freq_hz; // output clock frequency
182+
parlio_clock_source_t clk_src; // Parallel IO internal clock source
183+
size_t max_transfer_bits; // maximum transfer size in bits
184+
size_t queue_depth; // size of transaction queue
185+
size_t num_trans_inflight; // indicates the number of transactions that are undergoing but not recycled to ready_queue
186+
QueueHandle_t trans_queues[PARLIO_TX_QUEUE_MAX]; // transaction queues
187+
parlio_tx_trans_desc_t *cur_trans; // points to current transaction
188+
uint32_t idle_value_mask; // mask of idle value
189+
_Atomic parlio_tx_fsm_t fsm; // Driver FSM state
190+
parlio_tx_done_callback_t on_trans_done; // callback function when the transmission is done
191+
void *user_data; // user data passed to the callback function
192+
bitscrambler_handle_t bs_handle; // bitscrambler handle
193+
parlio_tx_bs_enable_fn_t bs_enable_fn; // bitscrambler enable function
194+
parlio_tx_bs_disable_fn_t bs_disable_fn; // bitscrambler disable function
195+
parlio_tx_trans_desc_t trans_desc_pool[]; // transaction descriptor pool
196+
} parlio_tx_unit_t;
197+
153198
/**
154199
* @brief Register the rx or tx unit to the parlio group
155200
*

0 commit comments

Comments
 (0)