Skip to content

Commit eef4f13

Browse files
committed
cc3200: Add basic threading capabilities.
Can create a new thread and run it. Does not use the GIL at this point.
1 parent 9b1c126 commit eef4f13

9 files changed

Lines changed: 243 additions & 0 deletions

File tree

cc3200/FreeRTOS/FreeRTOSConfig.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,12 @@ version. */
154154
/* We provide a definition of ucHeap so it can go in a special segment. */
155155
#define configAPPLICATION_ALLOCATED_HEAP 1
156156

157+
/* For threading */
158+
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1
159+
#define configSUPPORT_STATIC_ALLOCATION 1
160+
#undef configUSE_MUTEXES
161+
#define configUSE_MUTEXES 1
162+
#undef INCLUDE_vTaskDelete
163+
#define INCLUDE_vTaskDelete 1
164+
157165
#endif /* FREERTOS_CONFIG_H */

cc3200/application.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ APP_UTIL_SRC_S = $(addprefix util/,\
142142
APP_MAIN_SRC_C = \
143143
main.c \
144144
mptask.c \
145+
mpthreadport.c \
145146
serverstask.c
146147

147148
APP_LIB_SRC_C = $(addprefix lib/,\

cc3200/hal/cc3200_hal.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ mp_uint_t mp_hal_ticks_ms(void) {
111111
void mp_hal_delay_ms(mp_uint_t delay) {
112112
// only if we are not within interrupt context and interrupts are enabled
113113
if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) {
114+
MP_THREAD_GIL_EXIT();
114115
#ifdef USE_FREERTOS
115116
vTaskDelay (delay / portTICK_PERIOD_MS);
116117
#else
@@ -121,6 +122,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
121122
__WFI();
122123
}
123124
#endif
125+
MP_THREAD_GIL_ENTER();
124126
} else {
125127
for (int ms = 0; ms < delay; ms++) {
126128
UtilsDelay(UTILS_DELAY_US_TO_COUNT(1000));

cc3200/main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,15 @@ void stoupper (char *str) {
9898
str++;
9999
}
100100
}
101+
102+
// We need this when configSUPPORT_STATIC_ALLOCATION is enabled
103+
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
104+
StackType_t **ppxIdleTaskStackBuffer,
105+
uint32_t *pulIdleTaskStackSize ) {
106+
static StaticTask_t xIdleTaskTCB;
107+
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
108+
109+
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
110+
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
111+
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
112+
}

cc3200/mpconfigport.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@
102102
#define MICROPY_PY_CMATH (0)
103103
#define MICROPY_PY_IO (1)
104104
#define MICROPY_PY_IO_FILEIO (1)
105+
#define MICROPY_PY_THREAD (1)
106+
#define MICROPY_PY_THREAD_GIL (0)
105107
#define MICROPY_PY_UBINASCII (0)
106108
#define MICROPY_PY_UCTYPES (0)
107109
#define MICROPY_PY_UZLIB (0)

cc3200/mptask.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ void TASK_Micropython (void *pvParameters) {
116116

117117
soft_reset:
118118

119+
// Thread init
120+
#if MICROPY_PY_THREAD
121+
mp_thread_init();
122+
#endif
123+
119124
// GC init
120125
gc_init(&_boot, &_eheap);
121126

cc3200/mpthreadport.c

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stdio.h>
28+
29+
#include "py/mpconfig.h"
30+
#include "py/mpstate.h"
31+
#include "py/gc.h"
32+
#include "py/mpthread.h"
33+
#include "task.h"
34+
35+
#if MICROPY_PY_THREAD
36+
37+
// this structure forms a linked list, one node per active thread
38+
typedef struct _thread_t {
39+
TaskHandle_t id; // system id of thread
40+
int ready; // whether the thread is ready and running
41+
void *arg; // thread Python args, a GC root pointer
42+
void *stack; // pointer to the stack
43+
size_t stack_len; // number of words in the stack
44+
struct _thread_t *next;
45+
} thread_t;
46+
47+
// the mutex controls access to the linked list
48+
STATIC mp_thread_mutex_t thread_mutex;
49+
STATIC thread_t thread_entry0;
50+
STATIC thread_t *thread; // root pointer, handled bp mp_thread_gc_others
51+
52+
void mp_thread_init(void) {
53+
mp_thread_mutex_init(&thread_mutex);
54+
mp_thread_set_state(&mp_state_ctx.thread);
55+
56+
// create first entry in linked list of all threads
57+
thread = &thread_entry0;
58+
thread->id = NULL; // TODO
59+
thread->ready = 1;
60+
thread->arg = NULL;
61+
thread->next = NULL;
62+
}
63+
64+
void mp_thread_gc_others(void) {
65+
mp_thread_mutex_lock(&thread_mutex, 1);
66+
gc_collect_root((void**)&thread, 1);
67+
for (thread_t *th = thread; th != NULL; th = th->next) {
68+
gc_collect_root(&th->arg, 1);
69+
if (th->id == xTaskGetCurrentTaskHandle()) {
70+
continue;
71+
}
72+
if (!th->ready) {
73+
continue;
74+
}
75+
gc_collect_root(th->stack, th->stack_len);
76+
}
77+
mp_thread_mutex_unlock(&thread_mutex);
78+
}
79+
80+
mp_state_thread_t *mp_thread_get_state(void) {
81+
return pvTaskGetThreadLocalStoragePointer(NULL, 0);
82+
}
83+
84+
void mp_thread_set_state(void *state) {
85+
vTaskSetThreadLocalStoragePointer(NULL, 0, state);
86+
}
87+
88+
void mp_thread_start(void) {
89+
mp_thread_mutex_lock(&thread_mutex, 1);
90+
for (thread_t *th = thread; th != NULL; th = th->next) {
91+
if (th->id == xTaskGetCurrentTaskHandle()) {
92+
th->ready = 1;
93+
break;
94+
}
95+
}
96+
mp_thread_mutex_unlock(&thread_mutex);
97+
}
98+
99+
STATIC void *(*ext_thread_entry)(void*) = NULL;
100+
101+
STATIC void freertos_entry(void *arg) {
102+
if (ext_thread_entry) {
103+
ext_thread_entry(arg);
104+
}
105+
vTaskDelete(NULL);
106+
for (;;) {
107+
}
108+
}
109+
110+
void mp_thread_create(void *(*entry)(void*), void *arg, size_t stack_size) {
111+
// store thread entry function into a global variable so we can access it
112+
ext_thread_entry = entry;
113+
114+
if (stack_size == 0) {
115+
stack_size = 2048; // default stack size
116+
}
117+
118+
mp_thread_mutex_lock(&thread_mutex, 1);
119+
120+
// create thread
121+
StackType_t *stack = m_new(StackType_t, stack_size / sizeof(StackType_t));
122+
StaticTask_t *task_buf = m_new(StaticTask_t, 1);
123+
TaskHandle_t id = xTaskCreateStatic(freertos_entry, "Thread", stack_size / sizeof(void*), arg, 2, stack, task_buf);
124+
if (id == NULL) {
125+
mp_thread_mutex_unlock(&thread_mutex);
126+
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, "can't create thread"));
127+
}
128+
129+
// add thread to linked list of all threads
130+
thread_t *th = m_new_obj(thread_t);
131+
th->id = id;
132+
th->ready = 0;
133+
th->arg = arg;
134+
th->stack = stack;
135+
th->stack_len = stack_size / sizeof(StackType_t);
136+
th->next = thread;
137+
thread = th;
138+
139+
mp_thread_mutex_unlock(&thread_mutex);
140+
}
141+
142+
void mp_thread_finish(void) {
143+
mp_thread_mutex_lock(&thread_mutex, 1);
144+
// TODO unlink from list
145+
for (thread_t *th = thread; th != NULL; th = th->next) {
146+
if (th->id == xTaskGetCurrentTaskHandle()) {
147+
th->ready = 0;
148+
break;
149+
}
150+
}
151+
mp_thread_mutex_unlock(&thread_mutex);
152+
}
153+
154+
void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
155+
*mutex = xSemaphoreCreateMutex();
156+
if (*mutex == NULL) {
157+
// error!
158+
}
159+
}
160+
161+
int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
162+
int ret = xSemaphoreTake(*mutex, wait ? portMAX_DELAY : 0);
163+
return ret == pdTRUE;
164+
}
165+
166+
void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
167+
xSemaphoreGive(*mutex);
168+
// TODO check return value
169+
}
170+
171+
#endif // MICROPY_PY_THREAD

cc3200/mpthreadport.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
#ifndef __MICROPY_INCLUDED_CC3200_MPTHREADPORT_H__
27+
#define __MICROPY_INCLUDED_CC3200_MPTHREADPORT_H__
28+
29+
#include "FreeRTOS.h"
30+
31+
typedef SemaphoreHandle_t mp_thread_mutex_t;
32+
33+
void mp_thread_init(void);
34+
void mp_thread_gc_others(void);
35+
36+
#endif // __MICROPY_INCLUDED_CC3200_MPTHREADPORT_H__

cc3200/util/gccollect.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "py/mpconfig.h"
3232
#include "py/gc.h"
33+
#include "py/mpthread.h"
3334
#include "gccollect.h"
3435
#include "gchelper.h"
3536

@@ -57,6 +58,11 @@ void gc_collect(void) {
5758
// trace the stack, including the registers (since they live on the stack in this function)
5859
gc_collect_root((void**)sp, (stackend - sp) / sizeof(uint32_t));
5960

61+
// trace root pointers from any threads
62+
#if MICROPY_PY_THREAD
63+
mp_thread_gc_others();
64+
#endif
65+
6066
// end the GC
6167
gc_collect_end();
6268
}

0 commit comments

Comments
 (0)