summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--cc3200/FreeRTOS/FreeRTOSConfig.h8
-rw-r--r--cc3200/application.mk1
-rw-r--r--cc3200/hal/cc3200_hal.c2
-rw-r--r--cc3200/main.c12
-rw-r--r--cc3200/mpconfigport.h2
-rw-r--r--cc3200/mptask.c5
-rw-r--r--cc3200/mpthreadport.c171
-rw-r--r--cc3200/mpthreadport.h36
-rw-r--r--cc3200/util/gccollect.c6
9 files changed, 243 insertions, 0 deletions
diff --git a/cc3200/FreeRTOS/FreeRTOSConfig.h b/cc3200/FreeRTOS/FreeRTOSConfig.h
index 27ba880f62..abde289374 100644
--- a/cc3200/FreeRTOS/FreeRTOSConfig.h
+++ b/cc3200/FreeRTOS/FreeRTOSConfig.h
@@ -154,4 +154,12 @@ version. */
/* We provide a definition of ucHeap so it can go in a special segment. */
#define configAPPLICATION_ALLOCATED_HEAP 1
+/* For threading */
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1
+#define configSUPPORT_STATIC_ALLOCATION 1
+#undef configUSE_MUTEXES
+#define configUSE_MUTEXES 1
+#undef INCLUDE_vTaskDelete
+#define INCLUDE_vTaskDelete 1
+
#endif /* FREERTOS_CONFIG_H */
diff --git a/cc3200/application.mk b/cc3200/application.mk
index b862212a54..dca6fcbc65 100644
--- a/cc3200/application.mk
+++ b/cc3200/application.mk
@@ -142,6 +142,7 @@ APP_UTIL_SRC_S = $(addprefix util/,\
APP_MAIN_SRC_C = \
main.c \
mptask.c \
+ mpthreadport.c \
serverstask.c
APP_LIB_SRC_C = $(addprefix lib/,\
diff --git a/cc3200/hal/cc3200_hal.c b/cc3200/hal/cc3200_hal.c
index f0987ae9d2..f4d38d120e 100644
--- a/cc3200/hal/cc3200_hal.c
+++ b/cc3200/hal/cc3200_hal.c
@@ -111,6 +111,7 @@ mp_uint_t mp_hal_ticks_ms(void) {
void mp_hal_delay_ms(mp_uint_t delay) {
// only if we are not within interrupt context and interrupts are enabled
if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) {
+ MP_THREAD_GIL_EXIT();
#ifdef USE_FREERTOS
vTaskDelay (delay / portTICK_PERIOD_MS);
#else
@@ -121,6 +122,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
__WFI();
}
#endif
+ MP_THREAD_GIL_ENTER();
} else {
for (int ms = 0; ms < delay; ms++) {
UtilsDelay(UTILS_DELAY_US_TO_COUNT(1000));
diff --git a/cc3200/main.c b/cc3200/main.c
index 4a6f6172bf..2aed70f76b 100644
--- a/cc3200/main.c
+++ b/cc3200/main.c
@@ -98,3 +98,15 @@ void stoupper (char *str) {
str++;
}
}
+
+// We need this when configSUPPORT_STATIC_ALLOCATION is enabled
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
+ StackType_t **ppxIdleTaskStackBuffer,
+ uint32_t *pulIdleTaskStackSize ) {
+ static StaticTask_t xIdleTaskTCB;
+ static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
+
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
+}
diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h
index d3aacc082f..69114516a8 100644
--- a/cc3200/mpconfigport.h
+++ b/cc3200/mpconfigport.h
@@ -102,6 +102,8 @@
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (1)
#define MICROPY_PY_IO_FILEIO (1)
+#define MICROPY_PY_THREAD (1)
+#define MICROPY_PY_THREAD_GIL (0)
#define MICROPY_PY_UBINASCII (0)
#define MICROPY_PY_UCTYPES (0)
#define MICROPY_PY_UZLIB (0)
diff --git a/cc3200/mptask.c b/cc3200/mptask.c
index f8f33c2959..828263c4a1 100644
--- a/cc3200/mptask.c
+++ b/cc3200/mptask.c
@@ -116,6 +116,11 @@ void TASK_Micropython (void *pvParameters) {
soft_reset:
+ // Thread init
+ #if MICROPY_PY_THREAD
+ mp_thread_init();
+ #endif
+
// GC init
gc_init(&_boot, &_eheap);
diff --git a/cc3200/mpthreadport.c b/cc3200/mpthreadport.c
new file mode 100644
index 0000000000..7cc44d73dc
--- /dev/null
+++ b/cc3200/mpthreadport.c
@@ -0,0 +1,171 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "py/mpconfig.h"
+#include "py/mpstate.h"
+#include "py/gc.h"
+#include "py/mpthread.h"
+#include "task.h"
+
+#if MICROPY_PY_THREAD
+
+// this structure forms a linked list, one node per active thread
+typedef struct _thread_t {
+ TaskHandle_t id; // system id of thread
+ int ready; // whether the thread is ready and running
+ void *arg; // thread Python args, a GC root pointer
+ void *stack; // pointer to the stack
+ size_t stack_len; // number of words in the stack
+ struct _thread_t *next;
+} thread_t;
+
+// the mutex controls access to the linked list
+STATIC mp_thread_mutex_t thread_mutex;
+STATIC thread_t thread_entry0;
+STATIC thread_t *thread; // root pointer, handled bp mp_thread_gc_others
+
+void mp_thread_init(void) {
+ mp_thread_mutex_init(&thread_mutex);
+ mp_thread_set_state(&mp_state_ctx.thread);
+
+ // create first entry in linked list of all threads
+ thread = &thread_entry0;
+ thread->id = NULL; // TODO
+ thread->ready = 1;
+ thread->arg = NULL;
+ thread->next = NULL;
+}
+
+void mp_thread_gc_others(void) {
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ gc_collect_root((void**)&thread, 1);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ gc_collect_root(&th->arg, 1);
+ if (th->id == xTaskGetCurrentTaskHandle()) {
+ continue;
+ }
+ if (!th->ready) {
+ continue;
+ }
+ gc_collect_root(th->stack, th->stack_len);
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+mp_state_thread_t *mp_thread_get_state(void) {
+ return pvTaskGetThreadLocalStoragePointer(NULL, 0);
+}
+
+void mp_thread_set_state(void *state) {
+ vTaskSetThreadLocalStoragePointer(NULL, 0, state);
+}
+
+void mp_thread_start(void) {
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ if (th->id == xTaskGetCurrentTaskHandle()) {
+ th->ready = 1;
+ break;
+ }
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+STATIC void *(*ext_thread_entry)(void*) = NULL;
+
+STATIC void freertos_entry(void *arg) {
+ if (ext_thread_entry) {
+ ext_thread_entry(arg);
+ }
+ vTaskDelete(NULL);
+ for (;;) {
+ }
+}
+
+void mp_thread_create(void *(*entry)(void*), void *arg, size_t stack_size) {
+ // store thread entry function into a global variable so we can access it
+ ext_thread_entry = entry;
+
+ if (stack_size == 0) {
+ stack_size = 2048; // default stack size
+ }
+
+ mp_thread_mutex_lock(&thread_mutex, 1);
+
+ // create thread
+ StackType_t *stack = m_new(StackType_t, stack_size / sizeof(StackType_t));
+ StaticTask_t *task_buf = m_new(StaticTask_t, 1);
+ TaskHandle_t id = xTaskCreateStatic(freertos_entry, "Thread", stack_size / sizeof(void*), arg, 2, stack, task_buf);
+ if (id == NULL) {
+ mp_thread_mutex_unlock(&thread_mutex);
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, "can't create thread"));
+ }
+
+ // add thread to linked list of all threads
+ thread_t *th = m_new_obj(thread_t);
+ th->id = id;
+ th->ready = 0;
+ th->arg = arg;
+ th->stack = stack;
+ th->stack_len = stack_size / sizeof(StackType_t);
+ th->next = thread;
+ thread = th;
+
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+void mp_thread_finish(void) {
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ // TODO unlink from list
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ if (th->id == xTaskGetCurrentTaskHandle()) {
+ th->ready = 0;
+ break;
+ }
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
+ *mutex = xSemaphoreCreateMutex();
+ if (*mutex == NULL) {
+ // error!
+ }
+}
+
+int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
+ int ret = xSemaphoreTake(*mutex, wait ? portMAX_DELAY : 0);
+ return ret == pdTRUE;
+}
+
+void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
+ xSemaphoreGive(*mutex);
+ // TODO check return value
+}
+
+#endif // MICROPY_PY_THREAD
diff --git a/cc3200/mpthreadport.h b/cc3200/mpthreadport.h
new file mode 100644
index 0000000000..83995915eb
--- /dev/null
+++ b/cc3200/mpthreadport.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef __MICROPY_INCLUDED_CC3200_MPTHREADPORT_H__
+#define __MICROPY_INCLUDED_CC3200_MPTHREADPORT_H__
+
+#include "FreeRTOS.h"
+
+typedef SemaphoreHandle_t mp_thread_mutex_t;
+
+void mp_thread_init(void);
+void mp_thread_gc_others(void);
+
+#endif // __MICROPY_INCLUDED_CC3200_MPTHREADPORT_H__
diff --git a/cc3200/util/gccollect.c b/cc3200/util/gccollect.c
index 094ca73bc6..bc9cba4b8d 100644
--- a/cc3200/util/gccollect.c
+++ b/cc3200/util/gccollect.c
@@ -30,6 +30,7 @@
#include "py/mpconfig.h"
#include "py/gc.h"
+#include "py/mpthread.h"
#include "gccollect.h"
#include "gchelper.h"
@@ -57,6 +58,11 @@ void gc_collect(void) {
// trace the stack, including the registers (since they live on the stack in this function)
gc_collect_root((void**)sp, (stackend - sp) / sizeof(uint32_t));
+ // trace root pointers from any threads
+ #if MICROPY_PY_THREAD
+ mp_thread_gc_others();
+ #endif
+
// end the GC
gc_collect_end();
}