Skip to content

Commit c009176

Browse files
committed
lock: use nested and atomic control in critical section
Make sure Wi-Fi and BLE blob calls have nested and atomic access. The peripherals in this PR need to use atomic and nested call handling as it is either used in RF blobs or spread among multiple drivers. - phy - regi2c - periph_ctrl - esp_timer Signed-off-by: Sylvio Alves <[email protected]>
1 parent 7901db6 commit c009176

File tree

7 files changed

+124
-145
lines changed

7 files changed

+124
-145
lines changed

components/esp_hw_support/periph_ctrl.c

+25-20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66
#include <zephyr/kernel.h>
7+
#include <zephyr/sys/atomic.h>
8+
#include <zephyr/sys/__assert.h>
79

810
#include "hal/clk_gate_ll.h"
911
#include "esp_attr.h"
@@ -14,21 +16,24 @@
1416
#include "esp_private/esp_modem_clock.h"
1517
#endif
1618

17-
static int periph_spinlock;
18-
19-
#define ENTER_CRITICAL_SECTION() do { periph_spinlock = irq_lock(); } while(0)
20-
#define LEAVE_CRITICAL_SECTION() irq_unlock(periph_spinlock);
19+
unsigned int rcc_lock;
20+
static atomic_t rcc_lock_counter;
2121

2222
static uint8_t ref_counts[PERIPH_MODULE_MAX] = {0};
2323

2424
IRAM_ATTR void periph_rcc_enter(void)
2525
{
26-
ENTER_CRITICAL_SECTION();
26+
if (atomic_inc(&rcc_lock_counter) == 0) {
27+
rcc_lock = irq_lock();
28+
}
2729
}
2830

2931
IRAM_ATTR void periph_rcc_exit(void)
3032
{
31-
LEAVE_CRITICAL_SECTION();
33+
__ASSERT_NO_MSG(atomic_get(&rcc_lock_counter) > 0);
34+
if (atomic_dec(&rcc_lock_counter) == 1) {
35+
irq_unlock(rcc_lock);
36+
}
3237
}
3338

3439
IRAM_ATTR uint8_t periph_rcc_acquire_enter(periph_module_t periph)
@@ -58,31 +63,31 @@ IRAM_ATTR void periph_rcc_release_exit(periph_module_t periph, uint8_t ref_count
5863
void periph_module_enable(periph_module_t periph)
5964
{
6065
assert(periph < PERIPH_MODULE_MAX);
61-
ENTER_CRITICAL_SECTION();
66+
unsigned int key = irq_lock();
6267
if (ref_counts[periph] == 0) {
6368
periph_ll_enable_clk_clear_rst(periph);
6469
}
6570
ref_counts[periph]++;
66-
LEAVE_CRITICAL_SECTION();
71+
irq_unlock(key);
6772
}
6873

6974
void periph_module_disable(periph_module_t periph)
7075
{
7176
assert(periph < PERIPH_MODULE_MAX);
72-
ENTER_CRITICAL_SECTION();
77+
unsigned int key = irq_lock();
7378
ref_counts[periph]--;
7479
if (ref_counts[periph] == 0) {
7580
periph_ll_disable_clk_set_rst(periph);
7681
}
77-
LEAVE_CRITICAL_SECTION();
82+
irq_unlock(key);
7883
}
7984

8085
void periph_module_reset(periph_module_t periph)
8186
{
8287
assert(periph < PERIPH_MODULE_MAX);
83-
ENTER_CRITICAL_SECTION();
88+
unsigned int key = irq_lock();
8489
periph_ll_reset(periph);
85-
LEAVE_CRITICAL_SECTION();
90+
irq_unlock(key);
8691
}
8792

8893
#if !SOC_IEEE802154_BLE_ONLY
@@ -91,12 +96,12 @@ IRAM_ATTR void wifi_bt_common_module_enable(void)
9196
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
9297
modem_clock_module_enable(PERIPH_PHY_MODULE);
9398
#else
94-
ENTER_CRITICAL_SECTION();
99+
unsigned int key = irq_lock();
95100
if (ref_counts[PERIPH_WIFI_BT_COMMON_MODULE] == 0) {
96101
periph_ll_wifi_bt_module_enable_clk();
97102
}
98103
ref_counts[PERIPH_WIFI_BT_COMMON_MODULE]++;
99-
LEAVE_CRITICAL_SECTION();
104+
irq_unlock(key);
100105
#endif
101106
}
102107

@@ -105,12 +110,12 @@ IRAM_ATTR void wifi_bt_common_module_disable(void)
105110
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
106111
modem_clock_module_disable(PERIPH_PHY_MODULE);
107112
#else
108-
ENTER_CRITICAL_SECTION();
113+
unsigned int key = irq_lock();
109114
ref_counts[PERIPH_WIFI_BT_COMMON_MODULE]--;
110115
if (ref_counts[PERIPH_WIFI_BT_COMMON_MODULE] == 0) {
111116
periph_ll_wifi_bt_module_disable_clk();
112117
}
113-
LEAVE_CRITICAL_SECTION();
118+
irq_unlock(key);
114119
#endif
115120
}
116121
#endif
@@ -121,9 +126,9 @@ void wifi_module_enable(void)
121126
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
122127
modem_clock_module_enable(PERIPH_WIFI_MODULE);
123128
#else
124-
ENTER_CRITICAL_SECTION();
129+
unsigned int key = irq_lock();
125130
periph_ll_wifi_module_enable_clk_clear_rst();
126-
LEAVE_CRITICAL_SECTION();
131+
irq_unlock(key);
127132
#endif
128133
}
129134

@@ -132,9 +137,9 @@ void wifi_module_disable(void)
132137
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
133138
modem_clock_module_disable(PERIPH_WIFI_MODULE);
134139
#else
135-
ENTER_CRITICAL_SECTION();
140+
unsigned int key = irq_lock();
136141
periph_ll_wifi_module_disable_clk_set_rst();
137-
LEAVE_CRITICAL_SECTION();
142+
irq_unlock(key);
138143
#endif
139144
}
140145
#endif // CONFIG_WIFI_ESP32

components/esp_hw_support/regi2c_ctrl.c

+23-21
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,56 @@
1313
#include "hal/regi2c_ctrl_ll.h"
1414
#include "esp_hw_log.h"
1515

16-
static int mux;
17-
18-
#define ENTER_CRITICAL_SECTION() do { mux = irq_lock(); } while(0)
19-
#define LEAVE_CRITICAL_SECTION() irq_unlock(mux);
20-
2116
static DRAM_ATTR __attribute__((unused)) const char *TAG = "REGI2C";
2217

18+
static unsigned int regi2c_lock;
19+
static atomic_t regi2c_lock_counter;
20+
2321
#ifndef BOOTLOADER_BUILD
2422
uint8_t IRAM_ATTR regi2c_ctrl_read_reg(uint8_t block, uint8_t host_id, uint8_t reg_add)
2523
{
26-
ENTER_CRITICAL_SECTION();
24+
unsigned int key = irq_lock();
2725
uint8_t value = regi2c_read_reg_raw(block, host_id, reg_add);
28-
LEAVE_CRITICAL_SECTION();
26+
irq_unlock(key);
2927
return value;
3028
}
3129

3230
uint8_t IRAM_ATTR regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb)
3331
{
34-
ENTER_CRITICAL_SECTION();
32+
unsigned int key = irq_lock();
3533
uint8_t value = regi2c_read_reg_mask_raw(block, host_id, reg_add, msb, lsb);
36-
LEAVE_CRITICAL_SECTION();
34+
irq_unlock(key);
3735
return value;
3836
}
3937

4038
void IRAM_ATTR regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data)
4139
{
42-
ENTER_CRITICAL_SECTION();
40+
unsigned int key = irq_lock();
4341
regi2c_write_reg_raw(block, host_id, reg_add, data);
44-
LEAVE_CRITICAL_SECTION();
42+
irq_unlock(key);
4543
}
4644

4745
void IRAM_ATTR regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data)
4846
{
49-
ENTER_CRITICAL_SECTION();
47+
unsigned int key = irq_lock();
5048
regi2c_write_reg_mask_raw(block, host_id, reg_add, msb, lsb, data);
51-
LEAVE_CRITICAL_SECTION();
49+
irq_unlock(key);
5250
}
5351
#endif /* BOOTLOADER_BUILD */
5452

5553
void IRAM_ATTR regi2c_enter_critical(void)
5654
{
57-
ENTER_CRITICAL_SECTION();
55+
if (atomic_inc(&regi2c_lock_counter) == 0) {
56+
regi2c_lock = irq_lock();
57+
}
5858
}
5959

6060
void IRAM_ATTR regi2c_exit_critical(void)
6161
{
62-
LEAVE_CRITICAL_SECTION();
62+
__ASSERT_NO_MSG(atomic_get(&regi2c_lock_counter) > 0);
63+
if (atomic_dec(&regi2c_lock_counter) == 1) {
64+
irq_unlock(regi2c_lock);
65+
}
6366
}
6467

6568
/**
@@ -93,24 +96,23 @@ static int s_i2c_saradc_enable_cnt;
9396

9497
void regi2c_saradc_enable(void)
9598
{
96-
regi2c_enter_critical();
99+
unsigned int key = irq_lock();
97100
s_i2c_saradc_enable_cnt++;
98101
if (s_i2c_saradc_enable_cnt == 1) {
99102
regi2c_ctrl_ll_i2c_saradc_enable();
100103
}
101-
regi2c_exit_critical();
104+
irq_unlock(key);
102105
}
103106

104107
void regi2c_saradc_disable(void)
105108
{
106-
regi2c_enter_critical();
109+
unsigned int key = irq_lock();
107110
s_i2c_saradc_enable_cnt--;
108111
if (s_i2c_saradc_enable_cnt < 0){
109-
regi2c_exit_critical();
112+
irq_unlock(key);
110113
ESP_HW_LOGE(TAG, "REGI2C_SARADC is already disabled");
111114
} else if (s_i2c_saradc_enable_cnt == 0) {
112115
regi2c_ctrl_ll_i2c_saradc_disable();
113116
}
114-
regi2c_exit_critical();
115-
117+
irq_unlock(key);
116118
}

components/esp_phy/src/phy_init.c

+11-20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "esp_check.h"
2323
#include "sdkconfig.h"
2424
#include <zephyr/kernel.h>
25+
#include <zephyr/sys/atomic.h>
26+
#include <zephyr/sys/__assert.h>
2527
#include <esp_heap_caps.h>
2628
#include "esp_private/phy.h"
2729
#include "phy_init_data.h"
@@ -71,7 +73,7 @@ static int64_t s_phy_rf_en_ts = 0;
7173

7274
/* PHY spinlock for libphy.a */
7375
static DRAM_ATTR int s_phy_int_mux;
74-
static DRAM_ATTR int s_phy_lock_nest = 0;
76+
static atomic_t s_phy_lock_nest;
7577

7678
/* Indicate PHY is calibrated or not */
7779
static bool s_is_phy_calibrated = false;
@@ -211,29 +213,18 @@ esp_err_t phy_clear_used_time(esp_phy_modem_t modem) {
211213

212214
uint32_t IRAM_ATTR phy_enter_critical(void)
213215
{
214-
int key = irq_lock();
215-
if(s_phy_lock_nest == 0) {
216-
s_phy_int_mux = key;
217-
}
218-
219-
if(s_phy_lock_nest < 0xFFFFFFFF) {
220-
s_phy_lock_nest++;
221-
}
222-
223-
// Interrupt level will be stored in current tcb, so always return zero.
224-
return 0;
216+
if (atomic_inc(&s_phy_lock_nest) == 0) {
217+
s_phy_int_mux = irq_lock();
218+
}
219+
return 0;
225220
}
226221

227222
void IRAM_ATTR phy_exit_critical(uint32_t level)
228223
{
229-
if(s_phy_lock_nest > 0) {
230-
s_phy_lock_nest--;
231-
}
232-
233-
if(s_phy_lock_nest == 0) {
234-
// Param level don't need any more, ignore it.
235-
irq_unlock(s_phy_int_mux);
236-
}
224+
__ASSERT_NO_MSG(atomic_get(&s_phy_lock_nest) > 0);
225+
if (atomic_dec(&s_phy_lock_nest) == 1) {
226+
irq_unlock(s_phy_int_mux);
227+
}
237228
}
238229

239230
#if CONFIG_IDF_TARGET_ESP32

0 commit comments

Comments
 (0)