Skip to content

Commit ff0ca1e

Browse files
Daniel Camporadpgeorge
authored andcommitted
esp32: Enable threading; be sure to exit GIL when a thread will block.
1 parent f704375 commit ff0ca1e

File tree

5 files changed

+61
-8
lines changed

5 files changed

+61
-8
lines changed

esp32/main.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "esp_system.h"
3535
#include "nvs_flash.h"
3636
#include "esp_task.h"
37+
#include "soc/cpu.h"
3738

3839
#include "py/stackctrl.h"
3940
#include "py/nlr.h"
@@ -46,22 +47,29 @@
4647
#include "lib/utils/pyexec.h"
4748
#include "uart.h"
4849
#include "modmachine.h"
50+
#include "mpthreadport.h"
4951

5052
// MicroPython runs as a task under FreeRTOS
5153
#define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1)
5254
#define MP_TASK_STACK_SIZE (16 * 1024)
5355
#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t))
5456
#define MP_TASK_HEAP_SIZE (96 * 1024)
5557

56-
//STATIC StaticTask_t mp_task_tcb;
57-
//STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8)));
58+
STATIC StaticTask_t mp_task_tcb;
59+
STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8)));
5860
STATIC uint8_t mp_task_heap[MP_TASK_HEAP_SIZE];
5961

6062
void mp_task(void *pvParameter) {
63+
volatile uint32_t sp = (uint32_t)get_sp();
64+
#if MICROPY_PY_THREAD
65+
mp_thread_init(&mp_task_stack[0], MP_TASK_STACK_LEN);
66+
#endif
6167
uart_init();
68+
6269
soft_reset:
63-
mp_stack_set_top((void*)&pvParameter);
64-
mp_stack_set_limit(MP_TASK_STACK_SIZE - 512);
70+
// initialise the stack pointer for the main thread
71+
mp_stack_set_top((void *)sp);
72+
mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024);
6573
gc_init(mp_task_heap, mp_task_heap + sizeof(mp_task_heap));
6674
mp_init();
6775
mp_obj_list_init(mp_sys_path, 0);
@@ -92,6 +100,10 @@ void mp_task(void *pvParameter) {
92100
}
93101
}
94102

103+
#if MICROPY_PY_THREAD
104+
mp_thread_deinit();
105+
#endif
106+
95107
mp_hal_stdout_tx_str("PYB: soft reboot\r\n");
96108

97109
// deinitialise peripherals
@@ -104,9 +116,8 @@ void mp_task(void *pvParameter) {
104116

105117
void app_main(void) {
106118
nvs_flash_init();
107-
// TODO use xTaskCreateStatic (needs custom FreeRTOSConfig.h)
108-
xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, NULL, 0);
109-
//xTaskCreateStatic(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_task_stack[0], &mp_task_tcb);
119+
xTaskCreateStaticPinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY,
120+
&mp_task_stack[0], &mp_task_tcb, 0);
110121
}
111122

112123
void nlr_jump_fail(void *val) {

esp32/modnetwork.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) {
241241
memcpy(wifi_sta_config.sta.password, p, MIN(len, sizeof(wifi_sta_config.sta.password)));
242242
ESP_EXCEPTIONS( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config) );
243243
}
244+
MP_THREAD_GIL_EXIT();
244245
ESP_EXCEPTIONS( esp_wifi_connect() );
246+
MP_THREAD_GIL_ENTER();
245247
wifi_sta_connected = true;
246248

247249
return mp_const_none;
@@ -274,7 +276,9 @@ STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
274276
mp_obj_t list = mp_obj_new_list(0, NULL);
275277
wifi_scan_config_t config = { 0 };
276278
// XXX how do we scan hidden APs (and if we can scan them, are they really hidden?)
279+
MP_THREAD_GIL_EXIT();
277280
esp_err_t status = esp_wifi_scan_start(&config, 1);
281+
MP_THREAD_GIL_ENTER();
278282
if (status == 0) {
279283
uint16_t count = 0;
280284
ESP_EXCEPTIONS( esp_wifi_scan_get_ap_num(&count) );

esp32/modsocket.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,11 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc
112112
const char *host_str = mp_obj_str_get_data(host, &host_len);
113113
const char *port_str = mp_obj_str_get_data(port, &port_len);
114114

115-
return lwip_getaddrinfo(host_str, port_str, &hints, resp);
115+
MP_THREAD_GIL_EXIT();
116+
int res = lwip_getaddrinfo(host_str, port_str, &hints, resp);
117+
MP_THREAD_GIL_ENTER();
118+
119+
return res;
116120
}
117121

118122
int _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) {
@@ -151,7 +155,9 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) {
151155

152156
int new_fd = -1;
153157
for (int i=0; i<=self->retries; i++) {
158+
MP_THREAD_GIL_EXIT();
154159
new_fd = lwip_accept_r(self->fd, &addr, &addr_len);
160+
MP_THREAD_GIL_ENTER();
155161
if (new_fd >= 0) break;
156162
if (errno != EAGAIN) exception_from_errno(errno);
157163
check_for_exceptions();
@@ -182,7 +188,9 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
182188
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
183189
struct addrinfo *res;
184190
_socket_getaddrinfo(arg1, &res);
191+
MP_THREAD_GIL_EXIT();
185192
int r = lwip_connect_r(self->fd, res->ai_addr, res->ai_addrlen);
193+
MP_THREAD_GIL_ENTER();
186194
lwip_freeaddrinfo(res);
187195
if (r != 0) {
188196
exception_from_errno(errno);
@@ -255,7 +263,9 @@ mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in,
255263

256264
// XXX Would be nicer to use RTC to handle timeouts
257265
for (int i=0; i<=sock->retries; i++) {
266+
MP_THREAD_GIL_EXIT();
258267
int r = lwip_recvfrom_r(sock->fd, vstr.buf, len, 0, from, from_len);
268+
MP_THREAD_GIL_ENTER();
259269
if (r >= 0) { vstr.len = r; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
260270
if (errno != EWOULDBLOCK) exception_from_errno(errno);
261271
check_for_exceptions();
@@ -286,7 +296,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
286296
int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) {
287297
int sentlen = 0;
288298
for (int i=0; i<sock->retries && sentlen < datalen; i++) {
299+
MP_THREAD_GIL_EXIT();
289300
int r = lwip_write_r(sock->fd, data+sentlen, datalen-sentlen);
301+
MP_THREAD_GIL_ENTER();
290302
if (r < 0 && errno != EWOULDBLOCK) exception_from_errno(errno);
291303
if (r > 0) sentlen += r;
292304
check_for_exceptions();
@@ -331,7 +343,9 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
331343

332344
// send the data
333345
for (int i=0; i<self->retries; i++) {
346+
MP_THREAD_GIL_EXIT();
334347
int ret = lwip_sendto_r(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to));
348+
MP_THREAD_GIL_ENTER();
335349
if (ret > 0) return mp_obj_new_int_from_uint(ret);
336350
if (ret == -1 && errno != EWOULDBLOCK) {
337351
exception_from_errno(errno);
@@ -364,7 +378,9 @@ STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size,
364378

365379
// XXX Would be nicer to use RTC to handle timeouts
366380
for (int i=0; i<=sock->retries; i++) {
381+
MP_THREAD_GIL_EXIT();
367382
int x = lwip_recvfrom_r(sock->fd, buf, size, 0, NULL, NULL);
383+
MP_THREAD_GIL_ENTER();
368384
if (x >= 0) return x;
369385
if (x < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; }
370386
check_for_exceptions();
@@ -375,7 +391,9 @@ STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size,
375391
STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
376392
socket_obj_t *sock = self_in;
377393
for (int i=0; i<sock->retries; i++) {
394+
MP_THREAD_GIL_EXIT();
378395
int r = lwip_write_r(sock->fd, buf, size);
396+
MP_THREAD_GIL_ENTER();
379397
if (r > 0) return r;
380398
if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; }
381399
check_for_exceptions();

esp32/mpconfigport.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@
108108
#define MICROPY_PY_UERRNO (1)
109109
#define MICROPY_PY_USELECT (1)
110110
#define MICROPY_PY_UTIME_MP_HAL (1)
111+
#define MICROPY_PY_THREAD (1)
112+
#define MICROPY_PY_THREAD_GIL (1)
113+
#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32)
111114

112115
// extended modules
113116
#define MICROPY_PY_UCTYPES (1)
@@ -202,12 +205,23 @@ extern const struct _mp_obj_module_t mp_module_network;
202205
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p)))
203206
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
204207
#define MP_SSIZE_MAX (0x7fffffff)
208+
209+
#if MICROPY_PY_THREAD
210+
#define MICROPY_EVENT_POLL_HOOK \
211+
do { \
212+
extern void mp_handle_pending(void); \
213+
mp_handle_pending(); \
214+
MP_THREAD_GIL_EXIT(); \
215+
MP_THREAD_GIL_ENTER(); \
216+
} while (0);
217+
#else
205218
#define MICROPY_EVENT_POLL_HOOK \
206219
do { \
207220
extern void mp_handle_pending(void); \
208221
mp_handle_pending(); \
209222
asm("waiti 0"); \
210223
} while (0);
224+
#endif
211225

212226
#define UINT_FMT "%u"
213227
#define INT_FMT "%d"

esp32/mphalport.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,30 @@ void mp_hal_stdout_tx_char(char c) {
5959
}
6060

6161
void mp_hal_stdout_tx_str(const char *str) {
62+
MP_THREAD_GIL_EXIT();
6263
while (*str) {
6364
mp_hal_stdout_tx_char(*str++);
6465
}
66+
MP_THREAD_GIL_ENTER();
6567
}
6668

6769
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
70+
MP_THREAD_GIL_EXIT();
6871
while (len--) {
6972
mp_hal_stdout_tx_char(*str++);
7073
}
74+
MP_THREAD_GIL_ENTER();
7175
}
7276

7377
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
78+
MP_THREAD_GIL_EXIT();
7479
while (len--) {
7580
if (*str == '\n') {
7681
mp_hal_stdout_tx_char('\r');
7782
}
7883
mp_hal_stdout_tx_char(*str++);
7984
}
85+
MP_THREAD_GIL_ENTER();
8086
}
8187

8288
uint32_t mp_hal_ticks_ms(void) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy