diff --git a/kernel/atom.h b/kernel/atom.h index 64c5ce8..152f98e 100755 --- a/kernel/atom.h +++ b/kernel/atom.h @@ -42,6 +42,15 @@ extern "C" { /* Forward declaration */ struct atom_tcb; +/* + * Define THREAD_PORT_PRIV to be empty if the used atomport.h does not define + * a port specific entry for the atom_tcb struct. This way we do not have an + * unused element. + */ +#if !defined(THREAD_PORT_PRIV) +#define THREAD_PORT_PRIV +#endif + typedef struct atom_tcb { /* @@ -50,6 +59,12 @@ typedef struct atom_tcb */ POINTER sp_save_ptr; + /* Thread's port specific private data. Do not move, some poorly written + * thread switching code (*cough* Cortex-M *cough*) might depend on a + * known offset into the atom_tcb struct + */ + THREAD_PORT_PRIV; + /* Thread priority (0-255) */ uint8_t priority; diff --git a/ports/cortex-m/Makefile b/ports/cortex-m/Makefile index 2a1e14f..20bc7e7 100644 --- a/ports/cortex-m/Makefile +++ b/ports/cortex-m/Makefile @@ -113,6 +113,10 @@ CPPFLAGS += -Wall -Wundef -Werror CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS) CPPFLAGS += -I$(board_dir) -I$(common_dir) -I$(src_dir) -I$(kernel_dir) -I$(tests_dir) +# Assembler flags +ASFLAGS += -D__ASSEMBLY__ +ASFLAGS += -D__NEWLIB__ + # Linker flags LDFLAGS += --static -nostartfiles LDFLAGS += -L$(LIB_DIR) @@ -254,7 +258,7 @@ $(build_dir)/%.elf $(build_dir)/%.map: $(LIB_DIR)/lib$(LIBNAME).a $(build_dir)/% $(build_dir)/%.o: $(src_dir)/%.S Makefile $(board_dir)/Makefile.include $(Q)mkdir -p `dirname $@` $(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)") - $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -D__ASSEMBLY__ -I`dirname $<` -c $< -o $@ + $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) $(ASFLAGS) -I`dirname $<` -c $< -o $@ $(build_dir)/%.o: $(src_dir)/%.c Makefile $(board_dir)/Makefile.include $(Q)mkdir -p `dirname $@` @@ -264,7 +268,7 @@ $(build_dir)/%.o: $(src_dir)/%.c Makefile $(board_dir)/Makefile.include $(build_dir)/%.o: $(board_dir)/%.S Makefile $(board_dir)/Makefile.include $(Q)mkdir -p `dirname $@` $(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)") - $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -D__ASSEMBLY__ -I`dirname $<` -c $< -o $@ + $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) $(ASFLAGS) -I`dirname $<` -c $< -o $@ $(build_dir)/%.o: $(board_dir)/%.c Makefile $(board_dir)/Makefile.include $(Q)mkdir -p `dirname $@` @@ -274,7 +278,7 @@ $(build_dir)/%.o: $(board_dir)/%.c Makefile $(board_dir)/Makefile.include $(build_dir)/%.o: $(common_dir)/%.S Makefile $(board_dir)/Makefile.include $(Q)mkdir -p `dirname $@` $(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)") - $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -D__ASSEMBLY__ -I`dirname $<` -c $< -o $@ + $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) $(ASFLAGS) -I`dirname $<` -c $< -o $@ $(build_dir)/%.o: $(common_dir)/%.c Makefile $(board_dir)/Makefile.include $(Q)mkdir -p `dirname $@` @@ -363,4 +367,4 @@ else endif # Include auto-generated dependencies --include $(all_objs:.o=.d) \ No newline at end of file +-include $(all_objs:.o=.d) diff --git a/ports/cortex-m/atomport-asm.S b/ports/cortex-m/atomport-asm.S index 6098ba3..24f1060 100644 --- a/ports/cortex-m/atomport-asm.S +++ b/ports/cortex-m/atomport-asm.S @@ -49,6 +49,13 @@ .extern CTX_SW_NFO .extern vector_table +#if defined(__NEWLIB__) +/** + * When using newlib, reentry context needs to be updated on task switch + */ +.extern _impure_ptr +#endif + /** * Some bit masks and registers used */ @@ -87,6 +94,17 @@ archFirstThreadRestore: ldr r1, [r0, #0] msr PSP, r1 +#if defined(__NEWLIB__) + /** + * Store the thread's reentry context address in _impure_ptr. This + * should be the TCB's second element + */ + ldr r1, = _impure_ptr + mov r2, r0 + add r2, #4 + str r2, [r1, #0] +#endif + /** * Set bit #1 in CONTROL. Causes switch to PSP, so we can work directly * with SP now and use pop/push. @@ -223,7 +241,8 @@ pend_sv_handler: /** * Copy running thread's process stack pointer to r3 and use it to push - * */ + * the thread's register context on its stack + */ mrs r3, PSP #if defined(THUMB_2) @@ -281,7 +300,7 @@ pend_sv_handler: subs r3, r3, #32 #endif // !THUMB_2 /** - * Address of running TCB still in r1. Store threads current stack top + * Address of running TCB still in r1. Store thread's current stack top * into its sp_save_ptr, which is the struct's first element */ str r3, [r1, #0] @@ -292,6 +311,17 @@ pend_sv_handler: */ str r2, [r0, #0] +#if defined(__NEWLIB__) + /** + * Store the thread's reentry context address in _impure_ptr. This + * should be the TCB's second element + */ + mov r4, r2 + add r4, #4 + ldr r3, = _impure_ptr + str r4, [r3, #0] +#endif + /** * Fetch next thread's stack pointer from its TCB's sp_save_ptr and restore * the thread's register context. diff --git a/ports/cortex-m/atomport.c b/ports/cortex-m/atomport.c index 49ea73d..67767cf 100644 --- a/ports/cortex-m/atomport.c +++ b/ports/cortex-m/atomport.c @@ -27,6 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + #include #include #include @@ -201,5 +203,12 @@ void archThreadContextInit(ATOM_TCB *tcb_ptr, void *stack_top, tcb_ptr->sp_save_ptr = tsk_ctx; tcb_ptr->entry_point = entry_point; tcb_ptr->entry_param = entry_param; + +#if defined(__NEWLIB__) + /** + * Initialise thread's reentry context for newlib + */ + _REENT_INIT_PTR(&(tcb_ptr->port_priv.reent)); +#endif } diff --git a/ports/cortex-m/atomport.h b/ports/cortex-m/atomport.h index 562b84e..1f662f9 100644 --- a/ports/cortex-m/atomport.h +++ b/ports/cortex-m/atomport.h @@ -33,6 +33,7 @@ #include #include #include +#include /* Required number of system ticks per second (normally 100 for 10ms tick) */ #define SYSTEM_TICKS_PER_SEC 100 @@ -61,6 +62,18 @@ #define CRITICAL_START() __irq_flags = cm_mask_interrupts(true) #define CRITICAL_END() (void) cm_mask_interrupts(__irq_flags) +/** + * When using newlib, define port private field in atom_tcb to be a + * struct _reent. + */ +#if defined(__NEWLIB__) +struct cortex_port_priv { + struct _reent reent; +}; + +#define THREAD_PORT_PRIV struct cortex_port_priv port_priv +#endif + /* Uncomment to enable stack-checking */ /* #define ATOM_STACK_CHECKING */ diff --git a/ports/cortex-m/common/stubs.c b/ports/cortex-m/common/stubs.c index 4bcf302..d12a17c 100644 --- a/ports/cortex-m/common/stubs.c +++ b/ports/cortex-m/common/stubs.c @@ -64,19 +64,23 @@ static char *heap_end = 0; caddr_t _sbrk(int incr) { char *prev_end; + CRITICAL_STORE; - if(heap_end == 0){ + prev_end = NULL; + + CRITICAL_START(); + + if(unlikely(heap_end == 0)){ heap_end = &end; } - prev_end = heap_end; - - if(heap_end + incr + MST_SIZE > (char *) vector_table.initial_sp_value){ - /* new heap size would collide with main stack area*/ - return (caddr_t) 0; + /* make sure new heap size does not collide with main stack area*/ + if(heap_end + incr + MST_SIZE <= (char *) vector_table.initial_sp_value){ + prev_end = heap_end; + heap_end += incr; } - heap_end += incr; + CRITICAL_END(); return (caddr_t) prev_end; }