Skip to content

Commit d2f3e69

Browse files
committed
adding channel and block locks
1 parent 2e76fc0 commit d2f3e69

File tree

1 file changed

+63
-4
lines changed

1 file changed

+63
-4
lines changed

Diff for: cores/esp32/esp32-hal-rmt.c

+63-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "freertos/FreeRTOS.h"
22
#include "freertos/event_groups.h"
3+
#include "freertos/semphr.h"
34

45
#include "esp32-hal.h"
56
#include "esp8266-compat.h"
@@ -28,6 +29,14 @@
2829
#define _INT_ERROR(channel) (__INT_ERROR<<(channel*3))
2930
#define _INT_THR_EVNT(channel) ((__INT_THR_EVNT)<<(channel))
3031

32+
#if CONFIG_DISABLE_HAL_LOCKS
33+
# define UART_MUTEX_LOCK(channel)
34+
# define UART_MUTEX_UNLOCK(channel)
35+
#else
36+
# define RMT_MUTEX_LOCK(channel) do {} while (xSemaphoreTake(g_rmt_objlocks[channel], portMAX_DELAY) != pdPASS)
37+
# define RMT_MUTEX_UNLOCK(channel) xSemaphoreGive(g_rmt_objlocks[channel])
38+
#endif /* CONFIG_DISABLE_HAL_LOCKS */
39+
3140
typedef enum {
3241
e_no_intr = 0,
3342
e_tx_intr = 1,
@@ -58,15 +67,28 @@ struct rmt_obj_s
5867
transaction_state_t tx_state;
5968
};
6069

70+
static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
71+
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
72+
};
73+
6174
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
6275
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
6376
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
77+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
78+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
79+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
80+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
81+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
82+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
6483
};
6584

6685
static intr_handle_t intr_handle;
6786

6887
static bool periph_enabled = false;
6988

89+
static xSemaphoreHandle g_rmt_block_lock = NULL;
90+
91+
7092
static void _initPin(int pin, int channel, bool tx_not_rx);
7193

7294
static void IRAM_ATTR _rmt_isr(void* arg);
@@ -84,6 +106,13 @@ bool rmtDeinit(rmt_obj_t *rmt)
84106
}
85107

86108
size_t from = rmt->channel;
109+
110+
#if !CONFIG_DISABLE_HAL_LOCKS
111+
if(g_rmt_objlocks[from] != NULL) {
112+
vSemaphoreDelete(g_rmt_objlocks[from]);
113+
}
114+
#endif
115+
87116
size_t to = rmt->buffers + rmt->channel;
88117
size_t i;
89118

@@ -106,13 +135,13 @@ bool rmtSendQueued(rmt_obj_t* rmt, uint32_t* data, size_t size)
106135

107136
if (size > MAX_DATA_PER_ITTERATION) {
108137
// if (size > MAX_DATA_PER_CHANNEL) {
109-
138+
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
139+
RMT_MUTEX_LOCK(channel);
110140
// setup interrupt handler if not yet installed for half and full tx
111141
if (!intr_handle) {
112142
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle);
113143
}
114144

115-
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
116145
rmt->remaining_to_send = size - MAX_DATA_PER_ITTERATION;
117146
rmt->remaining_ptr = data + MAX_DATA_PER_ITTERATION;
118147
rmt->intr_mode = e_tx_intr | e_txthr_intr;
@@ -140,6 +169,8 @@ bool rmtSendQueued(rmt_obj_t* rmt, uint32_t* data, size_t size)
140169
RMT.int_ena.val |= _INT_THR_EVNT(channel);
141170
RMT.int_ena.val |= _INT_ERROR(channel);
142171

172+
RMT_MUTEX_UNLOCK(channel);
173+
143174
// start the transation
144175
return rmtSend(rmt, data, MAX_DATA_PER_ITTERATION);
145176
} else {
@@ -217,6 +248,7 @@ bool rmtReceiveAsync(rmt_obj_t* rmt, size_t idle_thres, uint32_t* data, size_t s
217248
rmt->remaining_to_send = size;
218249
}
219250

251+
RMT_MUTEX_LOCK(channel);
220252
rmt->intr_mode = e_rx_intr;
221253

222254
RMT.conf_ch[channel].conf1.mem_owner = 1;
@@ -231,6 +263,7 @@ bool rmtReceiveAsync(rmt_obj_t* rmt, size_t idle_thres, uint32_t* data, size_t s
231263
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
232264

233265
RMT.conf_ch[channel].conf1.rx_en = 1;
266+
RMT_MUTEX_UNLOCK(channel);
234267

235268
return true;
236269
}
@@ -253,9 +286,10 @@ bool rmtSend(rmt_obj_t* rmt, uint32_t* data, size_t size)
253286
RMTMEM.chan[channel].data32[size].val = 0;
254287
}
255288

289+
RMT_MUTEX_LOCK(channel);
256290
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
257-
258291
RMT.conf_ch[channel].conf1.tx_start = 1;
292+
RMT_MUTEX_UNLOCK(channel);
259293

260294
return true;
261295
}
@@ -292,7 +326,8 @@ float rmtSetTick(rmt_obj_t* rmt, float tick)
292326
float apb_tick = 12.5 * apb_div;
293327
float ref_tick = 1000.0 * ref_div;
294328

295-
size_t channel = rmt->channel;
329+
size_t channel = rmt->channel;
330+
296331
if (_ABS(apb_tick - tick) < _ABS(ref_tick - tick)) {
297332
RMT.conf_ch[channel].conf0.div_cnt = apb_div & 0xFF;
298333
RMT.conf_ch[channel].conf1.ref_always_on = 1;
@@ -310,6 +345,14 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, int entries, int period)
310345
rmt_obj_t* rmt;
311346
size_t i;
312347
size_t j;
348+
349+
// create common block mutex for protecting allocs from multiple threads
350+
if (!g_rmt_block_lock) {
351+
g_rmt_block_lock = xSemaphoreCreateMutex();
352+
}
353+
// lock
354+
while (xSemaphoreTake(g_rmt_block_lock, portMAX_DELAY) != pdPASS) {}
355+
313356
for (i=0; i<MAX_CHANNELS; i++) {
314357
for (j=0; j<buffers && i+j < MAX_CHANNELS; j++) {
315358
// if the space is ocupied break and continue on other channel
@@ -324,11 +367,26 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, int entries, int period)
324367
}
325368
}
326369
if (i == MAX_CHANNELS || i+j >= MAX_CHANNELS || j != buffers) {
370+
xSemaphoreGive(g_rmt_block_lock);
327371
return NULL;
328372
}
329373
rmt = _rmtAllocate(pin, i, buffers);
330374

375+
xSemaphoreGive(g_rmt_block_lock);
376+
331377
size_t channel = i;
378+
379+
#if !CONFIG_DISABLE_HAL_LOCKS
380+
if(g_rmt_objlocks[channel] == NULL) {
381+
g_rmt_objlocks[channel] = xSemaphoreCreateMutex();
382+
if(g_rmt_objlocks[channel] == NULL) {
383+
return NULL;
384+
}
385+
}
386+
#endif
387+
388+
RMT_MUTEX_LOCK(channel);
389+
332390
rmt->pin = pin;
333391
rmt->tx_not_rx = tx_not_rx;
334392
rmt->buffers =buffers;
@@ -367,6 +425,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, int entries, int period)
367425
if (!intr_handle) {
368426
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle);
369427
}
428+
RMT_MUTEX_UNLOCK(channel);
370429

371430
return rmt;
372431
}

0 commit comments

Comments
 (0)