mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-07-21 06:35:22 +02:00
Some work on using newlib's reentry capabilities.
This commit is contained in:
@@ -42,6 +42,15 @@ extern "C" {
|
|||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
struct atom_tcb;
|
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
|
typedef struct atom_tcb
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -50,6 +59,12 @@ typedef struct atom_tcb
|
|||||||
*/
|
*/
|
||||||
POINTER sp_save_ptr;
|
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) */
|
/* Thread priority (0-255) */
|
||||||
uint8_t priority;
|
uint8_t priority;
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ CPPFLAGS += -Wall -Wundef -Werror
|
|||||||
CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
|
CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
|
||||||
CPPFLAGS += -I$(board_dir) -I$(common_dir) -I$(src_dir) -I$(kernel_dir) -I$(tests_dir)
|
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
|
# Linker flags
|
||||||
LDFLAGS += --static -nostartfiles
|
LDFLAGS += --static -nostartfiles
|
||||||
LDFLAGS += -L$(LIB_DIR)
|
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
|
$(build_dir)/%.o: $(src_dir)/%.S Makefile $(board_dir)/Makefile.include
|
||||||
$(Q)mkdir -p `dirname $@`
|
$(Q)mkdir -p `dirname $@`
|
||||||
$(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)")
|
$(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
|
$(build_dir)/%.o: $(src_dir)/%.c Makefile $(board_dir)/Makefile.include
|
||||||
$(Q)mkdir -p `dirname $@`
|
$(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
|
$(build_dir)/%.o: $(board_dir)/%.S Makefile $(board_dir)/Makefile.include
|
||||||
$(Q)mkdir -p `dirname $@`
|
$(Q)mkdir -p `dirname $@`
|
||||||
$(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)")
|
$(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
|
$(build_dir)/%.o: $(board_dir)/%.c Makefile $(board_dir)/Makefile.include
|
||||||
$(Q)mkdir -p `dirname $@`
|
$(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
|
$(build_dir)/%.o: $(common_dir)/%.S Makefile $(board_dir)/Makefile.include
|
||||||
$(Q)mkdir -p `dirname $@`
|
$(Q)mkdir -p `dirname $@`
|
||||||
$(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)")
|
$(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
|
$(build_dir)/%.o: $(common_dir)/%.c Makefile $(board_dir)/Makefile.include
|
||||||
$(Q)mkdir -p `dirname $@`
|
$(Q)mkdir -p `dirname $@`
|
||||||
@@ -363,4 +367,4 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Include auto-generated dependencies
|
# Include auto-generated dependencies
|
||||||
-include $(all_objs:.o=.d)
|
-include $(all_objs:.o=.d)
|
||||||
|
|||||||
@@ -49,6 +49,13 @@
|
|||||||
.extern CTX_SW_NFO
|
.extern CTX_SW_NFO
|
||||||
.extern vector_table
|
.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
|
* Some bit masks and registers used
|
||||||
*/
|
*/
|
||||||
@@ -87,6 +94,17 @@ archFirstThreadRestore:
|
|||||||
ldr r1, [r0, #0]
|
ldr r1, [r0, #0]
|
||||||
msr PSP, r1
|
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
|
* Set bit #1 in CONTROL. Causes switch to PSP, so we can work directly
|
||||||
* with SP now and use pop/push.
|
* 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
|
* 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
|
mrs r3, PSP
|
||||||
|
|
||||||
#if defined(THUMB_2)
|
#if defined(THUMB_2)
|
||||||
@@ -281,7 +300,7 @@ pend_sv_handler:
|
|||||||
subs r3, r3, #32
|
subs r3, r3, #32
|
||||||
#endif // !THUMB_2
|
#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
|
* into its sp_save_ptr, which is the struct's first element
|
||||||
*/
|
*/
|
||||||
str r3, [r1, #0]
|
str r3, [r1, #0]
|
||||||
@@ -292,6 +311,17 @@ pend_sv_handler:
|
|||||||
*/
|
*/
|
||||||
str r2, [r0, #0]
|
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
|
* Fetch next thread's stack pointer from its TCB's sp_save_ptr and restore
|
||||||
* the thread's register context.
|
* the thread's register context.
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <libopencm3/cm3/nvic.h>
|
#include <libopencm3/cm3/nvic.h>
|
||||||
#include <libopencm3/cm3/systick.h>
|
#include <libopencm3/cm3/systick.h>
|
||||||
#include <libopencm3/cm3/cortex.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->sp_save_ptr = tsk_ctx;
|
||||||
tcb_ptr->entry_point = entry_point;
|
tcb_ptr->entry_point = entry_point;
|
||||||
tcb_ptr->entry_param = entry_param;
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <libopencm3/cm3/cortex.h>
|
#include <libopencm3/cm3/cortex.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* Required number of system ticks per second (normally 100 for 10ms tick) */
|
/* Required number of system ticks per second (normally 100 for 10ms tick) */
|
||||||
#define SYSTEM_TICKS_PER_SEC 100
|
#define SYSTEM_TICKS_PER_SEC 100
|
||||||
@@ -61,6 +62,18 @@
|
|||||||
#define CRITICAL_START() __irq_flags = cm_mask_interrupts(true)
|
#define CRITICAL_START() __irq_flags = cm_mask_interrupts(true)
|
||||||
#define CRITICAL_END() (void) cm_mask_interrupts(__irq_flags)
|
#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 */
|
/* Uncomment to enable stack-checking */
|
||||||
/* #define ATOM_STACK_CHECKING */
|
/* #define ATOM_STACK_CHECKING */
|
||||||
|
|
||||||
|
|||||||
@@ -64,19 +64,23 @@ static char *heap_end = 0;
|
|||||||
caddr_t _sbrk(int incr)
|
caddr_t _sbrk(int incr)
|
||||||
{
|
{
|
||||||
char *prev_end;
|
char *prev_end;
|
||||||
|
CRITICAL_STORE;
|
||||||
|
|
||||||
if(heap_end == 0){
|
prev_end = NULL;
|
||||||
|
|
||||||
|
CRITICAL_START();
|
||||||
|
|
||||||
|
if(unlikely(heap_end == 0)){
|
||||||
heap_end = &end;
|
heap_end = &end;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_end = heap_end;
|
/* make sure new heap size does not collide with main stack area*/
|
||||||
|
if(heap_end + incr + MST_SIZE <= (char *) vector_table.initial_sp_value){
|
||||||
if(heap_end + incr + MST_SIZE > (char *) vector_table.initial_sp_value){
|
prev_end = heap_end;
|
||||||
/* new heap size would collide with main stack area*/
|
heap_end += incr;
|
||||||
return (caddr_t) 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_end += incr;
|
CRITICAL_END();
|
||||||
|
|
||||||
return (caddr_t) prev_end;
|
return (caddr_t) prev_end;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user