Some work on using newlib's reentry capabilities.

This commit is contained in:
Tido Klaassen
2015-09-08 15:22:24 +02:00
parent c23613360e
commit 0be9a35aeb
6 changed files with 88 additions and 13 deletions

View File

@@ -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;

View File

@@ -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)
-include $(all_objs:.o=.d)

View File

@@ -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.

View File

@@ -27,6 +27,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/cm3/cortex.h>
@@ -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
}

View File

@@ -33,6 +33,7 @@
#include <stdint.h>
#include <stddef.h>
#include <libopencm3/cm3/cortex.h>
#include <stdlib.h>
/* 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 */

View File

@@ -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;
}