Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 86da8097 authored by Daniel Campora's avatar Daniel Campora
Browse files

esp32: Fix asserts caused by mutex memory being in pSRAM.

Also implement empty() and full() methods for the Queue class.
parent a2d50d6e
No related branches found
No related tags found
No related merge requests found
...@@ -36,19 +36,23 @@ STATIC mp_obj_t mod_uqueue_queue(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ ...@@ -36,19 +36,23 @@ STATIC mp_obj_t mod_uqueue_queue(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[0].u_int <= 0) { if (args[0].u_int <= 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Queue size cannot be infinite")); nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "queue size cannot be infinite"));
} }
int32_t maxsize = args[0].u_int; int32_t maxsize = args[0].u_int;
// allocate the queue storage and the queue buffer
StaticQueue_t *xQueueBuffer = m_new(StaticQueue_t, 1);
mp_obj_t *storage = m_new(mp_obj_t, maxsize);
// create the queue object // create the queue object
mp_obj_queue_t *queue = m_new_obj_with_finaliser(mp_obj_queue_t); mp_obj_queue_t *queue = m_new_obj_with_finaliser(mp_obj_queue_t);
// allocate the queue storage and the queue buffer
queue->buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (NULL == queue->buffer) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, "no memory available to create the queue"));
}
queue->storage = m_new(mp_obj_t, maxsize);
queue->base.type = &mp_queue_type; queue->base.type = &mp_queue_type;
queue->maxsize = maxsize; queue->maxsize = maxsize;
queue->handle = xQueueCreateStatic(maxsize, sizeof(mp_obj_t), (uint8_t *)storage, xQueueBuffer); queue->handle = xQueueCreateStatic(maxsize, sizeof(mp_obj_t), (uint8_t *)queue->storage, queue->buffer);
return queue; return queue;
} }
...@@ -66,6 +70,15 @@ const mp_obj_module_t mp_module_uqueue = { ...@@ -66,6 +70,15 @@ const mp_obj_module_t mp_module_uqueue = {
.globals = (mp_obj_dict_t*)&mp_module_uqueue_globals, .globals = (mp_obj_dict_t*)&mp_module_uqueue_globals,
}; };
STATIC mp_obj_t mp_queue_delete(mp_obj_t self_in) {
mp_obj_queue_t *self = self_in;
if (self->buffer) {
free(self->buffer);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_queue_delete_obj, mp_queue_delete);
STATIC mp_obj_t mp_queue_put(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC mp_obj_t mp_queue_put(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_item, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_item, MP_ARG_REQUIRED | MP_ARG_OBJ, },
...@@ -108,11 +121,32 @@ STATIC mp_obj_t mp_queue_get(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_ ...@@ -108,11 +121,32 @@ STATIC mp_obj_t mp_queue_get(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_queue_get_obj, 1, mp_queue_get); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_queue_get_obj, 1, mp_queue_get);
STATIC mp_obj_t mp_queue_empty(mp_obj_t self_in) {
mp_obj_queue_t *self = self_in;
mp_obj_t buffer;
if (xQueuePeek(self->handle, &buffer, 0)) {
return mp_const_false;
}
return mp_const_true;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_queue_empty_obj, mp_queue_empty);
STATIC mp_obj_t mp_queue_full(mp_obj_t self_in) {
mp_obj_queue_t *self = self_in;
if (uxQueueSpacesAvailable(self->handle) > 0) {
return mp_const_false;
}
return mp_const_true;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_queue_full_obj, mp_queue_full);
STATIC const mp_map_elem_t queue_locals_dict_table[] = { STATIC const mp_map_elem_t queue_locals_dict_table[] = {
// instance methods // instance methods
// { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&mp_queue_delete_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&mp_queue_delete_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_put), (mp_obj_t)&mp_queue_put_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_put), (mp_obj_t)&mp_queue_put_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get), (mp_obj_t)&mp_queue_get_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_get), (mp_obj_t)&mp_queue_get_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_empty), (mp_obj_t)&mp_queue_empty_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_full), (mp_obj_t)&mp_queue_full_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Full), (mp_obj_t)&mp_type_OSError }, { MP_OBJ_NEW_QSTR(MP_QSTR_Full), (mp_obj_t)&mp_type_OSError },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Empty), (mp_obj_t)&mp_type_OSError }, { MP_OBJ_NEW_QSTR(MP_QSTR_Empty), (mp_obj_t)&mp_type_OSError },
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
******************************************************************************/ ******************************************************************************/
typedef struct _mp_obj_queue_t { typedef struct _mp_obj_queue_t {
mp_obj_base_t base; mp_obj_base_t base;
mp_obj_t storage;
StaticQueue_t *buffer;
QueueHandle_t handle; QueueHandle_t handle;
uint32_t maxsize; uint32_t maxsize;
} mp_obj_queue_t; } mp_obj_queue_t;
......
...@@ -151,8 +151,17 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i ...@@ -151,8 +151,17 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i
if (esp_get_revision() > 0) { if (esp_get_revision() > 0) {
// for revision 1 devices we allocate from the internal memory of the malloc heap // for revision 1 devices we allocate from the internal memory of the malloc heap
tcb = heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); tcb = heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (!tcb) {
goto memory_error;
}
stack = heap_caps_malloc(*stack_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); stack = heap_caps_malloc(*stack_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (!stack) {
goto memory_error;
}
th = heap_caps_malloc(sizeof(thread_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); th = heap_caps_malloc(sizeof(thread_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (!th) {
goto memory_error;
}
} else { } else {
// for revision 0 devices we allocate from the MicroPython heap which is all in the internal memory // for revision 0 devices we allocate from the MicroPython heap which is all in the internal memory
tcb = m_new(StaticTask_t, 1); tcb = m_new(StaticTask_t, 1);
...@@ -183,6 +192,11 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i ...@@ -183,6 +192,11 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i
thread = th; thread = th;
mp_thread_mutex_unlock(&thread_mutex); mp_thread_mutex_unlock(&thread_mutex);
return;
memory_error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, "can't create thread"));
} }
void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
...@@ -228,6 +242,17 @@ void vPortCleanUpTCB (void *tcb) { ...@@ -228,6 +242,17 @@ void vPortCleanUpTCB (void *tcb) {
mp_thread_mutex_unlock(&thread_mutex); mp_thread_mutex_unlock(&thread_mutex);
} }
mp_obj_thread_lock_t *mp_thread_new_thread_lock(void) {
mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t);
self->mutex = heap_caps_malloc(sizeof(mp_thread_mutex_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (NULL == self->mutex) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, "can't create lock"));
}
mp_thread_mutex_init(self->mutex);
self->locked = false;
return self;
}
void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer); mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer);
} }
......
...@@ -38,22 +38,28 @@ ...@@ -38,22 +38,28 @@
#ifndef __MICROPY_INCLUDED_ESP32_MPTHREADPORT_H__ #ifndef __MICROPY_INCLUDED_ESP32_MPTHREADPORT_H__
#define __MICROPY_INCLUDED_ESP32_MPTHREADPORT_H__ #define __MICROPY_INCLUDED_ESP32_MPTHREADPORT_H__
#ifndef BOOTLOADER #include "py/mpconfig.h"
#include "py/mpstate.h"
#include "py/obj.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#endif
#define MP_THREAD_PRIORITY 5 #define MP_THREAD_PRIORITY 5
typedef struct _mp_thread_mutex_t { typedef struct _mp_thread_mutex_t {
#ifndef BOOTLOADER
SemaphoreHandle_t handle; SemaphoreHandle_t handle;
StaticSemaphore_t buffer; StaticSemaphore_t buffer;
#endif
} mp_thread_mutex_t; } mp_thread_mutex_t;
typedef struct _mp_obj_thread_lock_t {
mp_obj_base_t base;
mp_thread_mutex_t *mutex;
volatile bool locked;
} mp_obj_thread_lock_t;
void mp_thread_preinit(void *stack); void mp_thread_preinit(void *stack);
void mp_thread_init(void); void mp_thread_init(void);
void mp_thread_gc_others(void); void mp_thread_gc_others(void);
void mp_thread_deinit(void); void mp_thread_deinit(void);
mp_obj_thread_lock_t *mp_thread_new_thread_lock(void);
#endif // __MICROPY_INCLUDED_ESP32_MPTHREADPORT_H__ #endif // __MICROPY_INCLUDED_ESP32_MPTHREADPORT_H__
...@@ -47,19 +47,14 @@ ...@@ -47,19 +47,14 @@
STATIC const mp_obj_type_t mp_type_thread_lock; STATIC const mp_obj_type_t mp_type_thread_lock;
typedef struct _mp_obj_thread_lock_t { STATIC mp_obj_t thread_lock_delete(mp_obj_t self_in) {
mp_obj_base_t base; mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in);
mp_thread_mutex_t mutex; if (self->mutex) {
volatile bool locked; free(self->mutex);
} mp_obj_thread_lock_t; }
return mp_const_none;
STATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) {
mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t);
self->base.type = &mp_type_thread_lock;
mp_thread_mutex_init(&self->mutex);
self->locked = false;
return self;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_delete_obj, thread_lock_delete);
STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) {
mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(args[0]);
...@@ -69,7 +64,7 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) { ...@@ -69,7 +64,7 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) {
// TODO support timeout arg // TODO support timeout arg
} }
MP_THREAD_GIL_EXIT(); MP_THREAD_GIL_EXIT();
int ret = mp_thread_mutex_lock(&self->mutex, wait); int ret = mp_thread_mutex_lock(self->mutex, wait);
MP_THREAD_GIL_ENTER(); MP_THREAD_GIL_ENTER();
if (ret == 0) { if (ret == 0) {
return mp_const_false; return mp_const_false;
...@@ -87,7 +82,7 @@ STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) { ...@@ -87,7 +82,7 @@ STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) {
// TODO check if already unlocked // TODO check if already unlocked
self->locked = false; self->locked = false;
MP_THREAD_GIL_EXIT(); MP_THREAD_GIL_EXIT();
mp_thread_mutex_unlock(&self->mutex); mp_thread_mutex_unlock(self->mutex);
MP_THREAD_GIL_ENTER(); MP_THREAD_GIL_ENTER();
return mp_const_none; return mp_const_none;
} }
...@@ -106,6 +101,7 @@ STATIC mp_obj_t thread_lock___exit__(size_t n_args, const mp_obj_t *args) { ...@@ -106,6 +101,7 @@ STATIC mp_obj_t thread_lock___exit__(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock___exit___obj, 4, 4, thread_lock___exit__); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock___exit___obj, 4, 4, thread_lock___exit__);
STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&thread_lock_delete_obj) },
{ MP_ROM_QSTR(MP_QSTR_acquire), MP_ROM_PTR(&thread_lock_acquire_obj) }, { MP_ROM_QSTR(MP_QSTR_acquire), MP_ROM_PTR(&thread_lock_acquire_obj) },
{ MP_ROM_QSTR(MP_QSTR_release), MP_ROM_PTR(&thread_lock_release_obj) }, { MP_ROM_QSTR(MP_QSTR_release), MP_ROM_PTR(&thread_lock_release_obj) },
{ MP_ROM_QSTR(MP_QSTR_locked), MP_ROM_PTR(&thread_lock_locked_obj) }, { MP_ROM_QSTR(MP_QSTR_locked), MP_ROM_PTR(&thread_lock_locked_obj) },
...@@ -266,7 +262,9 @@ STATIC mp_obj_t mod_thread_exit(void) { ...@@ -266,7 +262,9 @@ STATIC mp_obj_t mod_thread_exit(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit); STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit);
STATIC mp_obj_t mod_thread_allocate_lock(void) { STATIC mp_obj_t mod_thread_allocate_lock(void) {
return MP_OBJ_FROM_PTR(mp_obj_new_thread_lock()); mp_obj_thread_lock_t *self = mp_thread_new_thread_lock();
self->base.type = &mp_type_thread_lock;
return MP_OBJ_FROM_PTR(self);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_allocate_lock_obj, mod_thread_allocate_lock); STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_allocate_lock_obj, mod_thread_allocate_lock);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment