Skip to content

Commit d46019b

Browse files
committed
refactor(bitscrambler): don't use Reset Clock Control lock of RC version
1 parent 7bca1fe commit d46019b

File tree

4 files changed

+117
-92
lines changed

4 files changed

+117
-92
lines changed

components/esp_driver_bitscrambler/include/driver/bitscrambler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ typedef struct {
5050
/**
5151
* @brief Allocate BitScrambler handle for a hardware channel
5252
*
53+
* @note This function can only be used to create a single direction BitScrambler handle.
54+
* If you need a loopback BitScrambler, call bitscrambler_loopback_create() instead.
55+
*
5356
* @param config Configuration for requested BitScrambler
5457
* @param[out] handle BitScrambler controller handle
5558
*

components/esp_driver_bitscrambler/src/bitscrambler.c

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
#include <string.h>
77
#include <stdatomic.h>
8+
#include "soc/soc_caps.h"
89
#include "esp_log.h"
910
#include "esp_heap_caps.h"
1011
#include "driver/bitscrambler.h"
@@ -20,6 +21,13 @@ static const char *TAG = "bitscrambler";
2021
#define BITSCRAMBLER_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
2122
#endif
2223

24+
#if !SOC_RCC_IS_INDEPENDENT
25+
// Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section
26+
#define BS_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
27+
#else
28+
#define BS_RCC_ATOMIC()
29+
#endif
30+
2331
#define BITSCRAMBLER_BINARY_VER 1 //max version we're compatible with
2432
#define BITSCRAMBLER_HW_REV 0
2533

@@ -54,95 +62,92 @@ typedef struct {
5462
atomic_flag tx_in_use = ATOMIC_FLAG_INIT;
5563
atomic_flag rx_in_use = ATOMIC_FLAG_INIT;
5664

57-
// Claim both TX and RX channels for loopback use
58-
// Returns true on success, false if any of the two directions already is claimed.
59-
static bool claim_channel_loopback(void)
60-
{
61-
bool old_val_tx = atomic_flag_test_and_set(&tx_in_use);
62-
if (old_val_tx) {
63-
return false;
64-
}
65-
bool old_val_rx = atomic_flag_test_and_set(&rx_in_use);
66-
if (old_val_rx) {
67-
atomic_flag_clear(&tx_in_use);
68-
return false;
69-
}
70-
return true;
71-
}
65+
// This is a reference count for the BitScrambler module. It is used to keep track of how many clients are using the module.
66+
atomic_int group_ref_count = 0;
7267

7368
// Claim a channel using the direction it indicated.
7469
// Returns true on success, false if the direction already is claimed
7570
static bool claim_channel(bitscrambler_direction_t dir)
7671
{
72+
int old_use_count = atomic_fetch_add(&group_ref_count, 1);
73+
if (old_use_count == 0) {
74+
BS_RCC_ATOMIC() {
75+
// This is the first client using the module, so we need to enable the sys clock
76+
bitscrambler_ll_set_bus_clock_sys_enable(true);
77+
bitscrambler_ll_reset_sys();
78+
// also power on the memory
79+
bitscrambler_ll_mem_power_by_pmu();
80+
}
81+
}
7782
if (dir == BITSCRAMBLER_DIR_TX) {
7883
bool old_val = atomic_flag_test_and_set(&tx_in_use);
7984
if (old_val) {
80-
return false;
85+
goto err;
86+
} else {
87+
BS_RCC_ATOMIC() {
88+
bitscrambler_ll_set_bus_clock_tx_enable(true);
89+
bitscrambler_ll_reset_tx();
90+
}
8191
}
82-
} else if (dir == BITSCRAMBLER_DIR_RX) {
92+
} else {
8393
bool old_val = atomic_flag_test_and_set(&rx_in_use);
8494
if (old_val) {
85-
return false;
95+
goto err;
96+
} else {
97+
BS_RCC_ATOMIC() {
98+
bitscrambler_ll_set_bus_clock_rx_enable(true);
99+
bitscrambler_ll_reset_rx();
100+
}
86101
}
87102
}
88103
return true;
104+
err:
105+
atomic_fetch_sub(&group_ref_count, 1);
106+
return false;
89107
}
90108

91-
//Initialize the BitScrambler object and hardware using the given config.
92-
static esp_err_t init_from_config(bitscrambler_t *bs, const bitscrambler_config_t *config)
93-
{
94-
bs->cfg = *config; //Copy config over
95-
bs->hw = BITSCRAMBLER_LL_GET_HW(0); //there's only one as of now; if there's more, we need to handle them as a pool.
96-
return ESP_OK;
97-
}
98-
99-
static void enable_clocks(bitscrambler_t *bs)
109+
// Release the channel using the direction it indicated.
110+
static void release_channel(bitscrambler_direction_t dir)
100111
{
101-
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_BITSCRAMBLER_MODULE, ref_count) {
102-
if (ref_count == 0) { //we're the first to enable the BitScrambler module
103-
bitscrambler_ll_set_bus_clock_sys_enable(1);
104-
bitscrambler_ll_reset_sys();
105-
bitscrambler_ll_mem_power_by_pmu();
106-
}
107-
if (bs->cfg.dir == BITSCRAMBLER_DIR_RX || bs->loopback) {
108-
bitscrambler_ll_set_bus_clock_rx_enable(1);
109-
bitscrambler_ll_reset_rx();
110-
}
111-
if (bs->cfg.dir == BITSCRAMBLER_DIR_TX || bs->loopback) {
112-
bitscrambler_ll_set_bus_clock_tx_enable(1);
113-
bitscrambler_ll_reset_tx();
112+
if (dir == BITSCRAMBLER_DIR_TX) {
113+
atomic_flag_clear(&tx_in_use);
114+
} else if (dir == BITSCRAMBLER_DIR_RX) {
115+
atomic_flag_clear(&rx_in_use);
116+
}
117+
int old_use_count = atomic_fetch_sub(&group_ref_count, 1);
118+
if (old_use_count == 1) {
119+
// This is the last client using the module, so we need to disable the sys clock
120+
BS_RCC_ATOMIC() {
121+
bitscrambler_ll_set_bus_clock_sys_enable(false);
122+
bitscrambler_ll_mem_force_power_off();
114123
}
115124
}
116125
}
117126

118-
static void disable_clocks(bitscrambler_t *bs)
127+
//Initialize the BitScrambler object and hardware using the given config.
128+
static esp_err_t init_from_config(bitscrambler_t *bs, const bitscrambler_config_t *config)
119129
{
120-
PERIPH_RCC_RELEASE_ATOMIC(PERIPH_BITSCRAMBLER_MODULE, ref_count) {
121-
if (bs->cfg.dir == BITSCRAMBLER_DIR_RX || bs->loopback) {
122-
bitscrambler_ll_set_bus_clock_rx_enable(0);
123-
}
124-
if (bs->cfg.dir == BITSCRAMBLER_DIR_TX || bs->loopback) {
125-
bitscrambler_ll_set_bus_clock_tx_enable(0);
126-
}
127-
if (ref_count == 0) { //we're the last to disable the BitScrambler module
128-
bitscrambler_ll_set_bus_clock_sys_enable(0);
129-
bitscrambler_ll_mem_force_power_off();
130-
}
131-
}
130+
bs->cfg = *config; //Copy config over
131+
bs->hw = BITSCRAMBLER_LL_GET_HW(0); //there's only one as of now; if there's more, we need to handle them as a pool.
132+
return ESP_OK;
132133
}
133134

134-
//Private function: init an existing BitScrambler object as a loopback BitScrambler.
135+
// init an existing BitScrambler object as a loopback BitScrambler, only used by the bitscrambler loopback driver
135136
esp_err_t bitscrambler_init_loopback(bitscrambler_handle_t handle, const bitscrambler_config_t *config)
136137
{
137-
if (!claim_channel_loopback()) {
138+
// claim the TX channel first
139+
if (!claim_channel(BITSCRAMBLER_DIR_TX)) {
140+
return ESP_ERR_NOT_FOUND;
141+
}
142+
// claim the RX channel, if it fails, release the TX channel
143+
if (!claim_channel(BITSCRAMBLER_DIR_RX)) {
144+
release_channel(BITSCRAMBLER_DIR_TX);
138145
return ESP_ERR_NOT_FOUND;
139146
}
140147

141-
assert(config->dir == BITSCRAMBLER_DIR_TX);
148+
// mark the BitScrambler object as a loopback BitScrambler
142149
handle->loopback = true;
143-
enable_clocks(handle);
144-
esp_err_t r = init_from_config(handle, config);
145-
return r;
150+
return init_from_config(handle, config);
146151
}
147152

148153
esp_err_t bitscrambler_new(const bitscrambler_config_t *config, bitscrambler_handle_t *handle)
@@ -172,8 +177,6 @@ esp_err_t bitscrambler_new(const bitscrambler_config_t *config, bitscrambler_han
172177
return r;
173178
}
174179

175-
enable_clocks(bs);
176-
177180
// Return the handle
178181
*handle = bs;
179182
return ESP_OK;
@@ -304,14 +307,11 @@ void bitscrambler_free(bitscrambler_handle_t handle)
304307
if (!handle) {
305308
return;
306309
}
307-
disable_clocks(handle);
308310
if (handle->loopback) {
309-
atomic_flag_clear(&tx_in_use);
310-
atomic_flag_clear(&rx_in_use);
311-
} else if (handle->cfg.dir == BITSCRAMBLER_DIR_TX) {
312-
atomic_flag_clear(&tx_in_use);
313-
} else if (handle->cfg.dir == BITSCRAMBLER_DIR_RX) {
314-
atomic_flag_clear(&rx_in_use);
311+
release_channel(BITSCRAMBLER_DIR_TX);
312+
release_channel(BITSCRAMBLER_DIR_RX);
313+
} else {
314+
release_channel(handle->cfg.dir);
315315
}
316316
if (handle->extra_clean_up) {
317317
handle->extra_clean_up(handle, handle->clean_up_user_ctx);

components/hal/esp32c5/include/hal/bitscrambler_ll.h

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -298,23 +298,23 @@ static inline bool bitscrambler_ll_is_fifo_ready(bitscrambler_dev_t *hw, bitscra
298298
/**
299299
* @brief Enable the bus clock for BitScrambler module
300300
*/
301-
static inline void _bitscrambler_ll_set_bus_clock_sys_enable(bool enable)
301+
static inline void bitscrambler_ll_set_bus_clock_sys_enable(bool enable)
302302
{
303303
PCR.bs_conf.bs_clk_en = enable;
304304
}
305305

306306
/**
307307
* @brief Enable the bus clock for RX BitScrambler module
308308
*/
309-
static inline void _bitscrambler_ll_set_bus_clock_rx_enable(bool enable)
309+
static inline void bitscrambler_ll_set_bus_clock_rx_enable(bool enable)
310310
{
311311
// empty
312312
}
313313

314314
/**
315315
* @brief Enable the bus clock for TX BitScrambler module
316316
*/
317-
static inline void _bitscrambler_ll_set_bus_clock_tx_enable(bool enable)
317+
static inline void bitscrambler_ll_set_bus_clock_tx_enable(bool enable)
318318
{
319319
// empty
320320
}
@@ -349,7 +349,7 @@ static inline void bitscrambler_ll_mem_power_by_pmu(void)
349349
/**
350350
* @brief Reset the BitScrambler module
351351
*/
352-
static inline void _bitscrambler_ll_reset_sys(void)
352+
static inline void bitscrambler_ll_reset_sys(void)
353353
{
354354
PCR.bs_conf.bs_rst_en = 1;
355355
PCR.bs_conf.bs_rst_en = 0;
@@ -358,7 +358,7 @@ static inline void _bitscrambler_ll_reset_sys(void)
358358
/**
359359
* @brief Reset the BitScrambler RX module
360360
*/
361-
static inline void _bitscrambler_ll_reset_rx(void)
361+
static inline void bitscrambler_ll_reset_rx(void)
362362
{
363363
PCR.bs_func_conf.bs_rx_rst_en = 1;
364364
PCR.bs_func_conf.bs_rx_rst_en = 0;
@@ -367,22 +367,12 @@ static inline void _bitscrambler_ll_reset_rx(void)
367367
/**
368368
* @brief Reset the BitScrambler TX module
369369
*/
370-
static inline void _bitscrambler_ll_reset_tx(void)
370+
static inline void bitscrambler_ll_reset_tx(void)
371371
{
372372
PCR.bs_func_conf.bs_tx_rst_en = 1;
373373
PCR.bs_func_conf.bs_tx_rst_en = 0;
374374
}
375375

376-
/// use a macro to wrap the function, force the caller to use it in a critical section
377-
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
378-
#define bitscrambler_ll_set_bus_clock_sys_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_sys_enable(__VA_ARGS__)
379-
#define bitscrambler_ll_set_bus_clock_rx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_rx_enable(__VA_ARGS__)
380-
#define bitscrambler_ll_set_bus_clock_tx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_tx_enable(__VA_ARGS__)
381-
382-
#define bitscrambler_ll_reset_sys(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_sys(__VA_ARGS__)
383-
#define bitscrambler_ll_reset_rx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_rx(__VA_ARGS__)
384-
#define bitscrambler_ll_reset_tx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_tx(__VA_ARGS__)
385-
386376
#ifdef __cplusplus
387377
}
388378
#endif

components/hal/esp32p4/include/hal/bitscrambler_ll.h

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ static inline void _bitscrambler_ll_set_bus_clock_sys_enable(bool enable)
303303
HP_SYS_CLKRST.soc_clk_ctrl1.reg_bitscrambler_sys_clk_en = enable;
304304
}
305305

306+
/// use a macro to wrap the function, force the caller to use it in a critical section
307+
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
308+
#define bitscrambler_ll_set_bus_clock_sys_enable(...) do { \
309+
(void)__DECLARE_RCC_ATOMIC_ENV; \
310+
_bitscrambler_ll_set_bus_clock_sys_enable(__VA_ARGS__); \
311+
} while (0)
312+
306313
/**
307314
* @brief Enable the bus clock for RX BitScrambler module
308315
*/
@@ -311,6 +318,13 @@ static inline void _bitscrambler_ll_set_bus_clock_rx_enable(bool enable)
311318
HP_SYS_CLKRST.soc_clk_ctrl1.reg_bitscrambler_rx_sys_clk_en = enable;
312319
}
313320

321+
/// use a macro to wrap the function, force the caller to use it in a critical section
322+
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
323+
#define bitscrambler_ll_set_bus_clock_rx_enable(...) do { \
324+
(void)__DECLARE_RCC_ATOMIC_ENV; \
325+
_bitscrambler_ll_set_bus_clock_rx_enable(__VA_ARGS__); \
326+
} while (0)
327+
314328
/**
315329
* @brief Enable the bus clock for TX BitScrambler module
316330
*/
@@ -319,6 +333,13 @@ static inline void _bitscrambler_ll_set_bus_clock_tx_enable(bool enable)
319333
HP_SYS_CLKRST.soc_clk_ctrl1.reg_bitscrambler_tx_sys_clk_en = enable;
320334
}
321335

336+
/// use a macro to wrap the function, force the caller to use it in a critical section
337+
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
338+
#define bitscrambler_ll_set_bus_clock_tx_enable(...) do { \
339+
(void)__DECLARE_RCC_ATOMIC_ENV; \
340+
_bitscrambler_ll_set_bus_clock_tx_enable(__VA_ARGS__); \
341+
} while (0)
342+
322343
/**
323344
* @brief Force power on the bitscrambler memory block, regardless of the outside PMU logic
324345
*/
@@ -352,6 +373,13 @@ static inline void _bitscrambler_ll_reset_sys(void)
352373
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_bitscrambler = 0;
353374
}
354375

376+
/// use a macro to wrap the function, force the caller to use it in a critical section
377+
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
378+
#define bitscrambler_ll_reset_sys(...) do { \
379+
(void)__DECLARE_RCC_ATOMIC_ENV; \
380+
_bitscrambler_ll_reset_sys(__VA_ARGS__); \
381+
} while (0)
382+
355383
/**
356384
* @brief Reset the BitScrambler RX module
357385
*/
@@ -361,6 +389,13 @@ static inline void _bitscrambler_ll_reset_rx(void)
361389
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_bitscrambler_rx = 0;
362390
}
363391

392+
/// use a macro to wrap the function, force the caller to use it in a critical section
393+
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
394+
#define bitscrambler_ll_reset_rx(...) do { \
395+
(void)__DECLARE_RCC_ATOMIC_ENV; \
396+
_bitscrambler_ll_reset_rx(__VA_ARGS__); \
397+
} while (0)
398+
364399
/**
365400
* @brief Reset the BitScrambler TX module
366401
*/
@@ -371,14 +406,11 @@ static inline void _bitscrambler_ll_reset_tx(void)
371406
}
372407

373408
/// use a macro to wrap the function, force the caller to use it in a critical section
374-
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
375-
#define bitscrambler_ll_set_bus_clock_sys_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_sys_enable(__VA_ARGS__)
376-
#define bitscrambler_ll_set_bus_clock_rx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_rx_enable(__VA_ARGS__)
377-
#define bitscrambler_ll_set_bus_clock_tx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_tx_enable(__VA_ARGS__)
378-
379-
#define bitscrambler_ll_reset_sys(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_sys(__VA_ARGS__)
380-
#define bitscrambler_ll_reset_rx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_rx(__VA_ARGS__)
381-
#define bitscrambler_ll_reset_tx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_tx(__VA_ARGS__)
409+
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
410+
#define bitscrambler_ll_reset_tx(...) do { \
411+
(void)__DECLARE_RCC_ATOMIC_ENV; \
412+
_bitscrambler_ll_reset_tx(__VA_ARGS__); \
413+
} while (0)
382414

383415
#ifdef __cplusplus
384416
}

0 commit comments

Comments
 (0)