mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-01-11 18:33:16 +01:00
- initial commit from private repository
This commit is contained in:
@@ -342,6 +342,9 @@ static void atomThreadSwitch(ATOM_TCB *old_tcb, ATOM_TCB *new_tcb)
|
||||
/* Set the new currently-running thread pointer */
|
||||
curr_tcb = new_tcb;
|
||||
|
||||
/* TKL: If the thread is being scheduled in, it can not be suspended */
|
||||
curr_tcb->suspended = FALSE;
|
||||
|
||||
/* Call the architecture-specific context switch */
|
||||
archContextSwitch (old_tcb, new_tcb);
|
||||
}
|
||||
@@ -351,7 +354,13 @@ static void atomThreadSwitch(ATOM_TCB *old_tcb, ATOM_TCB *new_tcb)
|
||||
* we get back here, we are running in old_tcb context again. Clear its
|
||||
* suspend status now that we're back.
|
||||
*/
|
||||
old_tcb->suspended = FALSE;
|
||||
|
||||
/**
|
||||
* TKL: does not work on Cortex-M because of the delayed context switching
|
||||
* via pend_sv_handler and also the separate thread and exception stacks
|
||||
* being used.
|
||||
*/
|
||||
// old_tcb->suspended = FALSE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
291
ports/cortex-m/Makefile
Normal file
291
ports/cortex-m/Makefile
Normal file
@@ -0,0 +1,291 @@
|
||||
################################################
|
||||
# Toplevel makefile for all libopencm3 targets #
|
||||
################################################
|
||||
|
||||
ifeq ($(V),)
|
||||
Q := @
|
||||
# Do not print "Entering directory ...".
|
||||
MAKEFLAGS += --no-print-directory
|
||||
endif
|
||||
|
||||
# Build directory
|
||||
ifdef O
|
||||
build_dir=$(shell readlink -f $(O))
|
||||
else
|
||||
build_dir=$(CURDIR)/build
|
||||
endif
|
||||
|
||||
# Source directory
|
||||
src_dir=$(CURDIR)
|
||||
|
||||
# Clean object list before including board makefile
|
||||
objs :=
|
||||
|
||||
# set default board if none is given
|
||||
ifeq ($(BOARD),)
|
||||
BOARD = nucleo-f103rb
|
||||
endif
|
||||
|
||||
include $(src_dir)/boards/$(BOARD)/Makefile
|
||||
|
||||
# Make sure target MCU is set
|
||||
ifndef TARGET
|
||||
$(error TARGET undefined)
|
||||
endif
|
||||
|
||||
# Configure toolchain
|
||||
CROSS_COMPILE ?= arm-none-eabi-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
CXX := $(CROSS_COMPILE)g++
|
||||
LD := $(CROSS_COMPILE)gcc
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
AS := $(CROSS_COMPILE)as
|
||||
OBJCOPY := $(CROSS_COMPILE)objcopy
|
||||
OBJDUMP := $(CROSS_COMPILE)objdump
|
||||
GDB := $(CROSS_COMPILE)gdb
|
||||
STFLASH = $(shell which st-flash)
|
||||
|
||||
LDSCRIPT ?= linker/$(TARGET).ld
|
||||
|
||||
# Enable stack-checking. WARNING: the full automated test suite currently
|
||||
# requires a little over 1KB RAM with stack-checking enabled. If you are
|
||||
# using a device with 1KB internal SRAM and no external SRAM then you
|
||||
# must disable stack-checking to run all of the automated tests.
|
||||
#STACK_CHECK=true
|
||||
|
||||
# Location of atomthreads sources
|
||||
board_dir=$(src_dir)/boards/$(BOARD)
|
||||
common_dir=$(src_dir)/common
|
||||
kernel_dir=$(src_dir)/../../kernel
|
||||
tests_dir=$(src_dir)/../../tests
|
||||
|
||||
# Object files
|
||||
objs += atomport.o
|
||||
objs += atomport-asm.o
|
||||
|
||||
# Kernel object files
|
||||
objs += atomkernel.o
|
||||
objs += atomsem.o
|
||||
objs += atommutex.o
|
||||
objs += atomtimer.o
|
||||
objs += atomqueue.o
|
||||
|
||||
objs += tests-main.o
|
||||
|
||||
# Collection of built objects (excluding test applications)
|
||||
build_objs = $(foreach obj,$(objs),$(build_dir)/$(obj))
|
||||
|
||||
# Target application filenames .elf for each test object
|
||||
tobjs = $(notdir $(patsubst %.c,%.o,$(wildcard $(tests_dir)/*.c)))
|
||||
telfs = $(patsubst %.o,%.elf,$(tobjs))
|
||||
tbins = $(patsubst %.o,%.bin,$(tobjs))
|
||||
thexs = $(patsubst %.o,%.hex,$(tobjs))
|
||||
build_tobjs = $(foreach tobj,$(tobjs),$(build_dir)/$(tobj))
|
||||
build_telfs = $(foreach telf,$(telfs),$(build_dir)/$(telf))
|
||||
build_tbins = $(foreach tbin,$(tbins),$(build_dir)/$(tbin))
|
||||
build_thexs = $(foreach thex,$(thexs),$(build_dir)/$(thex))
|
||||
|
||||
# Check if user wants to use external opencm3 lib or if we have to build
|
||||
# it ourselves
|
||||
ifeq ($(OPENCM3_DIR),)
|
||||
OPENCM3_DIR = $(src_dir)/libopencm3
|
||||
lib_needed = build_lib
|
||||
endif
|
||||
|
||||
ifneq ($(V),)
|
||||
$(info Using $(OPENCM3_DIR) as path to opencm3 library)
|
||||
endif
|
||||
|
||||
# Set up search paths for libopencm3
|
||||
INCLUDE_DIR = $(OPENCM3_DIR)/include
|
||||
LIB_DIR = $(OPENCM3_DIR)/lib
|
||||
SCRIPT_DIR = $(OPENCM3_DIR)/scripts
|
||||
|
||||
# GCC flags
|
||||
CFLAGS = -Os -g
|
||||
CFLAGS += -Wall -Wshadow -Wimplicit-function-declaration
|
||||
CFLAGS += -Wredundant-decls -Wstrict-prototypes
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
# Enable stack-checking (disable if not required)
|
||||
ifeq ($(STACK_CHECK),true)
|
||||
CFLAGS += -DATOM_STACK_CHECKING -DTESTS_LOG_STACK_USAGE
|
||||
endif
|
||||
|
||||
# C & C++ preprocessor common flags
|
||||
CPPFLAGS += -MD
|
||||
CPPFLAGS += -Wall -Wundef
|
||||
CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
|
||||
CPPFLAGS += -I$(board_dir) -I$(common_dir) -I$(src_dir) -I$(kernel_dir) -I$(tests_dir)
|
||||
|
||||
# Linker flags
|
||||
LDFLAGS += --static -nostartfiles
|
||||
LDFLAGS += -L$(LIB_DIR)
|
||||
LDFLAGS += -T$(LDSCRIPT)
|
||||
LDFLAGS += -Wl,-Map=$(build_dir)/$(*).map
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
ifeq ($(V),99)
|
||||
LDFLAGS += -Wl,--print-gc-sections
|
||||
endif
|
||||
|
||||
## Used libraries
|
||||
# Target specific version libopencm3
|
||||
LDLIBS += -l$(LIBNAME)
|
||||
|
||||
## Flags for newlibc.
|
||||
# This uses the version of newlib optimised for size and without libnosys.
|
||||
# This is the configuration you want to use unless you really know what
|
||||
# you are doing.
|
||||
LDLIBS += -Wl,--start-group -lc_nano -lgcc -Wl,--end-group
|
||||
|
||||
# This is the fully bloated version of newlib optimized for speed.
|
||||
#LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
|
||||
|
||||
# Use small newlib with libnosys if you do not want to use the provided stubs.
|
||||
# Be advised that heap management will probaly break in interesting ways
|
||||
# because libnosys' standard _sbrk() expects the stack to start at the top
|
||||
# end of memory while the threads' stacks are positioned inside the BSS.
|
||||
#LDLIBS += -Wl,--start-group -lc_nano -lgcc -lnosys -Wl,--end-group
|
||||
|
||||
# All
|
||||
.PHONY: all
|
||||
all: $(LIB_DIR)/lib$(LIBNAME).a $(build_tbins) $(build_thexs) $(build_telfs) $(build_tobjs) $(build_objs) Makefile
|
||||
|
||||
# add build dependency for local libopencm3 if no external libopencm3 is used
|
||||
$(LIB_DIR)/lib$(LIBNAME).a: $(lib_needed)
|
||||
|
||||
.PHONY: build_lib
|
||||
build_lib:
|
||||
$(Q)if [ ! -d libopencm3 ] ; then \
|
||||
printf "######## ERROR ########\n"; \
|
||||
printf "\tlibopencm3 is not initialized.\n"; \
|
||||
printf "\tPlease run:\n"; \
|
||||
printf "\t$$ git submodule add https://github.com/libopencm3/libopencm3.git\n"; \
|
||||
printf "\t$$ git submodule init\n"; \
|
||||
printf "\t$$ git submodule update\n"; \
|
||||
printf "\tbefore running make.\n"; \
|
||||
printf "######## ERROR ########\n"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(Q)$(MAKE) -C libopencm3
|
||||
|
||||
flash: $(BINARY).flash
|
||||
|
||||
$(build_dir)/%.bin: $(build_dir)/%.elf
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (OBJCOPY) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(OBJCOPY) -O binary $< $@
|
||||
|
||||
$(build_dir)/%.hex: $(build_dir)/%.elf
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (OBJCOPY) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
$(build_dir)/%.srec: $(build_dir)/%.elf
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (OBJCOPY) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(OBJCOPY) -O srec $< $@
|
||||
|
||||
$(build_dir)/%.list: $(build_dir)/%.elf
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (OBJDUMP) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(OBJDUMP) -S $< > $@
|
||||
|
||||
$(build_dir)/%.elf $(build_dir)/%.map: $(build_dir)/%.o $(build_objs) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (ELF) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(build_objs) $(build_dir)/$(*).o $(LDLIBS) -o $@
|
||||
|
||||
$(build_dir)/%.o: $(src_dir)/%.S
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -D__ASSEMBLY__ -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(src_dir)/%.c
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(board_dir)/%.c
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(common_dir)/%.c
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(kernel_dir)/%.c
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(tests_dir)/%.c
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
# Clean
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf doxygen-kernel
|
||||
rm -rf doxygen-opencm3
|
||||
rm -rf $(build_dir)
|
||||
ifneq ($(lib_needed),)
|
||||
$(Q)$(MAKE) -C libopencm3 V=$(V) clean
|
||||
endif
|
||||
|
||||
# Docs
|
||||
.PHONY: doxygen
|
||||
doxygen:
|
||||
doxygen $(kernel_dir)/Doxyfile
|
||||
doxygen ./Doxyfile
|
||||
|
||||
%.stlink-flash: $(build_dir)/%.bin
|
||||
@printf " FLASH $<\n"
|
||||
$(Q)$(STFLASH) write $(build_dir)/$(*).bin 0x8000000
|
||||
|
||||
ifeq ($(STLINK_PORT),)
|
||||
ifeq ($(BMP_PORT),)
|
||||
ifeq ($(OOCD_SERIAL),)
|
||||
%.flash: $(build_dir)/%.hex
|
||||
@printf " FLASH $<\n"
|
||||
@# IMPORTANT: Don't use "resume", only "reset" will work correctly!
|
||||
-$(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
|
||||
-f board/$(OOCD_BOARD).cfg \
|
||||
-c "init" -c "reset init" \
|
||||
-c "flash write_image erase $(build_dir)/$(*).hex" \
|
||||
-c "reset" \
|
||||
-c "shutdown" $(NULL)
|
||||
else
|
||||
%.flash: $(build_dir)/%.hex
|
||||
@printf " FLASH $<\n"
|
||||
@# IMPORTANT: Don't use "resume", only "reset" will work correctly!
|
||||
-$(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
|
||||
-f board/$(OOCD_BOARD).cfg \
|
||||
-c "ft2232_serial $(OOCD_SERIAL)" \
|
||||
-c "init" -c "reset init" \
|
||||
-c "flash write_image erase $(build_dir)/$(*).hex" \
|
||||
-c "reset" \
|
||||
-c "shutdown" $(NULL)
|
||||
endif
|
||||
else
|
||||
%.flash: $(build_dir)/%.elf
|
||||
@printf " GDB $(build_dir)/$(*).elf (flash)\n"
|
||||
$(Q)$(GDB) --batch \
|
||||
-ex 'target extended-remote $(BMP_PORT)' \
|
||||
-x $(SCRIPT_DIR)/black_magic_probe_flash.scr \
|
||||
$(build_dir)/$(*).elf
|
||||
endif
|
||||
else
|
||||
%.flash: $(build_dir)/%.elf
|
||||
@printf " GDB $(build_dir)/$(*).elf (flash)\n"
|
||||
$(Q)$(GDB) --batch \
|
||||
-ex 'target extended-remote $(STLINK_PORT)' \
|
||||
-x $(SCRIPT_DIR)/stlink_flash.scr \
|
||||
$(build_dir)/$(*).elf
|
||||
endif
|
||||
|
||||
|
||||
1
ports/cortex-m/README.md
Normal file
1
ports/cortex-m/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# Comming soon...
|
||||
176
ports/cortex-m/atomport-asm.S
Normal file
176
ports/cortex-m/atomport-asm.S
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
|
||||
.extern CTX_SW_NFO
|
||||
.extern _stack
|
||||
.extern vector_table
|
||||
|
||||
.equ FPU_USED, 0x00000010
|
||||
|
||||
.text
|
||||
|
||||
.global archFirstThreadRestore
|
||||
.func archFirstThreadRestore
|
||||
.type archFirstThreadRestore,%function
|
||||
.thumb_func
|
||||
archFirstThreadRestore:
|
||||
/**
|
||||
* Disable interrupts. They should be disabled anyways, but just
|
||||
* to make sure...
|
||||
*/
|
||||
mov r1, #1
|
||||
msr PRIMASK, r1
|
||||
|
||||
/**
|
||||
* Reset main stack pointer to initial value, which is the first entry
|
||||
* in the vector table.
|
||||
*/
|
||||
ldr r1, = vector_table
|
||||
ldr r1, [r1, #0]
|
||||
msr MSP, r1
|
||||
|
||||
/* Update ctx_switch_info, set this thread as both running and next */
|
||||
ldr r1, = CTX_SW_NFO
|
||||
str r0, [r1, #0]
|
||||
str r0, [r1, #4]
|
||||
|
||||
/* Get thread stack pointer from tcb. Conveniently the first element */
|
||||
ldr r2, [r0, #0]
|
||||
|
||||
/* Discard dummy thread stack frame */
|
||||
add r2, r2, #36
|
||||
|
||||
/**
|
||||
* New threads can't have used the FPU, so no need to check for
|
||||
* FPU stack frame here
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load exception stack frame to registers r3-r10. xPSR ends up in r10,
|
||||
* pc in r9
|
||||
*/
|
||||
ldmia r2!, {r3-r10}
|
||||
|
||||
/* initialise xPSR and store store adjusted stack pointer in PSP */
|
||||
msr APSR_nzcvq, r10
|
||||
msr PSP, r2
|
||||
|
||||
/* set bit #1 in CONTROL. Causes switch to PSP */
|
||||
mrs r1, CONTROL
|
||||
orr r1, r1, #2
|
||||
msr CONTROL, r1
|
||||
|
||||
/* enable interrupts */
|
||||
mov r1, #0
|
||||
msr PRIMASK, r1
|
||||
|
||||
/* branch to thread entry point */
|
||||
bx r9
|
||||
nop
|
||||
.size archFirstThreadRestore, . - archFirstThreadRestore
|
||||
.endfunc
|
||||
|
||||
.global pend_sv_handler
|
||||
.func pend_sv_handler
|
||||
.type pend_sv_handler,%function
|
||||
.thumb_func
|
||||
pend_sv_handler:
|
||||
/**
|
||||
* Disable interrupts. No need to check if they were enabled because,
|
||||
* well, we're an interrupt handler. Duh...
|
||||
*/
|
||||
mov r0, #1
|
||||
msr PRIMASK, r0
|
||||
|
||||
/* Get running thread's stack pointer*/
|
||||
mrs r3, PSP
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
/* Check if FPU was used by thread and store registers if necessary */
|
||||
tst lr, FPU_USED
|
||||
it eq
|
||||
vstmdbeq r3!, {s16-s31}
|
||||
|
||||
/**
|
||||
* TODO: Defer stacking FPU context by disabling FPU and using a
|
||||
* fault handler to store the FPU registers if another thread
|
||||
* tries using it
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* Push running thread's remaining registers on stack */
|
||||
stmdb r3!, {r4-r11, lr}
|
||||
|
||||
/* Fetch running thread's TCB and store its current stack pointer */
|
||||
ldr r2, = CTX_SW_NFO
|
||||
ldr r1, [r2, #0]
|
||||
str r3, [r1, #0]
|
||||
|
||||
/**
|
||||
* Fetch pointer to next thread's tcb from ctx_switch_info.next_tcb and
|
||||
* use it to update ctx_switch_info.running_tcb.
|
||||
*/
|
||||
ldr r1, [r2, #4]
|
||||
str r1, [r2, #0]
|
||||
|
||||
/**
|
||||
* Fetch next thread's stack pointer from its TCB and restore
|
||||
* the thread's register context.
|
||||
*/
|
||||
ldr r3, [r1, #0]
|
||||
ldmia r3!, {r4-r11, lr}
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
/**
|
||||
* Check if FPU was used by new thread and restore registers if necessary.
|
||||
*/
|
||||
tst lr, FPU_USED
|
||||
it eq
|
||||
vldmiaeq r3!, {s16-s31}
|
||||
|
||||
/**
|
||||
* TODO: only restore FPU registers if FPU was used by another thread
|
||||
* between this thread being scheduled out and now.
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* Restore process stack pointer */
|
||||
msr PSP, r3
|
||||
|
||||
/* Re-enable interrupts */
|
||||
mov r0, #0
|
||||
msr PRIMASK, r0
|
||||
|
||||
/* Return to new thread */
|
||||
bx lr
|
||||
nop
|
||||
.size pend_sv_handler, . - pend_sv_handler
|
||||
.endfunc
|
||||
117
ports/cortex-m/atomport-private.h
Normal file
117
ports/cortex-m/atomport-private.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ATOMPORT_PRIVATE_H_
|
||||
#define __ATOMPORT_PRIVATE_H_
|
||||
|
||||
#include "atomport.h"
|
||||
#include "atom.h"
|
||||
|
||||
/**
|
||||
* context saved automagically by exception entry
|
||||
*/
|
||||
struct isr_stack {
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t psr;
|
||||
};
|
||||
|
||||
struct isr_fpu_stack {
|
||||
uint32_t s0;
|
||||
uint32_t s1;
|
||||
uint32_t s2;
|
||||
uint32_t s3;
|
||||
uint32_t s4;
|
||||
uint32_t s5;
|
||||
uint32_t s6;
|
||||
uint32_t s7;
|
||||
uint32_t s8;
|
||||
uint32_t s9;
|
||||
uint32_t s10;
|
||||
uint32_t s11;
|
||||
uint32_t s12;
|
||||
uint32_t s13;
|
||||
uint32_t s14;
|
||||
uint32_t s15;
|
||||
uint32_t fpscr;
|
||||
};
|
||||
|
||||
/**
|
||||
* remaining context saved by task switch ISR
|
||||
*/
|
||||
struct task_stack {
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
uint32_t r8;
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
uint32_t lr;
|
||||
};
|
||||
|
||||
struct task_fpu_stack {
|
||||
uint32_t s16;
|
||||
uint32_t s17;
|
||||
uint32_t s18;
|
||||
uint32_t s19;
|
||||
uint32_t s20;
|
||||
uint32_t s21;
|
||||
uint32_t s22;
|
||||
uint32_t s23;
|
||||
uint32_t s24;
|
||||
uint32_t s25;
|
||||
uint32_t s26;
|
||||
uint32_t s27;
|
||||
uint32_t s28;
|
||||
uint32_t s29;
|
||||
uint32_t s30;
|
||||
uint32_t s31;
|
||||
};
|
||||
|
||||
/**
|
||||
* Info needed by pend_sv_handler used for delayed task switching.
|
||||
* Running_tcb is a pointer to the TCB currently running (gosh, really?!)
|
||||
* next_tcb is a pointer to a TCB that should be running.
|
||||
* archContextSwitch() will update next_tcb and trigger a pend_sv. The
|
||||
* pend_sv_handler will be called as soon as all other ISRs have returned,
|
||||
* do the real context switch and update running_tcb.
|
||||
*/
|
||||
struct task_switch_info {
|
||||
volatile struct atom_tcb *running_tcb;
|
||||
volatile struct atom_tcb *next_tcb;
|
||||
};
|
||||
|
||||
#endif /* __ATOMPORT_PRIVATE_H_ */
|
||||
47
ports/cortex-m/atomport-tests.h
Normal file
47
ports/cortex-m/atomport-tests.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ATOM_PORT_TESTS_H
|
||||
#define __ATOM_PORT_TESTS_H
|
||||
|
||||
/* Include Atomthreads kernel API */
|
||||
#include <stdio.h>
|
||||
#include "atom.h"
|
||||
|
||||
/* Default thread stack size (in bytes) */
|
||||
#define TEST_THREAD_STACK_SIZE 1024
|
||||
|
||||
/* Uncomment to enable logging of stack usage to UART */
|
||||
/* #define TESTS_LOG_STACK_USAGE */
|
||||
|
||||
#define ATOMLOG printf
|
||||
#define _STR
|
||||
|
||||
#endif /* __ATOM_PORT_TESTS_H */
|
||||
|
||||
200
ports/cortex-m/atomport.c
Normal file
200
ports/cortex-m/atomport.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
#include <libopencm3/cm3/sync.h>
|
||||
|
||||
#include "atomport.h"
|
||||
#include "atomport-private.h"
|
||||
|
||||
static void thread_shell(void);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
struct task_switch_info ctx_switch_info asm("CTX_SW_NFO") =
|
||||
{
|
||||
.running_tcb = NULL,
|
||||
.next_tcb = NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* We do not perform the context switch directly. Instead we mark the new tcb
|
||||
* as should-be-running in ctx_switch_info and trigger a PendSv-interrupt.
|
||||
* The pend_sv_handler will be called when all other pending exceptions have
|
||||
* returned and perform the actual context switch.
|
||||
* This way we do not have to worry if we are being called from task or
|
||||
* interrupt context, which would mean messing with either main or thread
|
||||
* stack format.
|
||||
*
|
||||
* One difference to the other architectures is that execution flow will
|
||||
* actually continue in the old thread context until interrupts are enabled
|
||||
* again. From a thread context this should make no difference, as the context
|
||||
* switch will be performed as soon as the execution flow would return to the
|
||||
* calling thread. Unless, of course, the thread called atomSched() with
|
||||
* disabled interrupts, which it should not do anyways...
|
||||
*/
|
||||
void __attribute__((noinline))
|
||||
archContextSwitch(ATOM_TCB *old_tcb_ptr __maybe_unused, ATOM_TCB *new_tcb_ptr)
|
||||
{
|
||||
if(likely(ctx_switch_info.running_tcb != NULL)){
|
||||
ctx_switch_info.next_tcb = new_tcb_ptr;
|
||||
|
||||
__dmb();
|
||||
|
||||
SCB_ICSR = SCB_ICSR_PENDSVSET;
|
||||
}
|
||||
}
|
||||
|
||||
void sys_tick_handler(void)
|
||||
{
|
||||
/* Call the interrupt entry routine */
|
||||
atomIntEnter();
|
||||
|
||||
/* Call the OS system tick handler */
|
||||
atomTimerTick();
|
||||
|
||||
/* Call the interrupt exit routine */
|
||||
atomIntExit(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put chip into infinite loop if NMI or hard fault occurs
|
||||
*/
|
||||
void nmi_handler(void)
|
||||
{
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
|
||||
void hard_fault_handler(void)
|
||||
{
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function is called when a new thread is scheduled in for the first
|
||||
* time. It will simply call the threads entry point function.
|
||||
*/
|
||||
static void thread_shell(void)
|
||||
{
|
||||
ATOM_TCB *task_ptr;
|
||||
|
||||
/**
|
||||
* We "return" to here after being scheduled in by the pend_sv_handler.
|
||||
* We get a pointer to our TCB from atomCurrentContext()
|
||||
*/
|
||||
task_ptr = atomCurrentContext();
|
||||
|
||||
/**
|
||||
* Our thread entry point and parameter are stored in the TCB.
|
||||
* Call it if it is valid
|
||||
*/
|
||||
if(task_ptr && task_ptr->entry_point){
|
||||
task_ptr->entry_point(task_ptr->entry_param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread returned or entry point was not valid.
|
||||
* Should never happen... Maybe we should switch MCU into debug mode here
|
||||
*/
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise a threads stack so it can be scheduled in by
|
||||
* archFirstThreadRestore or the pend_sv_handler.
|
||||
*/
|
||||
void archThreadContextInit(ATOM_TCB *tcb_ptr, void *stack_top,
|
||||
void (*entry_point)(uint32_t), uint32_t entry_param)
|
||||
{
|
||||
struct isr_stack *isr_ctx;
|
||||
struct task_stack *tsk_ctx;
|
||||
|
||||
/**
|
||||
* New threads will be scheduled from an exception handler, so we have to
|
||||
* set up an exception stack frame as well as task stack frame
|
||||
*/
|
||||
isr_ctx = stack_top - sizeof(*isr_ctx);
|
||||
tsk_ctx = stack_top - sizeof(*isr_ctx) - sizeof(*tsk_ctx);
|
||||
|
||||
#if 0
|
||||
printf("[%s] tcb_ptr: %p stack_top: %p isr_ctx: %p tsk_ctx: %p entry_point: %p, entry_param: 0x%x\n",
|
||||
__func__, tcb_ptr, stack_top, isr_ctx, tsk_ctx, entry_point, entry_param);
|
||||
printf("[%s] isr_ctx->r0: %p isr_ctx->psr: %p tsk_ctx->r4: %p tsk_ctx->lr: %p\n",
|
||||
__func__, &isr_ctx->r0, &isr_ctx->psr, &tsk_ctx->r4, &tsk_ctx->lr);
|
||||
#endif
|
||||
/**
|
||||
* We use the exception return mechanism to jump to our thread_shell()
|
||||
* function and initialise the PSR to the default value (thumb state
|
||||
* flag set and nothing else)
|
||||
*/
|
||||
isr_ctx->psr = 0x01000000;
|
||||
isr_ctx->pc = (uint32_t) thread_shell;
|
||||
|
||||
/* initialise unused registers to silly value */
|
||||
isr_ctx->lr = 0xDEADBEEF;
|
||||
isr_ctx->r12 = 0xDEADBEEF;
|
||||
isr_ctx->r3 = 0xDEADBEEF;
|
||||
isr_ctx->r2 = 0xDEADBEEF;
|
||||
isr_ctx->r1 = 0xDEADBEEF;
|
||||
isr_ctx->r0 = 0xDEADBEEF;
|
||||
|
||||
/**
|
||||
* We use this special EXC_RETURN code to switch from main stack to our
|
||||
* thread stack on exception return
|
||||
*/
|
||||
tsk_ctx->lr = 0xFFFFFFFD;
|
||||
|
||||
/* initialise unused registers to silly value */
|
||||
tsk_ctx->r11 = 0xDEADBEEF;
|
||||
tsk_ctx->r10 = 0xDEADBEEF;
|
||||
tsk_ctx->r9 = 0xDEADBEEF;
|
||||
tsk_ctx->r8 = 0xDEADBEEF;
|
||||
tsk_ctx->r7 = 0xDEADBEEF;
|
||||
tsk_ctx->r6 = 0xDEADBEEF;
|
||||
tsk_ctx->r5 = 0xDEADBEEF;
|
||||
tsk_ctx->r4 = 0xDEADBEEF;
|
||||
|
||||
/**
|
||||
* Stack frames have been initialised, save it to the TCB. Also set
|
||||
* the thread's real entry point and param, so the thread shell knows
|
||||
* what function to call.
|
||||
*/
|
||||
tcb_ptr->sp_save_ptr = tsk_ctx;
|
||||
tcb_ptr->entry_point = entry_point;
|
||||
tcb_ptr->entry_param = entry_param;
|
||||
}
|
||||
|
||||
63
ports/cortex-m/atomport.h
Normal file
63
ports/cortex-m/atomport.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ATOM_PORT_H
|
||||
#define __ATOM_PORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
|
||||
/* Required number of system ticks per second (normally 100 for 10ms tick) */
|
||||
#define SYSTEM_TICKS_PER_SEC 100
|
||||
|
||||
/* Size of each stack entry / stack alignment size (4 bytes on Cortex-M without FPU) */
|
||||
#define STACK_ALIGN_SIZE sizeof(uint32_t)
|
||||
|
||||
#define POINTER void *
|
||||
#define UINT32 uint32_t
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define __maybe_unused __attribute__((unused))
|
||||
|
||||
/**
|
||||
* Critical region protection: this should disable interrupts
|
||||
* to protect OS data structures during modification. It must
|
||||
* allow nested calls, which means that interrupts should only
|
||||
* be re-enabled when the outer CRITICAL_END() is reached.
|
||||
*/
|
||||
#define CRITICAL_STORE bool __irq_flags
|
||||
#define CRITICAL_START() __irq_flags = cm_mask_interrupts(true)
|
||||
#define CRITICAL_END() (void) cm_mask_interrupts(__irq_flags)
|
||||
|
||||
/* Uncomment to enable stack-checking */
|
||||
/* #define ATOM_STACK_CHECKING */
|
||||
|
||||
#endif /* __ATOM_PORT_H */
|
||||
16
ports/cortex-m/boards/ek-lm4f120xl/Makefile
Normal file
16
ports/cortex-m/boards/ek-lm4f120xl/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
TARGET := lm4f120xl
|
||||
|
||||
LIBNAME = opencm3_lm4f
|
||||
DEFS = -DLM4F
|
||||
DEFS += -DSTD_CON=UART0
|
||||
DEFS += -DMST_SIZE=0x400
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS)
|
||||
|
||||
OOCD ?= openocd
|
||||
OOCD_INTERFACE ?= ti-icdi
|
||||
OOCD_BOARD ?= ek-lm4f120xl
|
||||
|
||||
objs += board_setup.o
|
||||
objs += stubs.o lm4f_con.o
|
||||
134
ports/cortex-m/boards/ek-lm4f120xl/board_setup.c
Normal file
134
ports/cortex-m/boards/ek-lm4f120xl/board_setup.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libopencm3/lm4f/rcc.h>
|
||||
#include <libopencm3/lm4f/gpio.h>
|
||||
#include <libopencm3/lm4f/uart.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
|
||||
#include "atomport.h"
|
||||
|
||||
static void uart_setup(uint32_t baud)
|
||||
{
|
||||
periph_clock_enable(RCC_GPIOA);
|
||||
gpio_set_af(GPIOA, 1, GPIO0 | GPIO1);
|
||||
|
||||
periph_clock_enable(RCC_UART0);
|
||||
|
||||
/* We need a brief delay before we can access UART config registers */
|
||||
__asm__("nop");
|
||||
|
||||
/* Disable the UART while we mess with its setings */
|
||||
uart_disable(UART0);
|
||||
|
||||
/* Configure the UART clock source as precision internal oscillator */
|
||||
uart_clock_from_piosc(UART0);
|
||||
|
||||
/* Set communication parameters */
|
||||
uart_set_baudrate(UART0, baud);
|
||||
uart_set_databits(UART0, 8);
|
||||
uart_set_parity(UART0, UART_PARITY_NONE);
|
||||
uart_set_stopbits(UART0, 1);
|
||||
|
||||
/* Now that we're done messing with the settings, enable the UART */
|
||||
uart_enable(UART0);
|
||||
}
|
||||
|
||||
/**
|
||||
* initialise and start SysTick counter. This will trigger the
|
||||
* sys_tick_handler() periodically once interrupts have been enabled
|
||||
* by archFirstThreadRestore()
|
||||
*/
|
||||
static void systick_setup(void)
|
||||
{
|
||||
systick_set_frequency(SYSTEM_TICKS_PER_SEC, 80000000);
|
||||
|
||||
systick_interrupt_enable();
|
||||
|
||||
systick_counter_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the core clock to something other than the internal 16MHz PIOSC.
|
||||
* Make sure that you use the same clock frequency in systick_setup().
|
||||
*/
|
||||
static void clock_setup(void)
|
||||
{
|
||||
/**
|
||||
* set up 400MHz PLL from 16MHz crystal and divide by 5 to get 80MHz
|
||||
* system clock
|
||||
*/
|
||||
rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up user LED and provide function for toggling it. This is for
|
||||
* use by the test suit programs
|
||||
*/
|
||||
static void test_led_setup(void)
|
||||
{
|
||||
/* LED is connected to GPIO1 on port F */
|
||||
periph_clock_enable(RCC_GPIOF);
|
||||
gpio_mode_setup(GPIOF, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO1);
|
||||
gpio_set_output_config(GPIOF, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, GPIO1);
|
||||
|
||||
gpio_set(GPIOF, GPIO1);
|
||||
}
|
||||
|
||||
void test_led_toggle(void)
|
||||
{
|
||||
gpio_toggle(GPIOF, GPIO1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from your main program to set up the board's hardware before
|
||||
* the kernel is started.
|
||||
*/
|
||||
int board_setup(void)
|
||||
{
|
||||
/* Disable interrupts. This makes sure that the sys_tick_handler will
|
||||
* not be called before the first thread has been started.
|
||||
* Interrupts will be enabled by archFirstThreadRestore().
|
||||
*/
|
||||
cm_mask_interrupts(true);
|
||||
|
||||
/* configure system clock, user LED and UART */
|
||||
gpio_enable_ahb_aperture();
|
||||
clock_setup();
|
||||
test_led_setup();
|
||||
uart_setup(115200);
|
||||
|
||||
/* initialise SysTick counter */
|
||||
systick_setup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
15
ports/cortex-m/boards/nucleo-f103rb/Makefile
Normal file
15
ports/cortex-m/boards/nucleo-f103rb/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
TARGET := stm32f103rb
|
||||
LIBNAME = opencm3_stm32f1
|
||||
DEFS = -DSTM32F1
|
||||
DEFS += -DSTD_CON=USART2
|
||||
DEFS += -DMST_SIZE=0x400
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
|
||||
|
||||
OOCD ?= openocd
|
||||
OOCD_INTERFACE ?= stlink-v2-1
|
||||
OOCD_BOARD ?= st_nucleo_f103rb
|
||||
|
||||
objs += board_setup.o
|
||||
objs += stubs.o stm32_con.o
|
||||
131
ports/cortex-m/boards/nucleo-f103rb/board_setup.c
Normal file
131
ports/cortex-m/boards/nucleo-f103rb/board_setup.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
|
||||
#include "atomport.h"
|
||||
|
||||
/**
|
||||
* Set up USART2.
|
||||
* This one is connected via the virtual serial port on the Nucleo Board
|
||||
*/
|
||||
static void usart_setup(uint32_t baud)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_AFIO);
|
||||
rcc_periph_clock_enable(RCC_USART2);
|
||||
|
||||
usart_disable(USART2);
|
||||
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
|
||||
GPIO_USART2_TX | GPIO_USART2_RX);
|
||||
|
||||
usart_set_baudrate(USART2, baud);
|
||||
usart_set_databits(USART2, 8);
|
||||
usart_set_stopbits(USART2, USART_STOPBITS_1);
|
||||
usart_set_parity(USART2, USART_PARITY_NONE);
|
||||
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
|
||||
usart_set_mode(USART2, USART_MODE_TX_RX);
|
||||
|
||||
usart_enable(USART2);
|
||||
}
|
||||
|
||||
/**
|
||||
* initialise and start SysTick counter. This will trigger the
|
||||
* sys_tick_handler() periodically once interrupts have been enabled
|
||||
* by archFirstThreadRestore()
|
||||
*/
|
||||
static void systick_setup(void)
|
||||
{
|
||||
systick_set_frequency(SYSTEM_TICKS_PER_SEC, 72000000);
|
||||
|
||||
systick_interrupt_enable();
|
||||
|
||||
systick_counter_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the core clock to something other than the internal 16MHz PIOSC.
|
||||
* Make sure that you use the same clock frequency in systick_setup().
|
||||
*/
|
||||
static void clock_setup(void)
|
||||
{
|
||||
/* set core clock to 72MHz, generated from external 8MHz crystal */
|
||||
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up user LED and provide function for toggling it. This is for
|
||||
* use by the test suit programs
|
||||
*/
|
||||
static void test_led_setup(void)
|
||||
{
|
||||
/* LED is connected to GPIO5 on port A */
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
|
||||
|
||||
gpio_set(GPIOA, GPIO5);
|
||||
}
|
||||
|
||||
void test_led_toggle(void)
|
||||
{
|
||||
gpio_toggle(GPIOA, GPIO5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from your main program to set up the board's hardware before
|
||||
* the kernel is started.
|
||||
*/
|
||||
int board_setup(void)
|
||||
{
|
||||
/* Disable interrupts. This makes sure that the sys_tick_handler will
|
||||
* not be called before the first thread has been started.
|
||||
* Interrupts will be enabled by archFirstThreadRestore().
|
||||
*/
|
||||
cm_mask_interrupts(true);
|
||||
|
||||
/* configure system clock, user LED and UART */
|
||||
clock_setup();
|
||||
test_led_setup();
|
||||
usart_setup(115200);
|
||||
|
||||
/* initialise SysTick counter */
|
||||
systick_setup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
15
ports/cortex-m/boards/nucleo-f411re/Makefile
Normal file
15
ports/cortex-m/boards/nucleo-f411re/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
TARGET := stm32f411re
|
||||
LIBNAME = opencm3_stm32f4
|
||||
DEFS = -DSTM32F4
|
||||
DEFS += -DSTD_CON=USART2
|
||||
DEFS += -DMST_SIZE=0x400
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS)
|
||||
|
||||
OOCD ?= openocd
|
||||
OOCD_INTERFACE ?= stlink-v2-1
|
||||
OOCD_BOARD ?= st_nucleo_f4
|
||||
|
||||
objs += board_setup.o
|
||||
objs += stubs.o stm32_con.o
|
||||
129
ports/cortex-m/boards/nucleo-f411re/board_setup.c
Normal file
129
ports/cortex-m/boards/nucleo-f411re/board_setup.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
|
||||
#include "atomport.h"
|
||||
|
||||
/**
|
||||
* Set up USART2.
|
||||
* This one is connected via the virtual serial port on the Nucleo Board
|
||||
*/
|
||||
static void usart_setup(uint32_t baud)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_USART2);
|
||||
|
||||
usart_disable(USART2);
|
||||
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3);
|
||||
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
|
||||
|
||||
usart_set_baudrate(USART2, baud);
|
||||
usart_set_databits(USART2, 8);
|
||||
usart_set_stopbits(USART2, USART_STOPBITS_1);
|
||||
usart_set_parity(USART2, USART_PARITY_NONE);
|
||||
usart_set_mode(USART2, USART_MODE_TX_RX);
|
||||
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
|
||||
|
||||
usart_enable(USART2);
|
||||
}
|
||||
|
||||
/**
|
||||
* initialise and start SysTick counter. This will trigger the
|
||||
* sys_tick_handler() periodically once interrupts have been enabled
|
||||
* by archFirstThreadRestore()
|
||||
*/
|
||||
static void systick_setup(void)
|
||||
{
|
||||
systick_set_frequency(SYSTEM_TICKS_PER_SEC, 16000000);
|
||||
|
||||
systick_interrupt_enable();
|
||||
|
||||
systick_counter_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the core clock to something other than the internal 16MHz PIOSC.
|
||||
* Make sure that you use the same clock frequency in systick_setup().
|
||||
*/
|
||||
static void clock_setup(void)
|
||||
{
|
||||
/**
|
||||
* Clock setting for stm32f4 is currently broken in libopencm3.
|
||||
* Leave at internal 16MHz
|
||||
*/
|
||||
// rcc_clock_setup_hse_3v3(CLOCK_3V3_48MHZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up user LED and provide function for toggling it. This is for
|
||||
* use by the test suit programs
|
||||
*/
|
||||
static void test_led_setup(void)
|
||||
{
|
||||
/* LED is connected to GPIO5 on port A */
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO5);
|
||||
gpio_set(GPIOA, GPIO5);
|
||||
}
|
||||
|
||||
void test_led_toggle(void)
|
||||
{
|
||||
gpio_toggle(GPIOA, GPIO5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from your main program to set up the board's hardware before
|
||||
* the kernel is started.
|
||||
*/
|
||||
int board_setup(void)
|
||||
{
|
||||
/* Disable interrupts. This makes sure that the sys_tick_handler will
|
||||
* not be called before the first thread has been started.
|
||||
* Interrupts will be enabled by archFirstThreadRestore().
|
||||
*/
|
||||
cm_mask_interrupts(true);
|
||||
|
||||
/* configure system clock, user LED and UART */
|
||||
clock_setup();
|
||||
test_led_setup();
|
||||
usart_setup(115200);
|
||||
|
||||
/* initialise SysTick counter */
|
||||
systick_setup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
93
ports/cortex-m/common/lm4f_con.c
Normal file
93
ports/cortex-m/common/lm4f_con.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
#include <libopencm3/lm4f/uart.h>
|
||||
|
||||
/**
|
||||
* _read and _write for LM4F
|
||||
*
|
||||
* _read and _write are used by newlib's I/O routines (think printf, etc.)
|
||||
* If you want to use this code in your binary, you will have to initialise
|
||||
* the UART in your board's setup code and define STD_CON to your UART's
|
||||
* name in your board's Makefile
|
||||
*/
|
||||
int _read(int fd, void *buf, size_t count)
|
||||
{
|
||||
int rcvd;
|
||||
char *ptr;
|
||||
|
||||
if(fd <= 2){
|
||||
ptr = (char *) buf;
|
||||
rcvd = 0;
|
||||
|
||||
while(count > 0){
|
||||
*ptr = uart_recv_blocking(STD_CON);
|
||||
if(*ptr == '\r'){
|
||||
*ptr = '\n';
|
||||
}
|
||||
|
||||
++rcvd;
|
||||
--count;
|
||||
}
|
||||
}else{
|
||||
rcvd = -1;
|
||||
errno = EIO;
|
||||
}
|
||||
|
||||
return rcvd;
|
||||
}
|
||||
|
||||
int _write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
int sent;
|
||||
char *ptr;
|
||||
|
||||
if(fd <= 2){
|
||||
sent = count;
|
||||
ptr = (char *) buf;
|
||||
|
||||
while(count > 0){
|
||||
if(*ptr == '\n'){
|
||||
uart_send_blocking(STD_CON, '\r');
|
||||
}
|
||||
uart_send_blocking(STD_CON, *ptr++);
|
||||
|
||||
++sent;
|
||||
--count;
|
||||
}
|
||||
}else{
|
||||
errno = EIO;
|
||||
sent = -1;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
92
ports/cortex-m/common/stm32_con.c
Normal file
92
ports/cortex-m/common/stm32_con.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
|
||||
/**
|
||||
* _read and _write for STM32
|
||||
*
|
||||
* _read and _write are used by newlib's I/O routines (think printf, etc.)
|
||||
* If you want to use this code in your binary, you will have to initialise
|
||||
* the UART in your board's setup code and define STD_CON to your UART's
|
||||
* name in your board's Makefile
|
||||
*/
|
||||
int _read(int fd, void *buf, size_t count)
|
||||
{
|
||||
int rcvd;
|
||||
char *ptr;
|
||||
|
||||
if(fd <= 2){
|
||||
ptr = (char *) buf;
|
||||
rcvd = 0;
|
||||
while(count > 0){
|
||||
*ptr = usart_recv_blocking(STD_CON);
|
||||
if(*ptr == '\r'){
|
||||
*ptr = '\n';
|
||||
}
|
||||
++rcvd;
|
||||
--count;
|
||||
}
|
||||
}else{
|
||||
rcvd = -1;
|
||||
errno = EIO;
|
||||
}
|
||||
|
||||
return rcvd;
|
||||
}
|
||||
|
||||
int _write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
int sent;
|
||||
char *ptr;
|
||||
|
||||
if(fd <= 2){
|
||||
sent = count;
|
||||
ptr = (char *) buf;
|
||||
|
||||
while(count > 0){
|
||||
if(*ptr == '\n'){
|
||||
usart_send_blocking(STD_CON, '\r');
|
||||
}
|
||||
usart_send_blocking(STD_CON, *ptr++);
|
||||
++sent;
|
||||
--count;
|
||||
}
|
||||
|
||||
}else{
|
||||
errno = EIO;
|
||||
sent = -1;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
110
ports/cortex-m/common/stubs.c
Normal file
110
ports/cortex-m/common/stubs.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <libopencm3/cm3/vector.h>
|
||||
|
||||
/**
|
||||
* _sbrk is needed by newlib for heap management.
|
||||
* The main stack usually starts at the top of RAM and grows downwards,
|
||||
* while the heap starts at the bottom and grows upwards. To prevent
|
||||
* the heap from colliding with the main stack, we reserve a certain amount
|
||||
* of memory and check that growing the heap won't touch that region.
|
||||
* The size of the protected area is set via the define MST_SIZE in the
|
||||
* board Makefile
|
||||
*/
|
||||
|
||||
#ifndef MST_SIZE
|
||||
#error Main stack size not defined. Please define MST_SIZE in board Makefile
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The vector table is provided by libopencm3/cm3/vector.h and contains
|
||||
* the initial main stack pointer value
|
||||
*/
|
||||
extern vector_table_t vector_table;
|
||||
|
||||
/**
|
||||
* The linker provides the start address of the unused system memory.
|
||||
* It is exported via the symbol 'end' and will be used as the bottom
|
||||
* of the heap
|
||||
*/
|
||||
extern char end;
|
||||
|
||||
static char *heap_end = 0;
|
||||
caddr_t _sbrk(int incr)
|
||||
{
|
||||
char *prev_end;
|
||||
|
||||
if(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;
|
||||
}
|
||||
|
||||
heap_end += incr;
|
||||
|
||||
return (caddr_t) prev_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* dummy stubs needed by newlib when not linked with libnosys
|
||||
*/
|
||||
int _close(int file)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fstat(int file, struct stat *st)
|
||||
{
|
||||
st->st_mode = S_IFCHR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty(int file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _open(const char *name, int flags, int mode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
10
ports/cortex-m/linker/lm4f120xl.ld
Normal file
10
ports/cortex-m/linker/lm4f120xl.ld
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Memory regions for TI Stellaris EX-LM4F120XL evaluation board. */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x00000000, LENGTH = 256K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
|
||||
}
|
||||
|
||||
/* Include main opencm3 linker script */
|
||||
INCLUDE libopencm3_lm4f.ld
|
||||
10
ports/cortex-m/linker/stm32f103rb.ld
Normal file
10
ports/cortex-m/linker/stm32f103rb.ld
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Memory regions for STM32F103RB, 128K flash, 20K RAM. */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
|
||||
/* Include main opencm3 linker script */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
10
ports/cortex-m/linker/stm32f411re.ld
Normal file
10
ports/cortex-m/linker/stm32f411re.ld
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Memory regions for STM32F411RE, 512K flash, 128K RAM. */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
/* Include main opencm3 linker script */
|
||||
INCLUDE libopencm3_stm32f4.ld
|
||||
274
ports/cortex-m/tests-main.c
Normal file
274
ports/cortex-m/tests-main.c
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Kelvin Lawson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "atom.h"
|
||||
#include "atomport-private.h"
|
||||
#include "atomtests.h"
|
||||
#include "atomtimer.h"
|
||||
|
||||
|
||||
/* Constants */
|
||||
|
||||
/*
|
||||
* Idle thread stack size
|
||||
*
|
||||
* This needs to be large enough to handle any interrupt handlers
|
||||
* and callbacks called by interrupt handlers (e.g. user-created
|
||||
* timer callbacks) as well as the saving of all context when
|
||||
* switching away from this thread.
|
||||
*
|
||||
* In this case, the idle stack is allocated on the BSS via the
|
||||
* idle_thread_stack[] byte array.
|
||||
*/
|
||||
#define IDLE_STACK_SIZE_BYTES 512
|
||||
|
||||
|
||||
/*
|
||||
* Main thread stack size
|
||||
*
|
||||
* Note that this is not a required OS kernel thread - you will replace
|
||||
* this with your own application thread.
|
||||
*
|
||||
* In this case the Main thread is responsible for calling out to the
|
||||
* test routines. Once a test routine has finished, the test status is
|
||||
* printed out on the UART and the thread remains running in a loop
|
||||
* flashing a LED.
|
||||
*
|
||||
* The Main thread stack generally needs to be larger than the idle
|
||||
* thread stack, as not only does it need to store interrupt handler
|
||||
* stack saves and context switch saves, but the application main thread
|
||||
* will generally be carrying out more nested function calls and require
|
||||
* stack for application code local variables etc.
|
||||
*
|
||||
* With all OS tests implemented to date on the AVR, the Main thread
|
||||
* stack has not exceeded 201 bytes. To allow all tests to run we set
|
||||
* a minimum main thread stack size of 204 bytes. This may increase in
|
||||
* future as the codebase changes but for the time being is enough to
|
||||
* cope with all of the automated tests.
|
||||
*/
|
||||
#define MAIN_STACK_SIZE_BYTES 1024
|
||||
|
||||
|
||||
/*
|
||||
* Startup code stack
|
||||
*
|
||||
* Some stack space is required at initial startup for running the main()
|
||||
* routine. This stack space is only temporarily required at first bootup
|
||||
* and is no longer required as soon as the OS is started. By default
|
||||
* GCC sets this to the top of RAM (RAMEND) and it grows down from there.
|
||||
* Because we only need this temporarily, though, it would be wasteful to
|
||||
* set aside a region at the top of RAM which is not used during runtime.
|
||||
*
|
||||
* What we do here is to reuse part of the idle thread's stack during
|
||||
* initial startup. As soon as we enter the main() routine we move the
|
||||
* stack pointer to half-way down the idle thread's stack. This is used
|
||||
* temporarily while calls are made to atomOSInit(), atomThreadCreate()
|
||||
* and atomOSStart(). Once the OS is started this stack area is no
|
||||
* longer required, and can be used for its original purpose (for the
|
||||
* idle thread's stack).
|
||||
*
|
||||
* This does mean, however, that we cannot monitor the stack usage of the
|
||||
* idle thread. Stack usage is monitored by prefilling the stack with a
|
||||
* known value, and we are obliterating some of that prefilled area by
|
||||
* using it as our startup stack, so we cannot use the stack-checking API
|
||||
* to get a true picture of idle thread stack usage. If you wish to
|
||||
* monitor idle thread stack usage for your applications then you are
|
||||
* free to use a different region for the startup stack (e.g. set aside
|
||||
* an area permanently, or place it somewhere you know you can reuse
|
||||
* later in the application). For the time being, this method gives us a
|
||||
* simple way of reducing the memory consumption without having to add
|
||||
* any special AVR-specific considerations to the automated test
|
||||
* applications.
|
||||
*
|
||||
* This optimisation was required to allow some of the larger automated
|
||||
* test modules to run on devices with 1KB of RAM. You should avoid doing
|
||||
* this if you can afford to set aside 64 bytes or so, or if you are
|
||||
* writing your own applications in which you have further control over
|
||||
* where data is located.
|
||||
*/
|
||||
|
||||
|
||||
/* Local data */
|
||||
|
||||
/* Application threads' TCBs */
|
||||
static ATOM_TCB main_tcb;
|
||||
|
||||
/* Main thread's stack area */
|
||||
static uint8_t main_thread_stack[MAIN_STACK_SIZE_BYTES];
|
||||
|
||||
/* Idle thread's stack area */
|
||||
static uint8_t idle_thread_stack[IDLE_STACK_SIZE_BYTES];
|
||||
|
||||
/* Forward declarations */
|
||||
static void main_thread_func (uint32_t data);
|
||||
|
||||
|
||||
/**
|
||||
* \b main
|
||||
*
|
||||
* Program entry point.
|
||||
*
|
||||
* Sets up the AVR hardware resources (system tick timer interrupt) necessary
|
||||
* for the OS to be started. Creates an application thread and starts the OS.
|
||||
*/
|
||||
extern int board_setup(void);
|
||||
int main ( void )
|
||||
{
|
||||
int8_t status;
|
||||
|
||||
|
||||
/**
|
||||
* Note: to protect OS structures and data during initialisation,
|
||||
* interrupts must remain disabled until the first thread
|
||||
* has been restored. They are reenabled at the very end of
|
||||
* the first thread restore, at which point it is safe for a
|
||||
* reschedule to take place.
|
||||
*/
|
||||
board_setup();
|
||||
|
||||
/**
|
||||
* Initialise the OS before creating our threads.
|
||||
*
|
||||
* Note that we cannot enable stack-checking on the idle thread on
|
||||
* this platform because we are already using part of the idle
|
||||
* thread's stack now as our startup stack. Prefilling for stack
|
||||
* checking would overwrite our current stack.
|
||||
*
|
||||
* If you are not reusing the idle thread's stack during startup then
|
||||
* you are free to enable stack-checking here.
|
||||
*/
|
||||
status = atomOSInit(&idle_thread_stack[0], IDLE_STACK_SIZE_BYTES, FALSE);
|
||||
if (status == ATOM_OK)
|
||||
{
|
||||
|
||||
/* Create an application thread */
|
||||
status = atomThreadCreate(&main_tcb,
|
||||
TEST_THREAD_PRIO, main_thread_func, 0,
|
||||
&main_thread_stack[0],
|
||||
MAIN_STACK_SIZE_BYTES,
|
||||
TRUE);
|
||||
if (status == ATOM_OK)
|
||||
{
|
||||
/**
|
||||
* First application thread successfully created. It is
|
||||
* now possible to start the OS. Execution will not return
|
||||
* from atomOSStart(), which will restore the context of
|
||||
* our application thread and start executing it.
|
||||
*
|
||||
* Note that interrupts are still disabled at this point.
|
||||
* They will be enabled as we restore and execute our first
|
||||
* thread in archFirstThreadRestore().
|
||||
*/
|
||||
atomOSStart();
|
||||
}
|
||||
}
|
||||
|
||||
while (1)
|
||||
;
|
||||
|
||||
/* There was an error starting the OS if we reach here */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \b main_thread_func
|
||||
*
|
||||
* Entry point for main application thread.
|
||||
*
|
||||
* This is the first thread that will be executed when the OS is started.
|
||||
*
|
||||
* @param[in] data Unused (optional thread entry parameter)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
extern void test_led_toggle(void);
|
||||
static void main_thread_func (uint32_t data)
|
||||
{
|
||||
uint32_t test_status;
|
||||
int sleep_ticks;
|
||||
|
||||
|
||||
/* Put a message out on the UART */
|
||||
printf("Go\n");
|
||||
|
||||
/* Start test. All tests use the same start API. */
|
||||
test_status = test_start();
|
||||
|
||||
/* Check main thread stack usage (if enabled) */
|
||||
#ifdef ATOM_STACK_CHECKING
|
||||
if (test_status == 0)
|
||||
{
|
||||
uint32_t used_bytes, free_bytes;
|
||||
|
||||
/* Check idle thread stack usage */
|
||||
if (atomThreadStackCheck (&main_tcb, &used_bytes, &free_bytes) == ATOM_OK)
|
||||
{
|
||||
/* Check the thread did not use up to the end of stack */
|
||||
if (free_bytes == 0)
|
||||
{
|
||||
printf("Main stack overflow\n");
|
||||
test_status++;
|
||||
}
|
||||
|
||||
/* Log the stack usage */
|
||||
#ifdef TESTS_LOG_STACK_USAGE
|
||||
printf("MainUse: %lu\n", used_bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Log final status */
|
||||
if (test_status == 0)
|
||||
{
|
||||
printf("Pass\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Fail(%lu)\n", test_status);
|
||||
}
|
||||
|
||||
/* Flash LED once per second if passed, very quickly if failed */
|
||||
sleep_ticks = (test_status == 0) ? SYSTEM_TICKS_PER_SEC : (SYSTEM_TICKS_PER_SEC/8);
|
||||
|
||||
/* Test finished, flash slowly for pass, fast for fail */
|
||||
while (1)
|
||||
{
|
||||
/* Toggle a LED (STK500-specific) */
|
||||
test_led_toggle();
|
||||
|
||||
/* Sleep then toggle LED again */
|
||||
atomTimerDelay (sleep_ticks);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user