1
1
#include "freertos/FreeRTOS.h"
2
2
#include "freertos/event_groups.h"
3
+ #include "freertos/semphr.h"
3
4
4
5
#include "esp32-hal.h"
5
6
#include "esp8266-compat.h"
28
29
#define _INT_ERROR (channel ) (__INT_ERROR<<(channel*3))
29
30
#define _INT_THR_EVNT (channel ) ((__INT_THR_EVNT)<<(channel))
30
31
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
+
31
40
typedef enum {
32
41
e_no_intr = 0 ,
33
42
e_tx_intr = 1 ,
@@ -58,15 +67,28 @@ struct rmt_obj_s
58
67
transaction_state_t tx_state ;
59
68
};
60
69
70
+ static xSemaphoreHandle g_rmt_objlocks [MAX_CHANNELS ] = {
71
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL
72
+ };
73
+
61
74
static rmt_obj_t g_rmt_objects [MAX_CHANNELS ] = {
62
75
{ false, NULL , 0 , 0 , 0 , 0 , 0 , NULL , e_no_intr , e_inactive },
63
76
{ 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 },
64
83
};
65
84
66
85
static intr_handle_t intr_handle ;
67
86
68
87
static bool periph_enabled = false;
69
88
89
+ static xSemaphoreHandle g_rmt_block_lock = NULL ;
90
+
91
+
70
92
static void _initPin (int pin , int channel , bool tx_not_rx );
71
93
72
94
static void IRAM_ATTR _rmt_isr (void * arg );
@@ -84,6 +106,13 @@ bool rmtDeinit(rmt_obj_t *rmt)
84
106
}
85
107
86
108
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
+
87
116
size_t to = rmt -> buffers + rmt -> channel ;
88
117
size_t i ;
89
118
@@ -106,13 +135,13 @@ bool rmtSendQueued(rmt_obj_t* rmt, uint32_t* data, size_t size)
106
135
107
136
if (size > MAX_DATA_PER_ITTERATION ) {
108
137
// if (size > MAX_DATA_PER_CHANNEL) {
109
-
138
+ int half_tx_nr = MAX_DATA_PER_ITTERATION /2 ;
139
+ RMT_MUTEX_LOCK (channel );
110
140
// setup interrupt handler if not yet installed for half and full tx
111
141
if (!intr_handle ) {
112
142
esp_intr_alloc (ETS_RMT_INTR_SOURCE , (int )ESP_INTR_FLAG_IRAM , _rmt_isr , NULL , & intr_handle );
113
143
}
114
144
115
- int half_tx_nr = MAX_DATA_PER_ITTERATION /2 ;
116
145
rmt -> remaining_to_send = size - MAX_DATA_PER_ITTERATION ;
117
146
rmt -> remaining_ptr = data + MAX_DATA_PER_ITTERATION ;
118
147
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)
140
169
RMT .int_ena .val |= _INT_THR_EVNT (channel );
141
170
RMT .int_ena .val |= _INT_ERROR (channel );
142
171
172
+ RMT_MUTEX_UNLOCK (channel );
173
+
143
174
// start the transation
144
175
return rmtSend (rmt , data , MAX_DATA_PER_ITTERATION );
145
176
} else {
@@ -217,6 +248,7 @@ bool rmtReceiveAsync(rmt_obj_t* rmt, size_t idle_thres, uint32_t* data, size_t s
217
248
rmt -> remaining_to_send = size ;
218
249
}
219
250
251
+ RMT_MUTEX_LOCK (channel );
220
252
rmt -> intr_mode = e_rx_intr ;
221
253
222
254
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
231
263
RMT .conf_ch [channel ].conf1 .mem_wr_rst = 1 ;
232
264
233
265
RMT .conf_ch [channel ].conf1 .rx_en = 1 ;
266
+ RMT_MUTEX_UNLOCK (channel );
234
267
235
268
return true;
236
269
}
@@ -253,9 +286,10 @@ bool rmtSend(rmt_obj_t* rmt, uint32_t* data, size_t size)
253
286
RMTMEM .chan [channel ].data32 [size ].val = 0 ;
254
287
}
255
288
289
+ RMT_MUTEX_LOCK (channel );
256
290
RMT .conf_ch [channel ].conf1 .mem_rd_rst = 1 ;
257
-
258
291
RMT .conf_ch [channel ].conf1 .tx_start = 1 ;
292
+ RMT_MUTEX_UNLOCK (channel );
259
293
260
294
return true;
261
295
}
@@ -292,7 +326,8 @@ float rmtSetTick(rmt_obj_t* rmt, float tick)
292
326
float apb_tick = 12.5 * apb_div ;
293
327
float ref_tick = 1000.0 * ref_div ;
294
328
295
- size_t channel = rmt -> channel ;
329
+ size_t channel = rmt -> channel ;
330
+
296
331
if (_ABS (apb_tick - tick ) < _ABS (ref_tick - tick )) {
297
332
RMT .conf_ch [channel ].conf0 .div_cnt = apb_div & 0xFF ;
298
333
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)
310
345
rmt_obj_t * rmt ;
311
346
size_t i ;
312
347
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
+
313
356
for (i = 0 ; i < MAX_CHANNELS ; i ++ ) {
314
357
for (j = 0 ; j < buffers && i + j < MAX_CHANNELS ; j ++ ) {
315
358
// 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)
324
367
}
325
368
}
326
369
if (i == MAX_CHANNELS || i + j >= MAX_CHANNELS || j != buffers ) {
370
+ xSemaphoreGive (g_rmt_block_lock );
327
371
return NULL ;
328
372
}
329
373
rmt = _rmtAllocate (pin , i , buffers );
330
374
375
+ xSemaphoreGive (g_rmt_block_lock );
376
+
331
377
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
+
332
390
rmt -> pin = pin ;
333
391
rmt -> tx_not_rx = tx_not_rx ;
334
392
rmt -> buffers = buffers ;
@@ -367,6 +425,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, int entries, int period)
367
425
if (!intr_handle ) {
368
426
esp_intr_alloc (ETS_RMT_INTR_SOURCE , (int )ESP_INTR_FLAG_IRAM , _rmt_isr , NULL , & intr_handle );
369
427
}
428
+ RMT_MUTEX_UNLOCK (channel );
370
429
371
430
return rmt ;
372
431
}
0 commit comments